[Libreoffice-commits] .: sc/inc sc/Library_scfilt.mk sc/source

Noel Power noelp at kemper.freedesktop.org
Wed Jun 20 13:01:51 PDT 2012


 sc/Library_scfilt.mk                      |    1 
 sc/inc/autonamecache.hxx                  |    2 
 sc/inc/document.hxx                       |    1 
 sc/source/core/data/document.cxx          |    5 
 sc/source/filter/inc/formulabuffer.hxx    |   99 +++++++++++++
 sc/source/filter/inc/sheetdatabuffer.hxx  |   11 -
 sc/source/filter/inc/sheetdatacontext.hxx |    1 
 sc/source/filter/inc/workbookhelper.hxx   |    5 
 sc/source/filter/inc/worksheethelper.hxx  |    8 +
 sc/source/filter/oox/formulabuffer.cxx    |  224 ++++++++++++++++++++++++++++++
 sc/source/filter/oox/sheetdatacontext.cxx |   25 ++-
 sc/source/filter/oox/workbookfragment.cxx |    7 
 sc/source/filter/oox/workbookhelper.cxx   |   29 +++
 sc/source/filter/oox/worksheethelper.cxx  |   28 +++
 14 files changed, 430 insertions(+), 16 deletions(-)

New commits:
commit 7fff98724bc7e3f4d3defb005aa1358d743d08ed
Author: Noel Power <noel.power at novell.com>
Date:   Wed Jun 20 18:47:22 2012 +0100

    big formula performance improvement for xlsx import (bnc#763168 & bnc#765942)
    
    we get a large performance win by evaluating the formulas at the end of import where we can set up the ScAutoNameCache cache.
    
    Change-Id: Id3763afb805eb9bfa9a6a55e1de3923f02e621ae

diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index d582e22..388686c 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -184,6 +184,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
         sc/source/filter/oox/externallinkfragment \
 	sc/source/filter/oox/extlstcontext \
         sc/source/filter/oox/formulabase \
+        sc/source/filter/oox/formulabuffer \
         sc/source/filter/oox/formulaparser \
         sc/source/filter/oox/numberformatsbuffer \
         sc/source/filter/oox/pagesettings \
diff --git a/sc/inc/autonamecache.hxx b/sc/inc/autonamecache.hxx
index 76804ad..6534a39 100644
--- a/sc/inc/autonamecache.hxx
+++ b/sc/inc/autonamecache.hxx
@@ -42,7 +42,7 @@ typedef ::boost::unordered_map< String, ScAutoNameAddresses, ScStringHashCode, :
 //  (during CompileXML, no document content is changed)
 //
 
-class ScAutoNameCache
+class SC_DLLPUBLIC ScAutoNameCache
 {
     ScAutoNameHashMap   aNames;
     ScDocument*         pDoc;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index b4df35b..a4de4c8 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -883,6 +883,7 @@ public:
     void            CompileXML();
 
     ScAutoNameCache* GetAutoNameCache()     { return pAutoNameCache; }
+    SC_DLLPUBLIC  void             SetAutoNameCache(  ScAutoNameCache* pCache );
 
                     /** Creates a ScLookupCache cache for the range if it
                         doesn't already exist. */
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 475a49f..965f09c 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5740,4 +5740,9 @@ ScNotes* ScDocument::GetNotes(SCTAB nTab)
     return NULL;
 }
 
+void ScDocument::SetAutoNameCache(  ScAutoNameCache* pCache )
+{
+    delete pAutoNameCache;
+    pAutoNameCache = pCache;
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx
new file mode 100644
index 0000000..aabd5ff
--- /dev/null
+++ b/sc/source/filter/inc/formulabuffer.hxx
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2012 LibreOffice contributors.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef OOX_XLS_FORMULABUFFER_HXX
+#define OOX_XLS_FORMULABUFFER_HXX
+
+#include <utility>
+#include "oox/helper/refmap.hxx"
+#include "oox/helper/refvector.hxx"
+#include "workbookhelper.hxx"
+#include <com/sun/star/table/CellAddress.hpp>
+#include <com/sun/star/table/CellRangeAddress.hpp>
+#include <com/sun/star/table/XCellRange.hpp>
+#include <com/sun/star/table/XCell.hpp>
+#include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <map>
+#include <vector>
+#include "worksheethelper.hxx"
+#include "sheetdatabuffer.hxx"
+#include <com/sun/star/sheet/XFormulaTokens.hpp>
+
+namespace oox {
+namespace xls {
+
+class FormulaBuffer : public WorkbookHelper
+{
+private:
+struct SharedFormulaEntry
+{
+    ::com::sun::star::table::CellAddress maAddress;
+    rtl::OUString maTokenStr;
+    sal_Int32 mnSharedId;
+    ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens > mxFormulaTokens;
+    SharedFormulaEntry( const ::com::sun::star::table::CellAddress& rAddress, const rtl::OUString& rTokenStr, sal_Int32 nSharedId ) : maAddress( rAddress ), maTokenStr( rTokenStr ), mnSharedId( nSharedId ) {}
+};
+
+
+struct TokenAddressItem
+{
+    ::rtl::OUString maTokenStr;
+    ::com::sun::star::table::CellAddress maCellAddress;
+    TokenAddressItem( rtl::OUString& rTokenStr, ::com::sun::star::table::CellAddress& rCellAddress ) : maTokenStr( rTokenStr ), maCellAddress( rCellAddress ) {}
+};
+
+struct TokenRangeAddressItem
+{
+    TokenAddressItem maTokenAndAddress;
+    ::com::sun::star::table::CellRangeAddress maCellRangeAddress;
+    TokenRangeAddressItem( TokenAddressItem& rTokenAndAddress, ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {}
+};
+
+typedef ::std::map< sal_Int32, std::vector< TokenAddressItem > > FormulaDataMap;
+typedef ::std::map< sal_Int32, std::vector< TokenRangeAddressItem > > ArrayFormulaDataMap;
+// shared formuala descriptions, the id and address the formula is at
+typedef std::pair< ::com::sun::star::table::CellAddress, sal_Int32 > SharedFormulaDesc;
+// sheet -> list of shared formula descriptions
+typedef ::std::map< sal_Int32, std::vector< SharedFormulaDesc > > SheetToSharedFormulaid;
+// sheet -> stuff needed to create shared formulae
+typedef ::std::map< sal_Int32, std::vector< SharedFormulaEntry > >  SheetToFormulaEntryMap;
+// sharedId -> tokedId
+typedef ::std::map< sal_Int32, sal_Int32 > SharedIdToTokenIndex;
+typedef ::std::map< sal_Int32, SharedIdToTokenIndex > SheetToSharedIdToTokenIndex;
+typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
+typedef ::std::map< sal_Int32, std::vector< ValueAddressPair > > FormulaValueMap;
+
+    void createSharedFormula(  ::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const rtl::OUString& rTokens );
+    ::com::sun::star::uno::Reference< com::sun::star::table::XCellRange > getRange( ::com::sun::star::table::CellRangeAddress& rRange);
+    ::com::sun::star::uno::Reference< com::sun::star::table::XCell > getCell( ::com::sun::star::table::CellAddress& rAddress );
+    com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheet > mxCurrSheet;
+    FormulaDataMap      cellFormulas;
+    ArrayFormulaDataMap cellArrayFormulas;
+    SheetToFormulaEntryMap sharedFormulas;
+    SheetToSharedFormulaid sharedFormulaIds;
+    SheetToSharedIdToTokenIndex tokenIndexes;
+    FormulaValueMap        cellFormulaValues;
+
+    void                applyArrayFormulas(  std::vector< TokenRangeAddressItem >& rVector );
+    void                applyCellFormulas(  std::vector< TokenAddressItem >& rVector );
+    void                applyCellFormulaValues( std::vector< ValueAddressPair >& rVector );
+
+public:
+    explicit            FormulaBuffer( const WorkbookHelper& rHelper );
+    void                finalizeImport();
+    void                setCellFormula( ::com::sun::star::table::CellAddress& rAddress, rtl::OUString&  );
+    void                setCellFormula( ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId );
+    void                setCellFormulaValue( ::com::sun::star::table::CellAddress& rAddress, double fValue  );
+    void                setCellArrayFormula( ::com::sun::star::table::CellRangeAddress& rRangeAddress, ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString&  );
+    void                createSharedFormulaMapEntry(::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokens );
+};
+}
+}
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/sheetdatabuffer.hxx b/sc/source/filter/inc/sheetdatabuffer.hxx
index fdbfa12..c840bc1 100644
--- a/sc/source/filter/inc/sheetdatabuffer.hxx
+++ b/sc/source/filter/inc/sheetdatabuffer.hxx
@@ -156,6 +156,7 @@ private:
 
 // ============================================================================
 
+
 /** Manages the cell contents and cell formatting of a sheet.
  */
 class SheetDataBuffer : public WorksheetHelper
@@ -202,6 +203,7 @@ public:
     void                createSharedFormula(
                             sal_Int32 nSharedId,
                             const ApiTokenSequence& rTokens );
+
     /** Creates a named range with a special name for a shared formula with the
         specified base address and formula definition (BIFF only). */
     void                createSharedFormula(
@@ -216,6 +218,10 @@ public:
     void                setStandardNumFmt(
                             const ::com::sun::star::table::CellAddress& rCellAddr,
                             sal_Int16 nStdNumFmt );
+    /** Processes the cell formatting data of the passed cell.
+        @param nNumFmtId  If set, overrides number format of the cell XF. */
+    void                setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId = -1 );
+
 
     /** Final processing after the sheet has been imported. */
     void                finalizeImport();
@@ -244,10 +250,6 @@ private:
                             const ::com::sun::star::table::CellRangeAddress& rRange,
                             const DataTableModel& rModel ) const;
 
-    /** Processes the cell formatting data of the passed cell.
-        @param nNumFmtId  If set, overrides number format of the cell XF. */
-    void                setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId = -1 );
-
     /** Writes all cell formatting attributes to the passed cell range list. (depreciates writeXfIdRangeProperties) */
     void                writeXfIdRangeListProperties( sal_Int32 nXfId, sal_Int32 nNumFmtId, const ApiCellRangeList& rRanges ) const;
     void                applyCellMerging( const ::com::sun::star::table::CellRangeAddress& rRange );
@@ -261,7 +263,6 @@ private:
     typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, DataTableModel > TableOperation;
     typedef ::std::list< TableOperation > TableOperationList;
 
-    typedef ::std::map< BinAddress, sal_Int32 > SharedFormulaMap;
 
     /** Stores information about a range of rows with equal cell formatting. */
     struct XfIdRowRange
diff --git a/sc/source/filter/inc/sheetdatacontext.hxx b/sc/source/filter/inc/sheetdatacontext.hxx
index 05c8768..8dd16de 100644
--- a/sc/source/filter/inc/sheetdatacontext.hxx
+++ b/sc/source/filter/inc/sheetdatacontext.hxx
@@ -122,6 +122,7 @@ private:
     ::rtl::OUString     maCellValue;        /// Cell value string (OOXML only).
     RichStringRef       mxInlineStr;        /// Inline rich string (OOXML only).
     ApiTokenSequence    maTokens;           /// Formula token array (OOXML only).
+    ::rtl::OUString     maFormulaStr;
     DataTableModel      maTableData;        /// Settings for table operations.
     BinAddress          maCurrPos;          /// Current cell position (BIFF12 only).
     bool                mbHasFormula;       /// True = current cell has formula data (OOXML only).
diff --git a/sc/source/filter/inc/workbookhelper.hxx b/sc/source/filter/inc/workbookhelper.hxx
index c4a4ee1..643d950 100644
--- a/sc/source/filter/inc/workbookhelper.hxx
+++ b/sc/source/filter/inc/workbookhelper.hxx
@@ -54,6 +54,7 @@ namespace com { namespace sun { namespace star {
 namespace oox {
     class AttributeList;
     class SegmentProgressBar;
+    class ISegmentProgressBar;
     class SequenceInputStream;
 }
 
@@ -113,6 +114,7 @@ class UnitConverter;
 class ViewSettings;
 class WorkbookSettings;
 class WorksheetBuffer;
+class FormulaBuffer;
 
 class WorkbookGlobals;
 typedef ::boost::shared_ptr< WorkbookGlobals > WorkbookGlobalsRef;
@@ -144,6 +146,8 @@ public:
     FilterType          getFilterType() const;
     /** Returns the filter progress bar. */
     SegmentProgressBar& getProgressBar() const;
+    ::boost::shared_ptr<oox::ISegmentProgressBar> getFormulaProgressBar() const;
+    void setFormulaProgressBar( ::boost::shared_ptr<oox::ISegmentProgressBar> rBar );
     /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */
     bool                isWorkbookFile() const;
     /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */
@@ -221,6 +225,7 @@ public:
 
     // buffers ----------------------------------------------------------------
 
+    FormulaBuffer&      getFormulaBuffer() const;
     /** Returns the global workbook settings object. */
     WorkbookSettings&   getWorkbookSettings() const;
     /** Returns the workbook and sheet view settings object. */
diff --git a/sc/source/filter/inc/worksheethelper.hxx b/sc/source/filter/inc/worksheethelper.hxx
index 3c994c9..b726230 100644
--- a/sc/source/filter/inc/worksheethelper.hxx
+++ b/sc/source/filter/inc/worksheethelper.hxx
@@ -72,6 +72,8 @@ typedef ::std::map< rtl::OUString, void* >  ExtLst;
 // ============================================================================
 // ============================================================================
 
+typedef ::std::map< BinAddress, sal_Int32 > SharedFormulaMap;
+
 /** An enumeration for all types of sheets in a workbook. */
 enum WorksheetType
 {
@@ -316,6 +318,12 @@ public:
     /** Final conversion after importing the worksheet. */
     void                finalizeWorksheetImport();
 
+    void                setCellFormula( ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString&  );
+    void                setCellFormula( ::com::sun::star::table::CellAddress& rTokenAddress, sal_Int32  );
+    void                setCellArrayFormula( ::com::sun::star::table::CellRangeAddress& rRangeAddress, ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString&  );
+    void                createSharedFormulaMapEntry( ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokens );
+    void                setCellFormulaValue( ::com::sun::star::table::CellAddress& rAddress,
+                            double fValue  );
 private:
     WorksheetGlobals&   mrSheetGlob;
 };
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
new file mode 100644
index 0000000..f93a517
--- /dev/null
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2012 LibreOffice contributors.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "formulabuffer.hxx"
+#include "formulaparser.hxx"
+#include <com/sun/star/sheet/XFormulaTokens.hpp>
+#include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/table/XCell2.hpp>
+#include "cell.hxx"
+#include "document.hxx"
+#include "convuno.hxx"
+
+#include "rangelst.hxx"
+#include "autonamecache.hxx"
+
+namespace oox {
+namespace xls {
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::sheet;
+using namespace ::com::sun::star::container;
+
+FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
+{
+}
+
+Reference< XCellRange > FormulaBuffer::getRange( CellRangeAddress& rRange)
+{
+    Reference< XCellRange > xRange;
+    try
+    {
+        xRange = mxCurrSheet->getCellRangeByPosition( rRange.StartColumn, rRange.StartRow, rRange.EndColumn, rRange.EndRow );
+    }
+    catch( Exception& )
+    {
+    }
+    return xRange;
+}
+
+Reference< XCell > FormulaBuffer::getCell( CellAddress& rAddress )
+{
+    Reference< XCell > xCell;
+    try
+    {
+        xCell = mxCurrSheet->getCellByPosition( rAddress.Column, rAddress.Row );
+    }
+    catch( Exception& )
+    {
+    }
+    return xCell;
+}
+
+void FormulaBuffer::finalizeImport()
+{
+    ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
+
+    ScDocument& rDoc = getScDocument();
+    Reference< XIndexAccess > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW );
+    rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
+    for ( sal_Int16 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
+    {
+        double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
+        xFormulaBar->setPosition( fPosition );
+        mxCurrSheet = getSheetFromDoc( nTab );
+        // process shared Formula
+        SheetToFormulaEntryMap::iterator sharedIt = sharedFormulas.find( nTab );
+        if ( sharedIt != sharedFormulas.end() )
+        {
+            // shared id ( to create the special shared names from )
+            std::vector<SharedFormulaEntry>& rSharedFormulas = sharedIt->second;
+            for ( std::vector<SharedFormulaEntry>::iterator it = rSharedFormulas.begin(), it_end = rSharedFormulas.end(); it != it_end; ++it )
+            {
+                 createSharedFormula( it->maAddress, it->mnSharedId, it->maTokenStr );
+            }
+        }
+        // now process any defined shared formulae
+        SheetToSharedFormulaid::iterator formulDescIt = sharedFormulaIds.find( nTab );
+        SheetToSharedIdToTokenIndex::iterator tokensIt = tokenIndexes.find( nTab );
+        if ( formulDescIt != sharedFormulaIds.end() && tokensIt !=  tokenIndexes.end() )
+        {
+            SharedIdToTokenIndex& rTokenIdMap = tokensIt->second;
+            std::vector< SharedFormulaDesc >& rVector = formulDescIt->second;
+            for ( std::vector< SharedFormulaDesc >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
+            {
+                // see if we have a
+                // resolved tokenId
+                CellAddress& rAddress = it->first;
+                sal_Int32& rnSharedId = it->second;
+                SharedIdToTokenIndex::iterator itTokenId =  rTokenIdMap.find( rnSharedId );
+                if ( itTokenId != rTokenIdMap.end() )
+                {
+                    ApiTokenSequence aTokens =  getFormulaParser().convertNameToFormula( itTokenId->second );
+                    Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY );
+                    OSL_ENSURE( xTokens.is(), "FormulaBuffer::finalizeImport - missing token interface" );
+                    if( xTokens.is() ) xTokens->setTokens( aTokens );
+
+                }
+            }
+        }
+
+        FormulaDataMap::iterator cellIt = cellFormulas.find( nTab );
+        if ( cellIt != cellFormulas.end() )
+        {
+            applyCellFormulas( cellIt->second );
+        }
+
+        FormulaValueMap::iterator itValues = cellFormulaValues.find( nTab );
+        if ( itValues != cellFormulaValues.end() )
+        {
+            std::vector< ValueAddressPair > & rVector = itValues->second;
+            applyCellFormulaValues( rVector );
+        }
+
+        ArrayFormulaDataMap::iterator itArray = cellArrayFormulas.find( nTab );
+
+        if ( itArray != cellArrayFormulas.end() )
+        {
+            applyArrayFormulas( itArray->second );
+        }
+    }
+    rDoc.SetAutoNameCache( NULL );
+    xFormulaBar->setPosition( 1.0 );
+}
+
+void FormulaBuffer::applyCellFormulas( std::vector< TokenAddressItem >& rVector )
+{
+    for ( std::vector< TokenAddressItem >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
+    {
+        ::com::sun::star::table::CellAddress& rAddress = it->maCellAddress;
+        ApiTokenSequence rTokens = getFormulaParser().importFormula( rAddress, it->maTokenStr );
+
+        Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY );
+        OSL_ENSURE( xTokens.is(), "WorksheetHelper::putFormulaTokens - missing token interface" );
+        if( xTokens.is() ) xTokens->setTokens( rTokens );
+    }
+}
+
+void FormulaBuffer::applyCellFormulaValues( std::vector< ValueAddressPair >& rVector )
+{
+    for ( std::vector< ValueAddressPair >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
+    {
+        ScDocument& rDoc = getScDocument();
+        ScAddress aCellPos;
+        ScUnoConversion::FillScAddress( aCellPos, it->first );
+        ScBaseCell* pBaseCell = rDoc.GetCell( aCellPos );
+        if ( pBaseCell->GetCellType() == CELLTYPE_FORMULA )
+        {
+            ScFormulaCell* pCell = static_cast< ScFormulaCell* >( pBaseCell );
+            pCell->SetHybridDouble( it->second );
+            pCell->ResetDirty();
+            pCell->ResetChanged();
+        }
+    }
+}
+
+void FormulaBuffer::applyArrayFormulas( std::vector< TokenRangeAddressItem >& rVector )
+{
+    for ( std::vector< TokenRangeAddressItem >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
+    {
+        Reference< XArrayFormulaTokens > xTokens( getRange( it->maCellRangeAddress ), UNO_QUERY );
+        OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
+        ApiTokenSequence rTokens = getFormulaParser().importFormula( it->maTokenAndAddress.maCellAddress, it->maTokenAndAddress.maTokenStr );
+        if( xTokens.is() )
+            xTokens->setArrayTokens( rTokens );
+    }
+}
+
+void FormulaBuffer::createSharedFormulaMapEntry(::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokens )
+{
+     std::vector<SharedFormulaEntry>& rSharedFormulas = sharedFormulas[ rAddress.Sheet ];
+    SharedFormulaEntry aEntry( rAddress, rTokens, nSharedId );
+    rSharedFormulas.push_back( aEntry );
+}
+
+void FormulaBuffer::setCellFormula( ::com::sun::star::table::CellAddress& rAddress, rtl::OUString& rTokenStr )
+{
+    cellFormulas[ rAddress.Sheet ].push_back( TokenAddressItem( rTokenStr, rAddress ) );
+}
+
+void FormulaBuffer::setCellFormula( ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId )
+{
+    sharedFormulaIds[ rAddress.Sheet ].push_back( SharedFormulaDesc( rAddress, nSharedId ) );
+}
+
+void FormulaBuffer::setCellArrayFormula( ::com::sun::star::table::CellRangeAddress& rRangeAddress, ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString& rTokenStr )
+{
+
+    TokenAddressItem tokenPair( rTokenStr, rTokenAddress );
+    cellArrayFormulas[ rRangeAddress.Sheet ].push_back( TokenRangeAddressItem( tokenPair, rRangeAddress ) );
+}
+
+void FormulaBuffer::setCellFormulaValue( ::com::sun::star::table::CellAddress& rAddress, double fValue )
+{
+    cellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) );
+}
+
+void  FormulaBuffer::createSharedFormula(::com::sun::star::table::CellAddress& rAddress,  sal_Int32 nSharedId, const rtl::OUString& rTokenStr )
+{
+    ApiTokenSequence rTokens = getFormulaParser().importFormula( rAddress, rTokenStr );
+    rtl::OUString aName = rtl::OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
+        append( static_cast< sal_Int32 >( rAddress.Sheet + 1 ) ).
+        append( sal_Unicode( '_' ) ).append( nSharedId ).
+        append( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_0") ) ).makeStringAndClear();
+    ScRangeData* pScRangeData  = createNamedRangeObject( aName, rTokens, 0  );
+
+    pScRangeData->SetType(RT_SHARED);
+    sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
+
+        // store the token index in the map
+   tokenIndexes[  rAddress.Sheet ][ nSharedId ] = nTokenIndex;
+}
+} // namespace xls
+} // namespace oox
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx
index 266eb47..28fcc00 100644
--- a/sc/source/filter/oox/sheetdatacontext.cxx
+++ b/sc/source/filter/oox/sheetdatacontext.cxx
@@ -165,7 +165,8 @@ void SheetDataContext::onCharacters( const OUString& rChars )
         case XLS_TOKEN( f ):
             if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID )
             {
-                maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars );
+//                maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars );
+                  maFormulaStr = rChars;
             }
         break;
     }
@@ -178,15 +179,25 @@ void SheetDataContext::onEndElement()
         // try to create a formula cell
         if( mbHasFormula ) switch( maFmlaData.mnFormulaType )
         {
+            // will buffer formulas but need to
+            // a) need to set format first
+            // :/
             case XML_normal:
-                mrSheetData.setFormulaCell( maCellData, maTokens );
+                //mrSheetData.setFormulaCell( maCellData, maTokens );
+                setCellFormula( maCellData.maCellAddr, maFormulaStr );
+                mrSheetData.setCellFormat( maCellData );
                 break;
             case XML_shared:
                 if( maFmlaData.mnSharedId >= 0 )
                 {
                     if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
-                        mrSheetData.createSharedFormula( maFmlaData.mnSharedId, maTokens );
-                    mrSheetData.setFormulaCell( maCellData, maFmlaData.mnSharedId );
+                    {
+                        //mrSheetData.createSharedFormula( maFmlaData.mnSharedId, mrFormulaParser.importFormula( maCellData.maCellAddr, maFormulaStr ) );
+                        createSharedFormulaMapEntry( maCellData.maCellAddr, maFmlaData.mnSharedId, maFormulaStr );
+                    }
+                    //mrSheetData.setFormulaCell( maCellData, maFmlaData.mnSharedId );
+                    setCellFormula( maCellData.maCellAddr, maFmlaData.mnSharedId );
+                    mrSheetData.setCellFormat( maCellData );
                 }
                 else
                     // no success, set plain cell value and formatting below
@@ -194,7 +205,8 @@ void SheetDataContext::onEndElement()
             break;
             case XML_array:
                 if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
-                    mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens );
+                    //mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens );
+                    setCellArrayFormula( maFmlaData.maFormulaRef, maCellData.maCellAddr, maFormulaStr );
                 // set cell formatting, but do not set result as cell value
                 mrSheetData.setBlankCell( maCellData );
             break;
@@ -246,7 +258,7 @@ void SheetDataContext::onEndElement()
         {
             case XML_n:
                 /* Set the pre-loaded value */
-                mrSheetData.putFormulaResult( maCellData.maCellAddr, maCellValue.toDouble() );
+                setCellFormulaValue( maCellData.maCellAddr, maCellValue.toDouble() );
                 break;
         }
     }
@@ -369,6 +381,7 @@ void SheetDataContext::importFormula( const AttributeList& rAttribs )
 
     // clear token array, will be regenerated from element text
     maTokens = ApiTokenSequence();
+    maFormulaStr = rtl::OUString();
 }
 
 void SheetDataContext::importRow( SequenceInputStream& rStrm )
diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index 2ef185d..843a7fe 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -222,6 +222,7 @@ void WorkbookFragment::finalizeImport()
         importOoxFragment( new ConnectionsFragment( *this, aConnFragmentPath ) );
     xGlobalSegment->setPosition( 1.0 );
 
+
     /*  Create fragments for all sheets, before importing them. Needed to do
         some preprocessing in the fragment constructors, e.g. loading the table
         fragments for all sheets that are needed before the cell formulas are
@@ -243,7 +244,9 @@ void WorkbookFragment::finalizeImport()
             OSL_ENSURE( !aFragmentPath.isEmpty(), "WorkbookFragment::finalizeImport - cannot access sheet fragment" );
             if( !aFragmentPath.isEmpty() )
             {
-                double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - nWorksheet);
+                // leave space for formula processing ( calcuate the segments as
+                // if there is an extra sheet )
+                double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - ( nWorksheet - 1) );
                 ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength );
 
                 // get the sheet type according to the relations type
@@ -293,7 +296,7 @@ void WorkbookFragment::finalizeImport()
     // create all defined names and database ranges
     getDefinedNames().finalizeImport();
     getTables().finalizeImport();
-
+    int nSheetNum = 0;
     // load all worksheets
     for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt )
     {
diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx
index 1110ebc..891573f 100644
--- a/sc/source/filter/oox/workbookhelper.cxx
+++ b/sc/source/filter/oox/workbookhelper.cxx
@@ -77,6 +77,7 @@
 #include "tokenarray.hxx"
 #include "tokenuno.hxx"
 
+#include "formulabuffer.hxx"
 namespace oox {
 namespace xls {
 
@@ -123,6 +124,9 @@ public:
     inline FilterBase&  getBaseFilter() const { return mrBaseFilter; }
     /** Returns the filter progress bar. */
     inline SegmentProgressBar& getProgressBar() const { return *mxProgressBar; }
