Perl如何将两个或多个excel文件合并为一个(多个工作表)?
Posted
技术标签:
【中文标题】Perl如何将两个或多个excel文件合并为一个(多个工作表)?【英文标题】:Perl How to merge two or more excel files in one (multiple worksheets)? 【发布时间】:2012-10-14 13:52:49 【问题描述】:我需要将几个 excel 文件合并为一张,多张。 我不太关心新文件上的工作表名称。
我计划运行它的计算机上没有 Excel。所以我不能使用 Win32 OLE。 我试图运行此代码https://sites.google.com/site/mergingxlsfiles/,但它不起作用,我得到一个新的空 excel 文件。
我尝试运行http://www.perlmonks.org/?node_id=743574,但我只获得了新excel文件中的一个文件。
我输入的 excel 文件有一些法语字符(例如 é)我相信这些是 cp1252。
使用的代码:
#!/usr/bin/perl -w
use strict;
use Spreadsheet::ParseExcel;
use Spreadsheet::WriteExcel;
use File::Glob qw(bsd_glob);
use Getopt::Long;
use POSIX qw(strftime);
GetOptions(
'output|o=s' => \my $outfile,
'strftime|t' => \my $do_strftime,
) or die;
if ($do_strftime)
$outfile = strftime $outfile, localtime;
;
my $output = Spreadsheet::WriteExcel->new($outfile)
or die "Couldn't create '$outfile': $!";
for (@ARGV)
my ($filename,$sheetname,$targetname);
my @files;
if (m!^(.*\.xls):(.*?)(?::([\w ]+))$!)
($filename,$sheetname,$targetname) = ($1,qr($2),$3);
warn $filename;
if ($do_strftime)
$filename = strftime $filename, localtime;
;
@files = glob $filename;
else
($filename,$sheetname,$targetname) = ($_,qr(.*),undef);
if ($do_strftime)
$filename = strftime $filename, localtime;
;
push @files, glob $filename;
;
for my $f (@files)
my $excel = Spreadsheet::ParseExcel::Workbook->Parse($f);
foreach my $sheet (@$excel->Worksheet)
if ($sheet->Name !~ /$sheetname/)
warn "Skipping '" . $sheet->Name . "' (/$sheetname/)";
next;
;
$targetname ||= $sheet->Name;
#warn sprintf "Copying %s to %s\n", $sheet->Name, $targetname;
my $s = $output->add_worksheet($targetname);
$sheet->MaxRow ||= $sheet->MinRow;
foreach my $row ($sheet->MinRow .. $sheet->MaxRow)
my @rowdata = map
$sheet->Cells->[$row]->[$_]->Val;
$sheet->MinCol .. $sheet->MaxCol;
$s->write($row,0,\@rowdata);
;
;
$output->close;
我有 2 个名为的 excel 文件:2.xls(其中只有一张名为 2 的工作表)、3.xls(只有一张名为 3 的工作表)
我是这样启动脚本的:
xlsmerge.pl -s -o results-%Y%m%d.xls 2.xls:2 3.xls:3
结果:results-20121024.xls 中没有任何内容。
然后我尝试了
xlsmerge.pl -s -o results-%Y%m%d.xls 2.xls 3.xls
它奏效了。 我不确定为什么在添加 Sheetname 时会失败
【问题讨论】:
也许您可以显示您尝试过的确切代码,或者您使用 PerlMonks 脚本运行的确切命令?这两个脚本大概可以工作 - 所以它一定是特定于您的案例的东西导致了问题。 @dan1111 我添加了代码,并重新测试,看起来没有工作表名称。 【参考方案1】:这行脚本好像有bug:
if (m!^(.*\.xls):(.*?)(?::([\w ]+))$!)
($filename,$sheetname,$targetname) = ($1,qr($2),$3);
...
在我看来,该行的目标是允许表单中的参数
spreadsheet.xls:source_worksheet
或以其他形式允许指定目标工作表的名称:
spreadsheet.xls:source_worksheet:target_worksheet
最后一个分组似乎旨在捕获最后一个可选参数:(?::([\w ]+))
。唯一的问题是,这个分组不是可选的。因此,当您只指定源工作表而不指定目标时,正则表达式无法匹配,它会落入备份行为,即将整个参数视为文件名。但这也失败了,因为您没有名为 2.xls:2
的文件。
解决方案是在正则表达式的最后一组之后引入?
修饰符,使其成为可选:
if (m!^(.*\.xls):(.*?)(?::([\w ]+))?$!)
($filename,$sheetname,$targetname) = ($1,qr($2),$3);
...
当然,这可能不是唯一的问题。如果脚本发布时出现错误,则也可能存在其他错误。我目前没有可用的 Perl 来测试它。
【讨论】:
以上是关于Perl如何将两个或多个excel文件合并为一个(多个工作表)?的主要内容,如果未能解决你的问题,请参考以下文章