Cell Style optimisations too

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@677057 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-07-15 21:38:38 +00:00
parent b2edbb5332
commit 58f0fc9eaf
4 changed files with 190 additions and 3 deletions

View File

@ -713,6 +713,18 @@ public class Workbook implements Model
return retval; return retval;
} }
/**
* Removes the given ExtendedFormatRecord record from the
* file's list. This will make all
* subsequent font indicies drop by one,
* so you'll need to update those yourself!
*/
public void removeExFormatRecord(ExtendedFormatRecord rec) {
records.remove(rec); // this updates XfPos for us
numxfs--;
}
/** /**
* creates a new Cell-type Extneded Format Record and adds it to the end of * creates a new Cell-type Extneded Format Record and adds it to the end of

View File

@ -927,14 +927,13 @@ public class HSSFCell
* object. * object.
* @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short) * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#getCellStyleAt(short)
*/ */
public HSSFCellStyle getCellStyle() public HSSFCellStyle getCellStyle()
{ {
short styleIndex=record.getXFIndex(); short styleIndex=record.getXFIndex();
ExtendedFormatRecord xf = book.getWorkbook().getExFormatAt(styleIndex); ExtendedFormatRecord xf = book.getWorkbook().getExFormatAt(styleIndex);
return new HSSFCellStyle(styleIndex, xf, book); return new HSSFCellStyle(styleIndex, xf, book);
} }
/** /**
* used for internationalization, currently -1 for unchanged, 0 for compressed unicode or 1 for 16-bit * used for internationalization, currently -1 for unchanged, 0 for compressed unicode or 1 for 16-bit
* *

View File

@ -173,6 +173,89 @@ public class HSSFOptimiser {
* @param workbook The workbook in which to optimise the cell styles * @param workbook The workbook in which to optimise the cell styles
*/ */
public static void optimiseCellStyles(HSSFWorkbook workbook) { public static void optimiseCellStyles(HSSFWorkbook workbook) {
// Where each style has ended up, and if we need to
// delete the record for it. Start off with no change
short[] newPos =
new short[workbook.getWorkbook().getNumExFormats()];
boolean[] zapRecords = new boolean[newPos.length];
for(int i=0; i<newPos.length; i++) {
newPos[i] = (short)i;
zapRecords[i] = false;
}
// Get each style record, so we can do deletes
// without getting confused
ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length];
for(int i=0; i<newPos.length; i++) {
xfrs[i] = workbook.getWorkbook().getExFormatAt(i);
}
// Loop over each style, seeing if it is the same
// as an earlier one. If it is, point users of the
// later duplicate copy to the earlier one, and
// mark the later one as needing deleting
// Only work on user added ones, which come after 20
for(int i=21; i<newPos.length; i++) {
// Check this one for being a duplicate
// of an earlier one
int earlierDuplicate = -1;
for(int j=0; j<i && earlierDuplicate == -1; j++) {
ExtendedFormatRecord xfCheck = workbook.getWorkbook().getExFormatAt(j);
if(xfCheck.equals(xfrs[i])) {
earlierDuplicate = j;
}
}
// If we got a duplicate, mark it as such
if(earlierDuplicate != -1) {
newPos[i] = (short)earlierDuplicate;
zapRecords[i] = true;
}
}
// Update the new positions based on
// deletes that have occurred between
// the start and them
// Only work on user added ones, which come after 20
for(int i=21; i<newPos.length; i++) {
// Find the number deleted to that
// point, and adjust
short preDeletePos = newPos[i];
short newPosition = preDeletePos;
for(int j=0; j<preDeletePos; j++) {
if(zapRecords[j]) newPosition--;
}
// Update the new position
newPos[i] = newPosition;
}
// Zap the un-needed user style records
for(int i=21; i<newPos.length; i++) {
if(zapRecords[i]) {
workbook.getWorkbook().removeExFormatRecord(
xfrs[i]
);
}
}
// Finally, update the cells to point at
// their new extended format records
for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) {
HSSFSheet s = workbook.getSheetAt(sheetNum);
Iterator rIt = s.rowIterator();
while(rIt.hasNext()) {
HSSFRow row = (HSSFRow)rIt.next();
Iterator cIt = row.cellIterator();
while(cIt.hasNext()) {
HSSFCell cell = (HSSFCell)cIt.next();
short oldXf = cell.getCellValueRecord().getXFIndex();
HSSFCellStyle newStyle = workbook.getCellStyleAt(
newPos[oldXf]
);
cell.setCellStyle(newStyle);
}
}
}
} }
} }

View File

