summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/qa/unit/data/xls/tdf128976.xlsbin0 -> 25600 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx23
-rw-r--r--sc/source/filter/excel/excdoc.cxx6
-rw-r--r--sc/source/filter/excel/xetable.cxx29
-rw-r--r--sc/source/filter/inc/xetable.hxx6
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
new file mode 100644
index 000000000000..7cd7b748aec3
--- /dev/null
+++ b/sc/qa/unit/data/xls/tdf128976.xls
Binary files differ
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