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
