VBA - Choosing Destination Folder for Saving File - vba

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"

Related

How can I manage the active document reference in word to save and close my newly created output?

I am trying to use VBA in an open .docm file to open a 2nd read only .docx file and then insert -> object -> text from file (a 3rd read only .docx stored within the same folder).
The below code correctly opens and merges the two files but when it comes to saving the output it returns a Run-Time 13 “mismatch” error. My limited understanding leads me to believe that at the point where I am saving, the active document reference is still the original .docm and it is the .docx designation that then causes the conflict.
I am really struggling to manage the active document reference to avoid this. Presumably I am missing something very simple, all assistance is very gratefully received.
Documents.Open ActiveDocument.Path & "\DocA.docx", Visible:=True
Selection.InsertFile FileName:=ActiveDocument.Path & "\DocB.docx", Range:="", _
ConfirmConversions:=False, Link:=False, Attachment:=False
ActiveDocument.SaveAs2 "C:\Users\" & Environ("UserName") & "\DocC" & ".docx", FileFormat:= _
wdFormatXMLDocument
ActiveWindow.Close
Putting flesh on John Korchok's comment:
Sub deleteme3()
Dim oldDoc As Document
Set oldDoc = Documents.Open(ActiveDocument.Path & "\DocA.docx", Visible:=True)
oldDoc.Activate
selection.Collapse Direction:=wdCollapseEnd 'to insert at end of document
selection.Range.InsertBreak Type:=wdPageBreak
Selection.EndKey Unit:=wdStory
Selection.InsertFile FileName:=ActiveDocument.Path & "\DocB.docx", range:="", _
ConfirmConversions:=False, Link:=False, Attachment:=False
oldDoc.SaveAs2 "C:\Users\" & Environ("UserName") & "\DocC" & ".docx", FileFormat:= _
wdFormatXMLDocument
oldDoc.Close
Set oldDoc = Nothing
End Sub
Note this puts the inserted document at the end of the original document. You may want to use a next-page section break instead if there is header/footer differentiation. If you need that, please comment and I will include it.
There are a number of break types. Here is the enumeration of all of them if you are interested. The following types create a page break of one sort or another:
wdPageBreak (the default)
wdSectionBreakNextPage
wdSectionBreakOddPage (starts section on next odd-numbered page - good for chapters)
wdSectionBreakEvenPage (starts section on next even-numbered page - rarely used)
If wanting to preserve headers and footers additional code would be needed.
(Every section in a Word document has three headers and three footers, even if they are not displayed or used.)
' Break Link to Previous in newly added section for all of the headers and footers
Dim oHeaderFooter As HeaderFooter
Dim iCounter As Long
Let iCounter = ActiveDocument.Sections.Count
' break link in headers
For Each oHeaderFooter In ActiveDocument.Sections(iCounter).Headers
Let oHeaderFooter.LinkToPrevious = False
Next oHeaderFooter
' repeat for footers
For Each oHeaderFooter In ActiveDocument.Sections(iCounter).Footers
Let oHeaderFooter.LinkToPrevious = False
Next oHeaderFooter

Save documents with the data from mail merge

For my work I make product specifications. I have a table with all the data, and a standard Word document where the data needs to be inserted. I do this using the built-in mail merge function from Word. However, I need to save the documents seperately, and I found the following code for this:
Sub BreakOnSection()
' Used to set criteria for moving through the document by section.
Application.Browser.Target = wdBrowseSection
'A mailmerge 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)
'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
This saves the documents as test 1, test 2, etc.
I want to save the documents using one of the data items I use for the mail merge. Is there any way to do this?
I made it work, this is the code I have now
Sub BreakOnSection()
' Used to set criteria for moving through the document by section.
Application.Browser.Target = wdBrowseSection
'A mailmerge 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)
'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
Dim rngParagraphs As Range
Set rngParagraphs = ActiveDocument.Range(Start:=(ActiveDocument.Paragraphs(1).Range.Start + 6), End:=(ActiveDocument.Paragraphs(1).Range.End - 1))
rngParagraphs.Select
' 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:="Productspec" & rngParagraphs & ".doc"
ActiveDocument.Close
' Move the selection to the next section in the document
Application.Browser.Next
Next i
ActiveDocument.Close savechanges:=wdDoNotSaveChanges
End Sub

Export individual documents from mail merge

How would I create individuals files from mail merge rather than the one large file that is output by the mail merge function in Microsoft Office?
I was hoping to be able to save each letter than was created as a name of one of the merge fields, but I haven't been able to find an intuitive way so far...
Recently I've come across the similar situation where I want to save individual files in pdf format rather than saving one large file created by Mail merge function. I've written down this small function to save individual file in pdf format.
Sub SaveAsPDF()
Dim CouncilName As String
With ActiveDocument.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
For SectionCount = 1 To .DataSource.RecordCount
With .DataSource
'FirstRecord and LastRecords defines how many data records needs to be merge in one document.
'createing pdf file for each data record so in this case they are both pointing to ActiveRecord.
.FirstRecord = ActiveDocument.MailMerge.DataSource.ActiveRecord
.LastRecord = ActiveDocument.MailMerge.DataSource.ActiveRecord
'get the council name from data source
CouncilName = .DataFields("Council").Value
'move to next datasource record.
If .ActiveRecord <> .RecordCount Then
.ActiveRecord = wdNextRecord
End If
End With
'Get path and file name
PDFPathAndName = ActiveDocument.Path & Application.PathSeparator & "FINAL - " & CouncilName & ".pdf"
' Merge the document
.Execute Pause:=False
' Save resulting document.
Set PDFFile = ActiveDocument
PDFFile.ExportAsFixedFormat PDFPathAndName, wdExportFormatPDF
PDFFile.Close 0
Next
End With
End Sub
as of my experience, there is no option to save individual files, instead you can use Macro to spit the files and save it individually with specific name that you want. I have tried the same and succeeded with what want. Hope the below code helps you as well to achieve you goal.
Sub BreakOnSection()
'Used to set criteria for moving through the document by section.
Application.Browser.Target = wdBrowseSection
'A mailmerge 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)
'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
'To save your document with the original formatting'
Selection.PasteAndFormat (wdFormatOriginalFormatting)
'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
Please revert me for any clarifications.
I modified Parth's answer since it didn't work for me.
Sub SaveAsFileName()
Dim FileName As String
With ActiveDocument.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
For SectionCount = 1 To .DataSource.RecordCount
With .DataSource
ActiveDocument.MailMerge.DataSource.ActiveRecord = SectionCount
ActiveDocument.MailMerge.DataSource.FirstRecord = SectionCount
ActiveDocument.MailMerge.DataSource.LastRecord = SectionCount
' replace Filename with the column heading that you want to use - can't have certain symbols in the name
FileName = .DataFields("Filename").Value
End With
'Get path and file name
FullPathAndName = ActiveDocument.Path & Application.PathSeparator & FileName & ".docx"
' Merge the document
.Execute Pause:=False
' Save resulting document.
ActiveDocument.SaveAs (FullPathAndName)
ActiveDocument.Close False
Next
End With
End Sub

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.

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

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