首先,有几点建议:
您的表达式中有太多括号,再加上我们看不到其定义的变量和函数,使您的代码难以直观地解析。您也没有发布一个显示问题的小型、独立的脚本,这意味着任何试图帮助您的人都必须设置一个测试脚本。让别人轻松。
例如,您定义的行$formula_range
可以重写如下:
my $formula_range = sprintf('%s!%s%d:%s%d',
$mm_arr[$mmindx - 1],
num2col(2 + $form_off),
5 + 5 * ($serv - 1),
num2col(2 + 31 + $form_off),
5 + 5 * ($serv - 1),
);
请记住,您可以使用Spreadsheet::WriteExcel::Utility提供的函数在单元格符号和行/列索引之间进行转换。
问题似乎是,如果存储的公式不在 formSheetName!Range
中,那么替换会在替换中去掉工作表名称,并且只放在范围内。
其原因似乎与Spreadsheet::WriteExcel::Formula
. 普通范围被解析为range2d
标记,而具有工作表引用的范围被解析为range3d
标记。稍后,在 中repeat_formula
,替换是在令牌上完成的。据我所知,range2d
令牌看起来像'_ref2dA1:A10'
。因此,'_ref2dA1:A2'
被转化为'_ref2dFeb!A1:10'
重复公式。但是,当它传递给 时,代码仍然根据前缀Spreadsheet::WriteExcel::Formula::parse_tokens
将其分类为令牌。range2d
我收集了最后的电话$parse_str .= $self->_convert_ref2d($token, $class);
,然后将其重新转换为'_ref2dA1:A10
. 我不确定这是否可以归类为错误,但从用户的 POV 来看,这绝对是出乎意料的。
因此,解决方案是放入保证存在的工作表的名称。
这是一个测试脚本:
#!/usr/bin/env perl
use strict; use warnings;
use Spreadsheet::WriteExcel;
use Const::Fast;
const my @MONTHS => qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
const my $WORKBOOK => 'test.xls';
my $book = Spreadsheet::WriteExcel->new($WORKBOOK)
or die "Cannot open '$WORKBOOK': $!";
my %sheets = map {$_ => $book->add_worksheet($_)} Summary => @MONTHS;
for my $m (@MONTHS) {
for my $n (1 .. 10) {
$sheets{ $m }->write_number($n - 1, 0, $n);
}
}
my $formula = $sheets{Summary}->store_formula('=MEDIAN(Summary!A1:A2)');
for my $n (0 .. 1) {
my $replacement = sprintf(q{'%s'!A1:A10}, $MONTHS[$n]);
$sheets{Summary}->repeat_formula($n, 0, $formula, undef,
'Summary!A1:A2' => $replacement
);
}
$book->close
or die "Error closing '$WORKBOOK': $!";
这是一个屏幕截图: