I've inherited some VBA code which copies the contents of tables in a Word document to Excel. The code itself is from an Excel addin which invokes Word using late binding to avoid the reference error when used in older versions of Excel. The addin itself is maintained in Office 2016 while also being used in Office 2016, 2013, and 2010.
The heart of the program is the following:
tc = 1 ' table counter
For Each tbl In doc.Tables
prev = -42 ' previous row
Application.Wait DateAdd("s", 2, Now) ' Note this line
For Each cel In tbl.Range.Cells
cont = CellContents(cel.Range) ' dim cont() as string
txt = cont(0)
xx = cel.ColumnIndex
yy = cel.RowIndex
If yy <> prev Then
xtra = 1 ' extra x cell counter
prev = yy ' reset for new row
End If
xtra = xtra - 1
For Each v In cont ' dim v as variant
txt = CStr(v)
ActiveSheet.Cells(xlrow + yy, xtra + xx).Activate
ActiveCell = txt
ActiveCell.Font.Bold = cel.Range.Bold
colr = cel.Range.Font.Color
ActiveCell.Font.Color = colr
colr = cel.Shading.BackgroundPatternColor
If colr <> -16777216 Then ActiveCell.Interior.Color = colr
Select Case cel.Range.ParagraphFormat.Alignment
Case 2 ' wdAlignParagraphRight
ActiveCell.HorizontalAlignment = xlRight
Case 1 ' wdAlignParagraphCenter
ActiveCell.HorizontalAlignment = xlCenter
Case 0, 3 ' wdAlignParagraphLeft, wdAlignParagraphJustify
ActiveCell.HorizontalAlignment = xlLeft
Case Else
End Select
xtra = xtra + 1
Next v
Next cel
xlrow = xlrow + tbl.rows.Count + 1
Application.StatusBar = "Table " & tc & " in " & nm
DoEvents
tc = tc + 1
Next tbl
No, copy paste from Word to Excel won't do as it does not do any processing, does not handle text copy from cell to cell well, does not handle cell breaks well, nor does it handle content controls.
I've observed a problem when this procedure is copying a large number of large tables from Word, it will miss a table. However, when I slow down the process, either by forcing a stop in the debugger or adding an Application.Wait
in the loop, the problem disappears.
The code does the following:
- For a document, loop over all tables in the document
- Then for a table, loop over all cells in that table and copy them over to Excel, preserving the background and foreground colours
A typical document may have 10 to 20 tables with 50 or more cells each.
It's almost as if when iterating through the tables, if VBA is still busy, subsequent tables are returned empty.
I have tried the following:
- Changing to Word Automation using Early Binding
- Getting rid of the
ActiveSheet.Cells(...).Activate
thing and usingCells(y, x)
instead - For loop using counter and
set tbl = doc.tables(tc)
andset tbl = Nothing
at the end of the loop - Multiple DoEvents
- Just setting the cell's text and nothing else, minimal work in the loop (Here I lost less data)
There was no change to the behaviour. Simply treacherous. ужас.
Is there a better way to do this, without Application.Wait
or sleep
? How to determine that Excel is really done before starting on the next iteration?