+    /** Returns the formula progress bar. */
+    inline ISegmentProgressBarRef getFormulaProgressBar() const { return mxFormulaProgressBar; }
+    inline void setFormulaProgressBar( ISegmentProgressBarRef rBar ) {  mxFormulaProgressBar = rBar; }
     /** Returns the file type of the current filter. */
     inline FilterType   getFilterType() const { return meFilterType; }
     /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */
@@ -177,6 +181,7 @@ public:
 
     // buffers ----------------------------------------------------------------
 
+    inline FormulaBuffer& getFormulaBuffer() const { return *mxFormulaBuffer; }
     /** Returns the global workbook settings object. */
     inline WorkbookSettings& getWorkbookSettings() const { return *mxWorkbookSettings; }
     /** Returns the workbook and sheet view settings object. */
@@ -238,6 +243,7 @@ private:
     void                finalize();
 
 private:
+    typedef ::std::auto_ptr< FormulaBuffer >            FormulaBufferPtr;
     typedef ::std::auto_ptr< SegmentProgressBar >       ProgressBarPtr;
     typedef ::std::auto_ptr< WorkbookSettings >         WorkbookSettPtr;
     typedef ::std::auto_ptr< ViewSettings >             ViewSettingsPtr;
@@ -268,11 +274,13 @@ private:
     ExcelFilterBase&    mrExcelBase;            /// Base object for registration of this structure.
     FilterType          meFilterType;           /// File type of the filter.
     ProgressBarPtr      mxProgressBar;          /// The progress bar.
