summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2016-07-19 00:26:54 +0200
committerAndras Timar <andras.timar@collabora.com>2016-10-10 19:17:21 +0200
commit958ead3894877de753d1e163f96d3414883e6d42 (patch)
tree18b0964324541ec8405d4aaa9b5279127a2acd46 /sc
parent9fae9fd2e156dc1c2790dd402787e62d94b96d6e (diff)
tdf#100946 Fix width calculation and add customWidth support (.xlsx)
On some MS Excel version (OS X), the column "width" is not applied, if "customWidth" key (in "col") is not set to "true". It means that in case of .xlsx files, exported by LibreOffice, all columns have default width. To resolve that "customWidth" key was added during export into .xlsx file format. During development it appears that Default Column Width is wrongly calculated, and it was done not according to MS documentation. This issue was also fixed. After fix default column width is properly set. MS documentation: https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx (cherry picked from commit 40d892a2db4d750aaf0562c63004e693c028273c) Change-Id: I0d1944081a5ea445d1e4284db62e9b4d504bf1c0
Diffstat (limited to 'sc')
-rw-r--r--sc/qa/unit/subsequent_filters-test.cxx2
-rw-r--r--sc/source/filter/excel/xetable.cxx19
-rw-r--r--sc/source/filter/excel/xltools.cxx5
-rw-r--r--sc/source/filter/inc/xetable.hxx4
-rw-r--r--sc/source/filter/inc/xltools.hxx1
-rw-r--r--sc/source/filter/oox/worksheethelper.cxx3
6 files changed, 26 insertions, 8 deletions
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index cff11cddadd1..adf870284704 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -1622,7 +1622,7 @@ void ScFiltersTest::testChartImportXLS()
const SdrOle2Obj* pOleObj = getSingleChartObject(rDoc, 0);
CPPUNIT_ASSERT_MESSAGE("Failed to retrieve a chart object from the 2nd sheet.", pOleObj);
- CPPUNIT_ASSERT_EQUAL(11148L, pOleObj->GetLogicRect().getWidth());
+ CPPUNIT_ASSERT_EQUAL(11137L, pOleObj->GetLogicRect().getWidth());
CPPUNIT_ASSERT(8640L > pOleObj->GetLogicRect().getHeight());
xDocSh->DoClose();
diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx
index 1dc6dbbf4d75..5f75d2eaf193 100644
--- a/sc/source/filter/excel/xetable.cxx
+++ b/sc/source/filter/excel/xetable.cxx
@@ -1561,20 +1561,28 @@ XclExpDefcolwidth::XclExpDefcolwidth( const 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.
+ // https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx
+ long defaultColumnWidth = static_cast< long >( 256.0 * ( GetValue() + 0.5 ) );
+
// exactly matched, if difference is less than 1/16 of a character to the left or to the right
- return std::abs( static_cast< long >( GetValue() * 256.0 - fNewColWidth + 0.5 ) ) < 16;
+ return std::abs( defaultColumnWidth - fNewColWidth ) < 16;
}
void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth )
{
double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
- SetValue( limit_cast< sal_uInt16 >( fNewColWidth / 256.0 + 0.5 ) );
+ // 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 ) );
}
XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer& rOutlineBfr ) :
XclExpRecord( EXC_ID_COLINFO, 12 ),
XclExpRoot( rRoot ),
+ mbCustomWidth( false ),
mnWidth( 0 ),
mnScWidth( 0 ),
mnFlags( 0 ),
@@ -1592,9 +1600,14 @@ XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
sal_uInt16 nScWidth = rDoc.GetColWidth( nScCol, nScTab );
mnWidth = XclTools::GetXclColumnWidth( nScWidth, GetCharWidth() );
mnScWidth = sc::TwipsToHMM( nScWidth );
+
// column flags
::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
+ // TODO Do we need to save customWidth information also for .xls (with mnFlags)?
+ XclExpDefcolwidth defColWidth = XclExpDefcolwidth( rRoot );
+ mbCustomWidth = !defColWidth.IsDefWidth( mnWidth );
+
// outline data
rOutlineBfr.Update( nScCol );
::set_flag( mnFlags, EXC_COLINFO_COLLAPSED, rOutlineBfr.IsCollapsed() );
@@ -1650,7 +1663,7 @@ void XclExpColinfo::SaveXml( XclExpXmlStream& rStrm )
rStrm.GetCurrentStream()->singleElement( XML_col,
// OOXTODO: XML_bestFit,
XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
- // OOXTODO: XML_customWidth,
+ XML_customWidth, XclXmlUtils::ToPsz( mbCustomWidth ),
XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
XML_max, OString::number( (nLastXclCol+1) ).getStr(),
XML_min, OString::number( (mnFirstXclCol+1) ).getStr(),
diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx
index f2a786cd0573..b64d94021856 100644
--- a/sc/source/filter/excel/xltools.cxx
+++ b/sc/source/filter/excel/xltools.cxx
@@ -312,13 +312,13 @@ sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth )
{
- double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth + 0.5;
+ double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth - 0.5;
return limit_cast< sal_uInt16 >( fScWidth );
}
sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth )
{
- double fXclWidth = static_cast< double >( nScWidth ) * 256.0 / nScCharWidth + 0.5;
+ double fXclWidth = ( static_cast< double >( nScWidth ) + 0.5 ) * 256.0 / nScCharWidth;
return limit_cast< sal_uInt16 >( fXclWidth );
}
@@ -629,6 +629,7 @@ bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, cons
return true;
}
}
+
rnStyleId = EXC_STYLE_USERDEF;
rnLevel = EXC_STYLE_NOLEVEL;
return false;
diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx
index 3a29f3582f4d..e6318fd1b4b0 100644
--- a/sc/source/filter/inc/xetable.hxx
+++ b/sc/source/filter/inc/xetable.hxx
@@ -683,6 +683,9 @@ private:
if the '0' character fits 10 times into a cell in a column with default
width.
+ Half of character width is reserved for non character display.
+ It is margin padding (two on each side) and padding for the gridlines.
+
The IsDefWidth() function returns true, if the passed width (measured in
1/256 of the width of the '0' character) could be converted exactly to the
default width. If the passed width is rounded up or down to get the default
@@ -740,6 +743,7 @@ private:
private:
XclExpXFId maXFId; /// The XF identifier for column default format.
+ bool mbCustomWidth; /// True = Column width is different from default width
sal_uInt16 mnWidth; /// Excel width of the column.
sal_uInt16 mnScWidth; /// Calc width of the column.
sal_uInt16 mnFlags; /// Additional column flags.
diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx
index 67c8f3ca4966..c3cf9bc39986 100644
--- a/sc/source/filter/inc/xltools.hxx
+++ b/sc/source/filter/inc/xltools.hxx
@@ -135,6 +135,7 @@ public:
static sal_Int32 GetHmmFromTwips( sal_Int32 nTwips );
/** Returns the Calc column width (twips) for the passed Excel width.
+ * Excel Column width is stored as 1/256th of a character.
@param nScCharWidth Width of the '0' character in Calc (twips). */
static sal_uInt16 GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth );
/** Returns the Excel column width for the passed Calc width (twips).
diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx
index e817d2508ac2..b50323589791 100644
--- a/sc/source/filter/oox/worksheethelper.cxx
+++ b/sc/source/filter/oox/worksheethelper.cxx
@@ -1183,11 +1183,10 @@ sal_Int32 getColumnWidth(UnitConverter& rConverter, double nWidth)
long nPixel = aDev->LogicToPixel(Point(nCoeff, 0), MapMode(MAP_100TH_MM)).getX();
-
// the 1.047 has been experimentally chosen based on measurements with a screen ruler
// TODO: fix the display of cells so that it no longer requires this hack
// algorithm from OOXML spec part1: 18.3.1.13
- sal_Int32 nColWidthPixel= std::floor(((256*nWidth + std::floor(128.0/nPixel))/256.0)*nPixel) * 1.047;
+ sal_Int32 nColWidthPixel= std::floor( ( ( 256 * nWidth + std::floor( 128.0 / nPixel ) ) / 256.0 ) * nPixel ) * 1.047;
return aDev->PixelToLogic(Point(nColWidthPixel, 0), MapMode(MAP_100TH_MM)).getX();
}