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