Извлекать необработанные данные из таблиц в Word? используя Perl - PullRequest
1 голос
/ 19 июля 2011

Я пытаюсь извлечь данные из нескольких таблиц в документе Word.При попытке преобразовать данные в таблицах в текст, я получаю сообщение об ошибке.У метода ConvertToText есть два необязательных параметра (как разделить данные и логический). Вот мой текущий код:

#usr/bin/perl
#OLEWord.pl

#Use string and print warnings
use strict;use warnings;
#Using OLE + OLE constants for Variants and OLE enumeration for Enumerations
use Win32::OLE qw(in);
use Win32::OLE::Const 'Microsoft Word';
use Win32::OLE::Variant;

my $var1 = Win32::OLE::Variant->new(VT_BOOL, 'true');

$Win32::OLE::Warn = 3;

#set the file to be opened
my $file = 'C:\work\SCL_International Financial New Fund Setup Questionnaire V1.6.docx';

#Create a new instance of Win32::OLE for the Word application, die if could not open the application
my $MSWord = Win32::OLE->GetActiveObject('Excel.Application') or Win32::OLE->new('Word.Application','Quit');

#Set the screen to Visible, so that you can see what is going on
$MSWord->{'Visible'} = 1;
 $MSWord->{'DisplayAlerts'} = 0; #Supress Alerts, such as 'Save As....'

#open the request file or die and print warning message
my $Doc = $MSWord->{'Documents'}->Open($file) or die "Could not open ", $file, " Error:", Win32::OLE->LastError();

#$MSWord->ActiveDocument->SaveAs({Filename => 'AlteredTest.docx', 
                            #FileFormat => wdFormatDocument});

my $tables = $MSWord->ActiveDocument->{'Tables'};

for my $table (in $tables){
   my $tableText = $table->ConverToText(wdSeparateByParagraphs,$var1);
   print "Table: ", $tableText, "\n";
}


$MSWord->ActiveDocument->Close;
$MSWord->Quit;

, и я получаю эту ошибку:

Базовое слово «VT_BOOL» не допускается, когда «строгие сабы» используются в строке OLEWord.pl 31
Баресловое слово «true» не допускается, когда «строгие сабы» используются в строке OLEWord.pl 31
Выполнение OLEWord.pl прервано из-за ошибок компиляции.

Ответы [ 4 ]

3 голосов
/ 19 июля 2011

Когда такие вещи, как VT_BOOL не определены как константы, Perl будет считать их голыми словами.Другие уже предоставили информацию о них.

Основной причиной вашей проблемы являются отсутствующие константы, которые экспортируются модулем Win32 :: OLE :: Variant .Добавьте:

use Win32::OLE::Variant;

в ваш скрипт, чтобы удалить первую ошибку.Вторая проблема похожа, true также не определена.Замените его на 1 или определите константу самостоятельно:

use constant true => 1;

Редактировать: Вот пример извлечения текста таблицы:

my $tables = $MSWord->ActiveDocument->{'Tables'};
for my $table (in $tables){
   my $tableText = $table->ConvertToText({ Separator => wdSeparateByTabs });
   print "Table: ", $tableText->Text(), "\n";
}

В вашем кодеопечатка в имени метода ConverToText.Также метод возвращает объект Range, поэтому вы должны использовать метод Text, чтобы получить реальный текст.

2 голосов
/ 19 июля 2011

Ошибка 'Bareword' вызвана синтаксической ошибкой в ​​вашем коде. «убегающие многострочные» обычно указывают, где начинается ошибка и обычно означает, что строка не была завершена, часто из-за несоответствующих скобок или кавычек.

Как указывалось несколькими SO, это не похоже на Perl! Интерпретатор Perl блокирует синтаксическую ошибку, потому что он не говорит на этом конкретном языке! Источник

Если не использовать строгий, вы не получите предупреждение. (Но вы должны использовать его для хорошего кода)

Прочтите о Bareword, чтобы вы знали, что это такое, и вы сами знаете, как можно исправить эту ошибку.

Вот несколько ссылок для изучения Bareword: 1. perl.com 2. выпускник

1 голос
/ 19 июля 2011

удаление «использовать строго» удалит ошибки «Bareword»

0 голосов
/ 11 февраля 2015

