簡體   English   中英

perl Excel::Writer::XLSX 將公式復制到一行的多個后續單元格

[英]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 列相同的方式遞增字母。 AAZ之后,這很方便。 但是 Perl 只對范圍和增量運算符++執行此操作,我們不能將其應用於捕獲變量,因此我們必須首先將其分配給一個新變量。 為了在替換內部執行此操作,我們使用了一個do塊。

我已將所有模式放入一個數組中並返回一個引用,但是您當然可以直接寫入工作表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM