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
This commit is contained in:
@@ -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 \
|
||||
|
@@ -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;
|
||||
|
@@ -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. */
|
||||
|
@@ -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: */
|
||||
|
99
sc/source/filter/inc/formulabuffer.hxx
Normal file
99
sc/source/filter/inc/formulabuffer.hxx
Normal file
@@ -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: */
|
@@ -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
|
||||
|
@@ -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).
|
||||
|
@@ -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. */
|
||||
|
@@ -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;
|
||||
};
|
||||
|
224
sc/source/filter/oox/formulabuffer.cxx
Normal file
224
sc/source/filter/oox/formulabuffer.cxx
Normal file
@@ -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: */
|
@@ -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 )
|
||||
|
@@ -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 )
|
||||
{
|
||||
|
@@ -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();
|
||||
|
@@ -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 );
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ============================================================================
|
||||
|
||||
|
Reference in New Issue
Block a user