I have this VBA code that takes two documents (one original document and one revision document with blue text to be added) and creates a third document with the revisions.It mostly works, but when the third copy is created, there is extra space after apostrophes. It isn't actually an extra space though. Upon selecting the "Hidden Formatting" button in Word, it shows that there isn't actually a space at all. The character is just being displayed on the monitor incorrectly. I have tried a few things such as changing the font during the file creation and using the REPLACE function to no avail. This is not an isolated incident, I found this documentation on the problem, unfortunately it does not pertain to VBA. Looking for some ideas on how to fix the problem.
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
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
'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
'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))
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " ,", ",")
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " .", ".")
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " '", "'")
For Each Key In dict
Debug.Print "KEY: " & Key
Debug.Print "Item: " & Item
Next
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))
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " ,", ",")
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " .", ".")
dict.Item(.Sentences(1).Text) = Replace$(Replace$(dict.Item(.Sentences(1).Text), .Text, vbNullString), " '", "'")
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
With objDocOrig.Range
.Font.Name = "Calibri"
End With
Next i
objDocChange.Close
objDocOrig.Save
objDocOrig.Close
objWordChange.Quit
objWordorig.Quit
End Sub
If you need / want to test my code, you will have to create two word documents. Each document will need a common sentence containing an apostrophe (obviously). The second document would require a few blue words in addition to the original sentence in RGB 0,0,225.
Found an answer to my own question. I had to disable the "Asian Text Font" in the Font Pane. This can be done by going into the Microsoft Language Register and disabling various languages. Source
Related
I have two documents in different languages (same number and format of paragraphs). I would like to create a third document from the 2 with the paragraphs alternating one after the other (to learn foreign language). The documents also have tables. I have tried using the code below, which I got from here (Copy/paste subsequent paragraphs from two Word documents one after another (to learn a foreign language)), but it fails on tables with the Run-time error '5251': This is not a valid action for the end of a row.
How can I make it run through the tables as well, alternating the paragraphs?
Sub AddSecondLanguage()
Application.ScreenUpdating = False
Dim DocA As Document, DocB As Document, Rng As Range, i As Long
With Application.FileDialog(FileDialogType:=msoFileDialogFilePicker)
.Title = "Select the source document containing the primary language."
.InitialFileName = "C:\Users\" & Environ("Username") & "\Documents\"
.AllowMultiSelect = False
If .Show = -1 Then
Set DocA = Documents.Open(.SelectedItems(1), ReadOnly:=True, AddToRecentFiles:=False)
Else
MsgBox "No primary language file selected. Exiting.", vbExclamation: Exit Sub
End If
End With
With Application.FileDialog(FileDialogType:=msoFileDialogFilePicker)
.Title = "Select the source document containing the secondary language."
.InitialFileName = DocA.Path & "\"
.AllowMultiSelect = False
If .Show = -1 Then
Set DocB = Documents.Open(.SelectedItems(1), ReadOnly:=False, AddToRecentFiles:=True)
Else
MsgBox "No secondary language file selected. Exiting.", vbExclamation
DocA.Close SaveChanges:=False: Set DocA = Nothing: Exit Sub
End If
End With
With DocB
For i = .Paragraphs.Count To 1 Step -1
Set Rng = .Paragraphs(i).Range
Rng.Collapse wdCollapseStart
Rng.FormattedText = DocA.Paragraphs(i).Range.FormattedText
Next
.SaveAs2 FileName:=Split(DocA.FullName, ".doc")(0) & "-Combined.docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
End With
DocA.Close SaveChanges:=False
Set DocA = Nothing: Set DocB = Nothing
Application.ScreenUpdating = True
End Sub
Try changing:
Dim DocA As Document, DocB As Document, Rng As Range, i As Long
to:
Dim DocA As Document, DocB As Document, RngSrc As Range, RngTgt As Range, i As Long
and changing:
For i = .Paragraphs.Count To 1 Step -1
Set Rng = .Paragraphs(i).Range
Rng.Collapse wdCollapseStart
Rng.FormattedText = DocA.Paragraphs(i).Range.FormattedText
Next
to:
For i = .Paragraphs.Count To 1 Step -1
Set RngTgt = .Paragraphs(i).Range
RngTgt.Collapse wdCollapseStart
Set RngSrc = DocA.Paragraphs(i).Range
If RngSrc.Information(wdWithInTable) = True Then
If RngSrc.End <> RngSrc.Rows(1).Range.End Then
If RngSrc.End = RngSrc.Cells(1).Range.End Then
RngSrc.InsertAfter vbCr: RngSrc.End = RngSrc.End - 1
End If
Else
RngTgt.FormattedText = RngSrc.FormattedText
End If
Next
I am using a Find and Replace script/macro in MS Word. For the two lines below, how would I adjust this to be case sensitive? Right now it will replace us, bus, ect..
Const strFind As String = "US"
Const strRepl As String = "USA"
Sub BatchProcess()
Dim strFileName As String
Dim strPath As String
Dim oDoc As Document
Dim fDialog As FileDialog
Dim oStory As Range
Dim oRng As Range
Const strFind As String = "2017"
Const strRepl As String = "2018"
Set fDialog = Application.FileDialog(msoFileDialogFolderPicker)
With fDialog
.Title = "Select folder and click OK"
.AllowMultiSelect = False
.InitialView = msoFileDialogViewList
If .Show <> -1 Then
MsgBox "Cancelled By User", , _
"List Folder Contents"
Exit Sub
End If
strPath = fDialog.SelectedItems.Item(1) & "\"
End With
strFileName = Dir$(strPath & "*.docx")
While Len(strFileName) <> 0
WordBasic.DisableAutoMacros 1
Set oDoc = Documents.Open(strPath & strFileName)
For Each oStory In ActiveDocument.StoryRanges
Set oRng = oStory
With oRng.Find
Do While .Execute(FindText:=strFind)
oRng.Text = strRepl
oRng.Collapse wdCollapseEnd
Loop
End With
If oStory.StoryType <> wdMainTextStory Then
While Not (oStory.NextStoryRange Is Nothing)
Set oStory = oStory.NextStoryRange
Set oRng = oStory
With oRng.Find
Do While .Execute(FindText:=strFind)
oRng.Text = strRepl
oRng.Collapse wdCollapseEnd
Loop
End With
Wend
End If
Next oStory
oDoc.SaveAs FileName:=strPath & strFileName
oDoc.Close SaveChanges:=wdDoNotSaveChanges
strFileName = Dir$()
WordBasic.DisableAutoMacros 0
Wend
Set oDoc = Nothing
Set oStory = Nothing
Set oRng = Nothing
End Sub
In response to the post below. I have added the entire code.
The Find and Replace method has a boolean MatchCase property. Set it to True.
Example: In your DoWhile code. Do While .Execute(FindText:=strFind, MatchCase:=True)
Simply matching the case is insufficient if what you're searching for as a whole word might also exist within a larger string. Try:
Sub BatchProcess()
Application.ScreenUpdating = False
Dim strFileName As String, strPath As String
Dim oDoc As Document, oStory As Range
Dim fDialog As FileDialog
Set fDialog = Application.FileDialog(msoFileDialogFolderPicker)
With fDialog
.Title = "Select folder and click OK"
.AllowMultiSelect = False
.InitialView = msoFileDialogViewList
If .Show <> -1 Then
MsgBox "Cancelled By User", , "List Folder Contents"
Exit Sub
End If
strPath = fDialog.SelectedItems.Item(1) & "\"
End With
strFileName = Dir$(strPath & "*.docx")
WordBasic.DisableAutoMacros 1
While Len(strFileName) <> 0
Set oDoc = Documents.Open(strPath & strFileName)
With oDoc
For Each oStory In .StoryRanges
While Not (oStory Is Nothing)
oStory.Find.Execute FindText:="<US>", Replacewith:="USA", Forward:=True, _
Wrap:=wdFindContinue, MatchWildcards:=True, Replace:=wdReplaceAll
Set oStory = oStory.NextStoryRange
Wend
Next oStory
.SaveAs FileName:=strPath & strFileName
.Close SaveChanges:=wdDoNotSaveChanges
End With
strFileName = Dir$()
Wend
WordBasic.DisableAutoMacros 0
Set oDoc = Nothing: Set oStory = Nothing
Application.ScreenUpdating = True
End Sub
Note that I've used wildcards, combined with as the Find expression. That guarantees only whole upper-case words will be matched. you could achieve the same with:
oStory.Find.Execute FindText:="US", Replacewith:="USA", Forward:=True, _
Wrap:=wdFindContinue, MatchWholeWord:=True, MatchCase:=True, Replace:=wdReplaceAll
Note, too, the overall simplification of your code.
Hopefully a quick one.
I through together a macro for splitting a word file (merged file of letters) into individual pdfs and naming them based on a ref number included in the file.
'Start split
For Each sec In ActiveDocument.Sections
Set rng = sec.Range 'Range of section
SecText = sec.Range.Text 'All text within section
SecTextPosition = InStr(SecText, "Our ref: ") 'Position of "Out ref: " within the section
strCDRS = Mid(SecText, (SecTextPosition + 9), 16) 'Retrieved CDRS reference
If sec.Index < ActiveDocument.Sections.Count Then
rng.MoveEnd wdCharacter, -1 'drop trailing section break
End If
rng.ExportAsFixedFormat strFolder & "\" & Replace(strCDRS, "/", "-") & "-" & strLetterType & ".pdf", wdExportFormatPDF
Set rng = Nothing
Next sec
This works perfectly when embedded in the word file. However, when embedding in the excel file and referencing the document, I get a type mismatch on the:
Set rng = sec.Range 'Range of section
Look at the value of sec.Range, it looks fine, so it appears to be something to do with the rng range object. Am I missing something obvious?
Full draft code as follows:
Sub SplitExport()
Dim sec As Section
Dim rng As Range
Dim strSplitFile As String
Dim strCDRS As String
Dim strLetterType As String
Dim strFolder As String
Dim SecText As String
Dim SecTextPosition As Long
Dim strfldr As FileDialog
Dim strfile As FileDialog
Dim WordFile As Word.Document
'Set word application
Set wordapp = CreateObject("word.Application")
'Pick file to split
Set strfile = Application.FileDialog(msoFileDialogFilePicker)
With strfile
.Title = "Select a file to split"
.AllowMultiSelect = False
.Show
strSplitFile = .SelectedItems(1)
End With
'Check if a file was selected
If strSplitFile = "" Then
MsgBox "Cannot proceed without file selection", vbOKOnly + vbCritical, "Error"
Exit Sub
End If
'Set Letter Type String
strLetterType = InputBox("Please enter letter code...")
If strLetterType = "" Then
MsgBox "Cannot proceed without letter code", vbOKOnly + vbCritical, "Error"
Exit Sub
End If
'Set folder to save PDFs to
Set strfldr = Application.FileDialog(msoFileDialogFolderPicker)
With strfldr
.Title = "Select a folder to save split files"
.AllowMultiSelect = False
.Show
strFolder = .SelectedItems(1)
End With
'Check a folder was selected
If strFolder = "" Then
MsgBox "Cannot proceed without folder selection", vbOKOnly + vbCritical, "Error"
Exit Sub
End If
'Open file to split
Set WordFile = wordapp.Documents.Open(strSplitFile)
WordFile.Activate
'Start split
For Each sec In ActiveDocument.Sections
Set rng = sec.Range 'Range of section
SecText = sec.Range.Text 'All text within section
SecTextPosition = InStr(SecText, "Our ref: ") 'Position of "Out ref: " within the section
strCDRS = Mid(SecText, (SecTextPosition + 9), 16) 'Retrieved reference
If sec.Index < ActiveDocument.Sections.Count Then
rng.MoveEnd wdCharacter, -1 'drop trailing section break
End If
rng.ExportAsFixedFormat strFolder & "\" & Replace(strCDRS, "/", "-") & "-" & strLetterType & ".pdf", wdExportFormatPDF
Set rng = Nothing
Next sec
End Sub
Apologies for wasting anyone's time reading this - I haven't changed the reference from section to Word.section, etc.
I will leave up as a testament to my muppetry.
I have about 700 different Word documents that need to be renamed based off a text string. The format of each of the words docs are exactly the same.
In the word doc, there is a string of text that says "Your establishment name 0001 - Reno, NV". Each of the 700 documents contain a different location name.
I need a VBA Macro that can scan each of these word docs to find that text string and then save the document according to whatever the location is. So in this instance, the document should be saved as: 0001 - Reno, NV.docx
My code so far is:
Sub Macro1()
Dim strFilename As String
Dim rngNum As Range
Dim fd As FileDialog
Dim strFolder As String
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
With fd
.Title = "Select the folder that contains the documents."
If .Show = -1 Then
strFolder = .SelectedItems(1) & "\"
Else
MsgBox "You did not select the folder that contains the documents."
Exit Sub
End If
End With
MkDir strFolder & "Processed"
strDoc = Dir$(strFolder & "*.docx")
While strDoc <> ""
Set Doc = Documents.Open(strFolder & strDoc)
With Doc
Selection.HomeKey wdStory
Selection.Find.ClearFormatting
With Selection.Find
Do While .Execute(FindText:="Your establishment name [0-9]{4}", MatchWildcards:=True, Forward:=True, Wrap:=wdFindStop) = True
With Selection
Set rngNum = .Range
strFilename = Right(.Range.Text, 4)
End With
Loop
End With
.SaveAs strFolder & "Processed\" & strFilename
End With
strDoc = Dir$()
Wend
End Sub
This code, at least in theory, has you select the folder in which all of the 700 docs exist and then creates a new folder named "Processed" where all of the new, renamed documents are then placed.
However, when I run the code, I receive this error:
Run time error '5152':
This is not a valid file name.
Try one or more of the following:
*Check the path to make sure it was typed correctly.
*Select a file from the list of files and folders.
I modified your code slightly while I was testing it to make it easier to read, wasn't exactly sure where your errors were coming from but the following code worked for me:
Sub Macro1()
Dim strFolder As String
Dim strDoc As String
Dim wordApp As Word.Application
Dim wordDoc As Word.document
Set wordApp = New Word.Application
wordApp.Visible = True
Dim fd As FileDialog
Set fd = Application.FileDialog(msoFileDialogFolderPicker)
With fd
.Title = "Select the folder that contains the documents."
If .Show = -1 Then
strFolder = .SelectedItems(1) & "\"
Else
MsgBox "You did not select the folder that contains the documents."
Exit Sub
End If
End With
MkDir strFolder & "Processed"
strDoc = Dir$(strFolder & "*.docx")
While strDoc <> ""
Set wordDoc = Word.Documents.Open(strFolder & strDoc)
With wordDoc
.Content.Select
With wordApp.Selection.Find
.Text = "Your establishment name [0-9]{4}"
.MatchWildcards = True
.wrap = wdFindStop
.Execute
End With
.SaveAs strFolder & "Processed\" & Right(wordApp.Selection, 4) & ".docx"
.Close
End With
strDoc = Dir$()
Wend
wordApp.Quit
Set wordApp = Nothing
End Sub
Hope this helps,
TheSilkCode
I have to copy the first table from doc1 and paste the table in doc2 bookmarked place.Both documents opened by browsing method.
find below my error code
Sub MTRUpdation()
Dim myStoryRange As Range
Dim Current_MTR As Document
Dim module_name As String
Dim livcycle_version As String
Dim XML As String
Dim length As Integer
Dim finalString As String
Dim MIL_History, Test_sce_summary As Table
Dim Test_sce As Range
' Open current MTR document by dialog box
Set old_doc = Application.FileDialog(msoFileDialogOpen)
With old_doc
.Title = "Choose old MTR document"
.AllowMultiSelect = False
If .Show <> -1 Then
Exit Sub
Set MIL_History = Word.ActiveDocument.Tables(1)
Set Test_sce = Word.ActiveDocument.Tables(1).Range
Set Test_sce_summary = Word.ActiveDocument.Tables(4)
'Word.Selection.Copy
End If
'ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
'Word.ActiveDocument.Close (False)
End With
' Open current MTR document by dialog box
Set myfile = Application.FileDialog(msoFileDialogOpen)
With myfile
.Title = "Choose current MTR document"
.AllowMultiSelect = False
If .Show <> -1 Then
Exit Sub
End If
'To get the file path name
fileselected = .SelectedItems(1)
'Activate the browsed document ie current MTR document
Set activation = Documents.Open(fileselected)
Documents(activation).Activate
ActiveDocument.Tables(1).Delete
'moving cursor to MIL author and version history position
With Selection.Find
.MatchWildcards = True
.Wrap = wdFindContinue
.Execute findtext:="MIL author & version history"
End With
' Selection.Find.Execute
Selection.MoveDown Unit:=wdLine, count:=1
Selection.HomeKey Unit:=wdLine
ActiveDocument.Bookmarks.Add Name:="MIL_Author", Range:=Selection.Range
Selection.GoTo What:=wdGoToBookmark, Name:="MIL_Author"
'With
Dim table_1 As Range
Set table_1 = ActiveDocument.Bookmarks("MIL_Author").Range
table_1.Collapse wdCollapseEnd
table_1.FormattedText = Test_sce.FormattedText
table_1.Collapse wdCollapseEnd
table_1.Text = vbCrLf
' = Test_sce_summary.Range
End With
End Sub
In my code i opened doc1 and copied the first table.Then opened doc2 added bookmark to paste the copied table.then go to the book marked places paste the copied table.This is what i want.please anyone help to get the correct code
I see there will be a problem with the With old_doc statement. The Exit Sub needs to be part of the If ....... Then and then the Setrows need to be part of the Else.
Also the way the documents are handled is incorrect.
I have tested this with two dummy documents, the "OLD" with four tables and the "NEW" with the text "MIL author & version history"
See if it works.
Sub MTRUpdation()
Dim myStoryRange As Range
Dim Current_MTR As Document
Dim module_name As String
Dim livcycle_version As String
Dim XML As String
Dim new_doc As Document
Dim length As Integer
Dim finalString As String
'You need to have As .... after each element to Dim it as that element
Dim MIL_History As Table, Test_sce_summary As Table
Dim Test_sce As Range
Dim table_1 As Range
'OLD MTR
With Application.FileDialog(msoFileDialogOpen)
.Title = "Choose old MTR document"
.AllowMultiSelect = False
If .Show <> -1 Then Exit Sub
old_doc_FileName = .SelectedItems(1)
End With 'Ending old MTR Dialog with
'Opening the OLD MTR Doc
Set old_doc = Documents.Open(FileName:=old_doc_FileName)
Set MIL_History = old_doc.Tables(1)
Set Test_sce = old_doc.Tables(1).Range
Set Test_sce_summary = old_doc.Tables(4)
'New MTR
With Application.FileDialog(msoFileDialogOpen)
.Title = "Choose current MTR document"
.AllowMultiSelect = False
If .Show <> -1 Then Exit Sub
new_doc_FileName = .SelectedItems(1)
End With ' Ending Open current MTR document by dialog box
'Opening the NEW MTR Doc
Set new_doc = Documents.Open(FileName:=new_doc_FileName)
new_doc.Tables(1).Delete
'Selecting the entire doc
new_doc.Content.Select
'moving cursor to MIL author and version history position
With Selection.Find
.MatchWildcards = True
.Wrap = wdFindContinue
.Execute findtext:="MIL author & version history"
End With
' Selection.Find.Execute
Selection.MoveDown Unit:=wdLine, Count:=1
Selection.HomeKey Unit:=wdLine
ActiveDocument.Bookmarks.Add Name:="MIL_Author", Range:=Selection.Range
Selection.GoTo What:=wdGoToBookmark, Name:="MIL_Author"
Set table_1 = ActiveDocument.Bookmarks("MIL_Author").Range
With table_1
.Collapse wdCollapseEnd
.FormattedText = Test_sce.FormattedText
.Collapse wdCollapseEnd
.Text = vbCrLf
End With
End Sub
There are many other things which can be corrected but I am not sure what some of the line are doing for your application, so I have left them.