/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ package org.apache.poi.hssf.record.aggregates; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.poi.hssf.record.ArrayRecord; import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.SharedFormulaRecord; import org.apache.poi.hssf.record.SharedValueRecordBase; import org.apache.poi.hssf.record.TableRecord; import org.apache.poi.ss.formula.ptg.ExpPtg; import org.apache.poi.hssf.util.CellRangeAddress8Bit; import org.apache.poi.ss.util.CellReference; /** * Manages various auxiliary records while constructing a * {@link RowRecordsAggregate}: *
null
*/
public SharedFormulaRecord linkSharedFormulaRecord(CellReference firstCell, FormulaRecordAggregate agg) {
SharedFormulaGroup result = findFormulaGroupForCell(firstCell);
if(null == result) {
throw new RuntimeException("Failed to find a matching shared formula record");
}
result.add(agg);
return result.getSFR();
}
private SharedFormulaGroup findFormulaGroupForCell(final CellReference cellRef) {
if(null == _groupsCache) {
_groupsCache = new HashMapnull
if the formula cell is not shared/array/table,
* or if the specified formula is not the the first in the group.
*/
public SharedValueRecordBase getRecordForFirstCell(FormulaRecordAggregate agg) {
CellReference firstCell = agg.getFormulaRecord().getFormula().getExpReference();
// perhaps this could be optimised by consulting the (somewhat unreliable) isShared flag
// and/or distinguishing between tExp and tTbl.
if (firstCell == null) {
// not a shared/array/table formula
return null;
}
int row = firstCell.getRow();
int column = firstCell.getCol();
if (agg.getRow() != row || agg.getColumn() != column) {
// not the first formula cell in the group
return null;
}
if(!_groupsBySharedFormulaRecord.isEmpty()) {
SharedFormulaGroup sfg = findFormulaGroupForCell(firstCell);
if(null != sfg) {
return sfg.getSFR();
}
}
// Since arrays and tables cannot be sparse (all cells in range participate)
// The first cell will be the top left in the range. So we can match the
// ARRAY/TABLE record directly.
for (TableRecord tr : _tableRecords) {
if (tr.isFirstCell(row, column)) {
return tr;
}
}
for (ArrayRecord ar : _arrayRecords) {
if (ar.isFirstCell(row, column)) {
return ar;
}
}
return null;
}
/**
* Converts all {@link FormulaRecord}s handled by sharedFormulaRecord
* to plain unshared formulas
*/
public void unlink(SharedFormulaRecord sharedFormulaRecord) {
SharedFormulaGroup svg = _groupsBySharedFormulaRecord.remove(sharedFormulaRecord);
if (svg == null) {
throw new IllegalStateException("Failed to find formulas for shared formula");
}
_groupsCache = null; // be sure to reset cached value
svg.unlinkSharedFormulas();
}
/**
* Add specified Array Record.
*/
public void addArrayRecord(ArrayRecord ar) {
// could do a check here to make sure none of the ranges overlap
_arrayRecords.add(ar);
}
/**
* Removes the {@link ArrayRecord} for the cell group containing the specified cell.
* The caller should clear (set blank) all cells in the returned range.
* @return the range of the array formula which was just removed. Never null
.
*/
public CellRangeAddress8Bit removeArrayFormula(int rowIndex, int columnIndex) {
for (ArrayRecord ar : _arrayRecords) {
if (ar.isInRange(rowIndex, columnIndex)) {
_arrayRecords.remove(ar);
return ar.getRange();
}
}
String ref = new CellReference(rowIndex, columnIndex, false, false).formatAsString();
throw new IllegalArgumentException("Specified cell " + ref
+ " is not part of an array formula.");
}
/**
* @return the shared ArrayRecord identified by (firstRow, firstColumn). never null
.
*/
public ArrayRecord getArrayRecord(int firstRow, int firstColumn) {
for(ArrayRecord ar : _arrayRecords) {
if(ar.isFirstCell(firstRow, firstColumn)) {
return ar;
}
}
return null;
}
}