【问题标题】:Fetch tabular data from MS-Word file从 MS-Word 文件中获取表格数据
【发布时间】:2015-04-30 06:39:38
【问题描述】:

我需要从 MS-Word 文件中获取表格数据。我提到的代码只获取第一行和最后一行,但我需要获取整个表。

稍后,如果文件夹中存在相同的文件名,则必须交叉检查提取的数据。

我什至无法理解代码的流程,因为我是 Win32::OLE 模块的新手。

我提到了一个关于在这个网站上获取数据的类似问题,但无法得到它。

请告诉我如何继续。

#!/usr/bin/perl 

use strict;
use warnings;

use File::Spec::Functions qw( catfile );
use Win32::OLE qw(in);
use Win32::OLE::Const 'Microsoft Word';

$Win32::OLE::Warn = 3;

my $word = get_word();
$word->{DisplayAlerts} = wdAlertsNone;
$word->{Visible}       = 1;

my $doc    = $word->{Documents}->Open('D:\A.doc');
my $tables = $word->ActiveDocument->{'Tables'};

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

$doc->Close(0);

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

更新: 文档

Article    No.      Count No      Committee
 A0029     A0029    16            E01.07
 B0028     B0028    34            E04.09
 C0036     C0036    17            E09.00
 D0033     D0033    15            E08.07

在 CMD 中输出

D:\Word>A.pl
D0033   D0033   15      E08.07No                     Committee

【问题讨论】:

  • 您需要参考Word Developer Reference,其中列出了所有可用的类及其属性和方法。但我不明白为什么你的代码应该只获取第一行和最后一行。 Table.ConvertToText 方法返回一个Range 对象,它本质上只是表格开头和结尾的字符位置。 Range.Text 属性只是这两个位置之间的文本,所以不会出错。您是在控制台上查看此内容吗?
  • 您能否发布您的 Word 文档以便我们自己试用?
  • @Borodin:我在控制台 (cmd) 上查看它,并以 D:\>A.pl 的身份运行程序我尝试了具有多行且仅在两行,但我得到相同的输出..
  • 已更新 A.doc 文件的示例以及生成的输出。 @sinan : 代码引用自link
  • @sinan:我只是想提供我引用代码的链接,无意不给你任何信任。我欠你们帮助初学者学习的人。我想你会帮助我摆脱代码中的这个错误并理解它..

标签: perl doc


【解决方案1】:

问题是由ConvertToText方法返回的文本中的CR字符终止的事实引起的:

C:\...\Temp> perl word-table.pl A.doc | xxd
00000000: 4172 7469 636c 6509 4e6f 2e09 436f 756e
00000010: 7420 4e6f 0943 6f6d 6d69 7474 6565 0d41 t No.Committee.A
00000020: 3030 3239 0941 3030 3239 0931 3609 4530 0029.A0029.16.E0
00000030: 312e 3037 0d42 3030 3238 0942 3030 3238 1.07.B0028.B0028
00000040: 0933 3409 4530 342e 3039 0d43 3030 3336 .34.E04.09.C0036
00000050: 0943 3030 3336 0931 3709 4530 392e 3030 .C0036.17.E09.00
00000060:0d44 3030 3333 0944 3030 3333 0931 3509 .D0033.D0033.15。
00000070: 4530 382e 3037 0d0d 0a E08.07...

要解决,用换行符替换回车:

#!/usr/bin/env 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;

run(\@ARGV);

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 "$@\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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 2011-11-05
    • 2013-07-06
    • 2010-09-12
    • 1970-01-01
    相关资源
    最近更新 更多