+    ISegmentProgressBarRef mxFormulaProgressBar;/// The progress bar for end of import formula processing
     StorageRef          mxVbaPrjStrg;           /// Storage containing the VBA project.
     sal_Int16           mnCurrSheet;            /// Current sheet index in Calc document.
     bool                mbWorkbook;             /// True = multi-sheet file.
 
     // buffers
+    FormulaBufferPtr    mxFormulaBuffer;
     WorkbookSettPtr     mxWorkbookSettings;     /// Global workbook settings.
     ViewSettingsPtr     mxViewSettings;         /// Workbook and sheet view settings.
     WorksheetBfrPtr     mxWorksheets;           /// Sheet info buffer.
@@ -509,6 +517,7 @@ void WorkbookGlobals::initialize( bool bWorkbookFile )
     mxDoc.set( mrBaseFilter.getModel(), UNO_QUERY );
     OSL_ENSURE( mxDoc.is(), "WorkbookGlobals::initialize - no spreadsheet document" );
 
+    mxFormulaBuffer.reset( new FormulaBuffer( *this ) );
     mxWorkbookSettings.reset( new WorkbookSettings( *this ) );
     mxViewSettings.reset( new ViewSettings( *this ) );
     mxWorksheets.reset( new WorksheetBuffer( *this ) );
