1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sheetdatacontext.hxx>
22 #include <oox/helper/attributelist.hxx>
23 #include <oox/helper/binaryinputstream.hxx>
24 #include <oox/token/namespaces.hxx>
25 #include <oox/token/tokens.hxx>
26 #include <addressconverter.hxx>
27 #include <biffhelper.hxx>
28 #include <formulaparser.hxx>
29 #include <richstringcontext.hxx>
30 #include <sal/log.hxx>
35 using ::oox::core::ContextHandlerRef
;
39 // record constants -----------------------------------------------------------
41 const sal_uInt32 BIFF12_CELL_SHOWPHONETIC
= 0x01000000;
43 const sal_uInt8 BIFF12_DATATABLE_ROW
= 0x01;
44 const sal_uInt8 BIFF12_DATATABLE_2D
= 0x02;
45 const sal_uInt8 BIFF12_DATATABLE_REF1DEL
= 0x04;
46 const sal_uInt8 BIFF12_DATATABLE_REF2DEL
= 0x08;
48 const sal_uInt16 BIFF12_ROW_THICKTOP
= 0x0001;
49 const sal_uInt16 BIFF12_ROW_THICKBOTTOM
= 0x0002;
50 const sal_uInt16 BIFF12_ROW_COLLAPSED
= 0x0800;
51 const sal_uInt16 BIFF12_ROW_HIDDEN
= 0x1000;
52 const sal_uInt16 BIFF12_ROW_CUSTOMHEIGHT
= 0x2000;
53 const sal_uInt16 BIFF12_ROW_CUSTOMFORMAT
= 0x4000;
54 const sal_uInt8 BIFF12_ROW_SHOWPHONETIC
= 0x01;
58 SheetDataContextBase::SheetDataContextBase( const WorksheetHelper
& rHelper
) :
59 mrAddressConv( rHelper
.getAddressConverter() ),
60 mrSheetData( rHelper
.getSheetData() ),
61 mnSheet( rHelper
.getSheetIndex() )
63 mxFormulaParser
.reset(rHelper
.createFormulaParser());
66 SheetDataContextBase::~SheetDataContextBase()
70 SheetDataContext::SheetDataContext( WorksheetFragmentBase
& rFragment
) :
71 WorksheetContextBase( rFragment
),
72 SheetDataContextBase( rFragment
),
73 mbHasFormula( false ),
74 mbValidRange( false ),
78 SAL_INFO( "sc.filter", "start safe sheet data context - unlock" );
81 SheetDataContext::~SheetDataContext()
83 SAL_INFO( "sc.filter", "end safe sheet data context - relock" );
86 ContextHandlerRef
SheetDataContext::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
88 switch( getCurrentElement() )
90 case XLS_TOKEN( sheetData
):
91 if( nElement
== XLS_TOKEN( row
) ) { importRow( rAttribs
); return this; }
94 case XLS_TOKEN( row
):
95 // do not process cell elements with invalid (out-of-range) address
96 if( nElement
== XLS_TOKEN( c
) && importCell( rAttribs
) )
103 case XLS_TOKEN( is
):
104 mxInlineStr
.reset( new RichString( *this ) );
105 return new RichStringContext( *this, mxInlineStr
);
107 return this; // characters contain cell value
109 importFormula( rAttribs
);
110 return this; // characters contain formula string
117 void SheetDataContext::onCharacters( const OUString
& rChars
)
119 switch( getCurrentElement() )
122 maCellValue
= rChars
;
125 if( maFmlaData
.mnFormulaType
!= XML_TOKEN_INVALID
)
127 maFormulaStr
= rChars
;
133 void SheetDataContext::onEndElement()
135 if( getCurrentElement() == XLS_TOKEN( c
) )
137 // try to create a formula cell
138 if( mbHasFormula
) switch( maFmlaData
.mnFormulaType
)
140 // will buffer formulas but need to
141 // a) need to set format first
144 setCellFormula( maCellData
.maCellAddr
, maFormulaStr
);
145 mrSheetData
.setCellFormat( maCellData
);
147 // If a number cell has some preloaded value, stick it into the buffer
148 // but do this only for real cell formulas (not array, shared etc.)
149 if (!maCellValue
.isEmpty())
150 setCellFormulaValue(maCellData
.maCellAddr
, maCellValue
, maCellData
.mnCellType
);
154 if( maFmlaData
.mnSharedId
>= 0 )
156 if( mbValidRange
&& maFmlaData
.isValidSharedRef( maCellData
.maCellAddr
) )
157 createSharedFormulaMapEntry(maCellData
.maCellAddr
, maFmlaData
.mnSharedId
, maFormulaStr
);
159 setCellFormula(maCellData
.maCellAddr
, maFmlaData
.mnSharedId
, maCellValue
, maCellData
.mnCellType
);
160 mrSheetData
.setCellFormat( maCellData
);
163 // no success, set plain cell value and formatting below
164 mbHasFormula
= false;
167 if( mbValidRange
&& maFmlaData
.isValidArrayRef( maCellData
.maCellAddr
) )
169 setCellArrayFormula( maFmlaData
.maFormulaRef
, maCellData
.maCellAddr
, maFormulaStr
);
171 // set cell formatting, but do not set result as cell value
172 mrSheetData
.setBlankCell( maCellData
);
176 mrSheetData
.createTableOperation( maFmlaData
.maFormulaRef
, maTableData
);
177 // set cell formatting, but do not set result as cell value
178 mrSheetData
.setBlankCell( maCellData
);
181 OSL_ENSURE( maFmlaData
.mnFormulaType
== XML_TOKEN_INVALID
, "SheetDataContext::onEndElement - unknown formula type" );
182 mbHasFormula
= false;
187 // no formula created: try to set the cell value
188 if( !maCellValue
.isEmpty() ) switch( maCellData
.mnCellType
)
191 mrSheetData
.setValueCell( maCellData
, maCellValue
.toDouble() );
194 mrSheetData
.setBooleanCell( maCellData
, maCellValue
.toDouble() != 0.0 );
197 mrSheetData
.setErrorCell( maCellData
, maCellValue
);
200 mrSheetData
.setStringCell( maCellData
, maCellValue
);
203 mrSheetData
.setStringCell( maCellData
, maCellValue
.toInt32() );
206 mrSheetData
.setDateCell( maCellData
, maCellValue
);
209 else if( (maCellData
.mnCellType
== XML_inlineStr
) && mxInlineStr
.get() )
211 mxInlineStr
->finalizeImport();
212 mrSheetData
.setStringCell( maCellData
, mxInlineStr
);
216 // empty cell, update cell type
217 maCellData
.mnCellType
= XML_TOKEN_INVALID
;
218 mrSheetData
.setBlankCell( maCellData
);
224 ContextHandlerRef
SheetDataContext::onCreateRecordContext( sal_Int32 nRecId
, SequenceInputStream
& rStrm
)
226 switch( getCurrentElement() )
228 case BIFF12_ID_SHEETDATA
:
229 if( nRecId
== BIFF12_ID_ROW
) { importRow( rStrm
); return this; }
235 case BIFF12_ID_ARRAY
: importArray( rStrm
); break;
236 case BIFF12_ID_CELL_BOOL
: importCellBool( rStrm
, CELLTYPE_VALUE
); break;
237 case BIFF12_ID_CELL_BLANK
: importCellBlank( rStrm
, CELLTYPE_VALUE
); break;
238 case BIFF12_ID_CELL_DOUBLE
: importCellDouble( rStrm
, CELLTYPE_VALUE
); break;
239 case BIFF12_ID_CELL_ERROR
: importCellError( rStrm
, CELLTYPE_VALUE
); break;
240 case BIFF12_ID_CELL_RK
: importCellRk( rStrm
, CELLTYPE_VALUE
); break;
241 case BIFF12_ID_CELL_RSTRING
: importCellRString( rStrm
, CELLTYPE_VALUE
); break;
242 case BIFF12_ID_CELL_SI
: importCellSi( rStrm
, CELLTYPE_VALUE
); break;
243 case BIFF12_ID_CELL_STRING
: importCellString( rStrm
, CELLTYPE_VALUE
); break;
244 case BIFF12_ID_DATATABLE
: importDataTable( rStrm
); break;
245 case BIFF12_ID_FORMULA_BOOL
: importCellBool( rStrm
, CELLTYPE_FORMULA
); break;
246 case BIFF12_ID_FORMULA_DOUBLE
: importCellDouble( rStrm
, CELLTYPE_FORMULA
); break;
247 case BIFF12_ID_FORMULA_ERROR
: importCellError( rStrm
, CELLTYPE_FORMULA
); break;
248 case BIFF12_ID_FORMULA_STRING
: importCellString( rStrm
, CELLTYPE_FORMULA
); break;
249 case BIFF12_ID_MULTCELL_BOOL
: importCellBool( rStrm
, CELLTYPE_MULTI
); break;
250 case BIFF12_ID_MULTCELL_BLANK
: importCellBlank( rStrm
, CELLTYPE_MULTI
); break;
251 case BIFF12_ID_MULTCELL_DOUBLE
: importCellDouble( rStrm
, CELLTYPE_MULTI
); break;
252 case BIFF12_ID_MULTCELL_ERROR
: importCellError( rStrm
, CELLTYPE_MULTI
); break;
253 case BIFF12_ID_MULTCELL_RK
: importCellRk( rStrm
, CELLTYPE_MULTI
); break;
254 case BIFF12_ID_MULTCELL_RSTRING
:importCellRString( rStrm
, CELLTYPE_MULTI
); break;
255 case BIFF12_ID_MULTCELL_SI
: importCellSi( rStrm
, CELLTYPE_MULTI
); break;
256 case BIFF12_ID_MULTCELL_STRING
: importCellString( rStrm
, CELLTYPE_MULTI
); break;
257 case BIFF12_ID_SHAREDFMLA
: importSharedFmla( rStrm
); break;
264 // private --------------------------------------------------------------------
266 void SheetDataContext::importRow( const AttributeList
& rAttribs
)
269 sal_Int32 nRow
= rAttribs
.getInteger( XML_r
, -1 ); // 1-based row index
273 mnRow
= nRow
-1; // to 0-based row index.
276 aModel
.mnRow
= (++mnRow
+ 1); // increment 0-based row index, to 1-based model row
277 mrAddressConv
.checkRow( mnRow
, true);
280 aModel
.mfHeight
= rAttribs
.getDouble( XML_ht
, -1.0 );
281 aModel
.mnXfId
= rAttribs
.getInteger( XML_s
, -1 );
282 aModel
.mnLevel
= rAttribs
.getInteger( XML_outlineLevel
, 0 );
283 aModel
.mbCustomHeight
= rAttribs
.getBool( XML_customHeight
, false );
284 aModel
.mbCustomFormat
= rAttribs
.getBool( XML_customFormat
, false );
285 aModel
.mbShowPhonetic
= rAttribs
.getBool( XML_ph
, false );
286 aModel
.mbHidden
= rAttribs
.getBool( XML_hidden
, false );
287 aModel
.mbCollapsed
= rAttribs
.getBool( XML_collapsed
, false );
288 aModel
.mbThickTop
= rAttribs
.getBool( XML_thickTop
, false );
289 aModel
.mbThickBottom
= rAttribs
.getBool( XML_thickBot
, false );
291 // decode the column spans (space-separated list of colon-separated integer pairs)
292 OUString aColSpansText
= rAttribs
.getString( XML_spans
, OUString() );
293 sal_Int32 nMaxCol
= mrAddressConv
.getMaxApiAddress().Col();
294 sal_Int32 nIndex
= 0;
297 OUString aColSpanToken
= aColSpansText
.getToken( 0, ' ', nIndex
);
298 sal_Int32 nSepPos
= aColSpanToken
.indexOf( ':' );
299 if( (0 < nSepPos
) && (nSepPos
+ 1 < aColSpanToken
.getLength()) )
301 // OOXML uses 1-based integer column indexes, row model expects 0-based colspans
302 const sal_Int32 nCol1
= aColSpanToken
.copy( 0, nSepPos
).toInt32() - 1;
303 const bool bValid1
= mrAddressConv
.checkCol( nCol1
, true);
306 const sal_Int32 nCol2
= aColSpanToken
.copy( nSepPos
+ 1 ).toInt32() - 1;
307 mrAddressConv
.checkCol( nCol2
, true);
308 aModel
.insertColSpan( ValueRange( nCol1
, ::std::min( nCol2
, nMaxCol
)));
313 // set row properties in the current sheet
314 setRowModel( aModel
);
317 bool SheetDataContext::importCell( const AttributeList
& rAttribs
)
320 const char* p
= rAttribs
.getChar(XML_r
);
325 ScAddress
aAddress( mnCol
, mnRow
, mnSheet
);
326 bValid
= mrAddressConv
.checkCellAddress( aAddress
, true );
327 maCellData
.maCellAddr
= aAddress
;
331 bValid
= mrAddressConv
.convertToCellAddress(maCellData
.maCellAddr
, p
, mnSheet
, true);
332 mnCol
= maCellData
.maCellAddr
.Col();
337 maCellData
.mnCellType
= rAttribs
.getToken( XML_t
, XML_n
);
338 maCellData
.mnXfId
= rAttribs
.getInteger( XML_s
, -1 );
339 maCellData
.mbShowPhonetic
= rAttribs
.getBool( XML_ph
, false );
341 // reset cell value, formula settings, and inline string
344 mbHasFormula
= false;
346 // update used area of the sheet
347 extendUsedArea( maCellData
.maCellAddr
);
352 void SheetDataContext::importFormula( const AttributeList
& rAttribs
)
355 mbValidRange
= mrAddressConv
.convertToCellRange( maFmlaData
.maFormulaRef
, rAttribs
.getString( XML_ref
, OUString() ), mnSheet
, true, true );
357 maFmlaData
.mnFormulaType
= rAttribs
.getToken( XML_t
, XML_normal
);
358 maFmlaData
.mnSharedId
= rAttribs
.getInteger( XML_si
, -1 );
360 if( maFmlaData
.mnFormulaType
== XML_dataTable
)
362 maTableData
.maRef1
= rAttribs
.getString( XML_r1
, OUString() );
363 maTableData
.maRef2
= rAttribs
.getString( XML_r2
, OUString() );
364 maTableData
.mb2dTable
= rAttribs
.getBool( XML_dt2D
, false );
365 maTableData
.mbRowTable
= rAttribs
.getBool( XML_dtr
, false );
366 maTableData
.mbRef1Deleted
= rAttribs
.getBool( XML_del1
, false );
367 maTableData
.mbRef2Deleted
= rAttribs
.getBool( XML_del2
, false );
370 maFormulaStr
.clear();
373 void SheetDataContext::importRow( SequenceInputStream
& rStrm
)
376 sal_Int32 nSpanCount
;
377 sal_uInt16 nHeight
, nFlags1
;
379 maCurrPos
.mnRow
= rStrm
.readInt32();
380 aModel
.mnXfId
= rStrm
.readInt32();
381 nHeight
= rStrm
.readuInt16();
382 nFlags1
= rStrm
.readuInt16();
383 nFlags2
= rStrm
.readuChar();
384 nSpanCount
= rStrm
.readInt32();
387 mrAddressConv
.checkRow( maCurrPos
.mnRow
, true);
388 // row index is 0-based in BIFF12, but RowModel expects 1-based
389 aModel
.mnRow
= maCurrPos
.mnRow
+ 1;
390 // row height is in twips in BIFF12, convert to points
391 aModel
.mfHeight
= nHeight
/ 20.0;
392 aModel
.mnLevel
= extractValue
< sal_Int32
>( nFlags1
, 8, 3 );
393 aModel
.mbCustomHeight
= getFlag( nFlags1
, BIFF12_ROW_CUSTOMHEIGHT
);
394 aModel
.mbCustomFormat
= getFlag( nFlags1
, BIFF12_ROW_CUSTOMFORMAT
);
395 aModel
.mbShowPhonetic
= getFlag( nFlags2
, BIFF12_ROW_SHOWPHONETIC
);
396 aModel
.mbHidden
= getFlag( nFlags1
, BIFF12_ROW_HIDDEN
);
397 aModel
.mbCollapsed
= getFlag( nFlags1
, BIFF12_ROW_COLLAPSED
);
398 aModel
.mbThickTop
= getFlag( nFlags1
, BIFF12_ROW_THICKTOP
);
399 aModel
.mbThickBottom
= getFlag( nFlags1
, BIFF12_ROW_THICKBOTTOM
);
401 // read the column spans
402 sal_Int32 nMaxCol
= mrAddressConv
.getMaxApiAddress().Col();
403 for( sal_Int32 nSpanIdx
= 0; (nSpanIdx
< nSpanCount
) && !rStrm
.isEof(); ++nSpanIdx
)
405 sal_Int32 nFirstCol
, nLastCol
;
406 nFirstCol
= rStrm
.readInt32();
407 const bool bValid1
= mrAddressConv
.checkCol( nFirstCol
, true);
408 nLastCol
= rStrm
.readInt32();
409 mrAddressConv
.checkCol( nLastCol
, true);
411 aModel
.insertColSpan( ValueRange( nFirstCol
, ::std::min( nLastCol
, nMaxCol
) ) );
414 // set row properties in the current sheet
415 setRowModel( aModel
);
418 bool SheetDataContext::readCellHeader( SequenceInputStream
& rStrm
, CellType eCellType
)
423 case CELLTYPE_FORMULA
: maCurrPos
.mnCol
= rStrm
.readInt32(); break;
424 case CELLTYPE_MULTI
: ++maCurrPos
.mnCol
; break;
427 sal_uInt32 nXfId
= rStrm
.readuInt32();
429 bool bValidAddr
= mrAddressConv
.convertToCellAddress( maCellData
.maCellAddr
, maCurrPos
, mnSheet
, true );
430 maCellData
.mnXfId
= extractValue
< sal_Int32
>( nXfId
, 0, 24 );
431 maCellData
.mbShowPhonetic
= getFlag( nXfId
, BIFF12_CELL_SHOWPHONETIC
);
433 // update used area of the sheet
435 extendUsedArea( maCellData
.maCellAddr
);
439 ApiTokenSequence
SheetDataContext::readCellFormula( SequenceInputStream
& rStrm
)
442 return mxFormulaParser
->importFormula( maCellData
.maCellAddr
, FormulaType::Cell
, rStrm
);
445 bool SheetDataContext::readFormulaRef( SequenceInputStream
& rStrm
)
449 return mrAddressConv
.convertToCellRange( maFmlaData
.maFormulaRef
, aRange
, mnSheet
, true, true );
452 void SheetDataContext::importCellBool( SequenceInputStream
& rStrm
, CellType eCellType
)
454 if( readCellHeader( rStrm
, eCellType
) )
456 maCellData
.mnCellType
= XML_b
;
457 bool bValue
= rStrm
.readuInt8() != 0;
458 if( eCellType
== CELLTYPE_FORMULA
)
459 mrSheetData
.setFormulaCell( maCellData
, readCellFormula( rStrm
) );
461 mrSheetData
.setBooleanCell( maCellData
, bValue
);
465 void SheetDataContext::importCellBlank( SequenceInputStream
& rStrm
, CellType eCellType
)
467 OSL_ENSURE( eCellType
!= CELLTYPE_FORMULA
, "SheetDataContext::importCellBlank - no formula cells supported" );
468 if( readCellHeader( rStrm
, eCellType
) )
469 mrSheetData
.setBlankCell( maCellData
);
472 void SheetDataContext::importCellDouble( SequenceInputStream
& rStrm
, CellType eCellType
)
474 if( readCellHeader( rStrm
, eCellType
) )
476 maCellData
.mnCellType
= XML_n
;
477 double fValue
= rStrm
.readDouble();
478 if( eCellType
== CELLTYPE_FORMULA
)
479 mrSheetData
.setFormulaCell( maCellData
, readCellFormula( rStrm
) );
481 mrSheetData
.setValueCell( maCellData
, fValue
);
485 void SheetDataContext::importCellError( SequenceInputStream
& rStrm
, CellType eCellType
)
487 if( readCellHeader( rStrm
, eCellType
) )
489 maCellData
.mnCellType
= XML_e
;
490 sal_uInt8 nErrorCode
= rStrm
.readuInt8();
491 if( eCellType
== CELLTYPE_FORMULA
)
492 mrSheetData
.setFormulaCell( maCellData
, readCellFormula( rStrm
) );
494 mrSheetData
.setErrorCell( maCellData
, nErrorCode
);
498 void SheetDataContext::importCellRk( SequenceInputStream
& rStrm
, CellType eCellType
)
500 OSL_ENSURE( eCellType
!= CELLTYPE_FORMULA
, "SheetDataContext::importCellRk - no formula cells supported" );
501 if( readCellHeader( rStrm
, eCellType
) )
503 maCellData
.mnCellType
= XML_n
;
504 mrSheetData
.setValueCell( maCellData
, BiffHelper::calcDoubleFromRk( rStrm
.readInt32() ) );
508 void SheetDataContext::importCellRString( SequenceInputStream
& rStrm
, CellType eCellType
)
510 OSL_ENSURE( eCellType
!= CELLTYPE_FORMULA
, "SheetDataContext::importCellRString - no formula cells supported" );
511 if( readCellHeader( rStrm
, eCellType
) )
513 maCellData
.mnCellType
= XML_inlineStr
;
514 RichStringRef
xString( new RichString( *this ) );
515 xString
->importString( rStrm
, true );
516 xString
->finalizeImport();
517 mrSheetData
.setStringCell( maCellData
, xString
);
521 void SheetDataContext::importCellSi( SequenceInputStream
& rStrm
, CellType eCellType
)
523 OSL_ENSURE( eCellType
!= CELLTYPE_FORMULA
, "SheetDataContext::importCellSi - no formula cells supported" );
524 if( readCellHeader( rStrm
, eCellType
) )
526 maCellData
.mnCellType
= XML_s
;
527 mrSheetData
.setStringCell( maCellData
, rStrm
.readInt32() );
531 void SheetDataContext::importCellString( SequenceInputStream
& rStrm
, CellType eCellType
)
533 if( readCellHeader( rStrm
, eCellType
) )
535 maCellData
.mnCellType
= XML_inlineStr
;
536 // always import the string, stream will point to formula afterwards, if existing
537 RichStringRef
xString( new RichString( *this ) );
538 xString
->importString( rStrm
, false );
539 xString
->finalizeImport();
540 if( eCellType
== CELLTYPE_FORMULA
)
541 mrSheetData
.setFormulaCell( maCellData
, readCellFormula( rStrm
) );
543 mrSheetData
.setStringCell( maCellData
, xString
);
547 void SheetDataContext::importArray( SequenceInputStream
& rStrm
)
549 if( readFormulaRef( rStrm
) && maFmlaData
.isValidArrayRef( maCellData
.maCellAddr
) )
552 ApiTokenSequence aTokens
= mxFormulaParser
->importFormula( maCellData
.maCellAddr
, FormulaType::Array
, rStrm
);
553 mrSheetData
.createArrayFormula( maFmlaData
.maFormulaRef
, aTokens
);
557 void SheetDataContext::importDataTable( SequenceInputStream
& rStrm
)
559 if( readFormulaRef( rStrm
) )
561 BinAddress aRef1
, aRef2
;
563 rStrm
>> aRef1
>> aRef2
;
564 nFlags
= rStrm
.readuChar();
565 maTableData
.maRef1
= FormulaProcessorBase::generateAddress2dString( aRef1
, false );
566 maTableData
.maRef2
= FormulaProcessorBase::generateAddress2dString( aRef2
, false );
567 maTableData
.mbRowTable
= getFlag( nFlags
, BIFF12_DATATABLE_ROW
);
568 maTableData
.mb2dTable
= getFlag( nFlags
, BIFF12_DATATABLE_2D
);
569 maTableData
.mbRef1Deleted
= getFlag( nFlags
, BIFF12_DATATABLE_REF1DEL
);
570 maTableData
.mbRef2Deleted
= getFlag( nFlags
, BIFF12_DATATABLE_REF2DEL
);
571 mrSheetData
.createTableOperation( maFmlaData
.maFormulaRef
, maTableData
);
575 void SheetDataContext::importSharedFmla( SequenceInputStream
& rStrm
)
577 if( readFormulaRef( rStrm
) && maFmlaData
.isValidSharedRef( maCellData
.maCellAddr
) )
579 ApiTokenSequence aTokens
= mxFormulaParser
->importFormula( maCellData
.maCellAddr
, FormulaType::SharedFormula
, rStrm
);
580 mrSheetData
.createSharedFormula( maCellData
.maCellAddr
, aTokens
);
587 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */