summaryrefslogtreecommitdiffstats
path: root/sc
diff options
context:
space:
mode:
authorNoel Power <noel.power@novell.com>2012-06-20 18:47:22 +0100
committerNoel Power <noel.power@novell.com>2012-06-20 21:01:13 +0100
commit7fff98724bc7e3f4d3defb005aa1358d743d08ed (patch)
tree2d1a257107b3f560cc06035dc1cef8c1c19fd37c /sc
parentmove ScNamedEntryArr_Impl out of header to make MSVC happy (diff)
downloadcore-7fff98724bc7e3f4d3defb005aa1358d743d08ed.tar.gz
core-7fff98724bc7e3f4d3defb005aa1358d743d08ed.zip
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
Diffstat (limited to 'sc')
-rw-r--r--sc/Library_scfilt.mk1
-rw-r--r--sc/inc/autonamecache.hxx2
-rw-r--r--sc/inc/document.hxx1
-rw-r--r--sc/source/core/data/document.cxx5
-rw-r--r--sc/source/filter/inc/formulabuffer.hxx99
-rw-r--r--sc/source/filter/inc/sheetdatabuffer.hxx11
-rw-r--r--sc/source/filter/inc/sheetdatacontext.hxx1
-rw-r--r--sc/source/filter/inc/workbookhelper.hxx5
-rw-r--r--sc/source/filter/inc/worksheethelper.hxx8
-rw-r--r--sc/source/filter/oox/formulabuffer.cxx224
-rw-r--r--sc/source/filter/oox/sheetdatacontext.cxx25
-rw-r--r--sc/source/filter/oox/workbookfragment.cxx7
-rw-r--r--sc/source/filter/oox/workbookhelper.cxx29
-rw-r--r--sc/source/filter/oox/worksheethelper.cxx28
14 files changed, 430 insertions, 16 deletions
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index d582e2210643..388686ca4c74 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 76804adc1361..6534a3917fff 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 b4df35bac059..a4de4c8341da 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 475a49f47700..965f09c544db 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 000000000000..aabd5ff4cf89
--- /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 fdbfa12d3f61..c840bc17f33a 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 05c876865c77..8dd16decb129 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 c4a4ee19b0aa..643d95000cf8 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 3c994c96dc67..b726230cee5e 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 000000000000..f93a51722817
--- /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 266eb470c5ee..28fcc00068c2 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 2ef185d0f921..843a7feadd4e 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 1110ebc9a17e..891573f80aa7 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 cfd9695f8c4a..e20efb44d5b7 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 );
+}
+
// ============================================================================
// ============================================================================