2016-12-21 10 views
1

У меня есть каталог с сотнями текстовых документов, каждый из которых содержит стандартизованный набор таблиц. Мне нужно разобрать эти таблицы и извлечь данные в них. Я разработал сценарий, который выплескивает все таблицы.Как перемещаться по таблицам Word с помощью пакета WIN32 :: OLE perl?

#!/usr/bin/perl; 
use strict; 
use warnings; 

use Carp qw(croak); 
use Cwd qw(abs_path); 
use Path::Class; 
use Win32::OLE qw(in); 
use Win32::OLE::Const 'Microsoft Word'; 
$Win32::OLE::Warn = 3; 
=d 
my $datasheet_dir = "./path/to/worddocs"; 
my @files = glob "$datasheet_dir/*.doc"; 
print "scalar: ".scalar(@files)."\n"; 
foreach my $f (@files){ 
    print $f."\n"; 
} 
=cut 
#my $file = $files[0]; 
my $file = "word.doc"; 
print "file: $file\n"; 

run(\@files); 

sub run { 
    my $argv = shift; 
    my $word = get_word(); 

    $word->{DisplayAlerts} = wdAlertsNone; 
    $word->{Visible}  = 1; 

    for my $word_file (@$argv) { 
     print_tables($word, $word_file); 
    } 

    return; 
} 

sub print_tables { 
    my $word = shift; 
    my $word_file = file(abs_path(shift)); 

    my $doc = $word->{Documents}->Open("$word_file"); 
    my $tables = $word->ActiveDocument->{Tables}; 

    for my $table (in $tables) { 
     my $text = $table->ConvertToText(wdSeparateByTabs)->Text; 
     $text =~ s/\r/\n/g; 
     print $text, "\n"; 
    } 

    $doc->Close(0); 
    return; 
} 

sub get_word { 
    my $word; 
    eval { $word = Win32::OLE->GetActiveObject('Word.Application'); 1 } 
     or die "[email protected]\n"; 
    $word and return $word; 
    $word = Win32::OLE->new('Word.Application', sub { $_[0]->Quit }) 
     or die "Oops, cannot start Word: ", Win32::OLE->LastError, "\n"; 
    return $word; 
} 

Есть ли способ передвижения по ячейкам? Я хочу только возвращать строки, которые имеют определенное значение в первом столбце?

Например, для следующей таблицы я хочу только grep строки, содержащие фрукты в первом столбце.

apple  pl 
banana  xml 
California csv 
pickle  txt 
Illinois gov 
pear  doc 

ответ

0

Вы можете использовать OLE для доступа к отдельным ячейкам таблицы, после первого получения размеров с помощью Columns объекта и Rows коллекции.

Или вы могли бы отправить текст в массив Perl и повторить его. Вместо

my $text = $table->ConvertToText(wdSeparateByTabs)->Text; 
$text =~ s/\r/\n/g; 
print $text, "\n"; 

что-то вроде

my %fruit; # population of look-up table of fruit omitted 

my $text = $table->ConvertToText(wdSeparateByTabs)->Text; 
my @lines = split /\r/, $text; 
for my $line (@lines) { 
    my @fields = split /\t/, $lines; 

    next unless exists $fruit{$fields[0]}; 

    print "$line\n"; 
} 

продолжений для случая чувствительности и т.д., могут быть добавлены по мере необходимости.