diff options
author | Noel Power <noel.power@suse.com> | 2013-01-29 14:51:49 +0000 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2013-02-07 16:23:32 +0000 |
commit | 5aade07de7b404d1254e2135de751c3af4a05e1e (patch) | |
tree | 5b285dff2db223b4b93a2580a59dc81cf0f823b6 | |
parent | Impress Remote 1.0.0, tag sdremote-1.0.0 (diff) | |
download | core-5aade07de7b404d1254e2135de751c3af4a05e1e.tar.gz core-5aade07de7b404d1254e2135de751c3af4a05e1e.zip |
correctly handle repeated row heights for empty rows ( fdo#59973 )
rollup of 9327467a2c5537613fa59013258532028da9c43b and b75bf09a5b905a3ed9c251869983a400c70c7fc6
it seems both xls & xlsx export suffer from problems with multiple row heights
repeated ( if those rows are empty )
better default row detection ( associated with fdo#55621 )
previous patch associated with fdo#55621 compared single instances of row
heights to determine the default height, it didn't take into account though
repeated rows. Additionally the limit of rows heights ( where rows were empty )
considered when exporting xlsx was the old 65535 limit.
Change-Id: I3ed68a81517a3e55d1de1954fcb99e7cb39be337
Reviewed-on: https://gerrit.libreoffice.org/2004
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
-rw-r--r-- | sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods | bin | 0 -> 7038 bytes | |||
-rwxr-xr-x | sc/qa/unit/data/xlsx/miscrowheights.xlsx | bin | 0 -> 8522 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 74 | ||||
-rw-r--r-- | sc/source/filter/excel/xetable.cxx | 81 | ||||
-rw-r--r-- | sc/source/filter/inc/xetable.hxx | 4 |
5 files changed, 138 insertions, 21 deletions
diff --git a/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods b/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods Binary files differnew file mode 100644 index 000000000000..5511ad9e99a2 --- /dev/null +++ b/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods diff --git a/sc/qa/unit/data/xlsx/miscrowheights.xlsx b/sc/qa/unit/data/xlsx/miscrowheights.xlsx Binary files differnew file mode 100755 index 000000000000..dbdbc137e535 --- /dev/null +++ b/sc/qa/unit/data/xlsx/miscrowheights.xlsx diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index 26fe25c8bd18..844020d71461 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -77,6 +77,7 @@ public: void test(); void testPasswordExport(); void testConditionalFormatExportXLSX(); + void testMiscRowHeightExport(); CPPUNIT_TEST_SUITE(ScExportTest); CPPUNIT_TEST(test); @@ -84,6 +85,7 @@ public: CPPUNIT_TEST(testPasswordExport); #endif CPPUNIT_TEST(testConditionalFormatExportXLSX); + CPPUNIT_TEST(testMiscRowHeightExport); CPPUNIT_TEST_SUITE_END(); private: @@ -297,6 +299,78 @@ void ScExportTest::testConditionalFormatExportXLSX() testCondFile(aCSVPath, pDoc, 0); } +void ScExportTest::testMiscRowHeightExport() +{ + + struct TestParam + { + struct RowData + { + SCROW nStartRow; + SCROW nEndRow; + SCTAB nTab; + int nExpectedHeight; + }; + const char* sTestDoc; + int nImportType; + int nExportType; + int nRowData; + RowData* pData; + }; + + TestParam::RowData DfltRowData[] = + { + { 0, 4, 0, 529 }, + { 5, 10, 0, 1058 }, + { 17, 20, 0, 1767 }, + { 1048573, 1048575, 0, 529 }, + }; + + TestParam::RowData EmptyRepeatRowData[] = + { + { 0, 4, 0, 529 }, + { 5, 10, 0, 1058 }, + { 17, 20, 0, 1767 }, + }; + + TestParam aTestValues[] = + { + { "miscrowheights.", XLSX, XLSX, SAL_N_ELEMENTS(DfltRowData), DfltRowData }, + { "miscrowheights.", XLSX, XLS, SAL_N_ELEMENTS(DfltRowData), DfltRowData }, + { "miscemptyrepeatedrowheights.", ODS, XLSX, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData }, + { "miscemptyrepeatedrowheights.", ODS, XLS, SAL_N_ELEMENTS(EmptyRepeatRowData), EmptyRepeatRowData }, + }; + + for ( unsigned int index=0; index<SAL_N_ELEMENTS(aTestValues); ++index ) + { + OUString sFileName = OUString::createFromAscii( aTestValues[ index ].sTestDoc ); + printf("aTestValues[%d] %s\n", index, OUStringToOString( sFileName, RTL_TEXTENCODING_UTF8 ).getStr() ); + int nImportType = aTestValues[ index ].nImportType; + int nExportType = aTestValues[ index ].nExportType; + ScDocShellRef xShell = loadDocument( sFileName, nImportType ); + CPPUNIT_ASSERT(xShell.Is()); + + ScDocShellRef xDocSh = saveAndReload(&(*xShell), nExportType ); + CPPUNIT_ASSERT(xDocSh.Is()); + + ScDocument* pDoc = xDocSh->GetDocument(); + + for (int i=0; i<aTestValues[ index ].nRowData; ++i) + { + SCROW nRow = aTestValues[ index ].pData[ i].nStartRow; + SCROW nEndRow = aTestValues[ index ].pData[ i ].nEndRow; + SCTAB nTab = aTestValues[ index ].pData[ i ].nTab; + int nExpectedHeight = aTestValues[ index ].pData[ i ].nExpectedHeight; + for ( ; nRow <= nEndRow; ++nRow ) + { + printf("\t checking row %d for height %d\n", nRow, nExpectedHeight ); + int nHeight = sc::TwipsToHMM( pDoc->GetRowHeight(nRow, nTab, false) ); + CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight); + } + } + } +} + ScExportTest::ScExportTest() : m_aBaseString(RTL_CONSTASCII_USTRINGPARAM("/sc/qa/unit/data")) { diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index ec54e15a4630..c44b32c1dcfa 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1708,6 +1708,8 @@ XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt32 nXclRow, mnFlags( EXC_ROW_DEFAULTFLAGS ), mnXFIndex( EXC_XF_DEFAULTCELL ), mnOutlineLevel( 0 ), + mnXclRowRpt( 1 ), + mnCurrentRow( nXclRow ), mbAlwaysEmpty( bAlwaysEmpty ), mbEnabled( true ) { @@ -1921,7 +1923,11 @@ void XclExpRow::WriteCellList( XclExpStream& rStrm ) void XclExpRow::Save( XclExpStream& rStrm ) { if( mbEnabled ) - XclExpRecord::Save( rStrm ); + { + mnCurrentRow = mnXclRow; + for ( sal_uInt32 i = 0; i < mnXclRowRpt; ++i, ++mnCurrentRow ) + XclExpRecord::Save( rStrm ); + } } void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase ) @@ -1950,7 +1956,7 @@ void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase void XclExpRow::WriteBody( XclExpStream& rStrm ) { - rStrm << static_cast< sal_uInt16 >(mnXclRow) + rStrm << static_cast< sal_uInt16 >(mnCurrentRow) << GetFirstUsedXclCol() << GetFirstFreeXclCol() << mnHeight @@ -1965,23 +1971,27 @@ void XclExpRow::SaveXml( XclExpXmlStream& rStrm ) return; sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); bool haveFormat = ::get_flag( mnFlags, EXC_ROW_USEDEFXF ); - rWorksheet->startElement( XML_row, - XML_r, OString::valueOf( (sal_Int32) (mnXclRow+1) ).getStr(), - // OOXTODO: XML_spans, optional - XML_s, haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : NULL, - XML_customFormat, XclXmlUtils::ToPsz( haveFormat ), - XML_ht, OString::valueOf( (double) mnHeight / 20.0 ).getStr(), - XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ), - XML_customHeight, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ), - XML_outlineLevel, OString::valueOf( (sal_Int32) mnOutlineLevel ).getStr(), - XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) ), - // OOXTODO: XML_thickTop, bool - // OOXTODO: XML_thickBot, bool - // OOXTODO: XML_ph, bool - FSEND ); - // OOXTODO: XML_extLst - maCellList.SaveXml( rStrm ); - rWorksheet->endElement( XML_row ); + mnCurrentRow = mnXclRow + 1; + for ( sal_uInt32 i=0; i<mnXclRowRpt; ++i ) + { + rWorksheet->startElement( XML_row, + XML_r, OString::valueOf( (sal_Int32) (mnCurrentRow++) ).getStr(), + // OOXTODO: XML_spans, optional + XML_s, haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : NULL, + XML_customFormat, XclXmlUtils::ToPsz( haveFormat ), + XML_ht, OString::valueOf( (double) mnHeight / 20.0 ).getStr(), + XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ), + XML_customHeight, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ), + XML_outlineLevel, OString::valueOf( (sal_Int32) mnOutlineLevel ).getStr(), + XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) ), + // OOXTODO: XML_thickTop, bool + // OOXTODO: XML_thickBot, bool + // OOXTODO: XML_ph, bool + FSEND ); + // OOXTODO: XML_extLst + maCellList.SaveXml( rStrm ); + rWorksheet->endElement( XML_row ); + } } // ---------------------------------------------------------------------------- @@ -2002,7 +2012,7 @@ void XclExpRowBuffer::AppendCell( XclExpCellRef xCell, bool bIsMergedBase ) void XclExpRowBuffer::CreateRows( SCROW nFirstFreeScRow ) { if( nFirstFreeScRow > 0 ) - GetOrCreateRow( static_cast< sal_uInt16 >( nFirstFreeScRow - 1 ), true ); + GetOrCreateRow( ::std::max ( nFirstFreeScRow - 1, GetMaxPos().Row() ), true ); } void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt16Vec& rColXFIndexes ) @@ -2023,6 +2033,9 @@ void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt XclExpDefaultRowData aMaxDefData; size_t nMaxDefCount = 0; // only look for default format in existing rows, if there are more than unused + XclExpRow* pPrev = NULL; + typedef std::vector< XclExpRow* > XclRepeatedRows; + XclRepeatedRows aRepeated; for (itr = itrBeg; itr != itrEnd; ++itr) { const RowRef& rRow = itr->second; @@ -2037,11 +2050,37 @@ void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt aMaxDefData = aDefData; } } + if ( pPrev ) + { + sal_uInt32 nRpt = rRow->GetXclRow() - pPrev->GetXclRow(); + pPrev->SetXclRowRpt( nRpt ); + if ( nRpt > 1 ) + aRepeated.push_back( pPrev ); + if ( pPrev->IsDefaultable()) + { + XclExpDefaultRowData aDefData( *pPrev ); + size_t& rnDefCount = aDefRowMap[ aDefData ]; + rnDefCount += ( pPrev->GetXclRowRpt() - 1 ); + if( rnDefCount > nMaxDefCount ) + { + nMaxDefCount = rnDefCount; + aMaxDefData = aDefData; + } + } + } + pPrev = rRow.get(); } - // return the default row format to caller rDefRowData = aMaxDefData; + // now disable repeating extra (empty) rows that are equal to + // default row height + for ( XclRepeatedRows::iterator it = aRepeated.begin(), it_end = aRepeated.end(); it != it_end; ++it) + { + if ( (*it)->GetXclRowRpt() > 1 && (*it)->GetHeight() == rDefRowData.mnHeight ) + (*it)->SetXclRowRpt( 1 ); + } + // *** Disable unused ROW records, find used area *** --------------------- sal_uInt16 nFirstUsedXclCol = SAL_MAX_UINT16; diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx index 41ec24b22266..3a2ec386921f 100644 --- a/sc/source/filter/inc/xetable.hxx +++ b/sc/source/filter/inc/xetable.hxx @@ -917,6 +917,8 @@ public: virtual void Save( XclExpStream& rStrm ); virtual void SaveXml( XclExpXmlStream& rStrm ); + inline sal_uInt32 GetXclRowRpt() const { return mnXclRowRpt; } + inline void SetXclRowRpt( sal_uInt32 nRpt ){ mnXclRowRpt = nRpt; } private: /** Initializes the record data. Called from constructors. */ void Init( sal_uInt16 nXclRow, XclExpRowOutlineBuffer* pOutlineBfr ); @@ -935,6 +937,8 @@ private: sal_uInt16 mnFlags; /// Flags for the ROW record. sal_uInt16 mnXFIndex; /// Default row formatting. sal_uInt16 mnOutlineLevel; /// Outline Level (for OOXML) + sal_uInt32 mnXclRowRpt; + sal_uInt32 mnCurrentRow; bool mbAlwaysEmpty; /// true = Do not add blank cells in Finalize(). bool mbEnabled; /// true = Write this ROW record. }; |