summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Rentz [dr] <daniel.rentz@oracle.com>2011-02-11 16:11:43 +0100
committerDaniel Rentz [dr] <daniel.rentz@oracle.com>2011-02-11 16:11:43 +0100
commitf042519085109581abcdff4403e7e6d9999d4980 (patch)
treed3f22e98804fa22c88b62d7ea42553a32df09230
parentaec1b58b2f959770f072778ec187ae89f6053b76 (diff)
dr78: #164376# oox import performance: step 2 - move every access to XCell interface into SheetDataBuffer class, delay creation of array formulas and table operations, let XCellRangeData::setDataArray() accept formula token sequences in addition to plain values
-rw-r--r--oox/inc/oox/xls/defnamesbuffer.hxx6
-rwxr-xr-xoox/inc/oox/xls/sheetdatabuffer.hxx133
-rw-r--r--oox/inc/oox/xls/sheetdatacontext.hxx84
-rw-r--r--oox/inc/oox/xls/worksheethelper.hxx47
-rw-r--r--oox/source/xls/defnamesbuffer.cxx22
-rw-r--r--oox/source/xls/externallinkbuffer.cxx5
-rw-r--r--oox/source/xls/pivotcachebuffer.cxx18
-rwxr-xr-xoox/source/xls/sheetdatabuffer.cxx410
-rw-r--r--oox/source/xls/sheetdatacontext.cxx789
-rw-r--r--oox/source/xls/worksheethelper.cxx43
10 files changed, 771 insertions, 786 deletions
diff --git a/oox/inc/oox/xls/defnamesbuffer.hxx b/oox/inc/oox/xls/defnamesbuffer.hxx
index 27f9f13f6e87..f26a51a1f04c 100644
--- a/oox/inc/oox/xls/defnamesbuffer.hxx
+++ b/oox/inc/oox/xls/defnamesbuffer.hxx
@@ -94,11 +94,11 @@ public:
protected:
/** Converts the OOXML formula string stored in the own model. */
- ApiTokenSequence importOoxFormula( const ::com::sun::star::table::CellAddress& rBaseAddr );
+ ApiTokenSequence importOoxFormula( sal_Int16 nBaseSheet );
/** Imports the BIFF12 formula from the passed stream. */
- ApiTokenSequence importBiff12Formula( const ::com::sun::star::table::CellAddress& rBaseAddr, SequenceInputStream& rStrm );
+ ApiTokenSequence importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm );
/** Imports the BIFF formula from the passed stream. */
- ApiTokenSequence importBiffFormula( const ::com::sun::star::table::CellAddress& rBaseAddr, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 );
+ ApiTokenSequence importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 );
/** Tries to convert the passed token sequence to a SingleReference or ComplexReference. */
void extractReference( const ApiTokenSequence& rTokens );
diff --git a/oox/inc/oox/xls/sheetdatabuffer.hxx b/oox/inc/oox/xls/sheetdatabuffer.hxx
index 52b71b4f0ef9..878d225ff81f 100755
--- a/oox/inc/oox/xls/sheetdatabuffer.hxx
+++ b/oox/inc/oox/xls/sheetdatabuffer.hxx
@@ -42,6 +42,53 @@ namespace xls {
// ============================================================================
+/** Stores basic data about cell values and formatting. */
+struct CellModel
+{
+ ::com::sun::star::table::CellAddress
+ maCellAddr; /// The address of the current cell.
+ sal_Int32 mnCellType; /// Data type of the cell value.
+ sal_Int32 mnXfId; /// XF (cell formatting) identifier.
+ bool mbShowPhonetic; /// True = show phonetic text.
+
+ explicit CellModel();
+};
+
+// ----------------------------------------------------------------------------
+
+/** Stores data about cell formulas. */
+struct CellFormulaModel
+{
+ ::com::sun::star::table::CellRangeAddress
+ maFormulaRef; /// Formula range for array/shared formulas and data tables.
+ sal_Int32 mnFormulaType; /// Type of the formula (regular, array, shared, table).
+ sal_Int32 mnSharedId; /// Identifier of a shared formula (OOXML only).
+
+ explicit CellFormulaModel();
+
+ /** Returns true, if the passed cell address is valid for an array formula. */
+ bool isValidArrayRef( const ::com::sun::star::table::CellAddress& rCellAddr );
+ /** Returns true, if the passed cell address is valid for a shared formula. */
+ bool isValidSharedRef( const ::com::sun::star::table::CellAddress& rCellAddr );
+};
+
+// ----------------------------------------------------------------------------
+
+/** Stores data about table operations. */
+struct DataTableModel
+{
+ ::rtl::OUString maRef1; /// First reference cell for table operations.
+ ::rtl::OUString maRef2; /// Second reference cell for table operations.
+ bool mb2dTable; /// True = 2-dimensional data table.
+ bool mbRowTable; /// True = row oriented data table.
+ bool mbRef1Deleted; /// True = first reference cell deleted.
+ bool mbRef2Deleted; /// True = second reference cell deleted.
+
+ explicit DataTableModel();
+};
+
+// ============================================================================
+
/** Manages the cell contents and cell formatting of a sheet.
*/
class SheetDataBuffer : public WorksheetHelper
@@ -49,81 +96,71 @@ class SheetDataBuffer : public WorksheetHelper
public:
explicit SheetDataBuffer( const WorksheetHelper& rHelper );
- /** Imports a shared formula from a OOXML formula string. */
- void importSharedFmla( const ::rtl::OUString& rFormula,
- const ::rtl::OUString& rSharedRange, sal_Int32 nSharedId,
- const ::com::sun::star::table::CellAddress& rBaseAddr );
- /** Imports a shared formula from a SHAREDFORMULA record in the passed stream */
- void importSharedFmla( SequenceInputStream& rStrm,
- const ::com::sun::star::table::CellAddress& rBaseAddr );
- /** Imports a shared formula from a SHAREDFMLA record in the passed stream. */
- void importSharedFmla( BiffInputStream& rStrm,
- const ::com::sun::star::table::CellAddress& rBaseAddr );
-
/** Sets the passed value to the cell. */
void setValueCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
double fValue );
/** Sets the passed string to the cell. */
void setStringCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
const ::rtl::OUString& rText );
/** Sets the passed rich-string to the cell. */
void setStringCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
const RichString& rString, sal_Int32 nXfId );
/** Sets the shared string with the passed identifier to the cell. */
void setStringCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
sal_Int32 nStringId, sal_Int32 nXfId );
/** Sets the passed date/time value to the cell and adjusts number format. */
void setDateTimeCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
const ::com::sun::star::util::DateTime& rDateTime );
/** Sets the passed boolean value to the cell and adjusts number format. */
void setBooleanCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
bool bValue );
/** Sets the passed BIFF error code to the cell (by converting it to a formula). */
void setErrorCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
const ::rtl::OUString& rErrorCode );
/** Sets the passed BIFF error code to the cell (by converting it to a formula). */
void setErrorCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
sal_uInt8 nErrorCode );
/** Sets the passed formula token sequence to the cell. */
void setFormulaCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
const ApiTokenSequence& rTokens );
/** Sets the shared formula with the passed identifier to the cell (OOXML only). */
void setFormulaCell(
- const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell,
const ::com::sun::star::table::CellAddress& rCellAddr,
sal_Int32 nSharedId );
/** Inserts the passed token array as array formula. */
- void setArrayFormula(
+ void createArrayFormula(
const ::com::sun::star::table::CellRangeAddress& rRange,
const ApiTokenSequence& rTokens );
/** Sets a multiple table operation to the passed range. */
- void setTableOperation(
+ void createTableOperation(
const ::com::sun::star::table::CellRangeAddress& rRange,
const DataTableModel& rModel );
+ /** Creates a named range with a special name for a shared formula with the
+ specified identifier and formula definition (OOXML only). */
+ 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(
+ const ::com::sun::star::table::CellAddress& rCellAddr,
+ const ApiTokenSequence& rTokens );
/** Sets default cell formatting for the specified range of rows. */
void setRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId, bool bCustomFormat );
- /** Processes the cell formatting data of the passed cell. */
- void setCellFormat( const CellModel& rModel );
+ /** 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 );
/** Merges the cells in the passed cell range. */
void setMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange );
/** Sets a standard number format (constant from com.sun.star.util.NumberFormat) to the specified cell. */
@@ -138,21 +175,21 @@ private:
struct XfIdRowRange;
struct XfIdRange;
- /** Creates and returns an empty named range with a special name for a
- shared formula with the specified base position. */
- ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XNamedRange >
- createSharedFormulaName( const BinAddress& rMapKey );
+ /** Inserts the passed array formula into the sheet. */
+ void finalizeArrayFormula(
+ const ::com::sun::star::table::CellRangeAddress& rRange,
+ const ApiTokenSequence& rTokens );
+ /** Inserts the passed table operation into the sheet. */
+ void finalizeTableOperation(
+ const ::com::sun::star::table::CellRangeAddress& rRange,
+ const DataTableModel& rModel );
+ /** Creates a named range with a special name for a shared formula with the
+ specified base address and formula definition. */
+ void createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens );
/** Creates a formula token array representing the shared formula with the
- passed identifier (OOXML only). */
- ApiTokenSequence resolveSharedFormula( sal_Int32 nSharedId ) const;
- /** Creates a formula token array representing the shared formula at the
- passed base address. */
- ApiTokenSequence resolveSharedFormula( const ::com::sun::star::table::CellAddress& rBaseAddr ) const;
-
- /** Retries to insert a shared formula that has not been set in the last
- call to setFormulaCell() due to the missing formula definition. */
- void retryPendingSharedFormulaCell();
+ passed identifier. */
+ ApiTokenSequence resolveSharedFormula( const BinAddress& rMapKey ) const;
/** Writes all cell formatting attributes to the passed row range. */
void writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const;
@@ -165,6 +202,9 @@ private:
void finalizeMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange );
private:
+ typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, ApiTokenSequence > ArrayFormula;
+ typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, DataTableModel > TableOperation;
+
struct XfIdRowRange
{
sal_Int32 mnFirstRow; /// Index of first row.
@@ -182,10 +222,10 @@ private:
::com::sun::star::table::CellRangeAddress
maRange; /// The formatted cell range.
sal_Int32 mnXfId; /// XF identifier for the range.
- sal_Int32 mnNumFmtId; /// Number format id overriding the XF.
+ sal_Int32 mnNumFmtId; /// Number format overriding the XF.
- void set( const CellModel& rModel );
- bool tryExpand( const CellModel& rModel );
+ void set( const CellModel& rModel, sal_Int32 nNumFmtId );
+ bool tryExpand( const CellModel& rModel, sal_Int32 nNumFmtId );
bool tryMerge( const XfIdRange& rXfIdRange );
};
@@ -200,15 +240,18 @@ private:
bool tryExpand( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nHorAlign );
};
- typedef ::std::map< BinAddress, sal_Int32 > TokenIndexMap;
+ typedef ::std::list< ArrayFormula > ArrayFormulaList;
+ typedef ::std::list< TableOperation > TableOperationList;
+ typedef ::std::map< BinAddress, sal_Int32 > SharedFormulaMap;
typedef ::std::map< BinAddress, XfIdRange > XfIdRangeMap;
typedef ::std::list< MergedRange > MergedRangeList;
- TokenIndexMap maTokenIndexes; /// Maps shared formula base address to defined name token index.
+ ArrayFormulaList maArrayFormulas; /// All array formulas in the sheet.
+ TableOperationList maTableOperations; /// All table operations in the sheet.
+ SharedFormulaMap maSharedFormulas; /// Maps shared formula base address to defined name token index.
::com::sun::star::table::CellAddress
maSharedFmlaAddr; /// Address of a cell containing a pending shared formula.
- ::com::sun::star::table::CellAddress
- maSharedBaseAddr; /// Base address of the pending shared formula.
+ BinAddress maSharedBaseAddr; /// Base address of the pending shared formula.
XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows.
XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges.
MergedRangeList maMergedRanges; /// Merged cell ranges.
diff --git a/oox/inc/oox/xls/sheetdatacontext.hxx b/oox/inc/oox/xls/sheetdatacontext.hxx
index c01106228c72..60948ab9f70d 100644
--- a/oox/inc/oox/xls/sheetdatacontext.hxx
+++ b/oox/inc/oox/xls/sheetdatacontext.hxx
@@ -30,22 +30,37 @@
#include "oox/xls/excelhandlers.hxx"
#include "oox/xls/richstring.hxx"
-
-namespace com { namespace sun { namespace star {
- namespace table { class XCell; }
-} } }
+#include "oox/xls/sheetdatabuffer.hxx"
namespace oox {
namespace xls {
// ============================================================================
+/** Used as base for sheet data context classes. Provides fast access to often
+ used converter objects and sheet index, to improve performance.
+ */
+struct SheetDataContextBase
+{
+ AddressConverter& mrAddressConv; /// The address converter.
+ FormulaParser& mrFormulaParser; /// The formula parser.
+ SheetDataBuffer& mrSheetData; /// The sheet data buffer for cell content and formatting.
+ CellModel maCellData; /// Position, contents, formatting of current imported cell.
+ CellFormulaModel maFmlaData; /// Settings for a cell formula.
+ sal_Int16 mnSheet; /// Index of the current sheet.
+
+ explicit SheetDataContextBase( const WorksheetHelper& rHelper );
+ virtual ~SheetDataContextBase();
+};
+
+// ============================================================================
+
/** This class implements importing the sheetData element.
The sheetData element contains all row settings and all cells in a single
sheet of a spreadsheet document.
*/
-class SheetDataContext : public WorksheetContextBase
+class SheetDataContext : public WorksheetContextBase, private SheetDataContextBase
{
public:
explicit SheetDataContext( WorksheetFragmentBase& rFragment );
@@ -64,12 +79,20 @@ private:
/** Imports row settings from a row element. */
void importRow( const AttributeList& rAttribs );
/** Imports cell settings from a c element. */
- void importCell( const AttributeList& rAttribs );
+ bool importCell( const AttributeList& rAttribs );
/** Imports cell settings from an f element. */
void importFormula( const AttributeList& rAttribs );
- /** Imports a cell address and the following XF identifier. */
- void importCellHeader( SequenceInputStream& rStrm, CellType eCellType );
+ /** Imports row settings from a ROW record. */
+ void importRow( SequenceInputStream& rStrm );
+
+ /** Reads a cell address and the following XF identifier. */
+ bool readCellHeader( SequenceInputStream& rStrm, CellType eCellType );
+ /** Reads a cell formula for the current cell. */
+ ApiTokenSequence readCellFormula( SequenceInputStream& rStrm );
+ /** Reads the formula range used by shared formulas, arrays, and data tables. */
+ bool readFormulaRef( SequenceInputStream& rStrm );
+
/** Imports an empty cell from a CELL_BLANK or MULTCELL_BLANK record. */
void importCellBlank( SequenceInputStream& rStrm, CellType eCellType );
/** Imports a boolean cell from a CELL_BOOL, MULTCELL_BOOL, or FORMULA_BOOL record. */
@@ -87,31 +110,28 @@ private:
/** Imports a string cell from a CELL_STRING, MULTCELL_STRING, or FORMULA_STRING record. */
void importCellString( SequenceInputStream& rStrm, CellType eCellType );
- /** Imports a cell formula for the current cell. */
- void importCellFormula( SequenceInputStream& rStrm );
-
- /** Imports row settings from a ROW record. */
- void importRow( SequenceInputStream& rStrm );
/** Imports an array formula from an ARRAY record. */
void importArray( SequenceInputStream& rStrm );
- /** Imports a shared formula from a SHAREDFORMULA record. */
- void importSharedFmla( SequenceInputStream& rStrm );
/** Imports table operation from a DATATABLE record. */
void importDataTable( SequenceInputStream& rStrm );
+ /** Imports a shared formula from a SHAREDFORMULA record. */
+ void importSharedFmla( SequenceInputStream& rStrm );
private:
- SheetDataBuffer& mrSheetData; /// The sheet data buffer for cell content and formatting.
- CellModel maCurrCell; /// Position and formatting of current imported cell.
- DataTableModel maTableData; /// Additional data for table operation ranges.
- BinAddress maCurrPos; /// Current position for binary import.
- RichStringRef mxInlineStr; /// Inline rich string from 'is' element.
+ ::rtl::OUString maCellValue; /// Cell value string (OOXML only).
+ RichStringRef mxInlineStr; /// Inline rich string (OOXML only).
+ ApiTokenSequence maTokens; /// Formula token array (OOXML only).
+ DataTableModel maTableData; /// Settings for table operations.
+ BinAddress maCurrPos; /// Current cell position (BIFF12 only).
+ bool mbHasFormula; /// True = current cell has formula data (OOXML only).
+ bool mbValidRange; /// True = maFmlaData.maFormulaRef is valid (OOXML only).
};
// ============================================================================
/** This class implements importing row settings and all cells of a sheet.
*/
-class BiffSheetDataContext : public BiffWorksheetContextBase
+class BiffSheetDataContext : public BiffWorksheetContextBase, private SheetDataContextBase
{
public:
explicit BiffSheetDataContext( const WorksheetHelper& rHelper );
@@ -120,13 +140,15 @@ public:
virtual void importRecord( BiffInputStream& rStrm );
private:
- /** Sets current cell according to the passed address. */
- void setCurrCell( const BinAddress& rAddr );
+ /** Imports row settings from a ROW record. */
+ void importRow( BiffInputStream& rStrm );
- /** Imports an XF identifier and sets the mnXfId member. */
- void importXfId( BiffInputStream& rStrm, bool bBiff2 );
- /** Imports a BIFF cell address and the following XF identifier. */
- void importCellHeader( BiffInputStream& rStrm, bool bBiff2 );
+ /** Reads an XF identifier and initializes a new cell. */
+ bool readCellXfId( const BinAddress& rAddr, BiffInputStream& rStrm, bool bBiff2 );
+ /** Reads a BIFF cell address and the following XF identifier. */
+ bool readCellHeader( BiffInputStream& rStrm, bool bBiff2 );
+ /** Reads the formula range used by shared formulas, arrays, and data tables. */
+ bool readFormulaRef( BiffInputStream& rStrm );
/** Imports a BLANK record describing a blank but formatted cell. */
void importBlank( BiffInputStream& rStrm );
@@ -149,18 +171,14 @@ private:
/** Imports an RK record describing a numeric cell. */
void importRk( BiffInputStream& rStrm );
- /** Imports row settings from a ROW record. */
- void importRow( BiffInputStream& rStrm );
/** Imports an ARRAY record describing an array formula of a cell range. */
void importArray( BiffInputStream& rStrm );
- /** Imports a SHAREDFMLA record describing a shared formula in a cell range. */
- void importSharedFmla( BiffInputStream& rStrm );
/** Imports table operation from a DATATABLE or DATATABLE2 record. */
void importDataTable( BiffInputStream& rStrm );
+ /** Imports a SHAREDFMLA record describing a shared formula in a cell range. */
+ void importSharedFmla( BiffInputStream& rStrm );
private:
- SheetDataBuffer& mrSheetData; /// The sheet data buffer for cell content and formatting.
- CellModel maCurrCell; /// Position and formatting of current imported cell.
sal_uInt32 mnFormulaSkipSize; /// Number of bytes to be ignored in FORMULA record.
sal_uInt32 mnArraySkipSize; /// Number of bytes to be ignored in ARRAY record.
sal_uInt16 mnBiff2XfId; /// Current XF identifier from IXFE record.
diff --git a/oox/inc/oox/xls/worksheethelper.hxx b/oox/inc/oox/xls/worksheethelper.hxx
index fe788be852cb..27754c898608 100644
--- a/oox/inc/oox/xls/worksheethelper.hxx
+++ b/oox/inc/oox/xls/worksheethelper.hxx
@@ -80,42 +80,6 @@ enum WorksheetType
// ============================================================================
-/** Stores some data about a cell. */
-struct CellModel
-{
- ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > mxCell;
- ::com::sun::star::table::CellAddress maAddress;
- ::rtl::OUString maValue; /// String containing cell value data.
- ::rtl::OUString maFormula; /// String containing the formula definition.
- ::rtl::OUString maFormulaRef; /// String containing formula range for array/shared formulas.
- sal_Int32 mnCellType; /// Data type of the cell value.
- sal_Int32 mnFormulaType; /// Type of the formula (regular, array, shared, table).
- sal_Int32 mnSharedId; /// Shared formula identifier.
- sal_Int32 mnXfId; /// XF (cell formatting) identifier.
- sal_Int32 mnNumFmtId; /// Forced number format (overrides XF if set).
- bool mbShowPhonetic; /// True = show phonetic text.
-
- inline explicit CellModel() { reset(); }
- void reset();
-};
-
-// ----------------------------------------------------------------------------
-
-/** Stores data about a data table a.k.a. multiple operation range. */
-struct DataTableModel
-{
- ::rtl::OUString maRef1; /// String containing first reference cell for data table formulas.
- ::rtl::OUString maRef2; /// String containing second reference cell for data table formulas.
- bool mb2dTable; /// True = 2-dimensional data table.
- bool mbRowTable; /// True = row oriented data table.
- bool mbRef1Deleted; /// True = first reference cell deleted.
- bool mbRef2Deleted; /// True = second reference cell deleted.
-
- explicit DataTableModel();
-};
-
-// ----------------------------------------------------------------------------
-
/** Stores formatting data about a range of columns. */
struct ColumnModel
{
@@ -243,17 +207,6 @@ public:
/** Returns the XCell interface for the passed cell address. */
::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >
getCell( const ::com::sun::star::table::CellAddress& rAddress ) const;
- /** Returns the XCell interface for the passed cell address string. */
- ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >
- getCell(
- const ::rtl::OUString& rAddressStr,
- ::com::sun::star::table::CellAddress* opAddress = 0 ) const;
- /** Returns the XCell interface for the passed cell address. */
- ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >
- getCell(
- const BinAddress& rBinAddress,
- ::com::sun::star::table::CellAddress* opAddress = 0 ) const;
-
/** Returns the XCellRange interface for the passed cell range address. */
::com::sun::star::uno::Reference< ::com::sun::star::table::XCellRange >
getCellRange( const ::com::sun::star::table::CellRangeAddress& rRange ) const;
diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx
index 335aae5273af..e69cc44c8a1d 100644
--- a/oox/source/xls/defnamesbuffer.cxx
+++ b/oox/source/xls/defnamesbuffer.cxx
@@ -276,22 +276,22 @@ Any DefinedNameBase::getReference( const CellAddress& rBaseAddr ) const
return Any();
}
-ApiTokenSequence DefinedNameBase::importOoxFormula( const CellAddress& rBaseAddr )
+ApiTokenSequence DefinedNameBase::importOoxFormula( sal_Int16 nBaseSheet )
{
return (maModel.maFormula.getLength() > 0) ?
- getFormulaParser().importFormula( rBaseAddr, maModel.maFormula ) :
+ getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), maModel.maFormula ) :
getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}
-ApiTokenSequence DefinedNameBase::importBiff12Formula( const CellAddress& rBaseAddr, SequenceInputStream& rStrm )
+ApiTokenSequence DefinedNameBase::importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm )
{
- return getFormulaParser().importFormula( rBaseAddr, FORMULATYPE_DEFINEDNAME, rStrm );
+ return getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm );
}
-ApiTokenSequence DefinedNameBase::importBiffFormula( const CellAddress& rBaseAddr, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
+ApiTokenSequence DefinedNameBase::importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize )
{
return (!pnFmlaSize || (*pnFmlaSize > 0)) ?
- getFormulaParser().importFormula( rBaseAddr, FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) :
+ getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) :
getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME );
}
@@ -460,8 +460,7 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcShee
these names contain a simple cell reference or range reference.
Other regular defined names and external names rely on existence of
this reference. */
- CellAddress aBaseAddr( mnCalcSheet, 0, 0 );
- ApiTokenSequence aTokens = importBiffFormula( aBaseAddr, rStrm, &mnFmlaSize );
+ ApiTokenSequence aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
extractReference( aTokens );
}
else
@@ -521,7 +520,6 @@ void DefinedName::convertFormula()
// convert and set formula of the defined name
ApiTokenSequence aTokens;
- CellAddress aBaseAddr( mnCalcSheet, 0, 0 );
switch( getFilterType() )
{
case FILTER_OOXML:
@@ -529,10 +527,10 @@ void DefinedName::convertFormula()
if( mxFormula.get() )
{
SequenceInputStream aStrm( *mxFormula );
- aTokens = importBiff12Formula( aBaseAddr, aStrm );
+ aTokens = importBiff12Formula( mnCalcSheet, aStrm );
}
else
- aTokens = importOoxFormula( aBaseAddr );
+ aTokens = importOoxFormula( mnCalcSheet );
}
break;
case FILTER_BIFF:
@@ -543,7 +541,7 @@ void DefinedName::convertFormula()
BiffInputStream& rStrm = mxBiffStrm->getStream();
BiffInputStreamPosGuard aStrmGuard( rStrm );
if( mxBiffStrm->restorePosition() )
- aTokens = importBiffFormula( aBaseAddr, rStrm, &mnFmlaSize );
+ aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize );
}
}
break;
diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx
index fe527f35f634..aa4d7a068530 100644
--- a/oox/source/xls/externallinkbuffer.cxx
+++ b/oox/source/xls/externallinkbuffer.cxx
@@ -242,8 +242,7 @@ void ExternalName::importExternalName( BiffInputStream& rStrm )
// cell references to other internal sheets are stored in hidden external names
if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() )
{
- CellAddress aBaseAddr( mrParentLink.getCalcSheetIndex(), 0, 0 );
- ApiTokenSequence aTokens = importBiffFormula( aBaseAddr, rStrm );
+ ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm );
extractReference( aTokens );
}
break;
@@ -252,7 +251,7 @@ void ExternalName::importExternalName( BiffInputStream& rStrm )
// cell references to other documents are stored in hidden external names
if( bHiddenRef )
{
- ApiTokenSequence aTokens = importBiffFormula( CellAddress(), rStrm );
+ ApiTokenSequence aTokens = importBiffFormula( 0, rStrm );
extractExternalReference( aTokens );
}
break;
diff --git a/oox/source/xls/pivotcachebuffer.cxx b/oox/source/xls/pivotcachebuffer.cxx
index 88935a679c83..2c4d55b089f1 100644
--- a/oox/source/xls/pivotcachebuffer.cxx
+++ b/oox/source/xls/pivotcachebuffer.cxx
@@ -34,7 +34,6 @@
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp>
#include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp>
-#include <com/sun/star/table/XCell.hpp>
#include <rtl/ustrbuf.hxx>
#include "oox/core/filterbase.hxx"
#include "oox/helper/attributelist.hxx"
@@ -938,7 +937,7 @@ OUString PivotCacheField::createParentGroupField( const Reference< XDataPilotFie
void PivotCacheField::writeSourceHeaderCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const
{
CellAddress aCellAddr( rSheetHelper.getSheetIndex(), nCol, nRow );
- rSheetHelper.getSheetData().setStringCell( rSheetHelper.getCell( aCellAddr ), aCellAddr, maFieldModel.maName );
+ rSheetHelper.getSheetData().setStringCell( aCellAddr, maFieldModel.maName );
}
void PivotCacheField::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const
@@ -986,15 +985,14 @@ void PivotCacheField::writeItemToSourceDataCell( WorksheetHelper& rSheetHelper,
{
CellAddress aCellAddr( rSheetHelper.getSheetIndex(), nCol, nRow );
SheetDataBuffer& rSheetData = rSheetHelper.getSheetData();
- Reference< XCell > xCell = rSheetHelper.getCell( aCellAddr );
- if( xCell.is() ) switch( rItem.getType() )
+ switch( rItem.getType() )
{
- case XML_s: rSheetData.setStringCell( xCell, aCellAddr, rItem.getValue().get< OUString >() ); break;
- case XML_n: rSheetData.setValueCell( xCell, aCellAddr, rItem.getValue().get< double >() ); break;
- case XML_i: rSheetData.setValueCell( xCell, aCellAddr, rItem.getValue().get< sal_Int16 >() ); break;
- case XML_d: rSheetData.setDateTimeCell( xCell, aCellAddr, rItem.getValue().get< DateTime >() ); break;
- case XML_b: rSheetData.setBooleanCell( xCell, aCellAddr, rItem.getValue().get< bool >() ); break;
- case XML_e: rSheetData.setErrorCell( xCell, aCellAddr, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break;
+ case XML_s: rSheetData.setStringCell( aCellAddr, rItem.getValue().get< OUString >() ); break;
+ case XML_n: rSheetData.setValueCell( aCellAddr, rItem.getValue().get< double >() ); break;
+ case XML_i: rSheetData.setValueCell( aCellAddr, rItem.getValue().get< sal_Int16 >() ); break;
+ case XML_d: rSheetData.setDateTimeCell( aCellAddr, rItem.getValue().get< DateTime >() ); break;
+ case XML_b: rSheetData.setBooleanCell( aCellAddr, rItem.getValue().get< bool >() ); break;
+ case XML_e: rSheetData.setErrorCell( aCellAddr, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break;
default: OSL_ENSURE( false, "PivotCacheField::writeItemToSourceDataCell - unexpected item data type" );
}
}
diff --git a/oox/source/xls/sheetdatabuffer.cxx b/oox/source/xls/sheetdatabuffer.cxx
index e63e9fbb61b5..0cfe741cb135 100755
--- a/oox/source/xls/sheetdatabuffer.cxx
+++ b/oox/source/xls/sheetdatabuffer.cxx
@@ -29,6 +29,7 @@
#include <algorithm>
#include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
+#include <com/sun/star/sheet/XCellRangeData.hpp>
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include <com/sun/star/sheet/XMultipleOperation.hpp>
#include <com/sun/star/table/XCell.hpp>
@@ -66,147 +67,116 @@ using ::rtl::OUStringBuffer;
// ============================================================================
-namespace {
-
-bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr )
+CellModel::CellModel() :
+ mnCellType( XML_TOKEN_INVALID ),
+ mnXfId( -1 ),
+ mbShowPhonetic( false )
{
- return
- (rRange.Sheet == rAddr.Sheet) &&
- (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) &&
- (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow);
}
-} // namespace
+// ----------------------------------------------------------------------------
-// ============================================================================
+CellFormulaModel::CellFormulaModel() :
+ mnFormulaType( XML_TOKEN_INVALID ),
+ mnSharedId( -1 )
+{
+}
-SheetDataBuffer::SheetDataBuffer( const WorksheetHelper& rHelper ) :
- WorksheetHelper( rHelper ),
- mbPendingSharedFmla( false )
+bool CellFormulaModel::isValidArrayRef( const CellAddress& rCellAddr )
{
+ return
+ (maFormulaRef.Sheet == rCellAddr.Sheet) &&
+ (maFormulaRef.StartColumn == rCellAddr.Column) &&
+ (maFormulaRef.StartRow == rCellAddr.Row);
}
-void SheetDataBuffer::importSharedFmla( const OUString& rFormula, const OUString& rSharedRange, sal_Int32 nSharedId, const CellAddress& rBaseAddr )
+bool CellFormulaModel::isValidSharedRef( const CellAddress& rCellAddr )
{
- CellRangeAddress aFmlaRange;
- if( getAddressConverter().convertToCellRange( aFmlaRange, rSharedRange, getSheetIndex(), true, true ) ) try
- {
- // get or create the defined name representing the shared formula
- OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SheetDataBuffer::importSharedFmla - invalid range for shared formula" );
- Reference< XNamedRange > xNamedRange = createSharedFormulaName( BinAddress( nSharedId, 0 ) );
- Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW );
- // convert the formula definition
- ApiTokenSequence aTokens = getFormulaParser().importFormula( rBaseAddr, rFormula );
- xTokens->setTokens( aTokens );
- // retry to insert a pending shared formula cell
- retryPendingSharedFormulaCell();
- }
- catch( Exception& )
- {
- }
+ return
+ (maFormulaRef.Sheet == rCellAddr.Sheet) &&
+ (maFormulaRef.StartColumn <= rCellAddr.Column) && (rCellAddr.Column <= maFormulaRef.EndColumn) &&
+ (maFormulaRef.StartRow <= rCellAddr.Row) && (rCellAddr.Row <= maFormulaRef.EndRow);
}
-void SheetDataBuffer::importSharedFmla( SequenceInputStream& rStrm, const CellAddress& rBaseAddr )
+// ----------------------------------------------------------------------------
+
+DataTableModel::DataTableModel() :
+ mb2dTable( false ),
+ mbRowTable( false ),
+ mbRef1Deleted( false ),
+ mbRef2Deleted( false )
{
- BinRange aRange;
- rStrm >> aRange;
- CellRangeAddress aFmlaRange;
- if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true, true ) ) try
- {
- // get or create the defined name representing the shared formula
- OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SheetDataBuffer::importSharedFmla - invalid range for shared formula" );
- Reference< XNamedRange > xNamedRange = createSharedFormulaName( BinAddress( rBaseAddr ) );
- Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW );
- // load the formula definition
- ApiTokenSequence aTokens = getFormulaParser().importFormula( rBaseAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
- xTokens->setTokens( aTokens );
- // retry to insert a pending shared formula cell
- retryPendingSharedFormulaCell();
- }
- catch( Exception& )
- {
- }
}
-void SheetDataBuffer::importSharedFmla( BiffInputStream& rStrm, const CellAddress& rBaseAddr )
+// ============================================================================
+
+SheetDataBuffer::SheetDataBuffer( const WorksheetHelper& rHelper ) :
+ WorksheetHelper( rHelper ),
+ mbPendingSharedFmla( false )
{
- BinRange aRange;
- aRange.read( rStrm, false ); // always 8bit column indexes
- CellRangeAddress aFmlaRange;
- if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true, true ) ) try
- {
- // get or create the defined name representing the shared formula
- OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SheetDataBuffer::importSharedFmla - invalid range for shared formula" );
- Reference< XNamedRange > xNamedRange = createSharedFormulaName( BinAddress( rBaseAddr ) );
- Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW );
- // load the formula definition
- rStrm.skip( 2 ); // flags
- ApiTokenSequence aTokens = getFormulaParser().importFormula( rBaseAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
- xTokens->setTokens( aTokens );
- // retry to insert a pending shared formula cell
- retryPendingSharedFormulaCell();
- }
- catch( Exception& )
- {
- }
}
-void SheetDataBuffer::setValueCell( const Reference< XCell >& rxCell, const CellAddress& /*rCellAddr*/, double fValue )
+void SheetDataBuffer::setValueCell( const CellAddress& rCellAddr, double fValue )
{
- OSL_ENSURE( rxCell.is(), "SheetDataBuffer::setDateTimeCell - missing cell interface" );
- if( rxCell.is() )
- rxCell->setValue( fValue );
+ Reference< XCell > xCell = getCell( rCellAddr );
+ OSL_ENSURE( xCell.is(), "SheetDataBuffer::setValueCell - missing cell interface" );
+ if( xCell.is() )
+ xCell->setValue( fValue );
}
-void SheetDataBuffer::setStringCell( const Reference< XCell >& rxCell, const CellAddress& /*rCellAddr*/, const OUString& rText )
+void SheetDataBuffer::setStringCell( const CellAddress& rCellAddr, const OUString& rText )
{
- Reference< XText > xText( rxCell, UNO_QUERY );
+ Reference< XText > xText( getCell( rCellAddr ), UNO_QUERY );
OSL_ENSURE( xText.is(), "SheetDataBuffer::setStringCell - missing text interface" );
if( xText.is() )
xText->setString( rText );
}
-void SheetDataBuffer::setStringCell( const Reference< XCell >& rxCell, const CellAddress& /*rCellAddr*/, const RichString& rString, sal_Int32 nXfId )
+void SheetDataBuffer::setStringCell( const CellAddress& rCellAddr, const RichString& rString, sal_Int32 nXfId )
{
- Reference< XText > xText( rxCell, UNO_QUERY );
+ Reference< XText > xText( getCell( rCellAddr ), UNO_QUERY );
OSL_ENSURE( xText.is(), "SheetDataBuffer::setStringCell - missing text interface" );
rString.convert( xText, nXfId );
+ (void)rString;
+ (void)nXfId;
}
-void SheetDataBuffer::setStringCell( const Reference< XCell >& rxCell, const CellAddress& /*rCellAddr*/, sal_Int32 nStringId, sal_Int32 nXfId )
+void SheetDataBuffer::setStringCell( const CellAddress& rCellAddr, sal_Int32 nStringId, sal_Int32 nXfId )
{
- Reference< XText > xText( rxCell, UNO_QUERY );
+ Reference< XText > xText( getCell( rCellAddr ), UNO_QUERY );
OSL_ENSURE( xText.is(), "SheetDataBuffer::setStringCell - missing text interface" );
getSharedStrings().convertString( xText, nStringId, nXfId );
+ (void)nStringId;
+ (void)nXfId;
}
-void SheetDataBuffer::setDateTimeCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, const DateTime& rDateTime )
+void SheetDataBuffer::setDateTimeCell( const CellAddress& rCellAddr, const DateTime& rDateTime )
{
// write serial date/time value into the cell
double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime );
- setValueCell( rxCell, rCellAddr, fSerial );
+ setValueCell( rCellAddr, fSerial );
// set appropriate number format
using namespace ::com::sun::star::util::NumberFormat;
sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE);
setStandardNumFmt( rCellAddr, nStdFmt );
}
-void SheetDataBuffer::setBooleanCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, bool bValue )
+void SheetDataBuffer::setBooleanCell( const CellAddress& rCellAddr, bool bValue )
{
- setFormulaCell( rxCell, rCellAddr, getFormulaParser().convertBoolToFormula( bValue ) );
+ setFormulaCell( rCellAddr, getFormulaParser().convertBoolToFormula( bValue ) );
}
-void SheetDataBuffer::setErrorCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, const OUString& rErrorCode )
+void SheetDataBuffer::setErrorCell( const CellAddress& rCellAddr, const OUString& rErrorCode )
{
- setErrorCell( rxCell, rCellAddr, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
+ setErrorCell( rCellAddr, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
}
-void SheetDataBuffer::setErrorCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, sal_uInt8 nErrorCode )
+void SheetDataBuffer::setErrorCell( const CellAddress& rCellAddr, sal_uInt8 nErrorCode )
{
- setFormulaCell( rxCell, rCellAddr, getFormulaParser().convertErrorToFormula( nErrorCode ) );
+ setFormulaCell( rCellAddr, getFormulaParser().convertErrorToFormula( nErrorCode ) );
}
-void SheetDataBuffer::setFormulaCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
+void SheetDataBuffer::setFormulaCell( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
{
mbPendingSharedFmla = false;
ApiTokenSequence aTokens;
@@ -234,11 +204,12 @@ void SheetDataBuffer::setFormulaCell( const Reference< XCell >& rxCell, const Ce
array formula. In this case, the cell will be remembered. After
reading the formula definition it will be retried to insert the
formula via retryPendingSharedFormulaCell(). */
- aTokens = resolveSharedFormula( aTokenInfo.First );
+ BinAddress aBaseAddr( aTokenInfo.First );
+ aTokens = resolveSharedFormula( aBaseAddr );
if( !aTokens.hasElements() )
{
maSharedFmlaAddr = rCellAddr;
- maSharedBaseAddr = aTokenInfo.First;
+ maSharedBaseAddr = aBaseAddr;
mbPendingSharedFmla = true;
}
}
@@ -251,89 +222,42 @@ void SheetDataBuffer::setFormulaCell( const Reference< XCell >& rxCell, const Ce
if( aTokens.hasElements() )
{
- Reference< XFormulaTokens > xTokens( rxCell, UNO_QUERY );
+ Reference< XFormulaTokens > xTokens( getCell( rCellAddr ), UNO_QUERY );
OSL_ENSURE( xTokens.is(), "SheetDataBuffer::setFormulaCell - missing formula interface" );
if( xTokens.is() )
xTokens->setTokens( aTokens );
}
}
-void SheetDataBuffer::setFormulaCell( const Reference< XCell >& rxCell, const CellAddress& rCellAddr, sal_Int32 nSharedId )
+void SheetDataBuffer::setFormulaCell( const CellAddress& rCellAddr, sal_Int32 nSharedId )
{
- setFormulaCell( rxCell, rCellAddr, resolveSharedFormula( nSharedId ) );
+ setFormulaCell( rCellAddr, resolveSharedFormula( BinAddress( nSharedId, 0 ) ) );
}
-void SheetDataBuffer::setArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens )
+void SheetDataBuffer::createArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens )
{
- try
- {
- Reference< XArrayFormulaTokens > xTokens( getCellRange( rRange ), UNO_QUERY_THROW );
- xTokens->setArrayTokens( rTokens );
- }
- catch( Exception& )
- {
- }
+ /* Array formulas will be inserted later in finalizeImport(). This is
+ needed to not disturb collecting all the cells, which will be put into
+ the sheet in large blocks to increase performance. */
+ maArrayFormulas.push_back( ArrayFormula( rRange, rTokens ) );
}
-void SheetDataBuffer::setTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
+void SheetDataBuffer::createTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
{
- OSL_ENSURE( getAddressConverter().checkCellRange( rRange, true, false ), "SheetDataBuffer::setTableOperation - invalid range" );
- sal_Int16 nSheet = getSheetIndex();
- bool bOk = false;
- if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
- {
- CellRangeAddress aOpRange = rRange;
- CellAddress aRef1, aRef2;
- if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try
- {
- if( rModel.mb2dTable )
- {
- if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) )
- {
- // API call expects input values inside operation range
- --aOpRange.StartColumn;
- --aOpRange.StartRow;
- // formula range is top-left cell of operation range
- CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 );
- bOk = true;
- }
- }
- else if( rModel.mbRowTable )
- {
- // formula range is column to the left of operation range
- CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
- // API call expects input values (top row) inside operation range
- --aOpRange.StartRow;
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 );
- bOk = true;
- }
- else
- {
- // formula range is row above operation range
- CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
- // API call expects input values (left column) inside operation range
- --aOpRange.StartColumn;
- // set multiple operation
- Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
- xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 );
- bOk = true;
- }
- }
- catch( Exception& )
- {
- }
- }
+ /* Table operations will be inserted later in finalizeImport(). This is
+ needed to not disturb collecting all the cells, which will be put into
+ the sheet in large blocks to increase performance. */
+ maTableOperations.push_back( TableOperation( rRange, rModel ) );
+}
+
+void SheetDataBuffer::createSharedFormula( sal_Int32 nSharedId, const ApiTokenSequence& rTokens )
+{
+ createSharedFormula( BinAddress( nSharedId, 0 ), rTokens );
+}
- // on error: fill cell range with error codes
- if( !bOk )
- for( CellAddress aPos( nSheet, rRange.StartColumn, rRange.StartRow ); aPos.Row <= rRange.EndRow; ++aPos.Row )
- for( aPos.Column = rRange.StartColumn; aPos.Column <= rRange.EndColumn; ++aPos.Column )
- setErrorCell( getCell( aPos ), aPos, BIFF_ERR_REF );
+void SheetDataBuffer::createSharedFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
+{
+ createSharedFormula( BinAddress( rCellAddr ), rTokens );
}
void SheetDataBuffer::setRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId, bool bCustomFormat )
@@ -356,9 +280,9 @@ void SheetDataBuffer::setRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal
}
}
-void SheetDataBuffer::setCellFormat( const CellModel& rModel )
+void SheetDataBuffer::setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId )
{
- if( rModel.mxCell.is() && ((rModel.mnXfId >= 0) || (rModel.mnNumFmtId >= 0)) )
+ if( (rModel.mnXfId >= 0) || (nNumFmtId >= 0) )
{
// try to merge existing ranges and to write some formatting properties
if( !maXfIdRanges.empty() )
@@ -366,7 +290,7 @@ void SheetDataBuffer::setCellFormat( const CellModel& rModel )
// get row index of last inserted cell
sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
// row changed - try to merge ranges of last row with existing ranges
- if( rModel.maAddress.Row != nLastRow )
+ if( rModel.maCellAddr.Row != nLastRow )
{
mergeXfIdRanges();
// write format properties of all ranges above last row and remove them
@@ -386,8 +310,8 @@ void SheetDataBuffer::setCellFormat( const CellModel& rModel )
}
// try to expand last existing range, or create new range entry
- if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel ) )
- maXfIdRanges[ BinAddress( rModel.maAddress ) ].set( rModel );
+ if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel, nNumFmtId ) )
+ maXfIdRanges[ BinAddress( rModel.maCellAddr ) ].set( rModel, nNumFmtId );
// update merged ranges for 'center across selection' and 'fill'
if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() )
@@ -398,9 +322,9 @@ void SheetDataBuffer::setCellFormat( const CellModel& rModel )
/* start new merged range, if cell is not empty (#108781#),
or try to expand last range with empty cell */
if( rModel.mnCellType != XML_TOKEN_INVALID )
- maCenterFillRanges.push_back( MergedRange( rModel.maAddress, nHorAlign ) );
+ maCenterFillRanges.push_back( MergedRange( rModel.maCellAddr, nHorAlign ) );
else if( !maCenterFillRanges.empty() )
- maCenterFillRanges.rbegin()->tryExpand( rModel.maAddress, nHorAlign );
+ maCenterFillRanges.rbegin()->tryExpand( rModel.maCellAddr, nHorAlign );
}
}
}
@@ -428,6 +352,14 @@ void SheetDataBuffer::setStandardNumFmt( const CellAddress& rCellAddr, sal_Int16
void SheetDataBuffer::finalizeImport()
{
+ // create all array formulas
+ for( ArrayFormulaList::iterator aIt = maArrayFormulas.begin(), aEnd = maArrayFormulas.end(); aIt != aEnd; ++aIt )
+ finalizeArrayFormula( aIt->first, aIt->second );
+
+ // create all table operations
+ for( TableOperationList::iterator aIt = maTableOperations.begin(), aEnd = maTableOperations.end(); aIt != aEnd; ++aIt )
+ finalizeTableOperation( aIt->first, aIt->second );
+
// write default formatting of remaining row range
writeXfIdRowRangeProperties( maXfIdRowRange );
@@ -438,10 +370,9 @@ void SheetDataBuffer::finalizeImport()
writeXfIdRangeProperties( aIt->second );
// merge all cached merged ranges and update right/bottom cell borders
- MergedRangeList::const_iterator aIt, aEnd;
- for( aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
+ for( MergedRangeList::iterator aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
finalizeMergedRange( aIt->maRange );
- for( aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
+ for( MergedRangeList::iterator aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
finalizeMergedRange( aIt->maRange );
}
@@ -484,21 +415,21 @@ bool SheetDataBuffer::XfIdRowRange::tryExpand( sal_Int32 nFirstRow, sal_Int32 nL
return false;
}
-void SheetDataBuffer::XfIdRange::set( const CellModel& rModel )
+void SheetDataBuffer::XfIdRange::set( const CellModel& rModel, sal_Int32 nNumFmtId )
{
- maRange.Sheet = rModel.maAddress.Sheet;
- maRange.StartColumn = maRange.EndColumn = rModel.maAddress.Column;
- maRange.StartRow = maRange.EndRow = rModel.maAddress.Row;
+ maRange.Sheet = rModel.maCellAddr.Sheet;
+ maRange.StartColumn = maRange.EndColumn = rModel.maCellAddr.Column;
+ maRange.StartRow = maRange.EndRow = rModel.maCellAddr.Row;
mnXfId = rModel.mnXfId;
- mnNumFmtId = rModel.mnNumFmtId;
+ mnNumFmtId = nNumFmtId;
}
-bool SheetDataBuffer::XfIdRange::tryExpand( const CellModel& rModel )
+bool SheetDataBuffer::XfIdRange::tryExpand( const CellModel& rModel, sal_Int32 nNumFmtId )
{
- if( (mnXfId == rModel.mnXfId) && (mnNumFmtId == rModel.mnNumFmtId) &&
- (maRange.StartRow == rModel.maAddress.Row) &&
- (maRange.EndRow == rModel.maAddress.Row) &&
- (maRange.EndColumn + 1 == rModel.maAddress.Column) )
+ if( (mnXfId == rModel.mnXfId) && (mnNumFmtId == nNumFmtId) &&
+ (maRange.StartRow == rModel.maCellAddr.Row) &&
+ (maRange.EndRow == rModel.maCellAddr.Row) &&
+ (maRange.EndColumn + 1 == rModel.maCellAddr.Column) )
{
++maRange.EndColumn;
return true;
@@ -544,7 +475,83 @@ bool SheetDataBuffer::MergedRange::tryExpand( const CellAddress& rAddress, sal_I
return false;
}
-Reference< XNamedRange > SheetDataBuffer::createSharedFormulaName( const BinAddress& rMapKey )
+void SheetDataBuffer::finalizeArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens )
+{
+ Reference< XArrayFormulaTokens > xTokens( getCellRange( rRange ), UNO_QUERY );
+ OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
+ if( xTokens.is() )
+ xTokens->setArrayTokens( rTokens );
+}
+
+void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
+{
+ sal_Int16 nSheet = getSheetIndex();
+ bool bOk = false;
+ if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
+ {
+ CellRangeAddress aOpRange = rRange;
+ CellAddress aRef1;
+ if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try
+ {
+ if( rModel.mb2dTable )
+ {
+ CellAddress aRef2;
+ if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) )
+ {
+ // API call expects input values inside operation range
+ --aOpRange.StartColumn;
+ --aOpRange.StartRow;
+ // formula range is top-left cell of operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 );
+ bOk = true;
+ }
+ }
+ else if( rModel.mbRowTable )
+ {
+ // formula range is column to the left of operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
+ // API call expects input values (top row) inside operation range
+ --aOpRange.StartRow;
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 );
+ bOk = true;
+ }
+ else
+ {
+ // formula range is row above operation range
+ CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
+ // API call expects input values (left column) inside operation range
+ --aOpRange.StartColumn;
+ // set multiple operation
+ Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
+ xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 );
+ bOk = true;
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ }
+
+ // on error: fill cell range with #REF! error codes
+ if( !bOk ) try
+ {
+ Reference< XCellRangeData > xCellRangeData( getCellRange( rRange ), UNO_QUERY_THROW );
+ size_t nWidth = static_cast< size_t >( rRange.EndColumn - rRange.StartColumn + 1 );
+ size_t nHeight = static_cast< size_t >( rRange.EndRow - rRange.StartRow + 1 );
+ Matrix< Any > aErrorCells( nWidth, nHeight, Any( getFormulaParser().convertErrorToFormula( BIFF_ERR_REF ) ) );
+ xCellRangeData->setDataArray( ContainerHelper::matrixToSequenceSequence( aErrorCells ) );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+void SheetDataBuffer::createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens )
{
// create the defined name that will represent the shared formula
OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
@@ -552,40 +559,39 @@ Reference< XNamedRange > SheetDataBuffer::createSharedFormulaName( const BinAddr
append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
Reference< XNamedRange > xNamedRange = createNamedRangeObject( aName );
+ OSL_ENSURE( xNamedRange.is(), "SheetDataBuffer::createSharedFormula - cannot create shared formula" );
PropertySet aNameProps( xNamedRange );
aNameProps.setProperty( PROP_IsSharedFormula, true );
// get and store the token index of the defined name
- OSL_ENSURE( maTokenIndexes.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormulaName - key exists already" );
+ OSL_ENSURE( maSharedFormulas.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormula - shared formula exists already" );
sal_Int32 nTokenIndex = 0;
- if( aNameProps.getProperty( nTokenIndex, PROP_TokenIndex ) )
- maTokenIndexes[ rMapKey ] = nTokenIndex;
-
- return xNamedRange;
-}
-
-ApiTokenSequence SheetDataBuffer::resolveSharedFormula( sal_Int32 nSharedId ) const
-{
- sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maTokenIndexes, BinAddress( nSharedId, 0 ), -1 );
- return (nTokenIndex >= 0) ? getFormulaParser().convertNameToFormula( nTokenIndex ) : ApiTokenSequence();
+ if( aNameProps.getProperty( nTokenIndex, PROP_TokenIndex ) && (nTokenIndex >= 0) ) try
+ {
+ // store the token index in the map
+ maSharedFormulas[ rMapKey ] = nTokenIndex;
+ // set the formula definition
+ Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW );
+ xTokens->setTokens( rTokens );
+ // retry to insert a pending shared formula cell
+ if( mbPendingSharedFmla )
+ {
+ ApiTokenSequence aTokens = resolveSharedFormula( maSharedBaseAddr );
+ setFormulaCell( maSharedFmlaAddr, aTokens );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ mbPendingSharedFmla = false;
}
-ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const CellAddress& rBaseAddr ) const
+ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const BinAddress& rMapKey ) const
{
- sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maTokenIndexes, BinAddress( rBaseAddr ), -1 );
+ sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maSharedFormulas, rMapKey, -1 );
return (nTokenIndex >= 0) ? getFormulaParser().convertNameToFormula( nTokenIndex ) : ApiTokenSequence();
}
-void SheetDataBuffer::retryPendingSharedFormulaCell()
-{
- if( mbPendingSharedFmla )
- {
- ApiTokenSequence aTokens = resolveSharedFormula( maSharedBaseAddr );
- setFormulaCell( getCell( maSharedFmlaAddr ), maSharedFmlaAddr, aTokens );
- mbPendingSharedFmla = false;
- }
-}
-
void SheetDataBuffer::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const
{
if( (rXfIdRowRange.mnLastRow >= 0) && (rXfIdRowRange.mnXfId >= 0) )
diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx
index f387257eaaf0..63db3286cff6 100644
--- a/oox/source/xls/sheetdatacontext.cxx
+++ b/oox/source/xls/sheetdatacontext.cxx
@@ -37,7 +37,6 @@
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/formulaparser.hxx"
#include "oox/xls/richstringcontext.hxx"
-#include "oox/xls/sheetdatabuffer.hxx"
#include "oox/xls/unitconverter.hxx"
namespace oox {
@@ -102,9 +101,25 @@ const sal_Int32 BIFF2_CELL_USEIXFE = 63;
// ============================================================================
+SheetDataContextBase::SheetDataContextBase( const WorksheetHelper& rHelper ) :
+ mrAddressConv( rHelper.getAddressConverter() ),
+ mrFormulaParser( rHelper.getFormulaParser() ),
+ mrSheetData( rHelper.getSheetData() ),
+ mnSheet( rHelper.getSheetIndex() )
+{
+}
+
+SheetDataContextBase::~SheetDataContextBase()
+{
+}
+
+// ============================================================================
+
SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) :
WorksheetContextBase( rFragment ),
- mrSheetData( getSheetData() )
+ SheetDataContextBase( rFragment ),
+ mbHasFormula( false ),
+ mbValidRange( false )
{
}
@@ -117,11 +132,13 @@ ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const A
break;
case XLS_TOKEN( row ):
- if( nElement == XLS_TOKEN( c ) ) { importCell( rAttribs ); return this; }
+ // do not process cell elements with invalid (out-of-range) address
+ if( nElement == XLS_TOKEN( c ) && importCell( rAttribs ) )
+ return this;
break;
case XLS_TOKEN( c ):
- if( maCurrCell.mxCell.is() ) switch( nElement )
+ switch( nElement )
{
case XLS_TOKEN( is ):
mxInlineStr.reset( new RichString( *this ) );
@@ -142,112 +159,84 @@ void SheetDataContext::onCharacters( const OUString& rChars )
switch( getCurrentElement() )
{
case XLS_TOKEN( v ):
- maCurrCell.maValue = rChars;
+ maCellValue = rChars;
break;
case XLS_TOKEN( f ):
- maCurrCell.maFormula = rChars;
+ if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID )
+ maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars );
break;
}
}
void SheetDataContext::onEndElement()
{
- switch( getCurrentElement() )
+ if( getCurrentElement() == XLS_TOKEN( c ) )
{
- case XLS_TOKEN( c ):
- if( maCurrCell.mxCell.is() )
- {
- // try to create a formula cell
- if( maCurrCell.mxCell->getType() == CellContentType_EMPTY )
- {
- switch( maCurrCell.mnFormulaType )
- {
- case XML_normal:
- if( maCurrCell.maFormula.getLength() > 0 )
- {
- ApiTokenSequence aTokens = getFormulaParser().importFormula( maCurrCell.maAddress, maCurrCell.maFormula );
- mrSheetData.setFormulaCell( maCurrCell.mxCell, maCurrCell.maAddress, aTokens );
- }
- break;
-
- case XML_array:
- if( (maCurrCell.maFormula.getLength() > 0) && (maCurrCell.maFormulaRef.getLength() > 0) )
- {
- CellRangeAddress aArrayRange;
- if( getAddressConverter().convertToCellRange( aArrayRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) )
- {
- CellAddress aBaseAddr( aArrayRange.Sheet, aArrayRange.StartColumn, aArrayRange.StartRow );
- ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, maCurrCell.maFormula );
- mrSheetData.setArrayFormula( aArrayRange, aTokens );
- }
- }
- break;
-
- case XML_shared:
- if( maCurrCell.mnSharedId >= 0 )
- {
- if( maCurrCell.maFormula.getLength() > 0 )
- mrSheetData.importSharedFmla( maCurrCell.maFormula, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress );
- mrSheetData.setFormulaCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.mnSharedId );
- }
- break;
-
- case XML_dataTable:
- if( maCurrCell.maFormulaRef.getLength() > 0 )
- {
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) )
- mrSheetData.setTableOperation( aTableRange, maTableData );
- }
- break;
-
- default:
- OSL_ENSURE( maCurrCell.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onCharacters - unknown formula type" );
- }
- }
-
- // no formula created: try to set the cell value
- if( maCurrCell.mxCell->getType() == CellContentType_EMPTY )
+ // try to create a formula cell
+ if( mbHasFormula ) switch( maFmlaData.mnFormulaType )
+ {
+ case XML_normal:
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, maTokens );
+ break;
+ case XML_shared:
+ if( maFmlaData.mnSharedId >= 0 )
{
- if( maCurrCell.maValue.getLength() > 0 )
- {
- switch( maCurrCell.mnCellType )
- {
- case XML_n:
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.maValue.toDouble() );
- break;
- case XML_b:
- mrSheetData.setBooleanCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.maValue.toDouble() != 0.0 );
- // #108770# set 'Standard' number format for all Boolean cells
- maCurrCell.mnNumFmtId = 0;
- break;
- case XML_e:
- mrSheetData.setErrorCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.maValue );
- break;
- case XML_str:
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.maValue );
- break;
- case XML_s:
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, maCurrCell.maValue.toInt32(), maCurrCell.mnXfId );
- break;
- }
- }
- else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() )
- {
- mxInlineStr->finalizeImport();
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, *mxInlineStr, maCurrCell.mnXfId );
- }
- else
- {
- // empty cell, update cell type
- maCurrCell.mnCellType = XML_TOKEN_INVALID;
- }
+ if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ mrSheetData.createSharedFormula( maFmlaData.mnSharedId, maTokens );
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, maFmlaData.mnSharedId );
}
+ break;
+ case XML_array:
+ if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens );
+ break;
+ case XML_dataTable:
+ if( mbValidRange )
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
+ break;
+ default:
+ OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" );
+ mbHasFormula = false;
+ }
- // store the cell formatting data
- mrSheetData.setCellFormat( maCurrCell );
+ if( !mbHasFormula )
+ {
+ // no formula created: try to set the cell value
+ if( maCellValue.getLength() > 0 ) switch( maCellData.mnCellType )
+ {
+ case XML_n:
+ mrSheetData.setValueCell( maCellData.maCellAddr, maCellValue.toDouble() );
+ break;
+ case XML_b:
+ mrSheetData.setBooleanCell( maCellData.maCellAddr, maCellValue.toDouble() != 0.0 );
+ break;
+ case XML_e:
+ mrSheetData.setErrorCell( maCellData.maCellAddr, maCellValue );
+ break;
+ case XML_str:
+ mrSheetData.setStringCell( maCellData.maCellAddr, maCellValue );
+ break;
+ case XML_s:
+ mrSheetData.setStringCell( maCellData.maCellAddr, maCellValue.toInt32(), maCellData.mnXfId );
+ break;
}
- break;
+ else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr.get() )
+ {
+ mxInlineStr->finalizeImport();
+ mrSheetData.setStringCell( maCellData.maCellAddr, *mxInlineStr, maCellData.mnXfId );
+ }
+ else
+ {
+ // empty cell, update cell type
+ maCellData.mnCellType = XML_TOKEN_INVALID;
+ }
+ }
+
+ // #108770# set 'Standard' number format for all Boolean cells
+ bool bBoolCell = !mbHasFormula && (maCellData.mnCellType == XML_b);
+ sal_Int32 nNumFmtId = bBoolCell ? 0 : -1;
+ // store the cell formatting data
+ mrSheetData.setCellFormat( maCellData, nNumFmtId );
}
}
@@ -311,37 +300,73 @@ void SheetDataContext::importRow( const AttributeList& rAttribs )
setRowModel( aModel );
}
-void SheetDataContext::importCell( const AttributeList& rAttribs )
+bool SheetDataContext::importCell( const AttributeList& rAttribs )
{
- maCurrCell.reset();
- maCurrCell.mxCell = getCell( rAttribs.getString( XML_r, OUString() ), &maCurrCell.maAddress );
- maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n );
- maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 );
- maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
- mxInlineStr.reset();
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAttribs.getString( XML_r, OUString() ), mnSheet, true );
+ if( bValidAddr )
+ {
+ maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n );
+ maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 );
+ maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
- // update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
+ // reset cell value, formula settings, and inline string
+ maCellValue = OUString();
+ mxInlineStr.reset();
+ mbHasFormula = false;
+
+ // update used area of the sheet
+ extendUsedArea( maCellData.maCellAddr );
+ }
+ return bValidAddr;
}
void SheetDataContext::importFormula( const AttributeList& rAttribs )
{
- maCurrCell.maFormulaRef = rAttribs.getString( XML_ref, OUString() );
- maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
- maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 );
- maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() );
- maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() );
- maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false );
- maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false );
- maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
- maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
+ mbHasFormula = true;
+ mbValidRange = mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, rAttribs.getString( XML_ref, OUString() ), mnSheet, true, true );
+
+ maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
+ maFmlaData.mnSharedId = rAttribs.getInteger( XML_si, -1 );
+
+ if( maFmlaData.mnFormulaType == XML_dataTable )
+ {
+ maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() );
+ maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() );
+ maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false );
+ maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false );
+ maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
+ maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
+ }
+
+ // clear token array, will be regenerated from element text
+ maTokens = ApiTokenSequence();
}
-void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eCellType )
+void SheetDataContext::importRow( SequenceInputStream& rStrm )
{
- maCurrCell.reset();
+ RowModel aModel;
+ sal_uInt16 nHeight, nFlags1;
+ sal_uInt8 nFlags2;
+ rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2;
+ // row index is 0-based in BIFF12, but RowModel expects 1-based
+ aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1;
+ // row height is in twips in BIFF12, convert to points
+ aModel.mfHeight = nHeight / 20.0;
+ aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 );
+ aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT );
+ aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT );
+ aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC );
+ aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN );
+ aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED );
+ aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP );
+ aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM );
+ // set row properties in the current sheet
+ setRowModel( aModel );
+}
+
+bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType )
+{
switch( eCellType )
{
case CELLTYPE_VALUE:
@@ -352,194 +377,166 @@ void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eC
sal_uInt32 nXfId;
rStrm >> nXfId;
- maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress );
- maCurrCell.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
- maCurrCell.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC );
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, maCurrPos, mnSheet, true );
+ maCellData.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
+ maCellData.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC );
// update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
+ if( bValidAddr )
+ extendUsedArea( maCellData.maCellAddr );
+ return bValidAddr;
+}
+
+ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm )
+{
+ rStrm.skip( 2 );
+ return mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm );
+}
+
+bool SheetDataContext::readFormulaRef( SequenceInputStream& rStrm )
+{
+ BinRange aRange;
+ rStrm >> aRange;
+ return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true );
}
void SheetDataContext::importCellBool( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_b;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_b;
bool bValue = rStrm.readuInt8() != 0;
if( eCellType == CELLTYPE_FORMULA )
- {
- importCellFormula( rStrm );
- }
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, readCellFormula( rStrm ) );
else
- {
- mrSheetData.setBooleanCell( maCurrCell.mxCell, maCurrCell.maAddress, bValue );
- // #108770# set 'Standard' number format for all Boolean cells
- maCurrCell.mnNumFmtId = 0;
- }
+ mrSheetData.setBooleanCell( maCellData.maCellAddr, bValue );
+ // #108770# set 'Standard' number format for all Boolean cells
+ sal_Int32 nNumFmtId = (eCellType != CELLTYPE_FORMULA) ? 0 : -1;
+ mrSheetData.setCellFormat( maCellData, nNumFmtId );
}
- mrSheetData.setCellFormat( maCurrCell );
}
void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ mrSheetData.setCellFormat( maCellData );
}
void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_n;
double fValue = rStrm.readDouble();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, readCellFormula( rStrm ) );
else
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, fValue );
+ mrSheetData.setValueCell( maCellData.maCellAddr, fValue );
+ mrSheetData.setCellFormat( maCellData );
}
- mrSheetData.setCellFormat( maCurrCell );
}
void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_e;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_e;
sal_uInt8 nErrorCode = rStrm.readuInt8();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, readCellFormula( rStrm ) );
else
- mrSheetData.setErrorCell( maCurrCell.mxCell, maCurrCell.maAddress, nErrorCode );
+ mrSheetData.setErrorCell( maCellData.maCellAddr, nErrorCode );
+ mrSheetData.setCellFormat( maCellData );
}
- mrSheetData.setCellFormat( maCurrCell );
}
void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_n;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData.maCellAddr, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_inlineStr;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_inlineStr;
RichString aString( *this );
aString.importString( rStrm, true );
aString.finalizeImport();
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, aString, maCurrCell.mnXfId );
+ mrSheetData.setStringCell( maCellData.maCellAddr, aString, maCellData.mnXfId );
+ mrSheetData.setCellFormat( maCellData );
}
- mrSheetData.setCellFormat( maCurrCell );
}
void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType )
{
OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" );
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_s;
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, rStrm.readInt32(), maCurrCell.mnXfId );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, eCellType ) )
+ {
+ maCellData.mnCellType = XML_s;
+ mrSheetData.setStringCell( maCellData.maCellAddr, rStrm.readInt32(), maCellData.mnXfId );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType )
{
- importCellHeader( rStrm, eCellType );
- maCurrCell.mnCellType = XML_inlineStr;
- Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
- if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
+ if( readCellHeader( rStrm, eCellType ) )
{
+ maCellData.mnCellType = XML_inlineStr;
+ // always import the string, stream will point to formula afterwards, if existing
RichString aString( *this );
aString.importString( rStrm, false );
aString.finalizeImport();
if( eCellType == CELLTYPE_FORMULA )
- importCellFormula( rStrm );
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, readCellFormula( rStrm ) );
else
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, aString, maCurrCell.mnXfId );
+ mrSheetData.setStringCell( maCellData.maCellAddr, aString, maCellData.mnXfId );
+ mrSheetData.setCellFormat( maCellData );
}
- mrSheetData.setCellFormat( maCurrCell );
-}
-
-void SheetDataContext::importCellFormula( SequenceInputStream& rStrm )
-{
- rStrm.skip( 2 );
- ApiTokenSequence aTokens = getFormulaParser().importFormula( maCurrCell.maAddress, FORMULATYPE_CELL, rStrm );
- mrSheetData.setFormulaCell( maCurrCell.mxCell, maCurrCell.maAddress, aTokens );
-}
-
-void SheetDataContext::importRow( SequenceInputStream& rStrm )
-{
- RowModel aModel;
-
- sal_uInt16 nHeight, nFlags1;
- sal_uInt8 nFlags2;
- rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2;
-
- // row index is 0-based in BIFF12, but RowModel expects 1-based
- aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1;
- // row height is in twips in BIFF12, convert to points
- aModel.mfHeight = nHeight / 20.0;
- aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 );
- aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT );
- aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT );
- aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC );
- aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN );
- aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED );
- aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP );
- aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM );
- // set row properties in the current sheet
- setRowModel( aModel );
}
void SheetDataContext::importArray( SequenceInputStream& rStrm )
{
- BinRange aRange;
- rStrm >> aRange;
- CellRangeAddress aArrayRange;
- if( getAddressConverter().convertToCellRange( aArrayRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
{
rStrm.skip( 1 );
- CellAddress aBaseAddr( aArrayRange.Sheet, aArrayRange.StartColumn, aArrayRange.StartRow );
- ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_ARRAY, rStrm );
- mrSheetData.setArrayFormula( aArrayRange, aTokens );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm );
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens );
}
}
-void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
-{
- mrSheetData.importSharedFmla( rStrm, maCurrCell.maAddress );
-}
-
void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
{
- BinRange aRange;
- rStrm >> aRange;
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) )
{
- DataTableModel aModel;
BinAddress aRef1, aRef2;
sal_uInt8 nFlags;
rStrm >> aRef1 >> aRef2 >> nFlags;
- aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
- aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
- aModel.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW );
- aModel.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D );
- aModel.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL );
- aModel.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL );
- mrSheetData.setTableOperation( aTableRange, aModel );
+ maTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
+ maTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
+ maTableData.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW );
+ maTableData.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D );
+ maTableData.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL );
+ maTableData.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL );
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
+ }
+}
+
+void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
+{
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ {
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
+ mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
}
}
@@ -547,7 +544,7 @@ void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) :
BiffWorksheetContextBase( rHelper ),
- mrSheetData( getSheetData() ),
+ SheetDataContextBase( rHelper ),
mnBiff2XfId( 0 )
{
switch( getBiff() )
@@ -656,109 +653,160 @@ void BiffSheetDataContext::importRecord( BiffInputStream& rStrm )
// private --------------------------------------------------------------------
-void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr )
+void BiffSheetDataContext::importRow( BiffInputStream& rStrm )
{
- maCurrCell.reset();
- maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress );
- // update used area of the sheet
- if( maCurrCell.mxCell.is() )
- extendUsedArea( maCurrCell.maAddress );
-}
-
-void BiffSheetDataContext::importXfId( BiffInputStream& rStrm, bool bBiff2 )
-{
- if( bBiff2 )
- {
- /* #i71453# On first call, check if the file contains XF records (by
- trying to access the first XF with index 0). If there are no XFs,
- the explicit formatting information contained in each cell record
- will be used instead. */
- if( !mobBiff2HasXfs )
- mobBiff2HasXfs = getStyles().getCellXf( 0 ).get() != 0;
- // read formatting information (includes the XF identifier)
- sal_uInt8 nFlags1, nFlags2, nFlags3;
- rStrm >> nFlags1 >> nFlags2 >> nFlags3;
- /* If the file contains XFs, extract and set the XF identifier,
- otherwise get the explicit formatting. */
- if( mobBiff2HasXfs.get() )
- {
- maCurrCell.mnXfId = extractValue< sal_Int32 >( nFlags1, 0, 6 );
- /* If the identifier is equal to 63, then the real identifier is
- contained in the preceding IXFE record (stored in mnBiff2XfId). */
- if( maCurrCell.mnXfId == BIFF2_CELL_USEIXFE )
- maCurrCell.mnXfId = mnBiff2XfId;
- }
- else
+ RowModel aModel;
+ sal_uInt16 nRow, nHeight;
+ rStrm >> nRow;
+ rStrm.skip( 4 );
+ rStrm >> nHeight;
+ if( getBiff() == BIFF2 )
+ {
+ rStrm.skip( 2 );
+ aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT;
+ if( aModel.mbCustomFormat )
{
- /* Let the Xf class do the API conversion. Keeping the member
- maCurrCell.mnXfId untouched will prevent to trigger the usual
- XF formatting conversion later on. */
- PropertySet aPropSet( maCurrCell.mxCell );
- Xf::writeBiff2CellFormatToPropertySet( *this, aPropSet, nFlags1, nFlags2, nFlags3 );
+ rStrm.skip( 5 );
+ aModel.mnXfId = rStrm.readuInt16();
}
}
else
{
- maCurrCell.mnXfId = rStrm.readuInt16();
+ rStrm.skip( 4 );
+ sal_uInt32 nFlags = rStrm.readuInt32();
+ aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 );
+ aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 );
+ aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT );
+ aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT );
+ aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC );
+ aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN );
+ aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED );
+ aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP );
+ aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM );
}
+
+ // row index is 0-based in BIFF, but RowModel expects 1-based
+ aModel.mnFirstRow = aModel.mnLastRow = nRow + 1;
+ // row height is in twips in BIFF, convert to points
+ aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0;
+ // set row properties in the current sheet
+ setRowModel( aModel );
}
-void BiffSheetDataContext::importCellHeader( BiffInputStream& rStrm, bool bBiff2 )
+bool BiffSheetDataContext::readCellXfId( const BinAddress& rAddr, BiffInputStream& rStrm, bool bBiff2 )
+{
+ bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAddr, mnSheet, true );
+ if( bValidAddr )
+ {
+ // update used area of the sheet
+ extendUsedArea( maCellData.maCellAddr );
+
+ // load the XF identifier according to current BIFF version
+ if( bBiff2 )
+ {
+ /* #i71453# On first call, check if the file contains XF records
+ (by trying to access the first XF with index 0). If there are
+ no XFs, the explicit formatting information contained in each
+ cell record will be used instead. */
+ if( !mobBiff2HasXfs )
+ mobBiff2HasXfs = getStyles().getCellXf( 0 ).get() != 0;
+ // read formatting information (includes the XF identifier)
+ sal_uInt8 nFlags1, nFlags2, nFlags3;
+ rStrm >> nFlags1 >> nFlags2 >> nFlags3;
+ /* If the file contains XFs, extract and set the XF identifier,
+ otherwise get the explicit formatting. */
+ if( mobBiff2HasXfs.get() )
+ {
+ maCellData.mnXfId = extractValue< sal_Int32 >( nFlags1, 0, 6 );
+ /* If the identifier is equal to 63, then the real identifier
+ is contained in the preceding IXFE record (stored in the
+ class member mnBiff2XfId). */
+ if( maCellData.mnXfId == BIFF2_CELL_USEIXFE )
+ maCellData.mnXfId = mnBiff2XfId;
+ }
+ else
+ {
+ /* Let the Xf class do the API conversion. Keeping the member
+ maCellData.mnXfId untouched will prevent to trigger the
+ usual XF formatting conversion later on. */
+ PropertySet aPropSet( getCell( maCellData.maCellAddr ) );
+ Xf::writeBiff2CellFormatToPropertySet( *this, aPropSet, nFlags1, nFlags2, nFlags3 );
+ }
+ }
+ else
+ {
+ // BIFF3-BIFF8: 16-bit XF identifier
+ maCellData.mnXfId = rStrm.readuInt16();
+ }
+ }
+ return bValidAddr;
+}
+
+bool BiffSheetDataContext::readCellHeader( BiffInputStream& rStrm, bool bBiff2 )
{
BinAddress aAddr;
rStrm >> aAddr;
- setCurrCell( aAddr );
- importXfId( rStrm, bBiff2 );
+ return readCellXfId( aAddr, rStrm, bBiff2 );
+}
+
+bool BiffSheetDataContext::readFormulaRef( BiffInputStream& rStrm )
+{
+ BinRange aRange;
+ aRange.read( rStrm, false ); // columns always 8-bit
+ return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true );
}
void BiffSheetDataContext::importBlank( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ) )
+ mrSheetData.setCellFormat( maCellData );
}
void BiffSheetDataContext::importBoolErr( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR );
- if( maCurrCell.mxCell.is() )
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ) )
{
sal_uInt8 nValue, nType;
rStrm >> nValue >> nType;
switch( nType )
{
case BIFF_BOOLERR_BOOL:
- maCurrCell.mnCellType = XML_b;
- mrSheetData.setBooleanCell( maCurrCell.mxCell, maCurrCell.maAddress, nValue != 0 );
- // #108770# set 'Standard' number format for all Boolean cells
- maCurrCell.mnNumFmtId = 0;
+ maCellData.mnCellType = XML_b;
+ mrSheetData.setBooleanCell( maCellData.maCellAddr, nValue != 0 );
break;
case BIFF_BOOLERR_ERROR:
- maCurrCell.mnCellType = XML_e;
- mrSheetData.setErrorCell( maCurrCell.mxCell, maCurrCell.maAddress, nValue );
+ maCellData.mnCellType = XML_e;
+ mrSheetData.setErrorCell( maCellData.maCellAddr, nValue );
break;
default:
OSL_ENSURE( false, "BiffSheetDataContext::importBoolErr - unknown cell type" );
}
+ // #108770# set 'Standard' number format for all Boolean cells
+ sal_Int32 nNumFmtId = (nType == BIFF_BOOLERR_BOOL) ? 0 : -1;
+ mrSheetData.setCellFormat( maCellData, nNumFmtId );
}
- mrSheetData.setCellFormat( maCurrCell );
}
void BiffSheetDataContext::importFormula( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, getBiff() == BIFF2 );
- maCurrCell.mnCellType = XML_n;
- rStrm.skip( mnFormulaSkipSize );
- ApiTokenSequence aTokens = getFormulaParser().importFormula( maCurrCell.maAddress, FORMULATYPE_CELL, rStrm );
- mrSheetData.setFormulaCell( maCurrCell.mxCell, maCurrCell.maAddress, aTokens );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, getBiff() == BIFF2 ) )
+ {
+ maCellData.mnCellType = XML_n;
+ rStrm.skip( mnFormulaSkipSize );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm );
+ mrSheetData.setFormulaCell( maCellData.maCellAddr, aTokens );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void BiffSheetDataContext::importInteger( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, true );
- maCurrCell.mnCellType = XML_n;
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, rStrm.readuInt16() );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, true ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData.maCellAddr, rStrm.readuInt16() );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void BiffSheetDataContext::importLabel( BiffInputStream& rStrm )
@@ -771,143 +819,98 @@ void BiffSheetDataContext::importLabel( BiffInputStream& rStrm )
0x0204 8 -> 2 byte 16-bit length, unicode string
*/
bool bBiff2Xf = rStrm.getRecId() == BIFF2_ID_LABEL;
- importCellHeader( rStrm, bBiff2Xf );
- maCurrCell.mnCellType = XML_inlineStr;
- RichString aString( *this );
- if( getBiff() == BIFF8 )
+ if( readCellHeader( rStrm, bBiff2Xf ) )
{
- aString.importUniString( rStrm );
- }
- else
- {
- // #i63105# use text encoding from FONT record
- rtl_TextEncoding eTextEnc = getTextEncoding();
- if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() )
- eTextEnc = pFont->getFontEncoding();
- BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT;
- setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING );
- aString.importByteString( rStrm, eTextEnc, nFlags );
+ maCellData.mnCellType = XML_inlineStr;
+ RichString aString( *this );
+ if( getBiff() == BIFF8 )
+ {
+ aString.importUniString( rStrm );
+ }
+ else
+ {
+ // #i63105# use text encoding from FONT record
+ rtl_TextEncoding eTextEnc = getTextEncoding();
+ if( const Font* pFont = getStyles().getFontFromCellXf( maCellData.mnXfId ).get() )
+ eTextEnc = pFont->getFontEncoding();
+ BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT;
+ setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING );
+ aString.importByteString( rStrm, eTextEnc, nFlags );
+ }
+ aString.finalizeImport();
+ mrSheetData.setStringCell( maCellData.maCellAddr, aString, maCellData.mnXfId );
+ mrSheetData.setCellFormat( maCellData );
}
- aString.finalizeImport();
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, aString, maCurrCell.mnXfId );
- mrSheetData.setCellFormat( maCurrCell );
}
void BiffSheetDataContext::importLabelSst( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, false );
- maCurrCell.mnCellType = XML_s;
- mrSheetData.setStringCell( maCurrCell.mxCell, maCurrCell.maAddress, rStrm.readInt32(), maCurrCell.mnXfId );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, false ) )
+ {
+ maCellData.mnCellType = XML_s;
+ mrSheetData.setStringCell( maCellData.maCellAddr, rStrm.readInt32(), maCellData.mnXfId );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void BiffSheetDataContext::importMultBlank( BiffInputStream& rStrm )
{
BinAddress aAddr;
- for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol )
- {
- setCurrCell( aAddr );
- importXfId( rStrm, false );
- mrSheetData.setCellFormat( maCurrCell );
- }
+ bool bValidAddr = true;
+ for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol )
+ if( (bValidAddr = readCellXfId( aAddr, rStrm, false )) == true )
+ mrSheetData.setCellFormat( maCellData );
}
void BiffSheetDataContext::importMultRk( BiffInputStream& rStrm )
{
BinAddress aAddr;
- for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol )
+ bool bValidAddr = true;
+ for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol )
{
- setCurrCell( aAddr );
- maCurrCell.mnCellType = XML_n;
- importXfId( rStrm, false );
- sal_Int32 nRkValue = rStrm.readInt32();
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, BiffHelper::calcDoubleFromRk( nRkValue ) );
- mrSheetData.setCellFormat( maCurrCell );
+ if( (bValidAddr = readCellXfId( aAddr, rStrm, false )) == true )
+ {
+ maCellData.mnCellType = XML_n;
+ sal_Int32 nRkValue = rStrm.readInt32();
+ mrSheetData.setValueCell( maCellData.maCellAddr, BiffHelper::calcDoubleFromRk( nRkValue ) );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
}
void BiffSheetDataContext::importNumber( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER );
- maCurrCell.mnCellType = XML_n;
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, rStrm.readDouble() );
- mrSheetData.setCellFormat( maCurrCell );
+ if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ) )
+ {
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData.maCellAddr, rStrm.readDouble() );
+ mrSheetData.setCellFormat( maCellData );
+ }
}
void BiffSheetDataContext::importRk( BiffInputStream& rStrm )
{
- importCellHeader( rStrm, false );
- maCurrCell.mnCellType = XML_n;
- mrSheetData.setValueCell( maCurrCell.mxCell, maCurrCell.maAddress, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
- mrSheetData.setCellFormat( maCurrCell );
-}
-
-void BiffSheetDataContext::importRow( BiffInputStream& rStrm )
-{
- RowModel aModel;
-
- sal_uInt16 nRow, nHeight;
- rStrm >> nRow;
- rStrm.skip( 4 );
- rStrm >> nHeight;
- if( getBiff() == BIFF2 )
+ if( readCellHeader( rStrm, false ) )
{
- rStrm.skip( 2 );
- aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT;
- if( aModel.mbCustomFormat )
- {
- rStrm.skip( 5 );
- aModel.mnXfId = rStrm.readuInt16();
- }
- }
- else
- {
- rStrm.skip( 4 );
- sal_uInt32 nFlags = rStrm.readuInt32();
- aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 );
- aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 );
- aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT );
- aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT );
- aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC );
- aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN );
- aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED );
- aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP );
- aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM );
+ maCellData.mnCellType = XML_n;
+ mrSheetData.setValueCell( maCellData.maCellAddr, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
+ mrSheetData.setCellFormat( maCellData );
}
-
- // row index is 0-based in BIFF, but RowModel expects 1-based
- aModel.mnFirstRow = aModel.mnLastRow = nRow + 1;
- // row height is in twips in BIFF, convert to points
- aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0;
- // set row properties in the current sheet
- setRowModel( aModel );
}
void BiffSheetDataContext::importArray( BiffInputStream& rStrm )
{
- BinRange aRange;
- aRange.read( rStrm, false ); // columns always 8-bit
- CellRangeAddress aArrayRange;
- if( getAddressConverter().convertToCellRange( aArrayRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
{
rStrm.skip( mnArraySkipSize );
- CellAddress aBaseAddr( aArrayRange.Sheet, aArrayRange.StartColumn, aArrayRange.StartRow );
- ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_ARRAY, rStrm );
- mrSheetData.setArrayFormula( aArrayRange, aTokens );
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm );
+ mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens );
}
}
-void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm )
-{
- mrSheetData.importSharedFmla( rStrm, maCurrCell.maAddress );
-}
-
void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm )
{
- BinRange aRange;
- aRange.read( rStrm, false ); // columns always 8-bit
- CellRangeAddress aTableRange;
- if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
+ if( readFormulaRef( rStrm ) )
{
DataTableModel aModel;
BinAddress aRef1, aRef2;
@@ -939,7 +942,17 @@ void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm )
}
aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
- mrSheetData.setTableOperation( aTableRange, aModel );
+ mrSheetData.createTableOperation( maFmlaData.maFormulaRef, aModel );
+ }
+}
+
+void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm )
+{
+ if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
+ {
+ rStrm.skip( 2 ); // flags
+ ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm );
+ mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
}
}
diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx
index 778adcff24ab..bba52fb0d8f2 100644
--- a/oox/source/xls/worksheethelper.cxx
+++ b/oox/source/xls/worksheethelper.cxx
@@ -184,27 +184,6 @@ void ValueRangeSet::intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal
// ============================================================================
// ============================================================================
-void CellModel::reset()
-{
- mxCell.clear();
- maValue = maFormula = maFormulaRef = OUString();
- mnCellType = mnFormulaType = XML_TOKEN_INVALID;
- mnSharedId = mnXfId = mnNumFmtId = -1;
- mbShowPhonetic = false;
-}
-
-// ----------------------------------------------------------------------------
-
-DataTableModel::DataTableModel() :
- mb2dTable( false ),
- mbRowTable( false ),
- mbRef1Deleted( false ),
- mbRef2Deleted( false )
-{
-}
-
-// ----------------------------------------------------------------------------
-
ColumnModel::ColumnModel() :
mnFirstCol( -1 ),
mnLastCol( -1 ),
@@ -1430,28 +1409,6 @@ Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const
return mrSheetGlob.getCell( rAddress );
}
-Reference< XCell > WorksheetHelper::getCell( const OUString& rAddressStr, CellAddress* opAddress ) const
-{
- CellAddress aAddress;
- if( getAddressConverter().convertToCellAddress( aAddress, rAddressStr, mrSheetGlob.getSheetIndex(), true ) )
- {
- if( opAddress ) *opAddress = aAddress;
- return mrSheetGlob.getCell( aAddress );
- }
- return Reference< XCell >();
-}
-
-Reference< XCell > WorksheetHelper::getCell( const BinAddress& rBinAddress, CellAddress* opAddress ) const
-{
- CellAddress aAddress;
- if( getAddressConverter().convertToCellAddress( aAddress, rBinAddress, mrSheetGlob.getSheetIndex(), true ) )
- {
- if( opAddress ) *opAddress = aAddress;
- return mrSheetGlob.getCell( aAddress );
- }
- return Reference< XCell >();
-}
-
Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const
{
return mrSheetGlob.getCellRange( rRange );