3

于是我有了这个疯狂的想法。现在,我正在使用 Text::CSV_XS 在 Word 中生成一个表格,如下所示:

use Win32::OLE;
use Win32::OLE::Const 'Microsoft Word';
use Text::CSV_XS;

# instantiation of word and Text::CSV_XS omitted for clarity
my $select = $word->Selection;
foreach my $row (@rows) { # @rows is an array of arrayrefs
    $csv->combine(@{$row});
    $select->InsertAfter($csv->string);
    $select->InsertParagraphAfter;
}
$select->convertToTable(({'Separator' => wdSeparateByCommas});

但如果我能做这样的事情会更酷:

use Win32::OLE;
use Win32::OLE::Const 'Microsoft Word';
use Text::CSV_XS;

# instantiation of word and Text::CSV_XS omitted for clarity
my $select = $word->Selection;
foreach my $row (@rows) { # @rows is an array of arrayrefs
    $csv->bind_columns($row);
    $csv->print( 
        sub {
            my $something; # Should be the combine()'d string
            $select->InsertAfter($something);
            $select->InsertParagraphAfter;
        },
        undef
    ); 
}
$select->convertToTable(({'Separator' => wdSeparateByCommas});

那么,我的问题是如何$something从第二个代码示例中取出,以及我需要做什么才能使闭包看起来像一个句柄?

4

2 回答 2

2

我相信您实际上是在问如何使用以下界面使数据最终出现在 Word 中:

my $fh = SelectionHandle->new($selection);
my $csv = Text::CSV_XS->new({ binary => 1 });
$csv->print($fh, $_) for @rows;

(我认为这是一个坏主意。它是由内而外的。创建一个使用封装的 CSV 对象进行格式化的对象。)

如果你想给一个对象一个变量的接口(标量、数组、哈希、文件句柄),你想要tie. 当你这样做时,你最终得到

use SelectionHandle qw( );
use Text::CSV_XS    qw( );

my $selection = ...;
my @rows      = ...;

my $fh = SelectionHandle->new($selection);
my $csv = Text::CSV_XS->new({ binary => 1 });
$csv->print($fh, $_) for @rows;

模块看起来像:

package SelectionHandle;

use strict;
use warnings;

use Symbol      qw( gensym );
use Tie::Handle qw( );

our @ISA = qw( Tie::Handle );

sub new {
   my ($class, $selection) = @_;
   my $fh = gensym();
   tie(*$fh, $class, $selection);
   return $fh;
}

sub TIEHANDLE {
   my ($class, $selection) = @_;
   return bless({
      selection => $selection,
   }, $class);
}

sub PRINT {
   my ($self, $str) = @_;
   my $selection = $self->{selection};
   $selection->InsertAfter($str);
   $selection->InsertParagraphAfter();
   return 1;
}

1;
于 2013-02-01T17:33:59.360 回答
2

Text::CSV::print不一定需要手柄。文档只是说它需要一种print方法。

{
    package Print::After::Selection;
    sub new {
        my ($pkg, $selection) = @_;
        my $self = { selection => $selection };
        return bless $self, $pkg;
    }
    sub print {
        my ($self, $string) = @_;
        my $selection = $self->{selection};
        $selection->InsertAfter($string);
        $selection->InsertParagraphAfter;
        return 1;  # return true or Text::CSV will think print failed
    }
}

...
$csv->print( Print::After::Selection->new( $word->Selection ), undef );
...

(未测试)

于 2013-02-01T17:06:34.070 回答