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:
Noel Power
2012-06-20 18:47:22 +01:00
parent 0e73f3cbe1
commit 7fff98724b
14 changed files with 430 additions and 16 deletions

View File

@@ -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 \

View File

@@ -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;

View File

@@ -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. */

View File

@@ -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: */

View 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: */

View File

@@ -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

View File

@@ -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).

View File

@@ -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. */

View File

@@ -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;
};

View 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: */

View File

@@ -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 )

View File

@@ -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 )
{

View File

@@ -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();

View File

@@ -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 );
}
// ============================================================================
// ============================================================================