извлечь все таблицы документов в один файл xls

     sub doParseDoc {

           my $msg     = '' ; 
           my $ret     = 1 ; # assume failure at the beginning ...

           $msg        = 'START --- doParseDoc' ; 
           $objLogger->LogDebugMsg( $msg );
           $msg        = 'using the following DocFile: "' . $DocFile . '"' ; 
           $objLogger->LogInfoMsg( $msg );
           #-----------------------------------------------------------------------
           #Using OLE + OLE constants for Variants and OLE enumeration for Enumerations


           # Create a new Excel workbook
           my $objWorkBook = Spreadsheet::WriteExcel->new("$DocFile" . '.xls');

           # Add a worksheet
           my $objWorkSheet = $objWorkBook->add_worksheet();


           my $var1 = Win32::OLE::Variant->new(VT_BOOL, 'true');

           Win32::OLE->Option(Warn => \&Carp::croak);
           use constant true => 0;

           # at this point you should have the Word application opened in UI with t
           # the DocFile
           # build the MS Word object during run-time 
           my $objMSWord = Win32::OLE->GetActiveObject('Word.Application')
                             or Win32::OLE->new('Word.Application', 'Quit');  

           # build the doc object during run-time 
           my $objDoc   = $objMSWord->Documents->Open($DocFile)
                 or die "Could not open ", $DocFile, " Error:", Win32::OLE->LastError();

           #Set the screen to Visible, so that you can see what is going on
           $objMSWord->{'Visible'} = 1;
           # try NOT printing directly to the file


            #$objMSWord->ActiveDocument->SaveAs({Filename => 'AlteredTest.docx', 
                                        #FileFormat => wdFormatDocument});

           my $tables        = $objMSWord->ActiveDocument->Tables();
           my $tableText     = '' ;   
           my $xlsRow        = 1 ; 

           for my $table (in $tables){
              # extract the table text as a single string
              #$tableText = $table->ConvertToText({ Separator => 'wdSeparateByTabs' });
              # cheated those properties from here: 
              # https://msdn.microsoft.com/en-us/library/aa537149(v=office.11).aspx#officewordautomatingtablesdata_populateatablewithdata
              my $RowsCount = $table->{'Rows'}->{'Count'} ; 
              my $ColsCount = $table->{'Columns'}->{'Count'} ; 

              # disgard the tables having different than 5 columns count
              next unless ( $ColsCount == 5 ) ;

              $msg           = "Rows Count: $RowsCount " ; 
              $msg           .= "Cols Count: $ColsCount " ; 
              $objLogger->LogDebugMsg ( $msg ) ; 

              #my $tableRange = $table->ConvertToText({ Separator => '##' });
              # OBS !!! simple print WILL print to your doc file use Select ?!
              #$objLogger->LogDebugMsg ( $tableRange . "\n" );
              # skip the header row
              foreach my $row ( 0..$RowsCount ) {
                 foreach my $col (0..$ColsCount) {

                    # nope ... $table->cell($row,$col)->->{'WrapText'} = 1 ; 
                    # nope $table->cell($row,$col)->{'WordWrap'} = 1  ;
                    # so so $table->cell($row,$col)->WordWrap() ; 

                    my $txt = ''; 
                    # well some 1% of the values are so nasty that we really give up on them ... 
                    eval {
                       $txt = $table->cell($row,$col)->range->{'Text'}; 
                       #replace all the ctrl chars by space
                       $txt =~ s/\r/ /g   ; 
                       $txt =~ s/[^\040-\176]/ /g  ; 
                       # perform some cleansing - ColName<primary key>=> ColName
                       #$txt =~ s#^(.[a-zA-Z_0-9]*)(\<.*)#$1#g ; 

                       # this will most probably brake your cmd ... 
                       # $objLogger->LogDebugMsg ( "row: $row , col: $col with txt: $txt \n" ) ; 
                    } or $txt = 'N/A' ; 

                    # Write a formatted and unformatted string, row and column notation.
                    $objWorkSheet->write($xlsRow, $col, $txt);

                 } #eof foreach col

                 # we just want to dump all the tables into the one sheet
                 $xlsRow++ ; 
               } #eof foreach row
               sleep 1 ; 
           }  #eof foreach table

           # close the opened in the UI document
           $objMSWord->ActiveDocument->Close;

           # OBS !!! now we are able to print 
           $objLogger->LogDebugMsg ( $tableText . "\n" );

           # exit the whole Word application
           $objMSWord->Quit;

           return ( $ret , $msg ) ; 
     }
     #eof sub doParseDoc
...