167 lines
4.6 KiB
Java
167 lines
4.6 KiB
Java
package jxl.write.biff;
|
|
|
|
import common.Assert;
|
|
import common.Logger;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import jxl.Cell;
|
|
import jxl.CellType;
|
|
import jxl.Range;
|
|
import jxl.WorkbookSettings;
|
|
import jxl.biff.ByteData;
|
|
import jxl.biff.SheetRangeImpl;
|
|
import jxl.write.Blank;
|
|
import jxl.write.WritableCell;
|
|
import jxl.write.WritableSheet;
|
|
import jxl.write.WriteException;
|
|
|
|
class MergedCells {
|
|
private static Logger logger = Logger.getLogger(MergedCells.class);
|
|
|
|
private ArrayList ranges;
|
|
|
|
private WritableSheet sheet;
|
|
|
|
private static final int maxRangesPerSheet = 1020;
|
|
|
|
public MergedCells(WritableSheet ws) {
|
|
this.ranges = new ArrayList();
|
|
this.sheet = ws;
|
|
}
|
|
|
|
void add(Range r) {
|
|
this.ranges.add(r);
|
|
}
|
|
|
|
void insertRow(int row) {
|
|
SheetRangeImpl sr = null;
|
|
Iterator i = this.ranges.iterator();
|
|
while (i.hasNext()) {
|
|
sr = i.next();
|
|
sr.insertRow(row);
|
|
}
|
|
}
|
|
|
|
void insertColumn(int col) {
|
|
SheetRangeImpl sr = null;
|
|
Iterator i = this.ranges.iterator();
|
|
while (i.hasNext()) {
|
|
sr = i.next();
|
|
sr.insertColumn(col);
|
|
}
|
|
}
|
|
|
|
void removeColumn(int col) {
|
|
SheetRangeImpl sr = null;
|
|
Iterator i = this.ranges.iterator();
|
|
while (i.hasNext()) {
|
|
sr = i.next();
|
|
if (sr.getTopLeft().getColumn() == col && sr.getBottomRight().getColumn() == col) {
|
|
this.ranges.remove(this.ranges.indexOf(sr));
|
|
continue;
|
|
}
|
|
sr.removeColumn(col);
|
|
}
|
|
}
|
|
|
|
void removeRow(int row) {
|
|
SheetRangeImpl sr = null;
|
|
Iterator i = this.ranges.iterator();
|
|
while (i.hasNext()) {
|
|
sr = i.next();
|
|
if (sr.getTopLeft().getRow() == row && sr.getBottomRight().getRow() == row) {
|
|
i.remove();
|
|
continue;
|
|
}
|
|
sr.removeRow(row);
|
|
}
|
|
}
|
|
|
|
Range[] getMergedCells() {
|
|
Range[] cells = new Range[this.ranges.size()];
|
|
for (int i = 0; i < cells.length; i++)
|
|
cells[i] = this.ranges.get(i);
|
|
return cells;
|
|
}
|
|
|
|
void unmergeCells(Range r) {
|
|
int index = this.ranges.indexOf(r);
|
|
if (index != -1)
|
|
this.ranges.remove(index);
|
|
}
|
|
|
|
private void checkIntersections() {
|
|
ArrayList newcells = new ArrayList(this.ranges.size());
|
|
for (Iterator mci = this.ranges.iterator(); mci.hasNext(); ) {
|
|
SheetRangeImpl r = mci.next();
|
|
Iterator i = newcells.iterator();
|
|
SheetRangeImpl range = null;
|
|
boolean intersects = false;
|
|
while (i.hasNext() && !intersects) {
|
|
range = i.next();
|
|
if (range.intersects(r)) {
|
|
logger.warn("Could not merge cells " + r + " as they clash with an existing set of merged cells.");
|
|
intersects = true;
|
|
}
|
|
}
|
|
if (!intersects)
|
|
newcells.add(r);
|
|
}
|
|
this.ranges = newcells;
|
|
}
|
|
|
|
private void checkRanges() {
|
|
try {
|
|
SheetRangeImpl range = null;
|
|
for (int i = 0; i < this.ranges.size(); i++) {
|
|
range = this.ranges.get(i);
|
|
Cell tl = range.getTopLeft();
|
|
Cell br = range.getBottomRight();
|
|
boolean found = false;
|
|
for (int c = tl.getColumn(); c <= br.getColumn(); c++) {
|
|
for (int r = tl.getRow(); r <= br.getRow(); r++) {
|
|
Cell cell = this.sheet.getCell(c, r);
|
|
if (cell.getType() != CellType.EMPTY)
|
|
if (!found) {
|
|
found = true;
|
|
} else {
|
|
logger.warn("Range " + range + " contains more than one data cell. " + "Setting the other cells to blank.");
|
|
Blank b = new Blank(c, r);
|
|
this.sheet.addCell((WritableCell)b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (WriteException e) {
|
|
Assert.verify(false);
|
|
}
|
|
}
|
|
|
|
void write(File outputFile) throws IOException {
|
|
if (this.ranges.size() == 0)
|
|
return;
|
|
WorkbookSettings ws = ((WritableSheetImpl)this.sheet).getWorkbookSettings();
|
|
if (!ws.getMergedCellCheckingDisabled()) {
|
|
checkIntersections();
|
|
checkRanges();
|
|
}
|
|
if (this.ranges.size() < 1020) {
|
|
MergedCellsRecord mcr = new MergedCellsRecord(this.ranges);
|
|
outputFile.write((ByteData)mcr);
|
|
return;
|
|
}
|
|
int numRecordsRequired = this.ranges.size() / 1020 + 1;
|
|
int pos = 0;
|
|
for (int i = 0; i < numRecordsRequired; i++) {
|
|
int numranges = Math.min(1020, this.ranges.size() - pos);
|
|
ArrayList cells = new ArrayList(numranges);
|
|
for (int j = 0; j < numranges; j++)
|
|
cells.add(this.ranges.get(pos + j));
|
|
MergedCellsRecord mcr = new MergedCellsRecord(cells);
|
|
outputFile.write((ByteData)mcr);
|
|
pos += numranges;
|
|
}
|
|
}
|
|
}
|