Обнаружение циклической ссылки
Введение
У книг Excel могут быть циклические ссылки, и иногда необходимо определить, есть ли циклические ссылки или нет.
Концепция обнаружения циклических ссылок
Кольцевые ссылки могут быть обнаружены только при расчете формулы, поскольку ссылки одной формулы обычно зависят от расчитанного результата других частей или других формул. Поэтому мы предоставляем новые API для этого требования (чтобы собирать ячейки с кольцевыми ссылками) в процессе расчета формулы:
CalculationCell: Представляет расчет соответствующих данных по одной вычисляемой ячейке
AbstractCalculationMonitor.OnCircular(IEnumerator circularCellsData): будет вызван движком расчета формул при обнаружении кольцевых ссылок, элемент в перечислителе - CalculationCell объектов, которые представляют все ячейки в одном круге. Возвращенное значение указывает, нужно ли движку формулы рассчитать эти ячейки в кольцевом порядке после этого вызова.
Пользователь может собирать эти кольцевые ссылки в реализации метода AbstractCalculationMonitor.OnCircular().
Образец исходного файла можно загрузить по следующей ссылке:
LoadOptions LoadOptions = new LoadOptions(); | |
Workbook objWB = new Workbook(sourceDir + "Circular Formulas.xls", LoadOptions); | |
objWB.getSettings().getFormulaSettings().setEnableIterativeCalculation(true); | |
CalculationOptions copts = new CalculationOptions(); | |
CircularMonitor cm = new CircularMonitor(); | |
copts.setCalculationMonitor(cm); | |
objWB.calculateFormula(copts); | |
int lngCircularRef = cm.circulars.size(); | |
System.out.println("Circular References found - " + lngCircularRef); |
Определение класса CircularMonitor, который происходит от класса AbstractCalculationMonitor, приведено ниже:
public class CircularMonitor extends AbstractCalculationMonitor | |
{ | |
public ArrayList circulars = new ArrayList(); | |
public ArrayList getCirculars() { return circulars; } | |
public /*override*/ boolean onCircular(Iterator circularCellsData) | |
{ | |
CalculationCell cc = null; | |
ArrayList cur = new ArrayList(); | |
while (circularCellsData.hasNext()) | |
{ | |
cc = (CalculationCell)circularCellsData.next(); | |
cur.add(cc.getWorksheet().getName() + "!" + CellsHelper.cellIndexToName(cc.getCellRow(), cc.getCellColumn())); | |
} | |
circulars.add(cur); | |
return true; | |
} | |
} |