diff --git a/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java index 261cfd878..6f64d46ec 100644 --- a/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExtendedFormatRecord.java @@ -410,7 +410,7 @@ public final class ExtendedFormatRecord } /** - * set the degree of rotation. (I've not actually seen this used anywhere) + * set the degree of rotation. * * * @param rotation the degree of rotation @@ -1145,7 +1145,7 @@ public final class ExtendedFormatRecord } /** - * get the degree of rotation. (I've not actually seen this used anywhere) + * get the degree of rotation. * * * @return rotation - the degree of rotation diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java index b6d366c50..25e3b371c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java @@ -324,6 +324,12 @@ public final class HSSFCellStyle implements CellStyle { /** * set the degree of rotation for the text in the cell + * + * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF + * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges + * accordingly, however the corresponding getter is returning values in the range mandated by the current type + * of Excel file-format that this CellStyle is applied to. + * * @param rotation degrees (between -90 and 90 degrees, of 0xff for vertical) */ @Override @@ -337,7 +343,11 @@ public final class HSSFCellStyle implements CellStyle { //The 4th quadrant (-1 to -90) is stored as (91 to 180) rotation = (short)(90 - rotation); } - else if ((rotation < -90) ||(rotation > 90)) { + else if (rotation > 90 && rotation <= 180) { + // stay compatible with the range used by XSSF, map from ]90..180] to ]0..-90] + // we actually don't need to do anything here as the internal value is stored in [0-180] anyway! + } + else if ((rotation < -90) || (rotation > 90)) { //Do not allow an incorrect rotation to be set throw new IllegalArgumentException("The rotation must be between -90 and 90 degrees, or 0xff"); } diff --git a/src/java/org/apache/poi/ss/usermodel/CellStyle.java b/src/java/org/apache/poi/ss/usermodel/CellStyle.java index be5a43e93..e91d19d0f 100644 --- a/src/java/org/apache/poi/ss/usermodel/CellStyle.java +++ b/src/java/org/apache/poi/ss/usermodel/CellStyle.java @@ -363,17 +363,26 @@ public interface CellStyle { short getVerticalAlignment(); /** - * set the degree of rotation for the text in the cell - * @param rotation degrees (between -90 and 90 degrees) + * set the degree of rotation for the text in the cell. + * + * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF + * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges + * accordingly, however the corresponding getter is returning values in the range mandated by the current type + * of Excel file-format that this CellStyle is applied to. + * + * @param rotation degrees (see note above) */ - void setRotation(short rotation); /** - * get the degree of rotation for the text in the cell - * @return rotation degrees (between -90 and 90 degrees) + * get the degree of rotation for the text in the cell. + * + * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF + * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges + * value-range as used by the type of Excel file-format that this CellStyle is applied to. + * + * @return rotation degrees (see note above) */ - short getRotation(); /** diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java index a2c265f1b..ea355756e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java @@ -1364,6 +1364,11 @@ public void setFillPattern(short fp) { * [degrees below horizon] = 90 - textRotation. *

* + * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF + * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges + * accordingly, however the corresponding getter is returning values in the range mandated by the current type + * of Excel file-format that this CellStyle is applied to. + * * @param rotation - the rotation degrees (between 0 and 180 degrees) */ @Override diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java index 233616c83..06e5d0bf6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellAlignment.java @@ -133,9 +133,17 @@ public class XSSFCellAlignment { * [degrees below horizon] = 90 - textRotation. *

* + * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF + * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges + * accordingly, however the corresponding getter is returning values in the range mandated by the current type + * of Excel file-format that this CellStyle is applied to. + * * @param rotation - the rotation degrees (between 0 and 180 degrees) */ public void setTextRotation(long rotation) { + if(rotation < 0 && rotation >= -90) { + rotation = 90 + ((-1)*rotation); + } cellAlignement.setTextRotation(rotation); } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index 56eff4457..92235c439 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -2906,4 +2906,52 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { wb.close(); } + + private void createXls() throws IOException + { + Workbook workbook = new HSSFWorkbook(); + FileOutputStream fileOut = new FileOutputStream("/tmp/rotated.xls"); + Sheet sheet1 = workbook.createSheet(); + Row row1 = sheet1.createRow((short) 0); + + Cell cell1 = row1.createCell(0); + + cell1.setCellValue("Successful rotated text."); + + CellStyle style = workbook.createCellStyle(); + style.setRotation((short) -90); + + cell1.setCellStyle(style); + + workbook.write(fileOut); + fileOut.close(); + workbook.close(); + } + + private void createXlsx() throws IOException { + Workbook workbook = new XSSFWorkbook(); + FileOutputStream fileOut = new FileOutputStream("/tmp/rotated.xlsx"); + Sheet sheet1 = workbook.createSheet(); + Row row1 = sheet1.createRow((short) 0); + + Cell cell1 = row1.createCell(0); + + cell1.setCellValue("Unsuccessful rotated text."); + + CellStyle style = workbook.createCellStyle(); + style.setRotation((short) -90); + + cell1.setCellStyle(style); + + workbook.write(fileOut); + fileOut.close(); + workbook.close(); + } + + @Ignore("Creates files for checking results manually, actual values are tested in Test*CellStyle") + @Test + public void test58043() throws Exception { + createXls(); + createXlsx(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java index 1b33f28a4..21f14bb5d 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java @@ -1059,4 +1059,31 @@ public class TestXSSFCellStyle { target.close(); reference.close(); } + + @Test + public void test58043() { + assertEquals(0, cellStyle.getRotation()); + + cellStyle.setRotation((short)89); + assertEquals(89, cellStyle.getRotation()); + + cellStyle.setRotation((short)90); + assertEquals(90, cellStyle.getRotation()); + + cellStyle.setRotation((short)179); + assertEquals(179, cellStyle.getRotation()); + + cellStyle.setRotation((short)180); + assertEquals(180, cellStyle.getRotation()); + + // negative values are mapped to the correct values for compatibility between HSSF and XSSF + cellStyle.setRotation((short)-1); + assertEquals(91, cellStyle.getRotation()); + + cellStyle.setRotation((short)-89); + assertEquals(179, cellStyle.getRotation()); + + cellStyle.setRotation((short)-90); + assertEquals(180, cellStyle.getRotation()); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/TestExtendedFormatRecord.java b/src/testcases/org/apache/poi/hssf/record/TestExtendedFormatRecord.java index 6aaa509a5..5ed16ad0f 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestExtendedFormatRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestExtendedFormatRecord.java @@ -129,4 +129,28 @@ public final class TestExtendedFormatRecord extends TestCase { for (int i = 0; i < data.length; i++) assertEquals("At offset " + i, data[i], recordBytes[i + 4]); } + + public void testRotation() { + ExtendedFormatRecord record = createEFR(); + assertEquals(0, record.getRotation()); + + record.setRotation((short)1); + assertEquals(1, record.getRotation()); + + record.setRotation((short)89); + assertEquals(89, record.getRotation()); + + record.setRotation((short)90); + assertEquals(90, record.getRotation()); + + // internally values below zero are stored differently + record.setRotation((short)-1); + assertEquals(255, record.getRotation()); + + record.setRotation((short)-89); + assertEquals(-77, 90-record.getRotation()); + + record.setRotation((short)-90); + assertEquals(-76, 90-record.getRotation()); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java index 002803486..8d7fd012a 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java @@ -23,8 +23,6 @@ import java.io.IOException; import java.util.Calendar; import java.util.Date; -import junit.framework.TestCase; - import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -34,6 +32,9 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.TempFile; +import org.junit.Test; + +import junit.framework.TestCase; /** * Class to test cell styling functionality @@ -507,4 +508,40 @@ public final class TestCellStyle extends TestCase { // out.close(); // } } + + + @Test + public void test58043() throws IOException { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFCellStyle cellStyle = wb.createCellStyle(); + + assertEquals(0, cellStyle.getRotation()); + + cellStyle.setRotation((short)89); + assertEquals(89, cellStyle.getRotation()); + + cellStyle.setRotation((short)90); + assertEquals(90, cellStyle.getRotation()); + + cellStyle.setRotation((short)-1); + assertEquals(-1, cellStyle.getRotation()); + + cellStyle.setRotation((short)-89); + assertEquals(-89, cellStyle.getRotation()); + + cellStyle.setRotation((short)-90); + assertEquals(-90, cellStyle.getRotation()); + + cellStyle.setRotation((short)-89); + assertEquals(-89, cellStyle.getRotation()); + + // values above 90 are mapped to the correct values for compatibility between HSSF and XSSF + cellStyle.setRotation((short)179); + assertEquals(-89, cellStyle.getRotation()); + + cellStyle.setRotation((short)180); + assertEquals(-90, cellStyle.getRotation()); + + wb.close(); + } }