LCOV - code coverage report
Current view: top level - sc/source/filter/oox - worksheethelper.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 534 697 76.6 %
Date: 2015-06-13 12:38:46 Functions: 105 125 84.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11