change name of CustomDocumentProperties in word with vba - vba

How can I rename my customVariable in word? I have a Customvaraiable called "Document Number", but I would now like to rename it to _DocumentNumber"
I know I can create a new CustomVariable, delete the old one, but I am then struggling with how to update all the links in the document to the new one.
Edited code:
Sub test()
Dim A As word.Field
Dim FldUpd As String
Dim findText As String
Dim replaceText As String
findText = "Document Number"
replaceText = "_DocumentNumber"
ActiveWindow.View.ShowFieldCodes = False
If ActiveDocument.CustomDocumentProperties(findText).value = "" Then Exit Sub
For Each A In ActiveDocument.Fields
If A.result.Text = ActiveDocument.CustomDocumentProperties(findText).value Then
Call WordProperties.createCustomDocumentProperty(ActiveDocument.name, replaceText, ActiveDocument.CustomDocumentProperties(findText).value)
ActiveWindow.View.ShowFieldCodes = True
A.Select
'DOCPROPERTY "Document number" \* MERGEFORMAT
With Selection.Find
.Text = "DOCPROPERTY*" & findText
.Replacement.Text = "DOCPROPERTY " & replaceText
.Format = True
.MatchCase = False
.MatchWildcards = True
End With
tempBool = Selection.Find.Execute(replace:=wdReplaceAll)
' Refresh fields
ActiveDocument.Fields.update
ActiveWindow.View.ShowFieldCodes = False
If tempBool Then ActiveDocument.CustomDocumentProperties(findText).Delete
End If
Next
End Sub
Edited:
The problem is that the find method does not return true.

You are mixing up two things that must be separate.
First create the new doc property, using ActiveDocument.CustomDocumentProperties.Add
You do this only once, since the doc property exists only once.
Then you replace all existing references to the old doc property to the new one. Something like (excerpts from macro recorder)
' Show field source references (Alt+F9) so you can use Find&Replace
ActiveWindow.View.ShowFieldCodes = True
With Selection.Find
.Text = "DOCPROPERTY Document Number"
.Replacement.Text = "DOCPROPERTY _DocumentNumber"
.Format = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
' Refresh fields
ActiveDocument.Fields.Update
ActiveWindow.View.ShowFieldCodes = False
Then you can delete the old doc property.
Edit: to find and replace in all sections (including header & footer), see
Searching for Text in Header Section of A Word Document

