Reputation: 83
I have a Word document that is used as a template (but is not a Word template, just a .doc file) with tables in them that I need to populate with data. I am not having trouble populating the tables with data or writing anything that I need. The problem I am having is that it is taking forever to write the data because Word appears to be typing the text out in real-time.
The only possible solution I have seen online is to set.Visible = False, but I am doing that and it takes about 10 minutes to write 1000 rows of data.
I am upgrading a report application that was able to do the same thing in 5 seconds but it was written in VB6, so I can't imagine that it can't go just as fast in .NET.
Here's the setup for the code example below: I have the data in a .NET DataTable with a bookmark name and a value. Multiple occurrences of the bookmark name identify which table these should go into. All of that is irrelevant because it all works, unless I am doing it in a way that causes .TypeText() to go really slow. I even did some debugging and just the .TypeText() appears to take 1 whole second each time, which makes 1000 rows take anywhere from 10-15 minutes to write out.
Dim WordApp As New Word.Application()
WordApp.Documents.Open("C:\Report_Template.doc", [ReadOnly]:=True)
With WordApp
Try
.Visible = False
.ActiveDocument.SaveAs2("C:\Report.doc")
.ActiveWindow.View.ReadingLayout = False
With .Selection
Dim Bookmark As String
For Each BookmarkRow As DataRow In MyDataTable
Bookmark = BookmarkRow("Bookmark")
'create a sub datatable of each distinct bookmark name
Dim BookmarkView As New DataView(dtItemizedValues)
BookmarkView.RowFilter = "BOOKMARK = '" & Bookmark & "'"
Dim BookmarkData As DataTable = BookmarkView.ToTable()
'go to the bookmark
.GoTo(Word.WdGoToItem.wdGoToBookmark, , , Bookmark)
'move to the table for this section
.GoTo(Word.WdGoToItem.wdGoToTable, Word.WdGoToDirection.wdGoToNext)
'loop through rows
For Each Row As DataRow In BookmarkData.Rows
If .Text.Length > 0 Then
.SelectCell()
.Cut()
End If
.TypeText(Text:=Row("Value"))
'move to next row
.Move(Word.WdUnits.wdRow)
Next 'row
Next 'bookmark
End With 'with .selection
.ActiveDocument.Close(SaveChanges:=True)
Catch ex As Exception
.ActiveDocument.Close()
Finally
WordApp.Quit(False)
End Try
End With 'with .wordapp
Upvotes: 0
Views: 1722
Reputation: 25673
I wrote an article about this, many years ago... Constructing a table, cell-by-cell or row-by-row and filling it with data is slow. And the longer the table gets, the slower things become due to how Word repaginates.
The essential steps for achieving top efficiency are:
Range
object in WordConvertToTable
to turn the string into a tableSimple sample:
//Insert table at end of currently active document
Sub ConvertTextStringToTable()
Dim doc As Word.Document = Word.Application.ActiveDocument
Dim rng As Word.Range = doc.Content
Dim data As String
data = "one" & vbTab & "two" & vbTab & "three" & vbCr & _
"1" & vbTab & "2" & vbTab & "3" & vbCr
rng.Collapse(Word.WdCollapseDirection.wdCollapseEnd)
rng.Text = data
Dim tbl as Word.Table = rng.ConvertToTable(vbTab)
End Sub
Upvotes: 3