diff options
Diffstat (limited to 'sc/source/filter/oox/sheetdatacontext.cxx')
-rw-r--r-- | sc/source/filter/oox/sheetdatacontext.cxx | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx new file mode 100644 index 000000000..f4a9330b4 --- /dev/null +++ b/sc/source/filter/oox/sheetdatacontext.cxx @@ -0,0 +1,583 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sheetdatacontext.hxx> + +#include <oox/core/xmlfilterbase.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/helper/binaryinputstream.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <addressconverter.hxx> +#include <biffhelper.hxx> +#include <formulaparser.hxx> +#include <richstringcontext.hxx> +#include <sal/log.hxx> +#include <o3tl/string_view.hxx> + +namespace oox::xls { + +using ::oox::core::ContextHandlerRef; + +namespace { + +// record constants ----------------------------------------------------------- + +const sal_uInt32 BIFF12_CELL_SHOWPHONETIC = 0x01000000; + +const sal_uInt8 BIFF12_DATATABLE_ROW = 0x01; +const sal_uInt8 BIFF12_DATATABLE_2D = 0x02; +const sal_uInt8 BIFF12_DATATABLE_REF1DEL = 0x04; +const sal_uInt8 BIFF12_DATATABLE_REF2DEL = 0x08; + +const sal_uInt16 BIFF12_ROW_THICKTOP = 0x0001; +const sal_uInt16 BIFF12_ROW_THICKBOTTOM = 0x0002; +const sal_uInt16 BIFF12_ROW_COLLAPSED = 0x0800; +const sal_uInt16 BIFF12_ROW_HIDDEN = 0x1000; +const sal_uInt16 BIFF12_ROW_CUSTOMHEIGHT = 0x2000; +const sal_uInt16 BIFF12_ROW_CUSTOMFORMAT = 0x4000; +const sal_uInt8 BIFF12_ROW_SHOWPHONETIC = 0x01; + +} // namespace + +SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) : + WorksheetContextBase( rFragment ), + mrAddressConv( rFragment.getAddressConverter() ), + mrSheetData( rFragment.getSheetData() ), + mnSheet( rFragment.getSheetIndex() ), + mbHasFormula( false ), + mbValidRange( false ), + mnRow( -1 ), + mnCol( -1 ) +{ + SAL_INFO( "sc.filter", "start safe sheet data context - unlock" ); + mxFormulaParser.reset(rFragment.createFormulaParser()); +} + +SheetDataContext::~SheetDataContext() +{ + SAL_INFO( "sc.filter", "end safe sheet data context - relock" ); +} + +ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case XLS_TOKEN( sheetData ): + if( nElement == XLS_TOKEN( row ) ) { importRow( rAttribs ); return this; } + break; + + case XLS_TOKEN( row ): + // 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 ): + switch( nElement ) + { + case XLS_TOKEN( is ): + mxInlineStr = std::make_shared<RichString>( *this ); + return new RichStringContext( *this, mxInlineStr ); + case XLS_TOKEN( v ): + return this; // characters contain cell value + case XLS_TOKEN( f ): + importFormula( rAttribs ); + return this; // characters contain formula string + } + break; + } + return nullptr; +} + +void SheetDataContext::onCharacters( const OUString& rChars ) +{ + switch( getCurrentElement() ) + { + case XLS_TOKEN( v ): + maCellValue = rChars; + break; + case XLS_TOKEN( f ): + if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID ) + { + maFormulaStr = rChars; + } + break; + } +} + +void SheetDataContext::onEndElement() +{ + if( getCurrentElement() != XLS_TOKEN( c ) ) + return; + + // try to create a formula cell + if( mbHasFormula ) switch( maFmlaData.mnFormulaType ) + { + // will buffer formulas but need to + // a) need to set format first + // :/ + case XML_normal: + setCellFormula( maCellData.maCellAddr, maFormulaStr ); + mrSheetData.setCellFormat( maCellData ); + + // If a number cell has some preloaded value, stick it into the buffer + // but do this only for real cell formulas (not array, shared etc.) + if (!maCellValue.isEmpty()) + setCellFormulaValue(maCellData.maCellAddr, maCellValue, maCellData.mnCellType); + break; + + case XML_shared: + if( maFmlaData.mnSharedId >= 0 ) + { + if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + createSharedFormulaMapEntry(maCellData.maCellAddr, maFmlaData.mnSharedId, maFormulaStr); + + setCellFormula(maCellData.maCellAddr, maFmlaData.mnSharedId, maCellValue, maCellData.mnCellType); + mrSheetData.setCellFormat( maCellData ); + } + else + // no success, set plain cell value and formatting below + mbHasFormula = false; + break; + case XML_array: + if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) + { + setCellArrayFormula( maFmlaData.maFormulaRef, maCellData.maCellAddr, maFormulaStr ); + } + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + case XML_dataTable: + if( mbValidRange ) + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData ); + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + default: + OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" ); + mbHasFormula = false; + } + + if( mbHasFormula ) + return; + + // no formula created: try to set the cell value + if( !maCellValue.isEmpty() ) switch( maCellData.mnCellType ) + { + case XML_n: + mrSheetData.setValueCell( maCellData, maCellValue.toDouble() ); + break; + case XML_b: + mrSheetData.setBooleanCell( maCellData, maCellValue.toDouble() != 0.0 ); + break; + case XML_e: + mrSheetData.setErrorCell( maCellData, maCellValue ); + break; + case XML_str: + mrSheetData.setStringCell( maCellData, maCellValue ); + break; + case XML_s: + mrSheetData.setStringCell( maCellData, maCellValue.toInt32() ); + break; + case XML_d: + mrSheetData.setDateCell( maCellData, maCellValue ); + break; + } + else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr ) + { + mxInlineStr->finalizeImport(); + mrSheetData.setStringCell( maCellData, mxInlineStr ); + } + else + { + // empty cell, update cell type + maCellData.mnCellType = XML_TOKEN_INVALID; + mrSheetData.setBlankCell( maCellData ); + } +} + +ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) +{ + switch( getCurrentElement() ) + { + case BIFF12_ID_SHEETDATA: + if( nRecId == BIFF12_ID_ROW ) { importRow( rStrm ); return this; } + break; + + case BIFF12_ID_ROW: + switch( nRecId ) + { + case BIFF12_ID_ARRAY: importArray( rStrm ); break; + case BIFF12_ID_CELL_BOOL: importCellBool( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_BLANK: importCellBlank( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_DOUBLE: importCellDouble( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_ERROR: importCellError( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_RK: importCellRk( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_RSTRING: importCellRString( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_SI: importCellSi( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_CELL_STRING: importCellString( rStrm, CELLTYPE_VALUE ); break; + case BIFF12_ID_DATATABLE: importDataTable( rStrm ); break; + case BIFF12_ID_FORMULA_BOOL: importCellBool( rStrm, CELLTYPE_FORMULA ); break; + case BIFF12_ID_FORMULA_DOUBLE: importCellDouble( rStrm, CELLTYPE_FORMULA ); break; + case BIFF12_ID_FORMULA_ERROR: importCellError( rStrm, CELLTYPE_FORMULA ); break; + case BIFF12_ID_FORMULA_STRING: importCellString( rStrm, CELLTYPE_FORMULA ); break; + case BIFF12_ID_MULTCELL_BOOL: importCellBool( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_BLANK: importCellBlank( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_DOUBLE: importCellDouble( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_ERROR: importCellError( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_RK: importCellRk( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_RSTRING:importCellRString( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_SI: importCellSi( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_MULTCELL_STRING: importCellString( rStrm, CELLTYPE_MULTI ); break; + case BIFF12_ID_SHAREDFMLA: importSharedFmla( rStrm ); break; + } + break; + } + return nullptr; +} + +// private -------------------------------------------------------------------- + +void SheetDataContext::importRow( const AttributeList& rAttribs ) +{ + RowModel aModel; + sal_Int32 nRow = rAttribs.getInteger( XML_r, -1 ); // 1-based row index + if(nRow != -1) + { + aModel.mnRow = nRow; + mnRow = nRow-1; // to 0-based row index. + } + else + aModel.mnRow = (++mnRow + 1); // increment 0-based row index, to 1-based model row + mrAddressConv.checkRow( mnRow, true); + mnCol = -1; + + aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 ); + aModel.mnXfId = rAttribs.getInteger( XML_s, -1 ); + aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); + aModel.mbCustomHeight = rAttribs.getBool( XML_customHeight, false ); + aModel.mbCustomFormat = rAttribs.getBool( XML_customFormat, false ); + aModel.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); + aModel.mbHidden = rAttribs.getBool( XML_hidden, false ); + aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); + aModel.mbThickTop = rAttribs.getBool( XML_thickTop, false ); + aModel.mbThickBottom = rAttribs.getBool( XML_thickBot, false ); + + if (aModel.mfHeight > 0 && getFilter().isMSODocument()) + { + aModel.mfHeight -= fmod(aModel.mfHeight, 0.75); //round down to 0.75pt + } + + // decode the column spans (space-separated list of colon-separated integer pairs) + OUString aColSpansText = rAttribs.getString( XML_spans, OUString() ); + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Col(); + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + std::u16string_view aColSpanToken = o3tl::getToken(aColSpansText, 0, ' ', nIndex ); + size_t nSepPos = aColSpanToken.find( ':' ); + if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.size()) ) + { + // OOXML uses 1-based integer column indexes, row model expects 0-based colspans + const sal_Int32 nCol1 = o3tl::toInt32(aColSpanToken.substr( 0, nSepPos )) - 1; + const bool bValid1 = mrAddressConv.checkCol( nCol1, true); + if (bValid1) + { + const sal_Int32 nCol2 = o3tl::toInt32(aColSpanToken.substr( nSepPos + 1 )) - 1; + mrAddressConv.checkCol( nCol2, true); + aModel.insertColSpan( ValueRange( nCol1, ::std::min( nCol2, nMaxCol ))); + } + } + } + + // set row properties in the current sheet + setRowModel( aModel ); +} + +bool SheetDataContext::importCell( const AttributeList& rAttribs ) +{ + bool bValid = true; + const char* p = rAttribs.getChar(XML_r); + + if (!p) + { + ++mnCol; + ScAddress aAddress( mnCol, mnRow, mnSheet ); + bValid = mrAddressConv.checkCellAddress( aAddress, true ); + maCellData.maCellAddr = aAddress; + } + else + { + bValid = mrAddressConv.convertToCellAddress(maCellData.maCellAddr, p, mnSheet, true); + mnCol = maCellData.maCellAddr.Col(); + } + + if( bValid ) + { + maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n ); + maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 ); + maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); + + // reset cell value, formula settings, and inline string + maCellValue.clear(); + mxInlineStr.reset(); + mbHasFormula = false; + + // update used area of the sheet + extendUsedArea( maCellData.maCellAddr ); + } + return bValid; +} + +void SheetDataContext::importFormula( const AttributeList& rAttribs ) +{ + 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 ); + } + + maFormulaStr.clear(); +} + +void SheetDataContext::importRow( SequenceInputStream& rStrm ) +{ + RowModel aModel; + sal_Int32 nSpanCount; + sal_uInt16 nHeight, nFlags1; + sal_uInt8 nFlags2; + maCurrPos.mnRow = rStrm.readInt32(); + aModel.mnXfId = rStrm.readInt32(); + nHeight = rStrm.readuInt16(); + nFlags1 = rStrm.readuInt16(); + nFlags2 = rStrm.readuChar(); + nSpanCount = rStrm.readInt32(); + maCurrPos.mnCol = 0; + + mrAddressConv.checkRow( maCurrPos.mnRow, true); + // row index is 0-based in BIFF12, but RowModel expects 1-based + aModel.mnRow = 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 ); + + // read the column spans + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Col(); + for( sal_Int32 nSpanIdx = 0; (nSpanIdx < nSpanCount) && !rStrm.isEof(); ++nSpanIdx ) + { + sal_Int32 nFirstCol, nLastCol; + nFirstCol = rStrm.readInt32(); + const bool bValid1 = mrAddressConv.checkCol( nFirstCol, true); + nLastCol = rStrm.readInt32(); + mrAddressConv.checkCol( nLastCol, true); + if (bValid1) + aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) ); + } + + // set row properties in the current sheet + setRowModel( aModel ); +} + +bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType ) +{ + switch( eCellType ) + { + case CELLTYPE_VALUE: + case CELLTYPE_FORMULA: maCurrPos.mnCol = rStrm.readInt32(); break; + case CELLTYPE_MULTI: ++maCurrPos.mnCol; break; + } + + sal_uInt32 nXfId = rStrm.readuInt32(); + + 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( bValidAddr ) + extendUsedArea( maCellData.maCellAddr ); + return bValidAddr; +} + +ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm ) +{ + rStrm.skip( 2 ); + return mxFormulaParser->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 ) +{ + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_b; + bool bValue = rStrm.readuInt8() != 0; + if( eCellType == CELLTYPE_FORMULA ) + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); + else + mrSheetData.setBooleanCell( maCellData, bValue ); + } +} + +void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType ) +{ + OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" ); + if( readCellHeader( rStrm, eCellType ) ) + mrSheetData.setBlankCell( maCellData ); +} + +void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType ) +{ + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_n; + double fValue = rStrm.readDouble(); + if( eCellType == CELLTYPE_FORMULA ) + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); + else + mrSheetData.setValueCell( maCellData, fValue ); + } +} + +void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType ) +{ + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_e; + sal_uInt8 nErrorCode = rStrm.readuInt8(); + if( eCellType == CELLTYPE_FORMULA ) + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); + else + mrSheetData.setErrorCell( maCellData, nErrorCode ); + } +} + +void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType ) +{ + OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); + } +} + +void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType ) +{ + OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_inlineStr; + RichStringRef xString = std::make_shared<RichString>( *this ); + xString->importString( rStrm, true ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); + } +} + +void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType ) +{ + OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_s; + mrSheetData.setStringCell( maCellData, rStrm.readInt32() ); + } +} + +void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType ) +{ + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_inlineStr; + // always import the string, stream will point to formula afterwards, if existing + RichStringRef xString = std::make_shared<RichString>( *this ); + xString->importString( rStrm, false ); + xString->finalizeImport(); + if( eCellType == CELLTYPE_FORMULA ) + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); + else + mrSheetData.setStringCell( maCellData, xString ); + } +} + +void SheetDataContext::importArray( SequenceInputStream& rStrm ) +{ + if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) + { + rStrm.skip( 1 ); + ApiTokenSequence aTokens = mxFormulaParser->importFormula( maCellData.maCellAddr, FormulaType::Array, rStrm ); + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens ); + } +} + +void SheetDataContext::importDataTable( SequenceInputStream& rStrm ) +{ + if( !readFormulaRef( rStrm ) ) + return; + + BinAddress aRef1, aRef2; + sal_uInt8 nFlags; + rStrm >> aRef1 >> aRef2; + nFlags = rStrm.readuChar(); + 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 = mxFormulaParser->importFormula( maCellData.maCellAddr, FormulaType::SharedFormula, rStrm ); + mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens ); + } +} + +} // namespace oox + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |