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; } } }