xref: /trunk/main/oox/source/xls/worksheethelper.cxx (revision ca5ec200)
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             // convert validation type to API enum
1077             ValidationType eType = ValidationType_ANY;
1078             switch( aIt->mnType )
1079             {
1080                 case XML_custom:        eType = ValidationType_CUSTOM;      break;
1081                 case XML_date:          eType = ValidationType_DATE;        break;
1082                 case XML_decimal:       eType = ValidationType_DECIMAL;     break;
1083                 case XML_list:          eType = ValidationType_LIST;        break;
1084                 case XML_none:          eType = ValidationType_ANY;         break;
1085                 case XML_textLength:    eType = ValidationType_TEXT_LEN;    break;
1086                 case XML_time:          eType = ValidationType_TIME;        break;
1087                 case XML_whole:         eType = ValidationType_WHOLE;       break;
1088                 default:    OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown validation type" );
1089             }
1090             aValProps.setProperty( PROP_Type, eType );
1091 
1092             // convert error alert style to API enum
1093             ValidationAlertStyle eAlertStyle = ValidationAlertStyle_STOP;
1094             switch( aIt->mnErrorStyle )
1095             {
1096                 case XML_information:   eAlertStyle = ValidationAlertStyle_INFO;    break;
1097                 case XML_stop:          eAlertStyle = ValidationAlertStyle_STOP;    break;
1098                 case XML_warning:       eAlertStyle = ValidationAlertStyle_WARNING; break;
1099                 default:    OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown error style" );
1100             }
1101             aValProps.setProperty( PROP_ErrorAlertStyle, eAlertStyle );
1102 
1103             // convert dropdown style to API visibility constants
1104             sal_Int16 nVisibility = aIt->mbNoDropDown ? TableValidationVisibility::INVISIBLE : TableValidationVisibility::UNSORTED;
1105             aValProps.setProperty( PROP_ShowList, nVisibility );
1106 
1107             // messages
1108             aValProps.setProperty( PROP_ShowInputMessage, aIt->mbShowInputMsg );
1109             aValProps.setProperty( PROP_InputTitle, aIt->maInputTitle );
1110             aValProps.setProperty( PROP_InputMessage, aIt->maInputMessage );
1111             aValProps.setProperty( PROP_ShowErrorMessage, aIt->mbShowErrorMsg );
1112             aValProps.setProperty( PROP_ErrorTitle, aIt->maErrorTitle );
1113             aValProps.setProperty( PROP_ErrorMessage, aIt->maErrorMessage );
1114 
1115             // allow blank cells
1116             aValProps.setProperty( PROP_IgnoreBlankCells, aIt->mbAllowBlank );
1117 
1118             try
1119             {
1120                 // condition operator
1121                 Reference< XSheetCondition > xSheetCond( xValidation, UNO_QUERY_THROW );
1122                 xSheetCond->setOperator( CondFormatBuffer::convertToApiOperator( aIt->mnOperator ) );
1123 
1124                 // condition formulas
1125                 Reference< XMultiFormulaTokens > xTokens( xValidation, UNO_QUERY_THROW );
1126                 xTokens->setTokens( 0, aIt->maTokens1 );
1127                 xTokens->setTokens( 1, aIt->maTokens2 );
1128             }
1129             catch( Exception& )
1130             {
1131             }
1132 
1133             // write back validation settings to cell range(s)
1134             aPropSet.setProperty( PROP_Validation, xValidation );
1135         }
1136     }
1137 }
1138 
1139 void WorksheetGlobals::convertColumns()
1140 {
1141     sal_Int32 nNextCol = 0;
1142     sal_Int32 nMaxCol = mrMaxApiPos.Column;
1143     // stores first grouped column index for each level
1144     OutlineLevelVec aColLevels;
1145 
1146     for( ColumnModelRangeMap::iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt )
1147     {
1148         // column indexes are stored 0-based in maColModels
1149         ValueRange aColRange( ::std::max( aIt->first, nNextCol ), ::std::min( aIt->second.second, nMaxCol ) );
1150         // process gap between two column models, use default column model
1151         if( nNextCol < aColRange.mnFirst )
1152             convertColumns( aColLevels, ValueRange( nNextCol, aColRange.mnFirst - 1 ), maDefColModel );
1153         // process the column model
1154         convertColumns( aColLevels, aColRange, aIt->second.first );
1155         // cache next column to be processed
1156         nNextCol = aColRange.mnLast + 1;
1157     }
1158 
1159     // remaining default columns to end of sheet
1160     convertColumns( aColLevels, ValueRange( nNextCol, nMaxCol ), maDefColModel );
1161     // close remaining column outlines spanning to end of sheet
1162     convertOutlines( aColLevels, nMaxCol + 1, 0, false, false );
1163 }
1164 
1165 void WorksheetGlobals::convertColumns( OutlineLevelVec& orColLevels,
1166         const ValueRange& rColRange, const ColumnModel& rModel )
1167 {
1168     PropertySet aPropSet( getColumns( rColRange ) );
1169 
1170     // column width: convert 'number of characters' to column width in 1/100 mm
1171     sal_Int32 nWidth = getUnitConverter().scaleToMm100( rModel.mfWidth, UNIT_DIGIT );
1172     // macro sheets have double width
1173     if( meSheetType == SHEETTYPE_MACROSHEET )
1174         nWidth *= 2;
1175     if( nWidth > 0 )
1176         aPropSet.setProperty( PROP_Width, nWidth );
1177 
1178     // hidden columns: TODO: #108683# hide columns later?
1179     if( rModel.mbHidden )
1180         aPropSet.setProperty( PROP_IsVisible, false );
1181 
1182     // outline settings for this column range
1183     convertOutlines( orColLevels, rColRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, false );
1184 }
1185 
1186 void WorksheetGlobals::convertRows()
1187 {
1188     sal_Int32 nNextRow = 0;
1189     sal_Int32 nMaxRow = mrMaxApiPos.Row;
1190     // stores first grouped row index for each level
1191     OutlineLevelVec aRowLevels;
1192 
1193     for( RowModelRangeMap::iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt )
1194     {
1195         // row indexes are stored 0-based in maRowModels
1196         ValueRange aRowRange( ::std::max( aIt->first, nNextRow ), ::std::min( aIt->second.second, nMaxRow ) );
1197         // process gap between two row models, use default row model
1198         if( nNextRow < aRowRange.mnFirst )
1199             convertRows( aRowLevels, ValueRange( nNextRow, aRowRange.mnFirst - 1 ), maDefRowModel );
1200         // process the row model
1201         convertRows( aRowLevels, aRowRange, aIt->second.first, maDefRowModel.mfHeight );
1202         // cache next row to be processed
1203         nNextRow = aRowRange.mnLast + 1;
1204     }
1205 
1206     // remaining default rows to end of sheet
1207     convertRows( aRowLevels, ValueRange( nNextRow, nMaxRow ), maDefRowModel );
1208     // close remaining row outlines spanning to end of sheet
1209     convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true );
1210 }
1211 
1212 void WorksheetGlobals::convertRows( OutlineLevelVec& orRowLevels,
1213         const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight )
1214 {
1215     // row height: convert points to row height in 1/100 mm
1216     double fHeight = (rModel.mfHeight >= 0.0) ? rModel.mfHeight : fDefHeight;
1217     sal_Int32 nHeight = getUnitConverter().scaleToMm100( fHeight, UNIT_POINT );
1218     if( nHeight > 0 )
1219     {
1220         /*  Get all rows that have custom height inside the passed row model.
1221             If the model has the custom height flag set, all its rows have
1222             custom height, otherwise get all rows specified in the class member
1223             maManualRowHeights that are inside the passed row model. */
1224         ValueRangeVector aManualRows;
1225         if( rModel.mbCustomHeight )
1226             aManualRows.push_back( rRowRange );
1227         else
1228             aManualRows = maManualRowHeights.getIntersection( rRowRange );
1229         for( ValueRangeVector::const_iterator aIt = aManualRows.begin(), aEnd = aManualRows.end(); aIt != aEnd; ++aIt )
1230         {
1231             PropertySet aPropSet( getRows( *aIt ) );
1232             aPropSet.setProperty( PROP_Height, nHeight );
1233         }
1234     }
1235 
1236     // hidden rows: TODO: #108683# hide rows later?
1237     if( rModel.mbHidden )
1238     {
1239         PropertySet aPropSet( getRows( rRowRange ) );
1240         /*  #i116460# Use VisibleFlag instead of IsVisible: directly set the
1241             flag, without drawing layer update etc. (only possible before
1242             shapes are inserted). */
1243         aPropSet.setProperty( PROP_VisibleFlag, false );
1244     }
1245 
1246     // outline settings for this row range
1247     convertOutlines( orRowLevels, rRowRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, true );
1248 }
1249 
1250 void WorksheetGlobals::convertOutlines( OutlineLevelVec& orLevels,
1251         sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows )
1252 {
1253     /*  It is ensured from caller functions, that this function is called
1254         without any gaps between the processed column or row ranges. */
1255 
1256     OSL_ENSURE( nLevel >= 0, "WorksheetGlobals::convertOutlines - negative outline level" );
1257     nLevel = ::std::max< sal_Int32 >( nLevel, 0 );
1258 
1259     sal_Int32 nSize = orLevels.size();
1260     if( nSize < nLevel )
1261     {
1262         // Outline level increased. Push the begin column position.
1263         for( sal_Int32 nIndex = nSize; nIndex < nLevel; ++nIndex )
1264             orLevels.push_back( nColRow );
1265     }
1266     else if( nLevel < nSize )
1267     {
1268         // Outline level decreased. Pop them all out.
1269         for( sal_Int32 nIndex = nLevel; nIndex < nSize; ++nIndex )
1270         {
1271             sal_Int32 nFirstInLevel = orLevels.back();
1272             orLevels.pop_back();
1273             groupColumnsOrRows( nFirstInLevel, nColRow - 1, bCollapsed, bRows );
1274             bCollapsed = false; // collapse only once
1275         }
1276     }
1277 }
1278 
1279 void WorksheetGlobals::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows )
1280 {
1281     try
1282     {
1283         Reference< XSheetOutline > xOutline( mxSheet, UNO_QUERY_THROW );
1284         if( bRows )
1285         {
1286             CellRangeAddress aRange( getSheetIndex(), 0, nFirstColRow, 0, nLastColRow );
1287             xOutline->group( aRange, TableOrientation_ROWS );
1288             if( bCollapse )
1289                 xOutline->hideDetail( aRange );
1290         }
1291         else
1292         {
1293             CellRangeAddress aRange( getSheetIndex(), nFirstColRow, 0, nLastColRow, 0 );
1294             xOutline->group( aRange, TableOrientation_COLUMNS );
1295             if( bCollapse )
1296                 xOutline->hideDetail( aRange );
1297         }
1298     }
1299     catch( Exception& )
1300     {
1301     }
1302 }
1303 
1304 void WorksheetGlobals::finalizeDrawings()
1305 {
1306     // calculate the current drawing page size (after rows/columns are imported)
1307     PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) );
1308     aRangeProp.getProperty( maDrawPageSize, PROP_Size );
1309 
1310     switch( getFilterType() )
1311     {
1312         case FILTER_OOXML:
1313             // import DML and VML
1314             if( maDrawingPath.getLength() > 0 )
1315                 importOoxFragment( new DrawingFragment( *this, maDrawingPath ) );
1316             if( maVmlDrawingPath.getLength() > 0 )
1317                 importOoxFragment( new VmlDrawingFragment( *this, maVmlDrawingPath ) );
1318         break;
1319 
1320         case FILTER_BIFF:
1321             // convert BIFF3-BIFF5 drawing objects, or import and convert DFF stream
1322             getBiffDrawing().finalizeImport();
1323         break;
1324 
1325         case FILTER_UNKNOWN:
1326         break;
1327     }
1328 
1329     // comments (after callout shapes have been imported from VML/DFF)
1330     maComments.finalizeImport();
1331 
1332     /*  Extend used area of the sheet by cells covered with drawing objects.
1333         Needed if the imported document is inserted as "OLE object from file"
1334         and thus does not provide an OLE size property by itself. */
1335     if( (maShapeBoundingBox.Width > 0) || (maShapeBoundingBox.Height > 0) )
1336         extendUsedArea( getCellRangeFromRectangle( maShapeBoundingBox ) );
1337 
1338     // if no used area is set, default to A1
1339     if( maUsedArea.StartColumn > maUsedArea.EndColumn )
1340         maUsedArea.StartColumn = maUsedArea.EndColumn = 0;
1341     if( maUsedArea.StartRow > maUsedArea.EndRow )
1342         maUsedArea.StartRow = maUsedArea.EndRow = 0;
1343 
1344     /*  Register the used area of this sheet in global view settings. The
1345         global view settings will set the visible area if this document is an
1346         embedded OLE object. */
1347     getViewSettings().setSheetUsedArea( maUsedArea );
1348 
1349     /*  #i103686# Set right-to-left sheet layout. Must be done after all
1350         drawing shapes to simplify calculation of shape coordinates. */
1351     if( maSheetViewSett.isSheetRightToLeft() )
1352     {
1353         PropertySet aPropSet( mxSheet );
1354         aPropSet.setProperty( PROP_TableLayout, WritingMode2::RL_TB );
1355     }
1356 }
1357 
1358 // ============================================================================
1359 // ============================================================================
1360 
1361 WorksheetHelper::WorksheetHelper( WorksheetGlobals& rSheetGlob ) :
1362     WorkbookHelper( rSheetGlob ),
1363     mrSheetGlob( rSheetGlob )
1364 {
1365 }
1366 
1367 /*static*/ WorksheetGlobalsRef WorksheetHelper::constructGlobals( const WorkbookHelper& rHelper,
1368         const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet )
1369 {
1370     WorksheetGlobalsRef xSheetGlob( new WorksheetGlobals( rHelper, rxProgressBar, eSheetType, nSheet ) );
1371     if( !xSheetGlob->isValidSheet() )
1372         xSheetGlob.reset();
1373     return xSheetGlob;
1374 }
1375 
1376 WorksheetType WorksheetHelper::getSheetType() const
1377 {
1378     return mrSheetGlob.getSheetType();
1379 }
1380 
1381 sal_Int16 WorksheetHelper::getSheetIndex() const
1382 {
1383     return mrSheetGlob.getSheetIndex();
1384 }
1385 
1386 const Reference< XSpreadsheet >& WorksheetHelper::getSheet() const
1387 {
1388     return mrSheetGlob.getSheet();
1389 }
1390 
1391 Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const
1392 {
1393     return mrSheetGlob.getCell( rAddress );
1394 }
1395 
1396 Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const
1397 {
1398     return mrSheetGlob.getCellRange( rRange );
1399 }
1400 
1401 Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const
1402 {
1403     return mrSheetGlob.getCellRangeList( rRanges );
1404 }
1405 
1406 CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell )
1407 {
1408     CellAddress aAddress;
1409     Reference< XCellAddressable > xAddressable( rxCell, UNO_QUERY );
1410     OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getCellAddress - cell reference not addressable" );
1411     if( xAddressable.is() )
1412         aAddress = xAddressable->getCellAddress();
1413     return aAddress;
1414 }
1415 
1416 CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange >& rxRange )
1417 {
1418     CellRangeAddress aRange;
1419     Reference< XCellRangeAddressable > xAddressable( rxRange, UNO_QUERY );
1420     OSL_ENSURE( xAddressable.is(), "WorksheetHelper::getRangeAddress - cell range reference not addressable" );
1421     if( xAddressable.is() )
1422         aRange = xAddressable->getRangeAddress();
1423     return aRange;
1424 }
1425 
1426 Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const
1427 {
1428     return mrSheetGlob.getColumn( nCol );
1429 }
1430 
1431 Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const
1432 {
1433     return mrSheetGlob.getRow( nRow );
1434 }
1435 
1436 Reference< XTableColumns > WorksheetHelper::getColumns( const ValueRange& rColRange ) const
1437 {
1438     return mrSheetGlob.getColumns( rColRange );
1439 }
1440 
1441 Reference< XTableRows > WorksheetHelper::getRows( const ValueRange& rRowRange ) const
1442 {
1443     return mrSheetGlob.getRows( rRowRange );
1444 }
1445 
1446 Reference< XDrawPage > WorksheetHelper::getDrawPage() const
1447 {
1448     return mrSheetGlob.getDrawPage();
1449 }
1450 
1451 Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const
1452 {
1453     return mrSheetGlob.getCellPosition( nCol, nRow );
1454 }
1455 
1456 Size WorksheetHelper::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const
1457 {
1458     return mrSheetGlob.getCellSize( nCol, nRow );
1459 }
1460 
1461 Size WorksheetHelper::getDrawPageSize() const
1462 {
1463     return mrSheetGlob.getDrawPageSize();
1464 }
1465 
1466 SheetDataBuffer& WorksheetHelper::getSheetData() const
1467 {
1468     return mrSheetGlob.getSheetData();
1469 }
1470 
1471 CondFormatBuffer& WorksheetHelper::getCondFormats() const
1472 {
1473     return mrSheetGlob.getCondFormats();
1474 }
1475 
1476 CommentsBuffer& WorksheetHelper::getComments() const
1477 {
1478     return mrSheetGlob.getComments();
1479 }
1480 
1481 AutoFilterBuffer& WorksheetHelper::getAutoFilters() const
1482 {
1483     return mrSheetGlob.getAutoFilters();
1484 }
1485 
1486 QueryTableBuffer& WorksheetHelper::getQueryTables() const
1487 {
1488     return mrSheetGlob.getQueryTables();
1489 }
1490 
1491 WorksheetSettings& WorksheetHelper::getWorksheetSettings() const
1492 {
1493     return mrSheetGlob.getWorksheetSettings();
1494 }
1495 
1496 PageSettings& WorksheetHelper::getPageSettings() const
1497 {
1498     return mrSheetGlob.getPageSettings();
1499 }
1500 
1501 SheetViewSettings& WorksheetHelper::getSheetViewSettings() const
1502 {
1503     return mrSheetGlob.getSheetViewSettings();
1504 }
1505 
1506 VmlDrawing& WorksheetHelper::getVmlDrawing() const
1507 {
1508     return mrSheetGlob.getVmlDrawing();
1509 }
1510 
1511 BiffSheetDrawing& WorksheetHelper::getBiffDrawing() const
1512 {
1513     return mrSheetGlob.getBiffDrawing();
1514 }
1515 
1516 void WorksheetHelper::setSheetType( WorksheetType eSheetType )
1517 {
1518     mrSheetGlob.setSheetType( eSheetType );
1519 }
1520 
1521 void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak )
1522 {
1523     mrSheetGlob.setPageBreak( rModel, bRowBreak );
1524 }
1525 
1526 void WorksheetHelper::setHyperlink( const HyperlinkModel& rModel )
1527 {
1528     mrSheetGlob.setHyperlink( rModel );
1529 }
1530 
1531 void WorksheetHelper::setValidation( const ValidationModel& rModel )
1532 {
1533     mrSheetGlob.setValidation( rModel );
1534 }
1535 
1536 void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges )
1537 {
1538     const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
1539     PropertySet aPropSet( getSheet() );
1540 
1541     if( !rColRanges.empty() )
1542     {
1543         Reference< XLabelRanges > xLabelRanges( aPropSet.getAnyProperty( PROP_ColumnLabelRanges ), UNO_QUERY );
1544         if( xLabelRanges.is() )
1545         {
1546             for( ApiCellRangeList::const_iterator aIt = rColRanges.begin(), aEnd = rColRanges.end(); aIt != aEnd; ++aIt )
1547             {
1548                 CellRangeAddress aDataRange = *aIt;
1549                 if( aDataRange.EndRow < rMaxPos.Row )
1550                 {
1551                     aDataRange.StartRow = aDataRange.EndRow + 1;
1552                     aDataRange.EndRow = rMaxPos.Row;
1553                 }
1554                 else if( aDataRange.StartRow > 0 )
1555                 {
1556                     aDataRange.EndRow = aDataRange.StartRow - 1;
1557                     aDataRange.StartRow = 0;
1558                 }
1559                 xLabelRanges->addNew( *aIt, aDataRange );
1560             }
1561         }
1562     }
1563 
1564     if( !rRowRanges.empty() )
1565     {
1566         Reference< XLabelRanges > xLabelRanges( aPropSet.getAnyProperty( PROP_RowLabelRanges ), UNO_QUERY );
1567         if( xLabelRanges.is() )
1568         {
1569             for( ApiCellRangeList::const_iterator aIt = rRowRanges.begin(), aEnd = rRowRanges.end(); aIt != aEnd; ++aIt )
1570             {
1571                 CellRangeAddress aDataRange = *aIt;
1572                 if( aDataRange.EndColumn < rMaxPos.Column )
1573                 {
1574                     aDataRange.StartColumn = aDataRange.EndColumn + 1;
1575                     aDataRange.EndColumn = rMaxPos.Column;
1576                 }
1577                 else if( aDataRange.StartColumn > 0 )
1578                 {
1579                     aDataRange.EndColumn = aDataRange.StartColumn - 1;
1580                     aDataRange.StartColumn = 0;
1581                 }
1582                 xLabelRanges->addNew( *aIt, aDataRange );
1583             }
1584         }
1585     }
1586 }
1587 
1588 void WorksheetHelper::setDrawingPath( const OUString& rDrawingPath )
1589 {
1590     mrSheetGlob.setDrawingPath( rDrawingPath );
1591 }
1592 
1593 void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath )
1594 {
1595     mrSheetGlob.setVmlDrawingPath( rVmlDrawingPath );
1596 }
1597 
1598 void WorksheetHelper::extendUsedArea( const CellAddress& rAddress )
1599 {
1600     mrSheetGlob.extendUsedArea( rAddress );
1601 }
1602 
1603 void WorksheetHelper::extendUsedArea( const CellRangeAddress& rRange )
1604 {
1605     mrSheetGlob.extendUsedArea( rRange );
1606 }
1607 
1608 void WorksheetHelper::extendShapeBoundingBox( const Rectangle& rShapeRect )
1609 {
1610     mrSheetGlob.extendShapeBoundingBox( rShapeRect );
1611 }
1612 
1613 void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth )
1614 {
1615     mrSheetGlob.setBaseColumnWidth( nWidth );
1616 }
1617 
1618 void WorksheetHelper::setDefaultColumnWidth( double fWidth )
1619 {
1620     mrSheetGlob.setDefaultColumnWidth( fWidth );
1621 }
1622 
1623 void WorksheetHelper::setDefaultColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId )
1624 {
1625     mrSheetGlob.convertColumnFormat( nFirstCol, nLastCol, nXfId );
1626 }
1627 
1628 void WorksheetHelper::setColumnModel( const ColumnModel& rModel )
1629 {
1630     mrSheetGlob.setColumnModel( rModel );
1631 }
1632 
1633 void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom )
1634 {
1635     mrSheetGlob.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom );
1636 }
1637 
1638 void WorksheetHelper::setRowModel( const RowModel& rModel )
1639 {
1640     mrSheetGlob.setRowModel( rModel );
1641 }
1642 
1643 void WorksheetHelper::setManualRowHeight( sal_Int32 nRow )
1644 {
1645     mrSheetGlob.setManualRowHeight( nRow );
1646 }
1647 
1648 void WorksheetHelper::putValue( const CellAddress& rAddress, double fValue ) const
1649 {
1650     Reference< XCell > xCell = getCell( rAddress );
1651     OSL_ENSURE( xCell.is(), "WorksheetHelper::putValue - missing cell interface" );
1652     if( xCell.is() ) xCell->setValue( fValue );
1653 }
1654 
1655 void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) const
1656 {
1657     Reference< XText > xText( getCell( rAddress ), UNO_QUERY );
1658     OSL_ENSURE( xText.is(), "WorksheetHelper::putString - missing text interface" );
1659     if( xText.is() ) xText->setString( rText );
1660 }
1661 
1662 void WorksheetHelper::putRichString( const CellAddress& rAddress, const RichString& rString, const Font* pFirstPortionFont ) const
1663 {
1664     Reference< XText > xText( getCell( rAddress ), UNO_QUERY );
1665     OSL_ENSURE( xText.is(), "WorksheetHelper::putRichString - missing text interface" );
1666     /*  Passing false will always append the portions to the XText. This is
1667         essential for special rich formatting attributes at the leading text
1668         portion supported by edit cells only, e.g. font escapement. */
1669     rString.convert( xText, false, pFirstPortionFont );
1670 }
1671 
1672 void WorksheetHelper::putFormulaTokens( const CellAddress& rAddress, const ApiTokenSequence& rTokens ) const
1673 {
1674     Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY );
1675     OSL_ENSURE( xTokens.is(), "WorksheetHelper::putFormulaTokens - missing token interface" );
1676     if( xTokens.is() ) xTokens->setTokens( rTokens );
1677 }
1678 
1679 void WorksheetHelper::initializeWorksheetImport()
1680 {
1681     mrSheetGlob.initializeWorksheetImport();
1682 }
1683 
1684 void WorksheetHelper::finalizeWorksheetImport()
1685 {
1686     mrSheetGlob.finalizeWorksheetImport();
1687 }
1688 
1689 // ============================================================================
1690 // ============================================================================
1691 
1692 } // namespace xls
1693 } // namespace oox
1694