Consulting

Results 1 to 13 of 13

Thread: VBA Opening and Editing Word document when another is already open

  1. #1

    VBA Opening and Editing Word document when another is already open

    I have an Access macro which opens a new Word window, opening a pre-created .doc file. It then searches for key strings and replaces them.
    This works fine as long as word isn't already open. If I have a seperate document open, the new document opens on top, appears active, but my modifications done in VBA are executed on the first document.

    I am using this code to try and 'activate' the document I want, but to no avail:
    Set wrdApp = CreateObject("Word.Application")
        wrdApp.Visible = True
        wrdApp.Activate
        Set wrdDoc = wrdApp.Documents.Open("" & GetDBPath() & "MyDocument.doc")
        wrdDoc.Activate
    Thanks for your help.

  2. #2
    VBAX Master TonyJollans's Avatar
    Joined
    May 2004
    Location
    Norfolk, England
    Posts
    2,291
    Location
    No need to activate anything. You have a reference to your document - just use it.
    Enjoy,
    Tony

    ---------------------------------------------------------------
    Give a man a fish and he'll eat for a day.
    Teach him how to fish and he'll sit in a boat and drink beer all day.

    I'm (slowly) building my own site: www.WordArticles.com

  3. #3
    That's what I thought, however when I call a selection function such as:
    Selection.Find.Execute
    It actually executes on the first instance of Word, not the currently open, currently active Word instance which my document is open in.

  4. #4
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Then use:
    [vba]
    wrdApp.Selection.Find.Execute
    [/vba]

    It is good to use fully qualified instructions.

  5. #5
    Quote Originally Posted by fumei
    Then use:
    [vba]
    wrdApp.Selection.Find.Execute
    [/vba]
    It is good to use fully qualified instructions.
    That one fixed it, thanks.

  6. #6
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Basically, if you want wrdApp to use Selection...then tell VBA to do exactly that. Selection is an object of the application.

    In your case, Selection.Find is NOT the same as wrdApp.Selection.Find

    Selection, by itself will be used by Word.

    wrdApp.Selection will be used by THAT instance (wrdApp) of Word.

  7. #7
    VBAX Master TonyJollans's Avatar
    Joined
    May 2004
    Location
    Norfolk, England
    Posts
    2,291
    Location
    Quote Originally Posted by A.T
    That's what I thought, however when I call a selection function such as:
    Selection.Find.Execute
    It actually executes on the first instance of Word, not the currently open, currently active Word instance which my document is open in.
    I do not believe that this statement would act on a separate instance of Word - unless you were already holding a reference to it - in which case I wonder why you are creating a new one.

    As you have discovered, Gerry was correct to tell you to qualify the reference with the application. I am surprised he did not tell you to use:
    [vba]wrdDoc.Range.Find[/vba] but none of use are perfect :-)

    The Selection is what is displayed on screen, what the user interacts with. There is a significant overhead in using this when you do not want to interact with the user.
    Enjoy,
    Tony

    ---------------------------------------------------------------
    Give a man a fish and he'll eat for a day.
    Teach him how to fish and he'll sit in a boat and drink beer all day.

    I'm (slowly) building my own site: www.WordArticles.com

  8. #8
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    I did not as I rant on about that far too much, and it was not directly part of the OP question.

    But since it is now mentioned....

    use wrdDoc.Range.Find

    I too have to wonder why you are creating another instance, if you already have one. Word can handle a lot. Unless you have a really serious reason to make another instance, it would be better to simply use the one you already have.

  9. #9
    Quote Originally Posted by TonyJollans
    There is a significant overhead in using this when you do not want to interact with the user.
    By 'overhead' do you mean that this will run slowly, as this is what I am finding. If I'm trying to replace multiple pieces of text, it takes about 1 second per replacement, so if I have 18 keywords to replace, it takes 18 seconds.

    The code here:
    Dim iCount As Integer
        For iCount = 1 To 18
            wrdApp.Selection.Find.Text = findData(iCount)
            wrdApp.Selection.Find.Replacement.Text = replData(iCount)
            wrdApp.Selection.Find.Forward = True
            wrdApp.Selection.Find.Wrap = wdFindContinue
            wrdApp.Selection.Find.Format = False
            wrdApp.Selection.Find.MatchCase = True
            wrdApp.Selection.Find.MatchWholeWord = False
            wrdApp.Selection.Find.MatchWildcards = False
            wrdApp.Selection.Find.MatchSoundsLike = False
            wrdApp.Selection.Find.MatchAllWordForms = False
            
            wrdApp.Selection.Find.Execute Replace:=wdReplaceAll
        
        Next iCount
    Looks in the array findData{} for the search terms and replData{} for the text to replace it with.
    This code works fine, but is rather slow.

    I tried changing the code to be:
    wrdDoc.Select
    wrdDoc.Range = Selection.Range
    
        Dim iCount As Integer
        For iCount = 1 To 18
            wrdDoc.Range.Find.Text = findData(iCount)
            wrdDoc.Range.Find.Replacement.Text = replData(iCount) 
            wrdDoc.Range.Find.Forward = True
            wrdDoc.Range.Find.Wrap = wdFindContinue
            wrdDoc.Range.Find.Format = False
            wrdDoc.Range.Find.MatchCase = True
            wrdDoc.Range.Find.MatchWholeWord = False
            wrdDoc.Range.Find.MatchWildcards = False
            wrdDoc.Range.Find.MatchSoundsLike = False
            wrdDoc.Range.Find.MatchAllWordForms = False
            
            wrdDoc.Range.Find.Execute Replace:=wdReplaceAll
    
        Next iCount
    However, this doesn't actually change anything. At first I thought that my range wasn't set as the whole document, so I added "wrdDoc.Select
    wrdDoc.Range = Selection.Range", hoping that this worked.

    In essence, it is slow to replace text and I can't seem to implementwrdDoc.Range.Find correctly.

    The interesting thing is that when using the Selection.Find method, when the text is being replaced slowly, if I take focus off the Word application, even by clicking the windows Start button, the text is suddenly replaced quickly.

    Rather odd.


    EDIT: In relation to the original question, why do I have two instances of Word open? I don't. I only tell my VBA code to open an instance so that I have a handle to the document and application I want. However, say the user is writing a letter to a friend (completely unrelated to the database), and then executes this script; previously, it would edit the first document open, in this case the letter, which I don't want it to, I want it to edit the document I've just opened.
    Hopefully that clears up why I have two 'instances' of word open.

  10. #10
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    "I only tell my VBA code to open an instance so that I have a handle to the document and application I want."

    To repeat, you do NOT need to do that.

    Say they are in one document, and execute your code.

    [vba]Dim wrdDoc As Document
    ' NOTE! there is NO wrdApp! No other instance.
    Set wrdDoc = Documents.Open("" & GetDBPath() & "MyDocument.doc")
    [/vba]There is no need to Activate it. You are creating a Document object, and you can action it directly.

    As was mentioned, using Range, rather than Selection, is better. In fact, you do not need to Select anything at all, nor do you need any counters.

    IF your arrays - findData() for the search terms and replData() for the replacement text - are equal in number, it does not matter if there are 18 or 231 items in them. If they are not equal, this is another issue.
    [vba]' assume your arrays are HERE, or
    ' globals
    Dim wrdDoc As Document
    Dim r As Range
    Dim var
    ' opens the document as a Document object
    Set wrdDoc = Documents.Open("" & GetDBPath() & "MyDocument.doc")
    ' loop through the array findData
    For var = 0 To UBound(findData)
    ' set range object
    Set r = wrdDoc.Range
    With r.Find
    ' text to find is findData(var)
    .Text = findData(var)
    ' text to replace is replData(var)
    .Execute Forward:=True, Replacewith:=replData(var), _
    Replace:=wdReplaceAll
    End With
    Next

    ' Done

    ' I assume you want to save the document
    With wrdDoc
    .Save
    .Close
    End With
    set wrdDoc = Nothing
    [/vba]

    The other document - the one they are working on - is not touched, or affected. Nothing is Selected whatsoever.

    I suggest you learn to use With statements.

    Again, there is no need for another instance at all. Multiple instances should be avoided, and it is a VERY rare case where they are actually needed. Word can handle multiple files quite well with a single instance.

  11. #11
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    " In relation to the original question, why do I have two instances of Word open? I don't."

    Yes, you do.

    "I want it to edit the document I've just opened."

    You can, by using a Document object, which you are, in fact, using with your original posted code. It is simply that you do not need another, new, instance of Word do to this.

  12. #12
    Thanks, fumei, using range calls instead of selection calls is much faster.
    Thanks for all your advice and time.

  13. #13
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Oh yes, using Range is generally MUCH faster than Selection, and for good reason.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •