Paste not working between Excel and Word through VBA - 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

Related

Copy range in Word avoiding clipboard

I have the code below to copy an array of tables in Word to Excel. The volume of data being copied gives memory problems, so I would like to avoid the clipboard - i.e. avoid using Range.Copy
Word does not support Range.Value and I have not been able to get Range(x) = Range(y) to work.
Any suggestions for a way to avoid the clipboard? Word formatting can be junked.
Sub ImportWordTableArray()
Dim WordApp As Object
Dim WordDoc As Object
Dim arrFileList As Variant, FileName As Variant
Dim tableNo As Integer 'table number in Word
Dim tableStart As Integer
Dim tableTot As Integer
Dim Target As Range
On Error Resume Next
arrFileList = Application.GetOpenFilename("Word files (*.doc; *.docx),*.doc;*.docx", 2, _
"Browse for file containing table to be imported", , True)
If Not IsArray(arrFileList) Then Exit Sub
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False
Worksheets("Test").Range("A:AZ").ClearContents
Set Target = Worksheets("Test").Range("A1")
For Each FileName In arrFileList
Set WordDoc = WordApp.Documents.Open(FileName, ReadOnly:=True)
With WordDoc
'For array
Dim tables() As Variant
Dim tableCounter As Long
tableNo = WordDoc.tables.Count
tableTot = WordDoc.tables.Count
If tableNo = 0 Then
MsgBox WordDoc.Name & "Contains no tables", vbExclamation, "Import Word Table"
End If
tables = Array(1, 3, 5) '<- define array manually here if not using InputBox
For tableCounter = LBound(tables) To UBound(tables)
With .tables(tables(tableCounter))
.Range.Copy
Target.Activate
'Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False '<- memory problems!
'Or
ActiveSheet.Paste '<- pastes with formatting
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableCounter
.Close False
End With
Next FileName
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
You may need to tweak the code below to get it to do exactly what you want (Excel is not something I use often) as the calculation of ranges is a bit wonky, but it will transfer text from word to excel without cutting and pasting
Option Explicit
' This code is based on it being in an Excel VBA Module with the reference
' to the Microsoft Word Object XX.X Object Library (Tools.References)
' enabled so that we get intellisense for Word objects
Public Enum ImportError
NoTablesInDocument
End Enum
Sub ImportWordTableArray()
Dim myFileList As Variant
If Not TryGetFileList(myFileList) Then Exit Sub
Dim myWdApp As Word.Application
Set myWdApp = New Word.Application
myWdApp.Visible = True
If Application.ReferenceStyle = xlA1 Then Application.ReferenceStyle = xlR1C1
ThisWorkbook.Worksheets("Test").Range("A:AZ").ClearContents
Dim myFileName As Variant
For Each myFileName In myFileList
Dim myDoc As Word.Document
If TryGetWordDoc(myFileName, myWdApp, myDoc) Then
CopyDocTablesToExcel myDoc, ThisWorkbook.Worksheets("Test")
End If
Next
If Application.ReferenceStyle = xlR1C1 Then Application.ReferenceStyle = xlA1
End Sub
Public Sub CopyDocTablesToExcel(ByVal ipDoc As Word.Document, ByVal ipWs As Excel.Worksheet)
If ipDoc.Tables.Count = 0 Then
Report ipDoc.Name, ImportError.NoTablesInDocument
Exit Sub
End If
Dim myTable As Variant
Dim Target As Excel.Range
For Each myTable In ipDoc.Tables
' This code assumes that the Word table is 'uniform'
Dim myCols As Long
myCols = myTable.Range.Tables.Item(1).Range.Columns.Count
Dim myRows As Long
myRows = myTable.Range.Tables.Item(1).Range.Rows.Count
Dim myTLCell As Excel.Range
Dim myBRCell As Excel.Range
If Target Is Nothing Then
Set myTLCell = ipWs.Cells(1, 1)
Set myBRCell = ipWs.Cells(myCols, myRows)
Else
Set myTLCell = ipWs.Cells(1, Target.Cells.SpecialCells(xlCellTypeLastCell).Row + 2)
Set myBRCell = ipWs.Cells(myCols, Target.Cells.SpecialCells(xlCellTypeLastCell).Row + 2 + myRows)
End If
Set Target = ipWs.Range(myTLCell, myBRCell)
Target = GetTableArray(myTable)
Next
End Sub
Public Function GetTableArray(ByVal ipTable As Word.Table) As Variant
Dim myArray As Variant
Dim myRow As Long
Dim myCol As Long
ReDim myArray(1 To ipTable.Range.Tables.Item(1).Range.Rows.Count, 1 To ipTable.Range.Tables.Item(1).Range.Columns.Count)
For myRow = 1 To UBound(myArray, 1) - 1
For myCol = 1 To UBound(myArray, 2) - 1
Dim myText As String
myText = ipTable.Cell(myRow, myCol).Range.Text
myArray(myRow, myCol) = VBA.Left$(myText, Len(myText) - 2)
Next
Next
GetTableArray = myArray
End Function
Public Function TryGetFileList(ByRef opFileList As Variant) As Boolean
On Error Resume Next
opFileList = _
Application.GetOpenFilename _
( _
"Word files (*.doc; *.docx),*.doc;*.docx", _
2, _
"Browse for file containing table to be imported", _
, _
True _
)
TryGetFileList = (Err.Number = 0) And IsArray(opFileList)
On Error GoTo 0
End Function
Public Function TryGetWordDoc _
( _
ByVal ipName As String, _
ByRef ipWdApp As Word.Application, _
ByRef opDoc As Word.Document _
) As Boolean
On Error Resume Next
Set opDoc = ipWdApp.Documents.Open(ipName, ReadOnly:=True)
TryGetWordDoc = (Err.Number = 0) And (Not opDoc Is Nothing)
On Error GoTo 0
End Function
Public Function Report(ByVal ipString As String, ByVal ipError As ImportError)
Select Case ipError
Case NoTablesInDocument
MsgBox ipString & " Contains no tables", vbExclamation, "Import Word Table"
Case Else
End Select
End Function
For tableCounter ... Next code modified below to extract data directly rather than using copy and paste.
Sub ImportWordTablesArray()
Dim WordApp As Object
Dim WordDoc As Object
Dim arrFileList As Variant, Filename As Variant
Dim tableNo As Integer 'table number in Word
Dim iRow As Long 'row index in Excel
Dim iCol As Integer 'column index in Excel
Dim resultRow As Long
Dim tables() As Variant
Dim tableCounter As Long
On Error Resume Next
arrFileList = Application.GetOpenFilename("Word files (*.doc; *.docx),*.doc;*.docx", 2, _
"Browse for file containing table to be imported", , True)
If Not IsArray(arrFileList) Then Exit Sub '<-user cancelled import file browser
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False
Worksheets("Test").Range("A:E").Clear '<-ClearContents to clear only text
For Each Filename In arrFileList
Set WordDoc = WordApp.Documents.Open(Filename, ReadOnly:=True)
With WordDoc
If WordDoc.ProtectionType <> wdNoProtection Then
WordDoc.Unprotect Password:=SREPedit
End If
tableNo = WordDoc.tables.Count
If tableNo = 0 Then
MsgBox WordDoc.Name & "Contains no tables", vbExclamation, "Import Word Table"
End If
tables = Array(1, 2, 8) '<- Select tables for data extraction
For tableCounter = LBound(tables) To UBound(tables)
With .tables(tables(tableCounter))
For iRow = 1 To .Rows.Count
For iCol = 1 To .Columns.Count
Cells(resultRow, iCol) = WorksheetFunction.Clean(.Cell(iRow, iCol).Range.Text)
Next iCol
resultRow = resultRow + 1
Next iRow
End With
resultRow = resultRow + 1
Next tableCounter
.Close False
End With
Next Filename
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub

Excel VBA to get Word Document Form Data returning incorrect date format

I copied this code to get data from a word document form and put it into an excel spreadsheet and it works great except that the dates are coming in mm/dd/yyyy format. I need to it be dd/mm/yyyy format.
I tried adding a date picker to the form but that hasn't helped.
Normally I would put the formatting into the VBA code but I am unsure how to do that in this code. Can it be inserted or can I somehow reformat the date after it comes into the spreadsheet?
The code is in Excel VBA
Sub GetFormData()
'Note: this code requires a reference to the Word object model
Application.ScreenUpdating = False
Dim wdApp As New Word.Application
Dim wdDoc As Word.Document
Dim CCtrl As Word.ContentControl
Dim strFolder As String, strFile As String
Dim WkSht As Worksheet, i As Long, j As Long
strFolder = GetFolder
If strFolder = "" Then Exit Sub
Set WkSht = Sheets("Data")
i = WkSht.Cells(WkSht.Rows.Count, 1).End(xlUp).Row
strFile = Dir(strFolder & "\*.docx", vbNormal)
While strFile <> ""
i = i + 1
Set wdDoc = wdApp.Documents.Open(Filename:=strFolder & "\" & strFile, AddToRecentFiles:=False, Visible:=False)
With wdDoc
j = 0
For Each CCtrl In .ContentControls
j = j + 1
WkSht.Cells(i, j) = CCtrl.Range.Text
Next
End With
wdDoc.Close SaveChanges:=False
strFile = Dir()
Wend
wdApp.Quit
Set wdDoc = Nothing: Set wdApp = Nothing: Set WkSht = Nothing
Application.ScreenUpdating = True
You may want to replace
WkSht.Cells(i, j) = CCtrl.Range.Text
by
WkSht.Cells(i, j).FormulaLocal = CCtrl.Range.Text

Script to run a macro at a specific time with excel running in invisible mode

'This code is inside an module of a Workbook.
Sub Notes_Email_Excel_Cells2()
Application.WindowState = xlNormal
Dim NSession As Object
Dim NDatabase As Object
Dim NUIWorkSpace As Object
Dim NDoc As Object
Dim NUIdoc As Object
Dim WordApp As Object
Dim subject As String
Dim dd As String
Dim stAttachment As String
Dim obAttachment As Object, EmbedObject As Object
Const EMBED_ATTACHMENT As Long = 1454
Dim Wb As Workbook
Dim FirstCell As Range, LastCell As Range
Dim CC(1)
CC(1) = "yyy#itc.in,"
If bIsBookOpen("Daily Beetle Count Report - MMGR.xlsx") = True Then
Set Wb = Workbooks("Daily Beetle Count Report - MMGR.xlsx")
Else
Workbooks.Open ("B:\Sangeet\Daily Beetle Count Report - MMGR.xlsx")
Set Wb = Workbooks("Daily Beetle Count Report - MMGR.xlsx")
End If
Set NSession = CreateObject("Notes.NotesSession")
'Next line only works with 5.x and above. Replace password with your password
subject = "HOT SPOTS Infestation " & Now
Debug.Print subject
Set NUIWorkSpace = CreateObject("Notes.NotesUIWorkspace")
Set NDatabase = NSession.GetDatabase("", "")
If Not NDatabase.IsOpen Then NDatabase.OPENMAIL
'Create a new Lotus Notes document
Set NDoc = NDatabase.CreateDocument
stAttachment = ActiveWorkbook.FullName
Set obAttachment = NDoc.CreateRichTextItem("stAttachment")
Set EmbedObject = obAttachment.EmbedObject(EMBED_ATTACHMENT, "", stAttachment)
With NDoc
.SendTo = "xxx#itc.in" 'CHANGE RECIPIENT EMAIL ADDRESS
.CopyTo = ""
.subject = subject
'Email body text, including marker text which will be replaced by the Excel cells
.body = "Dear All," & vbLf & vbLf & "Please find the Hotspot areas" & vbLf & vbLf & _
"**PASTE HERE**" & vbLf & vbLf & vbLf & vbLf & _
"Auto Generated Mail. Please Donot Reply."
.Save True, False
End With
'Edit the just-created document to copy and paste the Excel cells into it via Word
Set NUIdoc = NUIWorkSpace.EDITDocument(True, NDoc)
With NUIdoc
'Find the marker text in the Body item
.GotoField ("Body")
.FINDSTRING "**PASTE HERE**"
'.DESELECTALL 'Uncomment to leave the marker text in place (cells are inserted immediately before)
'Copy Excel cells to clipboard
Wb.Sheets("HOT SPOT").Activate
Sheets("HOT SPOT").Range("v2:w21").Copy 'CHANGE SHEET AND RANGE TO BE COPIED AND PASTED
'Create a temporary Word Document
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False 'True to aid debugging
WordApp.Documents.Add
'Paste into Word document and copy to clipboard
With WordApp.Selection
.PasteSpecial DataType:=10 'Enum WdPasteDataType: 10 = HTML; 2 = Text; 1 = RTF
.WholeStory
.Copy
End With
'Paste from clipboard (Word) to Lotus Notes document
.Paste
Application.CutCopyMode = False
WordApp.Quit SaveChanges:=False
Set WordApp = Nothing
.Send
.Close
End With
Set NSession = Nothing
If bIsBookOpen("Daily Beetle Count Report - MMGR.xlsx") Then
Workbooks("Daily Beetle Count Report - MMGR.xlsx").Close SaveChanges:=False
Else
End If
End Sub
Function bIsBookOpen(ByRef szBookName As String) As Boolean
On Error Resume Next
bIsBookOpen = Not (Application.Workbooks(szBookName) Is Nothing)
End Function

Exporting Table of Contents from Word to Excel

I am looking for a way to get the table of contents (not created but headings available) from word and store the chapter numbers and headings on Excel. Is there a method using Excel VBA to take those headings from word doc to excel? I have searched for this but everybody suggest using paste special however I want it automated since the data from TOC is sorted into a different table in Excel afterwards.
Sub importwordtoexcel()
MsgBox ("This Macro Might Take a While, wait until next Message")
Application.ScreenUpdating = False
Sheets("Temp").Cells.Clear
'Import all tables to a single sheet
Dim wdDoc As Object
Dim wdFileName As Variant
Dim TableNo As Integer 'table number in Word
Dim iRow As Long 'row index in Word
Dim jRow As Long 'row index in Excel
Dim iCol As Integer 'column index in Excel
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 wdDoc = GetObject(wdFileName) 'open Word file
With wdDoc
If wdDoc.Tables.Count = 0 Then
MsgBox "This document contains no tables", _
vbExclamation, "Import Word Table"
Else
jRow = 0
For TableNo = 1 To wdDoc.Tables.Count
With .Tables(TableNo)
'copy cell contents from Word table cells to Excel cells
For iRow = 1 To .Rows.Count
jRow = jRow + 1
For iCol = 1 To .Columns.Count
On Error Resume Next
Sheets("Temp").Cells(jRow, iCol) = WorksheetFunction.Clean(.Cell(iRow, iCol).Range.Text)
On Error GoTo 0
Next iCol
Next iRow
End With
jRow = jRow + 1
Next TableNo
End If
End With
Set wdDoc = Nothing
'Takes data from temp to RTM_FD
Dim nRow As Long
Dim mRow As Long
Dim Temp As Worksheet
Dim RTM As Worksheet
Set Temp = Sheets("Temp")
Set RTM = Sheets("RTM_FD")
mRow = 16
For nRow = 1 To Temp.Rows.Count
If Temp.Cells(nRow, 1).Value = "Position" Or Temp.Cells(nRow, 1).Value = "" Then
Else
RTM.Cells(mRow, 1).Value = Temp.Cells(nRow, 1)
RTM.Cells(mRow, 2).Value = Temp.Cells(nRow, 4)
RTM.Cells(mRow, 2).Font.Bold = False
RTM.Cells(mRow, 3).Value = Temp.Cells(nRow, 5)
RTM.Cells(mRow, 3).Font.ColorIndex = 32
If Temp.Cells(nRow, 3).Value = "P" Then
RTM.Cells(mRow, 9).Value = "X"
RTM.Cells(mRow, 9).Interior.ColorIndex = 44
ElseIf Temp.Cells(nRow, 3) = "Q" Then
RTM.Cells(mRow, 7).Value = "X"
RTM.Cells(mRow, 7).Interior.ColorIndex = 44
ElseIf Temp.Cells(nRow, 3) = "TA" Then
RTM.Cells(mRow, 8).Value = "X"
RTM.Cells(mRow, 8).Interior.ColorIndex = 44
Else
End If
mRow = mRow + 1
End If
Next nRow
Application.ScreenUpdating = True
MsgBox ("DONE")
Sheets("Temp").Cells.Clear
Dim SaveName As String
SaveName = InputBox("What Do You Want to Save the File As:")
ActiveWorkbook.SaveAs (SaveName)
MsgBox ("Your file is saved as " & SaveName)
MsgBox ("Please Accept Delete Operation")
Sheets("Temp").Delete
ActiveWorkbook.Save
End Sub
One way to get section headings without creating a TOC is by iterating with the selection object, using Selection.Goto. The folowing example prints all the sections headings in a document to the immediate window. I am sure you can adapt the concept to your code.
Sub PrintHeadings()
Dim wrdApp As Word.Application
Dim wrdDoc As Document
Dim Para As Paragraph
Dim oldstart As Variant
Set wrdApp = CreateObject("Word.Application") 'open word
Set wrdDoc = wrdApp.Documents.Open("C:\sample.docx", , True, False, , , , , , , , True) 'open file
wrdDoc.ActiveWindow.ActivePane.View.Type = wdPrintView 'avoids crashing if opens on read view
With wrdDoc.ActiveWindow.Selection
.GoTo What:=wdGoToHeading, which:=wdGoToFirst 'go to first heading
Do
Set Para = .Paragraphs(1) 'get first paragraph
Title = Replace(Para.Range.Text, Chr(13), "") 'gets title and remove trailing newline
Debug.Print Title, "pg. "; .Information(wdActiveEndAdjustedPageNumber) 'prints title and page to console
oldstart = .Start 'stores position
.GoTo What:=wdGoToHeading, which:=wdGoToNext 'go to next heading
If .Start <= oldstart Then Exit Do 'if looped around to first section (i.e. new heading is before old heading) we are done
Loop
End With
wrdDoc.Close
wrdApp.Quit
Set Para = Nothing
Set wrdDoc = Nothing
Set wrdApp = Nothing
End Sub
I use early binding, so you will need to either add a reference to Word object model, or tweak the code to late binding (including finding out the numeric value of the enums).
I worked fine with My Chinese words documents, it may require to change some of the codes for different heading style.
If it won't work for you, I would love to have your words sample file and figure out why.
PS: The key point is to have the correct #OLE_LINK format.
My codes is as follows:
' Get your file and save in Range("A1")
Public Sub SelectAFile()
Dim intChoice As Integer
Dim strPath As String
'only allow the user to select one file
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strPath = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
'print the file path to sheet 1
Cells(1, 1) = strPath
End If
End Sub
' Main program start here
Sub genWordIndex()
Dim rng As Range
Dim r As Range
Dim PageName As String
Dim TestValue As String
Dim WshShell As Variant
Set WshShell = CreateObject("WScript.Shell")
Set rng = Range("A1") 'Selection
Call CleanOldText(1)
PageName = rng.text
Call ReadIndexFromWords3(PageName)
End Sub
Sub ReadIndexFromWords3(ByVal FileName As String)
'
' This is a common routine for handling open file
'
Dim WA As Object
Dim wdDoc As Word.Document
On Error Resume Next
Set WA = GetObject(, "Word.Application")
If WA Is Nothing Then
Set WA = CreateObject("Word.Application")
Set wdDoc = WA.Documents.Open(FileName)
Else
On Error GoTo notOpen
Set wdDoc = WA.Documents(FileName)
GoTo OpenAlready
notOpen:
Set wdDoc = WA.Documents.Open(FileName)
End If
OpenAlready:
wdDoc.Activate
'
' read index program start here。
'
Dim i As Integer: i = 2
Dim H_start, H_end, H_Caption, H_lvl, H_page As String
Dim H_txt As String
Dim Para As Paragraph
For Each Para In wdDoc.Paragraphs
Para.Range.Select
If Not Para.Range.Style Is Nothing Then
If IsMyHeadingStype(Para.Range.Style) = True Then
H_start = Para.Range.Start
H_end = Para.Range.End
H_txt = Para.Range.text
H_Caption = Para.Range.ListFormat.ListString
H_page = Para.Range.Information(wdActiveEndPageNumber)
Dim myLinkAddress As String
myLinkAddress = FileName & "#OLE_LINK" & i & vbTab & "1," & H_start & "," & H_end & ",2,," & H_txt
Application.ActiveWorkbook.Activate
ActiveSheet.Cells(i, 1).Select
Dim CapLen As Integer:
CapLen = Len(H_Caption) - 1
If CapLen < 0 Then CapLen = 0
ActiveSheet.Cells(i, 1) = Space(CapLen) & H_Caption & " " & H_txt
ActiveCell.Hyperlinks.Add Anchor:=Selection, Address:=myLinkAddress, SubAddress:="" 'TextToDisplay:=H_txt,
ActiveSheet.Cells(i, 2) = H_page
i = i + 1
End If
End If
Next
End Sub
'
' you may have to change your InStyle here
'
Function IsMyHeadingStype(ByVal InStyle As String) As Boolean
Dim rc As Boolean: rc = False
If InStr(InStyle, "標題 1") Or InStr(InStyle, "標題 2") Or InStr(InStyle, "標題 3") Then
rc = True
End If
IsMyHeadingStype = rc
End Function
' sub routine
Sub CleanOldText(ByVal col1 As Integer)
Dim i As Integer
Dim lastR As Integer
lastR = Cells(10000, col1).End(xlUp).Row
For i = 2 To lastR
Cells(i, col1).ClearContents
Cells(i, col1 + 1).ClearContents
Next i
End Sub

Populate word from excel template each row=one document through bookmarks

I'm getting the error
"error 424" - object required
on the marked line:
Sub CreateWordDocuments1()
Const FilePath As String = "D:\"
Dim wApp As Word.Application
Dim wDoc As Word.Document
Set wApp = CreateObject("word.application")
wApp.Visible = True
Dim PersonCell As Range
'create copy of Word in memory
Dim PersonRange As Range
'create a reference to all the people
Range("A1").Select
Set PersonRange = Range( ActiveCell, ActiveCell.End(xlDown))
'for each person in list �
For Each PersonCell In PersonRange
'open a document in Word
Set wDoc = wApp.Documents.Open("D:\template.doc")
'go to each bookmark and type in details
CopyCell "FirstName", 1
'save and close this document
wDoc.SaveAs2 FilePath & "person " & PersonCell.Value & ".doc"
wDoc.Close
Next PersonCell
wApp.Quit
MsgBox "Created files in " & FilePath & "!"
End Sub
Sub CopyCell(BookMarkName As String, ColumnOffset As Integer)
'copy each cell to relevant Word bookmark
wApp.Selection.GoTo What:=-1, Name:="FirstName" ''' Error on this line
wApp.Selection.TypeText PersonCell.Offset(0, ColumnOffset).Value
End Sub
Also, I am trying for whole day to skip this error but I can't. I search for some alternatives such as XML maybe?
The issues with your initial code:
Main error: variable wApp exists in CreateWordDocuments1, but
not in CopyCell
Variable PersonCell exists in CreateWordDocuments1, but not in CopyCell (same as 1st)
CopyCell doesn't use parameter BookMarkName (not critical but made it redundant)
.
Edited code to accommodate multiple Word bookmarks in synch with Excel columns
Here is how all files are setup - column names in Excel represent Bookmark names in Word:
.
Option Explicit
Public Sub CreateWordDocuments()
Const FILE_PATH As String = "C:\Tmp\"
Const FILE_NAME As String = "Template"
Const FILE_EXT As String = ".doc"
Dim wApp As Word.Application
Dim wDoc As Word.Document
Dim totalRows As Long 'assumes all columns are the same size
Dim totalCols As Long 'assumes all rows are the same size
Dim person As Long 'Outer loop counter (all rows)
Dim personList As Variant 'All data: rows and columns, without header row
Dim bookmark As Long 'Inner loop counter (all columns)
Dim bookmarks As Variant 'All bookmarks, from the header row
Set wApp = CreateObject("Word.Application")
wApp.Visible = False
'We're working in Sheet1, and data starts in its first cell (A1)
With ThisWorkbook.Worksheets(1)
With .UsedRange
bookmarks = .Rows(1).Value2 'get all column headers
totalRows = .Rows.Count
totalCols = .Columns.Count
End With
'all data without the header row -------------------------------------
personList = .Range(.Cells(2, 1), .Cells(totalRows, totalCols)).Value2
End With
For person = 1 To totalRows - 1 'each row (after header)
'Open Word Template file
Set wDoc = wApp.Documents.Open(FILE_PATH & FILE_NAME & FILE_EXT)
For bookmark = 1 To totalCols 'each column
With wApp.Selection
'bookmark name from header row
.GoTo What:=wdGoToBookmark, Name:=bookmarks(1, bookmark)
'enter data for each bookmark
.TypeText personList(person, bookmark)
End With
Next 'next column \ bookmark
With wDoc 'sava and close the new Word file (person name in column 1)
.SaveAs FILE_PATH & "Person " & personList(person, 1) & " " & personList(person, 2) & FILE_EXT
.Close
End With
Next 'next row
wApp.Quit
Set wDoc = Nothing
Set wApp = Nothing
MsgBox "Created " & totalRows - 1 & " files in " & FILE_PATH
End Sub