[Libreoffice-commits] core.git: Branch 'private/kohei/xlsx-import-speedup' - 3 commits - sc/qa sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Mon Nov 4 19:56:27 CET 2013


 dev/null                                          |binary
 sc/qa/unit/data/xls/data-table/mortgage.xls       |binary
 sc/qa/unit/data/xlsx/data-table/multi-table.xlsx  |binary
 sc/qa/unit/data/xlsx/data-table/one-variable.xlsx |binary
 sc/qa/unit/subsequent_filters-test.cxx            |   95 ++++++++++++++++
 sc/source/filter/inc/sheetdatabuffer.hxx          |    5 
 sc/source/filter/oox/sheetdatabuffer.cxx          |  124 +++++++++++-----------
 7 files changed, 160 insertions(+), 64 deletions(-)

New commits:
commit 380d36f32a6980c770c52e30d54a153a447549bf
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 13:57:34 2013 -0500

    Two new test cases for importing data tables from XLSX.
    
    Change-Id: I87da806612ae50fe1d64b851c5180ff1792752cb

diff --git a/sc/qa/unit/data/xlsx/data-table/multi-table.xlsx b/sc/qa/unit/data/xlsx/data-table/multi-table.xlsx
new file mode 100644
index 0000000..c2bf488
Binary files /dev/null and b/sc/qa/unit/data/xlsx/data-table/multi-table.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/data-table/one-variable.xlsx b/sc/qa/unit/data/xlsx/data-table/one-variable.xlsx
new file mode 100644
index 0000000..7ff098b2
Binary files /dev/null and b/sc/qa/unit/data/xlsx/data-table/one-variable.xlsx differ
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 2361f9f..6662dcd 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -108,6 +108,8 @@ public:
     void testRepeatedColumnsODS();
     void testDataValidityODS();
     void testDataTableMortgageXLS();
+    void testDataTableOneVarXLSX();
+    void testDataTableMultiTableXLSX();
 
     void testDataBarODS();
     void testDataBarXLSX();
@@ -171,6 +173,8 @@ public:
     CPPUNIT_TEST(testRepeatedColumnsODS);
     CPPUNIT_TEST(testDataValidityODS);
     CPPUNIT_TEST(testDataTableMortgageXLS);
+    CPPUNIT_TEST(testDataTableOneVarXLSX);
+    CPPUNIT_TEST(testDataTableMultiTableXLSX);
     CPPUNIT_TEST(testBrokenQuotesCSV);
     CPPUNIT_TEST(testCellValueXLSX);
     CPPUNIT_TEST(testControlImport);
@@ -1073,6 +1077,8 @@ void ScFiltersTest::testDataValidityODS()
 void ScFiltersTest::testDataTableMortgageXLS()
 {
     ScDocShellRef xDocSh = loadDoc("data-table/mortgage.", XLS);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xDocSh.Is());
+
     ScFormulaOptions aOptions;
     aOptions.SetFormulaSepArg(",");
     aOptions.SetFormulaSepArrayCol(",");
@@ -1121,6 +1127,87 @@ void ScFiltersTest::testDataTableMortgageXLS()
     xDocSh->DoClose();
 }
 
