Почему мой 2D-диапазон не заменяется 3D-диапазоном при использовании функции repeat_formula в Perl's Spreadsheet :: WriteExcel?

Мне нужно создать динамическую формулу Excel через скрипт Perl.

Я храню формулу, содержащую поддельный диапазон

my $stored_formula = $worksheet->store_formula('=MEDIAN(A1:A2)'); 

В сценарии я вычисляю новый диапазон

 $formula_range = $mm_arr[$mmindx-1] . "!" . num2col(2+$form_off) . ((($serv-1)*5)+5) . ":" . num2col((2+31+$form_off)) . ((($serv-1)*5)+5); 

где @mm_arr – массив ("Jan", "Feb", …) а num2col – это функция, которую я использую для перевода номеров столбцов в буквы.

Строка чуть ниже – repeat_formula

 $worksheet->repeat_formula( (($serv-1)*5)+4, 1+$mmindx, $stored_formula, undef, 'A1:A2', $formula_range ); 

Я ожидаю получить:

 =median(Feb!K3:AH3) 

но вместо этого я получаю:

 =median(K3:AH3) 

Таким образом, поиск / замена как-то работает, но я не могу понять, как это сделать!

Что я делаю не так?

Во-первых, несколько рекомендаций:

В ваших выражениях слишком много скобок, которые в сочетании с переменными и функциями, определения которых мы не можем видеть, делают ваш код сложным для синтаксического анализа. Вы также не опубликовали небольшой самодостаточный сценарий, который показывает проблему, а это означает, что любой, кто пытается вам помочь, должен установить тестовый скрипт. Успокойтесь на других.

Например, строка, в которой вы определяете $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 для преобразования между нотами ячеек и индексами строк и столбцов.

Проблема заключается в том, что если сохраненная формула не находится в форме SheetName!Range , то замена заменяет имя листа в замене и помещает только в диапазон.

Причина этого, похоже, связана с настройкой парсера в Spreadsheet::WriteExcel::Formula . range2d диапазон анализируется как токен 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': $!"; 

И вот скриншот:

Скриншот, показывающий правильные формулы

store_formula()/repeat_formula() – это историческое обходное решение для медленного разбора формул, использующего Parse :: RecDescent. Они предназначены только для замены простых и аналогичных диапазонов.

Изменение выражения из 2D-диапазона в 3D-диапазон не сработает, поскольку разборная двоичная структура, представляющая каждую из этих формул, очень отличается и не может быть изменена простой заменой.

Вы можете обойти это в Spreadsheet :: WriteExcel, но вместо этого я бы рекомендовал использовать Excel :: Writer :: XLSX, совместимую с API для Spreadsheet :: WriteExcel, и которая не требует store_formula()/repeat_formula() для ускорить повторные формулы.

В качестве окончательной заметки оба модуля для чтения Excel поставляются с :: Utility модулями для генерации диапазона.

  • R Ошибка: не удается прочитать в таблице xls в R, дает «Ошибка в файле .exists (tfn): неверный аргумент« file »
  • «состояние» всегда начинает синтаксический анализ из следующей строки?
  • Как использовать модуль CPAN в Perl-скрипте, который я хочу предоставить другим?
  • Как автоподстроить ширину столбца с помощью Excel :: Writer :: XLSX
  • добавить диаграмму к существующему excel, используя perl
  • perl для чтения файла xlsx (который имеет много листов), используя имя листа
  • Perl Excel OLE ошибка при открытии разных файлов из двух сценариев одновременно
  • r - Библиотека: gdata - Файл анализа ошибок и read.xls не удается создать Intermediate csv
  • Прикрепите xlsx к электронной почте с помощью MIME :: Lite
  • Невозможно вызвать метод «рабочий лист» по неопределенному значению
  • Ошибка копирования папок в Excel с использованием Perl Win32: OLE
  • Interesting Posts

    копирование с одного excel на другое с помощью VBA

    Автоматическое удаление специальных символов

    Получить NamedRange из неизвестного рабочего листа в другой книге

    Измените формулу в excel на основе пользовательского ввода

    Формула Excel INDEX с несколькими критериями

    VBA: условие IF при условном форматировании цвета интерьера не работает

    excel: ошибка времени выполнения 1004 в расширенном фильтре

    Заменить текст в документе Word из Excel

    Определяемая приложением или объектная ошибка при настройке цвета всей строки

    У гиперссылки формулы есть макрос VBA

    Array VLookup Возврат неверного значения VBA

    Как искать значение, которое происходит четыре раза, и извлекать каждое значение соседней ячейки

    Ошибка «Требуемый объект» для копирования значения массива

    Удаление строк в foreach

    Найти последние файлы FileS, вернуть последний x количество файлов IF, сделанных в течение минуты друг от друга

    Давайте будем гением компьютера.