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