I have a simple interface in Excel that allows the user to export a table from Excel to Word as a new or existing document. It then loops through the last column(8) in the word table and inserts a drop down list in each cell.
The code does what it is supposed to do but runs slowly when inserting the content controls. Additionally, I can see it insert each content control in MS Word which tells me that screen updating is not disabled in Word. Any suggestions to make my code to run faster?
Full code and reference word table below.
Sub ExportToWord()
Dim ws As Excel.Worksheet
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Dim objRange As Word.Range
Dim newDoc As Boolean
Dim rng As Excel.Range
Dim lRow As Integer, s As Integer
Dim objCC As ContentControl
Dim counter As Long
Dim oRow As Row
If UF_Load.check_new = True Then
newDoc = True
Else
newDoc = False
End If
Set ws = ThisWorkbook.Sheets("UI")
Application.ScreenUpdating = False
Application.EnableEvents = False
s = ws.Range("rng_demo").Row - 2
c = ws.Range("rng_demo").Column
lRow = ws.Cells(Rows.Count, s).End(xlUp).Row
Set rng = ws.Range("A" & s).Resize(lRow, 8)
rng.Copy
If wrdApp Is Nothing Then
On Error Resume Next
Set wrdApp = GetObject(, "Word.Application")
If Err.Number > 0 Then Set wrdApp = CreateObject("Word.Application")
On Error GoTo 0
End If
'Handle if Word Application is not found
If Err.Number <> 0 Then GoTo SafeExit:
'MsgBox "Microsoft Word document could not be found, aborting", vbExclamtion, "Microsoft Word Error 429"
'GoTo SafeExit:
'End If
On Error GoTo 0
'Make MS Word Visible and Active
wrdApp.Activate
wrdApp.Visible = True
If newDoc = True Then
Set wrdDoc = wrdApp.Documents.Add 'create as new word document
'Set as editable
If wrdDoc.ActiveWindow.View.SplitSpecial = wdPaneNone Then
wrdDoc.ActiveWindow.ActivePane.View.Type = wdPrintView
Else
wrdDoc.ActiveWindow.View.Type = wdPrintView
End If
'Copy table data to word doc
Set tbl = rng
tbl.Copy
'Paste Table into Word doc
wrdDoc.Paragraphs(1).Range.PasteExcelTable _
LinkedToExcel:=False, _
WordFormatting:=False, _
RTF:=False
'Autofit table to Word doc
Set Wordtable = wrdDoc.Tables(1)
Wordtable.AutoFitBehavior (wdAutoFitWindow)
'Dim oRng As Range
'Loop through last table column and add Combobox
'Insert comboboxes
With Wordtable
counter = 0
For Each oRow In Wordtable.Rows
'Set oRng = oRow.Cells(1).Range
'If Trim(Len(oRow.Cells(1).Range.Text)) <> " " Then
If Len(Trim(Replace(oRow.Cells(1).Range.Text, Chr(160), ""))) <> 2 And counter >= 8 Then 'GoTo Nexti:
On Error Resume Next
Set objCC = wrdApp.ActiveDocument.ContentControls.Add(wdContentControlDropdownList, oRow.Cells(8).Range)
If Err.Number = 5941 Then GoTo Nexti:
objCC.Title = "Interpretation"
If objCC.ShowingPlaceholderText Then
objCC.SetPlaceholderText , , "-"
objCC.DropdownListEntries.Add "Valid"
objCC.DropdownListEntries.Add "Significant Difference"
objCC.DropdownListEntries.Add "WNL"
objCC.DropdownListEntries.Add "Slightly Below Expectations"
objCC.DropdownListEntries.Add "Below Expectations"
objCC.DropdownListEntries.Add "Far Below Expectations"
Debug.Print Len(oRow.Cells(7).Range.Text)
End If
Else
'Do nothing
End If
Nexti:
On Error GoTo 0
counter = counter + 1
Next
End With
On Error GoTo SafeExit:
Else
'or open an existing document
Set wrdDoc = wrdApp.Documents.Open(filepath, , False) 'wrdApp.Documents.Open("C:\Users\Apache Paint\Desktop\Clients\Stephen Schmitz\TestDocument.docx")
'Set as editable
If wrdDoc.ActiveWindow.View.SplitSpecial = wdPaneNone Then
wrdDoc.ActiveWindow.ActivePane.View.Type = wdPrintView
Else
wrdDoc.ActiveWindow.View.Type = wdPrintView
End If
'Copy table data to word doc
With wrdDoc
Set tbl1 = .Tables.Add(Range:=wrdDoc.Paragraphs.Last.Range, _
NumRows:=1, NumColumns:=8, _
AutoFitBehavior:=wdAutoFitWindow) 'autofit content 'DefaultTableBehavior:=wdWord9TableBehavior,
With tbl1
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
End With
Set tbl = rng
Set objRange = wrdDoc.Content
With objRange
.Collapse Direction:=0 'wdCollapseEnd
'.InsertAfter vbCrLf '<<< Error on line
.Collapse Direction:=0
.InsertBreak Type:=wdPageBreak
.Paste '<< paste the table
End With
'Autofit the document
Set Wordtable = objRange.Tables(1) 'Set Wordtable = objRange.Tables(1)
Wordtable.AutoFitBehavior (wdAutoFitWindow)
With Wordtable
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
'Insert comboboxes
counter = 0
For Each oRow In Wordtable.Rows
Set oRng = oRow.Cells(1).Range
If Len(Trim(Replace(oRow.Cells(1).Range.Text, Chr(160), ""))) <> 2 And counter >= 8 Then 'GoTo Nexti:
On Error Resume Next
Set objCC = wrdApp.ActiveDocument.ContentControls.Add(wdContentControlDropdownList, oRow.Cells(8).Range)
If Err.Number = 5941 Then GoTo Nexti2:
objCC.Title = "Interpretation"
If objCC.ShowingPlaceholderText Then
objCC.SetPlaceholderText , , "-"
objCC.DropdownListEntries.Add "Valid"
objCC.DropdownListEntries.Add "Significant Difference"
objCC.DropdownListEntries.Add "WNL"
objCC.DropdownListEntries.Add "Slightly Below Expectations"
objCC.DropdownListEntries.Add "Below Expectations"
objCC.DropdownListEntries.Add "Far Below Expectations"
Debug.Print Len(oRow.Cells(7).Range.Text)
End If
Else
'Do nothing
End If
Nexti2:
On Error GoTo 0
counter = counter + 1
Next
End With
End With
filepath = ""
End If
SafeExit:
If Err.Number <> 0 Then
Beep
MsgBox "Microsoft Excel has encountered an error and could not complete the Export to MS Word. Possible reasons are:" & vbNewLine & vbNewLine & _
"-Reference to Microsoft Word Object Library is not enabled" & vbNewLine & vbNewLine & "-The document opened in Read Only mode" & vbNewLine & vbNewLine & _
"-Code execution was interrupted because the was closed or altered during execution" & vbNewLine & vbNewLine & "-Document is already open in MS Word" _
, vbCritical, "Error"
End If
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.CutCopyMode = False
End Sub
It seems to me your code could be made both more efficient and shorter:
Sub ExportToWord()
Application.ScreenUpdating = False: Application.EnableEvents = False
Dim ws As Excel.Worksheet, rng As Excel.Range, lRow As Long, c As Long, r As Long, newDoc As Boolean
Dim wrdApp As Word.Application, wrdDoc As Word.Document, wrdTbl As Word.Table, wrdCCtrl As Word.ContentControl
Const filepath As String = "C:\Users\Apache Paint\Desktop\Clients\Stephen Schmitz\TestDocument.docx"
Set ws = ThisWorkbook.Sheets("UI")
With ws
c = .Range("rng_demo").Column
r = .Range("rng_demo").Row - 2
lRow = .Cells(.Rows.Count, c).End(xlUp).Row
Set rng = .Range("A" & r).Resize(lRow, 8)
End With
If wrdApp Is Nothing Then
On Error Resume Next
Set wrdApp = GetObject(, "Word.Application")
If Err.Number > 0 Then Set wrdApp = CreateObject("Word.Application")
On Error GoTo 0
End If
With wrdApp
.Visible = True
If UF_Load.check_new = True = True Then
'create as new word document
Set wrdDoc = wrdApp.Documents.Add
'create a table
Set wrdTbl = wrdDoc.Tables.Add(Range:=wrdDoc.Paragraphs.Last.Range, NumRows:=1, NumColumns:=8)
Else
'open an existing document
Set wrdDoc = .Open(filepath, , False)
'copy & paste the Excel table
rng.Copy
Set wrdTbl = wrdDoc.Paragraphs.Last.Range.PasteExcelTable(LinkedToExcel:=False, WordFormatting:=False, RTF:=False)
End If
With wrdDoc
With wrdTbl
'format the table
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
'Insert comboboxes
For r = 9 To .Rows.Count
If r = 9 Then
Set wrdCCtrl = wrdDoc.ContentControls.Add(wdContentControlDropdownList, .Cell(r, 8).Range)
With wrdCCtrl
.Title = "Interpretation"
.SetPlaceholderText , , "-"
.DropdownListEntries.Add "Valid"
.DropdownListEntries.Add "Significant Difference"
.DropdownListEntries.Add "WNL"
.DropdownListEntries.Add "Slightly Below Expectations"
.DropdownListEntries.Add "Below Expectations"
.DropdownListEntries.Add "Far Below Expectations"
End With
Else
.Cell(r, 8).Range.FormattedText = wrdCCtrl.Range.FormattedText
End If
Next
End With
End With
End With
Application.ScreenUpdating = True: Application.EnableEvents = True: Application.CutCopyMode = False
End Sub
Related
I have a an Excel workbook with that creates a table and exports the table to MS word. My client now wants to also insert a drop down list into the last column of the word table. I cannot find any material on this. Can it be done? I would like to create a combobox and insert it into each cell in the "Interpretation" column. Can someone point me in the right direction or supply some sample code?
Current code:
Sub ExportToWord()
Dim ws As Worksheet
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Dim objRange As Word.Range
Dim bWeStartedWord As Boolean
Dim newDoc As Boolean, onSave As Boolean
Dim rng As Range
Dim lRow As Integer, s As Integer
If UF_Load.check_new = True Then
newDoc = True
Else
newDoc = False
End If
Set ws = ThisWorkbook.Sheets("UI")
On Error Resume Next
Set wrdApp = GetObject(, "Word.Application")
On Error GoTo 0
Application.ScreenUpdating = False
Application.EnableEvents = False
s = ws.Range("rng_demo").Row - 1
c = ws.Range("rng_demo").Column
lRow = ws.Cells(Rows.count, s).End(xlUp).Row
Set rng = ws.Range("A" & s).Resize(lRow, 8)
rng.Copy
If wrdApp Is Nothing Then
Set wrdApp = CreateObject("Word.Application")
bWeStartedWord = True
End If
'Handle if Word Application is not found
If Err.Number = 429 Then
MsgBox "Microsoft Word document could not be found, aborting", vbExclamtion, "Microsoft Word Error 429"
GoTo SafeExit:
End If
On Error GoTo 0
'Make MS Word Visible and Active
wrdApp.Visible = True
wrdApp.Activate
'
wrdApp.Visible = True
If newDoc = True Then
Set wrdDoc = wrdApp.Documents.Add 'create as new word document
'Copy table data to word doc
Set tbl = rng 'ThisWorkbook.Sheets("UI").Range("A4:H25")
tbl.Copy
'Paste Table into Word doc
wrdDoc.Paragraphs(1).Range.PasteExcelTable _
LinkedToExcel:=False, _
WordFormatting:=False, _
RTF:=False
'Autofit table to Word doc
Set wordtable = wrdDoc.Tables(1)
wordtable.AutoFitBehavior (wdAutoFitWindow)
Else
'or open an existing document
Set wrdDoc = wrdApp.Documents.Open(filepath) 'wrdApp.Documents.Open("C:\Users\Apache Paint\Desktop\Clients\Stephen Schmitz\TestDocument.docx")
'Copy table data to word doc
With wrdDoc
Set tbl1 = .Tables.Add(Range:=wrdDoc.Paragraphs.Last.Range, _
NumRows:=1, NumColumns:=8, _
AutoFitBehavior:=wdAutoFitWindow) 'autofit content 'DefaultTableBehavior:=wdWord9TableBehavior,
With tbl1
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
End With
Set tbl = rng 'ThisWorkbook.Sheets("UI").Range("A4:H25")
tbl.Copy
Set objRange = wrdDoc.Content
With objRange
.Collapse Direction:=0 'wdCollapseEnd
.InsertAfter vbCrLf
.Collapse Direction:=0
.InsertBreak Type:=wdPageBreak
.Paste '<< paste the table
End With
'Autofit the document
Set wordtable = objRange.Tables(1)
wordtable.AutoFitBehavior (wdAutoFitWindow)
With wordtable
.PreferredWidthType = wdPreferredWidthPercent
.PreferredWidth = 100
End With
End With
filepath = ""
End If
SafeExit:
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.CutCopyMode = False
End Sub
I was able to get it to work with the code below. Thanks to those who suggested I look into ContentControl.
Now I am intermittently getting 'Run-time error 462. The remote server machine does not exist or is unavailable.'
I will update the cooment back here when it is fully resolved.
'Copy table data to word doc
Set tbl = rng 'ThisWorkbook.Sheets("UI").Range("A4:H25")
tbl.Copy
'Paste Table into Word doc
wrdDoc.Paragraphs(1).Range.PasteExcelTable _
LinkedToExcel:=False, _
WordFormatting:=False, _
RTF:=False
'Autofit table to Word doc
Set Wordtable = wrdDoc.Tables(1)
Wordtable.AutoFitBehavior (wdAutoFitWindow)
Dim oRow As Row
'Dim oRng As Range
'Loop through last table column and add Combobox
With Wordtable
For Each oRow In Wordtable.Rows
'Set oRng = oRow.Cells(1).Range
If Len(oRow.Cells(7).Range.Text) > 11 Then
Set objCC = ActiveDocument.ContentControls.Add(wdContentControlDropdownList, oRow.Cells(8).Range)
objCC.Title = "Interpretation"
If objCC.ShowingPlaceholderText Then
objCC.SetPlaceholderText , , "-Select-"
objCC.DropdownListEntries.Add "Far Below Expectaions"
objCC.DropdownListEntries.Add "Below Expectaions"
objCC.DropdownListEntries.Add "Slightly Below Expectaions"
objCC.DropdownListEntries.Add "Significant Difference"
objCC.DropdownListEntries.Add "Valid"
objCC.DropdownListEntries.Add "WNL"
Debug.Print Len(oRow.Cells(7).Range.Text)
End If
Else
End If
Next
End With
so I have the code bellow (its macro sending emails with mail merge from excel file) and when I run it for the first time it's OK but if I run it for the second time I'm getting the 462 (The remove server machine does not exist or is unavailable). I know that this is caused by occupied variable. But I did everything that I know to prevent this. Could someone tell me how to adjust my code so it can run multiple times without closing the file?
Sub Send_Emails()
Application.ScreenUpdating = False
Dim wrd As Word.Application
Dim Doc1 As Document, Doc2 As Document, Doc3 As Document, Doc4 As Document
Dim StrDoc As String, ListOfDocuments As String
Set wrd = CreateObject("Word.Application")
ListOfDocuments = ThisWorkbook.Path & "\Templates\Germany\Supervisors\ListOfDocuments.docx"
Set Doc1 = wrd.Documents.Open(ListOfDocuments)
With Doc1.MailMerge
If .State = wdMainAndDataSource Then
.Destination = wdSendToNewDocument
.Execute
End If
End With
Set Doc2 = ActiveDocument
ActiveDocument.SaveAs (ThisWorkbook.Path & "\Templates\Germany\Supervisors\Recipients.docx")
Call EmailMergeTableMaker(Doc2)
With Doc2
.SaveAs (ThisWorkbook.Path & "\Templates\Germany\Supervisors\Recipients.docx")
End With
Set Doc3 = Documents.Open(Filename:=ThisWorkbook.Path & "\Templates\Germany\Supervisors\SupervisorEmail.docx", _
AddToRecentFiles:=False)
With Doc3.MailMerge
.MainDocumentType = wdEMail
.OpenDataSource Name:=(ThisWorkbook.Path & "\Templates\Germany\Supervisors\Recipients.docx"), ConfirmConversions:=False, ReadOnly:=False, _
LinkToSource:=True, AddToRecentFiles:=False, Connection:="", SQLStatement:="", _
SQLStatement1:="", SubType:=wdMergeSubTypeOther
If .State = wdMainAndDataSource Then
.Destination = wdSendToNewDocument
.Execute
End If
End With
ActiveDocument.SaveAs (ThisWorkbook.Path & "\Templates\Germany\Supervisors\EmailsToSend.docx")
Set Doc4 = Documents.Open(ThisWorkbook.Path & "\Templates\Germany\Supervisors\EmailsToSend.docx")
Doc3.Close SaveChanges:=False
Set Doc3 = Nothing
Call SendEmailsOutlook
Doc1.Close SaveChanges:=False
Doc2.Close SaveChanges:=False
Doc4.Close SaveChanges:=False
Set Doc1 = Nothing
Set Doc2 = Nothing
Set Doc4 = Nothing
wrd.Quit
Set wrd = Nothing
Application.ScreenUpdating = True
'ThisWorkbook.Close
ThisWorkbook.Saved = True
'Application.Quit
End Sub
Sub SendEmailsOutlook()
Dim oItem As Outlook.MailItem
Dim j As Long
Dim oAccount As Outlook.Account
Dim Source As Document, MailList As Document
Dim Recipient As String, MailListDocument As String, SourceDocument As String
MailListDocument = ThisWorkbook.Path & "\Templates\Germany\Supervisors\Recipients.docx"
SourceDocument = ThisWorkbook.Path & "\Templates\Germany\Supervisors\EmailsToSend.docx"
Set MailList = Documents.Open(MailListDocument)
Set Source = Documents.Open(SourceDocument)
For j = 1 To Source.Sections.Count - 1
Set oItem = CreateObject("Outlook.Application").CreateItem(olMailItem)
For Each oAccount In Outlook.Application.Session.Accounts
If oAccount = "xxxxxx" Then 'xxxxxx
With oItem
'.SentOnBehalfOfName = "xxxxxx"
'.Attachments.Add ThisWorkbook.Path & "xxxxxx"
.Subject = "xxxxxx"
.HTMLBody = Source.Sections(j).Range.Text
Recipient = Left(MailList.Tables(1).Cell(j + 1, 1).Range.Text, Len(MailList.Tables(1).Cell(j + 1, 1).Range.Text) - 1)
If Len(Recipient) < 3 Then Exit For
.SendUsingAccount = oAccount
.To = "xxxxxx"
'.To = Recipient
.Send
End With
Set oItem = Nothing
End If
Next
Next j
End Sub
Sub EmailMergeTableMaker(DocName As Document)
Dim oTbl As Object
Dim i As Integer, j As Integer
Dim oRow As Object
Dim oRng As Object
Dim strTxt As String
With DocName
.Paragraphs(1).Range.Delete
Call TableJoiner
For Each oTbl In .Tables
j = 4
With oTbl
i = .Columns.Count - j
For Each oRow In .Rows
Set oRng = oRow.Cells(j).Range
With oRng
.MoveEnd Unit:=wdCell, Count:=i
.Cells.Merge
strTxt = Replace(.Text, vbCr, vbTab)
On Error Resume Next
If Len(strTxt) > 1 Then .Text = Left(strTxt, Len(strTxt) - 2)
End With
Next
End With
Next
For Each oTbl In .Tables
For i = 1 To j
oTbl.Columns(i).Cells.Merge
Next
Next
With .Tables(1)
.Rows.Add BeforeRow:=.Rows(1)
.Cell(1, 1).Range.Text = "Recipient"
.Cell(1, 2).Range.Text = "Name"
.Cell(1, 3).Range.Text = "Gender"
.Cell(1, 4).Range.Text = "List"
End With
.Paragraphs(1).Range.Delete
Call TableJoiner
End With
Set oRng = Nothing
End Sub
Private Sub TableJoiner()
Dim wrd2 As Object, doc As Object, tbl As Object
Dim oTbl As Table
Set wrd2 = GetObject(, "Word.Application")
Set doc = wrd2.Documents.Open(ThisWorkbook.Path & "\Templates\Germany\Supervisors\Recipients.docx")
For Each tbl In doc.Tables
With tbl.Range.Next
If .Information(wdWithInTable) = False Then .Delete
End With
Next
Set wrd = Nothing
End Sub
Thank for any suggestions!
I am having an excel with two columns Requirement and Source. I have another Word document with Requirement which are there in excel. I want it to be matched. If it is matched then its corresponding source need to be sent to Requirement in word document.
The excel file data:
In the word document the data should be displayed like this:
enter image description here
I tried in this way:
Sub SearchItem()
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
Dim CurrRowShtSearchItem As Long
Dim CurrRowShtExtract As Long
Dim myPara As Long
On Error Resume Next
Set oWord = GetObject(, "Word.Application")
If Err Then
Set oWord = New Word.Application
WordNotOpen = True
End If
On Error GoTo Err_Handler
oWord.Visible = True
oWord.Activate
Set oDoc = oWord.Documents.Open("File Location")
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
If .Found Then
oRange.InsertAfter ("Reference" & ":") ' <= what need to be done?
End If
oRange.Start = oRange.End
oRange.End = ActiveDocument.Range.End
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
Please Help. Thank You
Try something based on:
Sub SendRefsToDoc()
'Note: A reference to the Word library must be set, via Tools|References
Dim wdApp As New Word.Application, wdDoc As Word.Document, StrNm As String
Dim r As Long, xlFList As String, xlRList As String
StrNm = "C:\Users\" & Environ("UserName") & "\Documents\MyDocument.docx"
If Dir(StrNm) <> "" Then
With Worksheets("Sheet1")
For r = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
If .Range("A" & r).Text = "" Then
xlRList = xlRList & ", " & Trim(.Range("B" & r))
Else
xlFList = xlFList & "|" & Trim(.Range("A" & r))
xlRList = xlRList & "|" & Trim(.Range("B" & r))
End If
Next
End With
With wdApp
.Visible = False
Set wdDoc = Documents.Open(Filename:=StrNm, AddToRecentFiles:=False, Visible:=False)
With wdDoc
For r = 1 To UBound(Split(xlFList, "|"))
With .Range
With .Find
.Replacement.ClearFormatting
.Text = Split(xlFList, "|")(r)
.Replacement.Text = ""
.Forward = True
.Format = False
.Wrap = wdFindStop
End With
Do While .Find.Execute
.Paragraphs.First.Range.Characters.Last.InsertBefore vbCr _
& "Reference: " & Split(xlRList, "|")(r)
With .Paragraphs.First.Range.Font
.Bold = True
.Italic = True
End With
With .Paragraphs.Last.Range.Font
.Bold = False
.Italic = False
End With
.Collapse wdCollapseEnd
Loop
End With
Next
.Close True
End With
.Quit
End With
Else
MsgBox "File not found: " & vbCr & StrNm, vbExclamation
End If
Set wdDoc = Nothing: Set wdApp = Nothing
End Sub
I have used the VBA macro below to put multiple tables from multiple Word documents into one worksheet in Excel.
I want the multiple tables from each different Word doc to go into different worksheets with the worksheets named the name of the Word doc.
Sub ImportWordTable()
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 '(user cancelled import file browser)
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
Range("A:AZ").ClearContents
Set Target = Range("A1")
For Each FileName In arrFileList
Set WordDoc = WordApp.Documents.Open(FileName, ReadOnly:=True)
With WordDoc
tableNo = WordDoc.tables.Count
tableTot = WordDoc.tables.Count
If tableNo = 0 Then
MsgBox WordDoc.Name & " contains no tables", vbExclamation, "Import Word Table"
ElseIf tableNo > 1 Then
tableNo = InputBox(WordDoc.Name & " contains " & tableNo & " tables." & vbCrLf & _
"Enter the table to start from", "Import Word Table", "1")
End If
For tableStart = 1 To tableTot
With .tables(tableStart)
.Range.Copy
'Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
Target.Activate
ActiveSheet.Paste
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableStart
.Close False
End With
Next FileName
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
Try the following macro. It allows you to choose the source folder. It creates a new worksheet for each document and outputs all tables from that document one below the other, with an empty row in between. Except for text wrapping, table formatting is preserved as much as possible.
Sub GetTableData()
'Note: this code requires a reference to the Word object model.
'See under the VBE's Tools|References.
Application.ScreenUpdating = False
Dim wdApp As New Word.Application, wdDoc As Word.Document, wdTbl As Word.Table
Dim strFolder As String, strFile As String, WkBk As Workbook, WkSht As Worksheet, r As Long
strFolder = GetFolder: If strFolder = "" Then GoTo ErrExit
Set WkBk = ActiveWorkbook
'Disable any Word Alerts
wdApp.DisplayAlerts =wdAlertsNone
'Disable any auto macros in the documents being processed
wdApp.WordBasic.DisableAutoMacros
strFile = Dir(strFolder & "\*.doc", vbNormal)
While strFile <> ""
Set wdDoc = wdApp.Documents.Open(Filename:=strFolder & "\" & strFile, ReadOnly:=True, AddToRecentFiles:=False, Visible:=False)
Set WkSht = WkBk.Sheets.Add
WkSht.Name = Split(strFile, ".doc")(0)
With wdDoc
For Each wdTbl In .Tables
With wdTbl.Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "[^13^l]"
.Replacement.Text = "¶"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
r = WkSht.Cells(WkSht.Rows.Count, 1).End(xlUp).Row
If r > 1 Then r = r + 2
wdTbl.Range.Copy
WkSht.Paste Destination:=WkSht.Range("A" & r)
Next
WkSht.UsedRange.Replace What:="¶", Replacement:=Chr(10), LookAt:=xlPart, SearchOrder:=xlByRows
.Close SaveChanges:=False
End With
strFile = Dir()
Wend
ErrExit:
wdApp.Quit
Set wdDoc = Nothing: Set wdApp = Nothing: Set WkSht = Nothing: Set WkBk = Nothing
Application.ScreenUpdating = True
End Sub
Function GetFolder() As String
Dim oFolder As Object
GetFolder = ""
Set oFolder = CreateObject("Shell.Application").BrowseForFolder(0, "Choose a folder", 0)
If (Not oFolder Is Nothing) Then GetFolder = oFolder.Items.Item.Path
Set oFolder = Nothing
End Function
Something like the following, perhaps. Since I can't replicate your documents my test environment wasn't identical...
The following code declares a Word.Table and a Excel.Worksheet object to the list of declared variables.
The Worksheet object is set to ActiveSheet and later to each added worksheet. Using an object instead of a selection or "active" something is almost always preferable - then it's clearer for both human and VBA what's is meant. ws is also used to more exactly define the Range specifications.
Before looping the tables, the worksheet Name is set to the value stored in Filename for the Word document.
The Table object is set to the WordDoc.tables(tableStart) table. It's more efficient to work with an object instead of querying the full "path" to an object each time. It's also easier to read.
Before looping to the next Word document a new worksheet is added.
Sub ImportWordTable()
Dim WordApp As Object
Dim WordDoc As Object
Dim tbl 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 ws As Worksheet
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 '(user cancelled import file browser)
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
Set ws = ActiveSheet
ws.Range("A:AZ").ClearContents
For Each FileName In arrFileList
Set WordDoc = WordApp.Documents.Open(FileName, ReadOnly:=True)
With WordDoc
tableNo = WordDoc.tables.Count
tableTot = WordDoc.tables.Count
If tableNo = 0 Then
MsgBox WordDoc.Name & " contains no tables", vbExclamation, "Import Word Table"
ElseIf tableNo > 1 Then
tableNo = InputBox(WordDoc.Name & " contains " & tableNo & " tables." & vbCrLf & _
"Enter the table to start from", "Import Word Table", "1")
End If
ws.Name = FileName
For tableStart = 1 To tableTot
Set Target = ws.Range("A1")
Set tbl = .tables(tableStart)
With tbl
.Range.Copy
'Target.Parent.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
Target.Activate
ws.Paste
Set Target = Target.Offset(.Rows.Count + 2, 0)
End With
Next tableStart
.Close False
End With
Set ws = ws.Parent.Worksheets.Add
Next FileName
ws.Delete 'the last sheet is one too many
WordApp.Quit
Set WordDoc = Nothing
Set WordApp = Nothing
End Sub
I am exporting all the data of a ListView control to an Excel sheet, in VB 6.0.
My code is below:
Private Sub cmdExport_Click()
'general
Dim objExcel As New Excel.Application
Dim objExcelSheet As Excel.Worksheet
'-----------------------------------
'check whether data is there
If LstLog.ListItems.count > 0 Then
objExcel.Workbooks.Add
Set objExcelSheet = objExcel.Worksheets.Add
For Col = 1 To LstLog.ColumnHeaders.count
objExcelSheet.Cells(1, Col).Value = LstLog.ColumnHeaders(Col)
Next
For Row = 2 To LstLog.ListItems.count
For Col = 1 To LstLog.ColumnHeaders.count
If Col = 1 Then
objExcelSheet.Cells(Row, Col).Value = LstLog.ListItems(Row).Text
Else
objExcelSheet.Cells(Row, Col).Value = LstLog.ListItems(Row).SubItems(Col - 1)
End If
Next
Next
objExcelSheet.Columns.AutoFit
CommonDialog1.ShowOpen
A = CommonDialog1.FileName
objExcelSheet.SaveAs A & ".xls"
MsgBox "Export Completed", vbInformation, Me.Caption
objExcel.Workbooks.Open A & ".xls"
objExcel.Visible = True
'objExcel.Quit
Else
MsgBox "No data to export", vbInformation, Me.Caption
End If
End Sub
The problem is that the first row from the ListView is covered by text from the ListView header.
You are not copying all the rows, for some reason. Try this:
For Row = 2 To LstLog.ListItems.count + 1
For Col = 1 To LstLog.ColumnHeaders.count
If Col = 1 Then
objExcelSheet.Cells(Row, Col).Value = LstLog.ListItems(Row - 1).Text
Else
objExcelSheet.Cells(Row, Col).Value = LstLog.ListItems(Row - 1).SubItems(Col - 1)
End If
Next
Next Row
Try this hope this will help u
Function Export2XLS(sQuery As String)
Dim oExcel As Object
Dim oExcelWrkBk As Object
Dim oExcelWrSht As Object
Dim bExcelOpened As Boolean
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim iCols As Integer
Const xlCenter = -4108
'Start Excel
On Error Resume Next
Set oExcel = GetObject(, "Excel.Application") 'Bind to existing instance of Excel
If Err.Number <> 0 Then 'Could not get instance of Excel, so create a new one
Err.Clear
On Error GoTo Error_Handler
Set oExcel = CreateObject("excel.application")
bExcelOpened = False
Else 'Excel was already running
bExcelOpened = True
End If
On Error GoTo Error_Handler
oExcel.ScreenUpdating = False
oExcel.Visible = False 'Keep Excel hidden until we are done with our manipulation
Set oExcelWrkBk = oExcel.Workbooks.Add() 'Start a new workbook
Set oExcelWrSht = oExcelWrkBk.Sheets(1)
'Open our SQL Statement, Table, Query
Set db = CurrentDb
Set rs = db.OpenRecordset(sQuery, dbOpenSnapshot)
With rs
If .RecordCount <> 0 Then
'Build our Header
For iCols = 0 To rs.Fields.Count - 1
oExcelWrSht.Cells(1, iCols + 1).Value = rs.Fields(iCols).Name
Next
With oExcelWrSht.Range(oExcelWrSht.Cells(1, 1), _
oExcelWrSht.Cells(1, rs.Fields.Count))
.Font.Bold = True
.Font.ColorIndex = 2
.Interior.ColorIndex = 1
.HorizontalAlignment = xlCenter
End With
oExcelWrSht.Range(oExcelWrSht.Cells(1, 1), _
oExcelWrSht.Cells(1, rs.Fields.Count)).Columns.AutoFit 'Resize our Columns based on the headings
'Copy the data from our query into Excel
oExcelWrSht.Range("A2").CopyFromRecordset rs
oExcelWrSht.Range("A1").Select 'Return to the top of the page
Else
MsgBox "There are no records returned by the specified queries/SQL statement.", vbCritical + vbOKOnly, "No data to generate an Excel spreadsheet with"
GoTo Error_Handler_Exit
End If
End With
' oExcelWrkBk.Close True, sFileName 'Save and close the generated workbook
' 'Close excel if is wasn't originally running
' If bExcelOpened = False Then
' oExcel.Quit
' End If
Error_Handler_Exit:
On Error Resume Next
oExcel.Visible = True 'Make excel visible to the user
rs.Close
Set rs = Nothing
Set db = Nothing
Set oExcelWrSht = Nothing
Set oExcelWrkBk = Nothing
oExcel.ScreenUpdating = True
Set oExcel = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: Export2XLS" & vbCrLf & _
"Error Description: " & Err.Description _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Function