@@ -554,7 +563,7 @@ void WorkbookGlobals::initialize( bool bWorkbookFile )
         //! TODO: localize progress bar text
         mxProgressBar.reset( new SegmentProgressBar( mrBaseFilter.getStatusIndicator(), CREATE_OUSTRING( "Saving..." ) ) );
     }
-
+//    mxFormulaProgressBar =  mxProgressBar->createSegment( 0.4 );
     // filter specific
     switch( getFilterType() )
     {
@@ -586,6 +595,9 @@ void WorkbookGlobals::finalize()
         aPropSet.setProperty( PROP_IsExecuteLinkEnabled, true );
         // #i79826# enable updating automatic row height after loading the document
         aPropSet.setProperty( PROP_IsAdjustHeightEnabled, true );
+        getFormulaBuffer().finalizeImport();
+        // hack, setting it true the second time will delete the cache
+        aPropSet.setProperty( PROP_IsAdjustHeightEnabled, true );
         // #i76026# enable Undo after loading the document
         aPropSet.setProperty( PROP_IsUndoEnabled, true );
         // disable editing read-only documents (e.g. from read-only files)
@@ -626,6 +638,16 @@ SegmentProgressBar& WorkbookHelper::getProgressBar() const
     return mrBookGlob.getProgressBar();
 }
 
