diff options
-rw-r--r-- | sc/qa/unit/data/xls/tdf128976.xls | bin | 0 -> 25600 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 23 | ||||
-rw-r--r-- | sc/source/filter/excel/excdoc.cxx | 6 | ||||
-rw-r--r-- | sc/source/filter/excel/xetable.cxx | 29 | ||||
-rw-r--r-- | sc/source/filter/inc/xetable.hxx | 6 |
5 files changed, 52 insertions, 12 deletions
diff --git a/sc/qa/unit/data/xls/tdf128976.xls b/sc/qa/unit/data/xls/tdf128976.xls Binary files differnew file mode 100644 index 000000000000..7cd7b748aec3 --- /dev/null +++ b/sc/qa/unit/data/xls/tdf128976.xls diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index e9ad4b5eade4..be4e1393aec4 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -229,6 +229,7 @@ public: void testXltxExport(); void testRotatedImageODS(); + void testTdf128976(); CPPUNIT_TEST_SUITE(ScExportTest); CPPUNIT_TEST(test); @@ -359,6 +360,7 @@ public: CPPUNIT_TEST(testXltxExport); CPPUNIT_TEST(testRotatedImageODS); + CPPUNIT_TEST(testTdf128976); CPPUNIT_TEST_SUITE_END(); @@ -4556,6 +4558,27 @@ void ScExportTest::testRotatedImageODS() xDocSh->DoClose(); } +void ScExportTest::testTdf128976() +{ + ScDocShellRef xShell = loadDoc("tdf128976.", FORMAT_XLS); + CPPUNIT_ASSERT(xShell.is()); + + ScDocShellRef xDocSh = saveAndReload(xShell.get(), FORMAT_XLS); + xShell->DoClose(); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + + // Trying to save very small fractional default column width to XLS (where only integer values + // between 0 and 255 are allowed as default) resulted in negative (-1) value after correction, + // and was written as 65535 (invalid default width). As the result, all columns had large width + // when reopened: 28415 (and Excel warned about invalid format). + const sal_uInt16 nColumn0Width = rDoc.GetColWidth(SCCOL(0), SCTAB(0), false); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(45), nColumn0Width); + + xDocSh->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index c0950245464d..4d9975d034cc 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -662,7 +662,7 @@ void ExcTable::Write( XclExpStream& rStrm ) { SetCurrScTab( mnScTab ); if( mxCellTable.get() ) - mxCellTable->Finalize(); + mxCellTable->Finalize(true); aRecList.Save( rStrm ); } @@ -673,7 +673,7 @@ void ExcTable::WriteXml( XclExpXmlStream& rStrm ) // header export. SetCurrScTab(mnScTab); if (mxCellTable) - mxCellTable->Finalize(); + mxCellTable->Finalize(false); aRecList.SaveXml(rStrm); return; @@ -692,7 +692,7 @@ void ExcTable::WriteXml( XclExpXmlStream& rStrm ) SetCurrScTab( mnScTab ); if (mxCellTable) - mxCellTable->Finalize(); + mxCellTable->Finalize(false); aRecList.SaveXml( rStrm ); XclExpXmlPivotTables* pPT = GetXmlPivotTableManager().GetTablesBySheet(mnScTab); diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index 132f48c2f44b..ff1b455899da 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1571,9 +1571,26 @@ bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const return std::abs(defaultColumnWidth - nXclColWidth) < 256.0 * 1.0 / 16.0; } -void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth ) +void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth, bool bXLS ) { - SetValue(nXclColWidth / 256.0); + double fCCh = nXclColWidth / 256.0; + if (bXLS) + { + const double fCorrection = lclGetCChCorrection(GetRoot()); + const double fCorrectedCCh = fCCh - fCorrection; + // Now get the value which would be stored in XLS DefColWidth struct + double fCChRound = std::round(fCorrectedCCh); + // If default width was set to a value that is not representable as integral CCh between 0 + // and 255, then just ignore that value, and use an arbitrary default. That way, the stored + // default might not represent the most used column width (or any used column width), but + // that's OK, and it just means that those columns will explicitly store their width in + // 1/256ths of char, and have fUserSet in their ColInfo records. + if (fCChRound < 0.0 || fCChRound > 255.0 || std::abs(fCChRound - fCorrectedCCh) > 1.0 / 512) + fCChRound = 8.0; + fCCh = fCChRound + fCorrection; + } + + SetValue(fCCh); } void XclExpDefcolwidth::Save(XclExpStream& rStrm) @@ -1714,7 +1731,7 @@ void XclExpColinfoBuffer::Initialize( SCROW nLastScRow ) } } -void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes ) +void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ) { rXFIndexes.clear(); rXFIndexes.reserve( maColInfos.GetSize() ); @@ -1760,7 +1777,7 @@ void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes ) nMaxUsedWidth = nWidth; } } - maDefcolwidth.SetDefWidth( nMaxUsedWidth ); + maDefcolwidth.SetDefWidth( nMaxUsedWidth, bXLS ); // remove all default COLINFO records nPos = 0; @@ -2661,7 +2678,7 @@ XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) : maRowBfr.CreateRows( ::std::max( nFirstUnflaggedScRow, nFirstUngroupedScRow ) ); } -void XclExpCellTable::Finalize() +void XclExpCellTable::Finalize(bool bXLS) { // Finalize multiple operations. maTableopBfr.Finalize(); @@ -2669,7 +2686,7 @@ void XclExpCellTable::Finalize() /* Finalize column buffer. This calculates column default XF indexes from the XF identifiers and fills a vector with these XF indexes. */ ScfUInt16Vec aColXFIndexes; - maColInfoBfr.Finalize( aColXFIndexes ); + maColInfoBfr.Finalize( aColXFIndexes, bXLS ); /* Finalize row buffer. This calculates all cell XF indexes from the XF identifiers. Then the XF index vector aColXFIndexes (filled above) is diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx index bf3d4cccab5a..c4648533eb7e 100644 --- a/sc/source/filter/inc/xetable.hxx +++ b/sc/source/filter/inc/xetable.hxx @@ -686,7 +686,7 @@ public: bool IsDefWidth( sal_uInt16 nXclColWidth ) const; /** Sets the passed column width (in 1/256 character width) as default width. */ - void SetDefWidth( sal_uInt16 nXclColWidth ); + void SetDefWidth( sal_uInt16 nXclColWidth, bool bXLS ); virtual void Save(XclExpStream& rStrm) override; }; @@ -757,7 +757,7 @@ public: void Initialize( SCROW nLastScRow ); /** Converts the XF identifiers into the Excel XF indexes and merges equal columns. @param rXFIndexes Returns the final XF indexes of all columns. */ - void Finalize( ScfUInt16Vec& rXFIndexes ); + void Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ); /** Writes all COLINFO records of this buffer. */ virtual void Save( XclExpStream& rStrm ) override; @@ -979,7 +979,7 @@ public: explicit XclExpCellTable( const XclExpRoot& rRoot ); /** Converts all XF identifiers into the Excel XF indexes and calculates default formats. */ - void Finalize(); + void Finalize(bool bXLS); /** Returns the reference to an internal record specified by the passed record id. @param nRecId The record identifier that specifies which record is |