Alexander (HH): Word 2002 Automation: Überschrift und Text zu einer Tabelle

Moin Moin!

Mal wieder ein Wald-und-Bäume-Problem:

Ich habe ein riesiges Word(2002)-Dokument mit knapp 600 Tabellen, jede Tabelle hat einen einleitenden Text und eine Überschrift, manchen Tabellen folgt auch noch etwas Text.

Die Tabellen kann ich über Automation ziemlich schmerzfrei finden, weil praktischerweise direkt am Document-Objekt eine Tables-Liste hängt. Die Liste mit den knapp 600 Table-Objekten kann ich durchlaufen und mir die Texte aus den einzelnen Zellen herausfummeln.

Ich finde aber keinen Weg, von der Tabelle zur Überschrift zu kommen, denn in der steckt noch eine Information, die ich unbedingt brauche. Mit dem HTML-DOM wäre das Problem mit tabelle.parentNode.getElementsByTagName("h2")[0] erschlagen. Wie geht das mit Word?

Alexander

  
#!/usr/bin/perl  
  
use strict;  
use warnings;  
use 5.010;  
use Win32::OLE;  
  
$|=1;  
  
sub enum  
{  
	return Win32::OLE::Enum->new($_[0]);  
}  
  
my $filename='E:\\tables.doc';  
  
my $word=Win32::OLE->CreateObject('Word.Application','Quit') or die $!;  
$word->{'Visible'}=1;  
  
my $doc=$word->Documents->Open($filename) or die "Can't open '$filename': ",Win32::OLE->LastError();  
  
print "Word opened\n";  
  
my $n=$doc->Tables->Count();  
print "$n tables in the file\n";  
  
my $tables=enum($doc->Tables);  
my $i=0;  
while (my $table=$tables->Next()) {  
	print "New Table\n";  
	my $rows=enum($table->Rows());  
	while (my $row=$rows->Next()) {  
		print "\tNew Row\n";  
		my $cells=enum($row->Cells());  
		while (my $cell=$cells->Next()) {  
			my $range=$cell->Range();  
			$range->{'End'}--; # a Range created from a cell contains a special end-of-cell marker. To access only the text in a cell, move the end of the range back one character.  
			print "\t\t (row=",$cell->{'RowIndex'},", col=",$cell->{'ColumnIndex'},") \"",$range->Text(),"\"\n";  
		}  
	}  
	last if ++$i>2; # for Debugging  
}  
  
$doc->Close();  
$word->Quit();  
  

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
  1. Hallo,

    Ich habe ein riesiges Word(2002)-Dokument mit knapp 600 Tabellen, jede Tabelle hat einen einleitenden Text und eine Überschrift, manchen Tabellen folgt auch noch etwas Text.

    Word 2002 hab' ich nicht, mit Perl hab' ich wenig am Hut, aber VBA sollte sich leicht in Perl-Word-Automation übersetzen lassen.

    Ich vermute, dass Dir das Range-Objekt weiterhelfen kann:

    ' Gibt Formatvorlage sowie Textinhalt des Absatzes vor dem Absatz, der eine
    ' Tabelle enthält, aus.
    ' enthält weder Fehlerbehandlung noch werden verschachtelte Tabellen berücksichtigt.
    ' Gegebenenfalls im Objektkatalog nachschauen, wofür die Konstante
    '     wdParagraph
    ' steht.
    Sub test()
        Dim r As Range
        Dim t As Table

    For Each t In ActiveDocument.Tables
            Set r = t.Range
            ' gehe zum Absatz vor dem Absatz, der die Tabelle enthält
            r.MoveStart wdParagraph, -1
            r.MoveEnd wdParagraph, -1
            ' Name der Absatzvorlage
            ' Beachte: Index beginnt bei 1
            Debug.Print r.Paragraphs(1).Style
            ' Textinhalt des Absatzes
            ' Beachte: Textinhalt ist keine direkte Eigenschaft des
            '          Paragraph-Objektes.
            Debug.Print r.Paragraphs(1).Range.Text
        Next t

    End Sub

    Freundliche Grüße

    Vinzenz

    1. Moin Moin!

      Ich habe ein riesiges Word(2002)-Dokument mit knapp 600 Tabellen, jede Tabelle hat einen einleitenden Text und eine Überschrift, manchen Tabellen folgt auch noch etwas Text.

      Es hat sich rausgestellt, dass die Tabellen auch noch einige strukturelle Schäden hatten, sinngemäß so etwas:

        
      <tr><td colspan=2>bla</td><td>bla</td></tr>  
      <tr><td>bla</td><td colspan=2>bla</td></tr>  
      
      

      Das sieht zwar optisch fast identisch aus wie die Version ohne colspan, macht beim Zerlegen aber mehr Mühe.

      Dazu kommen noch lustige Geschichten wie "durchgebrochene" Tabellen, die mittendrin aufhören und mit einer neuen, kopflosen Tabelle fortgeführt werden.

      Word 2002 hab' ich nicht, mit Perl hab' ich wenig am Hut, aber VBA sollte sich leicht in Perl-Word-Automation übersetzen lassen.

      Ich vermute, dass Dir das Range-Objekt weiterhelfen kann:

      For Each t In ActiveDocument.Tables
              Set r = t.Range
              ' gehe zum Absatz vor dem Absatz, der die Tabelle enthält
              r.MoveStart wdParagraph, -1
              r.MoveEnd wdParagraph, -1

      Sehr interessanter Ansatz. Ich bin davon ausgegangen, dass das Range-Objekt jeweils auf das übergeordnete Objekt begrenzt ist, ich mit dem Range also nicht aus der Tabelle herauskomme.

      Letzten Endes habe ich die Datei in Word als gefiltertes HTML gespeichert und mit XML::LibXML in mehreren Schritten aufgeräumt, ausgemistet, und die gewünschten Daten herausgefummelt. Damit hab ich zwar immer noch keinen Plan, wie genau die Automation tickt, aber ich habe mein Ergebnis. Das war im Moment wichtiger.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".