Automate Mail Merge - excel

Here is the problem from my original post:
I have a Word template (dotm) that has fields i would like filled in from a one-line/entry Excel file. I have a "Rough.txt", the contents of which i would like to insert into a specific place in this same mail-merge-generated document in addition to the information from the Excel file.
i would like to generate a DOC or DOCX from this scripting process that is saved in the same directory as the above-mentioned files. I would like this to be done by clicking run on a bat file or similar type of situation that does not involve me manually opening the file and clicking the buttons every time i want to do it. I would like it to be simpler than opening word manually and running the macro.
Plus, if i can put it in an executable/"runnable" file like a bat or something similar, then i can attach a shortcut to it and run it with Cortana voice commands. This is why i am going about it from this angle. This would be a GEM to have. Important here is that it runs when i tell it to, not scheduled at a certain time. I have done this with other bats with great success.
So i used a combination of what all the answers were to construct the following:
I have a bat file with a bunch of FART commands in it to correct many common grammar errors in a document; it's irrelevant and long, so i won't post it here. It's called FINISH-1.bat.
Then i have a second BAT file, FINISH-2.bat, which contains only the following:
"C:\Program Files\Microsoft Office 15\root\office15\winword.exe" "/mRunAllMacros" "C:\Transcription\Transcription\In Progress\NewKCJob\Transcript.docx"
So then I created about 20 find/replace Microsoft Word macros for styles which i will not post here since this was not relevant to the question.
I made two more macros in Word which are relevant to my issue. The following completes the mail merge for my Excel file, which is exported from Jotform.
Sub MailMergeCover()
'
' MailMergeCover Macro
'
'
ActiveDocument.MailMerge.OpenDataSource Name:= _
"C:\Transcription\Transcription\In Progress\JotformExport.xlsx", _
ConfirmConversions:=False, ReadOnly:=False, LinkToSource:=True, _
AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:="", _
WritePasswordDocument:="", WritePasswordTemplate:="", Revert:=False, _
Format:=wdOpenFormatAuto, Connection:= _
"Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=C:\Transcription\Transcription\In Progress\JotformExport.xlsx;Mode=Read;Extended Properties=""HDR=YES;IMEX=1;"";Jet OLEDB:System database="""";Jet OLEDB:Registry Path="""";Jet OLEDB:Engine Type=37;Jet " _
, SQLStatement:="SELECT * FROM `Submissions$`", SQLStatement1:="", _
SubType:=wdMergeSubTypeAccess
With ActiveDocument.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
Windows("Transcript.docx [Compatibility Mode]").Activate
End Sub
And the following macro inserts my "Rough.Txt" document into the same transcript/Word document at the bookmark i inserted called "rough":
Sub InsertRough()
'
' InsertRough Macro
'
'
If ActiveDocument.Bookmarks.Exists("rough") = True Then
ActiveDocument.Bookmarks("rough").Select
Selection.InsertFile FileName:="C:\Transcription\Transcription\In Progress\NewKCJob\Rough.txt"
Else
MsgBox "Bookmark ""rough"" does not exist!"
End If
End Sub
The next step was to tie them all together in Word in a certain order so that my find/replace macros i mentioned earlier also apply to "Rough.txt":
Sub RunAllMacros()
Call InsertRough
Call Macro1
Call Macro2
Call Macro3
Call Macro4
Call Macro5
Call Macro6
Call Macro7
Call Macro8
Call Macro9
Call Macro10
Call Macro11
Call Macro12
Call Macro13
Call Macro14
Call Macro15
Call Macro16
Call Macro17
Call Macro18
Call Macro19
Call Macro20
Call MailMergeCover
End Sub
The second-to-last step was to make a third bat file, FINISH.bat, which Cortana will be using, to call the two bat files:
call "C:\Transcription\Transcription\In Progress\NewKCJob\FINISH-1.bat"
call "C:\Transcription\Transcription\In Progress\NewKCJob\FINISH-2.bat"
The last step was to create a shortcut to FINISH.bat in C:\Users\Username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs called "Finish Job" for Cortana to index.
Now, i can say, "Hey, Cortana, open finish job," and it will do this for me all automatically.
i have just shaved 20 minutes to an hour off EVERY transcript i complete as i was doing many of these corrections manually. i would like to respect and follow the rules as much as i can, so if i am not giving enough detail or doing something abnormally, let me know so i can fix it. Again, thank you so much!! Really, i could not have crafted this without your help.

Based on the information you provide:
Create a template (*.dotm) for this. Double-clicking it in the Windows
Explorer/the Desktop will create a new document.
The text file: I'm assuming insert "as is" with no subsequent
processing, so just use the Insert/Text/Object/Text from file
command in the Word UI. Click the arrow next to the "Insert" button
in the dialog box and choose to insert with Link.
Use Word's built-in Mailings/Mail Merge tool to link to the Excel
data-source
Record a macro to execute the mail merge.
Create a macro named AutoNew in the template and copy the content of
the recorded macro into it. This macro will execute automatically
when a new document is created from the template.

Related

Merging Word docs with Excel as variable data

I'm trying to work out a simple way to get "variable" data into a Word docs.
I have a client who is supplying Word templates for various procedures. This would form a document that goes out to several locations, with personalized information for each location.
This could be done with a simple Mail Merge from Excel, but there are additional issues:
The doc will contain tables with supervisor contact information. It's the general info: Name, phone contacts, email, etc. But there could be 1 to 5 contacts. I could see that would mean several rows with the same key, meaning several copies where I only want one.
Is there an "easy" way to merge data into both document text and tables? The idea is to present the client with a "goof proof" solution so they can easily update the template and the data files.
I'm also looking at using Word variables, but one source said I'd be limited to 15 variable in a document.
Any ideas will be greatly appreciated. Also looking up previous questions on this stack.
One option would be to use a DATABASE field in a normal ‘letter’ mailmerge main document and a macro to drive the process. Here is an outline of this approach:
Suppose you have a data set that has fields for the subordinates' Firstname, Surname, Employee ID, & Job Title, and that against each record is recorded their Manager's ID, whose email address is also recorded. Let's also assume the mailmerge main document is kept in the same folder as the data source. In that case, you could use a DATABASE field coded as:
{DATABASE \d "{FILENAME \p}/../MM datasource.xlsx" \s " SELECT [Firstname], [Surname], [Employee ID], [Job Title] FROM [Sheet1$] WHERE [Manager ID] = {MERGEFIELD Manager_ID} ORDER BY [Job Title] " \l "15" \b "49" \h}
in an email merge, where 'MM datasource.xlsx' is the data source filename - it could even be an Access database filename, if that's what you chose to use. If the mailmerge main document is NOT kept in the same folder as the data source, you'd need to replace all of "{FILENAME \p}/../MM datasource.xlsx" with the full path & filename (plus the encompassing double-quotes). The \l and \b switches control the table format, while the \h switch inserts a table header row - see: https://support.office.com/en-us/article/Field-codes-Database-field-04398159-a2c9-463f-bb59-558a87badcbc?ui=en-US&rs=en-US&ad=US
Note: The field brace pairs (i.e. '{ }') for the above example are all created in the document itself, via Ctrl-F9 (Cmd-F9 on a Mac); you can't simply type them or copy & paste them from this post. Nor is it practical to add them via any of the standard Word dialogues. The spaces represented in the field constructions are all required.
Then, to drive the process, you could use a macro like:
Sub Merge_by_Group()
Application.ScreenUpdating = False
Dim MainDoc As Document, StrMgrID As String, i As Long
Set MainDoc = ActiveDocument
With MainDoc
For i = 1 To .MailMerge.DataSource.RecordCount
With .MailMerge
.Destination = wdSendToEmail
.SuppressBlankLines = True
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
End With
If .DataSource.DataFields("Manager_ID") <> StrMgrID Then
StrMgrID = .DataSource.DataFields("Manager_ID")
.MailAddressFieldName = "Email"
.MailSubject = "Your Team's Details"
.MailFormat = wdMailFormatHTML
.Execute Pause:=False
End If
End With
Next i
End With
Application.ScreenUpdating = True
End Sub
A merge to email is assumed, but not necessary. If you want the output to go to a Word document, change:
.Destination = wdSendToEmail
to:
.Destination = wdSendToNewDocument
and delete:
.MailAddressFieldName = "Email"
.MailSubject = "Your Team's Details"
.MailFormat = wdMailFormatHTML
Note: If you rename the above macro as 'MailMergeToEmail' (or 'MailMergeToDoc' to send the output to a document), clicking on the 'Send Email Messages' (or 'Edit Individual Documents') button will intercept the merge and the process will run automatically. The potential disadvantage of intercepting the 'Send Email Messages' (or 'Edit Individual Documents') process this way is that you no longer get to choose which records to merge at that stage. However, you can still achieve the same outcome - and with greater control - via the 'Edit Recipient List' tools.
Conversely, if you're using a relational database or, an Excel workbook with a separate table listing each of the grouping criteria (e.g. the Manager_ID & email address) and any other fields that occur once per group, a DATABASE field in a normal ‘letter’ or 'email' mailmerge main document could be used without the need for a macro. In this case, the same DATABASE field would be used, but the mailmerge would be connected to the Excel worksheet (or database table) containing just the Manager_IDs and Names. For some working examples of this approach, see:
https://www.msofficeforums.com/mail-merge/37844-mail-merge-using-one-excel-file-multiple.html
https://www.msofficeforums.com/mail-merge/45044-using-mailmerge-include-grouped-information-letter-2.html#post151706
https://www.excelforum.com/excel-general/1273421-merge-excel-list-into-word-receipt.html#post5110813
(the second of these uses a macro to apply some additional formatting).
If you'd like to have each group's mailmerge output from the second approach saved as a separate document/pdf, see the Send Mailmerge Output to Individual Files topic in my Mailmerge Tips & Tricks page: https://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html

"Out of Memory" VBA error after trying to register descriptions of UDFs

I have created a series of VBA mathematical functions in an Excel spreadsheet (i.e. minimisation algorithms). These functions have been tested and they seem to be working properly. I want to add a description of these function and their arguments therefore, based on this question on the topic, I tried to code some subroutines that would achieve that:
First, I created a subroutine to actually encapsulate the descriptions:
Sub RegisterUDF()
myFunctionOneDescription = "Long FunctionOne description" & vbLf _
& "myFunctionOne(<...>, ..., <...>)"
myFunctionOneArguments = Array("FunctionOne argument 1 description", _
"FunctionOne argument 2 description", _
"FunctionOne argument 3 description", _
"FunctionOne argument 4 description", _
"[Optional] FunctionOne argument 5 description")
myFunctionTwoDescription = "Long FunctionTwo description" & vbLf _
& "myFunctionTwo(<...>, ..., <...>)"
myFunctionTwoArguments = Array("FunctionTwo argument 1 description", _
"FunctionTwo argument 2 description", _
"FunctionTwo argument 3 description", _
"FunctionTwo argument 4 description", _
"[Optional] FunctionTwo argument 5 description")
myFunctionThreeDescription = "Long FunctionThree description" & vbLf _
& "myFunctionThree(<...>, ..., <...>)"
myFunctionThreeArguments = Array("FunctionThree argument 1 description", _
"FunctionThree argument 2 description", _
"FunctionThree argument 3 description", _
"FunctionThree argument 4 description", _
"[Optional] FunctionThree argument 5 description")
Application.MacroOptions Macro:="myFunctionOne", Description:=myFunctionOneDescription, ArgumentDescriptions:=myFunctionOneArguments, Category:=9
Application.MacroOptions Macro:="myFunctionTwo", Description:=myFunctionTwoDescription, ArgumentDescriptions:=myFunctionTwoArguments, Category:=9
Application.MacroOptions Macro:="myFunctionThree", Description:=myFunctionThreeDescription, ArgumentDescriptions:=myFunctionThreeArguments, Category:=9
End Sub
Then, I create the following subroutine in the ThisWorkbook object:
Private Sub Workbook_Open()
Call RegisterUDF
End Sub
so that the descriptions are automatically loaded when I open the workbook.
When creating these two subroutines and assessing the look of the function descriptions in the Function UI (namely the one that pops up when you press Ctrl+Shift+A or fx), I started closing and reopening the workbook given descriptions are updated only when Workbook_Open() is executed. Then, at some point I started getting an Out of Memory error immediately after opening the workbook; the error seemed to originate from the third function description above:
I started getting rid of these two subroutines but now I still see the Out of Memory error when I refresh my workbook (whose tabs are populated with instances of my user-defined functions); each time, the Out of Memory error seems to originate in one of my UDFs but not always the same. In addition, when I try to cancel the debugging by resetting VBA, I get a new Out of Memory error immediately after, before having refreshed the workbook or performed any additional action, thus I end trapped in a "loop" of Out of Memory errors and I am forced to close Excel from the Task Manager (1). This had never happened before I tried to code the functions' descriptions.
Can anybody help me in understanding what might be going on? I suspect this is related to the utilisation of Application.MacroOptions but I am unsure. Any help is greatly appreciated.
(1) I suspect this is actually explained by the fact that, when I refresh the workbook or a tab, multiple instances of my UDFs will try to reevaluate hence each Out of Memory error corresponds to one instance of my UDFs.
[EDIT #1] I observe very strange behaviour. For example, on a tab with preexisting instances of my UDFs in some cells, I have tried to evaluate one of my functions in a new cell after having commented out the 2 subroutines described above. When writing down the function in the cell and pressing enter, I got the Out of Memory error originating from the code of that UDF. Then, I deleted from the VBA code the commented subroutines and when pressing enter the function evaluated correctly! However, when refreshing that tab, I then got the same memory error but this time coming from another UDF.
This seems to have been solved by following the procedure outlined below(1):
Delete subroutines RegisterUDF() from module and Workbook_Open() from Workbook object;
Copy all the VBA code from the module(2) into e.g. the notepad;
Delete the workbook's module;
Create a new module in the same workbook;
Paste code into new module.
The Out of Memory errors have ceased after this manipulation, however I still do not know what the origin was in the first place, and I am not sure whether this could happen again if I try to reprogram RegisterUDF() and Workbook_Open(). Any additional explanation to this bug is greatly appreciated.
(1) Other tricks, such as copying the whole workbook; restarting the computer; copying/pasting the code to a new workbook without deleting the old module from the original workbook; etc. did not seem to solve the issue.
(2) All my code was located in a single module.

VBA - Update Linked Table of an Access file from Excel

I am trying to change the linked table address from an Access file "Hey.accdb" using VBA coding from an Excel file.
I've coded the script below in my Excel file and it prompts the error "Object required" when I run it. Can someone please help me with this problem. I've been staring at it for too long. Thanks.
Sub RunMacroinAccesswithPara2()
Set Db = CreateObject("Access.Application")
Db.OpenCurrentDatabase "D:\Database1\Hey.accdb"
Db.Visible = True
Db.AutomationSecurity = msoAutomationSecurityLow
DoCmd.TransferDatabase TransferType:=acLink, _
DatabaseType:="Microsoft Access", _
DatabaseName:="V:\Reporting\Quarterly\2018Q2\JP\Data\04\Database\Valuation_Database.mdb", _
ObjectType:=acTable, _
Source:="Valuation_Database_Adjusted", _
Destination:="Valuation_Database_Adjusted"
End Sub
DoCmd belongs to the Access application object.
So use
Db.DoCmd.TransferDatabase ' etc.
Edit
To update the link, you need the TableDef object, set its .Connect property and run .RefreshLink.
See Linked table ms access 2010 change connection string

Forms with vba code and importing

How to create an access form which has two fields for importing two different excel files, and after selecting excel files press the button to run a query (already exist) and automatically export the query result in excel sheet. I was able to create the vba code (once played the import dialog will pop up waiting the user to enter the file path then pops up another time for the second file, another dialoge for exporting the result to excel. but the problem is how to do it using Forms in Microsoft Access.please give me suggestions or reference.
Agree with Boeckm, your question is a little lacking in detail :-)
If you are asking for the VBA code to fire the macro's you already have then simply create a button and add the following to the [on click] property
Private Sub Excel_button_Click(Cancel As Integer)
DoCmd.SetWarnings False ' Switch off "Are you sure" message
Dim stDocName As String
stDocName = "qry_Import file 1"
DoCmd.OpenQuery stDocName, acNormal, acEdit
stDocName = "qry_Import file 2"
DoCmd.OpenQuery stDocName, acNormal, acEdit
stDocName = "qry_Export file 3"
DoCmd.OpenQuery stDocName, acNormal, acEdit
DoCmd.SetWarnings True ' Switch on "Are you sure" message
End Sub
You can also build this in a single button using the wizzard (select misc, run query and select the first import query. Go back to the button and edit the [embedded macro] adding the others. You can also add the set warning = off to the series if required).

User selects random excel cell, clicks button, macro executes - Bloomberg DDE

I am rather new to macros and new to this forum. I searched the forums and have not found the answer I am looking for. I am writing a macro to launch Bloomberg DDE so when a button is clicked, a terminal window will come to the front with the specific syntax already submitted.
for general sake, let's say that $B$3 = MSFT, $H$2=CSCO, $E$9=GIS
if the user selects MSFT on the spreadsheet and then clicks on the GIP30 button, I want the following sent to the BB terminal:
MSFT GIP30
So in addition to the macro identifying what cell was selected, 'US' may need to be appended before being transmitted to BB DDE. I have take some tidbits from around the web.
Got it to work when I hardcoded "MSFT US", but need it to be dynamic. I commented out the "dynamic" code.
All help is appreciated.
Thanks.
Sub OpenGIP()
Dim ch As Long
ch = DDEInitiate("winblp", "bbk")
'Opens Bloomberg window #2 (Note: <blp-n> - where n is [BB Window instance # - 1])
Call DDEExecute(ch, "<blp-1><home> MSFT US <EQUITY> GIP30 <GO>")
'Call DDEExecute(ch, "<blp-1><home> ActiveCell.Value & ' US' <EQUITY> GIP30 <GO>")
Call DDETerminate(ch)
End Sub
Try this
Call DDEExecute(ch, "<blp-1><home> " & ActiveCell.value & " US <EQUITY> GIP30 <GO>")

Resources