Here is the working code, feel free to improve it:
Sub test()
Dim findText As String
Dim replaceText As String
Dim temp As Variant
findText = "Document Number"
replaceText = "_DocumentNumber"
On Error GoTo doesNotExist
temp = ActiveDocument.CustomDocumentProperties(findText).value
pFindTxt = "DOCPROPERTY*" & findText
pReplaceTxt = "DOCPROPERTY """ & replaceText
ActiveWindow.View.ShowFieldCodes = True
'create the new variable
Call WordProperties.createCustomDocumentProperty(ActiveDocument.name, replaceText, ActiveDocument.CustomDocumentProperties(findText).value)
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case WdStoryType.wdEvenPagesHeaderStory, _
WdStoryType.wdPrimaryHeaderStory, _
WdStoryType.wdEvenPagesFooterStory, _
WdStoryType.wdPrimaryFooterStory, _
WdStoryType.wdFirstPageHeaderStory, _
WdStoryType.wdFirstPageFooterStory
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
' Refresh fields
ActiveDocument.Fields.update
ActiveWindow.View.ShowFieldCodes = False
Exit Sub
doesNotExist:
MsgBox "CustomVariable " & findText & " does not exist"
Exit Sub
End Sub
Public Sub SearchAndReplaceInStory(ByVal rngStory As word.Range, ByVal strSearch As String, ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.MatchCase = False
.MatchWildcards = True
.Execute replace:=wdReplaceAll
End With
End Sub

Related

Find first instance of the acronym

Any help would be awesome. I have a macro that finds acronyms and applies a spell out of the acronym with the acronym in parenthesis. It is applying the spell out and acronym once but randomly. I need the macro to identify the first instance and apply the spell out only to that first instance. So if the first instance should look like this:
Be Right Back (BRB) some text BRB some text BRB
Right know it looks like this: BRB some text Be Right Back (BRB) some text BRB
The macro has the code " .Execute Replace:=wdReplaceOne" but it doesn't seem to be working.
Here's the code I am using:
Sub AcronymManager()
Application.ScreenUpdating = False
Dim FRDoc As Document, FRList As String, j As Long, StrExp As String, StrAcc As String
'Load the strings from the reference doc into a text string to be used as an array.
Set FRDoc = ThisDocument
'Alternative code to use a different document the reference doc:
'Set FRDoc = Documents.Open("C:\Users" & Environ("UserName") & "\Documents\AcronymList.doc")
If ActiveDocument = FRDoc Then
MsgBox "Error: Cannot process this document - it's the source document", vbCritical
Exit Sub
End If
FRList = FRDoc.Range.Text
If FRDoc <> ThisDocument Then FRDoc.Close wdDoNotSaveChanges
Set FRDoc = Nothing
With ActiveDocument.Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Replacement.Highlight = True
.MatchWholeWord = True
.MatchCase = True
.Wrap = wdFindContinue
'Process each word from the Check List. Tab-delimited strings are assumed, formatted as:
'Find text <Tab> Replace text
For j = 0 To UBound(Split(FRList, vbCr)) - 1
StrExp = Split(Split(FRList, vbCr)(j), vbTab)(0)
StrAcc = Split(Split(FRList, vbCr)(j), vbTab)(1)
.Text = StrExp
.Replacement.Text = StrAcc
.Execute Replace:=wdReplaceAll
.Text = "(" & StrAcc & ")"
.Execute Replace:=wdReplaceAll
.Text = StrAcc & "^w" & StrAcc
.Execute Replace:=wdReplaceAll
.Text = StrAcc
.Replacement.Text = StrExp & " (" & StrAcc & ")"
.Execute Replace:=wdReplaceOne
Next
End With
Application.ScreenUpdating = True
End Sub

Error when inserting image using variable for Selection.InlineShapes.AddPicture

I am trying to go through a word document, and replace existing image path strings with the actual image. When I enter the address hard coded, it works. But if I put the same code in a variable I get an error
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.
Code:
Sub InsertJPGs()
For Each singleLine In ActiveDocument.Paragraphs
Dim Value As Variant
Dim imageName As String
Options.DefaultFilePath(wdDocumentsPath) = "d:\Downloads\ReportImages\"
originalLineText = singleLine.Range.Text
lineText = singleLine.Range.Text
If InStr(lineText, ".jpg") <> 0 Then
singleLine.Range.Select
rangeText = singleLine.Range.Text
imageName = rangeText
imageName = "D:\Downloads\ReportImages\" & rangeText
'imageName = "D:\Downloads\ReportImages\PictureImportTest_ATTICSkylight#1#_img2.jpg"
Selection.InlineShapes.AddPicture FileName:= _
imageName, LinkToFile:=True, SaveWithDocument:=True
End If
If InStr(lineText, "[[[IMAGE LIST]]]") <> 0 Then
Exit For
End If
Next singleLine
End Sub
Try:
Sub Demo()
Application.ScreenUpdating = False
Dim FlNm As String: Const StrPath As String = "d:\Downloads\ReportImages\"
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<[! ^t^l^13]#.[Jj][Pp][Gg]>"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
FlNm = .Duplicate.Text
.Text = vbNullString
.InlineShapes.AddPicture StrPath & FlNm, False, True, .Duplicate
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
If you want to retain the filenames in the document, delete or comment out:
.Text = vbNullString

Select certain page on condition in vba

I am writing a script that extract tables from Word file as copies it to a worksheet in Excel. However, the Word files I received do not have the same format and the tables I need are not always on the same page. Hence I cannot use the regular table index.
Each table is on a different page and only on that page there somewhere is a text string (may or may not be in the table itself) like 'material/material list'. What I'd like to do is scan each page of the Word document for a certain textstring and only if that string is present, use the corresponding table on that page. Is this possible and how would I go about this?
A complication of the inconsistent formatting is that on some pages, the data is not even in a table so for those files I'd like an alert if the trigger word is found on a page but no table is there.
Edited:
I have tried to redefine the range considered. My hope is that this is the easiest method; see where the keyword occurs and then use the first table after that. However this does not seem to work.
With ActiveDocument.Content.Find
.Text = "Equipment"
.Forward = True
.Execute
If .Found = True Then Set aRange = ActiveDocument.Range(Start:=0, End:=0)
End With
Edit:
I tried to combine the code from macropod with a vba in Excel that copies the table to the worksheet.
Sub LookForWordDocs()
Dim FolderName As String
With Application.FileDialog(msoFileDialogFolderPicker)
.AllowMultiSelect = False
.Show
On Error Resume Next
FolderName = .SelectedItems(1)
Err.Clear
On Error GoTo 0
End With
Dim sFoldPath As String: sFoldPath = FolderName ' Change the path. Ensure that your have "\" at the end of your path
Dim oFSO As New FileSystemObject ' Requires "Microsoft Scripting Runtime" reference
Dim oFile As File
' Loop to go through all files in specified folder
For Each oFile In oFSO.GetFolder(sFoldPath).Files
' Check if file is a word document. (Also added a check to ensure that we don't pick up a temp Word file)
If ((InStr(1, LCase(oFSO.GetExtensionName(oFile.Path)), "doc", vbTextCompare) > 0) Or _
(InStr(1, LCase(oFSO.GetExtensionName(oFile.Path)), "docx", vbTextCompare) > 0)) And _
(InStr(1, oFile.Name, "~$") = 0) And _
((InStr(1, oFile.Name, "k") = 1) Or (InStr(1, oFile.Name, "K") = 1)) Then
' Call the UDF to copy from word document
ImpTable oFile
End If
Next
End Sub
Sub ImpTable(ByVal oFile As File)
Dim oWdApp As New Word.Application
Dim oWdDoc As Word.Document
Dim oWdTable As Word.Table
Dim oWS As Excel.Worksheet
Dim lLastRow$, lLastColumn$
Dim s As String
s = "No correct table found"
With Excel.ThisWorkbook
Set oWS = Excel.Worksheets.Add
On Error Resume Next
oWS.Name = oFile.Name
On Error GoTo 0
Set sht = oWS.Range("A1")
Set oWdDoc = oWdApp.Documents.Open(oFile.Path)
oWdDoc.Activate
'Application.ScreenUpdating = False
Dim StrFnd As String, Rng As Word.Range, i As Long, j As Long
j = 0
StrFnd = "equipment"
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = StrFnd
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
Do While .Find.Found
i = .Information(wdActiveEndAdjustedPageNumber)
Set Rng = Word.ActiveDocument.Goto(What:=wdGoToPage, Name:=i)
Set Rng = Rng.Goto(What:=wdGoToBookmark, Name:="\page")
If Rng.Tables.Count > 0 Then
With Rng.Tables(1)
Set oWdTable = Rng.Tables(1)
oWdTable.Range.Copy
sht.PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
j = 1
End With
End If
.Start = Rng.End
.Find.Execute
Loop
End With
If j = 0 Then sht.Value = s
'Application.ScreenUpdating = True
oWdDoc.Close savechanges:=False
oWdApp.Quit
End With
Set oWS = Nothing
Set sht = Nothing
Set oWdDoc = Nothing
Set oWdTable = Nothing
Set Rng = Nothing
End Sub
For the first file, the code works fine. However on the second run I get a run-time error "The remote Server Machine does not Exist or is unavailable" on line
"Word.ActiveDocument.Range". I added a couple of qualifications for elements but this still did not solve the problem. Am I missing another line?
BTW When I place "Word" before ActiveDocument.Range the code does not work any more.
Since you've changed the text from 'material/material list' to 'Equipment', it's a bit hard to know quite what you want. Try something along the lines of:
Sub Demo()
Application.ScreenUpdating = False
Dim StrFnd As String, Rng As Range, i As Long
StrFnd = InputBox("What is the Text to Find")
If Trim(StrFnd) = "" Then Exit Sub
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = StrFnd
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = True
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
End With
Do While .Find.Found
i = .Information(wdActiveEndAdjustedPageNumber)
Set Rng = ActiveDocument.GoTo(What:=wdGoToPage, Name:=i)
Set Rng = Rng.GoTo(What:=wdGoToBookmark, Name:="\page")
If Rng.Tables.Count > 0 Then
MsgBox Chr(34) & StrFnd & Chr(34) & " and table found on page " & i & "."
With Rng.Tables(1)
'process this table
End With
Else
MsgBox Chr(34) & StrFnd & Chr(34) & " found on page " & i & " but no table."
End If
.Start = Rng.End
.Find.Execute
Loop
End With
Application.ScreenUpdating = True
End Sub
Note: the above code will test all pages on which the Find text is found.

Replacement text to text and field in word with vba

I have a working, however a slow method for searching through a document and search for a specific text: Issue "tab" A and then replace it with text but where A is referred to a customvariable. Has anyone done something similar?
Sub hsdkjgh()
Call replaceIssueNonVariable(ActiveDocument)
End Sub
Public Function SearchInStory(ByVal rngStory As word.Range, ByVal strSearch As String) As Boolean
SearchInStory = False
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.MatchCase = False
.MatchWildcards = True
.Execute
If .found Then
rngStory.Text = "Issue:" & vbTab & ";;;;;;"
Call SearchInStory2(rngStory, ";;;;;;")
SearchInStory = True
End If
End With
End Function
Public Function SearchInStory2(ByVal rngStory As word.Range, ByVal strSearch As String) As Boolean
SearchInStory2 = False
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue
.MatchCase = False
.MatchWildcards = True
.Execute
If .found Then
rngStory.Select
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldDocProperty, Text:="_DocumentIssue", PreserveFormatting:=True
SearchInStory2 = True
End If
End With
End Function
Sub replaceIssueNonVariable(doc As Document)
Dim temp As Variant
Dim pFindTxtArray(4) As String
Dim pReplaceTxtArray(4) As String
pReplaceTxt = "Issue:^t" ' { DOCPROPERTY _DocumentIssue ^92* MERGEFORMAT }"
ActiveWindow.View.ShowFieldCodes = True
exitRevision = False
For i = 65 To 90
pFindTxt = "Issue:^t^" & i
'Iterate through all story types in the current document
For Each rngStory In doc.StoryRanges
'Iterate through all linked stories
Do
If SearchInStory(rngStory, pFindTxt) Then
'rngStory.Select
'Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldDocProperty, Text:="_DocumentIssue", PreserveFormatting:=True
exitRevision = True
End If
On Error Resume Next
Select Case rngStory.StoryType
Case WdStoryType.wdEvenPagesHeaderStory, _
WdStoryType.wdPrimaryHeaderStory, _
WdStoryType.wdEvenPagesFooterStory, _
WdStoryType.wdPrimaryFooterStory, _
WdStoryType.wdFirstPageHeaderStory, _
WdStoryType.wdFirstPageFooterStory
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
If SearchInStory(rngStory, pFindTxt) Then
exitRevision = True
End If
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
If exitRevision Then
Call CustomProperties.createCustomDocumentProperty(doc, "_DocumentIssue", Chr(i))
Exit For
End If
Next i
' Refresh fields
doc.Fields.update
ActiveWindow.View.ShowFieldCodes = False
Exit Sub
'create the new variable
Call CustomProperties.createCustomDocumentProperty(doc, "_DocumentIssue", Right(pFindTxtArray, 1))
doesNotExist:
MsgBox "CustomVariable " & findText & " does not exist"
Exit Sub
Debug.Print findText & " variable has got this new name: " & replaceText
End Sub