+ISegmentProgressBarRef WorkbookHelper::getFormulaProgressBar() const
+{
+    return mrBookGlob.getFormulaProgressBar();
+}
+
+void WorkbookHelper::setFormulaProgressBar(ISegmentProgressBarRef rFormBar )
+{
+    return mrBookGlob.setFormulaProgressBar( rFormBar );
+}
+
 bool WorkbookHelper::isWorkbookFile() const
 {
     return mrBookGlob.isWorkbookFile();
@@ -766,6 +788,11 @@ Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bo
 
 // buffers --------------------------------------------------------------------
 
+FormulaBuffer& WorkbookHelper::getFormulaBuffer() const
+{
+    return mrBookGlob.getFormulaBuffer();
+}
+
 WorkbookSettings& WorkbookHelper::getWorkbookSettings() const
 {
     return mrBookGlob.getWorkbookSettings();
diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx
index cfd9695..e20efb4 100644
--- a/sc/source/filter/oox/worksheethelper.cxx
+++ b/sc/source/filter/oox/worksheethelper.cxx
@@ -48,7 +48,6 @@
 #include <com/sun/star/sheet/XSheetOutline.hpp>
 #include <com/sun/star/sheet/XSpreadsheet.hpp>
 #include <com/sun/star/table/XColumnRowRange.hpp>
-#include <com/sun/star/table/XCell2.hpp>
 #include <com/sun/star/text/WritingMode2.hpp>
 #include <com/sun/star/text/XText.hpp>
 #include <rtl/ustrbuf.hxx>
@@ -75,6 +74,7 @@
 #include "workbooksettings.hxx"
 #include "worksheetbuffer.hxx"
 #include "worksheetsettings.hxx"
+#include "formulabuffer.hxx"
 
 namespace oox {
 namespace xls {
@@ -1549,6 +1549,12 @@ void WorksheetHelper::putFormulaResult( const CellAddress& rAddress, double fVal
     }
 }
 
+void WorksheetHelper::setCellFormulaValue( ::com::sun::star::table::CellAddress& rAddress,
+                            double fValue  )
+{
+    getFormulaBuffer().setCellFormulaValue( rAddress, fValue );
+}
+
 void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) const
 {
     ScAddress aAddress;
@@ -1587,6 +1593,26 @@ void WorksheetHelper::finalizeWorksheetImport()
     mrSheetGlob.finalizeWorksheetImport();
 }
 
+void WorksheetHelper::setCellFormula( ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString& rTokenStr )
+{
+    getFormulaBuffer().setCellFormula( rTokenAddress,  rTokenStr );
+}
+
+void WorksheetHelper::setCellFormula( ::com::sun::star::table::CellAddress& rTokenAddress, sal_Int32 nSharedId )
+{
+    getFormulaBuffer().setCellFormula( rTokenAddress,  nSharedId );
+}
+
+void WorksheetHelper::setCellArrayFormula( ::com::sun::star::table::CellRangeAddress& rRangeAddress, ::com::sun::star::table::CellAddress& rTokenAddress, rtl::OUString& rTokenStr )
+{
+    getFormulaBuffer().setCellArrayFormula( rRangeAddress,  rTokenAddress, rTokenStr );
+}
+
+void WorksheetHelper::createSharedFormulaMapEntry(  ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokens )
+{
+    getFormulaBuffer().createSharedFormulaMapEntry( rAddress, nSharedId, rTokens );
+}
+
 // ============================================================================
 // ============================================================================
 


More information about the Libreoffice-commits mailing list