Skip to content

Commit

Permalink
Our XSLT-based MS Office 2003 SpreadsheetML format import filter, whe…
Browse files Browse the repository at this point in the history
…n doing

conversion from R1C1 style column references to our A1 style references, had a
bug where it was treating the column value as 0-based, and dividing by 26 to
find the 1st letter and taking the remainder when divided by 26 for the second
letter. Those numbers are then each converted to a letter [0 = nothing,
1 = "A", 2 = "B", ..., 26 = "Z"].

However since R1C1 is 1-based, and not 0-based, this breaks for column numbers
which are multiples of 26, as 26 mod 26 = 0, so the least significant digit is
converted to nothing while the most significant digit gets incremented too
early.

Fix this by converting the column number to 0-based by subtracting 1 before
calculation, then adding 1 to the least significant digit afterwards.

Also the fact we have 2 letters limited us to a maximum of 26^2 = 676 columns,
after which column references would wrap around. Fix this too, by adding a 3rd
letter, which lets us address a maximum of 17576 columns.

Add a sample file to our unit tests.

Found by: alex dot plantema at xs4all dot nl
Patch by: me
  • Loading branch information
Damjan Jovanovic committed Jan 11, 2023
1 parent 9fd60fc commit 577fe17
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 5 deletions.
25 changes: 21 additions & 4 deletions main/filter/source/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -8225,11 +8225,23 @@
<xsl:param name="row-number"/>
<xsl:param name="column-pos-style"/>
<xsl:param name="row-pos-style"/>
<xsl:variable name="zero-based-column-number">
<xsl:value-of select="$column-number - 1"/>
</xsl:variable>
<xsl:variable name="column-number1">
<xsl:value-of select="floor( $column-number div 26 )"/>
<xsl:value-of select="floor( $zero-based-column-number div 676 )"/>
</xsl:variable>
<xsl:variable name="column-remainder1">
<xsl:value-of select="floor( $zero-based-column-number mod 676 )"/>
</xsl:variable>
<xsl:variable name="column-number2">
<xsl:value-of select="$column-number mod 26"/>
<xsl:value-of select="floor( $column-remainder1 div 26 )"/>
</xsl:variable>
<xsl:variable name="column-remainder2">
<xsl:value-of select="floor( $column-remainder1 mod 26 )"/>
</xsl:variable>
<xsl:variable name="column-number3">
<xsl:value-of select="( $column-remainder2 mod 26 ) + 1"/>
</xsl:variable>
<xsl:variable name="column-character1">
<xsl:call-template name="number-to-character">
Expand All @@ -8241,13 +8253,18 @@
<xsl:with-param name="number" select="$column-number2"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="column-character3">
<xsl:call-template name="number-to-character">
<xsl:with-param name="number" select="$column-number3"/>
</xsl:call-template>
</xsl:variable>
<!-- position styles are 'absolute' or 'relative', -->
<xsl:choose>
<xsl:when test="$column-pos-style = 'absolute'">
<xsl:value-of select="concat( '$', $column-character1, $column-character2)"/>
<xsl:value-of select="concat( '$', $column-character1, $column-character2, $column-character3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat( $column-character1, $column-character2)"/>
<xsl:value-of select="concat( $column-character1, $column-character2, $column-character3)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
Expand Down
121 changes: 121 additions & 0 deletions test/testuno/data/uno/sc/fvt/Bug81233ColumnZReference.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel">
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<Colors>
<Color>
<Index>3</Index>
<RGB>#c0c0c0</RGB>
</Color>
</Colors>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>9000</WindowHeight>
<WindowWidth>13860</WindowWidth>
<WindowTopX>240</WindowTopX>
<WindowTopY>75</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Default"/>
<Style ss:ID="Result" ss:Name="Result">
<Font ss:Bold="1" ss:Italic="1" ss:Underline="Single"/>
</Style>
<Style ss:ID="Result2" ss:Name="Result2">
<Font ss:Bold="1" ss:Italic="1" ss:Underline="Single"/>
</Style>
<Style ss:ID="Heading" ss:Name="Heading">
<Alignment ss:Horizontal="Center"/>
<Font ss:Bold="1" ss:Italic="1" ss:Size="16"/>
</Style>
<Style ss:ID="Heading1" ss:Name="Heading1">
<Alignment ss:Horizontal="Center" ss:Rotate="90"/>
<Font ss:Bold="1" ss:Italic="1" ss:Size="16"/>
</Style>
<Style ss:ID="co1"/>
<Style ss:ID="co2"/>
<Style ss:ID="ta1"/>
<Style ss:ID="ce1"/>
<Style ss:ID="T1">
<Font ss:VerticalAlign="Subscript"/>
</Style>
</Styles>
<ss:Worksheet ss:Name="Sheet1">
<Table ss:StyleID="ta1">
<Column ss:Width="218.4408"/>
<Column ss:Span="1022" ss:Width="64.26"/>
<Row ss:Height="12.1032">
<Cell ss:StyleID="ce1">
<Data ss:Type="String">TestID</Data>
</Cell>
<Cell ss:StyleID="ce1">
<Data ss:Type="String">TestOK</Data>
</Cell>
<Cell ss:Index="10">
<Data ss:Type="String">wrapped!</Data>
</Cell>
<Cell ss:Index="25">
<Data ss:Type="String">Y test</Data>
</Cell>
<Cell>
<Data ss:Type="String">Z test</Data>
</Cell>
<Cell>
<Data ss:Type="String">AA test</Data>
</Cell>
<Cell ss:Index="1024">
<Data ss:Type="String">AMJ test</Data>
</Cell>
</Row>
<Row ss:Height="12.1032">
<Cell>
<Data ss:Type="String">Y2=Y1?</Data>
</Cell>
<Cell ss:Formula="=R2C25=R1C25">
<Data ss:Type="Boolean">1</Data>
</Cell>
<Cell ss:Index="25" ss:Formula="=R[-1]C">
<Data ss:Type="String">Y test</Data>
</Cell>
<Cell ss:Formula="=R[-1]C">
<Data ss:Type="String">Z test</Data>
</Cell>
<Cell ss:Formula="=R[-1]C">
<Data ss:Type="String">AA test</Data>
</Cell>
<Cell ss:Index="1024" ss:Formula="=R[-1]C">
<Data ss:Type="String">AMJ test</Data>
</Cell>
</Row>
<Row ss:Height="13.4064">
<Cell>
<ss:Data xmlns="http://www.w3.org/TR/REC-html40" ss:Type="String">Z2=Z1? (26th column.)</ss:Data>
</Cell>
<Cell ss:Formula="=R2C26=R1C26">
<Data ss:Type="Boolean">1</Data>
</Cell>
<Cell ss:Index="1024"/>
</Row>
<Row ss:Height="12.1032">
<Cell>
<Data ss:Type="String">AA2=AA1?</Data>
</Cell>
<Cell ss:Formula="=R2C27=R1C27">
<Data ss:Type="Boolean">1</Data>
</Cell>
<Cell ss:Index="1024"/>
</Row>
<Row ss:Height="13.4064">
<Cell>
<ss:Data xmlns="http://www.w3.org/TR/REC-html40" ss:Type="String">AMJ2=AMJ1? (1024th column.)</ss:Data>
</Cell>
<Cell ss:Formula="=R2C1024=R1C1024">
<Data ss:Type="Boolean">1</Data>
</Cell>
<Cell ss:Index="1024"/>
</Row>
</Table>
<x:WorksheetOptions/>
</ss:Worksheet>
</Workbook>
3 changes: 2 additions & 1 deletion test/testuno/source/fvt/uno/sc/formula/TestFormulaDocs.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ public static Collection<Object[]> data() {
{"uno/sc/fvt/StarBasicTab.ods", "Basic Tab Function Test"},
{"uno/sc/fvt/DGET on formulas.ods", "DGET on formulas Test"},
{"uno/sc/fvt/Basic Line as variable and Line Input.ods", "Basic Line as variable and Line Input Test"},
{"uno/sc/fvt/comment-in-single-line-if-then-else.ods", "Basic comment after single line if statement Test"}
{"uno/sc/fvt/comment-in-single-line-if-then-else.ods", "Basic comment after single line if statement Test"},
{"uno/sc/fvt/Bug81233ColumnZReference.xml", "Bug 81233 column Z reference wrongly converts to column A"}
});
}

Expand Down

0 comments on commit 577fe17

Please sign in to comment.