Index: src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java =================================================================== --- src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java (revision 1704432) +++ src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java (working copy) @@ -44,9 +44,9 @@ /** zero based, unsigned 16 bit */ private int field_2_last_row; /** zero based, unsigned 8 bit */ - private int field_3_first_column; + private int field_3_first_column; //BitFields: (first row relative, first col relative, first column number) /** zero based, unsigned 8 bit */ - private int field_4_last_column; + private int field_4_last_column; //BitFields: (last row relative, last col relative, last column number) private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000); private final static BitField colRelative = BitFieldFactory.getInstance(0x4000); @@ -96,6 +96,35 @@ setLastColRelative(firstColRelative); } } + + /** + * Sort the first and last row and columns in-place to the preferred (top left:bottom right) order + * Note: Sort only occurs when an instance is constructed or when this method is called. + * + *

For example, $E5:B$10 becomes B5:$E$10

+ */ + public void sortTopLeftToBottomRight() { + if (getFirstRow() > getLastRow()) { + //swap first row and last row numbers and relativity + //Note: cannot just swap the fields because row relativity is stored in fields 3 and 4 + final int firstRow = getFirstRow(); + final boolean firstRowRel = isFirstRowRelative(); + setFirstRow(getLastRow()); + setFirstRowRelative(isLastRowRelative()); + setLastRow(firstRow); + setLastRowRelative(firstRowRel); + } + if (getFirstColumn() > getLastColumn()) { + //swap first column and last column numbers and relativity + //Note: cannot just swap the fields because row relativity is stored in fields 3 and 4 + final int firstCol = getFirstColumn(); + final boolean firstColRel = isFirstColRelative(); + setFirstColumn(getLastColumn()); + setFirstColRelative(isLastColRelative()); + setLastColumn(firstCol); + setLastColRelative(firstColRel); + } + } protected final void readCoordinates(LittleEndianInput in) { field_1_first_row = in.readUShort(); Index: src/testcases/org/apache/poi/ss/formula/ptg/TestAreaPtg.java =================================================================== --- src/testcases/org/apache/poi/ss/formula/ptg/TestAreaPtg.java (revision 1704432) +++ src/testcases/org/apache/poi/ss/formula/ptg/TestAreaPtg.java (working copy) @@ -33,6 +33,7 @@ AreaPtg relative; AreaPtg absolute; + @Override protected void setUp() { short firstRow=5; short lastRow=13; @@ -41,6 +42,17 @@ relative = new AreaPtg(firstRow,lastRow,firstCol,lastCol,true,true,true,true); absolute = new AreaPtg(firstRow,lastRow,firstCol,lastCol,false,false,false,false); } + + public static void testSortTopLeftToBottomRight() { + AreaPtg ptg = new AreaPtg("A$1:$B5"); + assertEquals("A$1:$B5", ptg.toFormulaString()); + ptg.setFirstColumn(3); + assertEquals("Area Ptg should not implicitly re-sort itself (except during construction)", + "D$1:$B5", ptg.toFormulaString()); + ptg.sortTopLeftToBottomRight(); + assertEquals("Area Ptg should restore itself to top-left to lower-right order when explicitly asked", + "$B$1:D5", ptg.toFormulaString()); + } public void testSetColumnsAbsolute() {