From 511f83925b551fb749d6ac5c32ab67ff33f8ca03 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Sat, 12 Jul 2008 17:38:10 +0000 Subject: [PATCH] Allow the cloning of one HSSFCellStyle onto another, including cloning styles from one HSSFWorkbook onto another git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@676205 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/changes.xml | 1 + src/documentation/content/xdocs/status.xml | 1 + .../org/apache/poi/hssf/model/Workbook.java | 18 +++++ .../apache/poi/hssf/usermodel/HSSFCell.java | 4 + .../poi/hssf/usermodel/HSSFCellStyle.java | 58 +++++++++++++++ .../apache/poi/hssf/model/AllModelTests.java | 1 + .../apache/poi/hssf/model/TestWorkbook.java | 61 +++++++++++++++ .../poi/hssf/usermodel/TestCellStyle.java | 74 +++++++++++++++++++ .../poi/hssf/usermodel/TestHSSFCell.java | 37 ++++++++++ 9 files changed, 255 insertions(+) create mode 100644 src/testcases/org/apache/poi/hssf/model/TestWorkbook.java diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml index a9cee30b2..e1a1872be 100644 --- a/src/documentation/content/xdocs/changes.xml +++ b/src/documentation/content/xdocs/changes.xml @@ -37,6 +37,7 @@ + Allow the cloning of one HSSFCellStyle onto another, including cloning styles from one HSSFWorkbook onto another 45289 - finished support for special comparison operators in COUNTIF 45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes Fix cell.getRichStringCellValue() for formula cells with string results diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 6d5d51ea8..b6cb13dad 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + Allow the cloning of one HSSFCellStyle onto another, including cloning styles from one HSSFWorkbook onto another 45289 - finished support for special comparison operators in COUNTIF 45126 - Avoid generating multiple NamedRanges with the same name, which Excel dislikes Fix cell.getRichStringCellValue() for formula cells with string results diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java index 329e217a8..d56051445 100644 --- a/src/java/org/apache/poi/hssf/model/Workbook.java +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -408,6 +408,24 @@ public class Workbook implements Model return retval; } + + /** + * Retrieves the index of the given font + */ + public int getFontIndex(FontRecord font) { + for(int i=0; i<=numfonts; i++) { + FontRecord thisFont = + ( FontRecord ) records.get((records.getFontpos() - (numfonts - 1)) + i); + if(thisFont == font) { + // There is no 4! + if(i > 3) { + return (i+1); + } + return i; + } + } + throw new IllegalArgumentException("Could not find that font!"); + } /** * creates a new font record and adds it to the "font table". This causes the diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index dd1770f56..636c5406f 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -915,6 +915,10 @@ public class HSSFCell public void setCellStyle(HSSFCellStyle style) { + // Verify it really does belong to our workbook + style.verifyBelongsToWorkbook(book); + + // Change our cell record to use this style record.setXFIndex(style.getIndex()); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java index f0fb6ebfb..c613225ba 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.record.ExtendedFormatRecord; +import org.apache.poi.hssf.record.FontRecord; import org.apache.poi.hssf.util.HSSFColor; /** @@ -928,6 +929,63 @@ public class HSSFCellStyle return format.getFillForeground(); } + /** + * Verifies that this style belongs to the supplied Workbook. + * Will throw an exception if it belongs to a different one. + * This is normally called when trying to assign a style to a + * cell, to ensure the cell and the style are from the same + * workbook (if they're not, it won't work) + * @throws IllegalArgumentException if there's a workbook mis-match + */ + public void verifyBelongsToWorkbook(HSSFWorkbook wb) { + if(wb.getWorkbook() != workbook) { + throw new IllegalArgumentException("This Style does not belong to the supplied Workbook. Are you trying to assign a style from one workbook to the cell of a differnt workbook?"); + } + } + + /** + * Clones all the style information from another + * HSSFCellStyle, onto this one. This + * HSSFCellStyle will then have all the same + * properties as the source, but the two may + * be edited independently. + * Any stylings on this HSSFCellStyle will be lost! + * + * The source HSSFCellStyle could be from another + * HSSFWorkbook if you like. This allows you to + * copy styles from one HSSFWorkbook to another. + */ + public void cloneStyleFrom(HSSFCellStyle source) { + // First we need to clone the extended format + // record + format.cloneStyleFrom(source.format); + + // Handle matching things if we cross workbooks + if(workbook != source.workbook) { + // Then we need to clone the format string, + // and update the format record for this + short fmt = workbook.createFormat( + source.getDataFormatString() + ); + setDataFormat(fmt); + + // Finally we need to clone the font, + // and update the format record for this + FontRecord fr = workbook.createNewFont(); + fr.cloneStyleFrom( + source.workbook.getFontRecordAt( + source.getFontIndex() + ) + ); + + HSSFFont font = new HSSFFont( + (short)workbook.getFontIndex(fr), fr + ); + setFont(font); + } + } + + public int hashCode() { final int prime = 31; int result = 1; diff --git a/src/testcases/org/apache/poi/hssf/model/AllModelTests.java b/src/testcases/org/apache/poi/hssf/model/AllModelTests.java index 045e371a2..f157d3a0f 100755 --- a/src/testcases/org/apache/poi/hssf/model/AllModelTests.java +++ b/src/testcases/org/apache/poi/hssf/model/AllModelTests.java @@ -38,6 +38,7 @@ public final class AllModelTests { result.addTestSuite(TestRVA.class); result.addTestSuite(TestSheet.class); result.addTestSuite(TestSheetAdditional.class); + result.addTestSuite(TestWorkbook.class); return result; } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestWorkbook.java b/src/testcases/org/apache/poi/hssf/model/TestWorkbook.java new file mode 100644 index 000000000..99663d203 --- /dev/null +++ b/src/testcases/org/apache/poi/hssf/model/TestWorkbook.java @@ -0,0 +1,61 @@ +/* ==================================================================== + 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.model; + +import org.apache.poi.hssf.record.FontRecord; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import junit.framework.TestCase; + +/** + * Unit test for the Workbook class. + * + * @author Glen Stampoultzis (glens at apache.org) + */ +public final class TestWorkbook extends TestCase { + public void testFontStuff() throws Exception { + Workbook wb = (new HW()).getWorkbook(); + + assertEquals(4, wb.getNumberOfFontRecords()); + + FontRecord f1 = wb.getFontRecordAt(0); + FontRecord f4 = wb.getFontRecordAt(3); + + assertEquals(0, wb.getFontIndex(f1)); + assertEquals(3, wb.getFontIndex(f4)); + + assertEquals(f1, wb.getFontRecordAt(0)); + assertEquals(f4, wb.getFontRecordAt(3)); + + // There is no 4! new ones go in at 5 + + FontRecord n = wb.createNewFont(); + assertEquals(5, wb.getNumberOfFontRecords()); + assertEquals(5, wb.getFontIndex(n)); + assertEquals(n, wb.getFontRecordAt(5)); + } + + private class HW extends HSSFWorkbook { + private HW() { + super(); + } + protected Workbook getWorkbook() { + return super.getWorkbook(); + } + } +} \ No newline at end of file diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java index 0daa80326..39b949f7d 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java @@ -229,6 +229,80 @@ public class TestCellStyle // assert((s.getLastRowNum() == 99)); } + + /** + * Cloning one HSSFCellStyle onto Another, same + * HSSFWorkbook + */ + public void testCloneStyleSameWB() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFFont fnt = wb.createFont(); + fnt.setFontName("TestingFont"); + assertEquals(5, wb.getNumberOfFonts()); + + HSSFCellStyle orig = wb.createCellStyle(); + orig.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + orig.setFont(fnt); + orig.setDataFormat((short)18); + + assertTrue(HSSFCellStyle.ALIGN_RIGHT == orig.getAlignment()); + assertTrue(fnt == orig.getFont(wb)); + assertTrue(18 == orig.getDataFormat()); + + HSSFCellStyle clone = wb.createCellStyle(); + assertFalse(HSSFCellStyle.ALIGN_RIGHT == clone.getAlignment()); + assertFalse(fnt == clone.getFont(wb)); + assertFalse(18 == clone.getDataFormat()); + + clone.cloneStyleFrom(orig); + assertTrue(HSSFCellStyle.ALIGN_RIGHT == clone.getAlignment()); + assertTrue(fnt == clone.getFont(wb)); + assertTrue(18 == clone.getDataFormat()); + assertEquals(5, wb.getNumberOfFonts()); + } + + /** + * Cloning one HSSFCellStyle onto Another, across + * two different HSSFWorkbooks + */ + public void testCloneStyleDiffWB() throws Exception { + HSSFWorkbook wbOrig = new HSSFWorkbook(); + + HSSFFont fnt = wbOrig.createFont(); + fnt.setFontName("TestingFont"); + assertEquals(5, wbOrig.getNumberOfFonts()); + + HSSFDataFormat fmt = wbOrig.createDataFormat(); + fmt.getFormat("MadeUpOne"); + fmt.getFormat("MadeUpTwo"); + + HSSFCellStyle orig = wbOrig.createCellStyle(); + orig.setAlignment(HSSFCellStyle.ALIGN_RIGHT); + orig.setFont(fnt); + orig.setDataFormat(fmt.getFormat("Test##")); + + assertTrue(HSSFCellStyle.ALIGN_RIGHT == orig.getAlignment()); + assertTrue(fnt == orig.getFont(wbOrig)); + assertTrue(fmt.getFormat("Test##") == orig.getDataFormat()); + + // Now a style on another workbook + HSSFWorkbook wbClone = new HSSFWorkbook(); + assertEquals(4, wbClone.getNumberOfFonts()); + HSSFDataFormat fmtClone = wbClone.createDataFormat(); + + HSSFCellStyle clone = wbClone.createCellStyle(); + assertEquals(4, wbClone.getNumberOfFonts()); + + assertFalse(HSSFCellStyle.ALIGN_RIGHT == clone.getAlignment()); + assertFalse("TestingFont" == clone.getFont(wbClone).getFontName()); + + clone.cloneStyleFrom(orig); + assertTrue(HSSFCellStyle.ALIGN_RIGHT == clone.getAlignment()); + assertTrue("TestingFont" == clone.getFont(wbClone).getFontName()); + assertTrue(fmtClone.getFormat("Test##") == clone.getDataFormat()); + assertFalse(fmtClone.getFormat("Test##") == fmt.getFormat("Test##")); + assertEquals(5, wbClone.getNumberOfFonts()); + } public static void main(String [] ignored_args) { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java index 7f4375847..c3d73cf4a 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java @@ -381,6 +381,43 @@ public final class TestHSSFCell extends TestCase { throw new AssertionFailedError("Identified bug 44606"); } } + + /** + * Test to ensure we can only assign cell styles that belong + * to our workbook, and not those from other workbooks. + */ + public void testCellStyleWorkbookMatch() throws Exception { + HSSFWorkbook wbA = new HSSFWorkbook(); + HSSFWorkbook wbB = new HSSFWorkbook(); + + HSSFCellStyle styA = wbA.createCellStyle(); + HSSFCellStyle styB = wbB.createCellStyle(); + + styA.verifyBelongsToWorkbook(wbA); + styB.verifyBelongsToWorkbook(wbB); + try { + styA.verifyBelongsToWorkbook(wbB); + fail(); + } catch(IllegalArgumentException e) {} + try { + styB.verifyBelongsToWorkbook(wbA); + fail(); + } catch(IllegalArgumentException e) {} + + HSSFCell cellA = wbA.createSheet().createRow(0).createCell((short)0); + HSSFCell cellB = wbB.createSheet().createRow(0).createCell((short)0); + + cellA.setCellStyle(styA); + cellB.setCellStyle(styB); + try { + cellA.setCellStyle(styB); + fail(); + } catch(IllegalArgumentException e) {} + try { + cellB.setCellStyle(styA); + fail(); + } catch(IllegalArgumentException e) {} + } public static void main(String [] args) { junit.textui.TestRunner.run(TestHSSFCell.class);