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