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"
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"
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
;
126 // ============================================================================
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 // ----------------------------------------------------------------------------
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 // ----------------------------------------------------------------------------
173 inline explicit ValueRangeSet() {}
175 void insert( sal_Int32 nValue
);
176 void intersect( ValueRangeVector
& orRanges
, sal_Int32 nFirst
, sal_Int32 nLast
) const;
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
);
205 maData
.insert( aNext
, ValueRange( nValue
) );
209 void ValueRangeSet::intersect( ValueRangeVector
& orRanges
, sal_Int32 nFirst
, sal_Int32 nLast
) const
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
) ) );
220 // ============================================================================
221 // ============================================================================
223 void CellModel::reset()
226 maValueStr
= maFormulaRef
= OUString();
227 mnCellType
= mnFormulaType
= XML_TOKEN_INVALID
;
228 mnSharedId
= mnXfId
= mnNumFmtId
= -1;
229 mbHasValueStr
= mbShowPhonetic
= false;
232 // ----------------------------------------------------------------------------
234 DataTableModel::DataTableModel() :
237 mbRef1Deleted( false ),
238 mbRef2Deleted( false )
242 // ----------------------------------------------------------------------------
244 ColumnModel::ColumnModel() :
250 mbShowPhonetic( false ),
256 bool ColumnModel::tryExpand( const ColumnModel
& rModel
)
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
);
268 mnLastCol
= rModel
.mnLastCol
;
272 // ----------------------------------------------------------------------------
274 RowModel::RowModel() :
280 mbCustomHeight( false ),
281 mbCustomFormat( false ),
282 mbShowPhonetic( false ),
284 mbCollapsed( false ),
286 mbThickBottom( false )
290 bool RowModel::tryExpand( const RowModel
& rModel
)
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
);
303 mnLastRow
= rModel
.mnLastRow
;
307 // ----------------------------------------------------------------------------
309 PageBreakModel::PageBreakModel() :
315 // ----------------------------------------------------------------------------
317 HyperlinkModel::HyperlinkModel()
321 // ----------------------------------------------------------------------------
323 ValidationModel::ValidationModel() :
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
361 explicit WorksheetData(
362 const WorkbookHelper
& rHelper
,
363 ISegmentProgressBarRef xProgressBar
,
364 WorksheetType eSheetType
,
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();
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
;
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
);
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
);
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. */
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
);
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 ),
610 maSheetViewSett( *this ),
611 mxProgressBar( xProgressBar
),
612 meSheetType( eSheetType
),
614 mbHasDefWidth( false )
616 mxSheet
= getSheetFromDoc( nSheet
);
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;
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
);
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
);
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
);
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
);
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
);
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
);
735 xColumns
= xRange
->getColumns();
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
);
748 xRows
= xRange
->getRows();
753 Reference
< XDrawPage
> WorksheetData::getDrawPage() const
755 Reference
< XDrawPage
> xDrawPage
;
758 Reference
< XDrawPageSupplier
> xDrawPageSupp( mxSheet
, UNO_QUERY_THROW
);
759 xDrawPage
= xDrawPageSupp
->getDrawPage();
767 Point
WorksheetData::getCellPosition( sal_Int32 nCol
, sal_Int32 nRow
) const
770 PropertySet
aCellProp( getCell( CellAddress( mnSheet
, nCol
, nRow
) ) );
771 aCellProp
.getProperty( aPoint
, PROP_Position
);
775 Size
WorksheetData::getCellSize( sal_Int32 nCol
, sal_Int32 nRow
) const
778 PropertySet
aCellProp( getCell( CellAddress( mnSheet
, nCol
, nRow
) ) );
779 aCellProp
.getProperty( aSize
, PROP_Size
);
783 Size
WorksheetData::getDrawPageSize() const
786 PropertySet
aRangeProp( getCellRange( CellRangeAddress( mnSheet
, 0, 0, mrMaxApiPos
.Column
, mrMaxApiPos
.Row
) ) );
787 aRangeProp
.getProperty( aSize
, PROP_Size
);
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
)
810 // write format properties of all ranges above last row and remove them
811 XfIdRangeMap::iterator aIt
= maXfIdRanges
.begin(), aEnd
= maXfIdRanges
.end();
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
++ );
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()
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 );
1006 lclUpdateProgressBar( mxFinalProgress
, 0.75 );
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() :
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
;
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
;
1046 if( mnFirstRow
== nLastRow
+ 1 )
1048 mnFirstRow
= nFirstRow
;
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
;
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
;
1092 WorksheetData::MergedRange::MergedRange( const CellRangeAddress
& 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
;
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
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( '!' );
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
);
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
);
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" );
1243 // fix for #i31050# disabled, HYPERLINK is not able to return numeric value (#i91351#)
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" );
1252 SimpleFormulaContext
aContext( xTokens
, false, false );
1253 getFormulaParser().convertNumberToHyperlink( aContext
, rUrl
, xCell
->getValue() );
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
);
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
);
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
1365 PropertySet
aTopRightProp( getCell( CellAddress( mnSheet
, rRange
.EndColumn
, rRange
.StartRow
) ) );
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
1374 PropertySet
aBottomLeftProp( getCell( CellAddress( mnSheet
, rRange
.StartColumn
, rRange
.EndRow
) ) );
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
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);
1390 maManualRowHeights
.insert( rRange
.StartRow
);
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
)
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
);
1504 ValueRangeVector aManualRows
;
1505 if( rModel
.mbCustomHeight
)
1506 aManualRows
.push_back( ValueRange( nFirstRow
, nLastRow
) );
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
);
1563 CellRangeAddress
aRange( mnSheet
, 0, nFirstColRow
, 0, nLastColRow
);
1564 xOutline
->group( aRange
, ::com::sun::star::table::TableOrientation_ROWS
);
1566 xOutline
->hideDetail( aRange
);
1570 CellRangeAddress
aRange( mnSheet
, nFirstColRow
, 0, nLastColRow
, 0 );
1571 xOutline
->group( aRange
, ::com::sun::star::table::TableOrientation_COLUMNS
);
1573 xOutline
->hideDetail( aRange
);
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();
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();
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
);
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" );
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
)
1832 setBooleanCell( orModel
.mxCell
, orModel
.maValueStr
.toDouble() != 0.0 );
1833 // #108770# set 'Standard' number format for all Boolean cells
1834 orModel
.mnNumFmtId
= 0;
1837 orModel
.mxCell
->setValue( orModel
.maValueStr
.toDouble() );
1840 setErrorCell( orModel
.mxCell
, orModel
.maValueStr
);
1843 setStringCell( orModel
.mxCell
, orModel
.maValueStr
);
1846 setSharedStringCell( orModel
.mxCell
, orModel
.maValueStr
.toInt32(), orModel
.mnXfId
);
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
);
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" );
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
);
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
);
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
);
1954 // on error: fill cell range with error codes
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 // ============================================================================
2062 WorksheetDataOwner::WorksheetDataOwner( WorksheetDataRef xSheetData
) :
2063 mxSheetData( xSheetData
)
2067 WorksheetDataOwner::~WorksheetDataOwner()
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 // ============================================================================