none
Replace text using late binding RRS feed

  • Question

  • Hi.  I wonder if someone can point me in the right direction.  I am using the Office PIAs to open a Word document, and I'd like to replace some text within it.  However I can't quite find the right code to perform the replacement.  Here's what I have so far:-

    Dim objWordType As Type
    Dim objWord As Object 'Word.Application
    Dim objDocs As Object 'Word.Documents
    Dim objDoc As Object 'Word.Document
    Dim objStoryRanges As Object 'Word.StoryRanges
    Dim objStoryRangeItem As Object 'Word.Range?
    
    'The code below works perfectly
    
    objWordType = Type.GetTypeFromProgID("Word.Application")
    objWord = Activator.CreateInstance(objWordType, True)
    objDocs = objWord.GetType().InvokeMember("Documents", Reflection.BindingFlags.GetProperty, Nothing, objWord, Nothing)
    objDoc = objDocs.GetType().InvokeMember("Add", Reflection.BindingFlags.InvokeMethod, Nothing, objDocs, New Object() {strTempFileName})
    objStoryRanges = objDocs.GetType().InvokeMember("StoryRanges", Reflection.BindingFlags.GetProperty, Nothing, objDoc, Nothing)
    
    ' The next block of text is where my question relates to. I realise that I am not using reflection here, this is what I am struggling to translate correctly
    For Each objStoryRangeItem In objStoryRanges
       With objStoryRangeItem.Find
           .Text = "ReplaceThisText"
           .Replacement.Text = "WithThisNewText"
           .Execute(Replace:=2)
       End With
    Next
    Can anyone help?

    Alan Moseley

    Monday, November 18, 2013 9:59 AM

Answers

  • Hi Alan

    I find the following sample code in my test project

    //Using late binding
    object f = null;
    f = rng.GetType().InvokeMember("Find", BindingFlags.GetProperty, null,
        rng, null);
    f.GetType().InvokeMember("ClearFormatting", System.Reflection.BindingFlags.InvokeMethod, null,
        f, null);
    object bFound;
    object[] args = new object[11] { "test", missing, -1 , missing, missing, missing, missing, missing, missing,
        "OK", 1 }; //, missing, missing, missing, missing, missing, missing, missing, missing, missing };
    bFound = f.GetType().InvokeMember("Execute", BindingFlags.InvokeMethod, null,
        f, args);
    rng.Select();
    MessageBox.Show(f.Found.ToString());
    


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, November 19, 2013 7:01 PM
    Moderator
  • HI Alan

    I'm not sure I'm understanding things correctly...

    The Word Application can only run when Word is installed. Anything you do that works with the Word object model requires the installation of Word. Word code cannot run solely on the PIAs - the application must be present. It doesn't matter whether or not you use late-binding - the application is required.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, November 20, 2013 4:01 PM
    Moderator

All replies

  • Hi Alan

    I find the following sample code in my test project

    //Using late binding
    object f = null;
    f = rng.GetType().InvokeMember("Find", BindingFlags.GetProperty, null,
        rng, null);
    f.GetType().InvokeMember("ClearFormatting", System.Reflection.BindingFlags.InvokeMethod, null,
        f, null);
    object bFound;
    object[] args = new object[11] { "test", missing, -1 , missing, missing, missing, missing, missing, missing,
        "OK", 1 }; //, missing, missing, missing, missing, missing, missing, missing, missing, missing };
    bFound = f.GetType().InvokeMember("Execute", BindingFlags.InvokeMethod, null,
        f, args);
    rng.Select();
    MessageBox.Show(f.Found.ToString());
    


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, November 19, 2013 7:01 PM
    Moderator
  • Hi Cindy

    Thankyou, with your assistance I find myself almost there.  I have converted your code to VB to give me this:-

    For Each objStoryRangeItem In objStoryRanges
        Dim objFind As Object = objStoryRangeItem.GetType().InvokeMember("Find", Reflection.BindingFlags.GetProperty, Nothing, objStoryRangeItem, Nothing)
        If Not objFind Is Nothing Then
           Dim objFindText As String = "{{" + objField.FieldName + "}}"
           Dim objReplacementText As String = objField.FieldValue
           objFind.GetType().InvokeMember("Execute", Reflection.BindingFlags.InvokeMethod, Nothing, objFind, New Object() {objFindText, Nothing, -1, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, objReplacementText, 2})
        End If
    Next

    On my development machine, which has Word installed, this all works perfectly, but on the production machine which has only the PIAs it does not.  I suspect that it is the 'For Each objStoryRangeItem In objStoryRanges' line which is the culprit, it does look as though I have used late binding here.  Would you concur?  If so, do you have any suggestions as to what I can replace it with?  If not, might you have any other suggestions.  I know that my code works up until it reaches the code above.

    Kind regards

    Alan


    Alan Moseley

    Tuesday, November 19, 2013 8:14 PM
  • HI Alan

    I'm not sure I'm understanding things correctly...

    The Word Application can only run when Word is installed. Anything you do that works with the Word object model requires the installation of Word. Word code cannot run solely on the PIAs - the application must be present. It doesn't matter whether or not you use late-binding - the application is required.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, November 20, 2013 4:01 PM
    Moderator
  • Cindy

    Unfortunately you are understanding things correctly, I do not have Word installed and this is therefore the reason it isn't working.  Your comment has saved me a bunch of time, thankyou.  I have now also installed Word and things are now working perfectly.

    Just for completeness, I persisted with my late-binding code and the finished code is:-

    Dim objWordType As Type
    Dim objWord As Object 'Word.Application
    Dim objDocs As Object 'Word.Documents
    Dim objDoc As Object 'Word.Document
    Dim objStoryRanges As Object 'Word.StoryRanges
    Dim objStoryRangeItem As Object 'Word.Range
    objWordType = Type.GetTypeFromProgID("Word.Application")
    objWord = Activator.CreateInstance(objWordType, True)
    objDocs = objWord.GetType().InvokeMember("Documents", Reflection.BindingFlags.GetProperty, Nothing, objWord, Nothing)
    objDoc = objDocs.GetType().InvokeMember("Add", Reflection.BindingFlags.InvokeMethod, Nothing, objDocs, New Object() {"myfile.docx"})
    objStoryRanges = objDocs.GetType().InvokeMember("StoryRanges", Reflection.BindingFlags.GetProperty, Nothing, objDoc, Nothing)
    Dim objEnumerator As IEnumerator = objStoryRanges.GetType().InvokeMember("GetEnumerator", Reflection.BindingFlags.InvokeMethod, Nothing, objStoryRanges, Nothing)
    objEnumerator.Reset()
    While objEnumerator.MoveNext
        objStoryRangeItem = objEnumerator.Current
        Dim objFind As Object = objStoryRangeItem.GetType().InvokeMember("Find", Reflection.BindingFlags.GetProperty, Nothing, objStoryRangeItem, Nothing)
        objFind.GetType().InvokeMember("Execute", Reflection.BindingFlags.InvokeMethod, Nothing, objFind, New Object() {"Text to search for", True, False, False, False, False, True, 1, False, "Replacement Text", 2})
    End While
    Hope this helps someone else.

    Alan Moseley

    Sunday, November 24, 2013 12:54 PM