VBA Loop not sending data to word in a consistent way - vba

I have the below code that goes through a simple spreadsheet for now and paste the organisation,
one table a single cell value and a chart into a word template. The code runs and produces both a word and pdf version correctly. But what I see is that the table is on occasion ended up where the organisation should be and the chart is being repeated in the document. Each output of the loop seems to vary and I can't work out if the information is not being cleared from the clipboard before it gets pasted. Do I need to run the sections into sub sections or something?
Appreciate the help.
Sub CreateBasicWordReport()
Dim WdApp As Word.Application
Dim wdDoc As Word.Document
Dim SaveName As String
Dim FileExt As String
Dim LstObj1 As ListObject
Dim MaxValue As Integer
Dim FilterValue As Integer
Dim Organisation As String
Dim Rng As Range
Dim WS As Worksheet
Set LstObj1 = Worksheets("Sheet1").ListObjects("Table1")
MaxValue = WorksheetFunction.Max(LstObj1.ListColumns(1).Range)
FilterValue = MaxValue
Set WdApp = CreateObject("Word.Application")
Do Until FilterValue = 0
Application.DisplayAlerts = False
Sheets.Add(After:=Sheets("Sheet1")).Name = "Static"
Sheets("Sheet1").Select
'moved outside of loop
' Set WdApp = CreateObject("Word.Application")
With WdApp
.Visible = True
.Activate
'create new document and assign to object variable
Set wdDoc = .Documents.Add("C:\Users\david\Documents\Custom Office Templates\Template2.dotx")
'now mostly finished with WdApp as from here wdDoc is used
End With
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:=FilterValue
Range("F11").Select
Range("A1", Range("A1").End(xlDown).End(xlToRight)).Copy
' .Selection.GoTo what:=-1, Name:="TableLocation"
' .Selection.Paste
wdDoc.Bookmarks("TableLocation").Range.Paste
For Each Row In Range("Table1[#All]").Rows
If Row.EntireRow.Hidden = False Then
If Rng Is Nothing Then Set Rng = Row
Set Rng = Union(Row, Rng)
End If
Next Row
Set WS = Sheets("Static")
Rng.Copy Destination:=WS.Range("A1")
' Sheets("Static").Select
' Sheets("Static").Activate
Organisation = WS.Range("D2").Value
' Sheets("Static").Select
' Range("D2").Copy
WS.Range("D2").Copy
' .Selection.GoTo what:=-1, Name:="Organisation"
' .Selection.PasteAndFormat wdFormatPlainText
wdDoc.Bookmarks("Organisation").Range.PasteAndFormat wdFormatPlainText
Application.CutCopyMode = False
' Sheets("Static").Select
' Range("F2").Copy
WS.Range("F2").Copy
' .Selection.GoTo what:=-1, Name:="MalePatients"
' .Selection.PasteAndFormat wdFormatPlainText
wdDoc.Bookmarks("MalePatients").Range.PasteAndFormat wdFormatPlainText
Application.CutCopyMode = False
Chart2.ChartArea.Copy
' .Selection.GoTo what:=-1, Name:="ChartLocation"
' .Selection.Paste
wdDoc.Bookmarks("ChartLocation").Range.Paste
If WdApp.Version <= 11 Then
FileExt = ".doc"
Else
FileExt = ".docx"
End If
SaveName = Environ("UserProfile") & "\Desktop\Report for " & _
Organisation & " " & _
Format(Now, "yyyy-mm-dd hh-mm-ss") & FileExt
If WdApp.Version <= 12 Then
' .ActiveDocument.SaveAs SaveName
wdDoc.SaveAs SaveName
Else
' .ActiveDocument.SaveAs2 SaveName
wdDoc.SaveAs2 SaveName
End If
SaveNamePDF = Environ("UserProfile") & "\Desktop\Report " & _
Organisation & " " & _
Format(Now, "yyyy-mm-dd hh-mm-ss") & ".pdf"
wdDoc.ExportAsFixedFormat _
OutputFileName:=SaveNamePDF, _
ExportFormat:=wdExportFormatPDF _
wdDoc.Close
FilterValue = FilterValue - 1
Sheets("Static").Delete
Application.DisplayAlerts = True
Loop
WdApp.Quit
Set WdApp = Nothing
End Sub

