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