[Libreoffice-commits] core.git: Branch 'libreoffice-4-0' - sc/qa sc/source

Noel Power noel.power at suse.com
Thu Feb 7 08:23:52 PST 2013


 sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods |binary
 sc/qa/unit/data/xlsx/miscrowheights.xlsx            |binary
 sc/qa/unit/subsequent_export-test.cxx               |   74 ++++++++++++++++++
 sc/source/filter/excel/xetable.cxx                  |   81 ++++++++++++++------
 sc/source/filter/inc/xetable.hxx                    |    4 
 5 files changed, 138 insertions(+), 21 deletions(-)

New commits:
commit 5aade07de7b404d1254e2135de751c3af4a05e1e
Author: Noel Power <noel.power at suse.com>
Date:   Tue Jan 29 14:51:49 2013 +0000

    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 at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods b/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods
new file mode 100644
index 0000000..5511ad9
Binary files /dev/null and b/sc/qa/unit/data/ods/miscemptyrepeatedrowheights.ods differ
diff --git a/sc/qa/unit/data/xlsx/miscrowheights.xlsx b/sc/qa/unit/data/xlsx/miscrowheights.xlsx
new file mode 100755
index 0000000..dbdbc13
Binary files /dev/null and b/sc/qa/unit/data/xlsx/miscrowheights.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 26fe25c..844020d 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 ec54e15..c44b32c 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 41ec24b..3a2ec38 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.
 };


More information about the Libreoffice-commits mailing list