Word Macro to find and replace all in word document with textboxes

I need to write a VBA Word macro that will do a find and replace to change all occurrences of text in one font to another font. The code I have (listed below) does this but in ignores all the text in text boxes in the document. How do I either modify this macro to search all text both inside and outside textboxes in the document (headers and footers would be a plus but not absolutely necessary) or do it a different way in a macro. This macro is part of a larger macro that processes tens of thousands of documents so doing anything manually isn't an option.
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = True
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Font.Name = "PPalotina2007"
.Replacement.Font.Name = "Palotina X"
End With
Selection.Find.Execute Replace:=wdReplaceAll
Found this at http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm I should note this only works on the FIRST of each type of Story... There are better code on the link provided for getting to all story ranges.
Sub FindAndReplaceFirstStoryOfEachType()
Dim rngStory As Range
For Each rngStory In ActiveDocument.StoryRanges
With rngStory.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = True
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Font.Name = "PPalotina2007"
.Replacement.Font.Name = "Palotina X"
End With
rngStory.Find.Execute Replace:=wdReplaceAll
Next rngStory
End Sub
Thank you Chrismas007 for the link http://word.mvps.org/faqs/customization/ReplaceAnywhere.htm to the "complete answer" based on that link which I'm posting below for anyone else who needs this. It does a search not only on a text string but also on a particular font which it changes.
Sub FindReplaceAnywhere( _
ByVal pOldFontName As String, _
ByVal pNewFontName As String, _
ByVal pFindTxt As String, _
ByVal pReplaceTxt As String)
Dim rngStory As Word.Range
Dim lngJunk As Long
Dim oShp As Shape
'Fix the skipped blank Header/Footer problem
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pOldFontName, pNewFontName, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, pOldFontName, pNewFontName, pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
End Sub
Sub SearchAndReplaceInStory( _
ByVal rngStory As Word.Range, _
ByVal FindFontName As String, _
ByVal ReplaceFontName As String, _
ByVal strSearch As String, _
ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Font.Name = FindFontName
.Replacement.Font.Name = ReplaceFontName
.Text = strSearch
.Replacement.Text = strReplace
.Execute Replace:=wdReplaceAll
End With
End Sub
Thanks Harry Spier, even though I had to modify your code a little - finally it works great!
Sub FindReplaceAnywhere()
Dim pOldFontName As String
Dim pNewFontName As String
Dim rngStory As Word.Range
Dim lngJunk As Long
Dim oShp As Shape
pOldFontName = "FontDoe" 'replace with the font you want to replace
pNewFontName = "Font Dolores" 'replace with the font you really need to have in your doc
'Fix the skipped blank Header/Footer problem
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType
'Iterate through all story types in the current document
For Each rngStory In ActiveDocument.StoryRanges
'Iterate through all linked stories
Do
SearchAndReplaceInStory rngStory, pOldFontName, pNewFontName, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, pOldFontName, pNewFontName, pFindTxt, pReplaceTxt
End If
Next
End If
Case Else
'Do Nothing
End Select
On Error GoTo 0
'Get next linked story (if any)
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next
End Sub
Sub SearchAndReplaceInStory( _
ByVal rngStory As Word.Range, _
ByVal FindFontName As String, _
ByVal ReplaceFontName As String, _
ByVal strSearch As String, _
ByVal strReplace As String)
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Font.Name = FindFontName
.Replacement.Font.Name = ReplaceFontName
.Text = strSearch
.Replacement.Text = strReplace
.Execute Replace:=wdReplaceAll
End With
End Sub