You may or may not want to take this as an answer to your question, but here are some ways you can improve your code so as to gain better control over how it operates. It is not a "solution" in the sense of a completed, correctly working code module, but if you adopt this advice it should enable you to solve the issue yourself (along with many other issues you might otherwise encounter in the future).
(1) Avoid using Copy and Paste. As you correctly note, those put you at the mercy of the Windows clipboard. Instead, assign the source object or value to a variable, then insert the contents of the variable at the destination. For instance:
Organisation = WS.Range("D2").Value
wdDoc.Bookmarks("Organisation").Range.Text = Organisation
Now you are able to control what is inserted at the destination point. Among other things, you can reset the variable at the end of each loop, so that there is no risk of repeatedly inserting an object or value that may be carried over from one loop cycle to the next.
(2) Use With ... End With to explicitly specify the parents of your objects. That way you don't risk accidentally referencing a different object than you expected. For instance, in this excerpt from your code ...
With WdApp
Set wdDoc = .Documents.Add("C:\Users\david\Documents\Custom Office Templates\Template2.dotx")
End With
Range("A1", Range("A1").End(xlDown).End(xlToRight)).Copy
... the range copied in the last line may not be what you expect. If the active object at the moment is your newly minted Word doc, the Range object may be interpreted as some range in the document, rather than the spreadsheet range you wanted to copy.
To stay in control, use With consistently:
With WdApp
Set wdDoc = .Documents.Add("C:\Users\david\Documents\Custom Office Templates\Template2.dotx")
End With
With MyWorkbook.Sheets("MySheet")
Set MyTableRange = .Range("A1", .Range("A1").End(xlDown).End(xlToRight))
End With
That's just a couple of pointers, but these are basic good coding practices that you should adopt. I think they will help you resolve the issues with your code.

The issues you are seeing are likely being caused by using the clipboard. There can be a delay when copying and pasting larger items, e.g. tables of data, charts.
When you use the clipboard you are passing some control over to the OS. VBA includes a function, DoEvents that passes control to the operating system. Control is then returned after the operating system has finished processing the events in its queue. By adding this after each copy/paste it should allow things to catch up.
You can also slightly reduce your use of the clipboard by setting the values for 'Organisation' and 'Male Patients' directly.
Sub CreateBasicWordReport()
Dim WdApp As Word.Application
Dim wdDoc As Word.Document
Dim SaveName As String
Dim FileExt As String
Dim LstObj1 As ListObject
Dim MaxValue As Integer
Dim FilterValue As Integer
Dim Organisation As String
Dim Rng As Range
Dim WS As Worksheet
Application.DisplayAlerts = False
Set LstObj1 = Worksheets("Sheet1").ListObjects("Table1")
MaxValue = WorksheetFunction.Max(LstObj1.ListColumns(1).Range)
FilterValue = MaxValue
Set WdApp = CreateObject("Word.Application")
Do Until FilterValue = 0
Sheets.Add(After:=Sheets("Sheet1")).Name = "Static"
Sheets("Sheet1").Select
With WdApp
.Visible = True
.Activate
'create new document and assign to object variable
Set wdDoc = .Documents.Add("C:\Users\david\Documents\Custom Office Templates\IBD Registry Quarterly Report Template2.dotx")
'now mostly finished with WdApp as from here wdDoc is used
End With
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:=FilterValue
Range("F11").Select
Range("A1", Range("A1").End(xlDown).End(xlToRight)).Copy
wdDoc.Bookmarks("TableLocation").Range.Paste
DoEvents
For Each Row In Range("Table1[#All]").Rows
If Row.EntireRow.Hidden = False Then
If Rng Is Nothing Then Set Rng = Row
Set Rng = Union(Row, Rng)
End If
Next Row
Set WS = Sheets("Static")
Rng.Copy Destination:=WS.Range("A1")
Application.CutCopyMode = False
DoEvents
Organisation = WS.Range("D2").Value
wdDoc.Bookmarks("Organisation").Range.Text = Organisation
wdDoc.Bookmarks("MalePatients").Range.Text = WS.Range("F2").Text
Chart2.ChartArea.Copy
wdDoc.Bookmarks("ChartLocation").Range.Paste
DoEvents
Application.CutCopyMode = False
If CLng(WdApp.Version) <= 11 Then
FileExt = ".doc"
Else
FileExt = ".docx"
End If
SaveName = Environ("UserProfile") & "\Desktop\IBD Registry Quarterly Report for " & _
Organisation & " " & _
Format(Now, "yyyy-mm-dd hh-mm-ss")
SaveNamePDF = SaveName & ".pdf"
SaveName = SaveName & FileExt
If CLng(WdApp.Version) <= 12 Then
wdDoc.SaveAs SaveName
Else
wdDoc.SaveAs2 SaveName
End If
wdDoc.ExportAsFixedFormat _
OutputFileName:=SaveNamePDF, _
ExportFormat:=wdExportFormatPDF _
wdDoc.Close
FilterValue = FilterValue - 1
Sheets("Static").Delete
Application.DisplayAlerts = True
Loop
WdApp.Quit
Set WdApp = Nothing
End Sub

