1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/xls/worksheetfragment.hxx" 25 26 #include "oox/core/filterbase.hxx" 27 #include "oox/core/relations.hxx" 28 #include "oox/helper/attributelist.hxx" 29 #include "oox/xls/addressconverter.hxx" 30 #include "oox/xls/autofilterbuffer.hxx" 31 #include "oox/xls/autofiltercontext.hxx" 32 #include "oox/xls/biffinputstream.hxx" 33 #include "oox/xls/commentsfragment.hxx" 34 #include "oox/xls/condformatcontext.hxx" 35 #include "oox/xls/drawingfragment.hxx" 36 #include "oox/xls/drawingmanager.hxx" 37 #include "oox/xls/externallinkbuffer.hxx" 38 #include "oox/xls/pagesettings.hxx" 39 #include "oox/xls/pivottablefragment.hxx" 40 #include "oox/xls/querytablefragment.hxx" 41 #include "oox/xls/scenariobuffer.hxx" 42 #include "oox/xls/scenariocontext.hxx" 43 #include "oox/xls/sheetdatabuffer.hxx" 44 #include "oox/xls/sheetdatacontext.hxx" 45 #include "oox/xls/tablefragment.hxx" 46 #include "oox/xls/viewsettings.hxx" 47 #include "oox/xls/workbooksettings.hxx" 48 #include "oox/xls/worksheetsettings.hxx" 49 50 namespace oox { 51 namespace xls { 52 53 // ============================================================================ 54 55 using namespace ::com::sun::star::table; 56 using namespace ::com::sun::star::uno; 57 using namespace ::oox::core; 58 59 using ::rtl::OUString; 60 using ::rtl::OUStringBuffer; 61 62 // ============================================================================ 63 64 namespace { 65 66 const sal_uInt16 BIFF_COLINFO_HIDDEN = 0x0001; 67 const sal_uInt16 BIFF_COLINFO_SHOWPHONETIC = 0x0008; 68 const sal_uInt16 BIFF_COLINFO_COLLAPSED = 0x1000; 69 70 const sal_uInt16 BIFF_DEFROW_CUSTOMHEIGHT = 0x0001; 71 const sal_uInt16 BIFF_DEFROW_HIDDEN = 0x0002; 72 const sal_uInt16 BIFF_DEFROW_THICKTOP = 0x0004; 73 const sal_uInt16 BIFF_DEFROW_THICKBOTTOM = 0x0008; 74 const sal_uInt16 BIFF2_DEFROW_DEFHEIGHT = 0x8000; 75 const sal_uInt16 BIFF2_DEFROW_MASK = 0x7FFF; 76 77 const sal_uInt32 BIFF_DATAVAL_STRINGLIST = 0x00000080; 78 const sal_uInt32 BIFF_DATAVAL_ALLOWBLANK = 0x00000100; 79 const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200; 80 const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000; 81 const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000; 82 83 const sal_uInt32 BIFF_SHRFEATHEAD_SHEETPROT = 2; 84 85 const sal_Int32 BIFF12_OLEOBJECT_CONTENT = 1; 86 const sal_Int32 BIFF12_OLEOBJECT_ICON = 4; 87 const sal_Int32 BIFF12_OLEOBJECT_ALWAYS = 1; 88 const sal_Int32 BIFF12_OLEOBJECT_ONCALL = 3; 89 const sal_uInt16 BIFF12_OLEOBJECT_LINKED = 0x0001; 90 const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD = 0x0002; 91 92 } // namespace 93 94 // ============================================================================ 95 96 DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) : 97 WorksheetContextBase( rFragment ) 98 { 99 } 100 101 ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 102 { 103 switch( getCurrentElement() ) 104 { 105 case XLS_TOKEN( dataValidations ): 106 if( nElement == XLS_TOKEN( dataValidation ) ) 107 { 108 importDataValidation( rAttribs ); 109 return this; 110 } 111 break; 112 case XLS_TOKEN( dataValidation ): 113 switch( nElement ) 114 { 115 case XLS_TOKEN( formula1 ): 116 case XLS_TOKEN( formula2 ): 117 return this; // collect formulas in onCharacters() 118 } 119 break; 120 } 121 return 0; 122 } 123 124 void DataValidationsContext::onCharacters( const OUString& rChars ) 125 { 126 if( mxValModel.get() ) switch( getCurrentElement() ) 127 { 128 case XLS_TOKEN( formula1 ): 129 mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); 130 // process string list of a list validation (convert to list of string tokens) 131 if( mxValModel->mnType == XML_list ) 132 getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true ); 133 break; 134 case XLS_TOKEN( formula2 ): 135 mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); 136 break; 137 } 138 } 139 140 void DataValidationsContext::onEndElement() 141 { 142 if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() ) 143 { 144 setValidation( *mxValModel ); 145 mxValModel.reset(); 146 } 147 } 148 149 150 ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 151 { 152 if( nRecId == BIFF12_ID_DATAVALIDATION ) 153 importDataValidation( rStrm ); 154 return 0; 155 } 156 157 void DataValidationsContext::importDataValidation( const AttributeList& rAttribs ) 158 { 159 mxValModel.reset( new ValidationModel ); 160 getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true ); 161 mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() ); 162 mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() ); 163 mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() ); 164 mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() ); 165 mxValModel->mnType = rAttribs.getToken( XML_type, XML_none ); 166 mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between ); 167 mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop ); 168 mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false ); 169 mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false ); 170 /* The attribute showDropDown@dataValidation is in fact a "suppress 171 dropdown" flag, as it was in the BIFF format! ECMA specification 172 and attribute name are plain wrong! */ 173 mxValModel->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false ); 174 mxValModel->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false ); 175 } 176 177 void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm ) 178 { 179 ValidationModel aModel; 180 181 sal_uInt32 nFlags; 182 BinRangeList aRanges; 183 rStrm >> nFlags >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage; 184 185 // equal flags in all BIFFs 186 aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); 187 aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); 188 aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); 189 aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); 190 aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); 191 aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); 192 aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); 193 194 // cell range list 195 getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true ); 196 197 // condition formula(s) 198 FormulaParser& rParser = getFormulaParser(); 199 CellAddress aBaseAddr = aModel.maRanges.getBaseAddress(); 200 aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); 201 aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); 202 // process string list of a list validation (convert to list of string tokens) 203 if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) 204 rParser.convertStringToStringList( aModel.maTokens1, ',', true ); 205 206 // set validation data 207 setValidation( aModel ); 208 } 209 210 // ============================================================================ 211 212 WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : 213 WorksheetFragmentBase( rHelper, rFragmentPath ) 214 { 215 // import data tables related to this worksheet 216 RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "table" ) ); 217 for( Relations::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt ) 218 importOoxFragment( new TableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); 219 220 // import comments related to this worksheet 221 OUString aCommentsFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "comments" ) ); 222 if( aCommentsFragmentPath.getLength() > 0 ) 223 importOoxFragment( new CommentsFragment( *this, aCommentsFragmentPath ) ); 224 } 225 226 ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 227 { 228 switch( getCurrentElement() ) 229 { 230 case XML_ROOT_CONTEXT: switch( getSheetType() ) 231 { 232 case SHEETTYPE_WORKSHEET: return (nElement == XLS_TOKEN( worksheet )) ? this : 0; 233 case SHEETTYPE_CHARTSHEET: return 0; 234 case SHEETTYPE_MACROSHEET: return (nElement == XM_TOKEN( macrosheet )) ? this : 0; 235 case SHEETTYPE_DIALOGSHEET: return (nElement == XLS_TOKEN( dialogsheet )) ? this : 0; 236 case SHEETTYPE_MODULESHEET: return 0; 237 case SHEETTYPE_EMPTYSHEET: return 0; 238 } 239 break; 240 241 case XLS_TOKEN( worksheet ): 242 case XM_TOKEN( macrosheet ): 243 case XLS_TOKEN( dialogsheet ): 244 switch( nElement ) 245 { 246 case XLS_TOKEN( sheetData ): return new SheetDataContext( *this ); 247 case XLS_TOKEN( conditionalFormatting ): return new CondFormatContext( *this ); 248 case XLS_TOKEN( dataValidations ): return new DataValidationsContext( *this ); 249 case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() ); 250 case XLS_TOKEN( scenarios ): return new ScenariosContext( *this ); 251 252 case XLS_TOKEN( sheetViews ): 253 case XLS_TOKEN( cols ): 254 case XLS_TOKEN( mergeCells ): 255 case XLS_TOKEN( hyperlinks ): 256 case XLS_TOKEN( rowBreaks ): 257 case XLS_TOKEN( colBreaks ): 258 case XLS_TOKEN( oleObjects ): 259 case XLS_TOKEN( controls ): return this; 260 261 case XLS_TOKEN( sheetPr ): getWorksheetSettings().importSheetPr( rAttribs ); return this; 262 case XLS_TOKEN( dimension ): importDimension( rAttribs ); break; 263 case XLS_TOKEN( sheetFormatPr ): importSheetFormatPr( rAttribs ); break; 264 case XLS_TOKEN( sheetProtection ): getWorksheetSettings().importSheetProtection( rAttribs ); break; 265 case XLS_TOKEN( phoneticPr ): getWorksheetSettings().importPhoneticPr( rAttribs ); break; 266 case XLS_TOKEN( printOptions ): getPageSettings().importPrintOptions( rAttribs ); break; 267 case XLS_TOKEN( pageMargins ): getPageSettings().importPageMargins( rAttribs ); break; 268 case XLS_TOKEN( pageSetup ): getPageSettings().importPageSetup( getRelations(), rAttribs ); break; 269 case XLS_TOKEN( headerFooter ): getPageSettings().importHeaderFooter( rAttribs ); return this; 270 case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break; 271 case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break; 272 case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break; 273 } 274 break; 275 276 case XLS_TOKEN( sheetPr ): 277 switch( nElement ) 278 { 279 case XLS_TOKEN( tabColor ): getWorksheetSettings().importTabColor( rAttribs ); break; 280 case XLS_TOKEN( outlinePr ): getWorksheetSettings().importOutlinePr( rAttribs ); break; 281 case XLS_TOKEN( pageSetUpPr ): importPageSetUpPr( rAttribs ); break; 282 } 283 break; 284 285 case XLS_TOKEN( sheetViews ): 286 switch( nElement ) 287 { 288 case XLS_TOKEN( sheetView ): getSheetViewSettings().importSheetView( rAttribs ); return this; 289 } 290 break; 291 case XLS_TOKEN( sheetView ): 292 switch( nElement ) 293 { 294 case XLS_TOKEN( pane ): getSheetViewSettings().importPane( rAttribs ); break; 295 case XLS_TOKEN( selection ): getSheetViewSettings().importSelection( rAttribs ); break; 296 } 297 break; 298 299 case XLS_TOKEN( cols ): 300 if( nElement == XLS_TOKEN( col ) ) importCol( rAttribs ); 301 break; 302 case XLS_TOKEN( mergeCells ): 303 if( nElement == XLS_TOKEN( mergeCell ) ) importMergeCell( rAttribs ); 304 break; 305 case XLS_TOKEN( hyperlinks ): 306 if( nElement == XLS_TOKEN( hyperlink ) ) importHyperlink( rAttribs ); 307 break; 308 case XLS_TOKEN( rowBreaks ): 309 if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, true ); 310 break; 311 case XLS_TOKEN( colBreaks ): 312 if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, false ); 313 break; 314 315 case XLS_TOKEN( headerFooter ): 316 switch( nElement ) 317 { 318 case XLS_TOKEN( firstHeader ): 319 case XLS_TOKEN( firstFooter ): 320 case XLS_TOKEN( oddHeader ): 321 case XLS_TOKEN( oddFooter ): 322 case XLS_TOKEN( evenHeader ): 323 case XLS_TOKEN( evenFooter ): return this; // collect h/f contents in onCharacters() 324 } 325 break; 326 327 case XLS_TOKEN( oleObjects ): 328 if( nElement == XLS_TOKEN( oleObject ) ) importOleObject( rAttribs ); 329 break; 330 case XLS_TOKEN( controls ): 331 if( nElement == XLS_TOKEN( control ) ) importControl( rAttribs ); 332 break; 333 } 334 return 0; 335 } 336 337 void WorksheetFragment::onCharacters( const OUString& rChars ) 338 { 339 switch( getCurrentElement() ) 340 { 341 case XLS_TOKEN( firstHeader ): 342 case XLS_TOKEN( firstFooter ): 343 case XLS_TOKEN( oddHeader ): 344 case XLS_TOKEN( oddFooter ): 345 case XLS_TOKEN( evenHeader ): 346 case XLS_TOKEN( evenFooter ): 347 getPageSettings().importHeaderFooterCharacters( rChars, getCurrentElement() ); 348 break; 349 } 350 } 351 352 ContextHandlerRef WorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 353 { 354 switch( getCurrentElement() ) 355 { 356 case XML_ROOT_CONTEXT: 357 if( nRecId == BIFF12_ID_WORKSHEET ) return this; 358 break; 359 360 case BIFF12_ID_WORKSHEET: 361 switch( nRecId ) 362 { 363 case BIFF12_ID_SHEETDATA: return new SheetDataContext( *this ); 364 case BIFF12_ID_CONDFORMATTING: return new CondFormatContext( *this ); 365 case BIFF12_ID_DATAVALIDATIONS: return new DataValidationsContext( *this ); 366 case BIFF12_ID_AUTOFILTER: return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() ); 367 case BIFF12_ID_SCENARIOS: return new ScenariosContext( *this ); 368 369 case BIFF12_ID_SHEETVIEWS: 370 case BIFF12_ID_COLS: 371 case BIFF12_ID_MERGECELLS: 372 case BIFF12_ID_ROWBREAKS: 373 case BIFF12_ID_COLBREAKS: 374 case BIFF12_ID_OLEOBJECTS: 375 case BIFF12_ID_CONTROLS: return this; 376 377 case BIFF12_ID_SHEETPR: getWorksheetSettings().importSheetPr( rStrm ); break; 378 case BIFF12_ID_DIMENSION: importDimension( rStrm ); break; 379 case BIFF12_ID_SHEETFORMATPR: importSheetFormatPr( rStrm ); break; 380 case BIFF12_ID_HYPERLINK: importHyperlink( rStrm ); break; 381 case BIFF12_ID_PAGEMARGINS: getPageSettings().importPageMargins( rStrm ); break; 382 case BIFF12_ID_PAGESETUP: getPageSettings().importPageSetup( getRelations(), rStrm ); break; 383 case BIFF12_ID_PRINTOPTIONS: getPageSettings().importPrintOptions( rStrm ); break; 384 case BIFF12_ID_HEADERFOOTER: getPageSettings().importHeaderFooter( rStrm ); break; 385 case BIFF12_ID_PICTURE: getPageSettings().importPicture( getRelations(), rStrm ); break; 386 case BIFF12_ID_SHEETPROTECTION: getWorksheetSettings().importSheetProtection( rStrm ); break; 387 case BIFF12_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break; 388 case BIFF12_ID_DRAWING: importDrawing( rStrm ); break; 389 case BIFF12_ID_LEGACYDRAWING: importLegacyDrawing( rStrm ); break; 390 } 391 break; 392 393 case BIFF12_ID_SHEETVIEWS: 394 switch( nRecId ) 395 { 396 case BIFF12_ID_SHEETVIEW: getSheetViewSettings().importSheetView( rStrm ); return this; 397 } 398 break; 399 case BIFF12_ID_SHEETVIEW: 400 switch( nRecId ) 401 { 402 case BIFF12_ID_PANE: getSheetViewSettings().importPane( rStrm ); break; 403 case BIFF12_ID_SELECTION: getSheetViewSettings().importSelection( rStrm ); break; 404 } 405 break; 406 407 case BIFF12_ID_COLS: 408 if( nRecId == BIFF12_ID_COL ) importCol( rStrm ); 409 break; 410 case BIFF12_ID_MERGECELLS: 411 if( nRecId == BIFF12_ID_MERGECELL ) importMergeCell( rStrm ); 412 break; 413 case BIFF12_ID_ROWBREAKS: 414 if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, true ); 415 break; 416 case BIFF12_ID_COLBREAKS: 417 if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, false ); 418 break; 419 case BIFF12_ID_OLEOBJECTS: 420 if( nRecId == BIFF12_ID_OLEOBJECT ) importOleObject( rStrm ); 421 break; 422 case BIFF12_ID_CONTROLS: 423 if( nRecId == BIFF12_ID_CONTROL ) importControl( rStrm ); 424 break; 425 } 426 return 0; 427 } 428 429 const RecordInfo* WorksheetFragment::getRecordInfos() const 430 { 431 static const RecordInfo spRecInfos[] = 432 { 433 { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 }, 434 { BIFF12_ID_CFRULE, BIFF12_ID_CFRULE + 1 }, 435 { BIFF12_ID_COLBREAKS, BIFF12_ID_COLBREAKS + 1 }, 436 { BIFF12_ID_COLORSCALE, BIFF12_ID_COLORSCALE + 1 }, 437 { BIFF12_ID_COLS, BIFF12_ID_COLS + 1 }, 438 { BIFF12_ID_CONDFORMATTING, BIFF12_ID_CONDFORMATTING + 1 }, 439 { BIFF12_ID_CONTROLS, BIFF12_ID_CONTROLS + 2 }, 440 { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 }, 441 { BIFF12_ID_CUSTOMSHEETVIEW, BIFF12_ID_CUSTOMSHEETVIEW + 1 }, 442 { BIFF12_ID_CUSTOMSHEETVIEWS, BIFF12_ID_CUSTOMSHEETVIEWS + 3 }, 443 { BIFF12_ID_DATABAR, BIFF12_ID_DATABAR + 1 }, 444 { BIFF12_ID_DATAVALIDATIONS, BIFF12_ID_DATAVALIDATIONS + 1 }, 445 { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 }, 446 { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 }, 447 { BIFF12_ID_HEADERFOOTER, BIFF12_ID_HEADERFOOTER + 1 }, 448 { BIFF12_ID_ICONSET, BIFF12_ID_ICONSET + 1 }, 449 { BIFF12_ID_MERGECELLS, BIFF12_ID_MERGECELLS + 1 }, 450 { BIFF12_ID_OLEOBJECTS, BIFF12_ID_OLEOBJECTS + 2 }, 451 { BIFF12_ID_ROW, -1 }, 452 { BIFF12_ID_ROWBREAKS, BIFF12_ID_ROWBREAKS + 1 }, 453 { BIFF12_ID_SCENARIO, BIFF12_ID_SCENARIO + 1 }, 454 { BIFF12_ID_SCENARIOS, BIFF12_ID_SCENARIOS + 1 }, 455 { BIFF12_ID_SHEETDATA, BIFF12_ID_SHEETDATA + 1 }, 456 { BIFF12_ID_SHEETVIEW, BIFF12_ID_SHEETVIEW + 1 }, 457 { BIFF12_ID_SHEETVIEWS, BIFF12_ID_SHEETVIEWS + 1 }, 458 { BIFF12_ID_TABLEPARTS, BIFF12_ID_TABLEPARTS + 2 }, 459 { BIFF12_ID_WORKSHEET, BIFF12_ID_WORKSHEET + 1 }, 460 { -1, -1 } 461 }; 462 return spRecInfos; 463 } 464 465 void WorksheetFragment::initializeImport() 466 { 467 // initial processing in base class WorksheetHelper 468 initializeWorksheetImport(); 469 470 // import query table fragments related to this worksheet 471 RelationsRef xQueryRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "queryTable" ) ); 472 for( Relations::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt ) 473 importOoxFragment( new QueryTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); 474 475 // import pivot table fragments related to this worksheet 476 RelationsRef xPivotRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "pivotTable" ) ); 477 for( Relations::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt ) 478 importOoxFragment( new PivotTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); 479 } 480 481 void WorksheetFragment::finalizeImport() 482 { 483 // final processing in base class WorksheetHelper 484 finalizeWorksheetImport(); 485 } 486 487 // private -------------------------------------------------------------------- 488 489 void WorksheetFragment::importPageSetUpPr( const AttributeList& rAttribs ) 490 { 491 // for whatever reason, this flag is still stored separated from the page settings 492 getPageSettings().setFitToPagesMode( rAttribs.getBool( XML_fitToPage, false ) ); 493 } 494 495 void WorksheetFragment::importDimension( const AttributeList& rAttribs ) 496 { 497 CellRangeAddress aRange; 498 getAddressConverter().convertToCellRangeUnchecked( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex() ); 499 /* OOXML stores the used area, if existing, or "A1" if the sheet is empty. 500 In case of "A1", the dimension at the WorksheetHelper object will not 501 be set. If the cell A1 exists, the used area will be updated while 502 importing the cell. */ 503 if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) ) 504 extendUsedArea( aRange ); 505 } 506 507 void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs ) 508 { 509 // default column settings 510 setBaseColumnWidth( rAttribs.getInteger( XML_baseColWidth, 8 ) ); 511 setDefaultColumnWidth( rAttribs.getDouble( XML_defaultColWidth, 0.0 ) ); 512 // default row settings 513 setDefaultRowSettings( 514 rAttribs.getDouble( XML_defaultRowHeight, 0.0 ), 515 rAttribs.getBool( XML_customHeight, false ), 516 rAttribs.getBool( XML_zeroHeight, false ), 517 rAttribs.getBool( XML_thickTop, false ), 518 rAttribs.getBool( XML_thickBottom, false ) ); 519 } 520 521 void WorksheetFragment::importCol( const AttributeList& rAttribs ) 522 { 523 ColumnModel aModel; 524 aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 ); 525 aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 ); 526 aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 ); 527 aModel.mnXfId = rAttribs.getInteger( XML_style, -1 ); 528 aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); 529 aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false ); 530 aModel.mbHidden = rAttribs.getBool( XML_hidden, false ); 531 aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); 532 // set column properties in the current sheet 533 setColumnModel( aModel ); 534 } 535 536 void WorksheetFragment::importMergeCell( const AttributeList& rAttribs ) 537 { 538 CellRangeAddress aRange; 539 if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) 540 getSheetData().setMergedRange( aRange ); 541 } 542 543 void WorksheetFragment::importHyperlink( const AttributeList& rAttribs ) 544 { 545 HyperlinkModel aModel; 546 if( getAddressConverter().convertToCellRange( aModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) 547 { 548 aModel.maTarget = getRelations().getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); 549 aModel.maLocation = rAttribs.getXString( XML_location, OUString() ); 550 aModel.maDisplay = rAttribs.getXString( XML_display, OUString() ); 551 aModel.maTooltip = rAttribs.getXString( XML_tooltip, OUString() ); 552 setHyperlink( aModel ); 553 } 554 } 555 556 void WorksheetFragment::importBrk( const AttributeList& rAttribs, bool bRowBreak ) 557 { 558 PageBreakModel aModel; 559 aModel.mnColRow = rAttribs.getInteger( XML_id, 0 ); 560 aModel.mnMin = rAttribs.getInteger( XML_id, 0 ); 561 aModel.mnMax = rAttribs.getInteger( XML_id, 0 ); 562 aModel.mbManual = rAttribs.getBool( XML_man, false ); 563 setPageBreak( aModel, bRowBreak ); 564 } 565 566 void WorksheetFragment::importDrawing( const AttributeList& rAttribs ) 567 { 568 setDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) ); 569 } 570 571 void WorksheetFragment::importLegacyDrawing( const AttributeList& rAttribs ) 572 { 573 setVmlDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) ); 574 } 575 576 void WorksheetFragment::importOleObject( const AttributeList& rAttribs ) 577 { 578 ::oox::vml::OleObjectInfo aInfo; 579 aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); 580 OSL_ENSURE( rAttribs.hasAttribute( XML_link ) != rAttribs.hasAttribute( R_TOKEN( id ) ), 581 "WorksheetFragment::importOleObject - OLE object must be either linked or embedded" ); 582 aInfo.mbLinked = rAttribs.hasAttribute( XML_link ); 583 if( aInfo.mbLinked ) 584 aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rAttribs.getString( XML_link, OUString() ) ); 585 else if( rAttribs.hasAttribute( R_TOKEN( id ) ) ) 586 importEmbeddedOleData( aInfo.maEmbeddedData, rAttribs.getString( R_TOKEN( id ), OUString() ) ); 587 aInfo.maProgId = rAttribs.getString( XML_progId, OUString() ); 588 aInfo.mbShowAsIcon = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ) == XML_DVASPECT_ICON; 589 aInfo.mbAutoUpdate = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ONCALL ) == XML_OLEUPDATE_ALWAYS; 590 aInfo.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false ); 591 getVmlDrawing().registerOleObject( aInfo ); 592 } 593 594 void WorksheetFragment::importControl( const AttributeList& rAttribs ) 595 { 596 ::oox::vml::ControlInfo aInfo; 597 aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); 598 aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); 599 aInfo.maName = rAttribs.getString( XML_name, OUString() ); 600 getVmlDrawing().registerControl( aInfo ); 601 } 602 603 void WorksheetFragment::importDimension( SequenceInputStream& rStrm ) 604 { 605 BinRange aBinRange; 606 aBinRange.read( rStrm ); 607 CellRangeAddress aRange; 608 getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); 609 /* BIFF12 stores the used area, if existing, or "A1" if the sheet is 610 empty. In case of "A1", the dimension at the WorksheetHelper object 611 will not be set. If the cell A1 exists, the used area will be updated 612 while importing the cell. */ 613 if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) ) 614 extendUsedArea( aRange ); 615 } 616 617 void WorksheetFragment::importSheetFormatPr( SequenceInputStream& rStrm ) 618 { 619 sal_Int32 nDefaultWidth; 620 sal_uInt16 nBaseWidth, nDefaultHeight, nFlags; 621 rStrm >> nDefaultWidth >> nBaseWidth >> nDefaultHeight >> nFlags; 622 623 // base column with 624 setBaseColumnWidth( nBaseWidth ); 625 // default width is stored as 1/256th of a character in BIFF12, convert to entire character 626 setDefaultColumnWidth( static_cast< double >( nDefaultWidth ) / 256.0 ); 627 // row height is in twips in BIFF12, convert to points; equal flags in all BIFFs 628 setDefaultRowSettings( 629 nDefaultHeight / 20.0, 630 getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), 631 getFlag( nFlags, BIFF_DEFROW_HIDDEN ), 632 getFlag( nFlags, BIFF_DEFROW_THICKTOP ), 633 getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); 634 } 635 636 void WorksheetFragment::importCol( SequenceInputStream& rStrm ) 637 { 638 ColumnModel aModel; 639 640 sal_Int32 nWidth; 641 sal_uInt16 nFlags; 642 rStrm >> aModel.maRange.mnFirst >> aModel.maRange.mnLast >> nWidth >> aModel.mnXfId >> nFlags; 643 644 // column indexes are 0-based in BIFF12, but ColumnModel expects 1-based 645 ++aModel.maRange.mnFirst; 646 ++aModel.maRange.mnLast; 647 // width is stored as 1/256th of a character in BIFF12, convert to entire character 648 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; 649 // equal flags in all BIFFs 650 aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); 651 aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); 652 aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); 653 aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); 654 // set column properties in the current sheet 655 setColumnModel( aModel ); 656 } 657 658 void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm ) 659 { 660 BinRange aBinRange; 661 rStrm >> aBinRange; 662 CellRangeAddress aRange; 663 if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) ) 664 getSheetData().setMergedRange( aRange ); 665 } 666 667 void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm ) 668 { 669 BinRange aBinRange; 670 rStrm >> aBinRange; 671 HyperlinkModel aModel; 672 if( getAddressConverter().convertToCellRange( aModel.maRange, aBinRange, getSheetIndex(), true, true ) ) 673 { 674 aModel.maTarget = getRelations().getExternalTargetFromRelId( BiffHelper::readString( rStrm ) ); 675 rStrm >> aModel.maLocation >> aModel.maTooltip >> aModel.maDisplay; 676 setHyperlink( aModel ); 677 } 678 } 679 680 void WorksheetFragment::importBrk( SequenceInputStream& rStrm, bool bRowBreak ) 681 { 682 PageBreakModel aModel; 683 sal_Int32 nManual; 684 rStrm >> aModel.mnColRow >> aModel.mnMin >> aModel.mnMax >> nManual; 685 aModel.mbManual = nManual != 0; 686 setPageBreak( aModel, bRowBreak ); 687 } 688 689 void WorksheetFragment::importDrawing( SequenceInputStream& rStrm ) 690 { 691 setDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) ); 692 } 693 694 void WorksheetFragment::importLegacyDrawing( SequenceInputStream& rStrm ) 695 { 696 setVmlDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) ); 697 } 698 699 void WorksheetFragment::importOleObject( SequenceInputStream& rStrm ) 700 { 701 ::oox::vml::OleObjectInfo aInfo; 702 sal_Int32 nAspect, nUpdateMode, nShapeId; 703 sal_uInt16 nFlags; 704 rStrm >> nAspect >> nUpdateMode >> nShapeId >> nFlags >> aInfo.maProgId; 705 aInfo.mbLinked = getFlag( nFlags, BIFF12_OLEOBJECT_LINKED ); 706 if( aInfo.mbLinked ) 707 aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rStrm ); 708 else 709 importEmbeddedOleData( aInfo.maEmbeddedData, BiffHelper::readString( rStrm ) ); 710 aInfo.setShapeId( nShapeId ); 711 aInfo.mbShowAsIcon = nAspect == BIFF12_OLEOBJECT_ICON; 712 aInfo.mbAutoUpdate = nUpdateMode == BIFF12_OLEOBJECT_ALWAYS; 713 aInfo.mbAutoLoad = getFlag( nFlags, BIFF12_OLEOBJECT_AUTOLOAD ); 714 getVmlDrawing().registerOleObject( aInfo ); 715 } 716 717 void WorksheetFragment::importControl( SequenceInputStream& rStrm ) 718 { 719 ::oox::vml::ControlInfo aInfo; 720 aInfo.setShapeId( rStrm.readInt32() ); 721 aInfo.maFragmentPath = getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ); 722 rStrm >> aInfo.maName; 723 getVmlDrawing().registerControl( aInfo ); 724 } 725 726 void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedData, const OUString& rRelId ) 727 { 728 OUString aFragmentPath = getFragmentPathFromRelId( rRelId ); 729 if( aFragmentPath.getLength() > 0 ) 730 getBaseFilter().importBinaryData( orEmbeddedData, aFragmentPath ); 731 } 732 733 // ============================================================================ 734 735 BiffWorksheetFragment::BiffWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : 736 BiffWorksheetFragmentBase( rHelper, rParent ) 737 { 738 } 739 740 BiffWorksheetFragment::~BiffWorksheetFragment() 741 { 742 } 743 744 bool BiffWorksheetFragment::importFragment() 745 { 746 // initial processing in base class WorksheetHelper 747 initializeWorksheetImport(); 748 749 // create a SheetDataContext object that implements cell import 750 BiffSheetDataContext aSheetData( *this ); 751 752 WorkbookSettings& rWorkbookSett = getWorkbookSettings(); 753 WorksheetSettings& rWorksheetSett = getWorksheetSettings(); 754 SheetViewSettings& rSheetViewSett = getSheetViewSettings(); 755 CondFormatBuffer& rCondFormats = getCondFormats(); 756 PageSettings& rPageSett = getPageSettings(); 757 BiffSheetDrawing& rDrawing = getBiffDrawing(); 758 759 // process all record in this sheet fragment 760 BiffInputStream& rStrm = getInputStream(); 761 while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) 762 { 763 if( BiffHelper::isBofRecord( rStrm ) ) 764 { 765 // skip unknown embedded fragments (BOF/EOF blocks) 766 skipFragment(); 767 } 768 else 769 { 770 // cache base stream position to detect if record is already processed 771 sal_Int64 nStrmPos = rStrm.tellBase(); 772 sal_uInt16 nRecId = rStrm.getRecId(); 773 774 switch( nRecId ) 775 { 776 // records in all BIFF versions 777 case BIFF_ID_BOTTOMMARGIN: rPageSett.importBottomMargin( rStrm ); break; 778 case BIFF_ID_CALCCOUNT: rWorkbookSett.importCalcCount( rStrm ); break; 779 case BIFF_ID_CALCMODE: rWorkbookSett.importCalcMode( rStrm ); break; 780 case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; 781 case BIFF_ID_DELTA: rWorkbookSett.importDelta( rStrm ); break; 782 case BIFF2_ID_DIMENSION: importDimension( rStrm ); break; 783 case BIFF3_ID_DIMENSION: importDimension( rStrm ); break; 784 case BIFF_ID_FOOTER: rPageSett.importFooter( rStrm ); break; 785 case BIFF_ID_HEADER: rPageSett.importHeader( rStrm ); break; 786 case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break; 787 case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break; 788 case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break; 789 case BIFF_ID_NOTE: importNote( rStrm ); break; 790 case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break; 791 case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break; 792 case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break; 793 case BIFF_ID_PRINTHEADERS: rPageSett.importPrintHeaders( rStrm ); break; 794 case BIFF_ID_PROTECT: rWorksheetSett.importProtect( rStrm ); break; 795 case BIFF_ID_REFMODE: rWorkbookSett.importRefMode( rStrm ); break; 796 case BIFF_ID_RIGHTMARGIN: rPageSett.importRightMargin( rStrm ); break; 797 case BIFF_ID_SELECTION: rSheetViewSett.importSelection( rStrm ); break; 798 case BIFF_ID_TOPMARGIN: rPageSett.importTopMargin( rStrm ); break; 799 case BIFF_ID_VERPAGEBREAKS: importPageBreaks( rStrm, false ); break; 800 801 // BIFF specific records 802 default: switch( getBiff() ) 803 { 804 case BIFF2: switch( nRecId ) 805 { 806 case BIFF_ID_COLUMNDEFAULT: importColumnDefault( rStrm ); break; 807 case BIFF_ID_COLWIDTH: importColWidth( rStrm ); break; 808 case BIFF2_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; 809 case BIFF2_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; 810 } 811 break; 812 813 case BIFF3: switch( nRecId ) 814 { 815 case BIFF_ID_COLINFO: importColInfo( rStrm ); break; 816 case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; 817 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; 818 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; 819 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; 820 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; 821 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; 822 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; 823 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; 824 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; 825 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; 826 } 827 break; 828 829 case BIFF4: switch( nRecId ) 830 { 831 case BIFF_ID_COLINFO: importColInfo( rStrm ); break; 832 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; 833 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; 834 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; 835 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; 836 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; 837 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; 838 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; 839 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; 840 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; 841 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; 842 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; 843 } 844 break; 845 846 case BIFF5: switch( nRecId ) 847 { 848 case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break; 849 case BIFF_ID_COLINFO: importColInfo( rStrm ); break; 850 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; 851 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; 852 case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5 853 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; 854 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; 855 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; 856 case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break; 857 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; 858 case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; 859 case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; 860 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; 861 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; 862 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; 863 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; 864 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; 865 } 866 break; 867 868 case BIFF8: switch( nRecId ) 869 { 870 case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break; 871 case BIFF_ID_CFHEADER: rCondFormats.importCfHeader( rStrm ); break; 872 case BIFF_ID_CODENAME: rWorksheetSett.importCodeName( rStrm ); break; 873 case BIFF_ID_COLINFO: importColInfo( rStrm ); break; 874 case BIFF_ID_DATAVALIDATION: importDataValidation( rStrm ); break; 875 case BIFF_ID_DATAVALIDATIONS: importDataValidations( rStrm ); break; 876 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; 877 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; 878 case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break; 879 case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break; 880 case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; 881 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; 882 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; 883 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; 884 case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break; 885 case BIFF_ID_PICTURE: rPageSett.importPicture( rStrm ); break; 886 case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break; 887 case BIFF_ID_QUERYTABLE: importQueryTable( rStrm ); break; 888 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; 889 case BIFF_ID_SCENARIOS: importScenarios( rStrm ); break; 890 case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; 891 case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; 892 case BIFF_ID_SHEETEXT: rWorksheetSett.importSheetExt( rStrm ); break; 893 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; 894 case BIFF_ID_SHAREDFEATHEAD: importSharedFeatHead( rStrm ); break; 895 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; 896 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; 897 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; 898 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; 899 } 900 break; 901 902 case BIFF_UNKNOWN: break; 903 } 904 } 905 906 // record not processed, try record context objects 907 if( rStrm.tellBase() == nStrmPos ) 908 { 909 // first, try cell table records 910 aSheetData.importRecord( rStrm ); 911 // handle another open record context 912 if( mxContext.get() ) 913 { 914 // if it was a cell table record, forget the other record context 915 if( rStrm.tellBase() == nStrmPos ) 916 mxContext->importRecord( rStrm ); 917 else 918 mxContext.reset(); 919 } 920 } 921 } 922 } 923 924 // final processing in base class WorksheetHelper 925 finalizeWorksheetImport(); 926 return rStrm.getRecId() == BIFF_ID_EOF; 927 } 928 929 // private -------------------------------------------------------------------- 930 931 void BiffWorksheetFragment::importAutoFilter( BiffInputStream& rStrm ) 932 { 933 mxContext.reset( new BiffAutoFilterContext( *this, getAutoFilters().createAutoFilter() ) ); 934 mxContext->importRecord( rStrm ); 935 } 936 937 void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm ) 938 { 939 sal_uInt16 nFirstCol, nLastCol, nWidth, nXfId, nFlags; 940 rStrm >> nFirstCol >> nLastCol >> nWidth >> nXfId >> nFlags; 941 942 ColumnModel aModel; 943 // column indexes are 0-based in BIFF, but ColumnModel expects 1-based 944 aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; 945 aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; 946 // width is stored as 1/256th of a character in BIFF, convert to entire character 947 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; 948 aModel.mnXfId = nXfId; 949 aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); 950 aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); 951 aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); 952 aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); 953 // set column properties in the current sheet 954 setColumnModel( aModel ); 955 } 956 957 void BiffWorksheetFragment::importColumnDefault( BiffInputStream& rStrm ) 958 { 959 sal_uInt16 nFirstCol, nLastCol, nXfId; 960 rStrm >> nFirstCol >> nLastCol >> nXfId; 961 setDefaultColumnFormat( nFirstCol, nLastCol, nXfId ); 962 } 963 964 void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm ) 965 { 966 sal_uInt8 nFirstCol, nLastCol; 967 sal_uInt16 nWidth; 968 rStrm >> nFirstCol >> nLastCol >> nWidth; 969 970 ColumnModel aModel; 971 // column indexes are 0-based in BIFF, but ColumnModel expects 1-based 972 aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; 973 aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; 974 // width is stored as 1/256th of a character in BIFF, convert to entire character 975 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; 976 // set column properties in the current sheet 977 setColumnModel( aModel ); 978 } 979 980 void BiffWorksheetFragment::importDefColWidth( BiffInputStream& rStrm ) 981 { 982 /* Stored as entire number of characters without padding pixels, which 983 will be added in setBaseColumnWidth(). Call has no effect, if a 984 width has already been set from the STANDARDWIDTH record. */ 985 setBaseColumnWidth( rStrm.readuInt16() ); 986 } 987 988 void BiffWorksheetFragment::importDefRowHeight( BiffInputStream& rStrm ) 989 { 990 sal_uInt16 nFlags = BIFF_DEFROW_CUSTOMHEIGHT, nHeight; 991 if( getBiff() != BIFF2 ) 992 rStrm >> nFlags; 993 rStrm >> nHeight; 994 if( getBiff() == BIFF2 ) 995 nHeight &= BIFF2_DEFROW_MASK; 996 // row height is in twips in BIFF, convert to points 997 setDefaultRowSettings( 998 nHeight / 20.0, 999 getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), 1000 getFlag( nFlags, BIFF_DEFROW_HIDDEN ), 1001 getFlag( nFlags, BIFF_DEFROW_THICKTOP ), 1002 getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); 1003 } 1004 1005 void BiffWorksheetFragment::importDataValidations( BiffInputStream& rStrm ) 1006 { 1007 sal_Int32 nObjId; 1008 rStrm.skip( 10 ); 1009 rStrm >> nObjId; 1010 //! TODO: invalidate object id in drawing object manager 1011 } 1012 1013 namespace { 1014 1015 OUString lclReadDataValMessage( BiffInputStream& rStrm ) 1016 { 1017 // empty strings are single NUL characters (string length is 1) 1018 OUString aMessage = rStrm.readUniString( true ); 1019 if( (aMessage.getLength() == 1) && (aMessage[ 0 ] == 0) ) 1020 aMessage = OUString(); 1021 return aMessage; 1022 } 1023 1024 ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& rParser ) 1025 { 1026 sal_uInt16 nFmlaSize = rStrm.readuInt16(); 1027 rStrm.skip( 2 ); 1028 return rParser.importFormula( CellAddress(), FORMULATYPE_VALIDATION, rStrm, &nFmlaSize ); 1029 } 1030 1031 } // namespace 1032 1033 void BiffWorksheetFragment::importDataValidation( BiffInputStream& rStrm ) 1034 { 1035 ValidationModel aModel; 1036 1037 // flags 1038 sal_uInt32 nFlags; 1039 rStrm >> nFlags; 1040 aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); 1041 aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); 1042 aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); 1043 aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); 1044 aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); 1045 aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); 1046 aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); 1047 1048 // message strings 1049 aModel.maInputTitle = lclReadDataValMessage( rStrm ); 1050 aModel.maErrorTitle = lclReadDataValMessage( rStrm ); 1051 aModel.maInputMessage = lclReadDataValMessage( rStrm ); 1052 aModel.maErrorMessage = lclReadDataValMessage( rStrm ); 1053 1054 // condition formula(s) 1055 FormulaParser& rParser = getFormulaParser(); 1056 aModel.maTokens1 = lclReadDataValFormula( rStrm, rParser ); 1057 aModel.maTokens2 = lclReadDataValFormula( rStrm, rParser ); 1058 // process string list of a list validation (convert to list of string tokens) 1059 if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) 1060 rParser.convertStringToStringList( aModel.maTokens1, '\0', true ); 1061 1062 // cell range list 1063 BinRangeList aRanges; 1064 rStrm >> aRanges; 1065 getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true ); 1066 1067 // set validation data 1068 setValidation( aModel ); 1069 } 1070 1071 void BiffWorksheetFragment::importDimension( BiffInputStream& rStrm ) 1072 { 1073 // 32-bit row indexes in BIFF8 1074 bool bInt32Rows = (rStrm.getRecId() == BIFF3_ID_DIMENSION) && (getBiff() == BIFF8); 1075 BinRange aBinRange; 1076 aBinRange.read( rStrm, true, bInt32Rows ); 1077 /* BIFF stores the used area with end column and end row increased by 1 1078 (first unused column and row). */ 1079 if( (aBinRange.maFirst.mnCol < aBinRange.maLast.mnCol) && (aBinRange.maFirst.mnRow < aBinRange.maLast.mnRow) ) 1080 { 1081 // reduce range to used area 1082 --aBinRange.maLast.mnCol; 1083 --aBinRange.maLast.mnRow; 1084 CellRangeAddress aRange; 1085 getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); 1086 extendUsedArea( aRange ); 1087 } 1088 } 1089 1090 void BiffWorksheetFragment::importHyperlink( BiffInputStream& rStrm ) 1091 { 1092 HyperlinkModel aModel; 1093 1094 // read cell range for the hyperlink 1095 BinRange aBiffRange; 1096 rStrm >> aBiffRange; 1097 // #i80006# Excel silently ignores invalid hi-byte of column index (TODO: everywhere?) 1098 aBiffRange.maFirst.mnCol &= 0xFF; 1099 aBiffRange.maLast.mnCol &= 0xFF; 1100 if( !getAddressConverter().convertToCellRange( aModel.maRange, aBiffRange, getSheetIndex(), true, true ) ) 1101 return; 1102 1103 // try to read the StdHlink data 1104 if( !::oox::ole::OleHelper::importStdHlink( aModel, rStrm, true ) ) 1105 return; 1106 1107 // try to read the optional following SCREENTIP record 1108 if( (rStrm.getNextRecId() == BIFF_ID_SCREENTIP) && rStrm.startNextRecord() ) 1109 { 1110 rStrm.skip( 2 ); // repeated record id 1111 // the cell range, again 1112 rStrm >> aBiffRange; 1113 CellRangeAddress aRange; 1114 if( getAddressConverter().convertToCellRange( aRange, aBiffRange, getSheetIndex(), true, true ) && 1115 (aRange.StartColumn == aModel.maRange.StartColumn) && 1116 (aRange.StartRow == aModel.maRange.StartRow) && 1117 (aRange.EndColumn == aModel.maRange.EndColumn) && 1118 (aRange.EndRow == aModel.maRange.EndRow) ) 1119 { 1120 /* This time, we have no string length, no flag field, and a 1121 null-terminated 16-bit character array. */ 1122 aModel.maTooltip = rStrm.readNulUnicodeArray(); 1123 } 1124 } 1125 1126 // store the hyperlink settings 1127 setHyperlink( aModel ); 1128 } 1129 1130 void BiffWorksheetFragment::importLabelRanges( BiffInputStream& rStrm ) 1131 { 1132 BinRangeList aBiffRowRanges, aBiffColRanges; 1133 rStrm >> aBiffRowRanges >> aBiffColRanges; 1134 ApiCellRangeList aColRanges, aRowRanges; 1135 getAddressConverter().convertToCellRangeList( aColRanges, aBiffColRanges, getSheetIndex(), true ); 1136 getAddressConverter().convertToCellRangeList( aRowRanges, aBiffRowRanges, getSheetIndex(), true ); 1137 setLabelRanges( aColRanges, aRowRanges ); 1138 } 1139 1140 void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm ) 1141 { 1142 BinRangeList aBiffRanges; 1143 rStrm >> aBiffRanges; 1144 ApiCellRangeList aRanges; 1145 getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true ); 1146 for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt ) 1147 getSheetData().setMergedRange( *aIt ); 1148 } 1149 1150 void BiffWorksheetFragment::importNote( BiffInputStream& rStrm ) 1151 { 1152 getComments().createComment()->importNote( rStrm ); 1153 } 1154 1155 void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak ) 1156 { 1157 PageBreakModel aModel; 1158 aModel.mbManual = true; // only manual breaks stored in BIFF 1159 bool bBiff8 = getBiff() == BIFF8; // skip start/end columns or rows in BIFF8 1160 1161 sal_uInt16 nCount; 1162 rStrm >> nCount; 1163 for( sal_uInt16 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) 1164 { 1165 aModel.mnColRow = rStrm.readuInt16(); 1166 setPageBreak( aModel, bRowBreak ); 1167 if( bBiff8 ) 1168 rStrm.skip( 4 ); 1169 } 1170 } 1171 1172 void BiffWorksheetFragment::importPTDefinition( BiffInputStream& rStrm ) 1173 { 1174 mxContext.reset( new BiffPivotTableContext( *this ) ); 1175 mxContext->importRecord( rStrm ); 1176 } 1177 1178 void BiffWorksheetFragment::importQueryTable( BiffInputStream& rStrm ) 1179 { 1180 mxContext.reset( new BiffQueryTableContext( *this ) ); 1181 mxContext->importRecord( rStrm ); 1182 } 1183 1184 void BiffWorksheetFragment::importScenarios( BiffInputStream& rStrm ) 1185 { 1186 getScenarios().createSheetScenarios( getSheetIndex() ).importScenarios( rStrm ); 1187 } 1188 1189 void BiffWorksheetFragment::importSharedFeatHead( BiffInputStream& rStrm ) 1190 { 1191 rStrm.skip( 12 ); 1192 sal_uInt16 nType = rStrm.readuInt16(); 1193 rStrm.skip( 5 ); 1194 switch( nType ) 1195 { 1196 case BIFF_SHRFEATHEAD_SHEETPROT: 1197 if( rStrm.getRemaining() >= 4 ) 1198 getWorksheetSettings().importSheetProtection( rStrm ); 1199 break; 1200 } 1201 } 1202 1203 void BiffWorksheetFragment::importStandardWidth( BiffInputStream& rStrm ) 1204 { 1205 sal_uInt16 nWidth; 1206 rStrm >> nWidth; 1207 // width is stored as 1/256th of a character in BIFF, convert to entire character 1208 double fWidth = static_cast< double >( nWidth ) / 256.0; 1209 // set as default width, will override the width from DEFCOLWIDTH record 1210 setDefaultColumnWidth( fWidth ); 1211 } 1212 1213 // ============================================================================ 1214 1215 } // namespace xls 1216 } // namespace oox 1217