Алгоритм корректировки формулы Excel из исходной ячейки в целевую ячейку

Я пытаюсь проанализировать формулу в Excel с тремя параметрами: формула, исходный адрес ячейки, адрес ячейки назначения.

Пример с некоторыми правилами:

Формула Исходный адрес Адрес назначения Ожидаемый результат Примечание =(А2+В2) С2 С3 =(А3+В3) =(А2+В2) С2 Д2 =(В2+С2) Увеличить столбец на 1 (C->D) =(A2+$B$2) С2 Д10 =(B10+$B$2) Выражение $ =(ЛистA2!A2+B2) С2 С3 =(ЛистA2!A3+B3) Имя листа (SheetA2) является инвариантным. =ЕСЛИ(A2=A3,A4,A5) А6 С6 =ЕСЛИ(С2=С3,С4,С5) Заменить все вариант

Я знаю какую-то библиотеку на C#, Python... сделал это, но теперь хочу сделать это на Java. Мне нужен алгоритм для анализа формулы на токен и замены ее, или библиотека сделает это быстро.

@P.b Какая у тебя LET функция?

cuong02n 20.07.2024 13:23
=LET(a,A2,b,B2,i,$1:$1048576,INDEX(i,COLUMN(a)+1,1)+INDEX(i,‌​COLUMN(b),2))a и b — это клетки, которые у вас есть изначально. Если вы скопируете и вставите его в другой столбец, индекс строки переместится, но индекс столбца останется прежним.
P.b 20.07.2024 16:38

@P.b Мне так сложно понять, можешь ли ты объяснить больше? с простой формулой C1 = A1 + B1, как я могу вставить в ячейку C2.

cuong02n 21.07.2024 04:45

Другим способом может быть использование =TRANSPOSE(range), а затем ссылка на ячейки в транспонированном диапазоне, и он должен вести себя так, как вы упомянули, только в другом созданном диапазоне.

P.b 22.07.2024 00:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
4
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Существует Java-библиотека Apache POI, которая умеет это делать.

Эта библиотека обеспечивает оценку формул и перемещение ячеек. Поэтому требуется анализ формул и корректировка формул для новых ячеек назначения. Для этого он предоставляет FormulaParser и FormulaRenderer.

Конечно, эти классы запрограммированы на выполнение своей работы в существующей книге. Но если требуется только корректировка строк формул, можно использовать пустую временную фиктивную книгу. В своем примере я использую XSSFWorkbook, так как это представление текущего *.xlsx, которое обеспечивает большее количество строк и столбцов, чем старое *.xls.

Полный пример тестирования приведенных вами примеров и еще одного:

import org.apache.poi.ss.formula.*;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.apache.poi.ss.util.CellAddress;

public class ExcelGetAdjustedFormula {

 private static String getAdjustedFormula(String formula, String originalAddress, String destinationAddress) {
     
  CellAddress originalCellAddress = new CellAddress(originalAddress);
  CellAddress destinationCellAddress = new CellAddress(destinationAddress);
  int coldiff = destinationCellAddress.getColumn() - originalCellAddress.getColumn();
  int rowdiff = destinationCellAddress.getRow() - originalCellAddress.getRow();

  XSSFEvaluationWorkbook workbookWrapper = 
   XSSFEvaluationWorkbook.create(new XSSFWorkbook());
  Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL, 0);

  for (int i = 0; i < ptgs.length; i++) {
   if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
    RefPtgBase ref = (RefPtgBase) ptgs[i];
    if (ref.isColRelative())
     ref.setColumn(ref.getColumn() + coldiff);
    if (ref.isRowRelative())
     ref.setRow(ref.getRow() + rowdiff);
   }
   else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
    AreaPtgBase ref = (AreaPtgBase) ptgs[i];
    if (ref.isFirstColRelative())
     ref.setFirstColumn(ref.getFirstColumn() + coldiff);
    if (ref.isLastColRelative())
     ref.setLastColumn(ref.getLastColumn() + coldiff);
    if (ref.isFirstRowRelative())
     ref.setFirstRow(ref.getFirstRow() + rowdiff);
    if (ref.isLastRowRelative())
     ref.setLastRow(ref.getLastRow() + rowdiff);
   }
  }

  formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs);
  return formula;
 }

 public static void main(String[] args) {
     
  String[][] examples = new String[][]{
   new String[]{"(A2+B2)", "C2", "C3"},
   new String[]{"(A2+B2)", "C2", "D2"},
   new String[]{"(A2+$B$2)", "C2", "D10"},
   new String[]{"(SheetA2!A2+B2)", "C2", "C3"},
   new String[]{"IF(A2=A3,A4,A5)", "A6", "C6"},
   new String[]{"VLOOKUP(A2,'Sheet Name'!$A$1:$G$1000,4,FALSE)", "F2", "F10"}
  };
     
  for (String[] example : examples) {
   String formula = example[0];
   String originalAddress = example[1];
   String destinationAddress = example[2];
  
   String newformula = getAdjustedFormula(formula, originalAddress, destinationAddress);
   System.out.println(newformula);
  }
  
 }
}

О, я вижу, что в приведенном выше коде есть временная книга, какова ее цель, влияет ли она на производительность?

cuong02n 20.07.2024 07:15

@cuong02n: «это влияет на производительность?»: Да, влияет. Если вы воссоздадите чистый алгоритм корректировки формулы без рабочей книги, это будет иметь лучшую производительность. Но этот алгоритм корректировки формулы очень сложен, и я не знаю ни одной библиотеки Java, которая бы обеспечивала такой подход. Я сомневаюсь, что даже библиотеки, которые вы нашли для C# и Python, действительно полны, чтобы правильно настроить все возможные строки формул, за исключением того, что они работают с использованием установленного приложения Excel, что, однако, еще больше повлияет на производительность. Apache POI не требует установки приложения Excel.

Axel Richter 20.07.2024 07:26

Другие вопросы по теме