Related

copying different excel files rows in one folder with similar A1 cell into one master file via vba (code not working)

Unfortunately I'm not much of a VBA expert, however I have managed to gather these codes from different websites.
I'm trying to get an Automation System running in excel and currently I'm able to send specific rows from an Excel sheet as attachment to each email mentioned in that row. Using this code:
Sub Send_Row_direct()
Dim OutApp As Object
Dim OutMail As Object
Dim rng As Range
Dim Ash As Worksheet
Dim Cws As Worksheet
Dim Rcount As Long
Dim Rnum As Long
Dim FilterRange As Range
Dim FieldNum As Integer
Dim NewWB As Workbook
Dim TempFilePath As String
Dim TempFileName As String
Dim FileExtStr As String
Dim FileFormatNum As Long
On Error GoTo cleanup
Set OutApp = CreateObject("Outlook.Application")
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
'Set filter sheet, you can also use Sheets("MySheet")
Set Ash = ActiveSheet
'Set filter range and filter column (column with e-mail addresses)
Set FilterRange = Ash.Range("A1:AF" & Ash.Rows.Count)
FieldNum = 2 'Filter column = B because the filter range start in column A
'Add a worksheet for the unique list and copy the unique list in A1
Set Cws = Worksheets.Add
FilterRange.Columns(FieldNum).AdvancedFilter _
Action:=xlFilterCopy, _
CopyToRange:=Cws.Range("A1"), _
CriteriaRange:="", Unique:=False
'Count of the unique values + the header cell
Rcount = Application.WorksheetFunction.CountA(Cws.Columns(1))
'If there are unique values start the loop
If Rcount >= 2 Then
For Rnum = 2 To Rcount
'If the unique value is a mail addres create a mail
If Cws.Cells(Rnum, 1).Value Like "?*#?*.?*" Then
'Filter the FilterRange on the FieldNum column
FilterRange.AutoFilter Field:=FieldNum, _
Criteria1:=Cws.Cells(Rnum, 1).Value
'Copy the visible data in a new workbook
With Ash.AutoFilter.Range
On Error Resume Next
Set rng = .SpecialCells(xlCellTypeVisible)
On Error GoTo 0
End With
Set NewWB = Workbooks.Add(xlWBATWorksheet)
rng.Copy
With NewWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial Paste:=xlPasteValues
.Cells(1).PasteSpecial Paste:=xlPasteFormats
.Cells(1).Select
Application.CutCopyMode = False
End With
'Create a file name
TempFilePath = Environ$("temp") & "\"
TempFileName = "KBB_taskforce_assignment_on_" _
& " " & Format(Now, "dd-mmm-yy h-mm-ss")
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007-2016
FileExtStr = ".xlsx": FileFormatNum = 51
End If
'Save, Mail, Close and Delete the file
Set OutMail = OutApp.CreateItem(0)
With NewWB
.SaveAs TempFilePath & TempFileName _
& FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = Cws.Cells(Rnum, 1).Value
.Subject = Range("F2")
.Attachments.Add NewWB.FullName
.Body = Range("G2")
.send 'Or use Send
End With
On Error GoTo 0
.Close savechanges:=False
End With
Set OutMail = Nothing
Kill TempFilePath & TempFileName & FileExtStr
End If
'Close AutoFilter
Ash.AutoFilterMode = False
Next Rnum
End If
cleanup:
Set OutApp = Nothing
Application.DisplayAlerts = False
Cws.Delete
Application.DisplayAlerts = True
With Application
.EnableEvents = True
.ScreenUpdating = True
End With End Sub
Lets say the emails come back with the attachments and I have saved them all in one Folder.
Now I need a VBA code to read through these attachments, which all are stored in a folder, and show the rows which have similar values in cell A2.
The current code that I have managed to setup does the job perfectly with any other Excel file. But when it starts processing the auto made files by my VBA code it runs into Error 91. The line which the error is at is CopyRange.Select
and when removing it I will get another error at CopyRange.Copy MasterSht.Cells(MasterWBShtLstRw + 1, 1) and when removing this line I will get no rows copied into my master file.
The Code is below :
Option Explicit Sub CopyToMasterFile11()
Dim MasterWB As Workbook
Dim MasterSht As Worksheet
Dim MasterWBShtLstRw As Long
Dim FolderPath As String
Dim TempFile
Dim CurrentWB As Workbook
Dim CurrentWBSht As Worksheet
Dim CurrentShtLstRw As Long
Dim CurrentShtRowRef As Long
Dim CopyRange As Range
Dim ProjectNumber As String
FolderPath = "d:\test\"
TempFile = Dir(FolderPath)
Dim WkBk As Workbook
Dim WkBkIsOpen As Boolean
'Check is master is open already
For Each WkBk In Workbooks
If WkBk.Name = "master.xlsm" Then WkBkIsOpen = True
Next WkBk
If WkBkIsOpen Then
Set MasterWB = Workbooks("master.xlsm")
Set MasterSht = MasterWB.Sheets("here")
Else
Set MasterWB = Workbooks.Open(FolderPath & "master.xlsm")
Set MasterSht = MasterWB.Sheets("here")
End If
ProjectNumber = MasterSht.Cells(1, 1).Value
Do While Len(TempFile) > 0
'Checking that the file is not the master and that it is a xlsx
If Not TempFile = "master.xlsm" And InStr(1, TempFile, "xlsx", vbTextCompare) Then
Set CopyRange = Nothing
'Note this is the last used Row, next empty row will be this plus 1
With MasterSht
MasterWBShtLstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Set CurrentWB = Workbooks.Open(FolderPath & TempFile)
Set CurrentWBSht = CurrentWB.Sheets("Tabelle1")
With CurrentWBSht
CurrentShtLstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
For CurrentShtRowRef = 1 To CurrentShtLstRw
' If CurrentWBSht.Cells(CurrentShtRowRef, "A").Value = ProjectNumber Then
'This is set to copy from Column A to Column L as per the question
If CopyRange Is Nothing Then
'If there is nothing in Copy range then union wont work
'so first row of the work sheet needs to set the initial copyrange
Set CopyRange = CurrentWBSht.Range("A" & CurrentShtRowRef & _
":AF" & CurrentShtRowRef)
Else
'Union is quicker to be able to copy from the sheet once
Set CopyRange = Union(CopyRange, CurrentWBSht.Range("A" & CurrentShtRowRef & ":AF" & CurrentShtRowRef))
End If ' ending If CopyRange Is Nothing ....
' End If ' ending If CurrentWBSht.Cells....
Next CurrentShtRowRef
CopyRange.Select
'add 1 to the master file last row to be the next open row
CopyRange.Copy MasterSht.Cells(MasterWBShtLstRw + 1, 1)
CurrentWB.Close savechanges:=False
End If 'ending If Not TempFile = "zmaster.xlsx" And ....
TempFile = Dir
Loop
End Sub
I hope I was able to explain my self properly. I would highly appreciate any productive solution.

Error On Second Iteration: Application-defined or object-defined error

This year I inherited support of about a dozen accdb applications in Office 2010 Win 7 that often manipulate external excel files.
I keep getting the same error scenario. It is in my vba for excel commands,
but only AFTER the first iteration of a loop. It always works fine the first time through. Seems to have something to do with how I am identifying the objects. I've read multiple articles on best practices for working with the objects and the specific error but nothing has translated into a solution. Can someone ELI5 what I am doing wrong?
In the example below it is throwing the error early in the second iteration at the Range("A1").Select command.
Code:
Sub runCleanAndImportUnpre()
Dim strFolder As String
Dim strTableDest As String
strTableDest = "Unpresented_EOD_Import"
strFolder = "C:\Users\lclambe\Projects\Inputs\test2"
Call CleanAndImportUnpresentedInAGivenFolder(strTableDest, strFolder)
End Sub
Function CleanAndImportUnpresentedInAGivenFolder(strTable As String, strFolder As String)
' Function that opens files in a folder, cleans them up and saves them.
Dim myfile
Dim mypath
Dim strPathFileName As String
Dim i As Integer
'Call ClearData(strTable)
'if it needs a backslash on the end, add one
If Right(strFolder, 1) <> "\" Then
strFolder = strFolder & "\"
End If
mypath = strFolder
ChDir (strFolder)
myfile = Dir(mypath)
ChDir (mypath)
myfile = Dir("")
i = 1
Do While myfile <> ""
'Format the excel report
strPathFileName = mypath & myfile
'use for unpresented
Call formatExcelUnPresentedForImport(strPathFileName)
i = i + 1
myfile = Dir()
Loop
End Function
Function formatExcelUnPresentedForImport(filePath As String)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Note:
' Called from CleanAndImportUnpresentedInAGivenFolder when
' importing Unpresented reports
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error GoTo formatExcelUnPresentedForImport_Error
Dim strFilePath As String
Dim strReportType As String
Dim i As Integer
Dim iTotal_Row
Dim Lastrow As Long
Dim iCol As Integer
Dim appExcel As excel.Application
Dim wkb As excel.Workbook
Dim sht As Worksheet
Dim rng As Range
strReportType = reportType
strFilePath = filePath
Set appExcel = New excel.Application
appExcel.Visible = False
'Define the worksheet
Set wkb = appExcel.Workbooks.Open(strFilePath, ReadOnly:=False)
'Turn off error msg: "minor loss of fidelity" if you are sure no data will be lost
wkb.CheckCompatibility = False
'Expand Column to avoid scientific notation
appExcel.Columns("A:A").EntireColumn.AutoFit
'Find last row
'FAILS HERE ON SECOND ITERATION OF LOOP:
Range("A1").Select
ActiveCell("A1").Select
Selection.End(xlDown).Select
'Delete the last 3 rows of totals
ActiveCell.offset(-2, 0).Select
Selection.EntireRow.Delete
Selection.EntireRow.Delete
Selection.EntireRow.Delete
'Add a TRIM of Cash Amount Field2 at column L
Range("L2").Select
ActiveCell.FormulaR1C1 = "=TRIM(RC[-9])"
Range("L2").Select
'Copy it to rest of cells to bottom
Selection.Copy
Lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Selection.AutoFill Destination:=Range("L2:L" & Lastrow), Type:=xlFillDefault
Range("L2:L" & Lastrow).Select
'Delete original unformatted unpresented
Selection.Copy
ActiveSheet.Paste
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Delete all the rows except Unpresented
Range("B:B,C:C,D:D,E:E,F:F,G:G,H:H,I:I,J:J,K:K").Select
Range("K1").Activate
Selection.Delete Shift:=xlToLeft
'Add a Header
Range("B1").Select
ActiveCell.FormulaR1C1 = "Unpresented"
wkb.Save
wkb.Close
appExcel.Quit
Set wkb = Nothing
Set appExcel = Nothing
On Error GoTo 0
Exit Function
formatExcelUnPresentedForImport_Error:
Set wkb = Nothing
Set appExcel = Nothing
strMessage = "Error " & err.Number & " (" & err.Description & ") in procedure formatExcelUnPresentedForImport of Module modExternalExcelClean."
strMessage = strMessage & " Application will stop processing now." & vbNewLine
strMessage = strMessage & "Please note or copy this error message and contact application developer for assistance."
MsgBox strMessage, vbCritical + vbOKOnly, "Error"
End
End Function
Just guessing that you are not iterating through an Excel file the second time, thus it throws an error. To debug it in ELI5 style, change your code like this:
Do While myfile <> ""
MsgBox myFile
'Format the excel report
strPathFileName = mypath & myfile
'use for unpresented
Call formatExcelUnPresentedForImport(strPathFileName)
i = i + 1
myfile = Dir()
Loop
and pay attention to the MsgBox every time. Is it showing what you think it should be showing?

