10

I've a perfectly working function to find and replace a variable with text in word documents.

HRESULT CMSWord::FindReplace( CString szVar, CString szText, bool bOnlyOnce/*=false*/ )
{
    if(m_pWApp==NULL || m_pActiveDocument==NULL) return E_FAIL;
    IDispatch *pDocApp;
    {  
        VARIANT result;
        VariantInit(&result);
        OLEMethod(DISPATCH_PROPERTYGET, &result, m_pActiveDocument, L"Application", 0);
        pDocApp= result.pdispVal;
    }
    IDispatch *pSelection;
    {
        VARIANT result;
        VariantInit(&result);
        OLEMethod(DISPATCH_PROPERTYGET, &result, pDocApp, L"Selection", 0);
        pSelection=result.pdispVal;
    }
    IDispatch *pFind;
    {
        VARIANT result;
        VariantInit(&result);
        OLEMethod(DISPATCH_PROPERTYGET, &result, pSelection, L"Find", 0);
        pFind=result.pdispVal;
    }
    OLEMethod(DISPATCH_METHOD, NULL, pFind, L"ClearFormatting",0);

    szText.Replace(_T("\r\n"), _T("\v")); 
    COleVariant sVariable(szVar);
    COleVariant sReplaceText(szText);
    COleVariant replace((long)2);
    COleVariant varBoolTrue;
    varBoolTrue.boolVal = true;
    COleVariant varBoolFalse;
    varBoolFalse.boolVal = false;
    COleVariant wdContinue((long)1);
    bool bFound=false;
    IDispatch *pExecute = NULL;
    {
        for(;;) {
            VARIANT result;
            VariantInit(&result);

            if(OLEMethod(DISPATCH_METHOD, &result, pFind, L"Execute", 8, wdContinue, varBoolTrue, varBoolFalse, varBoolFalse, varBoolFalse, varBoolTrue, varBoolFalse, sVariable)==S_OK) {
                pExecute=result.pdispVal;
                if(!pExecute) break;
                bFound = true;
                if(szText.IsEmpty()) DeleteChar(false);         else SetSelectionText(szText);
            }
            else break;
            if(bOnlyOnce) break;
        }
    }
    pDocApp->Release();
    pSelection->Release();
    pFind->Release();
    if(!bFound) return E_FAIL;
    else return S_OK;
}

The problem is, that this code won't touch any text in the header or the footer.

Maybe there is a parameter for the pFind execute method?

Honestly I've been looking in to this problem since Monday. The most of my search results are VB, C#, .NET and VBA documentation, but there is little documentation on VC++ OLE, a few lines of code, but nothing helpful. I even started to create and translate some Word macros, nothing works.

Here on Stack Overflow I found many questions related to this topic. Some of them looked promising, but it seems they're using some framework I don't know and people have left no response if I asked for sample code or links.

If someone can me help on this matter it'd be awesome and I'd really appreciate links to documentation and code on the general topic of OLE Word automation (besides this codeproject article).

Thanks in advance!

Seer
  • 5,226
  • 5
  • 33
  • 55
masche
  • 1,643
  • 2
  • 14
  • 24
  • 1
    I thingk you need to search and replace in all Story Ranges, as described here: http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm – Simon Mourier Jan 02 '13 at 10:49
  • In the meantime I've tried to adapt many VB and VBA macro codes. There are a few functions on the internet that works, but my own creations crashes. I need some kind of documentations how to adapt those funktions to c++. – masche Jan 02 '13 at 12:03
  • `OLEMethod(DISPATCH_METHOD, &result, pFindReplace, L"Execute", 15, v_false, //match control v_false, //match Alef Hamza v_false, //match didactics v_false, //match kashida v_replace, //replace v_replace_text, //replace with v_false, //format v_wrap, //find wrap v_true, //forward v_false, //match all word forms v_false, //match sounds-like v_true, //match wildcards v_true, //match whole word v_true, //match case v_find); //find text ` Find/Replace directly. None of the param helps. :-( – masche Jan 02 '13 at 15:09
  • Is it possible to extract the headers and fotting as strings, do the replacement on the strings and then put the strings back? There should be an easy way to get and set the headers and footings? Btw, any specific reason that you use C++ for this? – ZombieSpy Jan 05 '13 at 23:36
  • I were happy if I knew how to read or set the whole footer or header per OLE. This is only a tiny part of a huge mfc project. – masche Jan 07 '13 at 08:58
  • Maybe you could just run the macro given at the link from the first comment by Simon Mourier using the method described at http://support.microsoft.com/kb/183369 ... – Gregor Ophey Jan 07 '13 at 21:11
  • So, I guess this means there is no way adding/altering header/footer only per c++, am I right? A word macro is unfortunately no option because, we are generating rtf documents and is unable for me to insert a new macro there during or after generating. – masche Jan 08 '13 at 09:35
  • If you're only using RTF, then why do you need to use Word at all, at least for this part? Why not just use [simple string S & R](http://stackoverflow.com/questions/1494399/how-do-i-search-find-and-replace-in-a-standard-string)? – klugerama May 14 '13 at 19:07
  • Hi! Are you still interested by your question? – manuell Nov 20 '13 at 10:43
  • Sure, if you got any hints.But I'm quite convinced, that this problem can't be solved with unmanaged VC++. – masche Nov 21 '13 at 08:20

1 Answers1

1

Here is a Delphi function that searches and replaces in the header. I know this is a C++ question, but you can see from the functions what you need to do.

I always find that the simplest way to do something in work is to use the MacroRecorder and see how word does it, then call that code from your app.

I pity you doing COM programming in C++

Procedure Find_ReplaceText(find, ReplaceWith: String; Header : Boolean = false);
var
    tmpText: String;
    spos , epos : Integer;
begin
    {Start on first page.}
    fWordApp.Selection.Goto(wdGoToPage,wdGotoFirst);
    {Extra code is needed if I'm trying to replace text in the header}
    if Header then
    begin
        fWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekCurrentPageHeader;



        If fWordApp.Selection.HeaderFooter.IsHeader = False Then
        begin
            fWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekCurrentPageHeader;
        end;

        tmpText := fWordApp.ActiveDocument.sections.item(1).Headers.item(wdHeaderFooterPrimary).Range.text;
        spos := pos('[' ,tmptext);
        epos := pos(']' , tmpText);

        tmptext := copy(tmptext,1, spos);
        tmptext := tmptext + ReplaceWith + ']';
        fWordApp.ActiveDocument.sections.item(1).Headers.item(wdHeaderFooterPrimary).Range.text := tmptext;
        fWordApp.ActiveWindow.ActivePane.View.SeekView := wdSeekMainDocument;
    end
    else
    begin
        fWordApp.Selection.Find.Text := find;
        fWordApp.Selection.Find.Execute;
        fWordApp.Selection.typeText(' ');
        fWordApp.Selection.InsertAfter(ReplaceWith);
    end;

end;
Toby Allen
  • 10,997
  • 11
  • 73
  • 124