Skip to main content
Participating Frequently
November 26, 2024
Answered

Get All Tables in an Indesign Document - Indesign SDK C++

  • November 26, 2024
  • 2 replies
  • 998 views

How would I iterate through every page in an Indesign document and build a list of the tables in each page, using the Indesign C++ SDK?

 

This topic has been closed for replies.
Correct answer Lawrence Horwitz

You'd have to get the stories in the document, iterate through them, and get all the tables on each story.

 

Each story has a list of story threads. Each table is a story thread (though not every story thread is a table). So go through all the threads in a story, check if it's a table, and if it add it to the list.  Read the API docs for more info on story models, story threads, and tables.

 

Here's sample code:

/**
 * @brief Retrieves all table models in the specified document.
 *
 * This function iterates through all user-accessible stories in the given document
 * and collects the UID references of all table models found within those stories.
 *
 * @9397041 in_DocUIDRef The UID reference of the document to search for table models.
 * @9397041 out_TableUIDs A vector to store the UID references of the found table models.
 * @Return ErrorCode Returns kSuccess if all table models are successfully retrieved, otherwise kFailure.
 */
ErrorCode GetAllTableModelsOnDocument(const UIDRef& in_DocUIDRef, UIDRefVector& out_TableUIDs) const
{
    ErrorCode status = kFailure;

    do {
        // Get the story list interface for the document
        InterfacePtr<IStoryList> storyList(in_DocUIDRef, UseDefaultIID());
        if (storyList == nil)
        {
            ASSERT(storyList);
            break;
        }

        // Get the database associated with the document
        IDataBase* db = in_DocUIDRef.GetDataBase();
        if (db == nil)
        {
            ASSERT(db);
            break;
        }

        // Get the number of user-accessible stories in the document
        const int32 numStories = storyList->GetUserAccessibleStoryCount();

        status = kSuccess;

        // Iterate through each story and collect table models
        for (int32 index = 0; index < numStories; ++index)
        {
            UIDRef curStory(storyList->GetNthUserAccessibleStoryUID(index));

            // Retrieve all tables in the current story
            if (GetAllTablesInStory(curStory, out_TableUIDs) != kSuccess)
            {
                ASSERT_FAIL("Could not get tables from story!");
                status = kFailure;
                break;
            }
        }
    } while (kFalse);

    return status;
}

/**
 * @brief Retrieves all table models in the specified text story.
 *
 * This function iterates through the text story threads in the given text story
 * and collects the UID references of all table models found within those threads.
 *
 * @9397041 in_TextStoryRef The UID reference of the text story to search for table models.
 * @9397041 out_TableModelUIDs A vector to store the UID references of the found table models.
 * @Return ErrorCode Returns kSuccess if all table models are successfully retrieved, otherwise kFailure.
 */
ErrorCode GetAllTablesInStory(const UIDRef& in_TextStoryRef, UIDRefVector& out_TableModelUIDs) const
{
    ErrorCode status = kFailure;

    do {
        // Get the database associated with the text story
        IDataBase* db = in_TextStoryRef.GetDataBase();
        if (db == nil)
        {
            ASSERT(db);
            break;
        }

        // Get the story thread hierarchy interface for the text story
        InterfacePtr<ITextStoryThreadDictHier> storyThreadHier(in_TextStoryRef, UseDefaultIID());
        if (storyThreadHier == nil)
        {
            ASSERT(storyThreadHier);
            break;
        }

        UID nextUID = in_TextStoryRef.GetUID();

        // Iterate through the story threads and collect table models
        do {
            if (nextUID != kInvalidUID)
            {
                // Get the table model interface for the current UID
                InterfacePtr<ITableModel> tableModel(db, nextUID, UseDefaultIID());

                // If it's a table model, add it to the output vector
                if (tableModel != nil)
                {
                    out_TableModelUIDs.push_back(UIDRef(db, nextUID));
                }
            }
            nextUID = storyThreadHier->NextUID(nextUID);
        } while (nextUID != kInvalidUID);

        status = kSuccess;
    } while (kFalse);

    return status;
}

 

2 replies

Lawrence HorwitzCorrect answer
Inspiring
November 28, 2024

You'd have to get the stories in the document, iterate through them, and get all the tables on each story.

 

Each story has a list of story threads. Each table is a story thread (though not every story thread is a table). So go through all the threads in a story, check if it's a table, and if it add it to the list.  Read the API docs for more info on story models, story threads, and tables.

 

