diff options
author | Eike Rathke <erack@redhat.com> | 2016-05-19 23:49:08 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-05-20 00:01:53 +0200 |
commit | 6821ad076c276b997c44520fd700817566a718c5 (patch) | |
tree | 9d17385f4646c20d1168b99be78d7b8f0a7d48f3 | |
parent | 195ad648cf284384e82fa727442fa98b6e86e792 (diff) |
Resolves: tdf#83746 wrapAddress() didn't do what it was supposed to do
i.e. subtracted nMaxRow from MAXROW that is set for entire column
references, resulting in row 983040=1048576-65536, instead of doing a
modulo operation.
Also, entire column/row references are now untouched so they still
reference the entire column/row.
Note that in Excel BIFF8 an absolute addressing of row 1 and 65536 means
entire column, so B$1:B$65536 saved and reloaded results in B:B, which
may be unexpected.
Change-Id: Iae65d47ba937b9ade95e4ea1be98012b80e1c9db
-rw-r--r-- | sc/source/core/tool/token.cxx | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index a9894c0ed1f5..e20104b0ad95 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -4969,9 +4969,40 @@ namespace { void wrapAddress( ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow ) { if (rPos.Col() > nMaxCol) - rPos.SetCol(rPos.Col() - nMaxCol - 1); + rPos.SetCol((rPos.Col() % (nMaxCol+1))); if (rPos.Row() > nMaxRow) - rPos.SetRow(rPos.Row() - nMaxRow - 1); + rPos.SetRow((rPos.Row() % (nMaxRow+1))); +} + +template<typename T> void wrapRange( T& n1, T& n2, T nMax ) +{ + if (n2 > nMax) + { + if (n1 == 0) + n2 = nMax; // Truncate to full range instead of wrapping to a weird range. + else + n2 = n2 % (nMax+1); + } + if (n1 > nMax) + n1 = n1 % (nMax+1); +} + +void wrapColRange( ScRange& rRange, SCCOL nMaxCol ) +{ + SCCOL nCol1 = rRange.aStart.Col(); + SCCOL nCol2 = rRange.aEnd.Col(); + wrapRange( nCol1, nCol2, nMaxCol); + rRange.aStart.SetCol( nCol1); + rRange.aEnd.SetCol( nCol2); +} + +void wrapRowRange( ScRange& rRange, SCROW nMaxRow ) +{ + SCROW nRow1 = rRange.aStart.Row(); + SCROW nRow2 = rRange.aEnd.Row(); + wrapRange( nRow1, nRow2, nMaxRow); + rRange.aStart.SetRow( nRow1); + rRange.aEnd.SetRow( nRow2); } } @@ -4998,8 +5029,17 @@ void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nM formula::FormulaToken* pToken = *p; ScComplexRefData& rRef = *pToken->GetDoubleRef(); ScRange aAbs = rRef.toAbs(rPos); - wrapAddress(aAbs.aStart, nMaxCol, nMaxRow); - wrapAddress(aAbs.aEnd, nMaxCol, nMaxRow); + // Entire columns/rows are sticky. + if (!rRef.IsEntireCol() && !rRef.IsEntireRow()) + { + wrapColRange( aAbs, nMaxCol); + wrapRowRange( aAbs, nMaxRow); + } + else if (rRef.IsEntireCol() && !rRef.IsEntireRow()) + wrapColRange( aAbs, nMaxCol); + else if (!rRef.IsEntireCol() && rRef.IsEntireRow()) + wrapRowRange( aAbs, nMaxRow); + // else nothing if both, column and row, are entire. aAbs.PutInOrder(); rRef.SetRange(aAbs, rPos); } @@ -5032,8 +5072,9 @@ bool ScTokenArray::NeedsWrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCR formula::FormulaToken* pToken = *p; ScComplexRefData& rRef = *pToken->GetDoubleRef(); ScRange aAbs = rRef.toAbs(rPos); - if (aAbs.aStart.Col() > nMaxCol || aAbs.aStart.Row() > nMaxRow || - aAbs.aEnd.Col() > nMaxCol || aAbs.aEnd.Row() > nMaxRow) + // Entire columns/rows are sticky. + if ( (!rRef.IsEntireCol() && (aAbs.aStart.Row() > nMaxRow || aAbs.aEnd.Row() > nMaxRow)) || + (!rRef.IsEntireRow() && (aAbs.aStart.Col() > nMaxCol || aAbs.aEnd.Col() > nMaxCol))) return true; } break; |