summaryrefslogtreecommitdiff
path: root/sc/source/filter/excel
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2019-04-23 15:59:24 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2019-04-24 09:22:56 +0200
commit071d72cc3662168c58358ce53a77ceacbf80f545 (patch)
treee2970363750412a3141198d557dc6f349dd704c1 /sc/source/filter/excel
parentaf84fc9d906626255aaf136eefc5e55236e0e8a6 (diff)
tdf#124741: export default column width to XLSX
For some reason, we have never exported the default column width to XLSX, although we have such export for XLS. This led to bugs like tdf#100946. Workarounds applied to those bugs have made LO to export columns which shouldn't have been exported, abusing "customWidth" attribute in XclExpColinfo::XclExpColinfo depending on if the column has size different from an app-global default; after that, sheet-local default was determined, and then columns which have mbCustomWidth set (i.e., different from app default), as well as those different from sheet-local default, were stored. Effectively, the hack had disabled the removal of defaults from maColInfos in XclExpColinfoBuffer::Finalize. We even had unit tests explicitly testing that we export those columns that Excel skips. The effect of that is not only unnecessary data in the file; the data was actually wrong (customWidth actually means that the width was edited manually by user, even if equal to the default, thus changing Excel handling of the column); and also Calc initializes all columns to the right of last used column for such a file. Only in case when app-global default happened to match sheet-local one, columns would have properties allowing them to be removed from maColInfos in the end of XclExpColinfoBuffer::Finalize, which still resulted in problems similar to the workarounded one. This patch implements proper export of the default column width to XLSX, thus partially reverting changes made for tdf#100946 in commit 40d892a2db4d750aaf0562c63004e693c028273c. Actually, our export to XLSX does not depend on the 5-pixel correction (see ECMA-376-1:2016 18.3.1.81), since the exported default depends only on most-used column width. XclExpDefcolwidth implementation was edited to only take the correction into account when exporting to XLS (to keep status quo; it's clear that XLS widths export and import implementation is incorrect: some empirical formula is used in XclTools::GetXclDefColWidthCorrection, that was introduced in commit 555d702903fb0857122024e1ab78a72d122d3f16 for i#3006, that doesn't match any documentation, and changes widths of columns in exported XLS - something to be fixed independently). Change-Id: I227aca17e56247cbb839444717066a898987c4f1 Reviewed-on: https://gerrit.libreoffice.org/71132 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Tested-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sc/source/filter/excel')
-rw-r--r--sc/source/filter/excel/xetable.cxx43
1 files changed, 25 insertions, 18 deletions
diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx
index f3cd211ff71e..e236a795f72d 100644
--- a/sc/source/filter/excel/xetable.cxx
+++ b/sc/source/filter/excel/xetable.cxx
@@ -1538,38 +1538,48 @@ void XclExpDimensions::WriteBody( XclExpStream& rStrm )
namespace {
-double lclGetCorrectedColWidth( const XclExpRoot& rRoot, sal_uInt16 nXclColWidth )
+double lclGetCChCorrection(const XclExpRoot& rRoot)
{
+ // Convert the correction from 1/256ths of a character size to count of chars
+ // TODO: make to fit ECMA-376-1:2016 18.3.1.81 sheetFormatPr (Sheet Format Properties):
+ // 5 pixels are added to the base width: 2 for margin padding on each side, plus 1 for gridline
+ // So this should depend on rRoot.GetCharWidth(), not on font height
+
long nFontHt = rRoot.GetFontBuffer().GetAppFontData().mnHeight;
- return nXclColWidth - XclTools::GetXclDefColWidthCorrection( nFontHt );
+ return XclTools::GetXclDefColWidthCorrection(nFontHt) / 256.0;
}
} // namespace
XclExpDefcolwidth::XclExpDefcolwidth( const XclExpRoot& rRoot ) :
- XclExpUInt16Record( EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF ),
+ XclExpDoubleRecord(EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF + lclGetCChCorrection(rRoot)),
XclExpRoot( rRoot )
{
}
bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const
{
- double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
// This formula is taking number of characters with GetValue()
- // and it is translating it into default column width. 0.5 means half character.
+ // and it is translating it into default column width.
// https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx
- long defaultColumnWidth = static_cast< long >( 256.0 * ( GetValue() + 0.5 ) );
+ double defaultColumnWidth = 256.0 * GetValue();
// exactly matched, if difference is less than 1/16 of a character to the left or to the right
- return std::abs( defaultColumnWidth - fNewColWidth ) < 16;
+ return std::abs(defaultColumnWidth - nXclColWidth) < 256.0 * 1.0 / 16.0;
}
void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth )
{
- double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
- // This function is taking width and translate it into number of characters
- // Next this number of characters are stored. 0.5 means half character.
- SetValue( limit_cast< sal_uInt16 >( fNewColWidth / 256.0 - 0.5 ) );
+ SetValue(nXclColWidth / 256.0);
+}
+
+void XclExpDefcolwidth::Save(XclExpStream& rStrm)
+{
+ double fCorrectedCCh = GetValue() - lclGetCChCorrection(GetRoot());
+ // Convert double to sal_uInt16
+ XclExpUInt16Record aUInt16Rec(GetRecId(),
+ static_cast<sal_uInt16>(std::round(fCorrectedCCh)));
+ aUInt16Rec.Save(rStrm);
}
XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
@@ -1599,10 +1609,6 @@ XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
// column flags
::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
- XclExpDefcolwidth defColWidth( rRoot );
- mbCustomWidth = !defColWidth.IsDefWidth( mnWidth );
- set_flag(mnFlags, EXC_COLINFO_CUSTOMWIDTH, mbCustomWidth);
-
// outline data
rOutlineBfr.Update( nScCol );
::set_flag( mnFlags, EXC_COLINFO_COLLAPSED, rOutlineBfr.IsCollapsed() );
@@ -1615,12 +1621,13 @@ void XclExpColinfo::ConvertXFIndexes()
maXFId.ConvertXFIndex( GetRoot() );
}
-bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth ) const
+bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth )
{
+ mbCustomWidth = !rDefColWidth.IsDefWidth(mnWidth);
return (maXFId.mnXFIndex == EXC_XF_DEFAULTCELL) &&
(mnFlags == 0) &&
(mnOutlineLevel == 0) &&
- rDefColWidth.IsDefWidth( mnWidth );
+ !mbCustomWidth;
}
bool XclExpColinfo::TryMerge( const XclExpColinfo& rColInfo )
@@ -2680,7 +2687,7 @@ void XclExpCellTable::SaveXml( XclExpXmlStream& rStrm )
sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
rWorksheet->startElement( XML_sheetFormatPr,
// OOXTODO: XML_baseColWidth
- // OOXTODO: XML_defaultColWidth
+ XML_defaultColWidth, OString::number(maColInfoBfr.GetDefColWidth()),
// OOXTODO: XML_customHeight
// OOXTODO: XML_thickTop
// OOXTODO: XML_thickBottom