xref: /core/sc/source/filter/oox/sheetdatacontext.cxx (revision 76fbe494)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sheetdatacontext.hxx>
21 
22 #include <oox/helper/attributelist.hxx>
23 #include <oox/helper/binaryinputstream.hxx>
24 #include <oox/helper/propertyset.hxx>
25 #include <oox/token/namespaces.hxx>
26 #include <oox/token/tokens.hxx>
27 #include <addressconverter.hxx>
28 #include <biffhelper.hxx>
29 #include <formulaparser.hxx>
30 #include <richstringcontext.hxx>
31 #include <unitconverter.hxx>
32 #include <sal/log.hxx>
33 
34 namespace oox {
35 namespace xls {
36 
37 using ::oox::core::ContextHandlerRef;
38 
39 namespace {
40 
41 // record constants -----------------------------------------------------------
42 
43 const sal_uInt32 BIFF12_CELL_SHOWPHONETIC   = 0x01000000;
44 
45 const sal_uInt8 BIFF12_DATATABLE_ROW        = 0x01;
46 const sal_uInt8 BIFF12_DATATABLE_2D         = 0x02;
47 const sal_uInt8 BIFF12_DATATABLE_REF1DEL    = 0x04;
48 const sal_uInt8 BIFF12_DATATABLE_REF2DEL    = 0x08;
49 
50 const sal_uInt16 BIFF12_ROW_THICKTOP        = 0x0001;
51 const sal_uInt16 BIFF12_ROW_THICKBOTTOM     = 0x0002;
52 const sal_uInt16 BIFF12_ROW_COLLAPSED       = 0x0800;
53 const sal_uInt16 BIFF12_ROW_HIDDEN          = 0x1000;
54 const sal_uInt16 BIFF12_ROW_CUSTOMHEIGHT    = 0x2000;
55 const sal_uInt16 BIFF12_ROW_CUSTOMFORMAT    = 0x4000;
56 const sal_uInt8 BIFF12_ROW_SHOWPHONETIC     = 0x01;
57 
58 } // namespace
59 
60 SheetDataContextBase::SheetDataContextBase( const WorksheetHelper& rHelper ) :
61     mrAddressConv( rHelper.getAddressConverter() ),
62     mrSheetData( rHelper.getSheetData() ),
63     mnSheet( rHelper.getSheetIndex() )
64 {
65     mxFormulaParser.reset(rHelper.createFormulaParser());
66 }
67 
68 SheetDataContextBase::~SheetDataContextBase()
69 {
70 }
71 
72 SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) :
73     WorksheetContextBase( rFragment ),
74     SheetDataContextBase( rFragment ),
75     mbHasFormula( false ),
76     mbValidRange( false ),
77     mnRow( -1 ),
78     mnCol( -1 )
79 {
80     SAL_INFO( "sc.filter",  "start safe sheet data context - unlock" );
81 }
82 
83 SheetDataContext::~SheetDataContext()
84 {
85     SAL_INFO( "sc.filter",  "end safe sheet data context - relock" );
86 }
87 
88 ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
89 {
90     switch( getCurrentElement() )
91     {
92         case XLS_TOKEN( sheetData ):
93             if( nElement == XLS_TOKEN( row ) ) { importRow( rAttribs ); return this; }
94         break;
95 
96         case XLS_TOKEN( row ):
97             // do not process cell elements with invalid (out-of-range) address
98             if( nElement == XLS_TOKEN( c ) && importCell( rAttribs ) )
99                 return this;
100         break;
101 
102         case XLS_TOKEN( c ):
103             switch( nElement )
104             {
105                 case XLS_TOKEN( is ):
106                     mxInlineStr.reset( new RichString( *this ) );
107                     return new RichStringContext( *this, mxInlineStr );
108                 case XLS_TOKEN( v ):
109                     return this;    // characters contain cell value
110                 case XLS_TOKEN( f ):
111                     importFormula( rAttribs );
112                     return this;    // characters contain formula string
113             }
114         break;
115     }
116     return nullptr;
117 }
118 
119 void SheetDataContext::onCharacters( const OUString& rChars )
120 {
121     switch( getCurrentElement() )
122     {
123         case XLS_TOKEN( v ):
124             maCellValue = rChars;
125         break;
126         case XLS_TOKEN( f ):
127             if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID )
128             {
129                 maFormulaStr = rChars;
130             }
131         break;
132     }
133 }
134 
135 void SheetDataContext::onEndElement()
136 {
137     if( getCurrentElement() == XLS_TOKEN( c ) )
138     {
139         // try to create a formula cell
140         if( mbHasFormula ) switch( maFmlaData.mnFormulaType )
141         {
142             // will buffer formulas but need to
143             // a) need to set format first
144             // :/
145             case XML_normal:
146                 setCellFormula( maCellData.maCellAddr, maFormulaStr );
147                 mrSheetData.setCellFormat( maCellData );
148 
149                 // If a number cell has some preloaded value, stick it into the buffer
150                 // but do this only for real cell formulas (not array, shared etc.)
151                 if (!maCellValue.isEmpty())
152                     setCellFormulaValue(maCellData.maCellAddr, maCellValue, maCellData.mnCellType);
153                 break;
154 
155             case XML_shared:
156                 if( maFmlaData.mnSharedId >= 0 )
157                 {
158                     if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
159                         createSharedFormulaMapEntry(maCellData.maCellAddr, maFmlaData.mnSharedId, maFormulaStr);
160 
161                     setCellFormula(maCellData.maCellAddr, maFmlaData.mnSharedId, maCellValue, maCellData.mnCellType);
162                     mrSheetData.setCellFormat( maCellData );
163                 }
164                 else
165                     // no success, set plain cell value and formatting below
166                     mbHasFormula = false;
167             break;
168             case XML_array:
169                 if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
170                 {
171                     setCellArrayFormula( maFmlaData.maFormulaRef, maCellData.maCellAddr, maFormulaStr );
172                 }
173                 // set cell formatting, but do not set result as cell value
174                 mrSheetData.setBlankCell( maCellData );
175             break;
176             case XML_dataTable:
177                 if( mbValidRange )
178                     mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
179                 // set cell formatting, but do not set result as cell value
180                 mrSheetData.setBlankCell( maCellData );
181             break;
182             default:
183                 OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" );
184                 mbHasFormula = false;
185         }
186 
187         if( !mbHasFormula )
188         {
189             // no formula created: try to set the cell value
190             if( !maCellValue.isEmpty() ) switch( maCellData.mnCellType )
191             {
192                 case XML_n:
193                     mrSheetData.setValueCell( maCellData, maCellValue.toDouble() );
194                 break;
195                 case XML_b:
196                     mrSheetData.setBooleanCell( maCellData, maCellValue.toDouble() != 0.0 );
197                 break;
198                 case XML_e:
199                     mrSheetData.setErrorCell( maCellData, maCellValue );
200                 break;
201                 case XML_str:
202                     mrSheetData.setStringCell( maCellData, maCellValue );
203                 break;
204                 case XML_s:
205                     mrSheetData.setStringCell( maCellData, maCellValue.toInt32() );
206                 break;
207                 case XML_d:
208                     mrSheetData.setDateCell( maCellData, maCellValue );
209                 break;
210             }
211             else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr.get() )
212             {
213                 mxInlineStr->finalizeImport();
214                 mrSheetData.setStringCell( maCellData, mxInlineStr );
215             }
216             else
217             {
218                 // empty cell, update cell type
219                 maCellData.mnCellType = XML_TOKEN_INVALID;
220                 mrSheetData.setBlankCell( maCellData );
221             }
222         }
223     }
224 }
225 
226 ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
227 {
228     switch( getCurrentElement() )
229     {
230         case BIFF12_ID_SHEETDATA:
231             if( nRecId == BIFF12_ID_ROW ) { importRow( rStrm ); return this; }
232         break;
233 
234         case BIFF12_ID_ROW:
235             switch( nRecId )
236             {
237                 case BIFF12_ID_ARRAY:           importArray( rStrm );                           break;
238                 case BIFF12_ID_CELL_BOOL:       importCellBool( rStrm, CELLTYPE_VALUE );        break;
239                 case BIFF12_ID_CELL_BLANK:      importCellBlank( rStrm, CELLTYPE_VALUE );       break;
240                 case BIFF12_ID_CELL_DOUBLE:     importCellDouble( rStrm, CELLTYPE_VALUE );      break;
241                 case BIFF12_ID_CELL_ERROR:      importCellError( rStrm, CELLTYPE_VALUE );       break;
242                 case BIFF12_ID_CELL_RK:         importCellRk( rStrm, CELLTYPE_VALUE );          break;
243                 case BIFF12_ID_CELL_RSTRING:    importCellRString( rStrm, CELLTYPE_VALUE );     break;
244                 case BIFF12_ID_CELL_SI:         importCellSi( rStrm, CELLTYPE_VALUE );          break;
245                 case BIFF12_ID_CELL_STRING:     importCellString( rStrm, CELLTYPE_VALUE );      break;
246                 case BIFF12_ID_DATATABLE:       importDataTable( rStrm );                       break;
247                 case BIFF12_ID_FORMULA_BOOL:    importCellBool( rStrm, CELLTYPE_FORMULA );      break;
248                 case BIFF12_ID_FORMULA_DOUBLE:  importCellDouble( rStrm, CELLTYPE_FORMULA );    break;
249                 case BIFF12_ID_FORMULA_ERROR:   importCellError( rStrm, CELLTYPE_FORMULA );     break;
250                 case BIFF12_ID_FORMULA_STRING:  importCellString( rStrm, CELLTYPE_FORMULA );    break;
251                 case BIFF12_ID_MULTCELL_BOOL:   importCellBool( rStrm, CELLTYPE_MULTI );        break;
252                 case BIFF12_ID_MULTCELL_BLANK:  importCellBlank( rStrm, CELLTYPE_MULTI );       break;
253                 case BIFF12_ID_MULTCELL_DOUBLE: importCellDouble( rStrm, CELLTYPE_MULTI );      break;
254                 case BIFF12_ID_MULTCELL_ERROR:  importCellError( rStrm, CELLTYPE_MULTI );       break;
255                 case BIFF12_ID_MULTCELL_RK:     importCellRk( rStrm, CELLTYPE_MULTI );          break;
256                 case BIFF12_ID_MULTCELL_RSTRING:importCellRString( rStrm, CELLTYPE_MULTI );     break;
257                 case BIFF12_ID_MULTCELL_SI:     importCellSi( rStrm, CELLTYPE_MULTI );          break;
258                 case BIFF12_ID_MULTCELL_STRING: importCellString( rStrm, CELLTYPE_MULTI );      break;
259                 case BIFF12_ID_SHAREDFMLA:      importSharedFmla( rStrm );                      break;
260             }
261         break;
262     }
263     return nullptr;
264 }
265 
266 // private --------------------------------------------------------------------
267 
268 void SheetDataContext::importRow( const AttributeList& rAttribs )
269 {
270     RowModel aModel;
271     sal_Int32 nRow = rAttribs.getInteger( XML_r, -1 ); // 1-based row index
272     if(nRow != -1)
273     {
274         aModel.mnRow = nRow;
275         mnRow = nRow-1; // to 0-based row index.
276     }
277     else
278         aModel.mnRow = (++mnRow + 1);   // increment 0-based row index, to 1-based model row
279     mrAddressConv.checkRow( mnRow, true);
280     mnCol = -1;
281 
282     aModel.mfHeight       = rAttribs.getDouble( XML_ht, -1.0 );
283     aModel.mnXfId         = rAttribs.getInteger( XML_s, -1 );
284     aModel.mnLevel        = rAttribs.getInteger( XML_outlineLevel, 0 );
285     aModel.mbCustomHeight = rAttribs.getBool( XML_customHeight, false );
286     aModel.mbCustomFormat = rAttribs.getBool( XML_customFormat, false );
287     aModel.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
288     aModel.mbHidden       = rAttribs.getBool( XML_hidden, false );
289     aModel.mbCollapsed    = rAttribs.getBool( XML_collapsed, false );
290     aModel.mbThickTop     = rAttribs.getBool( XML_thickTop, false );
291     aModel.mbThickBottom  = rAttribs.getBool( XML_thickBot, false );
292 
293     // decode the column spans (space-separated list of colon-separated integer pairs)
294     OUString aColSpansText = rAttribs.getString( XML_spans, OUString() );
295     sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Col();
296     sal_Int32 nIndex = 0;
297     while( nIndex >= 0 )
298     {
299         OUString aColSpanToken = aColSpansText.getToken( 0, ' ', nIndex );
300         sal_Int32 nSepPos = aColSpanToken.indexOf( ':' );
301         if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.getLength()) )
302         {
303             // OOXML uses 1-based integer column indexes, row model expects 0-based colspans
304             const sal_Int32 nCol1 = aColSpanToken.copy( 0, nSepPos ).toInt32() - 1;
305             const bool bValid1 = mrAddressConv.checkCol( nCol1, true);
306             if (bValid1)
307             {
308                 const sal_Int32 nCol2 = aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1;
309                 mrAddressConv.checkCol( nCol2, true);
310                 aModel.insertColSpan( ValueRange( nCol1, ::std::min( nCol2, nMaxCol )));
311             }
312         }
313     }
314 
315     // set row properties in the current sheet
316     setRowModel( aModel );
317 }
318 
319 bool SheetDataContext::importCell( const AttributeList& rAttribs )
320 {
321     bool bValid = true;
322     const char* p = rAttribs.getChar(XML_r);
323 
324     if (!p)
325     {
326         ++mnCol;
327         ScAddress aAddress( mnCol, mnRow, mnSheet );
328         bValid = mrAddressConv.checkCellAddress( aAddress, true );
329         maCellData.maCellAddr = aAddress;
330     }
331     else
332     {
333         bValid = mrAddressConv.convertToCellAddress(maCellData.maCellAddr, p, mnSheet, true);
334         mnCol = maCellData.maCellAddr.Col();
335     }
336 
337     if( bValid )
338     {
339         maCellData.mnCellType     = rAttribs.getToken( XML_t, XML_n );
340         maCellData.mnXfId         = rAttribs.getInteger( XML_s, -1 );
341         maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
342 
343         // reset cell value, formula settings, and inline string
344         maCellValue.clear();
345         mxInlineStr.reset();
346         mbHasFormula = false;
347 
348         // update used area of the sheet
349         extendUsedArea( maCellData.maCellAddr );
350     }
351     return bValid;
352 }
353 
354 void SheetDataContext::importFormula( const AttributeList& rAttribs )
355 {
356     mbHasFormula = true;
357     mbValidRange = mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, rAttribs.getString( XML_ref, OUString() ), mnSheet, true, true );
358 
359     maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
360     maFmlaData.mnSharedId    = rAttribs.getInteger( XML_si, -1 );
361 
362     if( maFmlaData.mnFormulaType == XML_dataTable )
363     {
364         maTableData.maRef1        = rAttribs.getString( XML_r1, OUString() );
365         maTableData.maRef2        = rAttribs.getString( XML_r2, OUString() );
366         maTableData.mb2dTable     = rAttribs.getBool( XML_dt2D, false );
367         maTableData.mbRowTable    = rAttribs.getBool( XML_dtr, false );
368         maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
369         maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
370     }
371 
372     maFormulaStr.clear();
373 }
374 
375 void SheetDataContext::importRow( SequenceInputStream& rStrm )
376 {
377     RowModel aModel;
378     sal_Int32 nSpanCount;
379     sal_uInt16 nHeight, nFlags1;
380     sal_uInt8 nFlags2;
381     maCurrPos.mnRow = rStrm.readInt32();
382     aModel.mnXfId = rStrm.readInt32();
383     nHeight = rStrm.readuInt16();
384     nFlags1 = rStrm.readuInt16();
385     nFlags2 = rStrm.readuChar();
386     nSpanCount = rStrm.readInt32();
387     maCurrPos.mnCol = 0;
388 
389     mrAddressConv.checkRow( maCurrPos.mnRow, true);
390     // row index is 0-based in BIFF12, but RowModel expects 1-based
391     aModel.mnRow          = maCurrPos.mnRow + 1;
392     // row height is in twips in BIFF12, convert to points
393     aModel.mfHeight       = nHeight / 20.0;
394     aModel.mnLevel        = extractValue< sal_Int32 >( nFlags1, 8, 3 );
395     aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT );
396     aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT );
397     aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC );
398     aModel.mbHidden       = getFlag( nFlags1, BIFF12_ROW_HIDDEN );
399     aModel.mbCollapsed    = getFlag( nFlags1, BIFF12_ROW_COLLAPSED );
400     aModel.mbThickTop     = getFlag( nFlags1, BIFF12_ROW_THICKTOP );
401     aModel.mbThickBottom  = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM );
402 
403     // read the column spans
404     sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Col();
405     for( sal_Int32 nSpanIdx = 0; (nSpanIdx < nSpanCount) && !rStrm.isEof(); ++nSpanIdx )
406     {
407         sal_Int32 nFirstCol, nLastCol;
408         nFirstCol = rStrm.readInt32();
409         const bool bValid1 = mrAddressConv.checkCol( nFirstCol, true);
410         nLastCol = rStrm.readInt32();
411         mrAddressConv.checkCol( nLastCol, true);
412         if (bValid1)
413             aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) );
414     }
415 
416     // set row properties in the current sheet
417     setRowModel( aModel );
418 }
419 
420 bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType )
421 {
422     switch( eCellType )
423     {
424         case CELLTYPE_VALUE:
425         case CELLTYPE_FORMULA:  maCurrPos.mnCol = rStrm.readInt32();   break;
426         case CELLTYPE_MULTI:    ++maCurrPos.mnCol;          break;
427     }
428 
429     sal_uInt32 nXfId = rStrm.readuInt32();
430 
431     bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, maCurrPos, mnSheet, true );
432     maCellData.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
433     maCellData.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC );
434 
435     // update used area of the sheet
436     if( bValidAddr )
437         extendUsedArea( maCellData.maCellAddr );
438     return bValidAddr;
439 }
440 
441 ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm )
442 {
443     rStrm.skip( 2 );
444     return mxFormulaParser->importFormula( maCellData.maCellAddr, FormulaType::Cell, rStrm );
445 }
446 
447 bool SheetDataContext::readFormulaRef( SequenceInputStream& rStrm )
448 {
449     BinRange aRange;
450     rStrm >> aRange;
451     return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true );
452 }
453 
454 void SheetDataContext::importCellBool( SequenceInputStream& rStrm, CellType eCellType )
455 {
456     if( readCellHeader( rStrm, eCellType ) )
457     {
458         maCellData.mnCellType = XML_b;
459         bool bValue = rStrm.readuInt8() != 0;
460         if( eCellType == CELLTYPE_FORMULA )
461             mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
462         else
463             mrSheetData.setBooleanCell( maCellData, bValue );
464     }
465 }
466 
467 void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType )
468 {
469     OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" );
470     if( readCellHeader( rStrm, eCellType ) )
471         mrSheetData.setBlankCell( maCellData );
472 }
473 
474 void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType )
475 {
476     if( readCellHeader( rStrm, eCellType ) )
477     {
478         maCellData.mnCellType = XML_n;
479         double fValue = rStrm.readDouble();
480         if( eCellType == CELLTYPE_FORMULA )
481             mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
482         else
483             mrSheetData.setValueCell( maCellData, fValue );
484     }
485 }
486 
487 void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType )
488 {
489     if( readCellHeader( rStrm, eCellType ) )
490     {
491         maCellData.mnCellType = XML_e;
492         sal_uInt8 nErrorCode = rStrm.readuInt8();
493         if( eCellType == CELLTYPE_FORMULA )
494             mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
495         else
496             mrSheetData.setErrorCell( maCellData, nErrorCode );
497     }
498 }
499 
500 void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType )
501 {
502     OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" );
503     if( readCellHeader( rStrm, eCellType ) )
504     {
505         maCellData.mnCellType = XML_n;
506         mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
507     }
508 }
509 
510 void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType )
511 {
512     OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" );
513     if( readCellHeader( rStrm, eCellType ) )
514     {
515         maCellData.mnCellType = XML_inlineStr;
516         RichStringRef xString( new RichString( *this ) );
517         xString->importString( rStrm, true );
518         xString->finalizeImport();
519         mrSheetData.setStringCell( maCellData, xString );
520     }
521 }
522 
523 void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType )
524 {
525     OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" );
526     if( readCellHeader( rStrm, eCellType ) )
527     {
528         maCellData.mnCellType = XML_s;
529         mrSheetData.setStringCell( maCellData, rStrm.readInt32() );
530     }
531 }
532 
533 void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType )
534 {
535     if( readCellHeader( rStrm, eCellType ) )
536     {
537         maCellData.mnCellType = XML_inlineStr;
538         // always import the string, stream will point to formula afterwards, if existing
539         RichStringRef xString( new RichString( *this ) );
540         xString->importString( rStrm, false );
541         xString->finalizeImport();
542         if( eCellType == CELLTYPE_FORMULA )
543             mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) );
544         else
545             mrSheetData.setStringCell( maCellData, xString );
546     }
547 }
548 
549 void SheetDataContext::importArray( SequenceInputStream& rStrm )
550 {
551     if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) )
552     {
553         rStrm.skip( 1 );
554         ApiTokenSequence aTokens = mxFormulaParser->importFormula( maCellData.maCellAddr, FormulaType::Array, rStrm );
555         mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens );
556     }
557 }
558 
559 void SheetDataContext::importDataTable( SequenceInputStream& rStrm )
560 {
561     if( readFormulaRef( rStrm ) )
562     {
563         BinAddress aRef1, aRef2;
564         sal_uInt8 nFlags;
565         rStrm >> aRef1 >> aRef2;
566         nFlags = rStrm.readuChar();
567         maTableData.maRef1        = FormulaProcessorBase::generateAddress2dString( aRef1, false );
568         maTableData.maRef2        = FormulaProcessorBase::generateAddress2dString( aRef2, false );
569         maTableData.mbRowTable    = getFlag( nFlags, BIFF12_DATATABLE_ROW );
570         maTableData.mb2dTable     = getFlag( nFlags, BIFF12_DATATABLE_2D );
571         maTableData.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL );
572         maTableData.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL );
573         mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData );
574     }
575 }
576 
577 void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm )
578 {
579     if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) )
580     {
581         ApiTokenSequence aTokens = mxFormulaParser->importFormula( maCellData.maCellAddr, FormulaType::SharedFormula, rStrm );
582         mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens );
583     }
584 }
585 
586 } // namespace xls
587 } // namespace oox
588 
589 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
590