PDA

View Full Version : Solved: Searching for Tables



gcatlin
07-17-2008, 07:33 AM
Hello,

I am using VBA to parse a Word document and extract portions to a spreadsheet. I am scanning the document using the "Paragraphs" object until I find the desired document section. Once located, I want to locate the next Table in the document. I know about the "Tables" object, but not sure how to go about finding a table once a specific paragraph has been located. Any guidance would be appreciated.

The following is the starting portion of my search.

For i = 1 To wdDoc.Paragraphs.Count
wdDoc.Paragraphs(i).Range.Select

'Check for Heading4 paragraphs
If wdDoc.Paragraphs(i).Style = "Heading 4" Then
and so on...

Thank you.

gmc

fumei
07-17-2008, 10:16 AM
Avoid using Selection unless you have to. Sometimes you do, but most times you do not.

In the first part of your code (going through the paragraphs), unless you actually need to - and I do not see that you do - do not select each paragraph.

I take it you are making an instance of Word from some other application, as you are using wdDoc. Or, is wdDoc a Document object? It may help to state that. In any case...
Dim oPara As Paragraph
For Each oPara In wdDoc.Paragraphs
If oPara.Style = "Heading 4" Then
.....

Now, what exactly do you mean by "Once located, I want to locate the next Table in the document."

Locate. Do you need to select it? Do something with it?

Demo doc attached. Click "Next Table" on the top toolbar. It fires the Sub yadda, as follows.


Option Explicit

Function CellText(strIn As String) As String
CellText = Left(strIn, Len(strIn) - 2)
End Function


Sub yadda()
Dim oPara As Paragraph
Dim r As Range
Dim oTable As Table
For Each oPara In ActiveDocument.Paragraphs
If oPara.Style = "Heading 4" Then
Set r = oPara.Range.Next(Unit:=wdTable, Count:=1)
Set oTable = r.Tables(1)
MsgBox CellText(oTable.Cell(1, 1).Range.Text)
End If
Next
End Sub

Nothing is selected. A paragraph object is used to go through the paragraph collection.

If an oPara has "Heading 4" style, a Range object is set for the NEXT table.

A Table object is set for Table(1) of the Range.

A messagebox displays the text content of the first cell, using the Table object. As it IS a Table object, all properties and methods for action on the table are available.

gcatlin
07-18-2008, 05:42 AM
Thank you for your reply, fumei. Sorry for not being more explicit in my original post.

I am using my code within MS Excel and referencing an external MS Word document, from which I am attempting to extract certain portions from paragraphs and tables and store them in my Excel spreadsheet. I was using the following to define my MS Word object:

Dim wdApp As Word.Application
Dim wdDoc As Word.Document

On Error Resume Next
Set wdApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then 'Word isn't already running
Set wdApp = CreateObject("Word.Application")
End If
On Error GoTo 0

Set wdDoc = wdApp.Documents.Open(ThisWorkbook.Path & "\MyDocument.doc")

I used your example directly in MS Word and it seems to do what I need it to do. I was able to tweak it to do additional tasks (like findings the second table, etc.) However, when I use the same elements in my MS Excel code, I get a runtime error:

Run-time error '13':
Type mismatch

It seems to be bombing out at the following statement:

Set r = oPara.Range.Next(Unit:=wdTable, Count:=1)

Please let me know what changes have to be made to this statement so it might function in the MS Excel worksheet.

Thank you for your assistance so far.

gmc

fumei
07-18-2008, 09:18 AM
Simple, and a common mistake, so please do not think I am being critical.

When you make an instance of another application - in this case, you are creating an instance of Word, from Excel - you must fully qualify objects for that instance. I do not know if you did this, as you did not post full code.

How, exactly, did you Dim r? oTable? oPara?

If you did it as Dim r As Range...then:

Set r = oPara.Range.Next(Unit:=wdTable, Count:=1)

will indeed fail. Why? Because r is being declared as an Excel range, not a Word range. Remember the declaration is being done in Excel...not Word. And Excel has a Range object. It is quite different from a Word Range object. As I stated, this is a quite common mistake, actioning Word from Excel. I suspect this is the problem. Try something like:
Sub blah()
Dim wdApp As Word.Application
Dim wdDoc As Word.Document
Dim r As Word.Range
Dim oPara As Word.Paragraph
Dim oTable As Word.Table

On Error Resume Next
Set wdApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then 'Word isn't already running
Set wdApp = CreateObject("Word.Application")
End If
On Error GoTo 0

Set wdDoc = _
wdApp.Documents.Open(Filename:="c:\zzz\NextTable.doc")

For Each oPara In wdDoc.Paragraphs
If oPara.Style = "Heading 4" Then
Set r = oPara.Range.Next(Unit:=wdTable, Count:=1)
Set oTable = r.Tables(1)
MsgBox oTable.Cell(1, 1).Range.Text
End If
Next
wdDoc.Close
Set wdDoc = Nothing

wdApp.Quit
Set wdApp = Nothing
End Sub

The code above works fine from Excel. Of course you would have to change the filename to your filename.

1. I hope you are using Option Explicit

2. I hope you are fully destroying your objects/instance correctly. The Set wdDoc = Nothing...

gcatlin
07-18-2008, 12:32 PM
Thank you, fumei. No, you are not being overly critical. I am new at this, and consider myself just a 'hack'. Also, I learned what I know today (re VBA) from another hack.

Anyway, you were exactly right. Once I refined the Range element more correctly as Word.Range, all worked just fine. It makes perfect sense, since Range has different meaning s in the two applications. I have redone my code to make sure that my definitions are all proper and non-ambiguous.

I appreciate all the help and patience that you have shown. I am certain that this will only bring on a few other questions, once I get to that portion of the code, or want to perform a few more complex searches.

Thank you again. I will mark this as "solved". I will also pass this information on to my "hack" colleague.