198 lines
6.2 KiB
Java
198 lines
6.2 KiB
Java
/* ====================================================================
|
|
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.ss.formula;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.apache.poi.ss.util.CellReference;
|
|
|
|
/**
|
|
* Optimization - compacts many blank cell references used by a single formula.
|
|
*/
|
|
final class FormulaUsedBlankCellSet {
|
|
public static final class BookSheetKey {
|
|
|
|
private final int _bookIndex;
|
|
private final int _sheetIndex;
|
|
|
|
public BookSheetKey(int bookIndex, int sheetIndex) {
|
|
_bookIndex = bookIndex;
|
|
_sheetIndex = sheetIndex;
|
|
}
|
|
@Override
|
|
public int hashCode() {
|
|
return _bookIndex * 17 + _sheetIndex;
|
|
}
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (!(obj instanceof BookSheetKey)) {
|
|
return false;
|
|
}
|
|
BookSheetKey other = (BookSheetKey) obj;
|
|
return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
|
|
}
|
|
}
|
|
|
|
private static final class BlankCellSheetGroup {
|
|
private final List<BlankCellRectangleGroup> _rectangleGroups;
|
|
private int _currentRowIndex;
|
|
private int _firstColumnIndex;
|
|
private int _lastColumnIndex;
|
|
private BlankCellRectangleGroup _currentRectangleGroup;
|
|
|
|
public BlankCellSheetGroup() {
|
|
_rectangleGroups = new ArrayList<BlankCellRectangleGroup>();
|
|
_currentRowIndex = -1;
|
|
}
|
|
|
|
public void addCell(int rowIndex, int columnIndex) {
|
|
if (_currentRowIndex == -1) {
|
|
_currentRowIndex = rowIndex;
|
|
_firstColumnIndex = columnIndex;
|
|
_lastColumnIndex = columnIndex;
|
|
} else {
|
|
if (_currentRowIndex == rowIndex && _lastColumnIndex+1 == columnIndex) {
|
|
_lastColumnIndex = columnIndex;
|
|
} else {
|
|
// cell does not fit on end of current row
|
|
if (_currentRectangleGroup == null) {
|
|
_currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
|
|
} else {
|
|
if (!_currentRectangleGroup.acceptRow(_currentRowIndex, _firstColumnIndex, _lastColumnIndex)) {
|
|
_rectangleGroups.add(_currentRectangleGroup);
|
|
_currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
|
|
}
|
|
}
|
|
_currentRowIndex = rowIndex;
|
|
_firstColumnIndex = columnIndex;
|
|
_lastColumnIndex = columnIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean containsCell(int rowIndex, int columnIndex) {
|
|
for (int i=_rectangleGroups.size()-1; i>=0; i--) {
|
|
BlankCellRectangleGroup bcrg = _rectangleGroups.get(i);
|
|
if (bcrg.containsCell(rowIndex, columnIndex)) {
|
|
return true;
|
|
}
|
|
}
|
|
if(_currentRectangleGroup != null && _currentRectangleGroup.containsCell(rowIndex, columnIndex)) {
|
|
return true;
|
|
}
|
|
if (_currentRowIndex != -1 && _currentRowIndex == rowIndex) {
|
|
if (_firstColumnIndex <= columnIndex && columnIndex <= _lastColumnIndex) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static final class BlankCellRectangleGroup {
|
|
|
|
private final int _firstRowIndex;
|
|
private final int _firstColumnIndex;
|
|
private final int _lastColumnIndex;
|
|
private int _lastRowIndex;
|
|
|
|
public BlankCellRectangleGroup(int firstRowIndex, int firstColumnIndex, int lastColumnIndex) {
|
|
_firstRowIndex = firstRowIndex;
|
|
_firstColumnIndex = firstColumnIndex;
|
|
_lastColumnIndex = lastColumnIndex;
|
|
_lastRowIndex = firstRowIndex;
|
|
}
|
|
|
|
public boolean containsCell(int rowIndex, int columnIndex) {
|
|
if (columnIndex < _firstColumnIndex) {
|
|
return false;
|
|
}
|
|
if (columnIndex > _lastColumnIndex) {
|
|
return false;
|
|
}
|
|
if (rowIndex < _firstRowIndex) {
|
|
return false;
|
|
}
|
|
if (rowIndex > _lastRowIndex) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean acceptRow(int rowIndex, int firstColumnIndex, int lastColumnIndex) {
|
|
if (firstColumnIndex != _firstColumnIndex) {
|
|
return false;
|
|
}
|
|
if (lastColumnIndex != _lastColumnIndex) {
|
|
return false;
|
|
}
|
|
if (rowIndex != _lastRowIndex+1) {
|
|
return false;
|
|
}
|
|
_lastRowIndex = rowIndex;
|
|
return true;
|
|
}
|
|
@Override
|
|
public String toString() {
|
|
StringBuffer sb = new StringBuffer(64);
|
|
CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
|
|
CellReference crB = new CellReference(_lastRowIndex, _lastColumnIndex, false, false);
|
|
sb.append(getClass().getName());
|
|
sb.append(" [").append(crA.formatAsString()).append(':').append(crB.formatAsString()).append("]");
|
|
return sb.toString();
|
|
}
|
|
}
|
|
|
|
private final Map<BookSheetKey, BlankCellSheetGroup> _sheetGroupsByBookSheet;
|
|
|
|
public FormulaUsedBlankCellSet() {
|
|
_sheetGroupsByBookSheet = new HashMap<BookSheetKey, BlankCellSheetGroup>();
|
|
}
|
|
|
|
public void addCell(int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
|
|
BlankCellSheetGroup sbcg = getSheetGroup(bookIndex, sheetIndex);
|
|
sbcg.addCell(rowIndex, columnIndex);
|
|
}
|
|
|
|
private BlankCellSheetGroup getSheetGroup(int bookIndex, int sheetIndex) {
|
|
BookSheetKey key = new BookSheetKey(bookIndex, sheetIndex);
|
|
|
|
BlankCellSheetGroup result = _sheetGroupsByBookSheet.get(key);
|
|
if (result == null) {
|
|
result = new BlankCellSheetGroup();
|
|
_sheetGroupsByBookSheet.put(key, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public boolean containsCell(BookSheetKey key, int rowIndex, int columnIndex) {
|
|
BlankCellSheetGroup bcsg = _sheetGroupsByBookSheet.get(key);
|
|
if (bcsg == null) {
|
|
return false;
|
|
}
|
|
return bcsg.containsCell(rowIndex, columnIndex);
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return _sheetGroupsByBookSheet.isEmpty();
|
|
}
|
|
}
|