22 Replies Latest reply on Jan 23, 2010 2:55 PM by Harbs.

    .ItemByID() how to obtain ID

    Econometric Level 1

      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

        • 1. Re: .ItemByID() how to obtain ID
          Harbs. Level 6

          Table.id

           

          Harbs

          • 2. Re: .ItemByID() how to obtain ID
            Econometric Level 1

            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

            • 3. Re: .ItemByID() how to obtain ID
              Harbs. Level 6

              Select the text containing the table and run this:

               

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

               

              Harbs

              • 4. Re: .ItemByID() how to obtain ID
                [Jongware] Most Valuable Participant

                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);
                 
                

                1 person found this helpful
                • 5. Re: .ItemByID() how to obtain ID
                  Econometric Level 1

                  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

                  • 6. Re: .ItemByID() how to obtain ID
                    [Jongware] Most Valuable Participant

                    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[a].label == labelname)

                          return myDocument.textFrames[a];

                      }

                      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.

                    • 7. Re: .ItemByID() how to obtain ID
                      Harbs. Level 6

                      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

                      • 8. Re: .ItemByID() how to obtain ID
                        Roy McCoy Level 1

                        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

                        • 9. Re: .ItemByID() how to obtain ID
                          Harbs. Level 6

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

                          arbitrarily, things can go haywire very easily...

                           

                          Harbs

                          • 11. Re: .ItemByID() how to obtain ID
                            Kasyan Servetsky Level 5
                            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

                            • 12. Re: .ItemByID() how to obtain ID
                              [Jongware] Most Valuable Participant

                              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".

                              • 13. Re: .ItemByID() how to obtain ID
                                Harbs. Level 6

                                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

                                • 14. Re: .ItemByID() how to obtain ID
                                  Kasyan Servetsky Level 5

                                  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

                                  • 15. Re: .ItemByID() how to obtain ID
                                    [Jongware] Most Valuable Participant

                                    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.

                                    • 16. Re: .ItemByID() how to obtain ID
                                      Harbs. Level 6

                                      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

                                      • 17. Re: .ItemByID() how to obtain ID
                                        Kasyan Servetsky Level 5

                                        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

                                        • 18. Re: .ItemByID() how to obtain ID
                                          AdobeScripts Level 3

                                          [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[a].label == labelname)

                                                return myDocument.textFrames[a];

                                            }

                                            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

                                          • 19. Re: .ItemByID() how to obtain ID
                                            AdobeScripts Level 3

                                            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

                                            • 20. Re: .ItemByID() how to obtain ID
                                              Harbs. Level 6

                                              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

                                              • 21. Re: .ItemByID() how to obtain ID
                                                AdobeScripts Level 3

                                                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

                                                • 22. Re: .ItemByID() how to obtain ID
                                                  Harbs. Level 6

                                                  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