• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

.ItemByID() how to obtain ID

New Here ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Hello,

I have an Indesign document with several text tables.  What I would like to do is have a VBA script enter text into these tables.  I am using the .ItemByID() method.  However, I do not know how to obtain the table ID "x" so that the script knows which table to reference.  When I create the table in Indesign, is there a way to obtain the tables unique ID?

idDoc.TextFrames.ItemByID(x)

Thank you for your help,

Mike

TOPICS
Scripting

Views

4.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Table.id

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Thank you Harbs for helping me out with this, but I'm still not getting it.  If I create a table in my Indesign document, do you mean go to the table menu drop down to get the ID?  I don't see anything there that gives me the ID.  Hate to ask you to elaborate on such a simple task but I'm having trouble with this one.


Thanks again,
Mike

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Select the text containing the table and run this:

alert(app.selection[0].tables[0].id)

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

The ID is an internal unique identifier for the table (the ESTK Help describes it as "The unique ID of the Table." -- kind of summarizes it). It's guaranteed to be unique for all tables throughout your entire document -- InDesign needs it to be for every single object to be able to put your file together from its bits.

I can sort of imagine how it works: what if you rename a paragraph style? If the styles were applied "by name", ID would have to scan the entire document for that name and change it. What if you move a paragraph style around in its palette? If the styles were applied by using their index number (the index being their position in the palette), ID again would need to re-scan the document. Instead, all styles are applied by UniqueID. All InDesign has to do now is making sure it does not re-use an ID when you create a new style. The Unique ID will stay the same, whatever you do with the style. And if there is no style with some ID in the paragraph style list, it does not exist. Period.

.. Totally made this up, of course, but it does sound good doesn't it!?

The ID is "hidden" -- not available in the User Interface, and read-only for scripting purposes. If I would be prone to guessing, I'd say it's even read-only in plugins, except (maybe) at the very deepest core.

This is a Javascript that shows the ID for the table your cursor is in. However, interesting as that may sound, logically, you might not need it. If you can read the ID of a table, you already have to have a valid handle on it. And if you do, you don't have to use ItemById ...

I think it could be useful to store the table IDs somewhere, do something else, then do something with the stored IDs. But you can always store direct pointers to the tables themselves ... (And -- again, guessing -- perhaps the scripting interface store these internally by referring to their ID.)

Perhaps you could better use the zero-based index (or, in the case of VBS, 1-based) of the tables in your story. The first index always will point to the first table, and so on all the way to the end of the story.

if (app.selection.length != 1)

{

     alert ("Please select more or less than this. Preferably a TABLE!");

     exit(0);

}

table = app.selection[0];

if (table.hasOwnProperty("baseline"))

     table = table.parent;

if (table.constructor.name == "Cell")

     table = table.parent;

if (table.constructor.name == "Row")

     table = table.parent;

if (table.constructor.name != "Table")

{

     alert ("Ah. Not in a table, are we?");

     exit(0);

}

alert ("Table Index: "+table.index+"\nTable Unique ID: "+table.id);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Jongware,

Thanks for this reply.  Let me show you my code here so you can see what I want to do.  I am using VBA.  I would like my script to take text out of an Excel file and update a template that I have created in Indesign.  There must be some way to get the table ID I have put below in blue.  The "40830".  Why would there be an ItemByID() method if it was so difficult to get the item ID??