+void ScFiltersTest::testDataTableOneVarXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("data-table/one-variable.", XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xDocSh.Is());
+
+    ScFormulaOptions aOptions;
+    aOptions.SetFormulaSepArg(",");
+    aOptions.SetFormulaSepArrayCol(",");
+    aOptions.SetFormulaSepArrayRow(";");
+    xDocSh->SetFormulaOptions(aOptions);
+
+    ScDocument* pDoc = xDocSh->GetDocument();
+
+    // Right now, we have a bug that prevents Calc from re-calculating these
+    // cells automatically upon file load. We can remove this call if/when we
+    // fix the aforementioned bug.
+    pDoc->CalcAll();
+
+    // B5:B11 should have multiple operations formula cells.  Just check the
+    // top and bottom cells.
+
+    if (!checkFormula(*pDoc, ScAddress(1,4,0), "MULTIPLE.OPERATIONS(B$4,$A$2,$A5)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(2.0, pDoc->GetValue(ScAddress(1,4,0)));
+
+    if (!checkFormula(*pDoc, ScAddress(1,10,0), "MULTIPLE.OPERATIONS(B$4,$A$2,$A11)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(14.0, pDoc->GetValue(ScAddress(1,10,0)));
+
+    // Likewise, E5:I5 should have multiple operations formula cells.  Just
+    // check the left- and right-most cells.
+
+    if (!checkFormula(*pDoc, ScAddress(4,4,0), "MULTIPLE.OPERATIONS($D5,$B$2,E$4)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(10.0, pDoc->GetValue(ScAddress(4,4,0)));
+
+    if (!checkFormula(*pDoc, ScAddress(8,4,0), "MULTIPLE.OPERATIONS($D5,$B$2,I$4)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(50.0, pDoc->GetValue(ScAddress(8,4,0)));
+
+    xDocSh->DoClose();
+}
+
+void ScFiltersTest::testDataTableMultiTableXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("data-table/multi-table.", XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load the document.", xDocSh.Is());
+
+    ScFormulaOptions aOptions;
+    aOptions.SetFormulaSepArg(",");
+    aOptions.SetFormulaSepArrayCol(",");
+    aOptions.SetFormulaSepArrayRow(";");
+    xDocSh->SetFormulaOptions(aOptions);
+
+    ScDocument* pDoc = xDocSh->GetDocument();
+
+    // Right now, we have a bug that prevents Calc from re-calculating these
+    // cells automatically upon file load. We can remove this call if/when we
+    // fix the aforementioned bug.
+    pDoc->CalcAll();
+
+    // B4:M15 should have multiple operations formula cells.  We'll just check
+    // the top-left and bottom-right ones.
+
+    if (!checkFormula(*pDoc, ScAddress(1,3,0), "MULTIPLE.OPERATIONS($A$3,$E$1,$A4,$D$1,B$3)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(1,3,0)));
+
+    if (!checkFormula(*pDoc, ScAddress(12,14,0), "MULTIPLE.OPERATIONS($A$3,$E$1,$A15,$D$1,M$3)"))
+        CPPUNIT_FAIL("Wrong formula!");
+
+    CPPUNIT_ASSERT_EQUAL(144.0, pDoc->GetValue(ScAddress(12,14,0)));
+
+    xDocSh->DoClose();
+}
+
 void ScFiltersTest::testBrokenQuotesCSV()
 {
     const OUString aFileNameBase("fdo48621_broken_quotes.");
commit ed39603f8eb27fc5d03eab00dbc4ed175d0ff9d6
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 13:27:44 2013 -0500

    Create data-table directory and move the test file into it.
    
    Change-Id: I1007525a7d2e1135f0388975f9cb7b0cef9b3142

diff --git a/sc/qa/unit/data/xls/data-table-mortgage.xls b/sc/qa/unit/data/xls/data-table/mortgage.xls
similarity index 100%
rename from sc/qa/unit/data/xls/data-table-mortgage.xls
rename to sc/qa/unit/data/xls/data-table/mortgage.xls
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 4083993..2361f9f 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -107,7 +107,7 @@ public:
     void testMergedCellsODS();
     void testRepeatedColumnsODS();
     void testDataValidityODS();
-    void testDataTableXLS();
+    void testDataTableMortgageXLS();
 
     void testDataBarODS();
     void testDataBarXLSX();
@@ -170,7 +170,7 @@ public:
     CPPUNIT_TEST(testMergedCellsODS);
     CPPUNIT_TEST(testRepeatedColumnsODS);
     CPPUNIT_TEST(testDataValidityODS);
-    CPPUNIT_TEST(testDataTableXLS);
+    CPPUNIT_TEST(testDataTableMortgageXLS);
     CPPUNIT_TEST(testBrokenQuotesCSV);
     CPPUNIT_TEST(testCellValueXLSX);
     CPPUNIT_TEST(testControlImport);
@@ -1070,9 +1070,9 @@ void ScFiltersTest::testDataValidityODS()
     xDocSh->DoClose();
 }
 
-void ScFiltersTest::testDataTableXLS()
+void ScFiltersTest::testDataTableMortgageXLS()
 {
-    ScDocShellRef xDocSh = loadDoc("data-table-mortgage.", XLS);
+    ScDocShellRef xDocSh = loadDoc("data-table/mortgage.", XLS);
     ScFormulaOptions aOptions;
     aOptions.SetFormulaSepArg(",");
     aOptions.SetFormulaSepArrayCol(",");
commit d81441dc3b235a5fd0366ef6ad0d3e6885ff70b0
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 11:50:18 2013 -0500

    Import data tables from xlsx via ScDocumentImport.
    
    Change-Id: Id3d526720f99b7557476915beab35b429ec97c1d

diff --git a/sc/source/filter/inc/sheetdatabuffer.hxx b/sc/source/filter/inc/sheetdatabuffer.hxx
index 192f359..ceb3a80 100644
--- a/sc/source/filter/inc/sheetdatabuffer.hxx
+++ b/sc/source/filter/inc/sheetdatabuffer.hxx
@@ -176,9 +176,8 @@ private:
                             const ::com::sun::star::table::CellRangeAddress& rRange,
                             const ApiTokenSequence& rTokens ) const;
     /** Inserts the passed table operation into the sheet. */
-    void                finalizeTableOperation(
-                            const ::com::sun::star::table::CellRangeAddress& rRange,
-                            const DataTableModel& rModel ) const;
+    void finalizeTableOperation(
+        const ::com::sun::star::table::CellRangeAddress& rRange, const DataTableModel& rModel );
 
     /** Writes all cell formatting attributes to the passed cell range list. (depreciates writeXfIdRangeProperties) */
     void                applyCellMerging( const ::com::sun::star::table::CellRangeAddress& rRange );
diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx
index 7f9c8e4..ebc7dca 100644
--- a/sc/source/filter/oox/sheetdatabuffer.cxx
+++ b/sc/source/filter/oox/sheetdatabuffer.cxx
@@ -50,6 +50,8 @@
 #include "document.hxx"
 #include "scitems.hxx"
 #include "formulacell.hxx"
+#include "paramisc.hxx"
+#include "documentimport.hxx"
 
 namespace oox {
 namespace xls {
@@ -563,71 +565,79 @@ void SheetDataBuffer::finalizeArrayFormula( const CellRangeAddress& rRange, cons
         xTokens->setArrayTokens( rTokens );
 }
 
-void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const
+void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
 {
+    if (rModel.mbRef1Deleted)
+        return;
+
+    if (rModel.maRef1.isEmpty())
+        return;
+
+    if (rRange.StartColumn <= 0 || rRange.StartRow <= 0)
+        return;
+
     sal_Int16 nSheet = getSheetIndex();
-    bool bOk = false;
-    if( !rModel.mbRef1Deleted && !rModel.maRef1.isEmpty() && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
+
+    CellAddress aRef1;
+    if (!getAddressConverter().convertToCellAddress(aRef1, rModel.maRef1, nSheet, true))
+        return;
+
+    ScDocumentImport& rDoc = getDocImport();
+    ScTabOpParam aParam;
+
+    ScRange aScRange;
+    ScUnoConversion::FillScRange(aScRange, rRange);
+
+    if (rModel.mb2dTable)
     {
-        CellRangeAddress aOpRange = rRange;
-        CellAddress aRef1;
-        if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try
-        {
-            if( rModel.mb2dTable )
-            {
-                CellAddress aRef2;
-                if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) )
-                {
-                    // API call expects input values inside operation range
-                    --aOpRange.StartColumn;
-                    --aOpRange.StartRow;
-                    // formula range is top-left cell of operation range
-                    CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
-                    // set multiple operation
-                    Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
-                    xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 );
-                    bOk = true;
-                }
-            }
-            else if( rModel.mbRowTable )
-            {
-                // formula range is column to the left of operation range
-                CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
-                // API call expects input values (top row) inside operation range
-                --aOpRange.StartRow;
-                // set multiple operation
-                Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
-                xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 );
-                bOk = true;
-            }
-            else
-            {
-                // formula range is row above operation range
-                CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
-                // API call expects input values (left column) inside operation range
-                --aOpRange.StartColumn;
-                // set multiple operation
-                Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
-                xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 );
-                bOk = true;
-            }
-        }
-        catch( Exception& )
-        {
-        }
+        // Two-variable data table.
+        if (rModel.mbRef2Deleted)
+            return;
+
+        if (rModel.maRef2.isEmpty())
+            return;
+
+        CellAddress aRef2;
+        if (!getAddressConverter().convertToCellAddress(aRef2, rModel.maRef2, nSheet, true))
+            return;
+
+        aParam.meMode = ScTabOpParam::Both;
+
+        aParam.aRefFormulaCell.Set(rRange.StartColumn-1, rRange.StartRow-1, nSheet, false, false, false);
+        aParam.aRefFormulaEnd = aParam.aRefFormulaCell;
+
+        aScRange.aStart.IncRow(-1);
+        aScRange.aStart.IncCol(-1);
+
+        // Ref1 is row input cell and Ref2 is column input cell.
+        aParam.aRefRowCell.Set(aRef1.Column, aRef1.Row, aRef1.Sheet, false, false, false);
+        aParam.aRefColCell.Set(aRef2.Column, aRef2.Row, aRef2.Sheet, false, false, false);
+        rDoc.setTableOpCells(aScRange, aParam);
+
+        return;
     }
 
-    // on error: fill cell range with #REF! error codes
-    if( !bOk ) try
+    // One-variable data table.
+
+    if (rModel.mbRowTable)
     {
-        Reference< XCellRangeData > xCellRangeData( getCellRange( rRange ), UNO_QUERY_THROW );
-        size_t nWidth = static_cast< size_t >( rRange.EndColumn - rRange.StartColumn + 1 );
-        size_t nHeight = static_cast< size_t >( rRange.EndRow - rRange.StartRow + 1 );
-        Matrix< Any > aErrorCells( nWidth, nHeight, Any( getFormulaParser().convertErrorToFormula( BIFF_ERR_REF ) ) );
-        xCellRangeData->setDataArray( ContainerHelper::matrixToSequenceSequence( aErrorCells ) );
+        // One-variable row input cell (horizontal).
+        aParam.meMode = ScTabOpParam::Row;
+        aParam.aRefRowCell.Set(aRef1.Column, aRef1.Row, aRef1.Sheet, false, false, false);
+        aParam.aRefFormulaCell.Set(rRange.StartColumn-1, rRange.StartRow, nSheet, false, true, false);
+        aParam.aRefFormulaEnd = aParam.aRefFormulaCell;
+        aScRange.aStart.IncRow(-1);
+        rDoc.setTableOpCells(aScRange, aParam);
     }
-    catch( Exception& )
+    else
     {
+        // One-variable column input cell (vertical).
+        aParam.meMode = ScTabOpParam::Column;
+        aParam.aRefColCell.Set(aRef1.Column, aRef1.Row, aRef1.Sheet, false, false, false);
+        aParam.aRefFormulaCell.Set(rRange.StartColumn, rRange.StartRow-1, nSheet, true, false, false);
+        aParam.aRefFormulaEnd = aParam.aRefFormulaCell;
+        aScRange.aStart.IncCol(-1);
+        rDoc.setTableOpCells(aScRange, aParam);
     }
 }
 


More information about the Libreoffice-commits mailing list