Search code examples
c++vbams-wordc++builderole

Retrieve and loop through Story Ranges from Word OLE using Embarcadero C++ (Builder)


I have a code snippet which loops through a list of hyperlink (file link) objects (members anchor and destination) and inserts them into a selected Word document. I can search the Word document and insert the hyperlink when it finds the target (anchor) string. I would now like to loop through all the StoryRanges in the Word document to ensure that no sections is missed. I can get the number of story ranges, e.g., using WordApplication1->ActiveDocument->StoryRanges->Count. However, I can't pass the parameter in the correct form to actually retrieve the story range I want to search next, e.g. WordApplication1->ActiveDocument->StoryRanges->Item. I have a numeric count but Item expects as a parameter a VBA constant with the correct type. What am I missing?

Edit Here is the code. The line causing the problem is

wdFootnotesStoryID = WordApplication1->ActiveDocument->StoryRanges->Item(??????)->get_ID();

I previously tried to typing parameters as int, OleVariant. The error message for OleVariant was did not match the parameter expected. I used wdFootnotesStory in an attempt to reference the enum but that came up as not defined. I tried Int values as well.

Here is the OLESafe enum - defined in Word_2k.h

enum class WdStoryType
{
  wdMainTextStory = 1, 
  wdFootnotesStory = 2, 
  wdEndnotesStory = 3, 
  wdCommentsStory = 4, 
  wdTextFrameStory = 5, 
  wdEvenPagesHeaderStory = 6, 
  wdPrimaryHeaderStory = 7, 
  wdEvenPagesFooterStory = 8, 
  wdPrimaryFooterStory = 9, 
  wdFirstPageHeaderStory = 10, 
  wdFirstPageFooterStory = 11
};

Here is the main code.
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Word_2K_SRVR"
#pragma resource "*.dfm"

struct THyperLink
{
    String Anchor;
    String FilePath;
};

TList* linkList = new TList;

TForm1 *Form1;


//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    THyperLink* link = new THyperLink;
    link->Anchor = "ABC.0001.0002.0003";
    link->FilePath = "S:\\Development\\WordLinking\\Test\\ABC.0001.0002.0003.pdf";
    linkList->Add(link);

    THyperLink* link2 = new THyperLink;
    link2->Anchor = "ABC.0001.0002.0004";
    link2->FilePath = "S:\\Development\\WordLinking\\Test\\ABC.0001.0002.0004.pdf";
    linkList->Add(link2);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    OleVariant Template = EmptyParam();
    OleVariant NewTemplate = False;
    OleVariant ItemIndex = 1;
    OleVariant strToInsert = "Insert String";
    OleVariant endOfLine = "TEST";
    OleVariant wdStory = 6;
    //OleVariant wdMove = 0;
    OleVariant rng;

    OleVariant strSearch;// = "ABC.0001.0002.0003";
    OleVariant strLink; // = "S:Development\\WordLinking\\Test\\ABC.0001.0002.0003.pdf";
    OleVariant lnkDoc = "S:\\Development\\WordLinking\\Test\\ZZZ.0001.0002.0003.docx";

    OleVariant wdCharacter = "wdCharacter";
    OleVariant cChars = 18;
    OleVariant wdMove = "wdMove";
    OleVariant wdTrue = true;

    OleVariant wrdStoryRangeCount;
    OleVariant wdFootnotesStoryID;
    OleVariant rangeStory;
    OleVariant wrdDoc;

    WdStoryType wdFootnotesStory = 2;


    try
    {
        WordApplication1->Connect();

    }
    catch (...)
    {
        ShowMessage("Microsoft word is not installed");
    }



    //Make application visible
    WordApplication1->GetDefaultInterface()->Visible = True;

    //Open document to be linked
    WordApplication1->Documents->Open(lnkDoc);

    //Open new document - add to document collection in application
    //WordApplication1->Documents->Add(Template, NewTemplate);

    //go to top of the document
    WordApplication1->Selection->HomeKey(wdStory);

    for (int index = 0; index <= linkList->Count-1; index++)
    {
        //Retrieve hyperlink object
        THyperLink* link = reinterpret_cast<THyperLink*>(linkList->Items[index]);
        strSearch = (OleVariant)link->Anchor;
        strLink = (OleVariant)link->FilePath;

        //
        wrdStoryRangeCount = WordApplication1->ActiveDocument->StoryRanges->Count;

        //WordApplication1->ActiveDocument->StoryRanges->Item(1);

        wdFootnotesStoryID = WordApplication1->ActiveDocument->StoryRanges->Item(??????)->get_ID();
        ShowMessage ("wdFootnotesStory ID: " + wdFootnotesStoryID);

        //WordApplication1->ActiveDocument->get_

        while (WordApplication1->Selection->Find->Execute(strSearch,Template,Template,Template,Template,Template,wdTrue))
        //while (WordApplication1->ActiveDocument->StoryRanges->Item(wdFootnotesStory)->Find->Execute(strSearch,Template,Template,Template,Template,Template,wdTrue))
        {
            WordApplication1->Selection->Hyperlinks->Add(WordApplication1->Selection->Range,strLink,Template,Template,strSearch,Template);
        }

        //go back to top of Word document
        WordApplication1->Selection->HomeKey(wdStory);
    }

    //Disconnect from word
    WordApplication1->Disconnect();

}
//---------------------------------------------------------------------------

Solution: In the course of adding the code, I think I stumbled across the solution - WdStoryType::wdFootnotesStory. It appears all I was missing was the class qualifier reference.


Solution

  • Solution: In the course of adding the code, I think I stumbled across the solution - WdStoryType::wdFootnotesStory. It appears all I was missing was the class qualifier reference.