Open the lid like a pen in Perl
So, I had this crazy idea. Right now, I am creating a table in Word using Text :: CSV_XS, for example:
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});
But it would be cooler if I could do something like this:
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});
So my questions are, how do I get $something
from my second code example, and what do I need to do to make the closure look like a handle?
source to share
Text::CSV::print
a descriptor is not required. The documentation just says it needs something with a method 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 );
...
(not verified)
source to share
I believe you are really asking how to render data in Word with the following interface:
my $fh = SelectionHandle->new($selection);
my $csv = Text::CSV_XS->new({ binary => 1 });
$csv->print($fh, $_) for @rows;
(I think this is a bad idea, internally. Create an object that formats using an encapsulated CSV object.)
If you want to give an object a variable interface (scalar, array, hash, file descriptor) you want tie
. When you do, you will receive
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;
And the module looks like this:
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;
source to share