--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.eval.forked;\r
+\r
+import org.apache.poi.hssf.record.formula.eval.BlankEval;\r
+import org.apache.poi.hssf.record.formula.eval.BoolEval;\r
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;\r
+import org.apache.poi.hssf.record.formula.eval.NumberEval;\r
+import org.apache.poi.hssf.record.formula.eval.StringEval;\r
+import org.apache.poi.hssf.record.formula.eval.ValueEval;\r
+import org.apache.poi.hssf.usermodel.HSSFCell;\r
+import org.apache.poi.ss.formula.EvaluationCell;\r
+import org.apache.poi.ss.formula.EvaluationSheet;\r
+import org.apache.poi.ss.usermodel.Cell;\r
+\r
+/**\r
+ * Represents a cell being used for forked evaluation that has had a value set different from the\r
+ * corresponding cell in the shared master workbook.\r
+ *\r
+ * @author Josh Micich\r
+ */\r
+final class ForkedEvaluationCell implements EvaluationCell {\r
+\r
+ private final EvaluationSheet _sheet;\r
+ /** corresponding cell from master workbook */\r
+ private final EvaluationCell _masterCell;\r
+ private boolean _booleanValue;\r
+ private int _cellType;\r
+ private int _errorValue;\r
+ private double _numberValue;\r
+ private String _stringValue;\r
+\r
+ public ForkedEvaluationCell(ForkedEvaluationSheet sheet, EvaluationCell masterCell) {\r
+ _sheet = sheet;\r
+ _masterCell = masterCell;\r
+ // start with value blank, but expect construction to be immediately\r
+ setValue(BlankEval.INSTANCE); // followed by a proper call to setValue()\r
+ }\r
+\r
+ public Object getIdentityKey() {\r
+ return _masterCell.getIdentityKey();\r
+ }\r
+\r
+ public void setValue(ValueEval value) {\r
+ Class<? extends ValueEval> cls = value.getClass();\r
+\r
+ if (cls == NumberEval.class) {\r
+ _cellType = HSSFCell.CELL_TYPE_NUMERIC;\r
+ _numberValue = ((NumberEval)value).getNumberValue();\r
+ return;\r
+ }\r
+ if (cls == StringEval.class) {\r
+ _cellType = HSSFCell.CELL_TYPE_STRING;\r
+ _stringValue = ((StringEval)value).getStringValue();\r
+ return;\r
+ }\r
+ if (cls == BoolEval.class) {\r
+ _cellType = HSSFCell.CELL_TYPE_BOOLEAN;\r
+ _booleanValue = ((BoolEval)value).getBooleanValue();\r
+ return;\r
+ }\r
+ if (cls == ErrorEval.class) {\r
+ _cellType = HSSFCell.CELL_TYPE_ERROR;\r
+ _errorValue = ((ErrorEval)value).getErrorCode();\r
+ return;\r
+ }\r
+ if (cls == BlankEval.class) {\r
+ _cellType = HSSFCell.CELL_TYPE_BLANK;\r
+ return;\r
+ }\r
+ throw new IllegalArgumentException("Unexpected value class (" + cls.getName() + ")");\r
+ }\r
+ public void copyValue(Cell destCell) {\r
+ switch (_cellType) {\r
+ case Cell.CELL_TYPE_BLANK: destCell.setCellType(Cell.CELL_TYPE_BLANK); return;\r
+ case Cell.CELL_TYPE_NUMERIC: destCell.setCellValue(_numberValue); return;\r
+ case Cell.CELL_TYPE_BOOLEAN: destCell.setCellValue(_booleanValue); return;\r
+ case Cell.CELL_TYPE_STRING: destCell.setCellValue(_stringValue); return;\r
+ case Cell.CELL_TYPE_ERROR: destCell.setCellErrorValue((byte)_errorValue); return;\r
+ }\r
+ throw new IllegalStateException("Unexpected data type (" + _cellType + ")");\r
+ }\r
+\r
+ private void checkCellType(int expectedCellType) {\r
+ if (_cellType != expectedCellType) {\r
+ throw new RuntimeException("Wrong data type (" + _cellType + ")");\r
+ }\r
+ }\r
+ public int getCellType() {\r
+ return _cellType;\r
+ }\r
+ public boolean getBooleanCellValue() {\r
+ checkCellType(HSSFCell.CELL_TYPE_BOOLEAN);\r
+ return _booleanValue;\r
+ }\r
+ public int getErrorCellValue() {\r
+ checkCellType(HSSFCell.CELL_TYPE_ERROR);\r
+ return _errorValue;\r
+ }\r
+ public double getNumericCellValue() {\r
+ checkCellType(HSSFCell.CELL_TYPE_NUMERIC);\r
+ return _numberValue;\r
+ }\r
+ public String getStringCellValue() {\r
+ checkCellType(HSSFCell.CELL_TYPE_STRING);\r
+ return _stringValue;\r
+ }\r
+ public EvaluationSheet getSheet() {\r
+ return _sheet;\r
+ }\r
+ public int getRowIndex() {\r
+ return _masterCell.getRowIndex();\r
+ }\r
+ public int getColumnIndex() {\r
+ return _masterCell.getColumnIndex();\r
+ }\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.eval.forked;\r
+\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.apache.poi.ss.formula.EvaluationCell;\r
+import org.apache.poi.ss.formula.EvaluationSheet;\r
+import org.apache.poi.ss.formula.EvaluationWorkbook;\r
+import org.apache.poi.ss.usermodel.Cell;\r
+import org.apache.poi.ss.usermodel.Row;\r
+import org.apache.poi.ss.usermodel.Sheet;\r
+\r
+/**\r
+ * Represents a sheet being used for forked evaluation. Initially, objects of this class contain\r
+ * only the cells from the master workbook. By calling {@link #getOrCreateUpdatableCell(int, int)},\r
+ * the master cell object is logically replaced with a {@link ForkedEvaluationCell} instance, which\r
+ * will be used in all subsequent evaluations.\r
+ *\r
+ * @author Josh Micich\r
+ */\r
+final class ForkedEvaluationSheet implements EvaluationSheet {\r
+\r
+ private final EvaluationSheet _masterSheet;\r
+ /**\r
+ * Only cells which have been split are put in this map. (This has been done to conserve memory).\r
+ */\r
+ private final Map<RowColKey, ForkedEvaluationCell> _sharedCellsByRowCol;\r
+\r
+ public ForkedEvaluationSheet(EvaluationSheet masterSheet) {\r
+ _masterSheet = masterSheet;\r
+ _sharedCellsByRowCol = new HashMap<RowColKey, ForkedEvaluationCell>();\r
+ }\r
+\r
+ public EvaluationCell getCell(int rowIndex, int columnIndex) {\r
+ RowColKey key = new RowColKey(rowIndex, columnIndex);\r
+\r
+ ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);\r
+ if (result == null) {\r
+ return _masterSheet.getCell(rowIndex, columnIndex);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public ForkedEvaluationCell getOrCreateUpdatableCell(int rowIndex, int columnIndex) {\r
+ RowColKey key = new RowColKey(rowIndex, columnIndex);\r
+\r
+ ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);\r
+ if (result == null) {\r
+ EvaluationCell mcell = _masterSheet.getCell(rowIndex, columnIndex);\r
+ result = new ForkedEvaluationCell(this, mcell);\r
+ _sharedCellsByRowCol.put(key, result);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public void copyUpdatedCells(Sheet sheet) {\r
+ RowColKey[] keys = new RowColKey[_sharedCellsByRowCol.size()];\r
+ _sharedCellsByRowCol.keySet().toArray(keys);\r
+ Arrays.sort(keys);\r
+ for (int i = 0; i < keys.length; i++) {\r
+ RowColKey key = keys[i];\r
+ Row row = sheet.getRow(key.getRowIndex());\r
+ if (row == null) {\r
+ row = sheet.createRow(key.getRowIndex());\r
+ }\r
+ Cell destCell = row.getCell(key.getColumnIndex());\r
+ if (destCell == null) {\r
+ destCell = row.createCell(key.getColumnIndex());\r
+ }\r
+\r
+ ForkedEvaluationCell srcCell = _sharedCellsByRowCol.get(key);\r
+ srcCell.copyValue(destCell);\r
+ }\r
+ }\r
+\r
+ public int getSheetIndex(EvaluationWorkbook mewb) {\r
+ return mewb.getSheetIndex(_masterSheet);\r
+ }\r
+\r
+ private static final class RowColKey implements Comparable<RowColKey>{\r
+ private final int _rowIndex;\r
+ private final int _columnIndex;\r
+\r
+ public RowColKey(int rowIndex, int columnIndex) {\r
+ _rowIndex = rowIndex;\r
+ _columnIndex = columnIndex;\r
+ }\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ RowColKey other = (RowColKey) obj;\r
+ return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;\r
+ }\r
+ @Override\r
+ public int hashCode() {\r
+ return _rowIndex ^ _columnIndex;\r
+ }\r
+ public int compareTo(RowColKey o) {\r
+ int cmp = _rowIndex - o._rowIndex;\r
+ if (cmp != 0) {\r
+ return cmp;\r
+ }\r
+ return _columnIndex - o._columnIndex;\r
+ }\r
+ public int getRowIndex() {\r
+ return _rowIndex;\r
+ }\r
+ public int getColumnIndex() {\r
+ return _columnIndex;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.eval.forked;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.apache.poi.hssf.record.formula.NamePtg;\r
+import org.apache.poi.hssf.record.formula.NameXPtg;\r
+import org.apache.poi.hssf.record.formula.Ptg;\r
+import org.apache.poi.ss.formula.EvaluationCell;\r
+import org.apache.poi.ss.formula.EvaluationName;\r
+import org.apache.poi.ss.formula.EvaluationSheet;\r
+import org.apache.poi.ss.formula.EvaluationWorkbook;\r
+import org.apache.poi.ss.usermodel.Workbook;\r
+\r
+/**\r
+ * Represents a workbook being used for forked evaluation. Most operations are delegated to the\r
+ * shared master workbook, except those that potentially involve cell values that may have been \r
+ * updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.\r
+ *\r
+ * @author Josh Micich\r
+ */\r
+final class ForkedEvaluationWorkbook implements EvaluationWorkbook {\r
+\r
+ private final EvaluationWorkbook _masterBook;\r
+ private final Map<String, ForkedEvaluationSheet> _sharedSheetsByName;\r
+\r
+ public ForkedEvaluationWorkbook(EvaluationWorkbook master) {\r
+ _masterBook = master;\r
+ _sharedSheetsByName = new HashMap<String, ForkedEvaluationSheet>();\r
+ }\r
+\r
+ public ForkedEvaluationCell getOrCreateUpdatableCell(String sheetName, int rowIndex,\r
+ int columnIndex) {\r
+ ForkedEvaluationSheet sheet = getSharedSheet(sheetName);\r
+ return sheet.getOrCreateUpdatableCell(rowIndex, columnIndex);\r
+ }\r
+\r
+ public EvaluationCell getEvaluationCell(String sheetName, int rowIndex, int columnIndex) {\r
+ ForkedEvaluationSheet sheet = getSharedSheet(sheetName);\r
+ return sheet.getCell(rowIndex, columnIndex);\r
+ }\r
+\r
+ private ForkedEvaluationSheet getSharedSheet(String sheetName) {\r
+ ForkedEvaluationSheet result = _sharedSheetsByName.get(sheetName);\r
+ if (result == null) {\r
+ result = new ForkedEvaluationSheet(_masterBook.getSheet(_masterBook\r
+ .getSheetIndex(sheetName)));\r
+ _sharedSheetsByName.put(sheetName, result);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public void copyUpdatedCells(Workbook workbook) {\r
+ String[] sheetNames = new String[_sharedSheetsByName.size()];\r
+ _sharedSheetsByName.keySet().toArray(sheetNames);\r
+ OrderedSheet[] oss = new OrderedSheet[sheetNames.length];\r
+ for (int i = 0; i < sheetNames.length; i++) {\r
+ String sheetName = sheetNames[i];\r
+ oss[i] = new OrderedSheet(sheetName, _masterBook.getSheetIndex(sheetName));\r
+ }\r
+ for (int i = 0; i < oss.length; i++) {\r
+ String sheetName = oss[i].getSheetName();\r
+ ForkedEvaluationSheet sheet = _sharedSheetsByName.get(sheetName);\r
+ sheet.copyUpdatedCells(workbook.getSheet(sheetName));\r
+ }\r
+ }\r
+\r
+ public int convertFromExternSheetIndex(int externSheetIndex) {\r
+ return _masterBook.convertFromExternSheetIndex(externSheetIndex);\r
+ }\r
+\r
+ public ExternalSheet getExternalSheet(int externSheetIndex) {\r
+ return _masterBook.getExternalSheet(externSheetIndex);\r
+ }\r
+\r
+ public Ptg[] getFormulaTokens(EvaluationCell cell) {\r
+ if (cell instanceof ForkedEvaluationCell) {\r
+ // doesn't happen yet because formulas cannot be modified from the master workbook\r
+ throw new RuntimeException("Updated formulas not supported yet");\r
+ }\r
+ return _masterBook.getFormulaTokens(cell);\r
+ }\r
+\r
+ public EvaluationName getName(NamePtg namePtg) {\r
+ return _masterBook.getName(namePtg);\r
+ }\r
+\r
+ public EvaluationSheet getSheet(int sheetIndex) {\r
+ return getSharedSheet(getSheetName(sheetIndex));\r
+ }\r
+\r
+ public int getSheetIndex(EvaluationSheet sheet) {\r
+ if (sheet instanceof ForkedEvaluationSheet) {\r
+ ForkedEvaluationSheet mes = (ForkedEvaluationSheet) sheet;\r
+ return mes.getSheetIndex(_masterBook);\r
+ }\r
+ return _masterBook.getSheetIndex(sheet);\r
+ }\r
+\r
+ public int getSheetIndex(String sheetName) {\r
+ return _masterBook.getSheetIndex(sheetName);\r
+ }\r
+\r
+ public String getSheetName(int sheetIndex) {\r
+ return _masterBook.getSheetName(sheetIndex);\r
+ }\r
+\r
+ public String resolveNameXText(NameXPtg ptg) {\r
+ return _masterBook.resolveNameXText(ptg);\r
+ }\r
+\r
+ private static final class OrderedSheet implements Comparable<OrderedSheet> {\r
+ private final String _sheetName;\r
+ private final int _index;\r
+\r
+ public OrderedSheet(String sheetName, int index) {\r
+ _sheetName = sheetName;\r
+ _index = index;\r
+ }\r
+ public String getSheetName() {\r
+ return _sheetName;\r
+ }\r
+ public int compareTo(OrderedSheet o) {\r
+ return _index - o._index;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.eval.forked;\r
+\r
+import org.apache.poi.hssf.record.formula.eval.BoolEval;\r
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;\r
+import org.apache.poi.hssf.record.formula.eval.NumberEval;\r
+import org.apache.poi.hssf.record.formula.eval.StringEval;\r
+import org.apache.poi.hssf.record.formula.eval.ValueEval;\r
+import org.apache.poi.hssf.usermodel.HSSFCell;\r
+import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;\r
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
+import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;\r
+import org.apache.poi.ss.formula.EvaluationCell;\r
+import org.apache.poi.ss.formula.EvaluationWorkbook;\r
+import org.apache.poi.ss.formula.IStabilityClassifier;\r
+import org.apache.poi.ss.formula.WorkbookEvaluator;\r
+import org.apache.poi.ss.usermodel.Workbook;\r
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;\r
+\r
+/**\r
+ * An alternative workbook evaluator that saves memory in situations where a single workbook is\r
+ * concurrently and independently evaluated many times. With standard formula evaluation, around \r
+ * 90% of memory consumption is due to loading of the {@link HSSFWorkbook} or {@link XSSFWorkbook}.\r
+ * This class enables a 'master workbook' to be loaded just once and shared between many evaluation\r
+ * clients. Each evaluation client creates its own {@link ForkedEvaluator} and can set cell values\r
+ * that will be used for local evaluations (and don't disturb evaluations on other evaluators).\r
+ *\r
+ * @author Josh Micich\r
+ */\r
+public final class ForkedEvaluator {\r
+\r
+ private WorkbookEvaluator _evaluator;\r
+ private ForkedEvaluationWorkbook _sewb;\r
+\r
+ private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {\r
+ _sewb = new ForkedEvaluationWorkbook(masterWorkbook);\r
+ _evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);\r
+ }\r
+ private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {\r
+ if (wb instanceof HSSFWorkbook) {\r
+ return HSSFEvaluationWorkbook.create((HSSFWorkbook) wb);\r
+ }\r
+// TODO rearrange POI build to allow this\r
+// if (wb instanceof XSSFWorkbook) {\r
+// return XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);\r
+// }\r
+ throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");\r
+ }\r
+ public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier) {\r
+ return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier);\r
+ }\r
+\r
+ /**\r
+ * Sets the specified cell to the supplied <tt>value</tt>\r
+ * @param sheetName the name of the sheet containing the cell\r
+ * @param rowIndex zero based\r
+ * @param columnIndex zero based\r
+ */\r
+ public void updateCell(String sheetName, int rowIndex, int columnIndex, ValueEval value) {\r
+\r
+ ForkedEvaluationCell cell = _sewb.getOrCreateUpdatableCell(sheetName, rowIndex, columnIndex);\r
+ cell.setValue(value);\r
+ _evaluator.notifyUpdateCell(cell);\r
+ }\r
+ /**\r
+ * Copies the values of all updated cells (modified by calls to {@link \r
+ * #updateCell(String, int, int, ValueEval)}) to the supplied <tt>workbook</tt>.<br/>\r
+ * Typically, the supplied <tt>workbook</tt> is a writable copy of the 'master workbook', \r
+ * but at the very least it must contain sheets with the same names. \r
+ */\r
+ public void copyUpdatedCells(Workbook workbook) {\r
+ _sewb.copyUpdatedCells(workbook);\r
+ }\r
+\r
+ /**\r
+ * If cell contains a formula, the formula is evaluated and returned,\r
+ * else the CellValue simply copies the appropriate cell value from\r
+ * the cell and also its cell type. This method should be preferred over\r
+ * evaluateInCell() when the call should not modify the contents of the\r
+ * original cell.\r
+ *\r
+ * @param cell may be <code>null</code> signifying that the cell is not present (or blank)\r
+ * @return <code>null</code> if the supplied cell is <code>null</code> or blank\r
+ */\r
+ public ValueEval evaluate(String sheetName, int rowIndex, int columnIndex) {\r
+ EvaluationCell cell = _sewb.getEvaluationCell(sheetName, rowIndex, columnIndex);\r
+\r
+ switch (cell.getCellType()) {\r
+ case HSSFCell.CELL_TYPE_BOOLEAN:\r
+ return BoolEval.valueOf(cell.getBooleanCellValue());\r
+ case HSSFCell.CELL_TYPE_ERROR:\r
+ return ErrorEval.valueOf(cell.getErrorCellValue());\r
+ case HSSFCell.CELL_TYPE_FORMULA:\r
+ return _evaluator.evaluate(cell);\r
+ case HSSFCell.CELL_TYPE_NUMERIC:\r
+ return new NumberEval(cell.getNumericCellValue());\r
+ case HSSFCell.CELL_TYPE_STRING:\r
+ return new StringEval(cell.getStringCellValue());\r
+ case HSSFCell.CELL_TYPE_BLANK:\r
+ return null;\r
+ }\r
+ throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");\r
+ }\r
+ /**\r
+ * Coordinates several formula evaluators together so that formulas that involve external\r
+ * references can be evaluated.\r
+ * @param workbookNames the simple file names used to identify the workbooks in formulas\r
+ * with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")\r
+ * @param evaluators all evaluators for the full set of workbooks required by the formulas.\r
+ */\r
+ public static void setupEnvironment(String[] workbookNames, ForkedEvaluator[] evaluators) {\r
+ WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];\r
+ for (int i = 0; i < wbEvals.length; i++) {\r
+ wbEvals[i] = evaluators[i]._evaluator;\r
+ }\r
+ CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);\r
+ }\r
+}\r