Skip to main content
Fightergator
Inspiring
July 11, 2025
Answered

Extract Figure & Table Names From Document

  • July 11, 2025
  • 3 replies
  • 559 views

Last April I asked for help counting figures in our documents.  The code you helped me with has been a real help.  In addition to getting a figure count, I also get a table count.  The customer uses these to help determine the level of effort for editing various documents.  

Recently, I was asked if it's possible to extract the Title associated with each figure and table.  I tried boring down in the data browser, but can't find where that information stored.  I'm currently using the following code to get the counts:

function countFigures() {

    figureCtr = 0;
    var figure = doc.FirstGraphicInDoc;
        while (figure.ObjectValid()) {
 Alert ('Stop script and check for figure name.');           
            if (figure.constructor.name === "AFrame") { 
                 figureCtr++;
                }    
            figure = figure.NextGraphicInDoc;
        }
    return figureCtr;
    }
function countTbls() {

    tableCtr = 0;
    textList = doc.MainFlowInDoc.GetText (Constants.FTI_TblAnchor);

// If you want to loop through all of the tables, you can do this:
    count = textList.length;
    tableCtr = tableCtr + count;
    for (i = 0; i < count; i += 1) {
        tbl = textList[i].obj // The table object.
        tbl = doc.FirstTblInDoc;
        if(tbl.ObjectValid() == false) {
            Console('   No tables found!');
        }
    }
    return tableCtr;
}

Was hoping it would be as simple as doc.FirstGraphicInDoc.Name would work, but it's obviously not that simple. As always.  Any suggestions very much appreciated.

    Correct answer Bob_Niland

    A non-trivial part of the challenge here that FM has no default structure for a figure title at all, and authors don't always use the standard Title feature of the Table structure.

     

    Lacking Anchored Frame above, I have often used various hacks to get the title and other metadata into the bottom of the AF. I use consistent ¶names when doing this, but you won't encounter those. I've also used an invisible run-in ¶Figure.Anchor for the AF, with a ¶Figure.Caption as Next, both set to keep.

     

    Since Tables have to be anchored to some ¶format, that's usually ¶Table.Anchor or ¶Table.Title in my work, and may serve as the Table title.

     

    Are any of the AIs smart enough to scan a PDF and both count and name objects of interest?

    3 replies

    Bob_Niland
    Community Expert
    Bob_NilandCommunity ExpertCorrect answer
    Community Expert
    July 16, 2025

    A non-trivial part of the challenge here that FM has no default structure for a figure title at all, and authors don't always use the standard Title feature of the Table structure.

     

    Lacking Anchored Frame above, I have often used various hacks to get the title and other metadata into the bottom of the AF. I use consistent ¶names when doing this, but you won't encounter those. I've also used an invisible run-in ¶Figure.Anchor for the AF, with a ¶Figure.Caption as Next, both set to keep.

     

    Since Tables have to be anchored to some ¶format, that's usually ¶Table.Anchor or ¶Table.Title in my work, and may serve as the Table title.

     

    Are any of the AIs smart enough to scan a PDF and both count and name objects of interest?

    frameexpert
    Community Expert
    Community Expert
    July 15, 2025

    Why do you have this in there?

    tbl = doc.FirstTblInDoc;
    Fightergator
    Inspiring
    July 15, 2025

    Not exactly sure...I think it was in a piece of code I found on the forum, or recommended by one of the contributors.  Since the counter worked with it, I never bothered to question it.  However, I just ran the script with that line remarked out and it had no effect.  Still unable to pull the titles using the two lines of code you provided.  I'm guessing I have to use the getText function, but can't determine what textObj I need to send it.  Thanks for you time on this!

    frameexpert
    Community Expert
    Community Expert
    July 12, 2025

    Tables can have titles and you can check for one with this:

    if (tbl.TblTitlePosition !== Constants.FV_TBL_NO_TITLE) {
        // The FirstPgf property is always the table title.
        pgf = tbl.FirstPgf;
        // ... Get the text of the pgf here.
    }

    Anchored frames don't have built-in titles, so you have to figure out if there is a paragraph format to look for that has the title in it. I assuming you mean the title on the page. If you mean the graphic's file name, then it is this:

    // See if it is an imported graphic.
    if (graphic.constructor.name === "Inset") {
        filename = graphic.InsetFile;
    }

    If the graphic is imported by copy, the filename will be an empty string.

    Fightergator
    Inspiring
    July 15, 2025

    Thanks for the code suggestions.  I must be doing something wrong, because I don't get any "hits" on titles.  Here's how I incorporated your code into my table count script.  It doesn't appear the "if" statement condition is being met.  I'm working with unstructured FM 2022 docs, if that makes a difference.  

    function countTbls() {
    
        tableCtr = 0;
        textList = doc.MainFlowInDoc.GetText (Constants.FTI_TblAnchor);
    
    // If you want to loop through all of the tables, you can do this:
        count = textList.length;
        tableCtr = tableCtr + count;
        for (i = 0; i < count; i += 1) {
            tbl = textList[i].obj // The table object.
            tbl = doc.FirstTblInDoc;
            
            if (tbl.TblTitlePosition !== Constants.FV_TBL_NO_TITLE) {
                pgf = tbl.FirstPgf
                alert('Table title = ' + pgf);
                }
    
    //var find = getText (textRange, doc);
            
            if(tbl.ObjectValid() == false) {
                Console('   No tables found!');
            }
        }
        return tableCtr;
    }

     I haven't had a chance to work with the figure titles.  Wanted to get this working first.

    frameexpert
    Community Expert
    Community Expert
    July 16, 2025

    Some comments on your code:

     

    You need to declare your function variables inside the function or else they will be global to the whole script. You should also pass in the document object when calling the function.

    function countTbls(doc) {
    
        var tableCtr, textList, count, i, tbl, pgf;

     The tableCtr variable is unnecessarily because you already have the table count with this line:

    count = textList.length;

    If you are using this to get the number of tables in a book, it's best to increment this outside the function.

     

    This line is forcing the script to the first table everytime through the loop. It should be deleted.

    tbl = doc.FirstTblInDoc;

    If this is true, then you will have to use a function to get the text from the table's first paragraph (the title).

    if (tbl.TblTitlePosition !== Constants.FV_TBL_NO_TITLE) {
        pgf = tbl.FirstPgf;
        alert('Table title paragraph object = ' + pgf);
        // Use a function to get the paragraph object's text, for example:
        text = getText (pgf, doc);
    }

    If you use "text" as a variable, be sure to declare it at the top of the function.

     

    This will never match in the position you have it, because if textList returns tables (text items), then there is at least one table in the document's main flow.

    if(tbl.ObjectValid() == false) {
        Console('   No tables found!');
    }
    

    If there are no tables, then the count variable will be 0.