Я пытаюсь проанализировать формулу в Excel с тремя параметрами: формула, исходный адрес ячейки, адрес ячейки назначения.
Пример с некоторыми правилами:
Я знаю какую-то библиотеку на C#, Python... сделал это, но теперь хочу сделать это на Java. Мне нужен алгоритм для анализа формулы на токен и замены ее, или библиотека сделает это быстро.
=LET(a,A2,b,B2,i,$1:$1048576,INDEX(i,COLUMN(a)+1,1)+INDEX(i,COLUMN(b),2))
a
и b
— это клетки, которые у вас есть изначально. Если вы скопируете и вставите его в другой столбец, индекс строки переместится, но индекс столбца останется прежним.
@P.b Мне так сложно понять, можешь ли ты объяснить больше? с простой формулой C1 = A1 + B1, как я могу вставить в ячейку C2.
Другим способом может быть использование =TRANSPOSE(range), а затем ссылка на ячейки в транспонированном диапазоне, и он должен вести себя так, как вы упомянули, только в другом созданном диапазоне.
Существует 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: «это влияет на производительность?»: Да, влияет. Если вы воссоздадите чистый алгоритм корректировки формулы без рабочей книги, это будет иметь лучшую производительность. Но этот алгоритм корректировки формулы очень сложен, и я не знаю ни одной библиотеки Java, которая бы обеспечивала такой подход. Я сомневаюсь, что даже библиотеки, которые вы нашли для C# и Python, действительно полны, чтобы правильно настроить все возможные строки формул, за исключением того, что они работают с использованием установленного приложения Excel, что, однако, еще больше повлияет на производительность. Apache POI не требует установки приложения Excel.
@P.b Какая у тебя
LET
функция?