Open Active Workbook - vba

I have VBA code that should pick up the active workbook (and use the data to open a Word Document and leave the mail merged document open ready for review/saving).
It worked once but now it isn't picking up the open spreadsheet. It opens a 'Select Table' window of which the only option is the XLSTART.xls spreadsheet with no data.
How do I pick up the active workbook?
Sub Mailmerge()
Dim wd As Object
Dim wdocSource As Object
Application.DisplayAlerts = False
' Word constants
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Dim strWorkbookName As String
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wdocSource = wd.Documents.Open("File Name for Mail Merge doc, this bit works when not redacted!")
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdocSource.Mailmerge.MainDocumentType = wdFormLetters
wdocSource.Mailmerge.OpenDataSource _
Name:=strWorkbookName, _
AddToRecentFiles:=True, _
Revert:=False, _
Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet2$`"
With wdocSource.Mailmerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.Visible = True
wdocSource.Close SaveChanges:=False
Set wdocSource = Nothing
Set wd = Nothing
End Sub

Related

dataSource.RecordCount in a mailMerge

I'm trying to use a macro I found online to save each doc from a mail merge into an individual PDF. But the macro does nothing. (never used macros before or VB) I tried stepping through the code and I get .DataSource.RecordCount = -1.
I can see the previewed documents, so the datasource is there. I figure there is something wrong with how it's getting the count value.
Any help is appreciated.
This is the whole macro:
Sub Merge_To_Individual_Files()
' Sourced from: https://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html
Application.ScreenUpdating = False
Dim StrFolder As String, StrName As String, MainDoc As Document, i As Long, j As Long
Const StrNoChr As String = """*./\:?|"
Set MainDoc = ActiveDocument
With MainDoc
StrFolder = .Path & "\"
With .MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
On Error Resume Next
For i = 1 To .DataSource.RecordCount
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
If Trim(.DataFields("Last_Name")) = "" Then Exit For
'StrFolder = .DataFields("Folder") & "\"
StrName = .DataFields("key")
End With
On Error GoTo NextRecord
.Execute Pause:=False
For j = 1 To Len(StrNoChr)
StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
Next
StrName = Trim(StrName)
With ActiveDocument
'Add the name to the footer
'.Sections(1).Footers(wdHeaderFooterPrimary).Range.InsertBefore StrName
.SaveAs FileName:=StrFolder & StrName & ".docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
' and/or:
.SaveAs FileName:=StrFolder & StrName & ".pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
NextRecord:
Next i
End With
End With
Application.ScreenUpdating = True
End Sub

Getting error 5630

I want to send emails using mail merge from excel for selected records. If there is no email id then there is a dash sign in email id field. I'm getting a runtime error 5630:
Run-time error ‘5630’: excel cannot merge documents that can be
distributed by mail or fax without a valid mail address. Choose the
setup button to select a mail address data field.
option explicit
Sub MailMergeEmail()
'Note: this code requires a reference to the Word object model
Dim StrMMSrc As String, wdApp As New Word.Application, wdDoc As Word.Document, i As Long
Dim FirstRecord As Long, LastRecord As Long, DocName As String
wdApp.Visible = False
StrMMSrc = ThisWorkbook.FullName
Set wdDoc = wdApp.Documents.Open(Filename:=ThisWorkbook.Path & "\INPUT\ABCD COMPANY.docx", _
AddToRecentFiles:=False, ReadOnly:=True, Visible:=False)
With wdDoc
With .MailMerge
.MainDocumentType = wdFormLetters
.OpenDataSource Name:=StrMMSrc, ReadOnly:=True, AddToRecentFiles:=False, _
LinkToSource:=False, Connection:="Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;" & _
"Data Source=StrMMSrc;Mode=Read;Extended Properties=""HDR=YES;IMEX=1"";", _
SQLStatement:="SELECT * FROM `Data$`"
For i = FirstRecord To LastRecord
.Destination = wdSendToEmail
.SuppressBlankLines = True
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
End With
.MailFormat = wdMailFormatHTML
.MailSubject = "Test"
.MailAddressFieldName = "E-MAIL ID"
.Execute Pause:=False
Next i
.MainDocumentType = wdNotAMergeDocument
End With
.Close SaveChanges:=False
End With
wdApp.Quit
Set wdDoc = Nothing: Set wdApp = Nothing
Application.ScreenUpdating = False
MsgBox "done"
End Sub
[/code]

Any other method to solve "automation error"

I was able to successfully complete (with so much help from a stack exchange user) a macro to automatically mail merge a word document from excel. But the problem now is, unless the word document is open, I get an automation error.
Right now, I solve it by just opening the word document every time, but I doubt that is the right programming method.
Any suggestions to overcome this error? I am very new to VBA. This is part of my student assignments. Any advise or code changes to help overcome this error? I read the official msdn docs, did not understand a thing. :'(
The error is usually "automation error - with a cross sign" or this one:
http://imgur.com/a/zitah
For both these errors, solution so far was to open the word document first and then run macro.
Update:
I removed "on error..." part and now the error is this:
http://imgur.com/a/epmGR
The program is as follows:
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Sub RunMerge2()
Dim wd As Object, wdocSource As Object
Dim sh As Worksheet
Dim Lrow As Long, i As Long
Dim cdir As String, client As String, newname As String
Dim sSQL As String
cdir = "C:\Users\Kamlesh\Desktop\"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wdocSource = wd.Documents.Open(cdir & "\master\installers.docx")
Set sh = ActiveSheet
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
With sh
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To Lrow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
client = .Cells(i, 1).Value
newname = "Installer Instructions - " & client & ".docx"
wdocSource.MailMerge.MainDocumentType = wdFormLetters
'~~> Sample String
sSQL = "SELECT * FROM `Sheet1$` WHERE [Client Name] = '" & .Range("A" & i).Value & "'"
wdocSource.MailMerge.OpenDataSource Name:=strWorkbookName, _
AddToRecentFiles:=False, Revert:=False, Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:=sSQL
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.ActiveDocument.SaveAs cdir & newname
wd.ActiveDocument.Close SaveChanges:=False
End If
Next i
End With
wdocSource.Close SaveChanges:=False
'wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
End Sub
this line
Set wdocSource = wd.Documents.Open(cdir & "\master\installers.docx")
should be
Set wdocSource = wd.Documents.Open(cdir & "master\installers.docx")
and
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
can be replaced with
strWorkbookName = ThisWorkbook.FullName
To find what part of the code is causing the error, in Tools > Options > Editor tab check everything
(source: windows.net)
and in the General tab check everything and select Break in Class Module
(source: s-msft.com)
.aspx#odc_ac2007_ta_ErrorHandlingAndDebuggingTipsForAccessVBAndVBA_BasicErrorHandling)

Selecting only one row from a excel sheet (as part of mail merge)

I am totally new to VBA and I am writing a code to mail merge data from each row in an excel sheet to a certain word document and save that document with name corresponding to the first cell value from each row.
Each row contains the information of a client. That is why I have to mailmerge each row info seperately.
So far the code works fine, but two problems I need to solve:
1) SQLStatement:="SELECT * FROMSheet1$" ends up mail merging info from all the rows in sheet during each iteration of the for loop (the loop iterates through each row). So what happens is that, each client's document includes data of other clients (excel rows) as well.
2) The usual automation error unless I keep the source word document open.
So can someone please tell me how to select the info from only the row where the iteration has reached.
I triedSQLStatement:="SELECT rw.row* FROMSheet1$" But it does not work
Any help would be good.
The full code is:
Sub RunMerge()
'booking document begins here
Dim wd As Object
Dim wdocSource As Object
Dim activedoc
Dim strWorkbookName As String
Dim x As Integer
Dim cdir As String
Dim client As String
Dim sh As Worksheet
Dim rw As Range
Dim rowcount As Integer
Set sh = ActiveSheet
For Each rw In sh.Rows
If sh.Cells(rw.Row, 1).Value = "" Then
Exit For
End If
cdir = "C:\Users\Kamlesh\Desktop\"
client = Sheets("Sheet1").Cells(rw.Row + 1, 1).Value
Dim newname As String
newname = "Offer Letter - " & client & ".docx"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Set wdocSource = wd.Documents.Open("C:\Users\Kamlesh\Desktop\master\Regen-booking.docx")
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdocSource.MailMerge.MainDocumentType = wdFormLetters
wdocSource.MailMerge.OpenDataSource _
Name:=strWorkbookName, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet1$`"
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.Visible = True
wd.ActiveDocument.SaveAs cdir + newname
'wdocSource.Close SaveChanges:=False
'wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
Next rw
End Sub
My Excel Sheet looks like this
Try this. Obviously this is untested as I do not know your header names and values
SQLStatement:="SELECT * FROM `Sheet1$` WHERE SomeField = 'SomeUniqueValue'"
Something like
SQLStatement:="SELECT * FROM `Sheet1$` WHERE Client = " & Range("A" & rw + 1).Value & "'"
Replace "A" by the actual column
Replace "Client" by the actual header of the column
Also like I mentioned in the comment below the question, why are you creating and destroying objects in the loop? You can instantiate the Word Application out of the For loop. And you can destroy it out of the For Loop.
Is this what you are trying? (UNTESTED)
Change sSQL = "SELECT * FROMSheet1$WHERE [Client Name] = '" & .Range("A" & i).Value & "'" in the below code as per your requirements.
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Sub RunMerge()
Dim wd As Object, wdocSource As Object
Dim sh As Worksheet
Dim Lrow As Long, i As Long
Dim cdir As String, client As String, newname As String
Dim sSQL As String
cdir = "C:\Users\Kamlesh\Desktop\"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wdocSource = wd.Documents.Open(cdir & "\master\Regen-booking.docx")
Set sh = ActiveSheet
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
With sh
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To Lrow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
client = .Cells(i, 1).Value
newname = "Offer Letter - " & client & ".docx"
wdocSource.MailMerge.MainDocumentType = wdFormLetters
'~~> Sample String
sSQL = "SELECT * FROM `Sheet1$` WHERE [Client Name] = '" & .Range("A" & i).Value & "'"
wdocSource.MailMerge.OpenDataSource Name:=strWorkbookName, _
AddToRecentFiles:=False, Revert:=False, Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:=sSQL
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.ActiveDocument.SaveAs cdir & newname
wd.ActiveDocument.Close SaveChanges:=False
End If
Next i
End With
wdocSource.Close SaveChanges:=False
wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
End Sub

Run-time Error 91 : Object variable or With block variable not set

I have 2 separate word documents with Mail Merge lists. And I have an excel workbook with 2 sheets. Based on the worksheet name & if the sheet is not empty, I need to send the mailmerge to that respective word document(s).
When I try to execute this code, it runs upto the first document and at the second document, it stops with an error Run-time Error 91 : Object variable or With block variable not set
I'm not sure what's causing this error (if it's the Dim variable or With block). Would greatly appreciate if someone could kindly help me rectify this error.
Sub Generate_Certificate()
Dim wd As Object
Dim wdoc_reg As Object
Dim wdoc_occ As Object
Dim strWbName_reg As String
Dim strWbName_occ As String
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdFormLetters1 = 0, wdOpenFormatAuto1 = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Const wdSendToNewDocument1 = 0, wdDefaultFirstRecord1 = 1, wdDefaultLastRecord1 = -16
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error Goto 0
For Each Sheet In ActiveWorkbook.Sheets
'Generate report using "Mailmerge" if any data available for Mailmerge1
If Sheet.Name Like "Sheet1" And IsEmpty(ThisWorkbook.Sheets("Sheet1").Range("A2").Value) = False Then
Set wdoc_reg = wd.Documents.Open("C:\Mailmerge1.docx")
strWbName_reg = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdoc_reg.MailMerge.MainDocumentType = wdFormLetters
wdoc_reg.MailMerge.OpenDataSource _
Name:=strWbName_reg, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWbName_reg & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet1$`"
With wdoc_reg.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.Visible = True
wdoc_reg.Close SaveChanges:=False
Set wdoc_reg = Nothing
Set wd = Nothing
End If
'Generate report using "Mailmerge" if any data available for Mailmerge2
If Sheet.Name Like "Sheet2" And IsEmpty(ThisWorkbook.Sheets("Sheet2").Range("A2").Value) = False Then
Set wdoc_occ = wd.Documents.Open("C:\Mailmerge2.docx")
strWbName_occ = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdoc_occ.MailMerge.MainDocumentType = wdFormLetters1
wdoc_occ.MailMerge.OpenDataSource _
Name:=strWbName_Occ, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto1, _
Connection:="Data Source=" & strWbName_occ & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet2$`"
With wdoc_occ.MailMerge
.Destination = wdSendToNewDocument1
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord1
.LastRecord = wdDefaultLastRecord1
End With
.Execute Pause:=False
End With
wd.Visible = True
wdoc_occ.Close SaveChanges:=False
Set wdoc_Occ = Nothing
Set wd = Nothing
End If
Next
End Sub
As stated by Tim Williams in the question's comments.
You have Set wd = Nothing inside your loop, which will clear your reference to Word after the first sheet. Move that to just before the End Sub