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/worksheethelper.hxx" 29 30 #include <algorithm> 31 #include <list> 32 #include <utility> 33 #include <com/sun/star/awt/Point.hpp> 34 #include <com/sun/star/awt/Size.hpp> 35 #include <com/sun/star/drawing/XDrawPageSupplier.hpp> 36 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 37 #include <com/sun/star/sheet/TableValidationVisibility.hpp> 38 #include <com/sun/star/sheet/ValidationType.hpp> 39 #include <com/sun/star/sheet/ValidationAlertStyle.hpp> 40 #include <com/sun/star/sheet/XCellAddressable.hpp> 41 #include <com/sun/star/sheet/XCellRangeAddressable.hpp> 42 #include <com/sun/star/sheet/XFormulaTokens.hpp> 43 #include <com/sun/star/sheet/XLabelRanges.hpp> 44 #include <com/sun/star/sheet/XMultiFormulaTokens.hpp> 45 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> 46 #include <com/sun/star/sheet/XSheetCondition.hpp> 47 #include <com/sun/star/sheet/XSheetOutline.hpp> 48 #include <com/sun/star/sheet/XSpreadsheet.hpp> 49 #include <com/sun/star/table/XColumnRowRange.hpp> 50 #include <com/sun/star/text/WritingMode2.hpp> 51 #include <com/sun/star/text/XText.hpp> 52 #include <rtl/ustrbuf.hxx> 53 #include "oox/core/filterbase.hxx" 54 #include "oox/helper/propertyset.hxx" 55 #include "oox/xls/addressconverter.hxx" 56 #include "oox/xls/autofilterbuffer.hxx" 57 #include "oox/xls/commentsbuffer.hxx" 58 #include "oox/xls/condformatbuffer.hxx" 59 #include "oox/xls/drawingfragment.hxx" 60 #include "oox/xls/drawingmanager.hxx" 61 #include "oox/xls/formulaparser.hxx" 62 #include "oox/xls/pagesettings.hxx" 63 #include "oox/xls/querytablebuffer.hxx" 64 #include "oox/xls/sharedstringsbuffer.hxx" 65 #include "oox/xls/sheetdatabuffer.hxx" 66 #include "oox/xls/stylesbuffer.hxx" 67 #include "oox/xls/unitconverter.hxx" 68 #include "oox/xls/viewsettings.hxx" 69 #include "oox/xls/workbooksettings.hxx" 70 #include "oox/xls/worksheetbuffer.hxx" 71 #include "oox/xls/worksheetsettings.hxx" 72 73 namespace oox { 74 namespace xls { 75 76 // ============================================================================ 77 78 using namespace ::com::sun::star::awt; 79 using namespace ::com::sun::star::beans; 80 using namespace ::com::sun::star::drawing; 81 using namespace ::com::sun::star::lang; 82 using namespace ::com::sun::star::sheet; 83 using namespace ::com::sun::star::table; 84 using namespace ::com::sun::star::text; 85 using namespace ::com::sun::star::uno; 86 using namespace ::com::sun::star::util; 87 88 using ::rtl::OUString; 89 using ::rtl::OUStringBuffer; 90 91 // ============================================================================ 92 93 namespace { 94 95 void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, const CellRangeAddress& rUsedArea, sal_Int32 nRow ) 96 { 97 if( rxProgressBar.get() && (rUsedArea.StartRow <= nRow) && (nRow <= rUsedArea.EndRow) ) 98 { 99 double fPosition = static_cast< double >( nRow - rUsedArea.StartRow + 1 ) / (rUsedArea.EndRow - rUsedArea.StartRow + 1); 100 if( rxProgressBar->getPosition() < fPosition ) 101 rxProgressBar->setPosition( fPosition ); 102 } 103 } 104 105 void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, double fPosition ) 106 { 107 if( rxProgressBar.get() ) 108 rxProgressBar->setPosition( fPosition ); 109 } 110 111 } // namespace 112 113 // ============================================================================ 114 // ============================================================================ 115 116 ColumnModel::ColumnModel() : 117 maRange( -1 ), 118 mfWidth( 0.0 ), 119 mnXfId( -1 ), 120 mnLevel( 0 ), 121 mbShowPhonetic( false ), 122 mbHidden( false ), 123 mbCollapsed( false ) 124 { 125 } 126 127 bool ColumnModel::isMergeable( const ColumnModel& rModel ) const 128 { 129 return 130 (maRange.mnFirst <= rModel.maRange.mnFirst) && 131 (rModel.maRange.mnFirst <= maRange.mnLast + 1) && 132 (mfWidth == rModel.mfWidth) && 133 // ignore mnXfId, cell formatting is always set directly 134 (mnLevel == rModel.mnLevel) && 135 (mbHidden == rModel.mbHidden) && 136 (mbCollapsed == rModel.mbCollapsed); 137 } 138 139 // ---------------------------------------------------------------------------- 140 141 RowModel::RowModel() : 142 mnRow( -1 ), 143 mfHeight( 0.0 ), 144 mnXfId( -1 ), 145 mnLevel( 0 ), 146 mbCustomHeight( false ), 147 mbCustomFormat( false ), 148 mbShowPhonetic( false ), 149 mbHidden( false ), 150 mbCollapsed( false ), 151 mbThickTop( false ), 152 mbThickBottom( false ) 153 { 154 } 155 156 void RowModel::insertColSpan( const ValueRange& rColSpan ) 157 { 158 if( (0 <= rColSpan.mnFirst) && (rColSpan.mnFirst <= rColSpan.mnLast) ) 159 maColSpans.insert( rColSpan ); 160 } 161 162 bool RowModel::isMergeable( const RowModel& rModel ) const 163 { 164 return 165 // ignore maColSpans - is handled separately in SheetDataBuffer class 166 (mfHeight == rModel.mfHeight) && 167 // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly 168 (mnLevel == rModel.mnLevel) && 169 (mbCustomHeight == rModel.mbCustomHeight) && 170 (mbHidden == rModel.mbHidden) && 171 (mbCollapsed == rModel.mbCollapsed); 172 } 173 174 // ---------------------------------------------------------------------------- 175 176 PageBreakModel::PageBreakModel() : 177 mnColRow( 0 ), 178 mbManual( false ) 179 { 180 } 181 182 // ---------------------------------------------------------------------------- 183 184 HyperlinkModel::HyperlinkModel() 185 { 186 } 187 188 // ---------------------------------------------------------------------------- 189 190 ValidationModel::ValidationModel() : 191 mnType( XML_none ), 192 mnOperator( XML_between ), 193 mnErrorStyle( XML_stop ), 194 mbShowInputMsg( false ), 195 mbShowErrorMsg( false ), 196 mbNoDropDown( false ), 197 mbAllowBlank( false ) 198 { 199 } 200 201 void ValidationModel::setBiffType( sal_uInt8 nType ) 202 { 203 static const sal_Int32 spnTypeIds[] = { 204 XML_none, XML_whole, XML_decimal, XML_list, XML_date, XML_time, XML_textLength, XML_custom }; 205 mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_none ); 206 } 207 208 void ValidationModel::setBiffOperator( sal_uInt8 nOperator ) 209 { 210 static const sal_Int32 spnOperators[] = { 211 XML_between, XML_notBetween, XML_equal, XML_notEqual, 212 XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual }; 213 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID ); 214 } 215 216 void ValidationModel::setBiffErrorStyle( sal_uInt8 nErrorStyle ) 217 { 218 static const sal_Int32 spnErrorStyles[] = { XML_stop, XML_warning, XML_information }; 219 mnErrorStyle = STATIC_ARRAY_SELECT( spnErrorStyles, nErrorStyle, XML_stop ); 220 } 221 222 // ============================================================================ 223 // ============================================================================ 224 225 class WorksheetGlobals : public WorkbookHelper 226 { 227 public: 228 explicit WorksheetGlobals( 229 const WorkbookHelper& rHelper, 230 const ISegmentProgressBarRef& rxProgressBar, 231 WorksheetType eSheetType, 232 sal_Int16 nSheet ); 233 234 /** Returns true, if this helper refers to an existing Calc sheet. */ 235 inline bool isValidSheet() const { return mxSheet.is(); } 236 237 /** Returns the type of this sheet. */ 238 inline WorksheetType getSheetType() const { return meSheetType; } 239 /** Returns the index of the current sheet. */ 240 inline sal_Int16 getSheetIndex() const { return maUsedArea.Sheet; } 241 /** Returns the XSpreadsheet interface of the current sheet. */ 242 inline const Reference< XSpreadsheet >& getSheet() const { return mxSheet; } 243 244 /** Returns the XCell interface for the passed cell address. */ 245 Reference< XCell > getCell( const CellAddress& rAddress ) const; 246 /** Returns the XCellRange interface for the passed cell range address. */ 247 Reference< XCellRange > getCellRange( const CellRangeAddress& rRange ) const; 248 /** Returns the XSheetCellRanges interface for the passed cell range addresses. */ 249 Reference< XSheetCellRanges > getCellRangeList( const ApiCellRangeList& rRanges ) const; 250 251 /** Returns the XCellRange interface for a column. */ 252 Reference< XCellRange > getColumn( sal_Int32 nCol ) const; 253 /** Returns the XCellRange interface for a row. */ 254 Reference< XCellRange > getRow( sal_Int32 nRow ) const; 255 256 /** Returns the XTableColumns interface for a range of columns. */ 257 Reference< XTableColumns > getColumns( const ValueRange& rColRange ) const; 258 /** Returns the XTableRows interface for a range of rows. */ 259 Reference< XTableRows > getRows( const ValueRange& rRowRange ) const; 260 261 /** Returns the XDrawPage interface of the draw page of the current sheet. */ 262 Reference< XDrawPage > getDrawPage() const; 263 /** Returns the size of the entire drawing page in 1/100 mm. */ 264 const Size& getDrawPageSize() const; 265 266 /** Returns the absolute position of the top-left corner of the cell in 1/100 mm. */ 267 Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const; 268 /** Returns the size of the cell in 1/100 mm. */ 269 Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const; 270 271 /** Returns the address of the cell that contains the passed point in 1/100 mm. */ 272 CellAddress getCellAddressFromPosition( const Point& rPosition ) const; 273 /** Returns the cell range address that contains the passed rectangle in 1/100 mm. */ 274 CellRangeAddress getCellRangeFromRectangle( const Rectangle& rRect ) const; 275 276 /** Returns the buffer for cell contents and cell formatting. */ 277 inline SheetDataBuffer& getSheetData() { return maSheetData; } 278 /** Returns the conditional formattings in this sheet. */ 279 inline CondFormatBuffer& getCondFormats() { return maCondFormats; } 280 /** Returns the buffer for all cell comments in this sheet. */ 281 inline CommentsBuffer& getComments() { return maComments; } 282 /** Returns the auto filters for the sheet. */ 283 inline AutoFilterBuffer& getAutoFilters() { return maAutoFilters; } 284 /** Returns the buffer for all web query tables in this sheet. */ 285 inline QueryTableBuffer& getQueryTables() { return maQueryTables; } 286 /** Returns the worksheet settings object. */ 287 inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; } 288 /** Returns the page/print settings for this sheet. */ 289 inline PageSettings& getPageSettings() { return maPageSett; } 290 /** Returns the view settings for this sheet. */ 291 inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; } 292 /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only). */ 293 inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; } 294 /** Returns the BIFF drawing page for this sheet (BIFF2-BIFF8 only). */ 295 inline BiffSheetDrawing& getBiffDrawing() const { return *mxBiffDrawing; } 296 297 /** Changes the current sheet type. */ 298 inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; } 299 /** Sets a column or row page break described in the passed struct. */ 300 void setPageBreak( const PageBreakModel& rModel, bool bRowBreak ); 301 /** Inserts the hyperlink URL into the spreadsheet. */ 302 void setHyperlink( const HyperlinkModel& rModel ); 303 /** Inserts the data validation settings into the spreadsheet. */ 304 void setValidation( const ValidationModel& rModel ); 305 /** Sets the path to the DrawingML fragment of this sheet. */ 306 void setDrawingPath( const OUString& rDrawingPath ); 307 /** Sets the path to the legacy VML drawing fragment of this sheet. */ 308 void setVmlDrawingPath( const OUString& rVmlDrawingPath ); 309 310 /** Extends the used area of this sheet by the passed cell position. */ 311 void extendUsedArea( const CellAddress& rAddress ); 312 /** Extends the used area of this sheet by the passed cell range. */ 313 void extendUsedArea( const CellRangeAddress& rRange ); 314 /** Extends the shape bounding box by the position and size of the passed rectangle. */ 315 void extendShapeBoundingBox( const Rectangle& rShapeRect ); 316 317 /** Sets base width for all columns (without padding pixels). This value 318 is only used, if base width has not been set with setDefaultColumnWidth(). */ 319 void setBaseColumnWidth( sal_Int32 nWidth ); 320 /** Sets default width for all columns. This function overrides the base 321 width set with the setBaseColumnWidth() function. */ 322 void setDefaultColumnWidth( double fWidth ); 323 /** Sets column settings for a specific column range. 324 @descr Column default formatting is converted directly, other settings 325 are cached and converted in the finalizeImport() call. */ 326 void setColumnModel( const ColumnModel& rModel ); 327 /** Converts column default cell formatting. */ 328 void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const; 329 330 /** Sets default height and hidden state for all unused rows in the sheet. */ 331 void setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ); 332 /** Sets row settings for a specific row. 333 @descr Row default formatting is converted directly, other settings 334 are cached and converted in the finalizeImport() call. */ 335 void setRowModel( const RowModel& rModel ); 336 /** Specifies that the passed row needs to set its height manually. */ 337 void setManualRowHeight( sal_Int32 nRow ); 338 339 /** Initial conversion before importing the worksheet. */ 340 void initializeWorksheetImport(); 341 /** Final conversion after importing the worksheet. */ 342 void finalizeWorksheetImport(); 343 344 private: 345 typedef ::std::vector< sal_Int32 > OutlineLevelVec; 346 typedef ::std::pair< ColumnModel, sal_Int32 > ColumnModelRange; 347 typedef ::std::map< sal_Int32, ColumnModelRange > ColumnModelRangeMap; 348 typedef ::std::pair< RowModel, sal_Int32 > RowModelRange; 349 typedef ::std::map< sal_Int32, RowModelRange > RowModelRangeMap; 350 typedef ::std::list< HyperlinkModel > HyperlinkModelList; 351 typedef ::std::list< ValidationModel > ValidationModelList; 352 353 /** Inserts all imported hyperlinks into their cell ranges. */ 354 void finalizeHyperlinkRanges() const; 355 /** Generates the final URL for the passed hyperlink. */ 356 OUString getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const; 357 /** Inserts a hyperlinks into the specified cell. */ 358 void insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const; 359 360 /** Inserts all imported data validations into their cell ranges. */ 361 void finalizeValidationRanges() const; 362 363 /** Converts column properties for all columns in the sheet. */ 364 void convertColumns(); 365 /** Converts column properties. */ 366 void convertColumns( OutlineLevelVec& orColLevels, const ValueRange& rColRange, const ColumnModel& rModel ); 367 368 /** Converts row properties for all rows in the sheet. */ 369 void convertRows(); 370 /** Converts row properties. */ 371 void convertRows( OutlineLevelVec& orRowLevels, const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight = -1.0 ); 372 373 /** Converts outline grouping for the passed column or row. */ 374 void convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ); 375 /** Groups columns or rows for the given range. */ 376 void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows ); 377 378 /** Imports the drawings of the sheet (DML, VML, DFF) and updates the used area. */ 379 void finalizeDrawings(); 380 381 private: 382 typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; 383 typedef ::std::auto_ptr< BiffSheetDrawing > BiffSheetDrawingPtr; 384 385 const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object. 386 const OUString maUrlTextField; /// Service name for a URL text field. 387 const CellAddress& mrMaxApiPos; /// Reference to maximum Calc cell address from address converter. 388 CellRangeAddress maUsedArea; /// Used area of the sheet, and sheet index of the sheet. 389 ColumnModel maDefColModel; /// Default column formatting. 390 ColumnModelRangeMap maColModels; /// Ranges of columns sorted by first column index. 391 RowModel maDefRowModel; /// Default row formatting. 392 RowModelRangeMap maRowModels; /// Ranges of rows sorted by first row index. 393 HyperlinkModelList maHyperlinks; /// Cell ranges containing hyperlinks. 394 ValidationModelList maValidations; /// Cell ranges containing data validation settings. 395 ValueRangeSet maManualRowHeights; /// Rows that need manual height independent from own settings. 396 SheetDataBuffer maSheetData; /// Buffer for cell contents and cell formatting. 397 CondFormatBuffer maCondFormats; /// Buffer for conditional formattings. 398 CommentsBuffer maComments; /// Buffer for all cell comments in this sheet. 399 AutoFilterBuffer maAutoFilters; /// Sheet auto filters (not associated to a table). 400 QueryTableBuffer maQueryTables; /// Buffer for all web query tables in this sheet. 401 WorksheetSettings maSheetSett; /// Global settings for this sheet. 402 PageSettings maPageSett; /// Page/print settings for this sheet. 403 SheetViewSettings maSheetViewSett; /// View settings for this sheet. 404 VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes. 405 BiffSheetDrawingPtr mxBiffDrawing; /// Collection of all BIFF/DFF shapes. 406 OUString maDrawingPath; /// Path to DrawingML fragment. 407 OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment. 408 Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm. 409 Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings. 410 ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. 411 ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing. 412 ISegmentProgressBarRef mxFinalProgress; /// Progress bar for finalization. 413 WorksheetType meSheetType; /// Type of this sheet. 414 Reference< XSpreadsheet > mxSheet; /// Reference to the current sheet. 415 bool mbHasDefWidth; /// True = default column width is set from defaultColWidth attribute. 416 }; 417 418 // ---------------------------------------------------------------------------- 419 420 WorksheetGlobals::WorksheetGlobals( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : 421 WorkbookHelper( rHelper ), 422 maSheetCellRanges( CREATE_OUSTRING( "com.sun.star.sheet.SheetCellRanges" ) ), 423 maUrlTextField( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), 424 mrMaxApiPos( rHelper.getAddressConverter().getMaxApiAddress() ), 425 maUsedArea( nSheet, SAL_MAX_INT32, SAL_MAX_INT32, -1, -1 ), 426 maSheetData( *this ), 427 maCondFormats( *this ), 428 maComments( *this ), 429 maAutoFilters( *this ), 430 maQueryTables( *this ), 431 maSheetSett( *this ), 432 maPageSett( *this ), 433 maSheetViewSett( *this ), 434 mxProgressBar( rxProgressBar ), 435 meSheetType( eSheetType ), 436 mbHasDefWidth( false ) 437 { 438 mxSheet = getSheetFromDoc( nSheet ); 439 if( !mxSheet.is() ) 440 maUsedArea.Sheet = -1; 441 442 // default column settings (width and hidden state may be updated later) 443 maDefColModel.mfWidth = 8.5; 444 maDefColModel.mnXfId = -1; 445 maDefColModel.mnLevel = 0; 446 maDefColModel.mbHidden = false; 447 maDefColModel.mbCollapsed = false; 448 449 // default row settings (height and hidden state may be updated later) 450 maDefRowModel.mfHeight = 0.0; 451 maDefRowModel.mnXfId = -1; 452 maDefRowModel.mnLevel = 0; 453 maDefRowModel.mbCustomHeight = false; 454 maDefRowModel.mbCustomFormat = false; 455 maDefRowModel.mbShowPhonetic = false; 456 maDefRowModel.mbHidden = false; 457 maDefRowModel.mbCollapsed = false; 458 459 // buffers 460 switch( getFilterType() ) 461 { 462 case FILTER_OOXML: 463 mxVmlDrawing.reset( new VmlDrawing( *this ) ); 464 break; 465 case FILTER_BIFF: 466 mxBiffDrawing.reset( new BiffSheetDrawing( *this ) ); 467 break; 468 case FILTER_UNKNOWN: 469 break; 470 } 471 472 // prepare progress bars 473 if( mxProgressBar.get() ) 474 { 475 mxRowProgress = mxProgressBar->createSegment( 0.5 ); 476 mxFinalProgress = mxProgressBar->createSegment( 0.5 ); 477 } 478 } 479 480 Reference< XCell > WorksheetGlobals::getCell( const CellAddress& rAddress ) const 481 { 482 Reference< XCell > xCell; 483 if( mxSheet.is() ) try 484 { 485 xCell = mxSheet->getCellByPosition( rAddress.Column, rAddress.Row ); 486 } 487 catch( Exception& ) 488 { 489 } 490 return xCell; 491 } 492 493 Reference< XCellRange > WorksheetGlobals::getCellRange( const CellRangeAddress& rRange ) const 494 { 495 Reference< XCellRange > xRange; 496 if( mxSheet.is() ) try 497 { 498 xRange = mxSheet->getCellRangeByPosition( rRange.StartColumn, rRange.StartRow, rRange.EndColumn, rRange.EndRow ); 499 } 500 catch( Exception& ) 501 { 502 } 503 return xRange; 504 } 505 506 Reference< XSheetCellRanges > WorksheetGlobals::getCellRangeList( const ApiCellRangeList& rRanges ) const 507 { 508 Reference< XSheetCellRanges > xRanges; 509 if( mxSheet.is() && !rRanges.empty() ) try 510 { 511 xRanges.set( getBaseFilter().getModelFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); 512 Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW ); 513 xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False ); 514 } 515 catch( Exception& ) 516 { 517 } 518 return xRanges; 519 } 520 521 Reference< XCellRange > WorksheetGlobals::getColumn( sal_Int32 nCol ) const 522 { 523 Reference< XCellRange > xColumn; 524 try 525 { 526 Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW ); 527 Reference< XTableColumns > xColumns( xColRowRange->getColumns(), UNO_SET_THROW ); 528 xColumn.set( xColumns->getByIndex( nCol ), UNO_QUERY ); 529 } 530 catch( Exception& ) 531 { 532 } 533 return xColumn; 534 } 535 536 Reference< XCellRange > WorksheetGlobals::getRow( sal_Int32 nRow ) const 537 { 538 Reference< XCellRange > xRow; 539 try 540 { 541 Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW ); 542 Reference< XTableRows > xRows( xColRowRange->getRows(), UNO_SET_THROW ); 543 xRow.set( xRows->getByIndex( nRow ), UNO_QUERY ); 544 } 545 catch( Exception& ) 546 { 547 } 548 return xRow; 549 } 550 551 Reference< XTableColumns > WorksheetGlobals::getColumns( const ValueRange& rColRange ) const 552 { 553 Reference< XTableColumns > xColumns; 554 sal_Int32 nLastCol = ::std::min( rColRange.mnLast, mrMaxApiPos.Column ); 555 if( (0 <= rColRange.mnFirst) && (rColRange.mnFirst <= nLastCol) ) 556 { 557 Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), rColRange.mnFirst, 0, nLastCol, 0 ) ), UNO_QUERY ); 558 if( xRange.is() ) 559 xColumns = xRange->getColumns(); 560 } 561 return xColumns; 562 } 563 564 Reference< XTableRows > WorksheetGlobals::getRows( const ValueRange& rRowRange ) const 565 { 566 Reference< XTableRows > xRows; 567 sal_Int32 nLastRow = ::std::min( rRowRange.mnLast, mrMaxApiPos.Row ); 568 if( (0 <= rRowRange.mnFirst) && (rRowRange.mnFirst <= nLastRow) ) 569 { 570 Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), 0, rRowRange.mnFirst, 0, nLastRow ) ), UNO_QUERY ); 571 if( xRange.is() ) 572 xRows = xRange->getRows(); 573 } 574 return xRows; 575 } 576 577 Reference< XDrawPage > WorksheetGlobals::getDrawPage() const 578 { 579 Reference< XDrawPage > xDrawPage; 580 try 581 { 582 xDrawPage = Reference< XDrawPageSupplier >( mxSheet, UNO_QUERY_THROW )->getDrawPage(); 583 } 584 catch( Exception& ) 585 { 586 } 587 return xDrawPage; 588 } 589 590 const Size& WorksheetGlobals::getDrawPageSize() const 591 { 592 OSL_ENSURE( (maDrawPageSize.Width > 0) && (maDrawPageSize.Height > 0), "WorksheetGlobals::getDrawPageSize - called too early, size invalid" ); 593 return maDrawPageSize; 594 } 595 596 Point WorksheetGlobals::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const 597 { 598 Point aPoint; 599 PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) ); 600 aCellProp.getProperty( aPoint, PROP_Position ); 601 return aPoint; 602 } 603 604 Size WorksheetGlobals::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const 605 { 606 Size aSize; 607 PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) ); 608 aCellProp.getProperty( aSize, PROP_Size ); 609 return aSize; 610 } 611 612 namespace { 613 614 inline sal_Int32 lclGetMidAddr( sal_Int32 nBegAddr, sal_Int32 nEndAddr, sal_Int32 nBegPos, sal_Int32 nEndPos, sal_Int32 nSearchPos ) 615 { 616 // use sal_Int64 to prevent integer overflow 617 return nBegAddr + 1 + static_cast< sal_Int32 >( static_cast< sal_Int64 >( nEndAddr - nBegAddr - 2 ) * (nSearchPos - nBegPos) / (nEndPos - nBegPos) ); 618 } 619 620 bool lclPrepareInterval( sal_Int32 nBegAddr, sal_Int32& rnMidAddr, sal_Int32 nEndAddr, 621 sal_Int32 nBegPos, sal_Int32 nEndPos, sal_Int32 nSearchPos ) 622 { 623 // searched position before nBegPos -> use nBegAddr 624 if( nSearchPos <= nBegPos ) 625 { 626 rnMidAddr = nBegAddr; 627 return false; 628 } 629 630 // searched position after nEndPos, or begin next to end -> use nEndAddr 631 if( (nSearchPos >= nEndPos) || (nBegAddr + 1 >= nEndAddr) ) 632 { 633 rnMidAddr = nEndAddr; 634 return false; 635 } 636 637 /* Otherwise find mid address according to position. lclGetMidAddr() will 638 return an address between nBegAddr and nEndAddr. */ 639 rnMidAddr = lclGetMidAddr( nBegAddr, nEndAddr, nBegPos, nEndPos, nSearchPos ); 640 return true; 641 } 642 643 bool lclUpdateInterval( sal_Int32& rnBegAddr, sal_Int32& rnMidAddr, sal_Int32& rnEndAddr, 644 sal_Int32& rnBegPos, sal_Int32 nMidPos, sal_Int32& rnEndPos, sal_Int32 nSearchPos ) 645 { 646 // nSearchPos < nMidPos: use the interval [begin,mid] in the next iteration 647 if( nSearchPos < nMidPos ) 648 { 649 // if rnBegAddr is next to rnMidAddr, the latter is the column/row in question 650 if( rnBegAddr + 1 >= rnMidAddr ) 651 return false; 652 // otherwise, set interval end to mid 653 rnEndPos = nMidPos; 654 rnEndAddr = rnMidAddr; 655 rnMidAddr = lclGetMidAddr( rnBegAddr, rnEndAddr, rnBegPos, rnEndPos, nSearchPos ); 656 return true; 657 } 658 659 // nSearchPos > nMidPos: use the interval [mid,end] in the next iteration 660 if( nSearchPos > nMidPos ) 661 { 662 // if rnMidAddr is next to rnEndAddr, the latter is the column/row in question 663 if( rnMidAddr + 1 >= rnEndAddr ) 664 { 665 rnMidAddr = rnEndAddr; 666 return false; 667 } 668 // otherwise, set interval start to mid 669 rnBegPos = nMidPos; 670 rnBegAddr = rnMidAddr; 671 rnMidAddr = lclGetMidAddr( rnBegAddr, rnEndAddr, rnBegPos, rnEndPos, nSearchPos ); 672 return true; 673 } 674 675 // nSearchPos == nMidPos: rnMidAddr is the column/row in question, do not loop anymore 676 return false; 677 } 678 679 } // namespace 680 681 CellAddress WorksheetGlobals::getCellAddressFromPosition( const Point& rPosition ) const 682 { 683 // starting cell address and its position in drawing layer (top-left edge) 684 sal_Int32 nBegCol = 0; 685 sal_Int32 nBegRow = 0; 686 Point aBegPos( 0, 0 ); 687 688 // end cell address and its position in drawing layer (bottom-right edge) 689 sal_Int32 nEndCol = mrMaxApiPos.Column + 1; 690 sal_Int32 nEndRow = mrMaxApiPos.Row + 1; 691 Point aEndPos( maDrawPageSize.Width, maDrawPageSize.Height ); 692 693 // starting point for interval search 694 sal_Int32 nMidCol, nMidRow; 695 bool bLoopCols = lclPrepareInterval( nBegCol, nMidCol, nEndCol, aBegPos.X, aEndPos.X, rPosition.X ); 696 bool bLoopRows = lclPrepareInterval( nBegRow, nMidRow, nEndRow, aBegPos.Y, aEndPos.Y, rPosition.Y ); 697 Point aMidPos = getCellPosition( nMidCol, nMidRow ); 698 699 /* The loop will find the column/row index of the cell right of/below 700 the cell containing the passed point, unless the point is located at 701 the top or left border of the containing cell. */ 702 while( bLoopCols || bLoopRows ) 703 { 704 bLoopCols = bLoopCols && lclUpdateInterval( nBegCol, nMidCol, nEndCol, aBegPos.X, aMidPos.X, aEndPos.X, rPosition.X ); 705 bLoopRows = bLoopRows && lclUpdateInterval( nBegRow, nMidRow, nEndRow, aBegPos.Y, aMidPos.Y, aEndPos.Y, rPosition.Y ); 706 aMidPos = getCellPosition( nMidCol, nMidRow ); 707 } 708 709 /* The cell left of/above the current search position contains the passed 710 point, unless the point is located on the top/left border of the cell, 711 or the last column/row of the sheet has been reached. */ 712 if( aMidPos.X > rPosition.X ) --nMidCol; 713 if( aMidPos.Y > rPosition.Y ) --nMidRow; 714 return CellAddress( getSheetIndex(), nMidCol, nMidRow ); 715 } 716 717 CellRangeAddress WorksheetGlobals::getCellRangeFromRectangle( const Rectangle& rRect ) const 718 { 719 CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ) ); 720 Point aBotRight( rRect.X + rRect.Width, rRect.Y + rRect.Height ); 721 CellAddress aEndAddr = getCellAddressFromPosition( aBotRight ); 722 bool bMultiCols = aStartAddr.Column < aEndAddr.Column; 723 bool bMultiRows = aStartAddr.Row < aEndAddr.Row; 724 if( bMultiCols || bMultiRows ) 725 { 726 /* Reduce end position of the cell range to previous column or row, if 727 the rectangle ends exactly between two columns or rows. */ 728 Point aEndPos = getCellPosition( aEndAddr.Column, aEndAddr.Row ); 729 if( bMultiCols && (aBotRight.X <= aEndPos.X) ) 730 --aEndAddr.Column; 731 if( bMultiRows && (aBotRight.Y <= aEndPos.Y) ) 732 --aEndAddr.Row; 733 } 734 return CellRangeAddress( getSheetIndex(), aStartAddr.Column, aStartAddr.Row, aEndAddr.Column, aEndAddr.Row ); 735 } 736 737 void WorksheetGlobals::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) 738 { 739 if( rModel.mbManual && (rModel.mnColRow > 0) ) 740 { 741 PropertySet aPropSet( bRowBreak ? getRow( rModel.mnColRow ) : getColumn( rModel.mnColRow ) ); 742 aPropSet.setProperty( PROP_IsStartOfNewPage, true ); 743 } 744 } 745 746 void WorksheetGlobals::setHyperlink( const HyperlinkModel& rModel ) 747 { 748 maHyperlinks.push_back( rModel ); 749 } 750 751 void WorksheetGlobals::setValidation( const ValidationModel& rModel ) 752 { 753 maValidations.push_back( rModel ); 754 } 755 756 void WorksheetGlobals::setDrawingPath( const OUString& rDrawingPath ) 757 { 758 maDrawingPath = rDrawingPath; 759 } 760 761 void WorksheetGlobals::setVmlDrawingPath( const OUString& rVmlDrawingPath ) 762 { 763 maVmlDrawingPath = rVmlDrawingPath; 764 } 765 766 void WorksheetGlobals::extendUsedArea( const CellAddress& rAddress ) 767 { 768 maUsedArea.StartColumn = ::std::min( maUsedArea.StartColumn, rAddress.Column ); 769 maUsedArea.StartRow = ::std::min( maUsedArea.StartRow, rAddress.Row ); 770 maUsedArea.EndColumn = ::std::max( maUsedArea.EndColumn, rAddress.Column ); 771 maUsedArea.EndRow = ::std::max( maUsedArea.EndRow, rAddress.Row ); 772 } 773 774 void WorksheetGlobals::extendUsedArea( const CellRangeAddress& rRange ) 775 { 776 extendUsedArea( CellAddress( rRange.Sheet, rRange.StartColumn, rRange.StartRow ) ); 777 extendUsedArea( CellAddress( rRange.Sheet, rRange.EndColumn, rRange.EndRow ) ); 778 } 779 780 void WorksheetGlobals::extendShapeBoundingBox( const Rectangle& rShapeRect ) 781 { 782 if( (maShapeBoundingBox.Width == 0) && (maShapeBoundingBox.Height == 0) ) 783 { 784 // width and height of maShapeBoundingBox are assumed to be zero on first cell 785 maShapeBoundingBox = rShapeRect; 786 } 787 else 788 { 789 sal_Int32 nEndX = ::std::max( maShapeBoundingBox.X + maShapeBoundingBox.Width, rShapeRect.X + rShapeRect.Width ); 790 sal_Int32 nEndY = ::std::max( maShapeBoundingBox.Y + maShapeBoundingBox.Height, rShapeRect.Y + rShapeRect.Height ); 791 maShapeBoundingBox.X = ::std::min( maShapeBoundingBox.X, rShapeRect.X ); 792 maShapeBoundingBox.Y = ::std::min( maShapeBoundingBox.Y, rShapeRect.Y ); 793 maShapeBoundingBox.Width = nEndX - maShapeBoundingBox.X; 794 maShapeBoundingBox.Height = nEndY - maShapeBoundingBox.Y; 795 } 796 } 797 798 void WorksheetGlobals::setBaseColumnWidth( sal_Int32 nWidth ) 799 { 800 // do not modify width, if setDefaultColumnWidth() has been used 801 if( !mbHasDefWidth && (nWidth > 0) ) 802 { 803 // #i3006# add 5 pixels padding to the width 804 const UnitConverter& rUnitConv = getUnitConverter(); 805 maDefColModel.mfWidth = rUnitConv.scaleFromMm100( 806 rUnitConv.scaleToMm100( nWidth, UNIT_DIGIT ) + rUnitConv.scaleToMm100( 5, UNIT_SCREENX ), UNIT_DIGIT ); 807 } 808 } 809 810 void WorksheetGlobals::setDefaultColumnWidth( double fWidth ) 811 { 812 // overrides a width set with setBaseColumnWidth() 813 if( fWidth > 0.0 ) 814 { 815 maDefColModel.mfWidth = fWidth; 816 mbHasDefWidth = true; 817 } 818 } 819 820 void WorksheetGlobals::setColumnModel( const ColumnModel& rModel ) 821 { 822 // convert 1-based OOXML column indexes to 0-based API column indexes 823 sal_Int32 nFirstCol = rModel.maRange.mnFirst - 1; 824 sal_Int32 nLastCol = rModel.maRange.mnLast - 1; 825 if( getAddressConverter().checkCol( nFirstCol, true ) && (nFirstCol <= nLastCol) ) 826 { 827 // validate last column index 828 if( !getAddressConverter().checkCol( nLastCol, true ) ) 829 nLastCol = mrMaxApiPos.Column; 830 // try to find entry in column model map that is able to merge with the passed model 831 bool bInsertModel = true; 832 if( !maColModels.empty() ) 833 { 834 // find first column model range following nFirstCol (nFirstCol < aIt->first), or end of map 835 ColumnModelRangeMap::iterator aIt = maColModels.upper_bound( nFirstCol ); 836 OSL_ENSURE( aIt == maColModels.end(), "WorksheetGlobals::setColModel - columns are unsorted" ); 837 // if inserting before another column model, get last free column 838 OSL_ENSURE( (aIt == maColModels.end()) || (nLastCol < aIt->first), "WorksheetGlobals::setColModel - multiple models of the same column" ); 839 if( aIt != maColModels.end() ) 840 nLastCol = ::std::min( nLastCol, aIt->first - 1 ); 841 if( aIt != maColModels.begin() ) 842 { 843 // go to previous map element (which may be able to merge with the passed model) 844 --aIt; 845 // the usage of upper_bound() above ensures that aIt->first is less than or equal to nFirstCol now 846 sal_Int32& rnLastMapCol = aIt->second.second; 847 OSL_ENSURE( rnLastMapCol < nFirstCol, "WorksheetGlobals::setColModel - multiple models of the same column" ); 848 nFirstCol = ::std::max( rnLastMapCol + 1, nFirstCol ); 849 if( (rnLastMapCol + 1 == nFirstCol) && (nFirstCol <= nLastCol) && aIt->second.first.isMergeable( rModel ) ) 850 { 851 // can merge with existing model, update last column index 852 rnLastMapCol = nLastCol; 853 bInsertModel = false; 854 } 855 } 856 } 857 if( nFirstCol <= nLastCol ) 858 { 859 // insert the column model, if it has not been merged with another 860 if( bInsertModel ) 861 maColModels[ nFirstCol ] = ColumnModelRange( rModel, nLastCol ); 862 // set column formatting directly 863 convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId ); 864 } 865 } 866 } 867 868 void WorksheetGlobals::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const 869 { 870 CellRangeAddress aRange( getSheetIndex(), nFirstCol, 0, nLastCol, mrMaxApiPos.Row ); 871 if( getAddressConverter().validateCellRange( aRange, true, false ) ) 872 { 873 PropertySet aPropSet( getCellRange( aRange ) ); 874 getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); 875 } 876 } 877 878 void WorksheetGlobals::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) 879 { 880 maDefRowModel.mfHeight = fHeight; 881 maDefRowModel.mbCustomHeight = bCustomHeight; 882 maDefRowModel.mbHidden = bHidden; 883 maDefRowModel.mbThickTop = bThickTop; 884 maDefRowModel.mbThickBottom = bThickBottom; 885 } 886 887 void WorksheetGlobals::setRowModel( const RowModel& rModel ) 888 { 889 // convert 1-based OOXML row index to 0-based API row index 890 sal_Int32 nRow = rModel.mnRow - 1; 891 if( getAddressConverter().checkRow( nRow, true ) ) 892 { 893 // try to find entry in row model map that is able to merge with the passed model 894 bool bInsertModel = true; 895 bool bUnusedRow = true; 896 if( !maRowModels.empty() ) 897 { 898 // find first row model range following nRow (nRow < aIt->first), or end of map 899 RowModelRangeMap::iterator aIt = maRowModels.upper_bound( nRow ); 900 OSL_ENSURE( aIt == maRowModels.end(), "WorksheetGlobals::setRowModel - rows are unsorted" ); 901 if( aIt != maRowModels.begin() ) 902 { 903 // go to previous map element (which may be able to merge with the passed model) 904 --aIt; 905 // the usage of upper_bound() above ensures that aIt->first is less than or equal to nRow now 906 sal_Int32& rnLastMapRow = aIt->second.second; 907 bUnusedRow = rnLastMapRow < nRow; 908 OSL_ENSURE( bUnusedRow, "WorksheetGlobals::setRowModel - multiple models of the same row" ); 909 if( (rnLastMapRow + 1 == nRow) && aIt->second.first.isMergeable( rModel ) ) 910 { 911 // can merge with existing model, update last row index 912 ++rnLastMapRow; 913 bInsertModel = false; 914 } 915 } 916 } 917 if( bUnusedRow ) 918 { 919 // insert the row model, if it has not been merged with another 920 if( bInsertModel ) 921 maRowModels[ nRow ] = RowModelRange( rModel, nRow ); 922 // set row formatting 923 maSheetData.setRowFormat( nRow, rModel.mnXfId, rModel.mbCustomFormat ); 924 // set column spans 925 maSheetData.setColSpans( nRow, rModel.maColSpans ); 926 } 927 } 928 lclUpdateProgressBar( mxRowProgress, maUsedArea, nRow ); 929 } 930 931 void WorksheetGlobals::setManualRowHeight( sal_Int32 nRow ) 932 { 933 maManualRowHeights.insert( nRow ); 934 } 935 936 void WorksheetGlobals::initializeWorksheetImport() 937 { 938 // set default cell style for unused cells 939 PropertySet aPropSet( mxSheet ); 940 aPropSet.setProperty( PROP_CellStyle, getStyles().getDefaultStyleName() ); 941 942 /* Remember the current sheet index in global data, needed by global 943 objects, e.g. the chart converter. */ 944 setCurrentSheetIndex( getSheetIndex() ); 945 } 946 947 void WorksheetGlobals::finalizeWorksheetImport() 948 { 949 lclUpdateProgressBar( mxRowProgress, 1.0 ); 950 maSheetData.finalizeImport(); 951 lclUpdateProgressBar( mxFinalProgress, 0.25 ); 952 finalizeHyperlinkRanges(); 953 finalizeValidationRanges(); 954 maAutoFilters.finalizeImport( getSheetIndex() ); 955 maCondFormats.finalizeImport(); 956 maQueryTables.finalizeImport(); 957 maSheetSett.finalizeImport(); 958 maPageSett.finalizeImport(); 959 maSheetViewSett.finalizeImport(); 960 961 lclUpdateProgressBar( mxFinalProgress, 0.5 ); 962 convertColumns(); 963 convertRows(); 964 lclUpdateProgressBar( mxFinalProgress, 0.75 ); 965 finalizeDrawings(); 966 lclUpdateProgressBar( mxFinalProgress, 1.0 ); 967 968 // forget current sheet index in global data 969 setCurrentSheetIndex( -1 ); 970 } 971 972 // private -------------------------------------------------------------------- 973 974 void WorksheetGlobals::finalizeHyperlinkRanges() const 975 { 976 for( HyperlinkModelList::const_iterator aIt = maHyperlinks.begin(), aEnd = maHyperlinks.end(); aIt != aEnd; ++aIt ) 977 { 978 OUString aUrl = getHyperlinkUrl( *aIt ); 979 // try to insert URL into each cell of the range 980 if( aUrl.getLength() > 0 ) 981 for( CellAddress aAddress( getSheetIndex(), aIt->maRange.StartColumn, aIt->maRange.StartRow ); aAddress.Row <= aIt->maRange.EndRow; ++aAddress.Row ) 982 for( aAddress.Column = aIt->maRange.StartColumn; aAddress.Column <= aIt->maRange.EndColumn; ++aAddress.Column ) 983 insertHyperlink( aAddress, aUrl ); 984 } 985 } 986 987 OUString WorksheetGlobals::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const 988 { 989 OUStringBuffer aUrlBuffer; 990 if( rHyperlink.maTarget.getLength() > 0 ) 991 aUrlBuffer.append( getBaseFilter().getAbsoluteUrl( rHyperlink.maTarget ) ); 992 if( rHyperlink.maLocation.getLength() > 0 ) 993 aUrlBuffer.append( sal_Unicode( '#' ) ).append( rHyperlink.maLocation ); 994 OUString aUrl = aUrlBuffer.makeStringAndClear(); 995 996 // convert '#SheetName!A1' to '#SheetName.A1' 997 if( (aUrl.getLength() > 0) && (aUrl[ 0 ] == '#') ) 998 { 999 sal_Int32 nSepPos = aUrl.lastIndexOf( '!' ); 1000 if( nSepPos > 0 ) 1001 { 1002 // replace the exclamation mark with a period 1003 aUrl = aUrl.replaceAt( nSepPos, 1, OUString( sal_Unicode( '.' ) ) ); 1004 // #i66592# convert sheet names that have been renamed on import 1005 OUString aSheetName = aUrl.copy( 1, nSepPos - 1 ); 1006 OUString aCalcName = getWorksheets().getCalcSheetName( aSheetName ); 1007 if( aCalcName.getLength() > 0 ) 1008 aUrl = aUrl.replaceAt( 1, nSepPos - 1, aCalcName ); 1009 } 1010 } 1011 1012 return aUrl; 1013 } 1014 1015 void WorksheetGlobals::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const 1016 { 1017 Reference< XCell > xCell = getCell( rAddress ); 1018 if( xCell.is() ) switch( xCell->getType() ) 1019 { 1020 // #i54261# restrict creation of URL field to text cells 1021 case CellContentType_TEXT: 1022 { 1023 Reference< XText > xText( xCell, UNO_QUERY ); 1024 if( xText.is() ) 1025 { 1026 // create a URL field object and set its properties 1027 Reference< XTextContent > xUrlField( getBaseFilter().getModelFactory()->createInstance( maUrlTextField ), UNO_QUERY ); 1028 OSL_ENSURE( xUrlField.is(), "WorksheetGlobals::insertHyperlink - cannot create text field" ); 1029 if( xUrlField.is() ) 1030 { 1031 // properties of the URL field 1032 PropertySet aPropSet( xUrlField ); 1033 aPropSet.setProperty( PROP_URL, rUrl ); 1034 aPropSet.setProperty( PROP_Representation, xText->getString() ); 1035 try 1036 { 1037 // insert the field into the cell 1038 xText->setString( OUString() ); 1039 Reference< XTextRange > xRange( xText->createTextCursor(), UNO_QUERY_THROW ); 1040 xText->insertTextContent( xRange, xUrlField, sal_False ); 1041 } 1042 catch( const Exception& ) 1043 { 1044 OSL_ENSURE( false, "WorksheetGlobals::insertHyperlink - cannot insert text field" ); 1045 } 1046 } 1047 } 1048 } 1049 break; 1050 1051 // fix for #i31050# disabled, HYPERLINK is not able to return numeric value (#i91351#) 1052 #if 0 1053 // #i31050# replace number with HYPERLINK function 1054 case CellContentType_VALUE: 1055 { 1056 Reference< XFormulaTokens > xTokens( xCell, UNO_QUERY ); 1057 ApiTokenSequence aTokens = getFormulaParser().convertNumberToHyperlink( rUrl, xCell->getValue() ); 1058 OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula token interface" ); 1059 if( xTokens.is() && aTokens.hasElements() ) 1060 xTokens->setTokens( aTokens ); 1061 } 1062 break; 1063 #endif 1064 1065 default:; 1066 } 1067 } 1068 1069 void WorksheetGlobals::finalizeValidationRanges() const 1070 { 1071 for( ValidationModelList::const_iterator aIt = maValidations.begin(), aEnd = maValidations.end(); aIt != aEnd; ++aIt ) 1072 { 1073 PropertySet aPropSet( getCellRangeList( aIt->maRanges ) ); 1074 1075 Reference< XPropertySet > xValidation( aPropSet.getAnyProperty( PROP_Validation ), UNO_QUERY ); 1076 if( xValidation.is() ) 1077 { 1078 PropertySet aValProps( xValidation ); 1079 1080 // convert validation type to API enum 1081 ValidationType eType = ValidationType_ANY; 1082 switch( aIt->mnType ) 1083 { 1084 case XML_custom: eType = ValidationType_CUSTOM; break; 1085 case XML_date: eType = ValidationType_DATE; break; 1086 case XML_decimal: eType = ValidationType_DECIMAL; break; 1087 case XML_list: eType = ValidationType_LIST; break; 1088 case XML_none: eType = ValidationType_ANY; break; 1089 case XML_textLength: eType = ValidationType_TEXT_LEN; break; 1090 case XML_time: eType = ValidationType_TIME; break; 1091 case XML_whole: eType = ValidationType_WHOLE; break; 1092 default: OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown validation type" ); 1093 } 1094 aValProps.setProperty( PROP_Type, eType ); 1095 1096 // convert error alert style to API enum 1097 ValidationAlertStyle eAlertStyle = ValidationAlertStyle_STOP; 1098 switch( aIt->mnErrorStyle ) 1099 { 1100 case XML_information: eAlertStyle = ValidationAlertStyle_INFO; break; 1101 case XML_stop: eAlertStyle = ValidationAlertStyle_STOP; break; 1102 case XML_warning: eAlertStyle = ValidationAlertStyle_WARNING; break; 1103 default: OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown error style" ); 1104 } 1105 aValProps.setProperty( PROP_ErrorAlertStyle, eAlertStyle ); 1106 1107 // convert dropdown style to API visibility constants 1108 sal_Int16 nVisibility = aIt->mbNoDropDown ? TableValidationVisibility::INVISIBLE : TableValidationVisibility::UNSORTED; 1109 aValProps.setProperty( PROP_ShowList, nVisibility ); 1110 1111 // messages 1112 aValProps.setProperty( PROP_ShowInputMessage, aIt->mbShowInputMsg ); 1113 aValProps.setProperty( PROP_InputTitle, aIt->maInputTitle ); 1114 aValProps.setProperty( PROP_InputMessage, aIt->maInputMessage ); 1115 aValProps.setProperty( PROP_ShowErrorMessage, aIt->mbShowErrorMsg ); 1116 aValProps.setProperty( PROP_ErrorTitle, aIt->maErrorTitle ); 1117 aValProps.setProperty( PROP_ErrorMessage, aIt->maErrorMessage ); 1118 1119 // allow blank cells 1120 aValProps.setProperty( PROP_IgnoreBlankCells, aIt->mbAllowBlank ); 1121 1122 try 1123 { 1124 // condition operator 1125 Reference< XSheetCondition > xSheetCond( xValidation, UNO_QUERY_THROW ); 1126 xSheetCond->setOperator( CondFormatBuffer::convertToApiOperator( aIt->mnOperator ) ); 1127 1128 // condition formulas 1129 Reference< XMultiFormulaTokens > xTokens( xValidation, UNO_QUERY_THROW ); 1130 xTokens->setTokens( 0, aIt->maTokens1 ); 1131 xTokens->setTokens( 1, aIt->maTokens2 ); 1132 } 1133 catch( Exception& ) 1134 { 1135 } 1136 1137 // write back validation settings to cell range(s) 1138 aPropSet.setProperty( PROP_Validation, xValidation ); 1139 } 1140 } 1141 } 1142 1143 void WorksheetGlobals::convertColumns() 1144 { 1145 sal_Int32 nNextCol = 0; 1146 sal_Int32 nMaxCol = mrMaxApiPos.Column; 1147 // stores first grouped column index for each level 1148 OutlineLevelVec aColLevels; 1149 1150 for( ColumnModelRangeMap::iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt ) 1151 { 1152 // column indexes are stored 0-based in maColModels 1153 ValueRange aColRange( ::std::max( aIt->first, nNextCol ), ::std::min( aIt->second.second, nMaxCol ) ); 1154 // process gap between two column models, use default column model 1155 if( nNextCol < aColRange.mnFirst ) 1156 convertColumns( aColLevels, ValueRange( nNextCol, aColRange.mnFirst - 1 ), maDefColModel ); 1157 // process the column model 1158 convertColumns( aColLevels, aColRange, aIt->second.first ); 1159 // cache next column to be processed 1160 nNextCol = aColRange.mnLast + 1; 1161 } 1162 1163 // remaining default columns to end of sheet 1164 convertColumns( aColLevels, ValueRange( nNextCol, nMaxCol ), maDefColModel ); 1165 // close remaining column outlines spanning to end of sheet 1166 convertOutlines( aColLevels, nMaxCol + 1, 0, false, false ); 1167 } 1168 1169 void WorksheetGlobals::convertColumns( OutlineLevelVec& orColLevels, 1170 const ValueRange& rColRange, const ColumnModel& rModel ) 1171 { 1172 PropertySet aPropSet( getColumns( rColRange ) ); 1173 1174 // column width: convert 'number of characters' to column width in 1/100 mm 1175 sal_Int32 nWidth = getUnitConverter().scaleToMm100( rModel.mfWidth, UNIT_DIGIT ); 1176 // macro sheets have double width 1177 if( meSheetType == SHEETTYPE_MACROSHEET ) 1178 nWidth *= 2; 1179 if( nWidth > 0 ) 1180 aPropSet.setProperty( PROP_Width, nWidth ); 1181 1182 // hidden columns: TODO: #108683# hide columns later? 1183 if( rModel.mbHidden ) 1184 aPropSet.setProperty( PROP_IsVisible, false ); 1185 1186 // outline settings for this column range 1187 convertOutlines( orColLevels, rColRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, false ); 1188 } 1189 1190 void WorksheetGlobals::convertRows() 1191 { 1192 sal_Int32 nNextRow = 0; 1193 sal_Int32 nMaxRow = mrMaxApiPos.Row; 1194 // stores first grouped row index for each level 1195 OutlineLevelVec aRowLevels; 1196 1197 for( RowModelRangeMap::iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt ) 1198 { 1199 // row indexes are stored 0-based in maRowModels 1200 ValueRange aRowRange( ::std::max( aIt->first, nNextRow ), ::std::min( aIt->second.second, nMaxRow ) ); 1201 // process gap between two row models, use default row model 1202 if( nNextRow < aRowRange.mnFirst ) 1203 convertRows( aRowLevels, ValueRange( nNextRow, aRowRange.mnFirst - 1 ), maDefRowModel ); 1204 // process the row model 1205 convertRows( aRowLevels, aRowRange, aIt->second.first, maDefRowModel.mfHeight ); 1206 // cache next row to be processed 1207 nNextRow = aRowRange.mnLast + 1; 1208 } 1209 1210 // remaining default rows to end of sheet 1211 convertRows( aRowLevels, ValueRange( nNextRow, nMaxRow ), maDefRowModel ); 1212 // close remaining row outlines spanning to end of sheet 1213 convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true ); 1214 } 1215 1216 void WorksheetGlobals::convertRows( OutlineLevelVec& orRowLevels, 1217 const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight ) 1218 { 1219 // row height: convert points to row height in 1/100 mm 1220 double fHeight = (rModel.mfHeight >= 0.0) ? rModel.mfHeight : fDefHeight; 1221 sal_Int32 nHeight = getUnitConverter().scaleToMm100( fHeight, UNIT_POINT ); 1222 if( nHeight > 0 ) 1223 { 1224 /* Get all rows that have custom height inside the passed row model. 1225 If the model has the custom height flag set, all its rows have 1226 custom height, otherwise get all rows specified in the class member 1227 maManualRowHeights that are inside the passed row model. */ 1228 ValueRangeVector aManualRows; 1229 if( rModel.mbCustomHeight ) 1230 aManualRows.push_back( rRowRange ); 1231 else 1232 aManualRows = maManualRowHeights.getIntersection( rRowRange ); 1233 for( ValueRangeVector::const_iterator aIt = aManualRows.begin(), aEnd = aManualRows.end(); aIt != aEnd; ++aIt ) 1234 { 1235 PropertySet aPropSet( getRows( *aIt ) ); 1236 aPropSet.setProperty( PROP_Height, nHeight ); 1237 } 1238 } 1239 1240 // hidden rows: TODO: #108683# hide rows later? 1241 if( rModel.mbHidden ) 1242 { 1243 PropertySet aPropSet( getRows( rRowRange ) ); 1244 /* #i116460# Use VisibleFlag instead of IsVisible: directly set the 1245 flag, without drawing layer update etc. (only possible before 1246 shapes are inserted). */ 1247 aPropSet.setProperty( PROP_VisibleFlag, false ); 1248 } 1249 1250 // outline settings for this row range 1251 convertOutlines( orRowLevels, rRowRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, true ); 1252 } 1253 1254 void WorksheetGlobals::convertOutlines( OutlineLevelVec& orLevels, 1255 sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ) 1256 { 1257 /* It is ensured from caller functions, that this function is called 1258 without any gaps between the processed column or row ranges. */ 1259 1260 OSL_ENSURE( nLevel >= 0, "WorksheetGlobals::convertOutlines - negative outline level" ); 1261 nLevel = ::std::max< sal_Int32 >( nLevel, 0 ); 1262 1263 sal_Int32 nSize = orLevels.size(); 1264 if( nSize < nLevel ) 1265 { 1266 // Outline level increased. Push the begin column position. 1267 for( sal_Int32 nIndex = nSize; nIndex < nLevel; ++nIndex ) 1268 orLevels.push_back( nColRow ); 1269 } 1270 else if( nLevel < nSize ) 1271 { 1272 // Outline level decreased. Pop them all out. 1273 for( sal_Int32 nIndex = nLevel; nIndex < nSize; ++nIndex ) 1274 { 1275 sal_Int32 nFirstInLevel = orLevels.back(); 1276 orLevels.pop_back(); 1277 groupColumnsOrRows( nFirstInLevel, nColRow - 1, bCollapsed, bRows ); 1278 bCollapsed = false; // collapse only once 1279 } 1280 } 1281 } 1282 1283 void WorksheetGlobals::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows ) 1284 { 1285 try 1286 { 1287 Reference< XSheetOutline > xOutline( mxSheet, UNO_QUERY_THROW ); 1288 if( bRows ) 1289 { 1290 CellRangeAddress aRange( getSheetIndex(), 0, nFirstColRow, 0, nLastColRow ); 1291 xOutline->group( aRange, TableOrientation_ROWS ); 1292 if( bCollapse ) 1293 xOutline->hideDetail( aRange ); 1294 } 1295 else 1296 { 1297 CellRangeAddress aRange( getSheetIndex(), nFirstColRow, 0, nLastColRow, 0 ); 1298 xOutline->group( aRange, TableOrientation_COLUMNS ); 1299 if( bCollapse ) 1300 xOutline->hideDetail( aRange ); 1301 } 1302 } 1303 catch( Exception& ) 1304 { 1305 } 1306 } 1307 1308 void WorksheetGlobals::finalizeDrawings() 1309 { 1310 // calculate the current drawing page size (after rows/columns are imported) 1311 PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) ); 1312 aRangeProp.getProperty( maDrawPageSize, PROP_Size ); 1313 1314 switch( getFilterType() ) 1315 { 1316 case FILTER_OOXML: 1317 // import DML and VML 1318 if( maDrawingPath.getLength() > 0 ) 1319 importOoxFragment( new DrawingFragment( *this, maDrawingPath ) ); 1320 if( maVmlDrawingPath.getLength() > 0 ) 1321 importOoxFragment( new VmlDrawingFragment( *this, maVmlDrawingPath ) ); 1322 break; 1323 1324 case FILTER_BIFF: 1325 // convert BIFF3-BIFF5 drawing objects, or import and convert DFF stream 1326 getBiffDrawing().finalizeImport(); 1327 break; 1328 1329 case FILTER_UNKNOWN: 1330 break; 1331 } 1332 1333 // comments (after callout shapes have been imported from VML/DFF) 1334 maComments.finalizeImport(); 1335 1336 /* Extend used area of the sheet by cells covered with drawing objects. 1337 Needed if the imported document is inserted as "OLE object from file" 1338 and thus does not provide an OLE size property by itself. */ 1339 if( (maShapeBoundingBox.Width > 0) || (maShapeBoundingBox.Height > 0) ) 1340 extendUsedArea( getCellRangeFromRectangle( maShapeBoundingBox ) ); 1341 1342 // if no used area is set, default to A1 1343 if( maUsedArea.StartColumn > maUsedArea.EndColumn ) 1344 maUsedArea.StartColumn = maUsedArea.EndColumn = 0; 1345 if( maUsedArea.StartRow > maUsedArea.EndRow ) 1346 maUsedArea.StartRow = maUsedArea.EndRow = 0; 1347 1348 /* Register the used area of this sheet in global view settings. The 1349 global view settings will set the visible area if this document is an 1350 embedded OLE object. */ 1351 getViewSettings().setSheetUsedArea( maUsedArea ); 1352 1353 /* #i103686# Set right-to-left sheet layout. Must be done after all 1354 drawing shapes to simplify calculation of shape coordinates. */ 1355 if( maSheetViewSett.isSheetRightToLeft() ) 1356 { 1357 PropertySet aPropSet( mxSheet ); 1358 aPropSet.setProperty( PROP_TableLayout, WritingMode2::RL_TB ); 1359 } 1360 } 1361 1362 // ============================================================================ 1363 // ============================================================================ 1364 1365 WorksheetHelper::WorksheetHelper( WorksheetGlobals& rSheetGlob ) : 1366 WorkbookHelper( rSheetGlob ), 1367 mrSheetGlob( rSheetGlob ) 1368 { 1369 } 1370 1371 /*static*/ WorksheetGlobalsRef WorksheetHelper::constructGlobals( const WorkbookHelper& rHelper, 1372 const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) 1373 { 1374 WorksheetGlobalsRef xSheetGlob( new WorksheetGlobals( rHelper, rxProgressBar, eSheetType, nSheet ) ); 1375 if( !xSheetGlob->isValidSheet() ) 1376 xSheetGlob.reset(); 1377 return xSheetGlob; 1378 } 1379 1380 WorksheetType WorksheetHelper::getSheetType() const 1381 { 1382 return mrSheetGlob.getSheetType(); 1383 } 1384 1385 sal_Int16 WorksheetHelper::getSheetIndex() const 1386 { 1387 return mrSheetGlob.getSheetIndex(); 1388 } 1389 1390 const Reference< XSpreadsheet >& WorksheetHelper::getSheet() const 1391 { 1392 return mrSheetGlob.getSheet(); 1393 } 1394 1395 Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const 1396 { 1397 return mrSheetGlob.getCell( rAddress ); 1398 } 1399 1400 Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const 1401 { 1402 return mrSheetGlob.getCellRange( rRange ); 1403 } 1404 1405 Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const 1406 { 1407 return mrSheetGlob.getCellRangeList( rRanges ); 1408 } 1409 1410 CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell ) 1411 { 1412 CellAddress aAddress; 1413 Reference< XCellAddressable > xAddressable( rxCell, UNO_QUERY ); 1414 OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getCellAddress - cell reference not addressable" ); 1415 if( xAddressable.is() ) 1416 aAddress = xAddressable->getCellAddress(); 1417 return aAddress; 1418 } 1419 1420 CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange >& rxRange ) 1421 { 1422 CellRangeAddress aRange; 1423 Reference< XCellRangeAddressable > xAddressable( rxRange, UNO_QUERY ); 1424 OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getRangeAddress - cell range reference not addressable" ); 1425 if( xAddressable.is() ) 1426 aRange = xAddressable->getRangeAddress(); 1427 return aRange; 1428 } 1429 1430 Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const 1431 { 1432 return mrSheetGlob.getColumn( nCol ); 1433 } 1434 1435 Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const 1436 { 1437 return mrSheetGlob.getRow( nRow ); 1438 } 1439 1440 Reference< XTableColumns > WorksheetHelper::getColumns( const ValueRange& rColRange ) const 1441 { 1442 return mrSheetGlob.getColumns( rColRange ); 1443 } 1444 1445 Reference< XTableRows > WorksheetHelper::getRows( const ValueRange& rRowRange ) const 1446 { 1447 return mrSheetGlob.getRows( rRowRange ); 1448 } 1449 1450 Reference< XDrawPage > WorksheetHelper::getDrawPage() const 1451 { 1452 return mrSheetGlob.getDrawPage(); 1453 } 1454 1455 Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const 1456 { 1457 return mrSheetGlob.getCellPosition( nCol, nRow ); 1458 } 1459 1460 Size WorksheetHelper::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const 1461 { 1462 return mrSheetGlob.getCellSize( nCol, nRow ); 1463 } 1464 1465 Size WorksheetHelper::getDrawPageSize() const 1466 { 1467 return mrSheetGlob.getDrawPageSize(); 1468 } 1469 1470 SheetDataBuffer& WorksheetHelper::getSheetData() const 1471 { 1472 return mrSheetGlob.getSheetData(); 1473 } 1474 1475 CondFormatBuffer& WorksheetHelper::getCondFormats() const 1476 { 1477 return mrSheetGlob.getCondFormats(); 1478 } 1479 1480 CommentsBuffer& WorksheetHelper::getComments() const 1481 { 1482 return mrSheetGlob.getComments(); 1483 } 1484 1485 AutoFilterBuffer& WorksheetHelper::getAutoFilters() const 1486 { 1487 return mrSheetGlob.getAutoFilters(); 1488 } 1489 1490 QueryTableBuffer& WorksheetHelper::getQueryTables() const 1491 { 1492 return mrSheetGlob.getQueryTables(); 1493 } 1494 1495 WorksheetSettings& WorksheetHelper::getWorksheetSettings() const 1496 { 1497 return mrSheetGlob.getWorksheetSettings(); 1498 } 1499 1500 PageSettings& WorksheetHelper::getPageSettings() const 1501 { 1502 return mrSheetGlob.getPageSettings(); 1503 } 1504 1505 SheetViewSettings& WorksheetHelper::getSheetViewSettings() const 1506 { 1507 return mrSheetGlob.getSheetViewSettings(); 1508 } 1509 1510 VmlDrawing& WorksheetHelper::getVmlDrawing() const 1511 { 1512 return mrSheetGlob.getVmlDrawing(); 1513 } 1514 1515 BiffSheetDrawing& WorksheetHelper::getBiffDrawing() const 1516 { 1517 return mrSheetGlob.getBiffDrawing(); 1518 } 1519 1520 void WorksheetHelper::setSheetType( WorksheetType eSheetType ) 1521 { 1522 mrSheetGlob.setSheetType( eSheetType ); 1523 } 1524 1525 void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) 1526 { 1527 mrSheetGlob.setPageBreak( rModel, bRowBreak ); 1528 } 1529 1530 void WorksheetHelper::setHyperlink( const HyperlinkModel& rModel ) 1531 { 1532 mrSheetGlob.setHyperlink( rModel ); 1533 } 1534 1535 void WorksheetHelper::setValidation( const ValidationModel& rModel ) 1536 { 1537 mrSheetGlob.setValidation( rModel ); 1538 } 1539 1540 void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges ) 1541 { 1542 const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress(); 1543 PropertySet aPropSet( getSheet() ); 1544 1545 if( !rColRanges.empty() ) 1546 { 1547 Reference< XLabelRanges > xLabelRanges( aPropSet.getAnyProperty( PROP_ColumnLabelRanges ), UNO_QUERY ); 1548 if( xLabelRanges.is() ) 1549 { 1550 for( ApiCellRangeList::const_iterator aIt = rColRanges.begin(), aEnd = rColRanges.end(); aIt != aEnd; ++aIt ) 1551 { 1552 CellRangeAddress aDataRange = *aIt; 1553 if( aDataRange.EndRow < rMaxPos.Row ) 1554 { 1555 aDataRange.StartRow = aDataRange.EndRow + 1; 1556 aDataRange.EndRow = rMaxPos.Row; 1557 } 1558 else if( aDataRange.StartRow > 0 ) 1559 { 1560 aDataRange.EndRow = aDataRange.StartRow - 1; 1561 aDataRange.StartRow = 0; 1562 } 1563 xLabelRanges->addNew( *aIt, aDataRange ); 1564 } 1565 } 1566 } 1567 1568 if( !rRowRanges.empty() ) 1569 { 1570 Reference< XLabelRanges > xLabelRanges( aPropSet.getAnyProperty( PROP_RowLabelRanges ), UNO_QUERY ); 1571 if( xLabelRanges.is() ) 1572 { 1573 for( ApiCellRangeList::const_iterator aIt = rRowRanges.begin(), aEnd = rRowRanges.end(); aIt != aEnd; ++aIt ) 1574 { 1575 CellRangeAddress aDataRange = *aIt; 1576 if( aDataRange.EndColumn < rMaxPos.Column ) 1577 { 1578 aDataRange.StartColumn = aDataRange.EndColumn + 1; 1579 aDataRange.EndColumn = rMaxPos.Column; 1580 } 1581 else if( aDataRange.StartColumn > 0 ) 1582 { 1583 aDataRange.EndColumn = aDataRange.StartColumn - 1; 1584 aDataRange.StartColumn = 0; 1585 } 1586 xLabelRanges->addNew( *aIt, aDataRange ); 1587 } 1588 } 1589 } 1590 } 1591 1592 void WorksheetHelper::setDrawingPath( const OUString& rDrawingPath ) 1593 { 1594 mrSheetGlob.setDrawingPath( rDrawingPath ); 1595 } 1596 1597 void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath ) 1598 { 1599 mrSheetGlob.setVmlDrawingPath( rVmlDrawingPath ); 1600 } 1601 1602 void WorksheetHelper::extendUsedArea( const CellAddress& rAddress ) 1603 { 1604 mrSheetGlob.extendUsedArea( rAddress ); 1605 } 1606 1607 void WorksheetHelper::extendUsedArea( const CellRangeAddress& rRange ) 1608 { 1609 mrSheetGlob.extendUsedArea( rRange ); 1610 } 1611 1612 void WorksheetHelper::extendShapeBoundingBox( const Rectangle& rShapeRect ) 1613 { 1614 mrSheetGlob.extendShapeBoundingBox( rShapeRect ); 1615 } 1616 1617 void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth ) 1618 { 1619 mrSheetGlob.setBaseColumnWidth( nWidth ); 1620 } 1621 1622 void WorksheetHelper::setDefaultColumnWidth( double fWidth ) 1623 { 1624 mrSheetGlob.setDefaultColumnWidth( fWidth ); 1625 } 1626 1627 void WorksheetHelper::setDefaultColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) 1628 { 1629 mrSheetGlob.convertColumnFormat( nFirstCol, nLastCol, nXfId ); 1630 } 1631 1632 void WorksheetHelper::setColumnModel( const ColumnModel& rModel ) 1633 { 1634 mrSheetGlob.setColumnModel( rModel ); 1635 } 1636 1637 void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) 1638 { 1639 mrSheetGlob.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom ); 1640 } 1641 1642 void WorksheetHelper::setRowModel( const RowModel& rModel ) 1643 { 1644 mrSheetGlob.setRowModel( rModel ); 1645 } 1646 1647 void WorksheetHelper::setManualRowHeight( sal_Int32 nRow ) 1648 { 1649 mrSheetGlob.setManualRowHeight( nRow ); 1650 } 1651 1652 void WorksheetHelper::putValue( const CellAddress& rAddress, double fValue ) const 1653 { 1654 Reference< XCell > xCell = getCell( rAddress ); 1655 OSL_ENSURE( xCell.is(), "WorksheetHelper::putValue - missing cell interface" ); 1656 if( xCell.is() ) xCell->setValue( fValue ); 1657 } 1658 1659 void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) const 1660 { 1661 Reference< XText > xText( getCell( rAddress ), UNO_QUERY ); 1662 OSL_ENSURE( xText.is(), "WorksheetHelper::putString - missing text interface" ); 1663 if( xText.is() ) xText->setString( rText ); 1664 } 1665 1666 void WorksheetHelper::putRichString( const CellAddress& rAddress, const RichString& rString, const Font* pFirstPortionFont ) const 1667 { 1668 Reference< XText > xText( getCell( rAddress ), UNO_QUERY ); 1669 OSL_ENSURE( xText.is(), "WorksheetHelper::putRichString - missing text interface" ); 1670 /* Passing false will always append the portions to the XText. This is 1671 essential for special rich formatting attributes at the leading text 1672 portion supported by edit cells only, e.g. font escapement. */ 1673 rString.convert( xText, false, pFirstPortionFont ); 1674 } 1675 1676 void WorksheetHelper::putFormulaTokens( const CellAddress& rAddress, const ApiTokenSequence& rTokens ) const 1677 { 1678 Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY ); 1679 OSL_ENSURE( xTokens.is(), "WorksheetHelper::putFormulaTokens - missing token interface" ); 1680 if( xTokens.is() ) xTokens->setTokens( rTokens ); 1681 } 1682 1683 void WorksheetHelper::initializeWorksheetImport() 1684 { 1685 mrSheetGlob.initializeWorksheetImport(); 1686 } 1687 1688 void WorksheetHelper::finalizeWorksheetImport() 1689 { 1690 mrSheetGlob.finalizeWorksheetImport(); 1691 } 1692 1693 // ============================================================================ 1694 // ============================================================================ 1695 1696 } // namespace xls 1697 } // namespace oox 1698