@ -15,6 +15,8 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.Workbook;
import junit.framework.TestCase; import junit.framework.TestCase;
public class TestHSSFOptimiser extends TestCase { public class TestHSSFOptimiser extends TestCase {
@ -38,7 +40,7 @@ public class TestHSSFOptimiser extends TestCase {
assertEquals(f, s.getFont(wb)); assertEquals(f, s.getFont(wb));
// Optimise styles // Optimise styles
// HSSFOptimiser.optimiseCellStyles(wb); HSSFOptimiser.optimiseCellStyles(wb);
assertEquals(5, wb.getNumberOfFonts()); assertEquals(5, wb.getNumberOfFonts());
assertEquals(22, wb.getNumCellStyles()); assertEquals(22, wb.getNumCellStyles());
@ -77,6 +79,8 @@ public class TestHSSFOptimiser extends TestCase {
// Use all three of the four in cell styles // Use all three of the four in cell styles
assertEquals(21, wb.getNumCellStyles());
HSSFCellStyle cs1 = wb.createCellStyle(); HSSFCellStyle cs1 = wb.createCellStyle();
cs1.setFont(f1); cs1.setFont(f1);
assertEquals(5, cs1.getFontIndex()); assertEquals(5, cs1.getFontIndex());
@ -93,6 +97,8 @@ public class TestHSSFOptimiser extends TestCase {
cs4.setFont(f6); cs4.setFont(f6);
assertEquals(10, cs4.getFontIndex()); assertEquals(10, cs4.getFontIndex());
assertEquals(25, wb.getNumCellStyles());
// And three in rich text // And three in rich text
HSSFSheet s = wb.createSheet(); HSSFSheet s = wb.createSheet();
@ -144,4 +150,91 @@ public class TestHSSFOptimiser extends TestCase {
assertEquals(8, r.getCell(1).getRichStringCellValue().getFontAtIndex(6)); assertEquals(8, r.getCell(1).getRichStringCellValue().getFontAtIndex(6));
assertEquals(8, r.getCell(1).getRichStringCellValue().getFontAtIndex(7)); assertEquals(8, r.getCell(1).getRichStringCellValue().getFontAtIndex(7));
} }
public void testOptimiseStyles() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
// Two fonts
assertEquals(4, wb.getNumberOfFonts());
HSSFFont f1 = wb.createFont();
f1.setFontHeight((short)11);
f1.setFontName("Testing");
HSSFFont f2 = wb.createFont();
f2.setFontHeight((short)22);
f2.setFontName("Also Testing");
assertEquals(6, wb.getNumberOfFonts());
// Several styles
assertEquals(21, wb.getNumCellStyles());
HSSFCellStyle cs1 = wb.createCellStyle();
cs1.setFont(f1);
HSSFCellStyle cs2 = wb.createCellStyle();
cs2.setFont(f2);
HSSFCellStyle cs3 = wb.createCellStyle();
cs3.setFont(f1);
HSSFCellStyle cs4 = wb.createCellStyle();
cs4.setFont(f1);
cs4.setAlignment((short)22);
HSSFCellStyle cs5 = wb.createCellStyle();
cs5.setFont(f2);
cs5.setAlignment((short)111);
HSSFCellStyle cs6 = wb.createCellStyle();
cs6.setFont(f2);
assertEquals(27, wb.getNumCellStyles());
// Use them
HSSFSheet s = wb.createSheet();
HSSFRow r = s.createRow(0);
r.createCell((short)0).setCellStyle(cs1);
r.createCell((short)1).setCellStyle(cs2);
r.createCell((short)2).setCellStyle(cs3);
r.createCell((short)3).setCellStyle(cs4);
r.createCell((short)4).setCellStyle(cs5);
r.createCell((short)5).setCellStyle(cs6);
r.createCell((short)6).setCellStyle(cs1);
r.createCell((short)7).setCellStyle(cs2);
assertEquals(21, r.getCell(0).getCellValueRecord().getXFIndex());
assertEquals(26, r.getCell(5).getCellValueRecord().getXFIndex());
assertEquals(21, r.getCell(6).getCellValueRecord().getXFIndex());
// Optimise
HSSFOptimiser.optimiseCellStyles(wb);
// Check
assertEquals(6, wb.getNumberOfFonts());
assertEquals(25, wb.getNumCellStyles());
// cs1 -> 21
assertEquals(21, r.getCell(0).getCellValueRecord().getXFIndex());
// cs2 -> 22
assertEquals(22, r.getCell(1).getCellValueRecord().getXFIndex());
// cs3 = cs1 -> 21
assertEquals(21, r.getCell(2).getCellValueRecord().getXFIndex());
// cs4 --> 24 -> 23
assertEquals(23, r.getCell(3).getCellValueRecord().getXFIndex());
// cs5 --> 25 -> 24
assertEquals(24, r.getCell(4).getCellValueRecord().getXFIndex());
// cs6 = cs2 -> 22
assertEquals(22, r.getCell(5).getCellValueRecord().getXFIndex());
// cs1 -> 21
assertEquals(21, r.getCell(6).getCellValueRecord().getXFIndex());
// cs2 -> 22
assertEquals(22, r.getCell(7).getCellValueRecord().getXFIndex());
}
} }