![](/img/trans.png)
[英]Perl Excel::Writer::XLSX formula not calculating when workbook is opened
[英]perl Excel::Writer::XLSX copy formula to several subsequent cells of a row
在 EXCEL 你可以写一个公式,标记单元格并使用标记右下角的“+”将公式复制到同一行或列的后续单元格。 相对参考会自动调整。
有没有办法用 Excel::Writer::XLSX 来完成这个?
我已经编写了一个基本实现,它可以在下方和右侧处理单个单元格。 您可以使用它作为示例来了解如何做更复杂的事情。 它用$
过滤掉固定单元格,因为它们不能递增。 它不适用于拉起或离开。
我添加了一个测试来解释 output 的样子。 解释如下。
use strict;
use warnings;
use feature 'say';
# caveat: does not check if the cells are inside of quotes!
sub pull_formula {
my ($formula, $from, $to) = @_;
my ($col_from, $row_from) = $from =~ m/([A-Z]+)([0-9]+)/;
my ($col_to, $row_to) = $to =~ m/([A-Z]+)([0-9]+)/;
my @formulas;
# determine direction, do we go down or right
if ($col_from eq $col_to) {
# pulling down, increment numbers
foreach my $n (++$row_from .. $row_to) {
$formula =~ s{
([A-Z]+)
([0-9]+)
}{$1 . ($2+1)}gex;
push @formulas, $formula;
}
}
else {
# pulling right, increment letters
foreach my $n (++$col_from .. $col_to) {
$formula =~ s{
(?<! \$) # not preceded by a dollar
(?<col> [A-Z]+) # column
(?<dollar> \$?) # optional dollar sign for row
(?<row> [0-9]+) # row
}{
do { my $c = $+{col}; ++$c }
. $+{dollar}
. $+{row}
}gex;
push @formulas, $formula;
}
}
return \@formulas;
}
use Test::More;
is_deeply pull_formula('=B5 + C5', 'A5', 'A8'), [
'=B6 + C6',
'=B7 + C7',
'=B8 + C8',
];
is_deeply pull_formula('=MIN(B5:B$999)', 'A5', 'A8'), [
'=MIN(B6:B$999)',
'=MIN(B7:B$999)',
'=MIN(B8:B$999)',
];
is_deeply pull_formula('=VLOOKUP(B3,B$2:E$7,2,FALSE)', 'B3', 'B5'), [
'=VLOOKUP(B4,B$2:E$7,2,FALSE)',
'=VLOOKUP(B5,B$2:E$7,2,FALSE)',
];
is_deeply pull_formula('=SUM(Y1:Y10)', 'Y11', 'AB11'), [
'=SUM(Z1:Z10)',
'=SUM(AA1:AA10)',
'=SUM(AB1:AB10)',
];
done_testing;
这个想法是用公式调用 function,你想要填充的范围是两个 arguments。如果你可以访问工作表,你当然可以只用一个单元格参数来完成这一切,你还想添加多少填写。但这更容易。
我们首先将单元格分成 cols 和 rows,然后决定是否要增加数字(行)或字母(cols)。
数字更简单,因为我们可以对它们进行数学运算。 一般的想法是迭代公式,找到每个出现的单元格,并将其替换为下一个更高的单元格。 我们使用的正则表达式替换具有用于在模式中添加格式的/x
标志、用于将替换视为 Perl 代码的/e
标志以及用于全局执行此操作的/g
标志,这意味着尽可能多地重复。
对于字母,模式更棘手。 我们不需要获取前面带有美元符号$
的字母,因此在开始时有一个否定的回顾。 我使用命名捕获组 ( (?<name>pattern)
) 使捕获更易于阅读。 注意所有空格都被忽略,它来自/x
修饰符。 对于字母,数字前面是否有美元并不重要,但我们必须捕获它。 如果没有美元, $+{dollar}
将是一个空字符串。
Perl 以与 Excel 列相同的方式递增字母。 AA
在Z
之后,这很方便。 但是 Perl 只对范围和增量运算符++
执行此操作,我们不能将其应用于捕获变量,因此我们必须首先将其分配给一个新变量。 为了在替换内部执行此操作,我们使用了一个do
块。
我已将所有模式放入一个数组中并返回一个引用,但是您当然可以直接写入工作表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.