Word macro that adds the file name to the body text of a series of Word documents in a folder - vba

I need a Word macro that adds the file name of a document to the first line of that Word document. But not just one document at a time. I would like the Macro to add these file names to a series of Word documents in a particular folder (with each document getting their own file name).
A Macro that adds the file name to document is simple:
Selection.HomeKey Unit:=wdStory
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, _
Text:= "FILENAME "
Selection.TypeParagraph
But how can I get it to add file names to an entire series of documents in a folder? I suppose the folder could be named in the Macro. For example: C:\Users\username\Desktop\somefolder\. I also suppose that a Loop could be used to go through the folder until the loop gets to the end of the documents in the folder.

This should at least get you started. I haven't tested it, but I've written this type of thing a few times before, so the basic idea works.
Dim filePath As String
Dim thisDoc As Document
Dim wordApp As Word.Application
Set wordApp = New Word.Application
'wordApp.Visible = True ' uncomment if you want to watch things happen
'Get first file that matches
filePath = Dir("C:\Users\username\Desktop\somefolder\*.doc") ' or *.whatever
Do While filePath <> ""
Set thisDoc = wordApp.Documents.Open(filePath)
'Add filename at top of document
Selection.HomeKey Unit:=wdStory
Selection.InsertAfter filePath
'Selection.InsertAfter ThisDocument.FullName ' alternative
'Your way using .Fields.Add is also fine if you want the file name as
' a field instead of
' plain text.
thisDoc.Close SaveChanges:=True
'Get next file that matches and start over
filePath = Dir()
Loop
wordApp.Quit
Set wordApp = Nothing

Related

Excel to Word VBA Export - Word Documents Not Being Created

I'm running an Excel to Word Export and I cannot create / save new documents based on the template. Each loop will reopen the word template, replaces the <<>> values in the template, and then moves on the next.
(Background - I have a table in Excel consisting 32 rows and 70 columns. I've created a corresponding word template consisting of values to replace from the excel sheet (for instance, <>). On the run, It exports values based on corresponding tags (for instance, <>) in the Excel sheet to the Word Doc). It seems to be working until it gets to WordDoc.SaveAs Filename
The error I get is
Do you want to save your document as the template name? yes / no
it stops there and does not create templates but only changes the template file.
Can anyone suggest a fix to this?
Sub CreateWordDoc()
Dim BenefitRow, BenefitCol, LastRow As Long
Dim TagName, TagValue, Filename As String
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
Dim WordContent As Word.Range
On Error Resume Next
With Sheets("VBA Output")
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True 'Make visible
LastRow = .Range("A9999").End(xlUp).Row 'Determine last row
For BenefitRow = 4 To 6
Set WordDoc = WordApp.Documents.Open(Filename:=" template name.dotm", ReadOnly:=False) 'Open Template saved as .dotm
For BenefitCol = 1 To 79
TagName = .Cells(3, BenefitCol).Value 'Tag Name
TagValue = .Cells(BenefitRow, BenefitCol).Value 'Tag Value
With WordDoc.Content.Find
.Text = TagName
.Replacement.Text = TagValue
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll ',Forward:True, Wrap:wdFindContinue
End With
Next BenefitCol
Filename = ThisWorkbookPath & "\" & .Range("E" & BenefitRow).Value & ".docx"
WordDoc.SaveAs Filename
WordDoc.Close
Next BenefitRow
End With
WordApp.Quit
End Sub
The problem (error message) you're seeing comes from opening a template file then wanting to save it as a "plain vanilla" document. This isn't how Word was designed to be used, which is why Word is basically saying, "Are you sure that's what you want to do?"
A template should not be opened unless the purpose is to change the template, itself. In that case, it would be saved again as a template - no message would be displayed.
When creating new documents from a template use the Documents.Add method:
Set WordDoc = WordApp.Documents.Add(Template:=" template name.dotm")
This automatically creates a copy of the template - there's no danger of overwriting the template. And the message mentioned in the question will not appear when the SaveAs method is executed.

VBA - Choosing Destination Folder for Saving File

I'm a total VBA noob and need a little help. If it matters I'm using Microsoft Word 2016 on a Mac. I'm using mail merge to create a word doc, and need to split the resulting word doc into multiple pages based on section breaks. I found this page with VBA code to split the pages and it works great. The only issue I'm having is it's saving to a random place on my computer (I have no idea how it's deciding where to save). Here's the code I'm working with:
Sub BreakOnSection()
' Used to set criteria for moving through the document by section.
Application.Browser.Target = wdBrowseSection
'A mail merge document ends with a section break next page.
'Subtracting one from the section count stop error message.
For i = 1 To ((ActiveDocument.Sections.Count) - 1)
'Note: If a document does not end with a section break,
'substitute the following line of code for the one above:
'For I = 1 To ActiveDocument.Sections.Count
'Select and copy the section text to the clipboard.
ActiveDocument.Bookmarks("\Section").Range.Copy
'Create a new document to paste text from clipboard.
Documents.Add
Selection.Paste
' Removes the break that is copied at the end of the section, if any.
Selection.MoveUp Unit:=wdLine, Count:=1, Extend:=wdExtend
Selection.Delete Unit:=wdCharacter, Count:=1
ChangeFileOpenDirectory "C:\"
DocNum = DocNum + 1
ActiveDocument.SaveAs fileName:="test_" & DocNum & ".doc"
ActiveDocument.Close
' Move the selection to the next section in the document.
Application.Browser.Next
Next i
ActiveDocument.Close savechanges:=wdDoNotSaveChanges
End Sub
I see the ChangeFileOpenDirectory is set to "C:\" which isn't right for a mac, but what would I need to change to have it ask me where to save all the resulting docs? I don't want to select a folder for each individual doc, but rather select one folder for all of the docs to save into and let it run.
Thanks in advance for the help, I've tried a few hours of google and am still unsure on this one.
I have not tested this on a mac but it should be
Dim mySaveLocation As String
Dim dlg As FileDialog
Set dlg = Application.FileDialog(msoFileDialogFolderPicker)
dlg.AllowMultiSelect = False
dlg.Show
mySaveLocation = dlg.SelectedItems.Item(1)
and then when you save it
ActiveDocument.SaveAs fileName:= mySaveLocation & "\test_" & DocNum & ".doc"

Copy and paste INCLUDING bookmarks VBA

I have an Excel worksheet from which I am trying to paste Information into a wordfile "Template" (just a word-document in the layout I want), which contains bookmarks. What I would like to do is:
Copy everything in the word document (including bookmarks)
Replace the bookmarks with the data in my sheet
Go to the bottom of the page, insert a page break and paste the copied Text, including bookmarks
Loop through points 2 & 3 for all the rows in my excel file
I have patched together some code, but I'm unable to get the bookmark to paste the text with the bookmarks still intact. Can any of you help me get there?
Sub ReplaceBookmarks
'Select template
PickFolder = "C:\Users\Folder"
Set fdn = Application.FileDialog(msoFileDialogFilePicker)
With fdn
.AllowMultiSelect = False
.Title = "Please select the file containing the Template"
.Filters.Clear
.InitialFileName = PickFolder
If .Show = True Then
Temp = fdn.SelectedItems(1)
End If
End With
'open the word document
Set wdApp = CreateObject("Word.Application")
Set wdDoc = wdApp.Documents.Open(Temp)
'show the word document - put outside of loop for speed later
wdApp.Visible = True
'Copy everything in word document
wdDoc.Application.Selection.Wholestory
wdDoc.Application.Selection.Copy
LastRow2 = 110 ' In real code this is counted on the sheet
For i = 2 To LastRow2
'Data that will replace bookmarks in ws2 (defined somewhere in real code)
Rf1 = ws2.Cells(i, 4).Value
Rf2 = ws2.Cells(i, 2).Value
Rf3 = ws2.Cells(i, 3).Value
'replace the bookmarks with the variables - references sub "Fillbookmark"
FillBookmark wdDoc, Rf1, "Rf1"
FillBookmark wdDoc, Rf2, "Rf2"
FillBookmark wdDoc, Rf3, "Rf3"
' Jump to bottom of document, add page break and paste
With wdDoc
.Application.Selection.EndKey Unit:=wdStory
.Application.Selection.InsertBreak Type:=wdPageBreak
.Application.Selection.PasteAndFormat (wdFormatOriginalFormatting)
End With
Next i
End Sub
Sub FillBookmark(ByRef wdDoc As Object, _
ByVal vValue As Variant, _
ByVal sBmName As String, _
Optional sFormat As String)
Dim wdRng As Object
'store the bookmarks range
Set wdRng = wdDoc.Bookmarks(sBmName).Range
'if the optional format wasn’t supplied
If Len(sFormat) = 0 Then
'replace the bookmark text
wdRng.Text = vValue
Else
'replace the bookmark text with formatted text
wdRng.Text = Format(vValue, sFormat)
End If
End Sub
First try, instead of Copy/Paste, using WordOpenXml. This is much more reliable than copy/paste. Now remember that a Bookmark is a named location, when you copy a section of the document and put it back on another location when the original bookmark is still in place, the new section won't get the copied Bookmark.
I'll provide a little bit of code to show this to you:
Sub Test()
ActiveDocument.Bookmarks.Add Name:="BM1", Range:=ActiveDocument.Paragraphs(1).Range
ActiveDocument.Application.Selection.WholeStory
Dim openxml As String
openxml = ActiveDocument.Application.Selection.wordopenxml
ActiveDocument.Bookmarks(1).Delete
With ActiveDocument
.Application.Selection.EndKey Unit:=wdStory
.Application.Selection.InsertBreak Type:=wdPageBreak
.Application.Selection.InsertXML xml:=openxml
End With
' ActiveDocument.Bookmarks(1).Delete
With ActiveDocument
.Application.Selection.EndKey Unit:=wdStory
.Application.Selection.InsertBreak Type:=wdPageBreak
.Application.Selection.InsertXML xml:=openxml
End With
End Sub
Now open a new document enter some text by entering =Rand() as text in the document and hit enter
Next run the code from the Test macro.
You'll see that because you delete the bookmark using ActiveDocument.Bookmarks(1).Delete from the original part the first inserted text now contains the bookmark, the second does not.
If you uncomment the ' ActiveDocument.Bookmarks(1).Delete line you will see that the bookmark ends up in the second added text part because there is no duplicate bookmark anymore when creating the second section.
So in short, copying a bookmark will not duplicate the bookmark when pasting it, so you need to make sure you either delete the original bookmark or rename the bookmarks to make them unique again. Duplicates is a no go.

Word Macro to Mass Hyperlink variable length strings

I've been looking through the forums for a while now trying to find an answer to my problem, and either I'm dense or it hasn't been answered, so here I am.
Long story short, my job involves writing up word documents that list building deficits and provides hyperlinks to images of said deficits. The visible hyperlink text always follows the same format: '[site abbreviation][(image number)].JPG'. For example, if we are looking at 'Administrative Building', our images will be named 'AB(1).JPG', 'AB(2).JPG', etc, often into the mid-hundreds or thousands. In the word document, they are referenced as 'AB1', 'AB2' etc.
Currently, I have a macro that allows me to automatically create a hyperlink once I've selected the text, but I am trying to create a macro that will look through a document (or better yet, a highlighted selection) and assign hyperlinks to any text that starts with the site's abbreviation all at once.
My current attempt at a mass-hyperlinking macro is frustratingly close, but has one major error: while it will correctly hyperlink the first image name it finds, all subsequent images are linked with the next two characters included in the link. For example, if a sentence were to say "This is not correct (AB33), but this is correct (AB34)', my macro will hyperlink the text 'AB34' (which is correct) and 'AB33) ' (which is incorrect).
This is the macro I've been working with thus far (note that the text between the lines of 'XXXX...' are basic instructions for my coworkers to change the link destination as needed)
Option Explicit
Sub Mass_Hyperlink_v_1_1()
'incomplete: selects incorrect text after first link
Dim fileName As String
Dim filePath As String
Dim rng As Range
Dim tag As String
Dim FileType As String
Dim folder As String
Dim space As String
Dim start As String
Dim report_type As String
Dim temp As String
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
'Do not touch anything above this line
'Answer the following for the current document. Leave all quotations.
report_type = "CL" 'CL = Checklist
'SR = Site Report
folder = "Doors" 'The name of the folder you are linking images from
'Must match folder exactly
tag = "FS" 'Put file prefix here (ex. if link says "AB123", put "AB")
space = "No" 'Does the image file have a space in it? (ex. if file name is "AB (23)", put "yes")
FileType = ".JPG" 'make sure filetype extensions match
'Do not touch anything below this line
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
If space = "Yes" Then
start = "%20("
Else: start = "("
End If
If report_type = "CL" Then
folder = "..\Images\" & folder
Else: folder = folder
End If
If report_type = "SR" Then
folder = "Images\" & folder
Else: folder = folder
End If
Set rng = ActiveDocument.Range
With rng.find
.MatchWildcards = True
Do While .Execute(findText:=tag, Forward:=False) = True
rng.MoveStartUntil (tag)
rng.Select
Selection.Extend
Selection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
'I believe the issue is created here
Selection.start = Selection.start + Len(tag)
ActiveDocument.Range(Selection.start - Len(tag), Selection.start).Delete
fileName = Selection.Text
filePath = folder & "\" & tag & start & fileName & ")" & FileType
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, address:= _
filePath, SubAddress:="", ScreenTip:="", TextToDisplay:= _
tag & Selection.Text
rng.Collapse wdCollapseStart
Loop
End With
End Sub
If I've explained this terribly wrong or not provided enough information, please let me know and I'll try to be more clear. And if there is a helpful resource that I'm simply too dense to have found, please let me know! thank you!
edit: if anyone knows how to only select words that start with the tag as opposed to words with the tag text in them, I'd be incredibly appreciative as well!
If you want to match a fixed tag followed by a variable number of digits:
Sub Tester()
TagMatches ActiveDocument, "AB"
End Sub
Sub TagMatches(doc As Document, tag As String)
Dim rng
Set rng = doc.Range
With rng.Find
.Text = tag & "[0-9]{1,}"
.Forward = True
.MatchWildcards = True
Do While .Execute
Debug.Print rng.Text
Loop
End With
End Sub
See: http://word.mvps.org/faqs/general/usingwildcards.htm

How to extract / delete first word of each page?

I did a mailmerge to create dynamic word pages with customer information.
Then I did (by looking on the net) a macro to split the result file into several pages, each page being saved as one file.
Now I'm looking to give those files some names containing customer info. I googled that and I think the (only?) way is to create a mergefield with that info, at the very beginning of the page, then extract and delete it from the page with a macro to put it in file names.
Example: If I have a customer named Stackoverflow I would like to have a file named Facture_Stackoverflow.doc.
I found nowhere how to select, extract and then delete this first word from my page.
Here is my "splitting macro", which currently names the files just with an incremented ID:
Sub DecouperDocument()
Application.Browser.Target = wdBrowsePage
For i = 1 To ActiveDocument.BuiltInDocumentProperties("Number of Pages")
ActiveDocument.Bookmarks("\page").Range.Copy
Documents.Add
Selection.Paste
Selection.TypeBackspace
ChangeFileOpenDirectory "C:\test\"
DocNum = DocNum + 1
ActiveDocument.SaveAs FileName:="Facture_" & DocNum & ".doc"
ActiveDocument.Close
Application.Browser.Next
Next i
ActiveDocument.Close savechanges:=wdDoNotSaveChanges
End Sub
The function below will enable you to extract the first word (and optionally remove it) of a Word document.
Public Function GetFirstWord(Optional blnRemove As Boolean = True) As String
Dim rng As Range
Dim intCharCount As Integer
Dim strWord As String
With ThisDocument
Set rng = .Characters(1)
intCharCount = rng.EndOf(wdWord, wdMove)
With .Range(0, intCharCount - 1)
strWord = .Text
If blnRemove Then
.Delete
End If
End With
End With
GetFirstWord = strWord
End Function
I hope this helps.