Adding multiple words to a word document in a sentence using an array with VBA

泪湿孤枕 提交于 2019-12-12 05:59:18

问题


My question pertains to the Do While loop in my code, but I posted the whole thing to show you what I'm doing. This code will compare two documents. The object is to have blue text in a revision document added into the sentences of the original document and have that become a new third document. The functionality I am having trouble accomplishing is adding multiple words within a sentence. Right now I can add a word anywhere in a sentence as long as it is the only instance of blue text within that sentence. The program finds blue text and selects the entire sentence of that particular blue word. This is the only way I have thought how to reference where to add the new text to the third document. The blue text is removed from the sentence and that sentence is taken and found in the original document that has been copied. The blue text is then added back and saved to the new document. Here is a rundown of why one blue word per sentence will work and not two or more:

Does not work:
Original Document: "This String Is."
Revision Document: "This New String Is New."
The first blue word is found and taken out to compare the string to the original document but.....
"This String Is New" does not match with "This String Is"

This works though with just one blue word per sentence:
Original Document: "This String Is."
Revision Document: "This String Is New."
"New" is removed "This String Is." = "This String Is."

The sentence is found in the original document and the blue word is added to the copied original document and is saved. The program then moves onto the next blue word and repeats the process till no more blue text is found. However, without removing all instances of blue text within a sentence at once, there will not be a match in the orignal document. That is what I need help accomplishing, probably with an array.

Sub ArrayTest()

 MsgBox "Welcome to the word document automatic modifier", vbInformation + vbOKOnly

    MsgBox "Please open the revision file", vbInformation + vbOKOnly

    Dim strfilename1 As String
    Dim fd1 As Office.FileDialog

   ''''''Browsing/Opening the change request'''''''

    Set fd1 = Application.FileDialog(msoFileDialogFilePicker)

   With fd1

      .AllowMultiSelect = False
      .Title = "Open the modified word document."
      .Filters.Clear
      .Filters.Add "Word 2010", "*.docx"
      .Filters.Add "All Files", "*.*"

      If .Show = True Then
        strfilename1 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With


''''''''''' Browsing/Opening the original Design Manual'''''''''''''''''''''''''''

MsgBox "Open the orginal document", vbInformation + vbOKOnly


Dim strfilename2 As String

    Dim fd2 As Office.FileDialog

    Set fd2 = Application.FileDialog(msoFileDialogFilePicker)

   With fd2

      .AllowMultiSelect = False
      .Title = "Please select the original file."
      .Filters.Clear
      .Filters.Add "Word 2010", "*.docx"
      .Filters.Add "All Files", "*.*"

      If .Show = True Then
        strfilename2 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With


MsgBox "Please enter the file name with which you want to store the new updated file", vbInformation + vbOKOnly


''''''''''''''''''Asking user to input name to the new revised document'''''''''''''''''''''''''''''''''''''

Dim strfilename3 As String

    Dim fd3 As Office.FileDialog

    Set fd3 = Application.FileDialog(msoFileDialogSaveAs)

   With fd3
      .AllowMultiSelect = False
      .Title = "Please select the name to be given to the new file."
      If .Show = True Then
        strfilename3 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With


Dim strg1 As String
Dim strg2 As String
Dim strg3 As String
Dim count As Integer
Dim strgArray()


FileCopy strfilename2, strfilename3

Set objWordChange = CreateObject("Word.Application")
Set objWordorig = CreateObject("Word.Application")

objWordChange.Visible = False
objWordorig.Visible = False

Set objDocChange = objWordChange.Documents.Open(strfilename1)
Set objSelectionChange = objWordChange.Selection
Set objDocOrig = objWordorig.Documents.Open(strfilename3)
Set objSelectionOrig = objWordorig.Selection

count = 0

objSelectionChange.Find.Forward = True
objSelectionChange.Find.Format = True
objSelectionChange.Find.Font.Color = wdColorBlue

Do While True
    objSelectionChange.Find.Execute
    If objSelectionChange.Find.Found Then
        strg2 = objSelectionChange.Sentences(1).Text
        count = count + 1
        ReDim strgArray(count)
        strgArray(count) = objSelectionChange.Text
        MsgBox strgArray(count) & " Located In Array Index # " & count
        MsgBox strg2
        strg3 = Replace(strg2, strgArray(count), "")
        strg3 = Replace(strg3, "  ", " ")
        strg3 = Mid(strg3, 1, Len(strg3) - 2)
        strg4 = strg3
        MsgBox strg4

        Set objRangeOrig = objDocOrig.Content
        '''''Search the string in the original manual'''''
        With objRangeOrig.Find
        .MatchWholeWord = False
        .MatchCase = False
        .MatchPhrase = True
        .IgnoreSpace = True
        .IgnorePunct = True
        .Wrap = wdFindContinue
        .Text = strg4
        .Replacement.Text = Left(strg2, Len(strg2) - 2)
        .Execute Replace:=wdReplaceOne
        objDocOrig.Save
        End With
    Else
        Exit Do
    End If
Loop
objDocChange.Close
objDocOrig.Save
objDocOrig.Close

objWordChange.Quit
objWordorig.Quit

End Sub

Edit: This is the newer code as suggested by Dick, however it is still not completely working.

Sub WordReplaceSentence()

MsgBox "Welcome to the word document automatic modifier", vbInformation + vbOKOnly

MsgBox "Please open the revision file", vbInformation + vbOKOnly

    Dim strfilename1 As String
    Dim fd1 As Office.FileDialog

   ''''''Browsing/Opening the change request'''''''

    Set fd1 = Application.FileDialog(msoFileDialogFilePicker)

   With fd1

      .AllowMultiSelect = False
      .Title = "Open the modified word document."
      .Filters.Clear
      .Filters.Add "Word 2010", "*.docx"
      .Filters.Add "All Files", "*.*"

      If .Show = True Then
        strfilename1 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With


''''''''''' Browsing/Opening the original Design Manual'''''''''''''''''''''''''''

MsgBox "Open the orginal document", vbInformation + vbOKOnly


Dim strfilename2 As String

    Dim fd2 As Office.FileDialog

    Set fd2 = Application.FileDialog(msoFileDialogFilePicker)

   With fd2

      .AllowMultiSelect = False
      .Title = "Please select the original file."
      .Filters.Clear
      .Filters.Add "Word 2010", "*.docx"
      .Filters.Add "All Files", "*.*"

      If .Show = True Then
        strfilename2 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With


MsgBox "Please enter the file name with which you want to store the new updated file", vbInformation + vbOKOnly


''''''''''''''''''Asking user to input name to the new revised document'''''''''''''''''''''''''''''''''''''

    Dim strfilename3 As String

    Dim fd3 As Office.FileDialog

    Set fd3 = Application.FileDialog(msoFileDialogSaveAs)

   With fd3
      .AllowMultiSelect = False
      .Title = "Please select the name to be given to the new file."
      If .Show = True Then
        strfilename3 = .SelectedItems(1) 'replace txtFileName with your textbox
      Else
      Exit Sub
      End If
   End With

    FileCopy strfilename2, strfilename3

    Set objWordChange = CreateObject("Word.Application")
    Set objWordorig = CreateObject("Word.Application")

    objWordChange.Visible = False
    objWordorig.Visible = False

    Set objDocChange = objWordChange.Documents.Open(strfilename1)
    Set objSelectionChange = objWordChange.Selection
    Set objDocOrig = objWordorig.Documents.Open(strfilename3)
    Set objSelectionOrig = objWordorig.Selection

    Dim rSearch As Range
    Dim dict As Scripting.Dictionary
    Dim i As Long

    'Set up the documents - you already have this part


    'We'll store the sentences here
    Set dict = New Scripting.Dictionary

    Set rSearch = objDocChange.Range
    With rSearch
        .Find.Forward = True
        .Find.Format = True
        .Find.Font.Color = wdColorBlue
        .Find.Execute

        Do While .Find.Found
        Dim strg1
        Dim strg2
        strg1 = rSearch.Sentences(1).Text
        MsgBox strg1
            'key = revised sentence, item = original sentence
            'if the revised sentence already exists in the dictionary, replace the found word in the entry
            If dict.Exists(.Sentences(1).Text) Then
                dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), Space(2), Space(1))
            Else
            'if the revised sentence isn't in the dict, then this is the first found word, so add it and replace the word
                dict.Add .Sentences(1).Text, Replace$(Replace$(.Sentences(1).Text, .Text, vbNullString), Space(2), Space(1))
            End If

            .Find.Execute
        Loop
    End With

    'Loop through all the dictionary entries and find the origial (item) and replace With
    'the revised (key)
    For i = 1 To dict.Count
        Set rSearch = objDocOrig.Range
        With rSearch.Find
            .MatchWholeWord = False
            .MatchCase = False
            .MatchPhrase = True
            .IgnoreSpace = True
            .IgnorePunct = True
            .Wrap = wdFindContinue
            .Text = dict.Items(i - 1)
            .Replacement.Text = dict.Keys(i - 1)
            .Execute Replace:=wdReplaceOne
        End With
    Next i

objDocChange.Close
objDocOrig.Save
objDocOrig.Close

objWordChange.Quit
objWordorig.Quit

End Sub

回答1:


This uses a Scripting.Dictionary - set a reference using Tools - References to Microsoft Scripting Runtime.

It saves the sentence of each found entry as an entry to the dictionary. It only saves each sentence once. When it finds the second word, it replaces that word within what's already in the dictionary.

Sub MergeRevision()

    Dim dcOrig As Document
    Dim dcRev As Document
    Dim dcNew As Document
    Dim rSearch As Range
    Dim dict As Scripting.Dictionary
    Dim i As Long

    'Set up the documents - you already have this part
    Set dcOrig = Documents("Document1.docm")
    Set dcRev = Documents("Document2.docx")
    Set dcNew = Documents("Document3.docx")
    dcOrig.Content.Copy
    dcNew.Content.Paste

    'We'll store the sentences here
    Set dict = New Scripting.Dictionary

    Set rSearch = dcRev.Range
    With rSearch
        .Find.Forward = True
        .Find.Format = True
        .Find.Font.Color = wdColorBlue
        .Find.Execute

        Do While .Find.Found
            'key = revised sentence, item = original sentence
            'if the revised sentence already exists in the dictionary, replace the found word in the entry
            If dict.Exists(.Sentences(1).Text) Then
                dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), Space(2), Space(1))
            Else
            'if the revised sentence isn't in the dict, then this is the first found word, so add it and replace the word
                dict.Add .Sentences(1).Text, Replace$(Replace$(.Sentences(1).Text, .Text, vbNullString), Space(2), Space(1))
            End If

            .Find.Execute
        Loop
    End With

    'Loop through all the dictionary entries and find the origial (item) and replace With
    'the revised (key)
    For i = 1 To dict.Count
        Set rSearch = dcNew.Range
        With rSearch.Find
            .MatchWholeWord = False
            .MatchCase = False
            .MatchPhrase = True
            .IgnoreSpace = True
            .IgnorePunct = True
            .Wrap = wdFindContinue
            .Text = dict.Items(i - 1)
            .Replacement.Text = dict.Keys(i - 1)
            .Execute Replace:=wdReplaceOne
        End With
    Next i

End Sub



回答2:


Change your .Execute line to

Debug.Assert .Execute(Replace:=wdReplaceOne)

Execute returns False if it's unsuccessful and Debug.Assert stops the code when it's False. When it stops, go to the immediate window and type the debug.print (?) statements below (the answers I got are shown)

?.Text
The word Automation tool, will hopefully work . 
?.Replacement.Text
The word Automation cool tool, will hopefully work now. 
?rsearch.Text
This is a test. The word Automation tool, will hopefully work. This is not a test. Need a new sentence here now for the word Automation tool, hopefully this works.

The problem is that it can't find .Text because of the <space><period> at the end. We're deleting double spaces, but that doesn't work when the blue text is at the end of the sentence. You need to replace SpaceSpace, SpacePeriod, and SpaceComma, at least. Who knows what other strange punctuation you might encounter.

Once you get things working, you can get rid of the Debug.Assert. But you may want to throw an error when .Execute returns False so the user is aware it didn't copy correctly.

The reason I was getting those "processing" errors was because I was using FileCopy on a macro-enabled document and copying with a .docx extension. So my bad.



来源:https://stackoverflow.com/questions/32619642/adding-multiple-words-to-a-word-document-in-a-sentence-using-an-array-with-vba

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!