'Im catching keywords (string) from an excel file and searching for them in a word doc. When found the string in the doc file is replaced with a specific content from an offset cell.This works for me .Some of the cells have multiple texts separated with semicolon ";".Each text must replace an occurrence of the found keyword in the doc file: for example if a cell contains 3 strings separated with a semicolon ,the first string should replace the first occurrence of the keyword in the doc file,the second one the second occurrence and the third one the third occurrence. I couldn't get a correct result. Below is the code:
Option Explicit
Public Sub copy_file(source, destination)
Dim FsyObjekt As Object
Set FsyObjekt = CreateObject("Scripting.FileSystemObject")
FsyObjekt.CopyFile source, destination
End Sub
Public Sub WordFindAndReplace(Index_offset, ProdType)
Dim ws As Worksheet, msWord As Object, itm As Range
Dim spl() As String, NbLines, Index, Occurences As Integer
Set ws = ActiveSheet
Set msWord = CreateObject("Word.Application")
Index = 0
With msWord
.Visible = True
.Documents.Open Filename:=ThisWorkbook.Path & "\Template.docx"
.Activate
With .ActiveDocument.Content.Find
.ClearFormatting
.Replacement.ClearFormatting
For Each itm In ws.Range("A6:A221")
.Text = itm.Text
If IsEmpty(itm.Offset(, Index_offset)) Then
.Replacement.Text = " "
Else
If InStr(1, itm.Offset(, Index_offset), ";", 1) > 0 Then
.Forward = True
.Wrap = wdFindContinue
.Format = False
.Execute Replace:=wdReplaceOne
spl = Split((itm.Offset(, Index_offset)), ";")
NbLines = UBound(spl) - LBound(spl) + 1
Index = 0
If Index <> NbLines - 1 Then
.Replacement.Text = spl(Index)
Index = Index + 1
End If
Else
.Replacement.Text = itm.Offset(, Index_offset).Text
.Execute Replace:=wdReplaceAll
End If
End If
.MatchCase = False
.MatchWholeWord = False
.Replacement.Highlight = False
Next itm
End With
.Quit SaveChanges:=True
End With
End Sub
I hope someone could help me to solve the problem.
The parameter you pass in 'ProdType' isn't used in the code you have published.
I've updated the code you published and it compiles, but obviously I can't run it because I don't have your worksheet and documents.
But it will help point you in the right direction
A key thing to note is how the search and replace operations have been split out from your main loop. This make the code much easier to follow.
Good luck with your endeavors.
Public Sub WordFindAndReplace(Index_Offset As Long, ProdType As String) ' ProdType is not used in the code you published
Const blankString As String = " " ' might bebetter using vbnullstring instead of " "
Dim ws As Excel.Worksheet ' Requires that Tools.References.Microsoft Excel X.XX Object Library is ticked
Dim msWord As Word.Application ' Requires that Tools.References.Microsoft Word X.XX Object Library is ticked
Dim spl() As String ' changed back to string as we can also iterate over a string array
Dim mySpl As Variant ' the variable in a for each has to be an object or variant
Dim myIndex As Long ' Was implicitly declared as Variant
Dim myDoc As Word.Document ' Better to get a specific reference to a document rather than use activedocument
Dim myOffsetString As String
Dim myFindString As String '
Dim myCells() As Variant
Dim myOffsetCells As Variant
Dim myOffsetRange As Variant
Set ws = ActiveSheet
Set msWord = New Word.Application ' changed from late to early binding as early binding gives intelisense for word objects
'Index = 0 not needed any more
With msWord
.Visible = True ' Not necessary if you just want to process some actions on a document but helpful when developing
Set myDoc = .Documents.Open(FileName:=ThisWorkbook.Path & "\Template.docx") 'changed to function form due to assignment to myDoc
'.Activate ' Not needed when working with a direct reference to a document
End With
' Bring the cells in the target column and the offset column into vba arrays
' an idiosyncracy when pullin in a column is we get a two dimensional array
myCells = ws.Range("A6:A221").Value2
myOffsetRange = Replace("A6:A221", "A", Chr$(Asc("A") + Index_Offset))
myOffsetCells = ws.Range(myOffsetRange).Value2
' As we are using two arrays we can't now do for each so back to using an index
' Another idiosyncracy is that the arrays start at 1 and not 0
For myIndex = 1 To UBound(myCells)
myOffsetString = CStr(myOffsetCells(myIndex, 1))
myFindString = CStr(myCells(myIndex, 1))
If Len(myOffsetString) = 0 Then 'quicker than comparing against vbnullstring
replaceText_ReplaceAll myDoc, myFindString, blankString
Else
' The offset cell contains a string (because it is not empty)
' It doesn't matter if there is no ';' in the string
' split will just produce an array with one cell
spl = Split(myOffsetString, ";")
If UBound(spl) = 0 Then
' Only one item present
replaceText_ReplaceAll myDoc, myFindString, Trim(CStr(mySpl))
Else
' more than one item present
For Each mySpl In spl
replaceText_ReplaceSingleInstance myDoc, myFindString, Trim(CStr(mySpl))
Next
' now replace any excess ocurrences of myFIndString
replaceText_ReplaceAll myDoc, myFindString, blankString
End If
End If
Next
myDoc.Close savechanges:=True
msWord.Quit
Set msWord = Nothing
End Sub
Sub replaceText_ReplaceAll(this_document As Word.Document, findText As String, replaceText As String)
With this_document.StoryRanges(wdMainTextStory).Find
.ClearFormatting
.Format = False
.Wrap = wdFindStop
.Text = findText
.Replacement.Text = replaceText
.Forward = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
End Sub
Sub replaceText_ReplaceSingleInstance(this_document As Word.Document, findText As String, replaceText As String)
With this_document.StoryRanges(wdMainTextStory).Find
.ClearFormatting
.Format = False
.Wrap = wdFindContinue
.Text = findText
.Replacement.Text = replaceText
.Forward = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
End Sub
Edited to update the WordFIndAndReplace sub
Related
I´m trying to find and replace multiple sentences from different word files from an specific folder. The words that I´m trying to change are on two columns in excel (Columns B and C)
The changes are been done correctly, but for some reason the words are not erased completly and the change happens twice. This is due to the trackchanges that needs to be activated due to the requirements of this automation.
Right now it does the first change, but then the word appears as if it wasn´t changed, so it does the change again with the new word.
This is the code:
Dim Wbk As Workbook: Set Wbk = ThisWorkbook
Dim Wrd As New Word.Application
Dim Dict As Object
Dim RefList As Range, RefElem As Range
Dim Key
Dim wrdRng As Range
Dim WDoc As Document
Wrd.Visible = True
Set WDoc = Wrd.Documents.Open(filename:=sFileName, OpenAndRepair:=True) 'Modify as necessary.
Debug.Print sFileName
'Assigns the columns that is going to have the original texts that need to be changed
Set Dict = CreateObject("Scripting.Dictionary")
Set RefList = Wbk.Sheets("Reemplazos").Range("B2:B50") 'Modify as necessary.
'Selects the column that´s one column to the right of the reference column
With Dict
For Each RefElem In RefList
If Not .Exists(RefElem) And Not IsEmpty(RefElem) Then
.Add RefElem.Value, RefElem.Offset(0, 1).Value
Debug.Print RefElem
End If
Next RefElem
End With
' Activar control de cambios en cada documento
With WDoc:
.TrackRevisions = True
WDoc.ActiveWindow.View.MarkupMode = wdBalloonRevisions
End With
'Assigns the conditions and loops through each text to replace it
For Each Key In Dict
With WDoc.Content.FIND
Application.ScreenUpdating = False
Debug.Print Key
.ClearFormatting
.Replacement.ClearFormatting
.Text = Key
.Font.Color = vbBlack
.Replacement.Text = Dict(Key)
.MatchAllWordForms = False
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWildcards = False
.MatchSoundsLike = False
.Execute Replace:=2
End With
Next Key
'Saves, Closes and quits the words.
WDoc.SaveAs NewNewWordName(sFileName)
WDoc.Close
Wrd.Quit
I though about getting a requirement of only changing the words when they are on the color black, because the trackchanges leaves the sentence with a color red. But I do not know how to do it.
In cases like this, you need to use something other than Replace for the replacement. For example:
Sub Demo()
Application.ScreenUpdating = False
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "AFC admin"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = True
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Do While .Find.Execute
With .Duplicate
If .Words.Last.Next = "(" Then
.MoveEndUntil ")", wdForward
.End = .End + 1
If Split(.Text, " ")(2) = "(ORG)" Then .Text = "REVISE"
Else
.Text = "DEBUG"
End If
End With
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
End Sub
Alternatively, you might do Find/Replace as:
AFC admin ----- DEBUG
then
DEBUG (ORG) ----- REVISE
I found a solution to this problem:
Dim Wbk As Workbook: Set Wbk = ThisWorkbook
Dim Wrd As New Word.Application
Dim Dict As Object
Dim RefList As Range, RefElem As Range
Dim Key
Dim wrdRng As Range
Dim WDoc As Document
Dim intParaCount
Dim objParagraph
Dim Wordd As Object
Wrd.Visible = True
Set WDoc = Wrd.Documents.Open(filename:=sFileName, OpenAndRepair:=True) 'Modify as necessary.
With WDoc:
.TrackRevisions = True
WDoc.ActiveWindow.View.MarkupMode = wdBalloonRevisions
End With
Set Dict = CreateObject("Scripting.Dictionary")
Set RefList = Wbk.Sheets("Reemplazos").Range("B2:B50") 'Modify as necessary.
With Dict
For Each RefElem In RefList
If Not .Exists(RefElem) And Not IsEmpty(RefElem) Then
.Add RefElem.Value, RefElem.Offset(0, 1).Value
''Debug.Print RefElem
End If
Next RefElem
End With
For Each Key In Dict
With WDoc.Content.FIND
Debug.Print Key
.Execute MatchAllWordForms:=False
.Execute Forward:=True
.Execute Wrap:=wdFindAsk
.Execute Format:=False
.Execute MatchCase:=False
.Execute MatchWildcards:=False
.Execute MatchSoundsLike:=False
.Execute wdReplaceAll
.Font.Color = wdColorAutomatic
.Execute FindText:=Key, ReplaceWith:=Dict(Key), Replace:=2
End With
Set objParagraph = WDoc.Content
objParagraph.FIND.Text = Key
Debug.Print Key
Do
objParagraph.FIND.Execute
If objParagraph.FIND.Found Then
objParagraph.Font.Color = RGB(0, 0, 1)
End If
Loop While objParagraph.FIND.Found
Next Key
WDoc.SaveAs NewNewWordName(sFileName)
WDoc.Close
Wrd.Quit
What this process does is change the color of each word once is changed.
I have assigned a color condition so that it only changes words with the color automatic:
.Font.Color = wdColorAutomatic
Once is changed, the word inside track changes are changed to another color, very similar but that are different:
objParagraph.Font.Color = RGB(0, 0, 1)
This way it only changes each word once. The only problem with this solution is that you need to assign all the words to the automatic color or the color you decide to give it.
I hope this helps anyone that found this or a similar problem.
FYI this code works for people that need to change multiple words that appear in columns in excel. I found lots of people with this problem. So check the code and it might help you.
This is my first post here and I'm very, very new to vba.
I have an Excel worksheet that I am using to assist in drafting several Word documents. I would like to program a command in Excel that if a specific cell has a specific value, it will delete a particular paragraph in a Word document. Specifically, I want to do something like the following:
if activesheet.range("I99")="1" then
'code to delete specific paragraph in Word document
elseif activesheet.range("I99")="2" then
'code to delete different paragraph in Word document
elseif activesheet.range("I99")="3" then
'code to delete different paragraph in Word document
end if
The following generic code (which I found on this site) in Word does what I want it to do in Word, but I can't get it to work in Excel:
Sub SomeSub()
Dim StartWord As String, EndWord As String
Dim Find1stRange As Range, FindEndRange As Range
Dim DelRange As Range, DelStartRange As Range, DelEndRange As Range
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Setting up the Ranges
Set Find1stRange = ActiveDocument.Range
Set FindEndRange = ActiveDocument.Range
Set DelRange = ActiveDocument.Range
'Set your Start and End Find words here to cleanup the script
StartWord = "From: Research.TA#traditionanalytics.com|Tradition Analytics Commentary| | |"
EndWord = "This message has been scanned for malware by Websense. www.websense.com"
'Starting the Find First Word
With Find1stRange.Find
.Text = StartWord
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindAsk
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
'Execute the Find
Do While .Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelStartRange
Set DelStartRange = Find1stRange
'Having these Selections during testing is benificial to test your script
DelStartRange.Select
'Setting the FindEndRange up for the remainder of the document form the end of the StartWord
FindEndRange.Start = DelStartRange.End
FindEndRange.End = ActiveDocument.Content.End
'Having these Selections during testing is benificial to test your script
FindEndRange.Select
'Setting the Find to look for the End Word
With FindEndRange.Find
.Text = EndWord
.Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelEndRange
Set DelEndRange = FindEndRange
'Having these Selections during testing is benificial to test your script
DelEndRange.Select
End If
End With
'Selecting the delete range
DelRange.Start = DelStartRange.Start
DelRange.End = DelEndRange.End
'Having these Selections during testing is benificial to test your script
DelRange.Select
'Remove comment to actually delete
DelRange.Delete
End If 'Ending the If Find1stRange .Found = True
Loop 'Ending the Do While .Execute Loop
End With 'Ending the Find1stRange.Find With Statement
End Sub
I want to do it this way so that I can edit my Word document without having to edit the vba code. Any help would be greatly appreciated!
Mark
Set a reference to Word (early binding) (check this article)
Read the code's comments and adjust it to fit your needs
' Set a reference to Word Library
Public Sub DeleteInWord()
' Set reference to worksheet
Dim sourceSheet As Worksheet
Set sourceSheet = ThisWorkbook.Worksheets("MySheetName")
' Define word document path
Dim wordDocPath As String
wordDocPath = "C:\Temp"
' Define word document name (include extension)
Dim wordDocName As String
wordDocName = "test.docx"
' Define start word to find in word document
Dim startWord As String
' Define end word to find in word document
Dim endWord As String
' Select the case when value in range I99 is X
Select Case sourceSheet.Range("I99").Value
Case 1
'code to delete specific paragraph in Word document
startWord = "StartWordValue1"
endWord = "EndWordValue1"
Case 2
'code to delete different paragraph in Word document
startWord = "StartWordValue2"
endWord = "EndWordValue2"
Case 3
'code to delete different paragraph in Word document
startWord = "StartWordValue3"
endWord = "EndWordValue3"
End Select
' Call delete paragraph procedure
delParagrInWordByStartEndWord wordDocPath, wordDocName, startWord, endWord
End Sub
Private Sub delParagrInWordByStartEndWord(ByVal wordDocPath As String, ByVal wordDocName As String, ByVal startWord As String, ByVal endWord As String)
' Turn off stuff
Application.ScreenUpdating = False
Application.DisplayAlerts = False
' Set a reference to word
Dim wordApp As Word.Application
Set wordApp = createWordObject(True)
' Fix document path if missing last \
If Right(wordDocPath, 1) <> "\" Then wordDocPath = wordDocPath & "\"
' Build document full path
Dim wordDocFullPath As String
wordDocFullPath = wordDocPath & wordDocName
' Open word document
Dim wordDoc As Word.Document
If Not wordFileIsOpen(wordDocFullPath) Then
Set wordDoc = wordApp.Documents.Open(wordDocFullPath)
Else
Set wordDoc = wordApp.Documents(wordDocName)
End If
'Setting up the Ranges
Dim find1stRange As Word.Range
Set find1stRange = wordDoc.Range
Dim findEndRange As Word.Range
Set findEndRange = wordDoc.Range
Dim delRange As Word.Range
Set delRange = wordDoc.Range
'Starting the Find First Word
With find1stRange.find
.Text = startWord
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindAsk
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
'Execute the Find
Do While .Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelStartRange
Dim delStartRange As Word.Range
Set delStartRange = find1stRange
'Having these Selections during testing is benificial to test your script
delStartRange.Select
'Setting the FindEndRange up for the remainder of the document form the end of the StartWord
findEndRange.Start = delStartRange.End
findEndRange.End = wordDoc.Content.End
'Having these Selections during testing is benificial to test your script
findEndRange.Select
'Setting the Find to look for the End Word
With findEndRange.find
.Text = endWord
.Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelEndRange
Dim delEndRange As Word.Range
Set delEndRange = findEndRange
'Having these Selections during testing is benificial to test your script
delEndRange.Select
End If
End With
'Selecting the delete range
delRange.Start = delStartRange.Start
delRange.End = delEndRange.End
'Having these Selections during testing is benificial to test your script
delRange.Select
'Remove comment to actually delete
delRange.Delete
End If 'Ending the If Find1stRange .Found = True
Loop 'Ending the Do While .Execute Loop
End With 'Ending the Find1stRange.Find With Statement
End Sub
' Credits: https://stackoverflow.com/a/47162311/1521579
Private Function createWordObject(Optional bVisible As Boolean = True) As Object
Dim tempWordObject As Object
On Error Resume Next
Set tempWordObject = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Err.Clear
On Error GoTo CleanFail
Set tempWordObject = CreateObject("Word.Application")
End If
tempWordObject.Visible = bVisible
Set createWordObject = tempWordObject
On Error GoTo 0
Exit Function
CleanFail:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure CreateWord."
Err.Clear
End Select
End Function
' Credits: https://stackoverflow.com/a/54040283/1521579
Private Function wordFileIsOpen(wordDocFullPath As String) As Boolean
Dim ff As Long
On Error Resume Next
ff = FreeFile()
Open wordDocFullPath For Input Lock Read As #ff
Close ff
wordFileIsOpen = (Err.Number <> 0)
On Error GoTo 0
End Function
I am trying to excecute a VBA macro from excel to remove a row in a word document if a string is present.
For i = startItem To endItem
Dim msWord As Object
Set msWord = CreateObject("Word.Application")
With msWord
.Visible = TRUE
.Documents.Open getSetting("PTC TEMPLATE") 'path of the template in msword format
.Activate
'Remove TEST ROW
'LOOP TEST TO REMOVE
Dim DirArray As Variant
DirArray = ThisWorkbook.Sheets("valveList").ListObjects("valveList").HeaderRowRange.value
For Each element In DirArray
If element Like "*TEST*" Then
Debug.Print element & "--> " & Range("valveList[" & element & "]")(i).value
If Range("valveList[" & element & "]")(i).value = "NO" Then
.ActiveDocument.Select
With .Selection.Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = Range("valveList[" & element & "]")(i).value 'Find all strings in col A
.Forward = TRUE
.Wrap = wdFindStop
.MatchCase = FALSE
.MatchWholeWord = FALSE
.Execute
If .Found = TRUE Then
.Selection.Rows.Delete
End If
End With
End If
End If
Next element
'End REMOVE TEST ROW
Here I have the problem that I dont know how to refer to the found string and delete the row of the table the string belongs to.
I'm not very familiar with VBA, if someone can revise my code and explain how to solve this problem I'll be thankful
There are numerous problems with your code, including repeatedly starting Word and opening a new copy of the document you're modifying, employing Word constants with late binding, and the use of unqualified Range references. Try something along the lines of:
Sub Demo()
Dim msWord As Object, wdDoc As Object, xlSht As Worksheet, DirArray As Variant
Set xlSht = ThisWorkbook.Sheets("valveList")
DirArray = xlSht.ListObjects("valveList").HeaderRowRange.Value
Set msWord = CreateObject("Word.Application")
With msWord
.Visible = True
.ScreenUpdating = False
Set wdDoc = .Documents.Open(GetSetting("PTC TEMPLATE")) 'path of the template in msword format
For i = startItem To endItem
For Each element In DirArray
If element Like "*TEST*" Then
If xlSht.Range("valveList[" & element & "]")(i).Value = "NO" Then
With wdDoc.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = xlSht.Range("valveList[" & element & "]")(i).Text 'Find all strings in col A
.Forward = True
.Wrap = 0 'wdFindStop
.MatchCase = False
.MatchWholeWord = False
End With
Do While .Find.Execute
If .Information(12) = True Then 'wdWithInTable
.Rows(1).Delete
End If
.Collapse 0 'wdCollapseEnd
Loop
End With
End If
End If
Next element
Next i
.ScreenUpdating = True
End With
End Sub
Elegant code and code readability question
This is my code and it works fine.
There is a contract number and the date in the beginning of the Word documents I need to process, which I need to extract and write into respective cells in a spreadsheet.
My question refers to the parts of the code where one with/end with statement is wrapped in another with/end with statement. 3rd and 4th paragraph in the code, where I'm looking for the wildcards expressions.
Sub ExtractRepertorNmbrUsingWildcards()
Application.ScreenUpdating = False
Dim wordApp As Word.Application
Dim wordDoc As Word.Document
Dim excelApp As Excel.Application
Dim rng As Word.Range
Dim kompar As Word.Range
Dim ws As Worksheet
Dim regEx As Object
Dim matches As Collection
Dim match As Variant
Dim repNmbr As String
Dim cesja As Range
Dim startPos As Long
Dim endPos As Long
'Assigning object variables
Set wordApp = GetObject(, "Word.Application")
Set excelApp = GetObject(, "Excel.Application")
Set wordDoc = wordApp.ActiveDocument
Set ws = excelApp.ActiveSheet
Set rng = wordApp.ActiveDocument.Content
Set matches = New Collection
Set cesja = ActiveSheet.Range("A10:J50").Find("cesja /", , xlValues)
Debug.Print cesja.Address
With wordApp.ActiveDocument.Range
With .Find
.Text = "<[0-9 ]{1;7}/[0-9]{4}>" 'contract number
.MatchWildcards = True
.Wrap = wdFindStop
.Forward = True
.Execute
End With
If .Find.Found = True Then matches.Add Replace(.Text, " ", "") 'macro is adding it to the collection
Debug.Print "# of items is"; matches.Count
End With
With wordApp.ActiveDocument.Range
With .Find
.Text = "<[0-9]{2}.[0-9]{2}.[0-9]{4}r." 'date
.MatchWildcards = True
.Wrap = wdFindStop
.Forward = True
.Execute
End With
If .Find.Found = True Then matches.Add .Text 'macro is adding it to the same collection as above on the next free record
Debug.Print "# of items is"; matches.Count
End With
For Each match In matches
Debug.Print match
Next match
What I don't understand is why in this part of the code (and next code paragraph as well):
With wordApp.ActiveDocument.Range
With .Find
.Text = "<[0-9 ]{1;7}/[0-9]{4}>" 'contract number
.MatchWildcards = True
.Wrap = wdFindStop
.Forward = True
.Execute
End With
If .Find.Found = True Then matches.Add Replace(.Text, " ", "")
Debug.Print "# of items is"; matches.Count
End With
one with/end with statement, is wrapped in another one.
How should this part of the code be written, to avoid this unnecessary wrapping / double with/end with statement. I'm asking how a pro coder would written it?
Please correct this code, to make it efficient, good looking, readable and short.
I have an excel sheet with two columns of strings. I track the changes of these two columns using ms-word and copy the result back to a third column. Then I copy the third column to a new word document.
The formating in Excel in Cell C3 is what I would like to transfer to word.
This is what I get at the moment. Notice the complete strike-through.
Why does it work twice but not in the third case?
I guess the root of the problem is that I remove the CR/Linefeed in the word to excel step and destroy the boundary of the strike-through-format. My goal is to get each string in one word-paragraph. If I don't remove the CR/Linefeed i get four paragraphs.
Background: In the final application the strings are going to be paragraphs of text.
Sourcecode of the excel-vba-macro (Excel 2010):
Technical remark: You may need to activate the ms-word-objects in excel-vba. (Microsoft Word 14.0 Object Library )
The macro assumes, that there a strings in the Range(A1:B3):
for example
a string a string, too
a string a new string
a string there is no try
The results will be put in the Range(C1:C3).
Option Explicit
Dim numberOfBlocks As Long
Sub main()
Dim i As Long
Dim tSht As Worksheet
Dim wordapp As Word.Application
Dim wdoc As Word.Document
Set tSht = ThisWorkbook.ActiveSheet
numberOfBlocks = 3
Application.ScreenUpdating = False
Set wordapp = CreateObject("Word.Application")
For i = 1 To numberOfBlocks
Call trackChanges(i, wordapp, tSht)
Next i
Set wdoc = wordapp.Documents.Add
Call copyChanges(tSht, wdoc)
End Sub
Sub trackChanges(i As Long, wordapp As Word.Application, tSht As Worksheet)
Dim diffDoc As Word.Document
Dim textString() As Variant
Dim j As Long
ReDim doc(2)
ReDim textString(2)
Set textString(1) = tSht.Range("A" & i)
Set textString(2) = tSht.Range("B" & i)
For j = 1 To 2
With wordapp
Set doc(j) = .Documents.Add
textString(j).Copy
doc(j).Paragraphs(1).Range.PasteSpecial
End With
Next j
wordapp.CompareDocuments OriginalDocument:=doc(1), RevisedDocument:=doc(2), _
Destination:=wdCompareDestinationNew, Granularity:=wdGranularityCharLevel
For j = 1 To 2
doc(j).Close SaveChanges:=False
Next j
Set diffDoc = wordapp.ActiveDocument
wordapp.Visible = True
'if the answer has two paragraphs, get both in one paragraph
With diffDoc.Content.Find
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.Text = vbCrLf
.Replacement.Text = " "
.Execute Replace:=wdReplaceAll
End With
diffDoc.Range.Copy
tSht.Range("C" & i).Select
tSht.PasteSpecial Format:="HTML"
With tSht.Range("C" & i)
.WrapText = True
.Font.Name = textString(2).Font.Name
.Font.Bold = textString(2).Font.Bold
.Font.Size = textString(2).Font.Size
.Rows.AutoFit
.Interior.Color = textString(2).Interior.Color
End With
diffDoc.Close SaveChanges:=False
Application.CutCopyMode = False
Set diffDoc = Nothing
End Sub
Sub copyChanges(tSht As Worksheet, wdoc As Word.Document)
tSht.Range("C1:C" & numberOfBlocks).Copy
wdoc.Range(wdoc.Range.End - 1, wdoc.Range.End).PasteSpecial Placement:=wdInLine, DataType:=wdPasteHTML
wdoc.Tables(1).ConvertToText Separator:=wdSeparateByParagraphs
End Sub