Here's sample code:

/**
 * @brief Retrieves all table models in the specified document.
 *
 * This function iterates through all user-accessible stories in the given document
 * and collects the UID references of all table models found within those stories.
 *
 * @9397041 in_DocUIDRef The UID reference of the document to search for table models.
 * @9397041 out_TableUIDs A vector to store the UID references of the found table models.
 * @Return ErrorCode Returns kSuccess if all table models are successfully retrieved, otherwise kFailure.
 */
ErrorCode GetAllTableModelsOnDocument(const UIDRef& in_DocUIDRef, UIDRefVector& out_TableUIDs) const
{
    ErrorCode status = kFailure;

    do {
        // Get the story list interface for the document
        InterfacePtr<IStoryList> storyList(in_DocUIDRef, UseDefaultIID());
        if (storyList == nil)
        {
            ASSERT(storyList);
            break;
        }

        // Get the database associated with the document
        IDataBase* db = in_DocUIDRef.GetDataBase();
        if (db == nil)
        {
            ASSERT(db);
            break;
        }

        // Get the number of user-accessible stories in the document
        const int32 numStories = storyList->GetUserAccessibleStoryCount();

        status = kSuccess;

        // Iterate through each story and collect table models
        for (int32 index = 0; index < numStories; ++index)
        {
            UIDRef curStory(storyList->GetNthUserAccessibleStoryUID(index));

            // Retrieve all tables in the current story
            if (GetAllTablesInStory(curStory, out_TableUIDs) != kSuccess)
            {
                ASSERT_FAIL("Could not get tables from story!");
                status = kFailure;
                break;
            }
        }
    } while (kFalse);

    return status;
}

/**
 * @brief Retrieves all table models in the specified text story.
 *
 * This function iterates through the text story threads in the given text story
 * and collects the UID references of all table models found within those threads.
 *
 * @9397041 in_TextStoryRef The UID reference of the text story to search for table models.
 * @9397041 out_TableModelUIDs A vector to store the UID references of the found table models.
 * @Return ErrorCode Returns kSuccess if all table models are successfully retrieved, otherwise kFailure.
 */
ErrorCode GetAllTablesInStory(const UIDRef& in_TextStoryRef, UIDRefVector& out_TableModelUIDs) const
{
    ErrorCode status = kFailure;

    do {
        // Get the database associated with the text story
        IDataBase* db = in_TextStoryRef.GetDataBase();
        if (db == nil)
        {
            ASSERT(db);
            break;
        }

        // Get the story thread hierarchy interface for the text story
        InterfacePtr<ITextStoryThreadDictHier> storyThreadHier(in_TextStoryRef, UseDefaultIID());
        if (storyThreadHier == nil)
        {
            ASSERT(storyThreadHier);
            break;
        }

        UID nextUID = in_TextStoryRef.GetUID();

        // Iterate through the story threads and collect table models
        do {
            if (nextUID != kInvalidUID)
            {
                // Get the table model interface for the current UID
                InterfacePtr<ITableModel> tableModel(db, nextUID, UseDefaultIID());

                // If it's a table model, add it to the output vector
                if (tableModel != nil)
                {
                    out_TableModelUIDs.push_back(UIDRef(db, nextUID));
                }
            }
            nextUID = storyThreadHier->NextUID(nextUID);
        } while (nextUID != kInvalidUID);

        status = kSuccess;
    } while (kFalse);

    return status;
}

 

Legend
November 29, 2024

ITableModelList is still around despite an old deprecation warning that also confirms ITextStoryThreadDictHier as new scheme.

On the other hand ITableModelList could be quicker as it is persistent.

Tough choice.

Inspiring
December 1, 2024

Ha! I think ITableModelList is 99.9% safe.  How many years old do you think that deprecation warning is?

 

Good points as always.

Robert at ID-Tasker
Legend
November 26, 2024

You don't go through Pages - you go through Stories. 

 

Participating Frequently
November 26, 2024

OK, if that's the case, how do I go through Stories?

Robert at ID-Tasker
Legend
November 26, 2024

I'm sorry but I'm not plug-in writer.

 

But, if I may - first, learn how to use InDesign and learn scripting - DOM - otherwise, you'll be constantly hitting the wall - as you have no idea about InDesign's internal structure.