summaryrefslogtreecommitdiff
path: root/sc/source/filter/excel
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2019-11-24 19:16:36 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2019-11-24 19:28:38 +0100
commit3e1f0c060f02db4515b2dc705bda17ee068d51b4 (patch)
tree0493bd0d5b8a32a2f43a2b7912759656328f2dd9 /sc/source/filter/excel
parentb004a1bd7bf3885613d52aba70dea79766eae639 (diff)
tdf#128976: properly calculate default value when writing XLS
XLS stores default column width as 16-bit unsigned integer in the range from 0 to 255 inclusive ([MS-XLS] 2.4.89 DefColWidth), unlike in OOXML where any floating-point value is valid. Additionally, some correction is used, introduced in commit 555d702903fb0857122024e1ab78a72d122d3f16 (basis of empirical formula in XclTools::GetXclDefColWidthCorrection is unclear). So in XLS, when the default is calculated, we need to take into account if the resulting stored value will actually represent our calculated value. If not, then just ignore the calculated value, and use arbitrary 8 as the default. With that, following IsDefWidth will correctly check if passed width is represented by the stored default or not. All widths that can't be represented as integral count chars in DefColWidth will have fUserSet set in corresponding ColInfo records, thus correctly keeping widths. Change-Id: Iedcc5583c861f5b18a422a9b279c48cff729cbc5 Reviewed-on: https://gerrit.libreoffice.org/83613 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sc/source/filter/excel')
-rw-r--r--sc/source/filter/excel/excdoc.cxx6
-rw-r--r--sc/source/filter/excel/xetable.cxx29
2 files changed, 26 insertions, 9 deletions
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