Update ooo320-m1
[ooovba.git] / oox / source / xls / worksheethelper.cxx
blobab2d5c1b19467333889c9b93d6eb24b9dc62eae5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: worksheethelper.cxx,v $
10 * $Revision: 1.5.20.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/worksheethelper.hxx"
32 #include <algorithm>
33 #include <utility>
34 #include <list>
35 #include <rtl/ustrbuf.hxx>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/awt/Point.hpp>
38 #include <com/sun/star/awt/Size.hpp>
39 #include <com/sun/star/util/NumberFormat.hpp>
40 #include <com/sun/star/util/XMergeable.hpp>
41 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
42 #include <com/sun/star/util/XNumberFormatTypes.hpp>
43 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
44 #include <com/sun/star/table/XColumnRowRange.hpp>
45 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
46 #include <com/sun/star/sheet/ValidationType.hpp>
47 #include <com/sun/star/sheet/ValidationAlertStyle.hpp>
48 #include <com/sun/star/sheet/XSpreadsheet.hpp>
49 #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp>
50 #include <com/sun/star/sheet/XSheetCondition.hpp>
51 #include <com/sun/star/sheet/XCellAddressable.hpp>
52 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
53 #include <com/sun/star/sheet/XFormulaTokens.hpp>
54 #include <com/sun/star/sheet/XMultiFormulaTokens.hpp>
55 #include <com/sun/star/sheet/XSheetOutline.hpp>
56 #include <com/sun/star/sheet/XMultipleOperation.hpp>
57 #include <com/sun/star/sheet/XLabelRanges.hpp>
58 #include <com/sun/star/text/XText.hpp>
59 #include "properties.hxx"
60 #include "tokens.hxx"
61 #include "oox/helper/containerhelper.hxx"
62 #include "oox/helper/propertyset.hxx"
63 #include "oox/core/filterbase.hxx"
64 #include "oox/xls/addressconverter.hxx"
65 #include "oox/xls/commentsbuffer.hxx"
66 #include "oox/xls/condformatbuffer.hxx"
67 #include "oox/xls/drawingfragment.hxx"
68 #include "oox/xls/formulaparser.hxx"
69 #include "oox/xls/pagesettings.hxx"
70 #include "oox/xls/sharedformulabuffer.hxx"
71 #include "oox/xls/sharedstringsbuffer.hxx"
72 #include "oox/xls/stylesbuffer.hxx"
73 #include "oox/xls/unitconverter.hxx"
74 #include "oox/xls/viewsettings.hxx"
75 #include "oox/xls/workbooksettings.hxx"
76 #include "oox/xls/worksheetbuffer.hxx"
77 #include "oox/xls/worksheetsettings.hxx"
79 using ::rtl::OUString;
80 using ::rtl::OUStringBuffer;
81 using ::com::sun::star::uno::Reference;
82 using ::com::sun::star::uno::Exception;
83 using ::com::sun::star::uno::UNO_QUERY;
84 using ::com::sun::star::uno::UNO_QUERY_THROW;
85 using ::com::sun::star::uno::UNO_SET_THROW;
86 using ::com::sun::star::lang::Locale;
87 using ::com::sun::star::lang::XMultiServiceFactory;
88 using ::com::sun::star::beans::XPropertySet;
89 using ::com::sun::star::util::DateTime;
90 using ::com::sun::star::util::XMergeable;
91 using ::com::sun::star::util::XNumberFormatsSupplier;
92 using ::com::sun::star::util::XNumberFormatTypes;
93 using ::com::sun::star::awt::Point;
94 using ::com::sun::star::awt::Size;
95 using ::com::sun::star::drawing::XDrawPage;
96 using ::com::sun::star::drawing::XDrawPageSupplier;
97 using ::com::sun::star::table::BorderLine;
98 using ::com::sun::star::table::CellAddress;
99 using ::com::sun::star::table::CellRangeAddress;
100 using ::com::sun::star::table::XCell;
101 using ::com::sun::star::table::XCellRange;
102 using ::com::sun::star::table::XColumnRowRange;
103 using ::com::sun::star::table::XTableColumns;
104 using ::com::sun::star::table::XTableRows;
105 using ::com::sun::star::sheet::ConditionOperator;
106 using ::com::sun::star::sheet::ValidationType;
107 using ::com::sun::star::sheet::ValidationAlertStyle;
108 using ::com::sun::star::sheet::XCellAddressable;
109 using ::com::sun::star::sheet::XCellRangeAddressable;
110 using ::com::sun::star::sheet::XFormulaTokens;
111 using ::com::sun::star::sheet::XLabelRanges;
112 using ::com::sun::star::sheet::XMultiFormulaTokens;
113 using ::com::sun::star::sheet::XMultipleOperation;
114 using ::com::sun::star::sheet::XSheetCellRangeContainer;
115 using ::com::sun::star::sheet::XSheetCellRanges;
116 using ::com::sun::star::sheet::XSheetCondition;
117 using ::com::sun::star::sheet::XSheetOutline;
118 using ::com::sun::star::sheet::XSpreadsheet;
119 using ::com::sun::star::text::XText;
120 using ::com::sun::star::text::XTextContent;
121 using ::com::sun::star::text::XTextRange;
123 namespace oox {
124 namespace xls {
126 // ============================================================================
128 namespace {
130 void lclUpdateProgressBar( ISegmentProgressBarRef xProgressBar, const CellRangeAddress& rDimension, sal_Int32 nRow )
132 if( xProgressBar.get() && (rDimension.StartRow <= nRow) && (nRow <= rDimension.EndRow) )
134 double fPosition = static_cast< double >( nRow - rDimension.StartRow + 1 ) / (rDimension.EndRow - rDimension.StartRow + 1);
135 if( xProgressBar->getPosition() < fPosition )
136 xProgressBar->setPosition( fPosition );
140 void lclUpdateProgressBar( ISegmentProgressBarRef xProgressBar, double fPosition )
142 if( xProgressBar.get() )
143 xProgressBar->setPosition( fPosition );
146 // ----------------------------------------------------------------------------
148 struct ValueRange
150 sal_Int32 mnFirst;
151 sal_Int32 mnLast;
153 inline explicit ValueRange( sal_Int32 nValue ) : mnFirst( nValue ), mnLast( nValue ) {}
154 inline explicit ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {}
157 typedef ::std::vector< ValueRange > ValueRangeVector;
159 // ----------------------------------------------------------------------------
161 struct ValueRangeComp
163 inline bool operator()( const ValueRange& rRange, sal_Int32 nValue ) const { return rRange.mnLast < nValue; }
166 typedef ::std::vector< ValueRange > ValueRangeVector;
168 // ----------------------------------------------------------------------------
170 class ValueRangeSet
172 public:
173 inline explicit ValueRangeSet() {}
175 void insert( sal_Int32 nValue );
176 void intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const;
178 private:
179 ValueRangeVector maData;
182 void ValueRangeSet::insert( sal_Int32 nValue )
184 // find the first range that contains nValue or that follows nValue
185 ValueRangeVector::iterator aBeg = maData.begin();
186 ValueRangeVector::iterator aEnd = maData.end();
187 ValueRangeVector::iterator aNext = ::std::lower_bound( aBeg, aEnd, nValue, ValueRangeComp() );
189 // nothing to do if found range contains nValue
190 if( (aNext == aEnd) || (nValue < aNext->mnFirst) )
192 ValueRangeVector::iterator aPrev = (aNext == aBeg) ? aEnd : (aNext - 1);
193 bool bJoinPrev = (aPrev != aEnd) && (aPrev->mnLast + 1 == nValue);
194 bool bJoinNext = (aNext != aEnd) && (aNext->mnFirst - 1 == nValue);
195 if( bJoinPrev && bJoinNext )
197 aPrev->mnLast = aNext->mnLast;
198 maData.erase( aNext );
200 else if( bJoinPrev )
201 ++aPrev->mnLast;
202 else if( bJoinNext )
203 --aNext->mnFirst;
204 else
205 maData.insert( aNext, ValueRange( nValue ) );
209 void ValueRangeSet::intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const
211 orRanges.clear();
212 // find the range that contains nFirst or the first range that follows nFirst
213 ValueRangeVector::const_iterator aIt = ::std::lower_bound( maData.begin(), maData.end(), nFirst, ValueRangeComp() );
214 for( ValueRangeVector::const_iterator aEnd = maData.end(); (aIt != aEnd) && (aIt->mnFirst <= nLast); ++aIt )
215 orRanges.push_back( ValueRange( ::std::max( aIt->mnFirst, nFirst ), ::std::min( aIt->mnLast, nLast ) ) );
218 } // namespace
220 // ============================================================================
221 // ============================================================================
223 void CellModel::reset()
225 mxCell.clear();
226 maValueStr = maFormulaRef = OUString();
227 mnCellType = mnFormulaType = XML_TOKEN_INVALID;
228 mnSharedId = mnXfId = mnNumFmtId = -1;
229 mbHasValueStr = mbShowPhonetic = false;
232 // ----------------------------------------------------------------------------
234 DataTableModel::DataTableModel() :
235 mb2dTable( false ),
236 mbRowTable( false ),
237 mbRef1Deleted( false ),
238 mbRef2Deleted( false )
242 // ----------------------------------------------------------------------------
244 ColumnModel::ColumnModel() :
245 mnFirstCol( -1 ),
246 mnLastCol( -1 ),
247 mfWidth( 0.0 ),
248 mnXfId( -1 ),
249 mnLevel( 0 ),
250 mbShowPhonetic( false ),
251 mbHidden( false ),
252 mbCollapsed( false )
256 bool ColumnModel::tryExpand( const ColumnModel& rModel )
258 bool bExpandable =
259 (mnFirstCol <= rModel.mnFirstCol) &&
260 (rModel.mnFirstCol <= mnLastCol + 1) &&
261 (mfWidth == rModel.mfWidth) &&
262 // ignore mnXfId, cell formatting is always set directly
263 (mnLevel == rModel.mnLevel) &&
264 (mbHidden == rModel.mbHidden) &&
265 (mbCollapsed == rModel.mbCollapsed);
267 if( bExpandable )
268 mnLastCol = rModel.mnLastCol;
269 return bExpandable;
272 // ----------------------------------------------------------------------------
274 RowModel::RowModel() :
275 mnFirstRow( -1 ),
276 mnLastRow( -1 ),
277 mfHeight( 0.0 ),
278 mnXfId( -1 ),
279 mnLevel( 0 ),
280 mbCustomHeight( false ),
281 mbCustomFormat( false ),
282 mbShowPhonetic( false ),
283 mbHidden( false ),
284 mbCollapsed( false ),
285 mbThickTop( false ),
286 mbThickBottom( false )
290 bool RowModel::tryExpand( const RowModel& rModel )
292 bool bExpandable =
293 (mnFirstRow <= rModel.mnFirstRow) &&
294 (rModel.mnFirstRow <= mnLastRow + 1) &&
295 (mfHeight == rModel.mfHeight) &&
296 // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly
297 (mnLevel == rModel.mnLevel) &&
298 (mbCustomHeight == rModel.mbCustomHeight) &&
299 (mbHidden == rModel.mbHidden) &&
300 (mbCollapsed == rModel.mbCollapsed);
302 if( bExpandable )
303 mnLastRow = rModel.mnLastRow;
304 return bExpandable;
307 // ----------------------------------------------------------------------------
309 PageBreakModel::PageBreakModel() :
310 mnColRow( 0 ),
311 mbManual( false )
315 // ----------------------------------------------------------------------------
317 HyperlinkModel::HyperlinkModel()
321 // ----------------------------------------------------------------------------
323 ValidationModel::ValidationModel() :
324 mnType( XML_none ),
325 mnOperator( XML_between ),
326 mnErrorStyle( XML_stop ),
327 mbShowInputMsg( false ),
328 mbShowErrorMsg( false ),
329 mbNoDropDown( false ),
330 mbAllowBlank( false )
334 void ValidationModel::setBinType( sal_uInt8 nType )
336 static const sal_Int32 spnTypeIds[] = {
337 XML_none, XML_whole, XML_decimal, XML_list, XML_date, XML_time, XML_textLength, XML_custom };
338 mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_none );
341 void ValidationModel::setBinOperator( sal_uInt8 nOperator )
343 static const sal_Int32 spnOperators[] = {
344 XML_between, XML_notBetween, XML_equal, XML_notEqual,
345 XML_greaterThan, XML_lessThan, XML_greaterThanOrEqual, XML_lessThanOrEqual };
346 mnOperator = STATIC_ARRAY_SELECT( spnOperators, nOperator, XML_TOKEN_INVALID );
349 void ValidationModel::setBinErrorStyle( sal_uInt8 nErrorStyle )
351 static const sal_Int32 spnErrorStyles[] = { XML_stop, XML_warning, XML_information };
352 mnErrorStyle = STATIC_ARRAY_SELECT( spnErrorStyles, nErrorStyle, XML_stop );
355 // ============================================================================
356 // ============================================================================
358 class WorksheetData : public WorkbookHelper
360 public:
361 explicit WorksheetData(
362 const WorkbookHelper& rHelper,
363 ISegmentProgressBarRef xProgressBar,
364 WorksheetType eSheetType,
365 sal_Int16 nSheet );
367 /** Returns true, if this helper refers to an existing Calc sheet. */
368 inline bool isValidSheet() const { return mxSheet.is(); }
370 /** Returns a cell formula simulating the passed boolean value. */
371 const OUString& getBooleanFormula( bool bValue ) const;
373 /** Returns the type of this sheet. */
374 inline WorksheetType getSheetType() const { return meSheetType; }
375 /** Returns the index of the current sheet. */
376 inline sal_Int16 getSheetIndex() const { return mnSheet; }
377 /** Returns the XSpreadsheet interface of the current sheet. */
378 inline const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >&
379 getSheet() const { return mxSheet; }
381 /** Returns the XCell interface for the passed cell address. */
382 Reference< XCell > getCell( const CellAddress& rAddress ) const;
383 /** Returns the XCellRange interface for the passed cell range address. */
384 Reference< XCellRange > getCellRange( const CellRangeAddress& rRange ) const;
385 /** Returns the XSheetCellRanges interface for the passed cell range addresses. */
386 Reference< XSheetCellRanges > getCellRangeList( const ApiCellRangeList& rRanges ) const;
388 /** Returns the XCellRange interface for a column. */
389 Reference< XCellRange > getColumn( sal_Int32 nCol ) const;
390 /** Returns the XCellRange interface for a row. */
391 Reference< XCellRange > getRow( sal_Int32 nRow ) const;
393 /** Returns the XTableColumns interface for a range of columns. */
394 Reference< XTableColumns > getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const;
395 /** Returns the XTableRows interface for a range of rows. */
396 Reference< XTableRows > getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const;
398 /** Returns the XDrawPage interface of the draw page of the current sheet. */
399 Reference< XDrawPage > getDrawPage() const;
401 /** Returns the absolute cell position in 1/100 mm. */
402 Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const;
403 /** Returns the cell size in 1/100 mm. */
404 Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const;
405 /** Returns the size of the entire drawing page in 1/100 mm. */
406 Size getDrawPageSize() const;
408 /** Returns the worksheet settings object. */
409 inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; }
410 /** Returns the buffer containing all shared formulas in this sheet. */
411 inline SharedFormulaBuffer& getSharedFormulas() { return maSharedFmlas; }
412 /** Returns the conditional formattings in this sheet. */
413 inline CondFormatBuffer& getCondFormats() { return maCondFormats; }
414 /** Returns the buffer for all cell comments in this sheet. */
415 inline CommentsBuffer& getComments() { return maComments; }
416 /** Returns the page/print settings for this sheet. */
417 inline PageSettings& getPageSettings() { return maPageSett; }
418 /** Returns the view settings for this sheet. */
419 inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; }
420 /** Returns the VML drawing page for this sheet (OOX only!). */
421 inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; }
423 /** Changes the current sheet type. */
424 inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; }
425 /** Sets the dimension (used area) of the sheet. */
426 void setDimension( const CellRangeAddress& rRange );
427 /** Stores the cell format at the passed address. */
428 void setCellFormat( const CellModel& rModel );
429 /** Merges the cells in the passed cell range. */
430 void setMergedRange( const CellRangeAddress& rRange );
431 /** Sets a column or row page break described in the passed struct. */
432 void setPageBreak( const PageBreakModel& rModel, bool bRowBreak );
433 /** Inserts the hyperlink URL into the spreadsheet. */
434 void setHyperlink( const HyperlinkModel& rModel );
435 /** Inserts the data validation settings into the spreadsheet. */
436 void setValidation( const ValidationModel& rModel );
437 /** Sets the path to the DrawingML fragment of this sheet. */
438 void setDrawingPath( const OUString& rDrawingPath );
439 /** Sets the path to the legacy VML drawing fragment of this sheet. */
440 void setVmlDrawingPath( const OUString& rVmlDrawingPath );
442 /** Sets base width for all columns (without padding pixels). This value
443 is only used, if base width has not been set with setDefaultColumnWidth(). */
444 void setBaseColumnWidth( sal_Int32 nWidth );
445 /** Sets default width for all columns. This function overrides the base
446 width set with the setBaseColumnWidth() function. */
447 void setDefaultColumnWidth( double fWidth );
448 /** Sets column settings for a specific column range.
449 @descr Column default formatting is converted directly, other settings
450 are cached and converted in the finalizeImport() call. */
451 void setColumnModel( const ColumnModel& rModel );
453 /** Sets default height and hidden state for all unused rows in the sheet. */
454 void setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom );
455 /** Sets row settings for a specific row.
456 @descr Row default formatting is converted directly, other settings
457 are cached and converted in the finalizeImport() call. */
458 void setRowModel( const RowModel& rModel );
460 /** Converts column default cell formatting. */
461 void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const;
462 /** Converts row default cell formatting. */
463 void convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const;
465 /** Initial conversion before importing the worksheet. */
466 void initializeWorksheetImport();
467 /** Final conversion after importing the worksheet. */
468 void finalizeWorksheetImport();
470 private:
471 typedef ::std::vector< sal_Int32 > OutlineLevelVec;
472 typedef ::std::map< sal_Int32, ColumnModel > ColumnModelMap;
473 typedef ::std::map< sal_Int32, RowModel > RowModelMap;
474 typedef ::std::list< HyperlinkModel > HyperlinkModelList;
475 typedef ::std::list< ValidationModel > ValidationModelList;
477 struct XfIdRowRange
479 sal_Int32 mnFirstRow; /// Index of first row.
480 sal_Int32 mnLastRow; /// Index of last row.
481 sal_Int32 mnXfId; /// XF identifier for the row range.
483 explicit XfIdRowRange();
484 bool intersects( const CellRangeAddress& rRange ) const;
485 void set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId );
486 bool tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId );
489 struct XfIdRange
491 CellRangeAddress maRange; /// The formatted cell range.
492 sal_Int32 mnXfId; /// XF identifier for the range.
493 sal_Int32 mnNumFmtId; /// Number format id overriding the XF.
495 void set( const CellModel& rModel );
496 bool tryExpand( const CellModel& rModel );
497 bool tryMerge( const XfIdRange& rXfIdRange );
500 struct MergedRange
502 CellRangeAddress maRange; /// The formatted cell range.
503 sal_Int32 mnHorAlign; /// Horizontal alignment in the range.
505 explicit MergedRange( const CellRangeAddress& rRange );
506 explicit MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign );
507 bool tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign );
510 typedef ::std::pair< sal_Int32, sal_Int32 > RowColKey;
511 typedef ::std::map< RowColKey, XfIdRange > XfIdRangeMap;
512 typedef ::std::list< MergedRange > MergedRangeList;
514 /** Writes all cell formatting attributes to the passed row range. */
515 void writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const;
516 /** Writes all cell formatting attributes to the passed cell range. */
517 void writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const;
518 /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */
519 void mergeXfIdRanges();
520 /** Finalizes the remaining ranges in maXfIdRanges. */
521 void finalizeXfIdRanges();
523 /** Inserts all imported hyperlinks into their cell ranges. */
524 void finalizeHyperlinkRanges() const;
525 /** Generates the final URL for the passed hyperlink. */
526 OUString getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const;
527 /** Inserts a hyperlinks into the specified cell. */
528 void insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const;
530 /** Inserts all imported data validations into their cell ranges. */
531 void finalizeValidationRanges() const;
533 /** Merges all cached merged ranges and updates right/bottom cell borders. */
534 void finalizeMergedRanges();
535 /** Merges the passed merged range and updates right/bottom cell borders. */
536 void finalizeMergedRange( const CellRangeAddress& rRange );
538 /** Imports the drawing layer of the sheet (DrawingML part). */
539 void finalizeDrawing();
540 /** Imports the drawing layer of the sheet (VML part). */
541 void finalizeVmlDrawing();
543 /** Converts column properties for all columns in the sheet. */
544 void convertColumns();
545 /** Converts column properties. */
546 void convertColumns( OutlineLevelVec& orColLevels, sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel );
548 /** Converts row properties for all rows in the sheet. */
549 void convertRows();
550 /** Converts row properties. */
551 void convertRows( OutlineLevelVec& orRowLevels, sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight = -1.0 );
553 /** Converts outline grouping for the passed column or row. */
554 void convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows );
555 /** Groups columns or rows for the given range. */
556 void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows );
558 private:
559 typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr;
561 const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells.
562 const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells.
563 const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object.
564 const OUString maUrlTextField; /// Service name for a URL text field.
565 const CellAddress& mrMaxApiPos; /// Reference to maximum Calc cell address from address converter.
566 CellRangeAddress maDimension; /// Dimension (used) area of the sheet.
567 ColumnModel maDefColModel; /// Default column formatting.
568 ColumnModelMap maColModels; /// Columns sorted by first column index.
569 RowModel maDefRowModel; /// Default row formatting.
570 RowModelMap maRowModels; /// Rows sorted by row index.
571 HyperlinkModelList maHyperlinks; /// Cell ranges containing hyperlinks.
572 ValidationModelList maValidations; /// Cell ranges containing data validation settings.
573 XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows.
574 XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges.
575 MergedRangeList maMergedRanges; /// Merged cell ranges.
576 MergedRangeList maCenterFillRanges; /// Merged cell ranges from 'center across' or 'fill' alignment.
577 ValueRangeSet maManualRowHeights; /// Rows that need manual height independent from own settings.
578 WorksheetSettings maSheetSett; /// Global settings for this sheet.
579 SharedFormulaBuffer maSharedFmlas; /// Buffer for shared formulas in this sheet.
580 CondFormatBuffer maCondFormats; /// Buffer for conditional formattings.
581 CommentsBuffer maComments; /// Buffer for all cell comments in this sheet.
582 PageSettings maPageSett; /// Page/print settings for this sheet.
583 SheetViewSettings maSheetViewSett; /// View settings for this sheet.
584 VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes.
585 OUString maDrawingPath; /// Path to DrawingML fragment.
586 OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment.
587 ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar.
588 ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing.
589 ISegmentProgressBarRef mxFinalProgress; /// Progress bar for finalization.
590 WorksheetType meSheetType; /// Type of this sheet.
591 Reference< XSpreadsheet > mxSheet; /// Reference to the current sheet.
592 sal_Int16 mnSheet; /// Index of the current sheet.
593 bool mbHasDefWidth; /// True = default column width is set from defaultColWidth attribute.
596 // ----------------------------------------------------------------------------
598 WorksheetData::WorksheetData( const WorkbookHelper& rHelper, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
599 WorkbookHelper( rHelper ),
600 maTrueFormula( CREATE_OUSTRING( "=TRUE()" ) ),
601 maFalseFormula( CREATE_OUSTRING( "=FALSE()" ) ),
602 maSheetCellRanges( CREATE_OUSTRING( "com.sun.star.sheet.SheetCellRanges" ) ),
603 maUrlTextField( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ),
604 mrMaxApiPos( rHelper.getAddressConverter().getMaxApiAddress() ),
605 maSheetSett( *this ),
606 maSharedFmlas( *this ),
607 maCondFormats( *this ),
608 maComments( *this ),
609 maPageSett( *this ),
610 maSheetViewSett( *this ),
611 mxProgressBar( xProgressBar ),
612 meSheetType( eSheetType ),
613 mnSheet( nSheet ),
614 mbHasDefWidth( false )
616 mxSheet = getSheetFromDoc( nSheet );
617 if( !mxSheet.is() )
618 mnSheet = -1;
620 maDimension.Sheet = mnSheet;
622 // default column settings (width and hidden state may be updated later)
623 maDefColModel.mfWidth = 8.5;
624 maDefColModel.mnXfId = -1;
625 maDefColModel.mnLevel = 0;
626 maDefColModel.mbHidden = false;
627 maDefColModel.mbCollapsed = false;
629 // default row settings (height and hidden state may be updated later)
630 maDefRowModel.mfHeight = 0.0;
631 maDefRowModel.mnXfId = -1;
632 maDefRowModel.mnLevel = 0;
633 maDefRowModel.mbCustomHeight = false;
634 maDefRowModel.mbCustomFormat = false;
635 maDefRowModel.mbShowPhonetic = false;
636 maDefRowModel.mbHidden = false;
637 maDefRowModel.mbCollapsed = false;
639 // buffers
640 if( getFilterType() == FILTER_OOX )
641 mxVmlDrawing.reset( new VmlDrawing( *this ) );
643 // prepare progress bars
644 if( mxProgressBar.get() )
646 mxRowProgress = mxProgressBar->createSegment( 0.5 );
647 mxFinalProgress = mxProgressBar->createSegment( 0.5 );
651 const OUString& WorksheetData::getBooleanFormula( bool bValue ) const
653 return bValue ? maTrueFormula : maFalseFormula;
656 Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const
658 Reference< XCell > xCell;
659 if( mxSheet.is() ) try
661 xCell = mxSheet->getCellByPosition( rAddress.Column, rAddress.Row );
663 catch( Exception& )
666 return xCell;
669 Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRange ) const
671 Reference< XCellRange > xRange;
672 if( mxSheet.is() ) try
674 xRange = mxSheet->getCellRangeByPosition( rRange.StartColumn, rRange.StartRow, rRange.EndColumn, rRange.EndRow );
676 catch( Exception& )
679 return xRange;
682 Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRangeList& rRanges ) const
684 Reference< XSheetCellRanges > xRanges;
685 if( mxSheet.is() && !rRanges.empty() ) try
687 xRanges.set( getDocumentFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW );
688 Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW );
689 xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False );
691 catch( Exception& )
694 return xRanges;
697 Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const
699 Reference< XCellRange > xColumn;
702 Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW );
703 Reference< XTableColumns > xColumns( xColRowRange->getColumns(), UNO_SET_THROW );
704 xColumn.set( xColumns->getByIndex( nCol ), UNO_QUERY );
706 catch( Exception& )
709 return xColumn;
712 Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const
714 Reference< XCellRange > xRow;
717 Reference< XColumnRowRange > xColRowRange( mxSheet, UNO_QUERY_THROW );
718 Reference< XTableRows > xRows( xColRowRange->getRows(), UNO_SET_THROW );
719 xRow.set( xRows->getByIndex( nRow ), UNO_QUERY );
721 catch( Exception& )
724 return xRow;
727 Reference< XTableColumns > WorksheetData::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const
729 Reference< XTableColumns > xColumns;
730 nLastCol = ::std::min( nLastCol, mrMaxApiPos.Column );
731 if( (0 <= nFirstCol) && (nFirstCol <= nLastCol) )
733 Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( mnSheet, nFirstCol, 0, nLastCol, 0 ) ), UNO_QUERY );
734 if( xRange.is() )
735 xColumns = xRange->getColumns();
737 return xColumns;
740 Reference< XTableRows > WorksheetData::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const
742 Reference< XTableRows > xRows;
743 nLastRow = ::std::min( nLastRow, mrMaxApiPos.Row );
744 if( (0 <= nFirstRow) && (nFirstRow <= nLastRow) )
746 Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( mnSheet, 0, nFirstRow, 0, nLastRow ) ), UNO_QUERY );
747 if( xRange.is() )
748 xRows = xRange->getRows();
750 return xRows;
753 Reference< XDrawPage > WorksheetData::getDrawPage() const
755 Reference< XDrawPage > xDrawPage;
758 Reference< XDrawPageSupplier > xDrawPageSupp( mxSheet, UNO_QUERY_THROW );
759 xDrawPage = xDrawPageSupp->getDrawPage();
761 catch( Exception& )
764 return xDrawPage;
767 Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
769 Point aPoint;
770 PropertySet aCellProp( getCell( CellAddress( mnSheet, nCol, nRow ) ) );
771 aCellProp.getProperty( aPoint, PROP_Position );
772 return aPoint;
775 Size WorksheetData::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
777 Size aSize;
778 PropertySet aCellProp( getCell( CellAddress( mnSheet, nCol, nRow ) ) );
779 aCellProp.getProperty( aSize, PROP_Size );
780 return aSize;
783 Size WorksheetData::getDrawPageSize() const
785 Size aSize;
786 PropertySet aRangeProp( getCellRange( CellRangeAddress( mnSheet, 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) );
787 aRangeProp.getProperty( aSize, PROP_Size );
788 return aSize;
791 void WorksheetData::setDimension( const CellRangeAddress& rRange )
793 maDimension = rRange;
796 void WorksheetData::setCellFormat( const CellModel& rModel )
798 OOX_LOADSAVE_TIMER( SETCELLFORMAT );
799 if( rModel.mxCell.is() && ((rModel.mnXfId >= 0) || (rModel.mnNumFmtId >= 0)) )
801 // try to merge existing ranges and to write some formatting properties
802 if( !maXfIdRanges.empty() )
804 // get row index of last inserted cell
805 sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
806 // row changed - try to merge ranges of last row with existing ranges
807 if( rModel.maAddress.Row != nLastRow )
809 mergeXfIdRanges();
810 // write format properties of all ranges above last row and remove them
811 XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end();
812 while( aIt != aEnd )
814 // check that range cannot be merged with current row, and that range is not in cached row range
815 if( (aIt->second.maRange.EndRow < nLastRow) && !maXfIdRowRange.intersects( aIt->second.maRange ) )
817 writeXfIdRangeProperties( aIt->second );
818 maXfIdRanges.erase( aIt++ );
820 else
821 ++aIt;
826 // try to expand last existing range, or create new range entry
827 if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel ) )
828 maXfIdRanges[ RowColKey( rModel.maAddress.Row, rModel.maAddress.Column ) ].set( rModel );
830 // update merged ranges for 'center across selection' and 'fill'
831 if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() )
833 sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign;
834 if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) )
836 /* start new merged range, if cell is not empty (#108781#),
837 or try to expand last range with empty cell */
838 if( rModel.mnCellType != XML_TOKEN_INVALID )
839 maCenterFillRanges.push_back( MergedRange( rModel.maAddress, nHorAlign ) );
840 else if( !maCenterFillRanges.empty() )
841 maCenterFillRanges.rbegin()->tryExpand( rModel.maAddress, nHorAlign );
847 void WorksheetData::setMergedRange( const CellRangeAddress& rRange )
849 maMergedRanges.push_back( MergedRange( rRange ) );
852 void WorksheetData::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
854 if( rModel.mbManual && (rModel.mnColRow > 0) )
856 PropertySet aPropSet( bRowBreak ? getRow( rModel.mnColRow ) : getColumn( rModel.mnColRow ) );
857 aPropSet.setProperty( PROP_IsStartOfNewPage, true );
861 void WorksheetData::setHyperlink( const HyperlinkModel& rModel )
863 maHyperlinks.push_back( rModel );
866 void WorksheetData::setValidation( const ValidationModel& rModel )
868 maValidations.push_back( rModel );
871 void WorksheetData::setDrawingPath( const OUString& rDrawingPath )
873 maDrawingPath = rDrawingPath;
876 void WorksheetData::setVmlDrawingPath( const OUString& rVmlDrawingPath )
878 maVmlDrawingPath = rVmlDrawingPath;
881 void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth )
883 // do not modify width, if setDefaultColumnWidth() has been used
884 if( !mbHasDefWidth && (nWidth > 0) )
886 // #i3006# add 5 pixels padding to the width
887 const UnitConverter& rUnitConv = getUnitConverter();
888 maDefColModel.mfWidth = rUnitConv.scaleFromMm100(
889 rUnitConv.scaleToMm100( nWidth, UNIT_DIGIT ) + rUnitConv.scaleToMm100( 5, UNIT_SCREENX ), UNIT_DIGIT );
893 void WorksheetData::setDefaultColumnWidth( double fWidth )
895 // overrides a width set with setBaseColumnWidth()
896 if( fWidth > 0.0 )
898 maDefColModel.mfWidth = fWidth;
899 mbHasDefWidth = true;
903 void WorksheetData::setColumnModel( const ColumnModel& rModel )
905 // convert 1-based OOX column indexes to 0-based API column indexes
906 sal_Int32 nFirstCol = rModel.mnFirstCol - 1;
907 sal_Int32 nLastCol = rModel.mnLastCol - 1;
908 if( (0 <= nFirstCol) && (nFirstCol <= mrMaxApiPos.Column) )
910 // set column formatting directly, nLastCol is checked inside the function
911 convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId );
912 // expand last entry or add new entry
913 if( maColModels.empty() || !maColModels.rbegin()->second.tryExpand( rModel ) )
914 maColModels[ nFirstCol ] = rModel;
918 void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
920 maDefRowModel.mfHeight = fHeight;
921 maDefRowModel.mbCustomHeight = bCustomHeight;
922 maDefRowModel.mbHidden = bHidden;
923 maDefRowModel.mbThickTop = bThickTop;
924 maDefRowModel.mbThickBottom = bThickBottom;
927 void WorksheetData::setRowModel( const RowModel& rModel )
929 // convert 1-based OOX row indexes to 0-based API row indexes
930 sal_Int32 nFirstRow = rModel.mnFirstRow - 1;
931 sal_Int32 nLastRow = rModel.mnLastRow - 1;
932 if( (0 <= nFirstRow) && (nFirstRow <= mrMaxApiPos.Row) )
934 // set row formatting
935 if( rModel.mbCustomFormat )
937 // try to expand cached row range, if formatting is equal
938 if( (maXfIdRowRange.mnLastRow < 0) || !maXfIdRowRange.tryExpand( nFirstRow, nLastRow, rModel.mnXfId ) )
940 writeXfIdRowRangeProperties( maXfIdRowRange );
941 maXfIdRowRange.set( nFirstRow, nLastRow, rModel.mnXfId );
944 else if( maXfIdRowRange.mnLastRow >= 0 )
946 // finish last cached row range
947 writeXfIdRowRangeProperties( maXfIdRowRange );
948 maXfIdRowRange.set( -1, -1, -1 );
951 // expand last entry or add new entry
952 if( maRowModels.empty() || !maRowModels.rbegin()->second.tryExpand( rModel ) )
953 maRowModels[ nFirstRow ] = rModel;
955 lclUpdateProgressBar( mxRowProgress, maDimension, nLastRow );
958 void WorksheetData::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const
960 OOX_LOADSAVE_TIMER( CONVERTCOLUMNFORMAT );
961 CellRangeAddress aRange( mnSheet, nFirstCol, 0, nLastCol, mrMaxApiPos.Row );
962 if( getAddressConverter().validateCellRange( aRange, true, false ) )
964 PropertySet aPropSet( getCellRange( aRange ) );
965 getStyles().writeCellXfToPropertySet( aPropSet, nXfId );
969 void WorksheetData::convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const
971 OOX_LOADSAVE_TIMER( CONVERTROWFORMAT );
972 CellRangeAddress aRange( mnSheet, 0, nFirstRow, mrMaxApiPos.Column, nLastRow );
973 if( getAddressConverter().validateCellRange( aRange, true, false ) )
975 PropertySet aPropSet( getCellRange( aRange ) );
976 getStyles().writeCellXfToPropertySet( aPropSet, nXfId );
980 void WorksheetData::initializeWorksheetImport()
982 // set default cell style for unused cells
983 PropertySet aPropSet( mxSheet );
984 aPropSet.setProperty( PROP_CellStyle, getStyles().getDefaultStyleName() );
986 /* Remember current sheet index in global data, needed by some global
987 objects, e.g. the chart converter. */
988 setCurrentSheetIndex( mnSheet );
991 void WorksheetData::finalizeWorksheetImport()
993 OOX_LOADSAVE_TIMER( FINALIZESHEETDATA );
994 lclUpdateProgressBar( mxRowProgress, 1.0 );
995 finalizeXfIdRanges();
996 lclUpdateProgressBar( mxFinalProgress, 0.25 );
997 finalizeHyperlinkRanges();
998 finalizeValidationRanges();
999 finalizeMergedRanges();
1000 maCondFormats.finalizeImport();
1001 maPageSett.finalizeImport();
1002 maSheetViewSett.finalizeImport();
1003 lclUpdateProgressBar( mxFinalProgress, 0.5 );
1004 convertColumns();
1005 convertRows();
1006 lclUpdateProgressBar( mxFinalProgress, 0.75 );
1007 finalizeDrawing();
1008 finalizeVmlDrawing();
1009 maComments.finalizeImport(); // after VML drawing
1010 lclUpdateProgressBar( mxFinalProgress, 1.0 );
1012 // reset current sheet index in global data
1013 setCurrentSheetIndex( -1 );
1016 // private --------------------------------------------------------------------
1018 WorksheetData::XfIdRowRange::XfIdRowRange() :
1019 mnFirstRow( -1 ),
1020 mnLastRow( -1 ),
1021 mnXfId( -1 )
1025 bool WorksheetData::XfIdRowRange::intersects( const CellRangeAddress& rRange ) const
1027 return (rRange.StartRow <= mnLastRow) && (mnFirstRow <= rRange.EndRow);
1030 void WorksheetData::XfIdRowRange::set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId )
1032 mnFirstRow = nFirstRow;
1033 mnLastRow = nLastRow;
1034 mnXfId = nXfId;
1037 bool WorksheetData::XfIdRowRange::tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId )
1039 if( mnXfId == nXfId )
1041 if( mnLastRow + 1 == nFirstRow )
1043 mnLastRow = nLastRow;
1044 return true;
1046 if( mnFirstRow == nLastRow + 1 )
1048 mnFirstRow = nFirstRow;
1049 return true;
1052 return false;
1055 void WorksheetData::XfIdRange::set( const CellModel& rModel )
1057 maRange.Sheet = rModel.maAddress.Sheet;
1058 maRange.StartColumn = maRange.EndColumn = rModel.maAddress.Column;
1059 maRange.StartRow = maRange.EndRow = rModel.maAddress.Row;
1060 mnXfId = rModel.mnXfId;
1061 mnNumFmtId = rModel.mnNumFmtId;
1064 bool WorksheetData::XfIdRange::tryExpand( const CellModel& rModel )
1066 if( (mnXfId == rModel.mnXfId) && (mnNumFmtId == rModel.mnNumFmtId) &&
1067 (maRange.StartRow == rModel.maAddress.Row) &&
1068 (maRange.EndRow == rModel.maAddress.Row) &&
1069 (maRange.EndColumn + 1 == rModel.maAddress.Column) )
1071 ++maRange.EndColumn;
1072 return true;
1074 return false;
1077 bool WorksheetData::XfIdRange::tryMerge( const XfIdRange& rXfIdRange )
1079 if( (mnXfId == rXfIdRange.mnXfId) &&
1080 (mnNumFmtId == rXfIdRange.mnNumFmtId) &&
1081 (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) &&
1082 (maRange.StartColumn == rXfIdRange.maRange.StartColumn) &&
1083 (maRange.EndColumn == rXfIdRange.maRange.EndColumn) )
1085 maRange.EndRow = rXfIdRange.maRange.EndRow;
1086 return true;
1088 return false;
1092 WorksheetData::MergedRange::MergedRange( const CellRangeAddress& rRange ) :
1093 maRange( rRange ),
1094 mnHorAlign( XML_TOKEN_INVALID )
1098 WorksheetData::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) :
1099 maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ),
1100 mnHorAlign( nHorAlign )
1104 bool WorksheetData::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign )
1106 if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) &&
1107 (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) )
1109 ++maRange.EndColumn;
1110 return true;
1112 return false;
1115 void WorksheetData::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const
1117 if( (rXfIdRowRange.mnLastRow >= 0) && (rXfIdRowRange.mnXfId >= 0) )
1118 convertRowFormat( rXfIdRowRange.mnFirstRow, rXfIdRowRange.mnLastRow, rXfIdRowRange.mnXfId );
1121 void WorksheetData::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const
1123 OOX_LOADSAVE_TIMER( WRITECELLPROPERTIES );
1124 StylesBuffer& rStyles = getStyles();
1125 PropertyMap aPropMap;
1126 if( rXfIdRange.mnXfId >= 0 )
1127 rStyles.writeCellXfToPropertyMap( aPropMap, rXfIdRange.mnXfId );
1128 if( rXfIdRange.mnNumFmtId >= 0 )
1129 rStyles.writeNumFmtToPropertyMap( aPropMap, rXfIdRange.mnNumFmtId );
1130 PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) );
1131 aPropSet.setProperties( aPropMap );
1134 void WorksheetData::mergeXfIdRanges()
1136 if( !maXfIdRanges.empty() )
1138 OOX_LOADSAVE_TIMER( MERGECELLFORMAT );
1139 // get row index of last range
1140 sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow;
1141 // process all ranges located in the same row of the last range
1142 XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end();
1143 while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) )
1145 const XfIdRange& rMergeXfIdRange = aMergeIt->second;
1146 // try to find a range that can be merged with rMergeRange
1147 bool bFound = false;
1148 for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt )
1149 if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true )
1150 maXfIdRanges.erase( aMergeIt++ );
1155 void WorksheetData::finalizeXfIdRanges()
1157 // write default formatting of remaining row range
1158 writeXfIdRowRangeProperties( maXfIdRowRange );
1159 // try to merge remaining inserted ranges
1160 mergeXfIdRanges();
1161 // write all formatting
1162 for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt )
1163 writeXfIdRangeProperties( aIt->second );
1166 void WorksheetData::finalizeHyperlinkRanges() const
1168 for( HyperlinkModelList::const_iterator aIt = maHyperlinks.begin(), aEnd = maHyperlinks.end(); aIt != aEnd; ++aIt )
1170 OUString aUrl = getHyperlinkUrl( *aIt );
1171 // try to insert URL into each cell of the range
1172 if( aUrl.getLength() > 0 )
1173 for( CellAddress aAddress( mnSheet, aIt->maRange.StartColumn, aIt->maRange.StartRow ); aAddress.Row <= aIt->maRange.EndRow; ++aAddress.Row )
1174 for( aAddress.Column = aIt->maRange.StartColumn; aAddress.Column <= aIt->maRange.EndColumn; ++aAddress.Column )
1175 insertHyperlink( aAddress, aUrl );
1179 OUString WorksheetData::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const
1181 OUStringBuffer aUrlBuffer;
1182 if( rHyperlink.maTarget.getLength() > 0 )
1183 aUrlBuffer.append( getBaseFilter().getAbsoluteUrl( rHyperlink.maTarget ) );
1184 if( rHyperlink.maLocation.getLength() > 0 )
1185 aUrlBuffer.append( sal_Unicode( '#' ) ).append( rHyperlink.maLocation );
1186 OUString aUrl = aUrlBuffer.makeStringAndClear();
1188 // convert '#SheetName!A1' to '#SheetName.A1'
1189 if( (aUrl.getLength() > 0) && (aUrl[ 0 ] == '#') )
1191 sal_Int32 nSepPos = aUrl.lastIndexOf( '!' );
1192 if( nSepPos > 0 )
1194 // replace the exclamation mark with a period
1195 aUrl = aUrl.replaceAt( nSepPos, 1, OUString( sal_Unicode( '.' ) ) );
1196 // #i66592# convert sheet names that have been renamed on import
1197 OUString aSheetName = aUrl.copy( 1, nSepPos - 1 );
1198 OUString aCalcName = getWorksheets().getCalcSheetName( aSheetName );
1199 if( aCalcName.getLength() > 0 )
1200 aUrl = aUrl.replaceAt( 1, nSepPos - 1, aCalcName );
1204 return aUrl;
1207 void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const
1209 Reference< XCell > xCell = getCell( rAddress );
1210 if( xCell.is() ) switch( xCell->getType() )
1212 // #i54261# restrict creation of URL field to text cells
1213 case ::com::sun::star::table::CellContentType_TEXT:
1215 Reference< XText > xText( xCell, UNO_QUERY );
1216 if( xText.is() )
1218 // create a URL field object and set its properties
1219 Reference< XTextContent > xUrlField( getDocumentFactory()->createInstance( maUrlTextField ), UNO_QUERY );
1220 OSL_ENSURE( xUrlField.is(), "WorksheetData::insertHyperlink - cannot create text field" );
1221 if( xUrlField.is() )
1223 // properties of the URL field
1224 PropertySet aPropSet( xUrlField );
1225 aPropSet.setProperty( PROP_URL, rUrl );
1226 aPropSet.setProperty( PROP_Representation, xText->getString() );
1229 // insert the field into the cell
1230 xText->setString( OUString() );
1231 Reference< XTextRange > xRange( xText->createTextCursor(), UNO_QUERY_THROW );
1232 xText->insertTextContent( xRange, xUrlField, sal_False );
1234 catch( const Exception& )
1236 OSL_ENSURE( false, "WorksheetData::insertHyperlink - cannot insert text field" );
1241 break;
1243 // fix for #i31050# disabled, HYPERLINK is not able to return numeric value (#i91351#)
1244 #if 0
1245 // #i31050# replace number with HYPERLINK function
1246 case ::com::sun::star::table::CellContentType_VALUE:
1248 Reference< XFormulaTokens > xTokens( xCell, UNO_QUERY );
1249 OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula interface" );
1250 if( xTokens.is() )
1252 SimpleFormulaContext aContext( xTokens, false, false );
1253 getFormulaParser().convertNumberToHyperlink( aContext, rUrl, xCell->getValue() );
1256 break;
1257 #endif
1259 default:;
1263 void WorksheetData::finalizeValidationRanges() const
1265 for( ValidationModelList::const_iterator aIt = maValidations.begin(), aEnd = maValidations.end(); aIt != aEnd; ++aIt )
1267 PropertySet aPropSet( getCellRangeList( aIt->maRanges ) );
1269 Reference< XPropertySet > xValidation;
1270 if( aPropSet.getProperty( xValidation, PROP_Validation ) && xValidation.is() )
1272 PropertySet aValProps( xValidation );
1273 namespace csss = ::com::sun::star::sheet;
1275 // convert validation type to API enum
1276 ValidationType eType = csss::ValidationType_ANY;
1277 switch( aIt->mnType )
1279 case XML_custom: eType = csss::ValidationType_CUSTOM; break;
1280 case XML_date: eType = csss::ValidationType_DATE; break;
1281 case XML_decimal: eType = csss::ValidationType_DECIMAL; break;
1282 case XML_list: eType = csss::ValidationType_LIST; break;
1283 case XML_none: eType = csss::ValidationType_ANY; break;
1284 case XML_textLength: eType = csss::ValidationType_TEXT_LEN; break;
1285 case XML_time: eType = csss::ValidationType_TIME; break;
1286 case XML_whole: eType = csss::ValidationType_WHOLE; break;
1287 default: OSL_ENSURE( false, "WorksheetData::finalizeValidationRanges - unknown validation type" );
1289 aValProps.setProperty( PROP_Type, eType );
1291 // convert error alert style to API enum
1292 ValidationAlertStyle eAlertStyle = csss::ValidationAlertStyle_STOP;
1293 switch( aIt->mnErrorStyle )
1295 case XML_information: eAlertStyle = csss::ValidationAlertStyle_INFO; break;
1296 case XML_stop: eAlertStyle = csss::ValidationAlertStyle_STOP; break;
1297 case XML_warning: eAlertStyle = csss::ValidationAlertStyle_WARNING; break;
1298 default: OSL_ENSURE( false, "WorksheetData::finalizeValidationRanges - unknown error style" );
1300 aValProps.setProperty( PROP_ErrorAlertStyle, eAlertStyle );
1302 // convert dropdown style to API visibility constants
1303 sal_Int16 nVisibility = aIt->mbNoDropDown ? csss::TableValidationVisibility::INVISIBLE : csss::TableValidationVisibility::UNSORTED;
1304 aValProps.setProperty( PROP_ShowList, nVisibility );
1306 // messages
1307 aValProps.setProperty( PROP_ShowInputMessage, aIt->mbShowInputMsg );
1308 aValProps.setProperty( PROP_InputTitle, aIt->maInputTitle );
1309 aValProps.setProperty( PROP_InputMessage, aIt->maInputMessage );
1310 aValProps.setProperty( PROP_ShowErrorMessage, aIt->mbShowErrorMsg );
1311 aValProps.setProperty( PROP_ErrorTitle, aIt->maErrorTitle );
1312 aValProps.setProperty( PROP_ErrorMessage, aIt->maErrorMessage );
1314 // allow blank cells
1315 aValProps.setProperty( PROP_IgnoreBlankCells, aIt->mbAllowBlank );
1319 // condition operator
1320 Reference< XSheetCondition > xSheetCond( xValidation, UNO_QUERY_THROW );
1321 xSheetCond->setOperator( CondFormatBuffer::convertToApiOperator( aIt->mnOperator ) );
1323 // condition formulas
1324 Reference< XMultiFormulaTokens > xTokens( xValidation, UNO_QUERY_THROW );
1325 xTokens->setTokens( 0, aIt->maTokens1 );
1326 xTokens->setTokens( 1, aIt->maTokens2 );
1328 catch( Exception& )
1332 // write back validation settings to cell range(s)
1333 aPropSet.setProperty( PROP_Validation, xValidation );
1338 void WorksheetData::finalizeMergedRanges()
1340 MergedRangeList::const_iterator aIt, aEnd;
1341 for( aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
1342 finalizeMergedRange( aIt->maRange );
1343 for( aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
1344 finalizeMergedRange( aIt->maRange );
1347 void WorksheetData::finalizeMergedRange( const CellRangeAddress& rRange )
1349 bool bMultiCol = rRange.StartColumn < rRange.EndColumn;
1350 bool bMultiRow = rRange.StartRow < rRange.EndRow;
1352 if( bMultiCol || bMultiRow ) try
1354 // merge the cell range
1355 Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW );
1356 xMerge->merge( sal_True );
1358 // if merging this range worked (no overlapping merged ranges), update cell borders
1359 Reference< XCell > xTopLeft( getCell( CellAddress( mnSheet, rRange.StartColumn, rRange.StartRow ) ), UNO_SET_THROW );
1360 PropertySet aTopLeftProp( xTopLeft );
1362 // copy right border of top-right cell to right border of top-left cell
1363 if( bMultiCol )
1365 PropertySet aTopRightProp( getCell( CellAddress( mnSheet, rRange.EndColumn, rRange.StartRow ) ) );
1366 BorderLine aLine;
1367 if( aTopRightProp.getProperty( aLine, PROP_RightBorder ) )
1368 aTopLeftProp.setProperty( PROP_RightBorder, aLine );
1371 // copy bottom border of bottom-left cell to bottom border of top-left cell
1372 if( bMultiRow )
1374 PropertySet aBottomLeftProp( getCell( CellAddress( mnSheet, rRange.StartColumn, rRange.EndRow ) ) );
1375 BorderLine aLine;
1376 if( aBottomLeftProp.getProperty( aLine, PROP_BottomBorder ) )
1377 aTopLeftProp.setProperty( PROP_BottomBorder, aLine );
1380 // #i93609# merged range in a single row: test if manual row height is needed
1381 if( !bMultiRow )
1383 bool bTextWrap = aTopLeftProp.getBoolProperty( PROP_IsTextWrapped );
1384 if( !bTextWrap && (xTopLeft->getType() == ::com::sun::star::table::CellContentType_TEXT) )
1386 Reference< XText > xText( xTopLeft, UNO_QUERY );
1387 bTextWrap = xText.is() && (xText->getString().indexOf( '\x0A' ) >= 0);
1389 if( bTextWrap )
1390 maManualRowHeights.insert( rRange.StartRow );
1393 catch( Exception& )
1398 void WorksheetData::finalizeDrawing()
1400 OSL_ENSURE( (getFilterType() == FILTER_OOX) || (maDrawingPath.getLength() == 0),
1401 "WorksheetData::finalizeDrawing - unexpected DrawingML path" );
1402 if( (getFilterType() == FILTER_OOX) && (maDrawingPath.getLength() > 0) )
1404 OOX_LOADSAVE_TIMER( FINALIZEDRAWING );
1405 importOoxFragment( new OoxDrawingFragment( *this, maDrawingPath ) );
1409 void WorksheetData::finalizeVmlDrawing()
1411 OSL_ENSURE( (getFilterType() == FILTER_OOX) || (maVmlDrawingPath.getLength() == 0),
1412 "WorksheetData::finalizeVmlDrawing - unexpected VML path" );
1413 if( (getFilterType() == FILTER_OOX) && (maVmlDrawingPath.getLength() > 0) )
1414 importOoxFragment( new OoxVmlDrawingFragment( *this, maVmlDrawingPath ) );
1417 void WorksheetData::convertColumns()
1419 sal_Int32 nNextCol = 0;
1420 sal_Int32 nMaxCol = mrMaxApiPos.Column;
1421 // stores first grouped column index for each level
1422 OutlineLevelVec aColLevels;
1424 for( ColumnModelMap::const_iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt )
1426 // convert 1-based OOX column indexes to 0-based API column indexes
1427 sal_Int32 nFirstCol = ::std::max( aIt->second.mnFirstCol - 1, nNextCol );
1428 sal_Int32 nLastCol = ::std::min( aIt->second.mnLastCol - 1, nMaxCol );
1430 // process gap between two column models, use default column model
1431 if( nNextCol < nFirstCol )
1432 convertColumns( aColLevels, nNextCol, nFirstCol - 1, maDefColModel );
1433 // process the column model
1434 convertColumns( aColLevels, nFirstCol, nLastCol, aIt->second );
1436 // cache next column to be processed
1437 nNextCol = nLastCol + 1;
1440 // remaining default columns to end of sheet
1441 convertColumns( aColLevels, nNextCol, nMaxCol, maDefColModel );
1442 // close remaining column outlines spanning to end of sheet
1443 convertOutlines( aColLevels, nMaxCol + 1, 0, false, false );
1446 void WorksheetData::convertColumns( OutlineLevelVec& orColLevels,
1447 sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel )
1449 PropertySet aPropSet( getColumns( nFirstCol, nLastCol ) );
1451 // column width: convert 'number of characters' to column width in 1/100 mm
1452 sal_Int32 nWidth = getUnitConverter().scaleToMm100( rModel.mfWidth, UNIT_DIGIT );
1453 // macro sheets have double width
1454 if( meSheetType == SHEETTYPE_MACROSHEET )
1455 nWidth *= 2;
1456 if( nWidth > 0 )
1457 aPropSet.setProperty( PROP_Width, nWidth );
1459 // hidden columns: TODO: #108683# hide columns later?
1460 if( rModel.mbHidden )
1461 aPropSet.setProperty( PROP_IsVisible, false );
1463 // outline settings for this column range
1464 convertOutlines( orColLevels, nFirstCol, rModel.mnLevel, rModel.mbCollapsed, false );
1467 void WorksheetData::convertRows()
1469 sal_Int32 nNextRow = 0;
1470 sal_Int32 nMaxRow = mrMaxApiPos.Row;
1471 // stores first grouped row index for each level
1472 OutlineLevelVec aRowLevels;
1474 for( RowModelMap::const_iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt )
1476 // convert 1-based OOX row indexes to 0-based API row indexes
1477 sal_Int32 nFirstRow = ::std::max( aIt->second.mnFirstRow - 1, nNextRow );
1478 sal_Int32 nLastRow = ::std::min( aIt->second.mnLastRow - 1, nMaxRow );
1480 // process gap between two row models, use default row model
1481 if( nNextRow < nFirstRow )
1482 convertRows( aRowLevels, nNextRow, nFirstRow - 1, maDefRowModel );
1483 // process the row model
1484 convertRows( aRowLevels, nFirstRow, nLastRow, aIt->second, maDefRowModel.mfHeight );
1486 // cache next row to be processed
1487 nNextRow = nLastRow + 1;
1490 // remaining default rows to end of sheet
1491 convertRows( aRowLevels, nNextRow, nMaxRow, maDefRowModel );
1492 // close remaining row outlines spanning to end of sheet
1493 convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true );
1496 void WorksheetData::convertRows( OutlineLevelVec& orRowLevels,
1497 sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight )
1499 // row height: convert points to row height in 1/100 mm
1500 double fHeight = (rModel.mfHeight >= 0.0) ? rModel.mfHeight : fDefHeight;
1501 sal_Int32 nHeight = getUnitConverter().scaleToMm100( fHeight, UNIT_POINT );
1502 if( nHeight > 0 )
1504 ValueRangeVector aManualRows;
1505 if( rModel.mbCustomHeight )
1506 aManualRows.push_back( ValueRange( nFirstRow, nLastRow ) );
1507 else
1508 maManualRowHeights.intersect( aManualRows, nFirstRow, nLastRow );
1509 for( ValueRangeVector::const_iterator aIt = aManualRows.begin(), aEnd = aManualRows.end(); aIt != aEnd; ++aIt )
1511 PropertySet aPropSet( getRows( aIt->mnFirst, aIt->mnLast ) );
1512 aPropSet.setProperty( PROP_Height, nHeight );
1516 // hidden rows: TODO: #108683# hide rows later?
1517 if( rModel.mbHidden )
1519 PropertySet aPropSet( getRows( nFirstRow, nLastRow ) );
1520 aPropSet.setProperty( PROP_IsVisible, false );
1523 // outline settings for this row range
1524 convertOutlines( orRowLevels, nFirstRow, rModel.mnLevel, rModel.mbCollapsed, true );
1527 void WorksheetData::convertOutlines( OutlineLevelVec& orLevels,
1528 sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows )
1530 /* It is ensured from caller functions, that this function is called
1531 without any gaps between the processed column or row ranges. */
1533 OSL_ENSURE( nLevel >= 0, "WorksheetData::convertOutlines - negative outline level" );
1534 nLevel = ::std::max< sal_Int32 >( nLevel, 0 );
1536 sal_Int32 nSize = orLevels.size();
1537 if( nSize < nLevel )
1539 // Outline level increased. Push the begin column position.
1540 for( sal_Int32 nIndex = nSize; nIndex < nLevel; ++nIndex )
1541 orLevels.push_back( nColRow );
1543 else if( nLevel < nSize )
1545 // Outline level decreased. Pop them all out.
1546 for( sal_Int32 nIndex = nLevel; nIndex < nSize; ++nIndex )
1548 sal_Int32 nFirstInLevel = orLevels.back();
1549 orLevels.pop_back();
1550 groupColumnsOrRows( nFirstInLevel, nColRow - 1, bCollapsed, bRows );
1551 bCollapsed = false; // collapse only once
1556 void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows )
1560 Reference< XSheetOutline > xOutline( mxSheet, UNO_QUERY_THROW );
1561 if( bRows )
1563 CellRangeAddress aRange( mnSheet, 0, nFirstColRow, 0, nLastColRow );
1564 xOutline->group( aRange, ::com::sun::star::table::TableOrientation_ROWS );
1565 if( bCollapse )
1566 xOutline->hideDetail( aRange );
1568 else
1570 CellRangeAddress aRange( mnSheet, nFirstColRow, 0, nLastColRow, 0 );
1571 xOutline->group( aRange, ::com::sun::star::table::TableOrientation_COLUMNS );
1572 if( bCollapse )
1573 xOutline->hideDetail( aRange );
1576 catch( Exception& )
1581 // ============================================================================
1582 // ============================================================================
1584 WorksheetHelper::WorksheetHelper( WorksheetData& rSheetData ) :
1585 WorkbookHelper( rSheetData ),
1586 mrSheetData( rSheetData )
1590 WorksheetType WorksheetHelper::getSheetType() const
1592 return mrSheetData.getSheetType();
1595 sal_Int16 WorksheetHelper::getSheetIndex() const
1597 return mrSheetData.getSheetIndex();
1600 const Reference< XSpreadsheet >& WorksheetHelper::getSheet() const
1602 return mrSheetData.getSheet();
1605 Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const
1607 return mrSheetData.getCell( rAddress );
1610 Reference< XCell > WorksheetHelper::getCell( const OUString& rAddressStr, CellAddress* opAddress ) const
1612 CellAddress aAddress;
1613 if( getAddressConverter().convertToCellAddress( aAddress, rAddressStr, mrSheetData.getSheetIndex(), true ) )
1615 if( opAddress ) *opAddress = aAddress;
1616 return mrSheetData.getCell( aAddress );
1618 return Reference< XCell >();
1621 Reference< XCell > WorksheetHelper::getCell( const BinAddress& rBinAddress, CellAddress* opAddress ) const
1623 CellAddress aAddress;
1624 if( getAddressConverter().convertToCellAddress( aAddress, rBinAddress, mrSheetData.getSheetIndex(), true ) )
1626 if( opAddress ) *opAddress = aAddress;
1627 return mrSheetData.getCell( aAddress );
1629 return Reference< XCell >();
1632 Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const
1634 return mrSheetData.getCellRange( rRange );
1637 Reference< XCellRange > WorksheetHelper::getCellRange( const OUString& rRangeStr, CellRangeAddress* opRange ) const
1639 CellRangeAddress aRange;
1640 if( getAddressConverter().convertToCellRange( aRange, rRangeStr, mrSheetData.getSheetIndex(), true, true ) )
1642 if( opRange ) *opRange = aRange;
1643 return mrSheetData.getCellRange( aRange );
1645 return Reference< XCellRange >();
1648 Reference< XCellRange > WorksheetHelper::getCellRange( const BinRange& rBinRange, CellRangeAddress* opRange ) const
1650 CellRangeAddress aRange;
1651 if( getAddressConverter().convertToCellRange( aRange, rBinRange, mrSheetData.getSheetIndex(), true, true ) )
1653 if( opRange ) *opRange = aRange;
1654 return mrSheetData.getCellRange( aRange );
1656 return Reference< XCellRange >();
1659 Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const
1661 return mrSheetData.getCellRangeList( rRanges );
1664 Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList(
1665 const OUString& rRangesStr, ApiCellRangeList* opRanges ) const
1667 ApiCellRangeList aRanges;
1668 getAddressConverter().convertToCellRangeList( aRanges, rRangesStr, mrSheetData.getSheetIndex(), true );
1669 if( opRanges ) *opRanges = aRanges;
1670 return mrSheetData.getCellRangeList( aRanges );
1673 Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList(
1674 const BinRangeList& rBinRanges, ApiCellRangeList* opRanges ) const
1676 ApiCellRangeList aRanges;
1677 getAddressConverter().convertToCellRangeList( aRanges, rBinRanges, mrSheetData.getSheetIndex(), true );
1678 if( opRanges ) *opRanges = aRanges;
1679 return mrSheetData.getCellRangeList( aRanges );
1682 CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell )
1684 CellAddress aAddress;
1685 Reference< XCellAddressable > xAddressable( rxCell, UNO_QUERY );
1686 OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getCellAddress - cell reference not addressable" );
1687 if( xAddressable.is() )
1688 aAddress = xAddressable->getCellAddress();
1689 return aAddress;
1692 CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange >& rxRange )
1694 CellRangeAddress aRange;
1695 Reference< XCellRangeAddressable > xAddressable( rxRange, UNO_QUERY );
1696 OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getRangeAddress - cell range reference not addressable" );
1697 if( xAddressable.is() )
1698 aRange = xAddressable->getRangeAddress();
1699 return aRange;
1702 Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const
1704 return mrSheetData.getColumn( nCol );
1707 Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const
1709 return mrSheetData.getRow( nRow );
1712 Reference< XTableColumns > WorksheetHelper::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const
1714 return mrSheetData.getColumns( nFirstCol, nLastCol );
1717 Reference< XTableRows > WorksheetHelper::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const
1719 return mrSheetData.getRows( nFirstRow, nLastRow );
1722 Reference< XDrawPage > WorksheetHelper::getDrawPage() const
1724 return mrSheetData.getDrawPage();
1727 Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
1729 return mrSheetData.getCellPosition( nCol, nRow );
1732 Size WorksheetHelper::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
1734 return mrSheetData.getCellSize( nCol, nRow );
1737 Size WorksheetHelper::getDrawPageSize() const
1739 return mrSheetData.getDrawPageSize();
1742 WorksheetSettings& WorksheetHelper::getWorksheetSettings() const
1744 return mrSheetData.getWorksheetSettings();
1747 SharedFormulaBuffer& WorksheetHelper::getSharedFormulas() const
1749 return mrSheetData.getSharedFormulas();
1752 CondFormatBuffer& WorksheetHelper::getCondFormats() const
1754 return mrSheetData.getCondFormats();
1757 CommentsBuffer& WorksheetHelper::getComments() const
1759 return mrSheetData.getComments();
1762 PageSettings& WorksheetHelper::getPageSettings() const
1764 return mrSheetData.getPageSettings();
1767 SheetViewSettings& WorksheetHelper::getSheetViewSettings() const
1769 return mrSheetData.getSheetViewSettings();
1772 VmlDrawing& WorksheetHelper::getVmlDrawing() const
1774 return mrSheetData.getVmlDrawing();
1777 void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText ) const
1779 OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" );
1780 Reference< XText > xText( rxCell, UNO_QUERY );
1781 if( xText.is() )
1782 xText->setString( rText );
1785 void WorksheetHelper::setSharedStringCell( const Reference< XCell >& rxCell, sal_Int32 nStringId, sal_Int32 nXfId ) const
1787 OSL_ENSURE( rxCell.is(), "WorksheetHelper::setSharedStringCell - missing cell interface" );
1788 getSharedStrings().convertString( Reference< XText >( rxCell, UNO_QUERY ), nStringId, nXfId );
1791 void WorksheetHelper::setDateTimeCell( const Reference< XCell >& rxCell, const DateTime& rDateTime ) const
1793 OSL_ENSURE( rxCell.is(), "WorksheetHelper::setDateTimeCell - missing cell interface" );
1794 // write serial date/time value into the cell
1795 double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime );
1796 rxCell->setValue( fSerial );
1797 // set appropriate number format
1798 using namespace ::com::sun::star::util::NumberFormat;
1799 sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE);
1800 setStandardNumFmt( rxCell, nStdFmt );
1803 void WorksheetHelper::setBooleanCell( const Reference< XCell >& rxCell, bool bValue ) const
1805 OSL_ENSURE( rxCell.is(), "WorksheetHelper::setBooleanCell - missing cell interface" );
1806 rxCell->setFormula( mrSheetData.getBooleanFormula( bValue ) );
1809 void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, const OUString& rErrorCode ) const
1811 setErrorCell( rxCell, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
1814 void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, sal_uInt8 nErrorCode ) const
1816 Reference< XFormulaTokens > xTokens( rxCell, UNO_QUERY );
1817 OSL_ENSURE( xTokens.is(), "WorksheetHelper::setErrorCell - missing formula interface" );
1818 if( xTokens.is() )
1820 SimpleFormulaContext aContext( xTokens, false, false );
1821 getFormulaParser().convertErrorToFormula( aContext, nErrorCode );
1825 void WorksheetHelper::setCell( CellModel& orModel ) const
1827 OSL_ENSURE( orModel.mxCell.is(), "WorksheetHelper::setCell - missing cell interface" );
1828 OOX_LOADSAVE_TIMER( SETCELL );
1829 if( orModel.mbHasValueStr ) switch( orModel.mnCellType )
1831 case XML_b:
1832 setBooleanCell( orModel.mxCell, orModel.maValueStr.toDouble() != 0.0 );
1833 // #108770# set 'Standard' number format for all Boolean cells
1834 orModel.mnNumFmtId = 0;
1835 break;
1836 case XML_n:
1837 orModel.mxCell->setValue( orModel.maValueStr.toDouble() );
1838 break;
1839 case XML_e:
1840 setErrorCell( orModel.mxCell, orModel.maValueStr );
1841 break;
1842 case XML_str:
1843 setStringCell( orModel.mxCell, orModel.maValueStr );
1844 break;
1845 case XML_s:
1846 setSharedStringCell( orModel.mxCell, orModel.maValueStr.toInt32(), orModel.mnXfId );
1847 break;
1851 void WorksheetHelper::setStandardNumFmt( const Reference< XCell >& rxCell, sal_Int16 nStdNumFmt ) const
1855 Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW );
1856 Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW );
1857 sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() );
1858 PropertySet aPropSet( rxCell );
1859 aPropSet.setProperty( PROP_NumberFormat, nIndex );
1861 catch( Exception& )
1866 void WorksheetHelper::setSheetType( WorksheetType eSheetType )
1868 mrSheetData.setSheetType( eSheetType );
1871 void WorksheetHelper::setDimension( const CellRangeAddress& rRange )
1873 mrSheetData.setDimension( rRange );
1876 void WorksheetHelper::setCellFormat( const CellModel& rModel )
1878 mrSheetData.setCellFormat( rModel );
1881 void WorksheetHelper::setMergedRange( const CellRangeAddress& rRange )
1883 mrSheetData.setMergedRange( rRange );
1886 void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
1888 mrSheetData.setPageBreak( rModel, bRowBreak );
1891 void WorksheetHelper::setHyperlink( const HyperlinkModel& rModel )
1893 mrSheetData.setHyperlink( rModel );
1896 void WorksheetHelper::setValidation( const ValidationModel& rModel )
1898 mrSheetData.setValidation( rModel );
1901 void WorksheetHelper::setTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const
1903 OSL_ENSURE( getAddressConverter().checkCellRange( rRange, true, false ), "WorksheetHelper::setTableOperation - invalid range" );
1904 bool bOk = false;
1905 if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
1907 CellRangeAddress aOpRange = rRange;
1908 CellAddress aRef1, aRef2;
1909 if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, mrSheetData.getSheetIndex(), true ) ) try
1911 if( rModel.mb2dTable )
1913 if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, mrSheetData.getSheetIndex(), true ) )
1915 // API call expects input values inside operation range
1916 --aOpRange.StartColumn;
1917 --aOpRange.StartRow;
1918 // formula range is top-left cell of operation range
1919 CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
1920 // set multiple operation
1921 Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
1922 xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_BOTH, aRef2, aRef1 );
1923 bOk = true;
1926 else if( rModel.mbRowTable )
1928 // formula range is column to the left of operation range
1929 CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
1930 // API call expects input values (top row) inside operation range
1931 --aOpRange.StartRow;
1932 // set multiple operation
1933 Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
1934 xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_ROW, aRef1, aRef1 );
1935 bOk = true;
1937 else
1939 // formula range is row above operation range
1940 CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
1941 // API call expects input values (left column) inside operation range
1942 --aOpRange.StartColumn;
1943 // set multiple operation
1944 Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW );
1945 xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_COLUMN, aRef1, aRef1 );
1946 bOk = true;
1949 catch( Exception& )
1954 // on error: fill cell range with error codes
1955 if( !bOk )
1957 for( CellAddress aPos( mrSheetData.getSheetIndex(), rRange.StartColumn, rRange.StartRow ); aPos.Row <= rRange.EndRow; ++aPos.Row )
1958 for( aPos.Column = rRange.StartColumn; aPos.Column <= rRange.EndColumn; ++aPos.Column )
1959 setErrorCell( mrSheetData.getCell( aPos ), BIFF_ERR_REF );
1963 void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges )
1965 const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
1966 Reference< XLabelRanges > xLabelRanges;
1967 PropertySet aPropSet( getSheet() );
1969 if( !rColRanges.empty() && aPropSet.getProperty( xLabelRanges, PROP_ColumnLabelRanges ) && xLabelRanges.is() )
1971 for( ApiCellRangeList::const_iterator aIt = rColRanges.begin(), aEnd = rColRanges.end(); aIt != aEnd; ++aIt )
1973 CellRangeAddress aDataRange = *aIt;
1974 if( aDataRange.EndRow < rMaxPos.Row )
1976 aDataRange.StartRow = aDataRange.EndRow + 1;
1977 aDataRange.EndRow = rMaxPos.Row;
1979 else if( aDataRange.StartRow > 0 )
1981 aDataRange.EndRow = aDataRange.StartRow - 1;
1982 aDataRange.StartRow = 0;
1984 xLabelRanges->addNew( *aIt, aDataRange );
1988 if( !rRowRanges.empty() && aPropSet.getProperty( xLabelRanges, PROP_RowLabelRanges ) && xLabelRanges.is() )
1990 for( ApiCellRangeList::const_iterator aIt = rRowRanges.begin(), aEnd = rRowRanges.end(); aIt != aEnd; ++aIt )
1992 CellRangeAddress aDataRange = *aIt;
1993 if( aDataRange.EndColumn < rMaxPos.Column )
1995 aDataRange.StartColumn = aDataRange.EndColumn + 1;
1996 aDataRange.EndColumn = rMaxPos.Column;
1998 else if( aDataRange.StartColumn > 0 )
2000 aDataRange.EndColumn = aDataRange.StartColumn - 1;
2001 aDataRange.StartColumn = 0;
2003 xLabelRanges->addNew( *aIt, aDataRange );
2008 void WorksheetHelper::setDrawingPath( const OUString& rDrawingPath )
2010 mrSheetData.setDrawingPath( rDrawingPath );
2013 void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath )
2015 mrSheetData.setVmlDrawingPath( rVmlDrawingPath );
2018 void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth )
2020 mrSheetData.setBaseColumnWidth( nWidth );
2023 void WorksheetHelper::setDefaultColumnWidth( double fWidth )
2025 mrSheetData.setDefaultColumnWidth( fWidth );
2028 void WorksheetHelper::setDefaultColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId )
2030 mrSheetData.convertColumnFormat( nFirstCol, nLastCol, nXfId );
2033 void WorksheetHelper::setColumnModel( const ColumnModel& rModel )
2035 mrSheetData.setColumnModel( rModel );
2038 void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
2040 mrSheetData.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom );
2043 void WorksheetHelper::setRowModel( const RowModel& rModel )
2045 mrSheetData.setRowModel( rModel );
2048 void WorksheetHelper::initializeWorksheetImport()
2050 mrSheetData.initializeWorksheetImport();
2053 void WorksheetHelper::finalizeWorksheetImport()
2055 mrSheetData.finalizeWorksheetImport();
2058 // ============================================================================
2060 namespace prv {
2062 WorksheetDataOwner::WorksheetDataOwner( WorksheetDataRef xSheetData ) :
2063 mxSheetData( xSheetData )
2067 WorksheetDataOwner::~WorksheetDataOwner()
2071 } // namespace prv
2073 // ----------------------------------------------------------------------------
2075 WorksheetHelperRoot::WorksheetHelperRoot( const WorkbookHelper& rHelper, ISegmentProgressBarRef xProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) :
2076 prv::WorksheetDataOwner( prv::WorksheetDataRef( new WorksheetData( rHelper, xProgressBar, eSheetType, nSheet ) ) ),
2077 WorksheetHelper( *mxSheetData )
2081 WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelper& rHelper ) :
2082 prv::WorksheetDataOwner( prv::WorksheetDataRef() ),
2083 WorksheetHelper( rHelper )
2087 WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelperRoot& rHelper ) :
2088 prv::WorksheetDataOwner( rHelper.mxSheetData ),
2089 WorksheetHelper( rHelper )
2093 bool WorksheetHelperRoot::isValidSheet() const
2095 return mxSheetData->isValidSheet();
2098 // ============================================================================
2099 // ============================================================================
2101 } // namespace xls
2102 } // namespace oox