Sub UpdateER()
  Set indd = CreateObject("indesign.application")
  Set idDoc = indd.ActiveDocument
  Dim strname As String, wsOut As Worksheet
  strname = Mid(idDoc.Name, 1, Len(idDoc.Name) - 4) & "xls"
  Set wbOutput = Workbooks(strname)
  fol = wbOutput.Path & "\graphs\"
  'get period, store as array with period(0) being current year and period(1) being prior period 1, etc
  With wbOutput.Sheets("info")
   If .Range("b15").Value = "Period Type Cal_Period" Then 'i.e. calendar period
    Let period = Array(CStr(.Range("d10").Value), CStr(.Range("d11").Value), CStr(.Range("d12").Value))
   Else 'it's rolling or anniversary, both of which are labeled the same
    Let period = Array(CStr(.Range("e10").Value), CStr(.Range("e11").Value), CStr(.Range("e12").Value))
   End If
  End With

  Call xlER
  Call InDesignCode.idER
  'ER
  Set wsOut = wbOutput.Sheets("ER")
  With idDoc.TextFrames.ItemByID(40830)
   .Paragraphs(1).Words(27).Contents = wbOutput.Sheets("info").Range("c3").Value & "'s"
  End With
  With idDoc.TextFrames.ItemByID(40853)
   .Paragraphs(1).Contents = wsOut.Range("b24").Value & vbCr
   .Paragraphs(2).Contents = wsOut.Range("b25").Value & vbCr
   .Paragraphs(3).Contents = wsOut.Range("b26").Value & vbCr
  End With
 
  Set wsOut = Nothing
  Set wbOutput = Nothing
  Set indd = Nothing
  Set idDoc = Nothing
  Let strname = Empty
End Sub

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

A-ha. You are trusting on InDesign to keep the assigned Unique ID the same, for some unspecified amount of time. Well ... it's not meant for that. I think. Remember, the ID is an internal value for InDesign. It may change this for your text frames at any time.

(You can actually confirm this quite easy. Export your document to INX or IDML, then open it again. The IDs will most likely not be the same.)

A much safer way to "store" and "retrieve" pointers to objects is to assign them a label. That can be done in the User Interface quite easy (it's what the Scripts Label panel is for), and your script can find the object or objects with that same label.

Assign a unique label to the frame you need to work on, such as "data_here", using the Script Label panel. Then, again in Javascript (sorry -- can't test in VB, but it ought to be quite similar), use something like this to find the actual frame:

app.select (findFrameLabeled (app.activeDocument, "data_here"));


function findFrameLabeled (myDocument, labelname)

{

  for (a=0; a<myDocument.textFrames.length; a++)

  {

    if (myDocument.textFrames.label == labelname)

      return myDocument.textFrames;

  }

  return null;

}

(This sample will select the frame you labeled.)

You only have to use this function once per frame in your code, preferably somewhere near the start.

The label you insert in the document is guaranteed to stay attached to that particular frame, no matter what happens with the document.

And be sure to use two different labels for your two frames.

There is another way to attach arbitrary custom information such as a name to each frame -- insertLabel and extractLabel -- but the plain label can be added, edited, and removed in the User Interface, which is a big plus.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Jong,

The ids do not change. They correspond to the UIDs on the C++ level

which is how InDesign keeps track of objects...

It's possible that the IDs are not the same because the original

objects were copied which would cause them to have different IDs than

the original objects.

There is another way to attach arbitrary custom information such as

a name to each frame -- insertLabel and extractLabel -- but the

plain label can be added, edited, and removed in the User Interface,

which is a big plus.

Or a HUGE minus if you use APID...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Harbs wrote, quoting Jong:

>> There is another way to attach arbitrary custom information such as

>> a name to each frame -- insertLabel and extractLabel -- but the

>> plain label can be added, edited, and removed in the User Interface,

>> which is a big plus.

>

Or a HUGE minus if you use APID...

Why is that?

Thanks,

Roy McCoy

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Because APID tracks objects by their label. If you change the label

arbitrarily, things can go haywire very easily...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 19, 2010 Jan 19, 2010

Copy link to clipboard

Copied

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 22, 2010 Jan 22, 2010

Copy link to clipboard

Copied

Harbs. wrote:

Because APID tracks objects by their label. If you change the label 

arbitrarily, things can go haywire very easily...

Harbs

Then why you don't use .InsertLabel and .ExtractLabel to hide labels from user?

robin

www.adobescripts.com

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 23, 2010 Jan 23, 2010

Copy link to clipboard

Copied

Then why you don't use .InsertLabel and .ExtractLabel to

hide labels from user?

No, you did not understand me. APID uses the label property to define

which page items trigger which events. If you assign a subject of

"thingamagig", you assign a label of "thingamagig" to a page item, and

your script will respond to changes of that object. If someone

overwrites that label, the object will no longer be watched by APID.

When using APID, you need to use insertLabel and extractLabel (or

APID's own dataStores) for storing your own data...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 23, 2010 Jan 23, 2010

Copy link to clipboard

Copied

Harbs. wrote:

Then why you don't use .InsertLabel and .ExtractLabel to 

hide labels from user?

No, you did not understand me. APID uses the label property to define 

which page items trigger which events. If you assign a subject of 

"thingamagig", you assign a label of "thingamagig" to a page item, and 

your script will respond to changes of that object. If someone 

overwrites that label, the object will no longer be watched by APID.

I know how yours APID works

My idea is to use .InsertLabel and .ExtractLabel inside your APID to copy .Label to hidden one. And when user want to "unlink" object - he need to use some special label-command.

robin

www.adobescripts.com

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 23, 2010 Jan 23, 2010

Copy link to clipboard

Copied

LATEST

Yeah.

Except APID is not mine...

I agree with you, that it might be a nice idea for APID use something

other than label, but since that's how APID currently works, my advice

to not arbitrarily change object labels when using APID, stands...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 22, 2010 Jan 22, 2010

Copy link to clipboard

Copied

[Jongware] wrote:

Assign a unique label to the frame you need to work on, such as "data_here", using the Script Label panel. Then, again in Javascript (sorry -- can't test in VB, but it ought to be quite similar), use something like this to find the actual frame:

app.select (findFrameLabeled (app.activeDocument, "data_here"));


function findFrameLabeled (myDocument, labelname)

{

  for (a=0; a<myDocument.textFrames.length; a++)

  {

    if (myDocument.textFrames.label == labelname)

      return myDocument.textFrames;

  }

  return null;

}

If you use .Label property - you don't need to iterate through all objects - you can just do this:

Set myTextFrame = myDoc.TextFrames.Item(myLabel)

Only if you use .InsertLabel - you need to iterate all objects and use .ExtractLabel.

robin

www.adobescripts.co.uk

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

exit(0);

Jongware,

I wonder what zero means in exit(0)? (I noticed that you always use this parameter in your scripts) And what is exit()? Is this a JS function? If it is a part of JS, then why it doesn’t work for example with photoshop scripts? I’m sorry for putting these silly questions – must be missing something obvious, but I just can find it documented nowhere.

Kasyan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

Now that you mention it -- can't really recall where & when I saw it first. It's just a regular exit (terminate, quit, abort, stop, halt, end, break, return, RTS, PostQuitMessage, signal(P_TERM), alt+F4, ctrl+C, cmd+Period) command that immediately stops execution of the script, but no -- it doesn't seem to be documented in the ESTK.

The (0) parameter originally served some kind of purpose of "exit status", in case the script is called from a command line. In, ah, "normal" programs, you can report a single value back to the calling program (usually a command shell), so you can act upon successfull or erronous execution. I remember always having to supply any argument in old CS, but for CS4 at least, a plain "exit()" also works. The '0' stuck though, as in the other programming languages I use, that argument is required for "exit".

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

I first saw exit() used by either Dave or Ole.

Dave used it in a lot of his scripts.

FWIW, I stay pretty far away from exit(). It exits the entire

scripting engine -- not just the current script, so if you have a

script nested inside another one (which is possible when you have

event driven scripts), exit() will stop the outer script as well.

I always construct my scripts that it's possible to exit by using

"return false" when necessary.

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

Thank you both -- Harbs and Jongware --  for the explanation. Once  a friend of mine -- a programmer -- told me that using exit() was a bad practice in programming. Now I see why.

Kasyan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

Heh heh. Bad programming? If a script can't continue, because -- for example -- the user didn't select the appropriate object to run on, exit. No point in continuing, is it?

But I'm more a lots-of-small-scripts guy -- I can imagine (just) a large script where you wouldn't want an inner function to halt all.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 20, 2010 Jan 20, 2010

Copy link to clipboard

Copied

Jong,

It's not just about inner (or outer) functions. If you have a script which triggers another script which responds to a specific event, exit() can inadvertently exit a script which your script does not even know about!

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guru ,
Jan 21, 2010 Jan 21, 2010

Copy link to clipboard

Copied

Your tip is very important to me since I have a few event driven scripts running on my computer and want to avoid any troubles.

Thanks.

Kasyan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines