Problem:
I would like to create letters using 2 different letter templates based on a cell value in a column in Excel.
My Question is an extension to the following question:
VBA Automated Mailmerge using 2 templates based on cell value
Example:
In the example below, the value in column C should dictate which letter template will be used for each row. (If cell value is YES use letter template "Yes.docx" otherwise use letter template "No.docx")
Solution proposed by #user3598756 (modified to the above example):
Option Explicit
Sub CommandButton2_Click()
Dim wordApp As Object
Set wordApp = GetWordObject '<--| get a Word object
If wordApp Is Nothing Then Exit Sub '<--| if no Word Object has been gotten then exit sub
With ThisWorkbook.Sheets("Sheet1") '<--| reference your letter worksheet
With Application.Intersect(.UsedRange, Range("A1:C1").EntireColumn) '<--| reference your data range as that in referenced worksheet columns D:H used range
CreateWordDocuments .Cells, "YES", wordApp, "C:\Users\camil\Desktop\YES.docx" '<--| process "YES" documents
CreateWordDocuments .Cells, "NO", wordApp, "C:\Users\camil\Desktop\NO.docx" '<--| process "NO" documents
End With
.AutoFilterMode = False '<--| show all rows back and remove autofilter
End With
'"dispose" Word
wordApp.Quit True '<--| quit Word and save changes to open documents
Set wordApp = Nothing
End Sub
Sub CreateWordDocuments(dataRng As Range, criteria As String, wordApp As Object, templateDocPath As String)
Dim cell As Range
With dataRng '<--| reference data range
.AutoFilter Field:=3, Criteria1:=criteria '<--| filter it on its column 3 with given criteria
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then '<--| if any cell has been filtered
For Each cell In .Offset(1).Resize(.Rows.Count - 1, 1).SpecialCells(xlCellTypeVisible) '<--| loop through filtered cells
wordApp.Documents.Add templateDocPath '<-- open the passed Word template
wordApp.Run "Module1.SaveIndividualWordFiles" '<--| run your macro
Next cell
End If
End With
End Sub
Function GetWordObject() As Object
Dim wordApp As Object
On Error Resume Next
Set wordApp = GetObject(, "Word.Application") '<--| try getting a running Word application
On Error GoTo 0
If wordApp Is Nothing Then Set wordApp = CreateObject("Word.Application") '<--| if no running instance of Word has been found then open a new one
Set GetWordObject = wordApp '<--| return the set Word application
wordApp.Visible = False
End Function
Request:
Unfortunately, the original poster of the question didn't share his "SaveIndividualWordFiles" macro.
I tried to fill in the gap with parts of the VBA I usually use to mailmerge from Word, when I only have one letter template. (Seen below)
However I can't fit the pieces together.
Sub Merge_To_Individual_Files()
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 & Application.PathSeparator
For i = 1 To .MailMerge.DataSource.RecordCount
With .MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
If Trim(.DataFields("Col A")) = "" Then Exit For
StrName = .DataFields("Col A") & " " & .DataFields("Col C")
End With
.Execute Pause:=False
If Err.Number = 5631 Then
Err.Clear
GoTo NextRecord
End If
End With
For j = 1 To Len(StrNoChr)
StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
Next
StrName = Trim(StrName)
With ActiveDocument
.SaveAs FileName:=StrFolder & StrName & ".docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
.SaveAs FileName:=StrFolder & StrName & ".pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
NextRecord:
Next i
End With
Application.ScreenUpdating = False
End Sub
Any help is appreciated.
Related
I have a Word file that has table with 5 columns: Step, Document, Doc #, Compo and Lot #, Sign, Date. I need to search for "Lot #" and "E#" in the word file then get the Step number, the text of row contains the string into an Excel file. I found a code that need to have the keywords in Sheet 1 of Excel then extract the data from Word into Sheet 2 with 1st column as keyword, 2nd column as row number in Word and 3rd column is the text of that row.
Is there any way I can hard code the keywords with options/message box to choose the keyword into VBA module instead of Sheet 1 and get the data in Sheet 1 with 1st column as keyword, 2nd column as the value in Step column in Word and 3rd column is the text of that row?
I'm pretty new to VBA so I don't know how to implement those.
Sub LocateSearchItem()
Dim shtSearchItem As Worksheet
Dim shtExtract As Worksheet
Dim oWord As Word.Application
Dim WordNotOpen As Boolean
Dim oDoc As Word.Document
Dim oRange As Word.Range
Dim LastRow As Long ' last row with data in shtSearchItem
Dim CurrRowShtSearchItem As Long ' current row in shtSearchItem
Dim CurrRowShtExtract As Long ' current row in shtExtract
Dim myPara As Long
On Error Resume Next
Set oWord = GetObject(, "Word.Application")
wdFileName = Application.GetOpenFilename("Word files (*.docx),*.docx", , _
"Browse for file containing table to be imported")
If wdFileName = False Then Exit Sub '(user cancelled import file browser)
Set oDoc = GetObject(wdFileName) 'open Word file
If Err Then
Set oWord = New Word.Application
WordNotOpen = True
End If
On Error GoTo Err_Handler
oWord.Visible = True
oWord.Activate
Set shtSearchItem = ThisWorkbook.Worksheets(1)
If ThisWorkbook.Worksheets.Count < 2 Then
ThisWorkbook.Worksheets.Add After:=shtSearchItem
End If
Set shtExtract = ThisWorkbook.Worksheets(2)
LastRow = shtSearchItem.UsedRange.Rows(shtSearchItem.UsedRange.Rows.Count).Row
For CurrRowShtSearchItem = 2 To LastRow
Set oRange = oDoc.Range
With oRange.Find
.Text = shtSearchItem.Cells(CurrRowShtSearchItem, 1).Text
.MatchCase = False
.MatchWholeWord = True
While oRange.Find.Execute = True
oRange.Select
myPara = oDoc.Range(0, oWord.Selection.Paragraphs(1).Range.End).Paragraphs.Count
CurrRowShtExtract = CurrRowShtExtract + 1
shtExtract.Cells(CurrRowShtExtract, 1).Value = .Text
shtExtract.Cells(CurrRowShtExtract, 2).Value = myPara
shtExtract.Cells(CurrRowShtExtract, 3) = oDoc.Paragraphs(myPara).Range
oRange.Collapse wdCollapseEnd
Wend
End With
Next CurrRowShtSearchItem
If WordNotOpen Then
oWord.Quit
End If
'Release object references
Set oWord = Nothing
Set oDoc = Nothing
Exit Sub
Err_Handler:
MsgBox "Word caused a problem. " & Err.Description, vbCritical, "Error: " & Err.Number
If WordNotOpen Then
oWord.Quit
End If
End Sub
What I got from the current code
I created a code that sopose to take a Word file template and fill it with data from my excel table.
Sub CreateWordDocs()
Dim CustRow, CustCol, LastRow, TemplRow As Long
Dim DocLoc, TagName, TagValue, TemplName, FileName As String
Dim WordDoc, WordApp As Object
With Sheet1
If ActiveCell.Value = Empty Then
MsgBox "pick a different cell"
End If
DocLoc = Sheet2.Range("K2").Value
'Open File
On Error Resume Next 'if Word ia already running
Set WordApp = GetObject("Word.Application")
If Err.Number <> 0 Then
Err.Clear
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
End If
LastRow = .Range("B999").End(xlUp).Row
For CustRow = ActiveCell.Row To LastRow
Set WordDoc = WordApp.Documents.Open(FileName:=DocLoc, ReadOnly:=False)
For CustCol = 2 To 8
TagName = Cells(3, CustCol)
TagValue = Cells(CustRow, CustCol).Value
With WordDoc.Content.find
.Text = TagName
.Replacement.Text = TagValue
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next CustCol
FileName = ThisWorkbook.Path & "\" & .Range("B" & CustRow).Value & ".docx"
WordDoc.SaveAs FileName
Next CustRow
WordDoc.Display
End With
End Sub
when I run the code it just opens Word without creating any file....
I am assuming here:
If ActiveCell.Value = Empty Then
MsgBox "pick a different cell"
End If
you wanted the code to stop executing if the selected cell in your Excel Worksheet was empty. If so, then you need to put a Exit Sub after MsgBox:
If ActiveCell.Value = Empty Then
MsgBox "pick a different cell"
Exit Sub
End If
I am also assuming that you have at least two Worksheets in your Excel doc because of:
Line 5: With Sheet1
Line 11: DocLoc = Sheet2.Range("K2").Value
It seems that you only use Sheet2 in your code to get the path of your Word Template, and everything else (Cells and Range statements) is meant to be referenced to Sheet1.
Even if the above assumptions are correct, it is not clear if you want to close the re-saved Word documents once they are filled.
If you don't close the individual Word docs once they are filled and saved, you may end up having huge amount of Word documents open depending how many Customers you have in your Excel Worksheet.
Your PC may run out of free memory, slows down very much, or who knows.
Based on the above assumptions, I made some changes in your code to make it run.
Let me know if you wanted it to do something else.
Make sure you have Microsoft Word Object Library enabled in VBA Editor, Tools -> References.
Depending on the version of your Office installed, the module to be enabled might have a different version number.
This is the complete code block after the edits:
Sub CreateWordDocs()
Dim CustRow, CustCol, LastRow, TemplRow As Long
Dim DocLoc, TagName, TagValue, TemplName, FileName As String
Dim WordDoc, WordApp As Object
Dim WBook As Workbook
Set WBook = Application.ActiveWorkbook
Dim Sheet1 As Worksheet
Dim Sheet2 As Worksheet
Set Sheet1 = WBook.Worksheets(1)
Set Sheet2 = WBook.Worksheets(2)
With Sheet1
If ActiveCell.Value = "" Then
MsgBox "pick a different cell"
Exit Sub
End If
DocLoc = Sheet2.Range("K2").Value
On Error Resume Next
'Set WordApp = GetObject("Word.Application")
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Err.Clear
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
End If
'LastRow = .Range("B999").End(xlUp).Row
LastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
For CustRow = ActiveCell.Row To LastRow
Set WordDoc = WordApp.Documents.Open(FileName:=DocLoc, ReadOnly:=False)
For CustCol = 2 To 8
TagName = .Cells(3, CustCol).Value
TagValue = .Cells(CustRow, CustCol).Value
With WordDoc.Content.Find
.Text = TagName
.Replacement.Text = TagValue
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next CustCol
FileName = ThisWorkbook.Path & "\" & .Range("B" & CustRow).Value & ".docx"
WordDoc.SaveAs FileName
WordDoc.Close
Next CustRow
'WordDoc.Display
End With
End Sub
I am trying to loop through a number of word documents in a folder, and add some information from the word tables to the excel sheet. Right now I have this:
Private Sub Loop_WordToExcel()
Dim WdApp As Object
Dim wddoc As Object
Dim docName As String
Dim strFile As String
Dim directory As String
directory = "c:\path\to\folder"
strFile = Dir(directory & "*.*")
Set WdApp = CreateObject("Word.Application")
Dim rng As Range
Set rng = Application.InputBox(Prompt:="Enter row", Type:=8)
'Do While strFile <> ""
Set wddoc = WdApp.Documents.Open(Filename:=directory & strFile)
rng.Cells(1) = wddoc.Name
'First Name
wddoc.Tables(1).Cell(1, 3).Range.Copy
rng.Cells(2).PasteSpecial (xlPasteValues)
WdApp.ActiveDocument.Close SaveChanges:=False
strFile = Dir
Loop
End Sub
I have two questions.
1. My first issue is a Run-time error '1004': PasteSpecial method of Range class failed
2. At the end of the loop, how to I advance to the next row for the next word document information to be pasted.
Correct syntax while copying from Word is given, May try
Sub Loop_WordToExcel()
Dim WdApp As Word.Application
Dim WdDoc As Document
Dim docName As String
Dim strFile As String
Dim directory As String
Dim Rng As Range
Dim Offst As Long, Txt As String
directory = "C:\users\user\Desktop\Folder1\" ' Change to your path
strFile = Dir(directory & "*.docx") ' docx extension added to prevent attempt to open other type of files
Set Rng = Application.InputBox(Prompt:="Enter row", Type:=8) '
Set WdApp = CreateObject("Word.Application")
WdApp.Visible = True
Do While strFile <> ""
Set WdDoc = WdApp.Documents.Open(Filename:=directory & strFile)
Rng.Offset(Offst, 0).Value = WdDoc.Name
'First Name
WdDoc.Tables(1).Cell(1, 3).Range.Copy 'will raise error if table& corres cell not exists , My use error handrel
Rng.Offset(Offst, 1).Activate
ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False 'Assumed want get name in Column B
'is is suggested to use the below two lines instead of paste special above three lines
'Txt = WdDoc.Tables(1).Cell(1, 3).Range.Text 'will raise error if table& corres cell not exists , My use error handrel
'Rng.Offset(Offst, 1).Value = Txt
WdDoc.Close SaveChanges:=False
Offst = Offst + 1
strFile = Dir
Loop
WdApp.Quit
End Sub
It is always preferred to add reference of Microsoft Word Object library.
Private Sub Submit_Click()
'----------The Script below writes values to Word Doc ----------------------------------------
Dim wApp As Object
Dim wDoc As Object
'We need to continue through errors since if Word isn't
'open the GetObject line will give an error
'On Error Resume Next
Set wApp = GetObject(, "Word.Application")
'We've tried to get Word but if it's nothing then it isn't open
If wApp Is Nothing Then
Set wApp = CreateObject("Word.Application")
End If
'It's good practice to reset error warnings
On Error GoTo 0
'Open your document and ensure its visible and activate after opening
Set wDoc = wApp.Documents.Open(Filename:="C:\Documents\example.docx ", ReadOnly:=False)
With wDoc
.Bookmarks("bookmark1").Range.Text = Me.TextBox1.Value 'how do I also insert the TextBox1.Value to the next empty row in worksheet?
'so far I got this to do it but everytime i click submit it puts it in the same cell instead of the next row
Sheet6.Range("H2").Value = Me.TextBox6.Value
End With
wApp.Visible = True
'set default file name and file path
ProposedFileName = Format(Now(), "DDMMMYYYY") & TextBox1.Value & "-" & ".doc"
ProposedFilePath = "C:\Documents\"
With wApp.FileDialog(msoFileDialogSaveAs)
wDoc.SaveAs2 ProposedFilePath & ProposedFileName, _
FilterIndex = 1, _
FileFormat:=wdFormatDocument
End With
End Sub
Hi all,
The code above is just a part of my script which works fine when the userform textbox value gets inserted to bookmark1 in word doc, but how do I also insert this textbox value to worksheet row for example goes under column header "name"?
Thank you.
I have finally managed to solve it by adding the code
Dim LastRow As Long, ws As Worksheet
Set ws = Sheets(2)
LastRow = ws.Range("A" & Rows.Count).End(xlUp).Row + 1 'Finds the last blank row
ws.Range("A" & LastRow).Value = TextBox1.Value 'Adds the TextBox1 into Col A & Last Blank Row
I made a nice Excel file with several (almost the same) macros. Goal is to fill open a Word template, fill in the bookmarks and save every individual document with predefined fields in the filename. Works like a charm... but it doesn't go further then the 10th row of my Excel file. All 12 macros have the same issue, basically the macro is the same only the fields are different.
The VBA I have now is this:
Option Explicit
Sub Akkoordverklaring()
Dim lonLaatsteRij As Long
Dim rngData As Range
Dim strVoornaam As String, strAchternaam As String, strSlber As String
Dim c As Range
With Sheets("Cijferlijst")
lonLaatsteRij = .Cells(Rows.Count, "A").End(xlUp).Row
Set rngData = .Range(.Cells(2, 1), .Cells(lonLaatsteRij, 1))
End With
For Each c In rngData
strVoornaam = c.Value
strAchternaam = c.Offset(0, 1).Value
strSlber = c.Offset(0, 12).Value
Call maakWordDocument(strVoornaam, strAchternaam, strSlber)
Next c
End Sub
Private Sub maakWordDocument(strVoornaam As String, strAchternaam As String, _
strSlber As String)
Dim wordApp As Object, WordDoc As Object
On Error Resume Next
Set wordApp = GetObject("", "Word.Application")
If wordApp Is Nothing Then
Set wordApp = CreateObject("Word.Application")
End If
wordApp.Visible = False
Set WordDoc = wordApp.Documents.Open(ThisWorkbook.Path & _
"Formulieren\Akkoordverklaring.docx")
Call InvullenBladwijzer(wordApp, "voornaam", strVoornaam)
Call InvullenBladwijzer(wordApp, "achternaam", strAchternaam)
Call InvullenBladwijzer(wordApp, "slber", strSlber)
wordApp.DisplayAlerts = False
WordDoc.SaveAs Filename:=ThisWorkbook.Path & _
"Akkoordverklaring\Akkoordverklaring " & strVoornaam & Space(1) & _
strAchternaam, FileFormat:=wdFormatDocumentDefault
WordDoc.Close
wordApp.Quit
Set WordDoc = Nothing
Set wordApp = Nothing
End Sub
Sub InvullenBladwijzer(wordApp As Object, strBladwijzer As String, _
strTekst As String)
wordApp.Selection.Goto What:=wdGoToBookmark, Name:=strBladwijzer
wordApp.Selection.TypeText strTekst
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
As I'm not a programmer I just know how to read some VBA. Some users in here also helped me out with the VBA above:
Excel: change VBA action frome same sheet to another sheet