Excel 2013 cannot find and open the file in ThisWorkbook directory

The following issue occured to me. I use MS Excel 2013.
With the macro below I tried to find those accounts (which meets the criteria "In scope", e.g. account 12345678), to copy them, to search in the same folder (where ThisWorkbook is), to find another excel file which has as name the number of account (e.g. "12345678.xlsx") and to open it.
After the proposed corrections below, my macro finds and opens the desired file. But now the problem is that no actions can be performed on it: copy, paste, etc.
Could you please help on this?
Sub FileFinder()
'Excel variables:
Dim RngS As Excel.Range
Dim wbResults As Workbook
'Go to the column with specific text
Worksheets("Accounts source data").Activate
X = 3
Y = 25
While Not IsEmpty(Sheets("Accounts source data").Cells(X, Y))
Sheets("Accounts source data").Cells(X, Y).Select
If ActiveCell = "In scope" Then
Sheets("Accounts source data").Cells(X, Y - 22).Select
'Copy the account in scope
Set RngS = Selection
Selection.Copy
'Search, in same directory where the file is located, the file with that account (file comes with account number as name)
sDir = Dir$(ThisWorkbook.Path & "\" & RngS & ".xlsx", vbNormal)
Set oWB = Workbooks.Open(ThisWorkbook.Path & "\" & sDir)
'Here is where my error occurs
'[Run-time error 5: Invalid procedure call or argument]
Sheet2.Cells("B27:B30").Copy
oWB.Close
End If
X = X + 1
Wend
End Sub
Try the code below, I have my explanation and questions for you in the code (as commnets):
Option Explicit
Sub FileFinder()
' Excel variables:
Dim wbResults As Workbook
Dim oWB As Workbook
Dim Sht As Worksheet
Dim RngS As Range
Dim sDir As String
Dim LastRow As Long
Dim i As Long, Col As Long
Col = 25
' set ThisWorkbook object
Set wbResults = ThisWorkbook
' set the worksheet object
Set Sht = Worksheets("Accounts source data")
With Sht
' find last row with data in Column "Y" (Col = 25)
LastRow = .Cells(.Rows.Count, 25).End(xlUp).Row
For i = 3 To LastRow
If .Cells(i, Col) = "In scope" Then
' Set the range directly, no need to use `Select` and `Selection`
Set RngS = .Cells(i, Col).Offset(, -22)
' Search, in same directory where the file is located, the file with that account (file comes with account number as name)
sDir = Dir$(ThisWorkbook.Path & "\" & RngS.Value & ".xlsx", vbNormal)
Set oWB = Workbooks.Open(ThisWorkbook.Path & "\" & sDir)
oWB.Worksheets("Report").Range("B27:B30").Copy
' *** Paste in ThisWorkbook, in my exmaple "Sheet2" <-- modify to your needs
wbResults.Worksheets("Sheet2").Range("C1").PasteSpecial Paste:=xlPasteAll, Transpose:=True
oWB.Close SaveChanges:=False
' sDir = Dir$
' clear objects
Set RngS = Nothing
Set oWB = Nothing
End If
Next i
End With
End Sub

Paste not working between Excel and Word through VBA

I have a workbook which creates Word reports based on a Word template and tables in the workbook.
Depending on the equipment type, it copies a range from the spreadsheet and pastes it to two bookmark locations in the word document (bmInternal and bmExternal). I tried using PasteAppendTable, but this only works once. If I try to use it twice, for each bookmark, it copies nothing both times. As such I used Paste for one and PasteAppendTable for the second (PasteAppendTable is much neater as the formatting is better).
This worked fine, but I made changes to the code, not related to this, and now the Paste (which goes to bmInternal) isn't working. I can't see why when I've not changed anything regarding that part:
Sub Data2Word()
Application.GoTo Reference:=ActiveSheet.Range("A2")
GoAgain:
On Error Resume Next
Dim vItem As String
'Dim vImagePath As String
Dim vCurrentRow As Integer
Dim vDesc As String
Dim vN2 As String
Dim vGuide As String
Dim vUnit As String
Dim vBlock As String
Dim wrdPic As Word.InlineShape
Dim rng As Excel.Range 'our source range
Dim rngText As Variant
Dim rngText2 As Variant
Dim wdApp As New Word.Application 'a new instance of Word
Dim wdDoc As Word.Document 'our new Word template
Dim myWordFile As String 'path to Word template
Dim wsExcel As Worksheet
Dim tmpAut
'Find Item and type
vItem = ActiveCell.Value
vDesc = ActiveCell.Offset(0, 2)
vN2 = ActiveCell.Offset(0, 1)
vGuide = ActiveCell.Offset(0, 3)
vBlock = ActiveCell.Offset(0, 4)
vUnit = Left(vItem, 3)
If ActiveSheet.Range("rngREPORTED") = "Yes" Then
MsgBox vItem & " already has a report."
Exit Sub
End If
'initialize the Word template path
'here, it's set to be in the same directory as our source workbook
myWordFile = "W:\Entity\Inspect\WORD\INSPECTION TEMPLATES\Inspection Template - 20160511.dotx"
'open a new word document from the template
Set wdDoc = wdApp.Documents.Add(myWordFile)
If vGuide = "IGE01" Then
rngText = "rngEXCH"
rngText2 = "rngEXCHE"
ElseIf ActiveCell.Offset(, 4) = "Mono" Then
'Do Mono
rngText = "rngMONO"
Else
ActiveWorkbook.Names.Add Name:="rngItemSub", RefersTo:=Worksheets("SubEquipment").Range("B" & ActiveCell.Offset(0, 6) & ":C" & ActiveCell.Offset(0, 7) + ActiveCell.Offset(0, 6))
CarryOn:
rngText = "rngItemSub"
End If
'Insert Tables
'get the range of the data
Set rng = Range(rngText)
rng.Copy 'copy the range
wdDoc.Bookmarks("bmInternal").Range.Paste 'AppendTable
If vGuide = "IGE01" Then
Set rng = Range(rngText2)
rng.Copy
End If
wdDoc.Bookmarks("bmExternal").Range.PasteAppendTable
wdDoc.Bookmarks("bmItem").Range.InsertAfter vItem
wdDoc.Bookmarks("bmDesc").Range.InsertAfter vDesc
wdDoc.Bookmarks("bmN2").Range.InsertAfter vN2
wdDoc.Bookmarks("bmGuide").Range.InsertAfter vGuide
wdDoc.Bookmarks("bmBlock").Range.InsertAfter vBlock
wdDoc.Variables("wvItem").Value = vItem
ActiveDocument.Fields.Update
With wdDoc
Set wrdPic = .Bookmarks("bmImage").Range.InlineShapes.AddOLEObject(ClassType:="AcroExch.Document.7", Filename:="W:\Entity\Inspect\T&I\2016\Various Items\Photos\Sorted\" & vItem & ".pdf", LinkToFile:=False, DisplayAsIcon:=False)
wrdPic.ScaleHeight = 55
wrdPic.ScaleWidth = 55
End With
wdApp.Visible = True
wdApp.Activate
wdDoc.SaveAs "W:\Entity\Inspect\WSDATA\REPORTS\2016\" & vUnit & "\" & vItem & " " & vN2 & " THO.docx" 'Mid(ActiveDocument.Name, 1, Len(ActiveDocument.Name) - 4)
MoveHere:
ActiveWorkbook.Sheets("AllItems").Range("G" & ActiveCell.Offset(0, 8)).Value = "Yes"
ActiveWorkbook.Save
End Sub
I think DocVariables are easier to use that Bookmarks. Do a quick Google search on Word DocVariables. Get things setup correct in Word, and then run the script below.
Sub PushToWord()
Dim objWord As New Word.Application
Dim doc As Word.Document
Dim bkmk As Word.Bookmark
sWdFileName = Application.GetOpenFilename(, , , , False)
Set doc = objWord.Documents.Open(sWdFileName)
'On Error Resume Next
objWord.ActiveDocument.variables("FirstName").Value = Range("FirstName").Value
objWord.ActiveDocument.variables("LastName").Value = Range("LastName").Value
objWord.ActiveDocument.variables("AnotherVariable").Value = Range("AnotherVariable").Value
objWord.ActiveDocument.Fields.Update
'On Error Resume Next
objWord.Visible = True
End Sub

Baffling Run-time error 91

I'm new to VBA, have searched all over the place but can't seem to find a solution. I'm
getting a Run-time error 91: Object variable or With block variable not set error. Does anyone know why?
Much thanks.
Option Explicit
Sub Survey()
'Name of the existing Word doc.
Const stCoHydroSurveyTemplate As String = "Survey Template.docx"
'Define Word objects.
Dim wdApp As Word.Application
Dim wdDoc As Word.Document
Dim wdbmHeadLossTable As Word.Range
Dim wdbmRevenueTable As Word.Range
'Define Excel objects.
Dim wbBook As Workbook
Dim wsSheet As Worksheet
Dim rnHeadLossTable As Range
Dim rnRevenueTable As Range
'Initialize the Excel objects.
Set wbBook = ThisWorkbook
Set wsSheet = wbBook.Worksheets("Sheet1")
Set rnHeadLossTable = wsSheet.Range("HeadLossTable")
Set rnRevenueTable = wsSheet.Range("RevenueTable")
'Initialize the Word objets.
Set wdApp = New Word.Application
Set wdDoc = wdApp.Documents.Open(wbBook.Path & "D:\Surveys" & stSurveyTemplate)
Set wdbmHeadLossTable = wdDoc.Bookmarks("HeadLossTable").Range
Set wdbmRevenueTable = wdDoc.Bookmarks("RevenueTable").Range
'If the macro has been run before, clean up any artifacts before trying to paste the table in again.
On Error Resume Next
With wdDoc.InlineShapes(1)
.Select
.Delete
End With
On Error GoTo 0
'Turn off screen updating.
Application.ScreenUpdating = False
'Copy the Head Loss Table to the clipboard.
rnHeadLossTable.Copy
rnRevenueTable.Copy
'Select the range defined by the "HeadLossTable" bookmark and paste in from the clipboard to the word doc "Survey Template".
With wdbmHeadLossTable
.Select
.PasteSpecial Link:=True, _
DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, _
DisplayAsIcon:=False
End With
With wdbmRevenueTable
.Select
.PasteSpecial Link:=True, _
DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, _
DisplayAsIcon:=False
End With
'Save and close the Word doc.
With wdDoc
.Save
.Close
End With
'Quit Word.
wdApp.Quit
'Null out your variables.
Set wdbmHeadLossTable = Nothing
Set wdbmRevenueTable = Nothing
Set wdDoc = Nothing
Set wdApp = Nothing
'Clear out the clipboard, and turn screen updating back on.
With Application
.CutCopyMode = False
.ScreenUpdating = True
End With
MsgBox "The Survey has successfully been " & vbNewLine & _
"transferred to " & stSurveyTemplate, vbInformation
End Sub
This line is incorrect:
Set wdDoc = wdApp.Documents.Open(wbBook.Path & "D:\Surveys" & stSurveyTemplate)
Maybe you meant for it to be like this:
Set wdDoc = wdApp.Documents.Open("D:\Surveys" & stSurveyTemplate)
or this:
Set wdDoc = wdApp.Documents.Open(wbBook.Path & "\Surveys" & stSurveyTemplate)
What I noticed is that with the original code, it didn't throw an error and wdDoc was just set to Nothing. I removed the "sbBook.Path" and by mistake had an incorrect file name, and that did throw an error.