LCOV - code coverage report
Current view: top level - sc/source/ui/vba - vbarange.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1992 2924 68.1 %
Date: 2015-06-13 12:38:46 Functions: 227 297 76.4 %
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 "vbarange.hxx"
      21             : 
      22             : #include <vbahelper/helperdecl.hxx>
      23             : 
      24             : #include <comphelper/unwrapargs.hxx>
      25             : #include <comphelper/processfactory.hxx>
      26             : #include <sfx2/objsh.hxx>
      27             : 
      28             : #include <com/sun/star/script/ArrayWrapper.hpp>
      29             : #include <com/sun/star/script/vba/VBAEventId.hpp>
      30             : #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
      31             : #include <com/sun/star/sheet/XDatabaseRange.hpp>
      32             : #include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
      33             : #include <com/sun/star/sheet/XGoalSeek.hpp>
      34             : #include <com/sun/star/sheet/XSheetOperation.hpp>
      35             : #include <com/sun/star/sheet/CellFlags.hpp>
      36             : #include <com/sun/star/table/XColumnRowRange.hpp>
      37             : #include <com/sun/star/sheet/XCellAddressable.hpp>
      38             : #include <com/sun/star/table/CellContentType.hpp>
      39             : #include <com/sun/star/sheet/XCellSeries.hpp>
      40             : #include <com/sun/star/text/XTextRange.hpp>
      41             : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
      42             : #include <com/sun/star/table/CellAddress.hpp>
      43             : #include <com/sun/star/table/CellRangeAddress.hpp>
      44             : #include <com/sun/star/sheet/XSpreadsheetView.hpp>
      45             : #include <com/sun/star/sheet/XCellRangeReferrer.hpp>
      46             : #include <com/sun/star/sheet/XSheetCellRange.hpp>
      47             : #include <com/sun/star/sheet/XSpreadsheet.hpp>
      48             : #include <com/sun/star/sheet/XSheetCellCursor.hpp>
      49             : #include <com/sun/star/sheet/XArrayFormulaRange.hpp>
      50             : #include <com/sun/star/sheet/XNamedRange.hpp>
      51             : #include <com/sun/star/sheet/XPrintAreas.hpp>
      52             : #include <com/sun/star/sheet/XCellRangesQuery.hpp>
      53             : #include <com/sun/star/beans/XPropertySet.hpp>
      54             : #include <com/sun/star/sheet/XFunctionAccess.hpp>
      55             : #include <com/sun/star/frame/XModel.hpp>
      56             : #include <com/sun/star/view/XSelectionSupplier.hpp>
      57             : #include <com/sun/star/table/XCellCursor.hpp>
      58             : #include <com/sun/star/table/XTableRows.hpp>
      59             : #include <com/sun/star/table/XTableColumns.hpp>
      60             : #include <com/sun/star/table/TableSortField.hpp>
      61             : #include <com/sun/star/util/XMergeable.hpp>
      62             : #include <com/sun/star/uno/XComponentContext.hpp>
      63             : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
      64             : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
      65             : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
      66             : #include <com/sun/star/util/XNumberFormats.hpp>
      67             : #include <com/sun/star/util/NumberFormat.hpp>
      68             : #include <com/sun/star/util/XNumberFormatTypes.hpp>
      69             : #include <com/sun/star/util/XReplaceable.hpp>
      70             : #include <com/sun/star/util/XSortable.hpp>
      71             : #include <com/sun/star/sheet/XCellRangeMovement.hpp>
      72             : #include <com/sun/star/sheet/XCellRangeData.hpp>
      73             : #include <com/sun/star/sheet/FormulaResult.hpp>
      74             : #include <com/sun/star/sheet/FilterOperator2.hpp>
      75             : #include <com/sun/star/sheet/TableFilterField.hpp>
      76             : #include <com/sun/star/sheet/TableFilterField2.hpp>
      77             : #include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
      78             : #include <com/sun/star/sheet/XSheetFilterable.hpp>
      79             : #include <com/sun/star/sheet/FilterConnection.hpp>
      80             : #include <com/sun/star/util/CellProtection.hpp>
      81             : #include <com/sun/star/util/TriState.hpp>
      82             : 
      83             : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
      84             : #include <com/sun/star/awt/XDevice.hpp>
      85             : 
      86             : #include <com/sun/star/sheet/XSubTotalCalculatable.hpp>
      87             : #include <com/sun/star/sheet/XSubTotalDescriptor.hpp>
      88             : #include <com/sun/star/sheet/GeneralFunction.hpp>
      89             : 
      90             : #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
      91             : #include <com/sun/star/sheet/XSheetAnnotations.hpp>
      92             : 
      93             : #include <ooo/vba/excel/XlPasteSpecialOperation.hpp>
      94             : #include <ooo/vba/excel/XlPasteType.hpp>
      95             : #include <ooo/vba/excel/Constants.hpp>
      96             : #include <ooo/vba/excel/XlFindLookIn.hpp>
      97             : #include <ooo/vba/excel/XlLookAt.hpp>
      98             : #include <ooo/vba/excel/XlSearchOrder.hpp>
      99             : #include <ooo/vba/excel/XlSortOrder.hpp>
     100             : #include <ooo/vba/excel/XlYesNoGuess.hpp>
     101             : #include <ooo/vba/excel/XlSortOrientation.hpp>
     102             : #include <ooo/vba/excel/XlSortMethod.hpp>
     103             : #include <ooo/vba/excel/XlDirection.hpp>
     104             : #include <ooo/vba/excel/XlSortDataOption.hpp>
     105             : #include <ooo/vba/excel/XlDeleteShiftDirection.hpp>
     106             : #include <ooo/vba/excel/XlInsertShiftDirection.hpp>
     107             : #include <ooo/vba/excel/XlReferenceStyle.hpp>
     108             : #include <ooo/vba/excel/XlBordersIndex.hpp>
     109             : #include <ooo/vba/excel/XlPageBreak.hpp>
     110             : #include <ooo/vba/excel/XlAutoFilterOperator.hpp>
     111             : #include <ooo/vba/excel/XlAutoFillType.hpp>
     112             : #include <ooo/vba/excel/XlTextParsingType.hpp>
     113             : #include <ooo/vba/excel/XlTextQualifier.hpp>
     114             : #include <ooo/vba/excel/XlCellType.hpp>
     115             : #include <ooo/vba/excel/XlSpecialCellsValue.hpp>
     116             : #include <ooo/vba/excel/XlConsolidationFunction.hpp>
     117             : #include <ooo/vba/excel/XlSearchDirection.hpp>
     118             : 
     119             : #include <scitems.hxx>
     120             : #include <svl/srchitem.hxx>
     121             : #include <cellsuno.hxx>
     122             : #include <dbdata.hxx>
     123             : #include "docfunc.hxx"
     124             : #include <docuno.hxx>
     125             : 
     126             : #include <sfx2/dispatch.hxx>
     127             : #include <sfx2/app.hxx>
     128             : #include <sfx2/bindings.hxx>
     129             : #include <sfx2/request.hxx>
     130             : #include <sfx2/viewfrm.hxx>
     131             : #include <sfx2/itemwrapper.hxx>
     132             : #include <sc.hrc>
     133             : #include <globstr.hrc>
     134             : #include <unonames.hxx>
     135             : 
     136             : #include "vbaapplication.hxx"
     137             : #include "vbafont.hxx"
     138             : #include "vbacomment.hxx"
     139             : #include "vbainterior.hxx"
     140             : #include "vbacharacters.hxx"
     141             : #include "vbaborders.hxx"
     142             : #include "vbaworksheet.hxx"
     143             : #include "vbavalidation.hxx"
     144             : #include "vbahyperlinks.hxx"
     145             : 
     146             : #include "tabvwsh.hxx"
     147             : #include "rangelst.hxx"
     148             : #include "convuno.hxx"
     149             : #include "compiler.hxx"
     150             : #include "attrib.hxx"
     151             : #include "undodat.hxx"
     152             : #include "dbdocfun.hxx"
     153             : #include "patattr.hxx"
     154             : #include "olinetab.hxx"
     155             : #include "transobj.hxx"
     156             : #include "queryentry.hxx"
     157             : #include "markdata.hxx"
     158             : #include <comphelper/anytostring.hxx>
     159             : 
     160             : #include <global.hxx>
     161             : 
     162             : #include "vbaglobals.hxx"
     163             : #include "vbastyle.hxx"
     164             : #include "vbaname.hxx"
     165             : #include <vector>
     166             : #include <vbahelper/vbacollectionimpl.hxx>
     167             : // begin test includes
     168             : #include <com/sun/star/sheet/FunctionArgument.hpp>
     169             : // end test includes
     170             : 
     171             : #include <ooo/vba/excel/Range.hpp>
     172             : #include <com/sun/star/bridge/oleautomation/Date.hpp>
     173             : #include "tokenarray.hxx"
     174             : #include "tokenuno.hxx"
     175             : #include <columnspanset.hxx>
     176             : 
     177             : #include <boost/scoped_ptr.hpp>
     178             : 
     179             : using namespace ::ooo::vba;
     180             : using namespace ::com::sun::star;
     181             : using ::std::vector;
     182             : 
     183             : // difference between VBA and file format width, in character units
     184             : const double fExtraWidth = 182.0 / 256.0;
     185             : 
     186             : //    * 1 point = 1/72 inch = 20 twips
     187             : //    * 1 inch = 72 points = 1440 twips
     188             : //    * 1 cm = 567 twips
     189          16 : static double lcl_hmmToPoints( double nVal ) { return ( (double)((nVal /1000 ) * 567 ) / 20 ); }
     190             : 
     191             : static const sal_Int16 supportedIndexTable[] = {  excel::XlBordersIndex::xlEdgeLeft, excel::XlBordersIndex::xlEdgeTop, excel::XlBordersIndex::xlEdgeBottom, excel::XlBordersIndex::xlEdgeRight, excel::XlBordersIndex::xlDiagonalDown, excel::XlBordersIndex::xlDiagonalUp, excel::XlBordersIndex::xlInsideVertical, excel::XlBordersIndex::xlInsideHorizontal };
     192             : 
     193           8 : static sal_uInt16 lcl_pointsToTwips( double nVal )
     194             : {
     195           8 :     nVal = nVal * static_cast<double>(20);
     196           8 :     short nTwips = static_cast<short>(nVal);
     197           8 :     return nTwips;
     198             : }
     199          77 : static double lcl_TwipsToPoints( sal_uInt16 nVal )
     200             : {
     201          77 :     double nPoints = nVal;
     202          77 :     return nPoints / 20;
     203             : }
     204             : 
     205          85 : static double lcl_Round2DecPlaces( double nVal )
     206             : {
     207          85 :     nVal  = (nVal * (double)100);
     208          85 :     long tmp = static_cast<long>(nVal);
     209          85 :     if ( ( ( nVal - tmp ) >= 0.5 ) )
     210          10 :         ++tmp;
     211          85 :     nVal = tmp;
     212          85 :     nVal = nVal/100;
     213          85 :     return nVal;
     214             : }
     215             : 
     216         682 : static uno::Any lcl_makeRange( const uno::Reference< XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, const uno::Any& rAny, bool bIsRows, bool bIsColumns )
     217             : {
     218         682 :     uno::Reference< table::XCellRange > xCellRange(rAny, uno::UNO_QUERY_THROW);
     219         682 :     return uno::makeAny( uno::Reference< excel::XRange >( new ScVbaRange( rParent, rContext, xCellRange, bIsRows, bIsColumns ) ) );
     220             : }
     221             : 
     222           7 : static uno::Reference< excel::XRange > lcl_makeXRangeFromSheetCellRanges( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSheetCellRanges >& xLocSheetCellRanges, ScDocShell* pDoc )
     223             : {
     224           7 :     uno::Reference< excel::XRange > xRange;
     225          14 :     uno::Sequence< table::CellRangeAddress  > sAddresses = xLocSheetCellRanges->getRangeAddresses();
     226          14 :     ScRangeList aCellRanges;
     227           7 :     sal_Int32 nLen = sAddresses.getLength();
     228           7 :     if ( nLen )
     229             :            {
     230          19 :     for ( sal_Int32 index = 0; index < nLen; ++index )
     231             :     {
     232          12 :         ScRange refRange;
     233          12 :         ScUnoConversion::FillScRange( refRange, sAddresses[ index ] );
     234          12 :         aCellRanges.Append( refRange );
     235             :     }
     236             :     // Single range
     237           7 :     if ( aCellRanges.size() == 1 )
     238             :     {
     239           2 :         uno::Reference< table::XCellRange > xTmpRange( new ScCellRangeObj( pDoc, *aCellRanges.front() ) );
     240           2 :         xRange = new ScVbaRange( xParent, xContext, xTmpRange );
     241             :     }
     242             :     else
     243             :     {
     244           5 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDoc, aCellRanges ) );
     245           5 :         xRange = new ScVbaRange( xParent, xContext, xRanges );
     246             :     }
     247             :     }
     248          14 :     return xRange;
     249             : }
     250             : 
     251         362 : ScCellRangesBase* ScVbaRange::getCellRangesBase() throw ( uno::RuntimeException )
     252             : {
     253         362 :     if( mxRanges.is() )
     254          36 :         return ScCellRangesBase::getImplementation( mxRanges );
     255         326 :     if( mxRange.is() )
     256         326 :         return ScCellRangesBase::getImplementation( mxRange );
     257           0 :     throw uno::RuntimeException("General Error creating range - Unknown" );
     258             : }
     259             : 
     260          10 : ScCellRangeObj* ScVbaRange::getCellRangeObj() throw ( uno::RuntimeException )
     261             : {
     262          10 :     return dynamic_cast< ScCellRangeObj* >( getCellRangesBase() );
     263             : }
     264             : 
     265          29 : SfxItemSet*  ScVbaRange::getCurrentDataSet( ) throw ( uno::RuntimeException )
     266             : {
     267          29 :     SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( getCellRangesBase() );
     268          29 :     if ( !pDataSet )
     269           0 :         throw uno::RuntimeException("Can't access Itemset for range" );
     270          29 :     return pDataSet;
     271             : }
     272             : 
     273         643 : void ScVbaRange::fireChangeEvent()
     274             : {
     275         643 :     if( ScVbaApplication::getDocumentEventsEnabled() )
     276             :     {
     277         621 :         ScDocument& rDoc = getScDocument();
     278         621 :         uno::Reference< script::vba::XVBAEventProcessor > xVBAEvents = rDoc.GetVbaEventProcessor();
     279         621 :         if( xVBAEvents.is() ) try
     280             :         {
     281         621 :             uno::Sequence< uno::Any > aArgs( 1 );
     282         621 :             aArgs[ 0 ] <<= uno::Reference< excel::XRange >( this );
     283         621 :             xVBAEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_CHANGE, aArgs );
     284             :         }
     285           0 :         catch( uno::Exception& )
     286             :         {
     287         621 :         }
     288             :     }
     289         643 : }
     290             : 
     291           0 : class SingleRangeEnumeration : public EnumerationHelper_BASE
     292             : {
     293             :     uno::Reference< XHelperInterface > m_xParent;
     294             :     uno::Reference< table::XCellRange > m_xRange;
     295             :     uno::Reference< uno::XComponentContext > mxContext;
     296             :     bool bHasMore;
     297             : public:
     298             : 
     299           0 :     SingleRangeEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException ) : m_xParent( xParent ), m_xRange( xRange ), mxContext( xContext ), bHasMore( true ) { }
     300           0 :     virtual sal_Bool SAL_CALL hasMoreElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return bHasMore; }
     301           0 :     virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     302             :     {
     303           0 :         if ( !bHasMore )
     304           0 :             throw container::NoSuchElementException();
     305           0 :         bHasMore = false;
     306           0 :         return uno::makeAny( m_xRange );
     307             :     }
     308             : };
     309             : 
     310             : // very simple class to pass to ScVbaCollectionBaseImpl containing
     311             : // just one item
     312             : typedef ::cppu::WeakImplHelper2< container::XIndexAccess, container::XEnumerationAccess > SingleRange_BASE;
     313             : 
     314        7018 : class SingleRangeIndexAccess : public SingleRange_BASE
     315             : {
     316             : private:
     317             :     uno::Reference< XHelperInterface > mxParent;
     318             :     uno::Reference< table::XCellRange > m_xRange;
     319             :     uno::Reference< uno::XComponentContext > mxContext;
     320             : 
     321             : public:
     322        3509 :     SingleRangeIndexAccess( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange ):mxParent( xParent ), m_xRange( xRange ), mxContext( xContext ) {}
     323             :     // XIndexAccess
     324        5036 :     virtual ::sal_Int32 SAL_CALL getCount() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return 1; }
     325         315 :     virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     326             :     {
     327         315 :         if ( Index != 0 )
     328           0 :             throw lang::IndexOutOfBoundsException();
     329         315 :         return uno::makeAny( m_xRange );
     330             :     }
     331             :         // XElementAccess
     332           0 :         virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return cppu::UnoType<table::XCellRange>::get(); }
     333             : 
     334           0 :         virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return sal_True; }
     335             :     // XEnumerationAccess
     336           0 :     virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return new SingleRangeEnumeration( mxParent, mxContext, m_xRange ); }
     337             : 
     338             : };
     339             : 
     340           0 : class RangesEnumerationImpl : public EnumerationHelperImpl
     341             : {
     342             :     bool mbIsRows;
     343             :     bool mbIsColumns;
     344             : public:
     345             : 
     346           0 :     RangesEnumerationImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XEnumeration >& xEnumeration, bool bIsRows, bool bIsColumns ) throw ( uno::RuntimeException ) : EnumerationHelperImpl( xParent, xContext, xEnumeration ), mbIsRows( bIsRows ), mbIsColumns( bIsColumns ) {}
     347           0 :     virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     348             :     {
     349           0 :         return lcl_makeRange( m_xParent, m_xContext, m_xEnumeration->nextElement(), mbIsRows, mbIsColumns );
     350             :     }
     351             : };
     352             : 
     353        7178 : class ScVbaRangeAreas : public ScVbaCollectionBaseImpl
     354             : {
     355             :     bool mbIsRows;
     356             :     bool mbIsColumns;
     357             : public:
     358        3589 :     ScVbaRangeAreas( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XIndexAccess >& xIndexAccess, bool bIsRows, bool bIsColumns ) : ScVbaCollectionBaseImpl( xParent, xContext, xIndexAccess ), mbIsRows( bIsRows ), mbIsColumns( bIsColumns ) {}
     359             : 
     360             :     // XEnumerationAccess
     361             :     virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration() throw (uno::RuntimeException) SAL_OVERRIDE;
     362             : 
     363             :     // XElementAccess
     364           0 :     virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException) SAL_OVERRIDE { return cppu::UnoType<excel::XRange>::get(); }
     365             : 
     366             :     virtual uno::Any createCollectionObject( const uno::Any& aSource ) SAL_OVERRIDE;
     367             : 
     368           0 :     virtual OUString getServiceImplName() SAL_OVERRIDE { return OUString(); }
     369             : 
     370           0 :     virtual uno::Sequence< OUString > getServiceNames() SAL_OVERRIDE { return uno::Sequence< OUString >(); }
     371             : 
     372             : };
     373             : 
     374             : uno::Reference< container::XEnumeration > SAL_CALL
     375           0 : ScVbaRangeAreas::createEnumeration() throw (uno::RuntimeException)
     376             : {
     377           0 :     uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
     378           0 :     return new RangesEnumerationImpl( mxParent, mxContext, xEnumAccess->createEnumeration(), mbIsRows, mbIsColumns );
     379             : }
     380             : 
     381             : uno::Any
     382         682 : ScVbaRangeAreas::createCollectionObject( const uno::Any& aSource )
     383             : {
     384         682 :     return lcl_makeRange( mxParent, mxContext, aSource, mbIsRows, mbIsColumns );
     385             : }
     386             : 
     387             : // assume that xIf is infact a ScCellRangesBase
     388             : ScDocShell*
     389       10944 : getDocShellFromIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException )
     390             : {
     391       10944 :         ScCellRangesBase* pUno = ScCellRangesBase::getImplementation( xIf );
     392       10944 :         if ( !pUno )
     393           0 :             throw uno::RuntimeException("Failed to access underlying uno range object"  );
     394       10944 :         return pUno->GetDocShell();
     395             : }
     396             : 
     397             : ScDocShell*
     398        2361 : getDocShellFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
     399             : {
     400             :         // need the ScCellRangesBase to get docshell
     401        2361 :     uno::Reference< uno::XInterface > xIf( xRange );
     402        2361 :         return getDocShellFromIf(xIf );
     403             : }
     404             : 
     405             : ScDocShell*
     406           3 : getDocShellFromRanges( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
     407             : {
     408             :     // need the ScCellRangesBase to get docshell
     409           3 :     uno::Reference< uno::XInterface > xIf( xRanges );
     410           3 :     return getDocShellFromIf(xIf );
     411             : }
     412             : 
     413        8580 : uno::Reference< frame::XModel > getModelFromXIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException )
     414             : {
     415        8580 :         ScDocShell* pDocShell = getDocShellFromIf(xIf );
     416        8580 :         return pDocShell->GetModel();
     417             : }
     418             : 
     419        8484 : uno::Reference< frame::XModel > getModelFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
     420             : {
     421             :     // the XInterface for getImplementation can be any derived interface, no need for queryInterface
     422        8484 :     uno::Reference< uno::XInterface > xIf( xRange );
     423        8484 :         return getModelFromXIf( xIf );
     424             : }
     425             : 
     426             : ScDocument&
     427        1031 : getDocumentFromRange( const uno::Reference< table::XCellRange >& xRange )
     428             : {
     429        1031 :         ScDocShell* pDocShell = getDocShellFromRange( xRange );
     430        1031 :         if ( !pDocShell )
     431           0 :             throw uno::RuntimeException("Failed to access underlying docshell from uno range object" );
     432        1031 :     ScDocument& rDoc = pDocShell->GetDocument();
     433        1031 :     return rDoc;
     434             : }
     435             : 
     436             : ScDocument&
     437         730 : ScVbaRange::getScDocument() throw (uno::RuntimeException)
     438             : {
     439         730 :     if ( mxRanges.is() )
     440             :     {
     441          15 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
     442          30 :         uno::Reference< table::XCellRange > xRange( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
     443          30 :         return getDocumentFromRange( xRange );
     444             :     }
     445         715 :     return getDocumentFromRange( mxRange );
     446             : }
     447             : 
     448             : ScDocShell*
     449        1323 : ScVbaRange::getScDocShell() throw (uno::RuntimeException)
     450             : {
     451        1323 :     if ( mxRanges.is() )
     452             :     {
     453           2 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
     454           4 :         uno::Reference< table::XCellRange > xRange( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
     455           4 :         return getDocShellFromRange( xRange );
     456             :     }
     457        1321 :     return getDocShellFromRange( mxRange );
     458             : }
     459             : 
     460         310 : ScVbaRange* ScVbaRange::getImplementation( const uno::Reference< excel::XRange >& rxRange )
     461             : {
     462             :     // FIXME: always save to use dynamic_cast? Or better to (implement and) use XTunnel?
     463         310 :     return dynamic_cast< ScVbaRange* >( rxRange.get() );
     464             : }
     465             : 
     466           1 : uno::Reference< frame::XModel > ScVbaRange::getUnoModel() throw (uno::RuntimeException)
     467             : {
     468           1 :     if( ScDocShell* pDocShell = getScDocShell() )
     469           2 :         return pDocShell->GetModel();
     470           0 :     throw uno::RuntimeException();
     471             : }
     472             : 
     473           0 : uno::Reference< frame::XModel > ScVbaRange::getUnoModel( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
     474             : {
     475           0 :     if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) )
     476           0 :         return pScVbaRange->getUnoModel();
     477           0 :     throw uno::RuntimeException();
     478             : }
     479             : 
     480           1 : const ScRangeList& ScVbaRange::getScRangeList() throw (uno::RuntimeException)
     481             : {
     482           1 :     if( ScCellRangesBase* pScRangesBase = getCellRangesBase() )
     483           2 :         return pScRangesBase->GetRangeList();
     484           0 :     throw uno::RuntimeException("Cannot obtain UNO range implementation object" );
     485             : }
     486             : 
     487           0 : const ScRangeList& ScVbaRange::getScRangeList( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
     488             : {
     489           0 :     if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) )
     490           0 :         return pScVbaRange->getScRangeList();
     491           0 :     throw uno::RuntimeException("Cannot obtain VBA range implementation object" );
     492             : }
     493             : 
     494        4897 : class NumFormatHelper
     495             : {
     496             :     uno::Reference< util::XNumberFormatsSupplier > mxSupplier;
     497             :     uno::Reference< beans::XPropertySet > mxRangeProps;
     498             :     uno::Reference< util::XNumberFormats > mxFormats;
     499             : public:
     500        4897 :     NumFormatHelper( const uno::Reference< table::XCellRange >& xRange )
     501        4897 :     {
     502        4897 :         mxSupplier.set( getModelFromRange( xRange ), uno::UNO_QUERY_THROW );
     503        4897 :         mxRangeProps.set( xRange, uno::UNO_QUERY_THROW);
     504        4897 :         mxFormats = mxSupplier->getNumberFormats();
     505        4897 :     }
     506        7416 :     uno::Reference< beans::XPropertySet > getNumberProps()
     507             :     {
     508        7416 :         long nIndexKey = 0;
     509        7416 :         uno::Any aValue = mxRangeProps->getPropertyValue( "NumberFormat" );
     510        7416 :         aValue >>= nIndexKey;
     511             : 
     512        7416 :         if ( mxFormats.is() )
     513        7416 :             return  mxFormats->getByKey( nIndexKey );
     514           0 :         return  uno::Reference< beans::XPropertySet > ();
     515             :     }
     516             : 
     517        4890 :     bool isBooleanType()
     518             :     {
     519             : 
     520        4890 :         if ( getNumberFormat() & util::NumberFormat::LOGICAL )
     521           3 :             return true;
     522        4887 :         return false;
     523             :     }
     524             : 
     525        2521 :     bool isDateType()
     526             :     {
     527        2521 :         sal_Int16 nType = getNumberFormat();
     528        2521 :         if(( nType & util::NumberFormat::DATETIME ))
     529             :         {
     530           0 :             return true;
     531             :         }
     532        2521 :         return false;
     533             :     }
     534             : 
     535           3 :     OUString getNumberFormatString()
     536             :     {
     537           3 :         uno::Reference< uno::XInterface > xIf( mxRangeProps, uno::UNO_QUERY_THROW );
     538           3 :         ScCellRangesBase* pUnoCellRange = ScCellRangesBase::getImplementation( xIf );
     539           3 :         if ( pUnoCellRange )
     540             :         {
     541             : 
     542           3 :             SfxItemSet* pDataSet =  excel::ScVbaCellRangeAccess::GetDataSet( pUnoCellRange );
     543           3 :             SfxItemState eState = pDataSet->GetItemState( ATTR_VALUE_FORMAT, true, NULL);
     544             :             // one of the cells in the range is not like the other ;-)
     545             :             // so return a zero length format to indicate that
     546           3 :             if ( eState == SfxItemState::DONTCARE )
     547           1 :                 return OUString();
     548             :         }
     549             : 
     550           4 :         uno::Reference< beans::XPropertySet > xNumberProps( getNumberProps(), uno::UNO_QUERY_THROW );
     551           4 :         OUString aFormatString;
     552           4 :         uno::Any aString = xNumberProps->getPropertyValue( "FormatString" );
     553           2 :         aString >>= aFormatString;
     554           5 :         return aFormatString;
     555             :     }
     556             : 
     557        7411 :     sal_Int16 getNumberFormat()
     558             :     {
     559        7411 :         uno::Reference< beans::XPropertySet > xNumberProps = getNumberProps();
     560             :         sal_Int16 nType = ::comphelper::getINT16(
     561        7411 :             xNumberProps->getPropertyValue( "Type" ) );
     562        7411 :         return nType;
     563             :     }
     564             : 
     565           3 :     bool setNumberFormat( const OUString& rFormat )
     566             :     {
     567             :         // #163288# treat "General" as "Standard" format
     568           3 :         sal_Int32 nNewIndex = 0;
     569           3 :         if( !rFormat.equalsIgnoreAsciiCase( "General" ) )
     570             :         {
     571           1 :             lang::Locale aLocale;
     572           2 :             uno::Reference< beans::XPropertySet > xNumProps = getNumberProps();
     573           1 :             xNumProps->getPropertyValue( "Locale" ) >>= aLocale;
     574           1 :             nNewIndex = mxFormats->queryKey( rFormat, aLocale, false );
     575           1 :             if ( nNewIndex == -1 ) // format not defined
     576           1 :                 nNewIndex = mxFormats->addNew( rFormat, aLocale );
     577             :         }
     578           3 :         mxRangeProps->setPropertyValue( "NumberFormat", uno::makeAny( nNewIndex ) );
     579           3 :         return true;
     580             :     }
     581             : 
     582           2 :     bool setNumberFormat( sal_Int16 nType )
     583             :     {
     584           2 :         uno::Reference< beans::XPropertySet > xNumberProps = getNumberProps();
     585           4 :         lang::Locale aLocale;
     586           2 :         xNumberProps->getPropertyValue( "Locale" ) >>= aLocale;
     587           4 :         uno::Reference<util::XNumberFormatTypes> xTypes( mxFormats, uno::UNO_QUERY );
     588           2 :         if ( xTypes.is() )
     589             :         {
     590           2 :             sal_Int32 nNewIndex = xTypes->getStandardFormat( nType, aLocale );
     591           2 :                mxRangeProps->setPropertyValue( "NumberFormat", uno::makeAny( nNewIndex ) );
     592           2 :             return true;
     593             :         }
     594           2 :         return false;
     595             :     }
     596             : 
     597             : };
     598             : 
     599             : struct CellPos
     600             : {
     601         269 :     CellPos( sal_Int32 nRow, sal_Int32 nCol, sal_Int32 nArea ):m_nRow(nRow), m_nCol(nCol), m_nArea( nArea ) {};
     602             : sal_Int32 m_nRow;
     603             : sal_Int32 m_nCol;
     604             : sal_Int32 m_nArea;
     605             : };
     606             : 
     607             : typedef ::cppu::WeakImplHelper1< container::XEnumeration > CellsEnumeration_BASE;
     608             : typedef ::std::vector< CellPos > vCellPos;
     609             : 
     610             : // #FIXME - QUICK
     611             : // we could probably could and should modify CellsEnumeration below
     612             : // to handle rows and columns ( but I do this separately for now
     613             : // and.. this class only handles singe areas ( does it have to handle
     614             : // multi area ranges?? )
     615           0 : class ColumnsRowEnumeration: public CellsEnumeration_BASE
     616             : {
     617             :     uno::Reference< uno::XComponentContext > mxContext;
     618             :         uno::Reference< excel::XRange > mxRange;
     619             :     sal_Int32 mMaxElems;
     620             :     sal_Int32 mCurElem;
     621             : 
     622             : public:
     623           0 :     ColumnsRowEnumeration( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< excel::XRange >& xRange, sal_Int32 nElems ) : mxContext( xContext ), mxRange( xRange ), mMaxElems( nElems ), mCurElem( 0 )
     624             :         {
     625           0 :     }
     626             : 
     627           0 :     virtual sal_Bool SAL_CALL hasMoreElements() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return mCurElem < mMaxElems; }
     628             : 
     629           0 :     virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     630             :     {
     631           0 :         if ( !hasMoreElements() )
     632           0 :             throw container::NoSuchElementException();
     633           0 :         sal_Int32 vbaIndex = 1 + mCurElem++;
     634           0 :         return uno::makeAny( mxRange->Item( uno::makeAny( vbaIndex ), uno::Any() ) );
     635             :     }
     636             : };
     637             : 
     638          36 : class CellsEnumeration : public CellsEnumeration_BASE
     639             : {
     640             :     uno::WeakReference< XHelperInterface > mxParent;
     641             :     uno::Reference< uno::XComponentContext > mxContext;
     642             :     uno::Reference< XCollection > m_xAreas;
     643             :     vCellPos m_CellPositions;
     644             :     vCellPos::const_iterator m_it;
     645             : 
     646         287 :     uno::Reference< table::XCellRange > getArea( sal_Int32 nVBAIndex ) throw ( uno::RuntimeException )
     647             :     {
     648         287 :         if ( nVBAIndex < 1 || nVBAIndex > m_xAreas->getCount() )
     649           0 :             throw uno::RuntimeException();
     650         287 :         uno::Reference< excel::XRange > xRange( m_xAreas->Item( uno::makeAny(nVBAIndex), uno::Any() ), uno::UNO_QUERY_THROW );
     651         287 :         uno::Reference< table::XCellRange > xCellRange( ScVbaRange::getCellRange( xRange ), uno::UNO_QUERY_THROW );
     652         287 :         return xCellRange;
     653             :     }
     654             : 
     655          18 :     void populateArea( sal_Int32 nVBAIndex )
     656             :     {
     657          18 :         uno::Reference< table::XCellRange > xRange = getArea( nVBAIndex );
     658          36 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW );
     659          18 :         sal_Int32 nRowCount =  xColumnRowRange->getRows()->getCount();
     660          18 :         sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
     661         113 :         for ( sal_Int32 i=0; i<nRowCount; ++i )
     662             :         {
     663         364 :             for ( sal_Int32 j=0; j<nColCount; ++j )
     664         269 :                 m_CellPositions.push_back( CellPos( i,j,nVBAIndex ) );
     665          18 :         }
     666          18 :     }
     667             : public:
     668          18 :     CellsEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< XCollection >& xAreas ): mxParent( xParent ), mxContext( xContext ), m_xAreas( xAreas )
     669             :     {
     670          18 :         sal_Int32 nItems = m_xAreas->getCount();
     671          36 :         for ( sal_Int32 index=1; index <= nItems; ++index )
     672             :         {
     673          18 :                 populateArea( index );
     674             :         }
     675          18 :         m_it = m_CellPositions.begin();
     676          18 :     }
     677         556 :     virtual sal_Bool SAL_CALL hasMoreElements() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return m_it != m_CellPositions.end(); }
     678             : 
     679         269 :     virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     680             :     {
     681         269 :         if ( !hasMoreElements() )
     682           0 :             throw container::NoSuchElementException();
     683         269 :         CellPos aPos = *(m_it)++;
     684             : 
     685         269 :         uno::Reference< table::XCellRange > xRangeArea = getArea( aPos.m_nArea );
     686         538 :         uno::Reference< table::XCellRange > xCellRange( xRangeArea->getCellByPosition(  aPos.m_nCol, aPos.m_nRow ), uno::UNO_QUERY_THROW );
     687         538 :         return uno::makeAny( uno::Reference< excel::XRange >( new ScVbaRange( mxParent, mxContext, xCellRange ) ) );
     688             : 
     689             :     }
     690             : };
     691             : 
     692             : static const char ISVISIBLE[] = "IsVisible";
     693             : static const char POSITION[] = "Position";
     694             : static const char EQUALS[] = "=";
     695             : static const char NOTEQUALS[] = "<>";
     696             : static const char GREATERTHAN[] = ">";
     697             : static const char GREATERTHANEQUALS[] = ">=";
     698             : static const char LESSTHAN[] = "<";
     699             : static const char LESSTHANEQUALS[] = "<=";
     700             : static const char CONTS_HEADER[] = "ContainsHeader";
     701             : static const char INSERTPAGEBREAKS[] = "InsertPageBreaks";
     702             : static const char STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY[] = "The command you chose cannot be performed with multiple selections.\nSelect a single range and click the command again";
     703             : static const char STR_ERRORMESSAGE_NOCELLSWEREFOUND[] = "No cells were found";
     704             : static const char CELLSTYLE[] = "CellStyle";
     705             : 
     706         302 : class CellValueSetter : public ValueSetter
     707             : {
     708             : protected:
     709             :     uno::Any maValue;
     710             : public:
     711             :     CellValueSetter( const uno::Any& aValue );
     712             :     virtual bool processValue( const uno::Any& aValue,  const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     713             :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     714             : 
     715             : };
     716             : 
     717         302 : CellValueSetter::CellValueSetter( const uno::Any& aValue ): maValue( aValue ) {}
     718             : 
     719             : void
     720        3924 : CellValueSetter::visitNode( sal_Int32 /*i*/, sal_Int32 /*j*/, const uno::Reference< table::XCell >& xCell )
     721             : {
     722        3924 :     processValue( maValue, xCell );
     723        3924 : }
     724             : 
     725             : bool
     726        3902 : CellValueSetter::processValue( const uno::Any& aValue, const uno::Reference< table::XCell >& xCell )
     727             : {
     728             : 
     729        3902 :     bool isExtracted = false;
     730        3902 :     switch ( aValue.getValueTypeClass() )
     731             :     {
     732             :         case  uno::TypeClass_BOOLEAN:
     733             :         {
     734           2 :             bool bState = false;
     735           2 :             if ( aValue >>= bState   )
     736             :             {
     737           2 :                 uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     738           2 :                 if ( bState )
     739           2 :                     xCell->setValue( (double) 1 );
     740             :                 else
     741           0 :                     xCell->setValue( (double) 0 );
     742           4 :                 NumFormatHelper cellNumFormat( xRange );
     743           4 :                 cellNumFormat.setNumberFormat( util::NumberFormat::LOGICAL );
     744             :             }
     745           2 :             break;
     746             :         }
     747             :         case uno::TypeClass_STRING:
     748             :         {
     749        1530 :             OUString aString;
     750        1530 :             if ( aValue >>= aString )
     751             :             {
     752             :                 // The required behavior for a string value is:
     753             :                 // 1. If the first character is a single quote, use the rest as a string cell, regardless of the cell's number format.
     754             :                 // 2. Otherwise, if the cell's number format is "text", use the string value as a string cell.
     755             :                 // 3. Otherwise, parse the string value in English locale, and apply a corresponding number format with the cell's locale
     756             :                 //    if the cell's number format was "General".
     757             :                 // Case 1 is handled here, the rest in ScCellObj::InputEnglishString
     758             : 
     759        1530 :                 if ( aString.toChar() == '\'' )     // case 1 - handle with XTextRange
     760             :                 {
     761           0 :                     OUString aRemainder( aString.copy(1) );    // strip the quote
     762           0 :                     uno::Reference< text::XTextRange > xTextRange( xCell, uno::UNO_QUERY_THROW );
     763           0 :                     xTextRange->setString( aRemainder );
     764             :                 }
     765             :                 else
     766             :                 {
     767             :                     // call implementation method InputEnglishString
     768        1530 :                     ScCellObj* pCellObj = dynamic_cast< ScCellObj* >( xCell.get() );
     769        1530 :                     if ( pCellObj )
     770        1530 :                         pCellObj->InputEnglishString( aString );
     771             :                 }
     772             :             }
     773             :             else
     774           0 :                 isExtracted = false;
     775        1530 :             break;
     776             :         }
     777             :         default:
     778             :         {
     779        2370 :             double nDouble = 0.0;
     780        2370 :             if ( aValue >>= nDouble )
     781             :             {
     782        2367 :                 uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     783        4734 :                 NumFormatHelper cellFormat( xRange );
     784             :                 // If we are setting a number and the cell types was logical
     785             :                 // then we need to reset the logical format. ( see case uno::TypeClass_BOOLEAN:
     786             :                 // handling above )
     787        2367 :                 if ( cellFormat.isBooleanType() )
     788           1 :                     cellFormat.setNumberFormat("General");
     789        4734 :                 xCell->setValue( nDouble );
     790             :             }
     791             :             else
     792           3 :                 isExtracted = false;
     793        2370 :             break;
     794             :         }
     795             :     }
     796        3902 :     return isExtracted;
     797             : 
     798             : }
     799             : 
     800         630 : class CellValueGetter : public ValueGetter
     801             : {
     802             : protected:
     803             :     uno::Any maValue;
     804             : public:
     805         630 :     CellValueGetter() {}
     806             :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     807             :     virtual void processValue( sal_Int32 x, sal_Int32 y, const uno::Any& aValue ) SAL_OVERRIDE;
     808        4005 :     const uno::Any& getValue() const SAL_OVERRIDE { return maValue; }
     809             : 
     810             : };
     811             : 
     812             : void
     813        4005 : CellValueGetter::processValue(  sal_Int32 /*x*/, sal_Int32 /*y*/, const uno::Any& aValue )
     814             : {
     815        4005 :     maValue = aValue;
     816        4005 : }
     817        3941 : void CellValueGetter::visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell )
     818             : {
     819        3941 :     uno::Any aValue;
     820        3941 :     table::CellContentType eType = xCell->getType();
     821        3941 :     if( eType == table::CellContentType_VALUE || eType == table::CellContentType_FORMULA )
     822             :     {
     823        2552 :         if ( eType == table::CellContentType_FORMULA )
     824             :         {
     825             : 
     826          29 :             OUString sFormula = xCell->getFormula();
     827          29 :             if ( sFormula == "=TRUE()" )
     828           0 :                 aValue <<= sal_True;
     829          29 :             else if ( sFormula == "=FALSE()" )
     830           0 :                 aValue <<= false;
     831             :             else
     832             :             {
     833          29 :                 uno::Reference< beans::XPropertySet > xProp( xCell, uno::UNO_QUERY_THROW );
     834             : 
     835          29 :                 table::CellContentType eFormulaType = table::CellContentType_VALUE;
     836             :                 // some formulas give textual results
     837          29 :                 xProp->getPropertyValue( "FormulaResultType" ) >>= eFormulaType;
     838             : 
     839          29 :                 if ( eFormulaType == table::CellContentType_TEXT )
     840             :                 {
     841           4 :                     uno::Reference< text::XTextRange > xTextRange(xCell, ::uno::UNO_QUERY_THROW);
     842           4 :                     aValue <<= xTextRange->getString();
     843             :                 }
     844             :                 else
     845          25 :                     aValue <<= xCell->getValue();
     846          29 :             }
     847             :         }
     848             :         else
     849             :         {
     850        2523 :             uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     851        5046 :             NumFormatHelper cellFormat( xRange );
     852        2523 :             if ( cellFormat.isBooleanType() )
     853           2 :                 aValue = uno::makeAny( ( xCell->getValue() != 0.0 ) );
     854        2521 :             else if ( cellFormat.isDateType() )
     855           0 :                 aValue = uno::makeAny( bridge::oleautomation::Date( xCell->getValue() ) );
     856             :             else
     857        5044 :                 aValue <<= xCell->getValue();
     858             :         }
     859             :     }
     860        3941 :     if( eType == table::CellContentType_TEXT )
     861             :     {
     862         107 :         uno::Reference< text::XTextRange > xTextRange(xCell, ::uno::UNO_QUERY_THROW);
     863         107 :         aValue <<= xTextRange->getString();
     864             :     }
     865        3941 :     processValue( x,y,aValue );
     866        3941 : }
     867             : 
     868          15 : class CellFormulaValueSetter : public CellValueSetter
     869             : {
     870             : private:
     871             :     ScDocument*  m_pDoc;
     872             :     formula::FormulaGrammar::Grammar m_eGrammar;
     873             : public:
     874          15 :     CellFormulaValueSetter( const uno::Any& aValue, ScDocument* pDoc, formula::FormulaGrammar::Grammar eGram ):CellValueSetter( aValue ),  m_pDoc( pDoc ), m_eGrammar( eGram ){}
     875             : protected:
     876          66 :     bool processValue( const uno::Any& aValue, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     877             :     {
     878          66 :         OUString sFormula;
     879          66 :         double aDblValue = 0.0;
     880          66 :         if ( aValue >>= sFormula )
     881             :         {
     882             :             // convert to GRAM_PODF_A1 style grammar because XCell::setFormula
     883             :             // always compile it in that grammar. Perhaps
     884             :             // css.sheet.FormulaParser should be used in future to directly
     885             :             // pass formula tokens when that API stabilizes.
     886          66 :             if ( m_eGrammar != formula::FormulaGrammar::GRAM_PODF_A1 && ( sFormula.trim().startsWith("=") ) )
     887             :             {
     888          63 :                 uno::Reference< uno::XInterface > xIf( xCell, uno::UNO_QUERY_THROW );
     889          63 :                 ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() );
     890          63 :                 if ( pUnoRangesBase )
     891             :                 {
     892          63 :                     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
     893         126 :                     ScCompiler aCompiler( m_pDoc, aCellRanges.front()->aStart );
     894          63 :                     aCompiler.SetGrammar(m_eGrammar);
     895             :                     // compile the string in the format passed in
     896         126 :                     boost::scoped_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula));
     897             :                     // set desired convention to that of the document
     898          63 :                     aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_PODF_A1 );
     899         126 :                     OUString sConverted;
     900          63 :                     aCompiler.CreateStringFromTokenArray(sConverted);
     901         126 :                     sFormula = EQUALS + sConverted;
     902          63 :                 }
     903             :             }
     904             : 
     905          66 :             xCell->setFormula( sFormula );
     906          66 :             return true;
     907             :         }
     908           0 :         else if ( aValue >>= aDblValue )
     909             :         {
     910           0 :             xCell->setValue( aDblValue );
     911           0 :             return true;
     912             :         }
     913           0 :         return false;
     914             :     }
     915             : 
     916             : };
     917             : 
     918          47 : class CellFormulaValueGetter : public CellValueGetter
     919             : {
     920             : private:
     921             :     ScDocument*  m_pDoc;
     922             :     formula::FormulaGrammar::Grammar m_eGrammar;
     923             : public:
     924          47 :     CellFormulaValueGetter(ScDocument* pDoc, formula::FormulaGrammar::Grammar eGram ) : CellValueGetter( ), m_pDoc( pDoc ), m_eGrammar( eGram ) {}
     925          64 :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     926             :     {
     927          64 :         uno::Any aValue;
     928          64 :         aValue <<= xCell->getFormula();
     929         128 :         OUString sVal;
     930          64 :         aValue >>= sVal;
     931         128 :         uno::Reference< uno::XInterface > xIf( xCell, uno::UNO_QUERY_THROW );
     932          64 :         ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() );
     933          64 :         if ( ( xCell->getType() == table::CellContentType_FORMULA ) &&
     934             :             pUnoRangesBase )
     935             :         {
     936          25 :             ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
     937          50 :             ScCompiler aCompiler( m_pDoc, aCellRanges.front()->aStart );
     938          25 :             aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_DEFAULT);
     939          50 :             boost::scoped_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal));
     940             :             // set desired convention
     941          25 :             aCompiler.SetGrammar( m_eGrammar );
     942          50 :             OUString sConverted;
     943          25 :             aCompiler.CreateStringFromTokenArray(sConverted);
     944          25 :             sVal = EQUALS + sConverted;
     945          50 :             aValue <<= sVal;
     946             :         }
     947             : 
     948         128 :         processValue( x,y,aValue );
     949          64 :     }
     950             : 
     951             : };
     952             : 
     953          31 : class Dim2ArrayValueGetter : public ArrayVisitor
     954             : {
     955             : protected:
     956             :     uno::Any maValue;
     957             :     ValueGetter& mValueGetter;
     958        3406 :     void processValue( sal_Int32 x, sal_Int32 y, const uno::Any& aValue )
     959             :     {
     960        3406 :         uno::Sequence< uno::Sequence< uno::Any > >& aMatrix = *const_cast<css::uno::Sequence<css::uno::Sequence<css::uno::Any>> *>(static_cast<uno::Sequence< uno::Sequence< uno::Any > > const *>(maValue.getValue()));
     961        3406 :         aMatrix[x][y] = aValue;
     962        3406 :     }
     963             : 
     964             : public:
     965          31 :     Dim2ArrayValueGetter(sal_Int32 nRowCount, sal_Int32 nColCount, ValueGetter& rValueGetter ): mValueGetter(rValueGetter)
     966             :     {
     967          31 :         uno::Sequence< uno::Sequence< uno::Any > > aMatrix;
     968          31 :         aMatrix.realloc( nRowCount );
     969         144 :         for ( sal_Int32 index = 0; index < nRowCount; ++index )
     970         113 :             aMatrix[index].realloc( nColCount );
     971          31 :         maValue <<= aMatrix;
     972          31 :     }
     973        3406 :     void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     974             : 
     975             :     {
     976        3406 :         mValueGetter.visitNode( x, y, xCell );
     977        3406 :         processValue( x, y, mValueGetter.getValue() );
     978        3406 :     }
     979          31 :     const uno::Any& getValue() const { return maValue; }
     980             : 
     981             : };
     982             : 
     983             : static const char sNA[] = "#N/A";
     984             : 
     985           3 : class Dim1ArrayValueSetter : public ArrayVisitor
     986             : {
     987             :     uno::Sequence< uno::Any > aMatrix;
     988             :     sal_Int32 nColCount;
     989             :     ValueSetter& mCellValueSetter;
     990             : public:
     991           3 :     Dim1ArrayValueSetter( const uno::Any& aValue, ValueSetter& rCellValueSetter ):mCellValueSetter( rCellValueSetter )
     992             :     {
     993           3 :         aValue >>= aMatrix;
     994           3 :         nColCount = aMatrix.getLength();
     995           3 :     }
     996          20 :     virtual void visitNode( sal_Int32 /*x*/, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     997             :     {
     998          20 :         if ( y < nColCount )
     999          20 :             mCellValueSetter.processValue( aMatrix[ y ], xCell );
    1000             :         else
    1001           0 :             mCellValueSetter.processValue( uno::makeAny( OUString(sNA) ), xCell );
    1002          20 :     }
    1003             : };
    1004             : 
    1005           2 : class Dim2ArrayValueSetter : public ArrayVisitor
    1006             : {
    1007             :     uno::Sequence< uno::Sequence< uno::Any > > aMatrix;
    1008             :     ValueSetter& mCellValueSetter;
    1009             :     sal_Int32 nRowCount;
    1010             :     sal_Int32 nColCount;
    1011             : public:
    1012           2 :     Dim2ArrayValueSetter( const uno::Any& aValue, ValueSetter& rCellValueSetter ) : mCellValueSetter( rCellValueSetter )
    1013             :     {
    1014           2 :         aValue >>= aMatrix;
    1015           2 :         nRowCount = aMatrix.getLength();
    1016           2 :         nColCount = aMatrix[0].getLength();
    1017           2 :     }
    1018             : 
    1019          24 :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
    1020             :     {
    1021          24 :         if ( x < nRowCount && y < nColCount )
    1022          24 :             mCellValueSetter.processValue( aMatrix[ x ][ y ], xCell );
    1023             :         else
    1024           0 :             mCellValueSetter.processValue( uno::makeAny( OUString(sNA) ), xCell );
    1025             : 
    1026          24 :     }
    1027             : };
    1028             : 
    1029          21 : class RangeProcessor
    1030             : {
    1031             : public:
    1032             :     virtual void process( const uno::Reference< excel::XRange >& xRange ) = 0;
    1033             : 
    1034             : protected:
    1035          21 :     ~RangeProcessor() {}
    1036             : };
    1037             : 
    1038             : class RangeValueProcessor : public RangeProcessor
    1039             : {
    1040             :     const uno::Any& m_aVal;
    1041             : public:
    1042           9 :     RangeValueProcessor( const uno::Any& rVal ):m_aVal( rVal ) {}
    1043           9 :     virtual ~RangeValueProcessor() {}
    1044          18 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1045             :     {
    1046          18 :         xRange->setValue( m_aVal );
    1047          18 :     }
    1048             : };
    1049             : 
    1050             : class RangeFormulaProcessor : public RangeProcessor
    1051             : {
    1052             :     const uno::Any& m_aVal;
    1053             : public:
    1054           1 :     RangeFormulaProcessor( const uno::Any& rVal ):m_aVal( rVal ) {}
    1055           1 :     virtual ~RangeFormulaProcessor() {}
    1056           2 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1057             :     {
    1058           2 :         xRange->setFormula( m_aVal );
    1059           2 :     }
    1060             : };
    1061             : 
    1062             : class RangeCountProcessor : public RangeProcessor
    1063             : {
    1064             :     sal_Int32 nCount;
    1065             : public:
    1066          11 :     RangeCountProcessor():nCount(0){}
    1067          11 :     virtual ~RangeCountProcessor() {}
    1068          25 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1069             :     {
    1070          25 :         nCount = nCount + xRange->getCount();
    1071          25 :     }
    1072          11 :     sal_Int32 value() { return nCount; }
    1073             : };
    1074          21 : class AreasVisitor
    1075             : {
    1076             : private:
    1077             :     uno::Reference< XCollection > m_Areas;
    1078             : public:
    1079          21 :     AreasVisitor( const uno::Reference< XCollection >& rAreas ):m_Areas( rAreas ){}
    1080             : 
    1081          21 :     void visit( RangeProcessor& processor )
    1082             :     {
    1083          21 :         if ( m_Areas.is() )
    1084             :         {
    1085          21 :             sal_Int32 nItems = m_Areas->getCount();
    1086          66 :             for ( sal_Int32 index=1; index <= nItems; ++index )
    1087             :             {
    1088          45 :                 uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1089          45 :                 processor.process( xRange );
    1090          45 :             }
    1091             :         }
    1092          21 :     }
    1093             : };
    1094             : 
    1095        2495 : class RangeHelper
    1096             : {
    1097             :     uno::Reference< table::XCellRange > m_xCellRange;
    1098             : 
    1099             : public:
    1100        2495 :     RangeHelper( const uno::Reference< table::XCellRange >& xCellRange ) throw (uno::RuntimeException) : m_xCellRange( xCellRange )
    1101             :     {
    1102        2495 :         if ( !m_xCellRange.is() )
    1103           0 :             throw uno::RuntimeException();
    1104        2495 :     }
    1105           0 :     RangeHelper( const uno::Any& rCellRange ) throw (uno::RuntimeException)
    1106           0 :     {
    1107           0 :         m_xCellRange.set(rCellRange, uno::UNO_QUERY_THROW);
    1108           0 :     }
    1109        1225 :     uno::Reference< sheet::XSheetCellRange > getSheetCellRange() throw (uno::RuntimeException)
    1110             :     {
    1111        1225 :         return uno::Reference< sheet::XSheetCellRange >(m_xCellRange, uno::UNO_QUERY_THROW);
    1112             :     }
    1113        1212 :     uno::Reference< sheet::XSpreadsheet >  getSpreadSheet() throw (uno::RuntimeException)
    1114             :     {
    1115        1212 :         return getSheetCellRange()->getSpreadsheet();
    1116             :     }
    1117             : 
    1118        1180 :     uno::Reference< table::XCellRange > getCellRangeFromSheet() throw (uno::RuntimeException)
    1119             :     {
    1120        1180 :         return uno::Reference< table::XCellRange >(getSpreadSheet(), uno::UNO_QUERY_THROW );
    1121             :     }
    1122             : 
    1123        1636 :     uno::Reference< sheet::XCellRangeAddressable >  getCellRangeAddressable() throw (uno::RuntimeException)
    1124             :     {
    1125        1636 :         return uno::Reference< sheet::XCellRangeAddressable >(m_xCellRange, ::uno::UNO_QUERY_THROW);
    1126             : 
    1127             :     }
    1128             : 
    1129          13 :     uno::Reference< sheet::XSheetCellCursor > getSheetCellCursor() throw ( uno::RuntimeException )
    1130             :     {
    1131          13 :         return  uno::Reference< sheet::XSheetCellCursor >( getSpreadSheet()->createCursorByRange( getSheetCellRange() ), uno::UNO_QUERY_THROW );
    1132             :     }
    1133             : 
    1134           8 :     static uno::Reference< excel::XRange > createRangeFromRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference<uno::XComponentContext >& xContext,
    1135             :         const uno::Reference< table::XCellRange >& xRange, const uno::Reference< sheet::XCellRangeAddressable >& xCellRangeAddressable,
    1136             :         sal_Int32 nStartColOffset = 0, sal_Int32 nStartRowOffset = 0, sal_Int32 nEndColOffset = 0, sal_Int32 nEndRowOffset = 0 )
    1137             :     {
    1138             :         return uno::Reference< excel::XRange >( new ScVbaRange( xParent, xContext,
    1139           8 :             xRange->getCellRangeByPosition(
    1140           8 :                 xCellRangeAddressable->getRangeAddress().StartColumn + nStartColOffset,
    1141           8 :                 xCellRangeAddressable->getRangeAddress().StartRow + nStartRowOffset,
    1142           8 :                 xCellRangeAddressable->getRangeAddress().EndColumn + nEndColOffset,
    1143          32 :                 xCellRangeAddressable->getRangeAddress().EndRow + nEndRowOffset ) ) );
    1144             :     }
    1145             : 
    1146             : };
    1147             : 
    1148             : bool
    1149         883 : ScVbaRange::getCellRangesForAddress( sal_uInt16& rResFlags, const OUString& sAddress, ScDocShell* pDocSh, ScRangeList& rCellRanges, formula::FormulaGrammar::AddressConvention& eConv, char cDelimiter )
    1150             : {
    1151             : 
    1152         883 :     if ( pDocSh )
    1153             :     {
    1154         883 :         ScDocument& rDoc = pDocSh->GetDocument();
    1155         883 :         sal_uInt16 nMask = SCA_VALID;
    1156         883 :         rResFlags = rCellRanges.Parse( sAddress, &rDoc, nMask, eConv, 0, cDelimiter );
    1157         883 :         if ( rResFlags & SCA_VALID )
    1158             :         {
    1159         881 :             return true;
    1160             :         }
    1161             :     }
    1162           2 :     return false;
    1163             : }
    1164             : 
    1165         844 : bool getScRangeListForAddress( const OUString& sName, ScDocShell* pDocSh, ScRange& refRange, ScRangeList& aCellRanges, formula::FormulaGrammar::AddressConvention aConv ) throw ( uno::RuntimeException )
    1166             : {
    1167             :     // see if there is a match with a named range
    1168         844 :     uno::Reference< beans::XPropertySet > xProps( pDocSh->GetModel(), uno::UNO_QUERY_THROW );
    1169        1688 :     uno::Reference< container::XNameAccess > xNameAccess( xProps->getPropertyValue( "NamedRanges" ), uno::UNO_QUERY_THROW );
    1170             :     // Strangly enough you can have Range( "namedRange1, namedRange2, etc," )
    1171             :     // loop around each ',' separated name
    1172        1688 :     std::vector< OUString > vNames;
    1173         844 :     sal_Int32 nIndex = 0;
    1174         883 :     do
    1175             :     {
    1176         883 :         OUString aToken = sName.getToken( 0, ',', nIndex );
    1177         883 :         vNames.push_back( aToken );
    1178         883 :     } while ( nIndex >= 0 );
    1179             : 
    1180         844 :     if ( vNames.empty() )
    1181           0 :         vNames.push_back( sName );
    1182             : 
    1183         844 :     std::vector< OUString >::iterator it = vNames.begin();
    1184         844 :     std::vector< OUString >::iterator it_end = vNames.end();
    1185         881 :     for ( ; it != it_end; ++it )
    1186             :     {
    1187             : 
    1188         883 :         formula::FormulaGrammar::AddressConvention eConv = aConv;
    1189             :         // spaces are illegal ( but the user of course can enter them )
    1190         883 :         OUString sAddress = (*it).trim();
    1191             :         // if a local name ( on the active sheet ) exists this will
    1192             :         // take precedence over a global with the same name
    1193         883 :         if ( !xNameAccess->hasByName( sAddress ) )
    1194             :         {
    1195             :             // try a local name
    1196         864 :             ScDocument& rDoc = pDocSh->GetDocument();
    1197         864 :             SCTAB nCurTab = ScDocShell::GetCurTab();
    1198         864 :             ScRangeName* pRangeName = rDoc.GetRangeName(nCurTab);
    1199         864 :             if (pRangeName)
    1200             :             {
    1201         864 :                 bool bLocalName = pRangeName->findByUpperName(ScGlobal::pCharClass->uppercase(sAddress)) != NULL;
    1202             :                 // TODO: Handle local names correctly.
    1203             :                 (void)bLocalName;
    1204             :             }
    1205             :         }
    1206         883 :         char aChar = 0;
    1207         883 :         if ( xNameAccess->hasByName( sAddress ) )
    1208             :         {
    1209          19 :             uno::Reference< sheet::XNamedRange > xNamed( xNameAccess->getByName( sAddress ), uno::UNO_QUERY_THROW );
    1210          19 :             sAddress = xNamed->getContent();
    1211             :             // As the address comes from OOO, the addressing
    1212             :             // style is may not be XL_A1
    1213          19 :             eConv = pDocSh->GetDocument().GetAddressConvention();
    1214          19 :             aChar = ';';
    1215             :         }
    1216             : 
    1217         883 :         sal_uInt16 nFlags = 0;
    1218         883 :         if ( !ScVbaRange::getCellRangesForAddress( nFlags, sAddress, pDocSh, aCellRanges, eConv, aChar ) )
    1219           2 :             return false;
    1220             : 
    1221         881 :         bool bTabFromReferrer = !( nFlags & SCA_TAB_3D );
    1222             : 
    1223        1815 :         for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    1224             :         {
    1225         934 :             ScRange* pRange = aCellRanges[ i ];
    1226         934 :             pRange->aStart.SetCol( refRange.aStart.Col() + pRange->aStart.Col() );
    1227         934 :             pRange->aStart.SetRow( refRange.aStart.Row() + pRange->aStart.Row() );
    1228         934 :             pRange->aStart.SetTab( bTabFromReferrer ? refRange.aStart.Tab()  : pRange->aStart.Tab() );
    1229         934 :             pRange->aEnd.SetCol( refRange.aStart.Col() + pRange->aEnd.Col() );
    1230         934 :             pRange->aEnd.SetRow( refRange.aStart.Row() + pRange->aEnd.Row() );
    1231         934 :             pRange->aEnd.SetTab( bTabFromReferrer ? refRange.aEnd.Tab()  : pRange->aEnd.Tab() );
    1232             :         }
    1233         881 :     }
    1234        1686 :     return true;
    1235             : }
    1236             : 
    1237             : ScVbaRange*
    1238         844 : getRangeForName( const uno::Reference< uno::XComponentContext >& xContext, const OUString& sName, ScDocShell* pDocSh, table::CellRangeAddress& pAddr, formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( uno::RuntimeException )
    1239             : {
    1240         844 :     ScRangeList aCellRanges;
    1241         844 :     ScRange refRange;
    1242         844 :     ScUnoConversion::FillScRange( refRange, pAddr );
    1243         844 :     if ( !getScRangeListForAddress ( sName, pDocSh, refRange, aCellRanges, eConv ) )
    1244           2 :         throw uno::RuntimeException();
    1245             :     // Single range
    1246         842 :     if ( aCellRanges.size() == 1 )
    1247             :     {
    1248         804 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pDocSh, *aCellRanges.front() ) );
    1249        1608 :         uno::Reference< XHelperInterface > xFixThisParent = excel::getUnoSheetModuleObj( xRange );
    1250        1608 :         return new ScVbaRange( xFixThisParent, xContext, xRange );
    1251             :     }
    1252          76 :     uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDocSh, aCellRanges ) );
    1253             : 
    1254          76 :     uno::Reference< XHelperInterface > xFixThisParent = excel::getUnoSheetModuleObj( xRanges );
    1255         882 :     return new ScVbaRange( xFixThisParent, xContext, xRanges );
    1256             : }
    1257             : 
    1258             : namespace {
    1259             : 
    1260             : template< typename RangeType >
    1261        1545 : inline table::CellRangeAddress lclGetRangeAddress( const uno::Reference< RangeType >& rxCellRange ) throw (uno::RuntimeException)
    1262             : {
    1263        1545 :     return uno::Reference< sheet::XCellRangeAddressable >( rxCellRange, uno::UNO_QUERY_THROW )->getRangeAddress();
    1264             : }
    1265             : 
    1266           1 : void lclClearRange( const uno::Reference< table::XCellRange >& rxCellRange ) throw (uno::RuntimeException)
    1267             : {
    1268             :     using namespace ::com::sun::star::sheet::CellFlags;
    1269           1 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | ANNOTATION | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED;
    1270           1 :     uno::Reference< sheet::XSheetOperation > xSheetOperation( rxCellRange, uno::UNO_QUERY_THROW );
    1271           1 :     xSheetOperation->clearContents( nFlags );
    1272           1 : }
    1273             : 
    1274         251 : uno::Reference< sheet::XSheetCellRange > lclExpandToMerged( const uno::Reference< table::XCellRange >& rxCellRange, bool bRecursive ) throw (uno::RuntimeException)
    1275             : {
    1276         251 :     uno::Reference< sheet::XSheetCellRange > xNewCellRange( rxCellRange, uno::UNO_QUERY_THROW );
    1277         502 :     uno::Reference< sheet::XSpreadsheet > xSheet( xNewCellRange->getSpreadsheet(), uno::UNO_SET_THROW );
    1278         251 :     table::CellRangeAddress aNewAddress = lclGetRangeAddress( xNewCellRange );
    1279         251 :     table::CellRangeAddress aOldAddress;
    1280             :     // expand as long as there are new merged ranges included
    1281         251 :     do
    1282             :     {
    1283         251 :         aOldAddress = aNewAddress;
    1284         251 :         uno::Reference< sheet::XSheetCellCursor > xCursor( xSheet->createCursorByRange( xNewCellRange ), uno::UNO_SET_THROW );
    1285         251 :         xCursor->collapseToMergedArea();
    1286         251 :         xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW );
    1287         251 :         aNewAddress = lclGetRangeAddress( xNewCellRange );
    1288             :     }
    1289         251 :     while( bRecursive && (aOldAddress != aNewAddress) );
    1290         502 :     return xNewCellRange;
    1291             : }
    1292             : 
    1293           3 : uno::Reference< sheet::XSheetCellRangeContainer > lclExpandToMerged( const uno::Reference< sheet::XSheetCellRangeContainer >& rxCellRanges, bool bRecursive ) throw (uno::RuntimeException)
    1294             : {
    1295           3 :     if( !rxCellRanges.is() )
    1296           0 :         throw uno::RuntimeException("Missing cell ranges object" );
    1297           3 :     sal_Int32 nCount = rxCellRanges->getCount();
    1298           3 :     if( nCount < 1 )
    1299           0 :         throw uno::RuntimeException("Missing cell ranges object" );
    1300             : 
    1301           3 :     ScRangeList aScRanges;
    1302           9 :     for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    1303             :     {
    1304           6 :         uno::Reference< table::XCellRange > xRange( rxCellRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    1305           6 :         table::CellRangeAddress aRangeAddr = lclGetRangeAddress( lclExpandToMerged( xRange, bRecursive ) );
    1306           6 :         ScRange aScRange;
    1307           6 :         ScUnoConversion::FillScRange( aScRange, aRangeAddr );
    1308           6 :         aScRanges.Append( aScRange );
    1309           6 :     }
    1310           3 :     return new ScCellRangesObj( getDocShellFromRanges( rxCellRanges ), aScRanges );
    1311             : }
    1312             : 
    1313           2 : void lclExpandAndMerge( const uno::Reference< table::XCellRange >& rxCellRange, bool bMerge ) throw (uno::RuntimeException)
    1314             : {
    1315           2 :     uno::Reference< util::XMergeable > xMerge( lclExpandToMerged( rxCellRange, true ), uno::UNO_QUERY_THROW );
    1316             :     // Calc cannot merge over merged ranges, always unmerge first
    1317           2 :     xMerge->merge( false );
    1318           2 :     if( bMerge )
    1319             :     {
    1320             :         // clear all contents of the covered cells (not the top-left cell)
    1321           1 :         table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxCellRange );
    1322           1 :         sal_Int32 nLastColIdx = aRangeAddr.EndColumn - aRangeAddr.StartColumn;
    1323           1 :         sal_Int32 nLastRowIdx = aRangeAddr.EndRow - aRangeAddr.StartRow;
    1324             :         // clear cells of top row, right of top-left cell
    1325           1 :         if( nLastColIdx > 0 )
    1326           1 :             lclClearRange( rxCellRange->getCellRangeByPosition( 1, 0, nLastColIdx, 0 ) );
    1327             :         // clear all rows below top row
    1328           1 :         if( nLastRowIdx > 0 )
    1329           0 :             lclClearRange( rxCellRange->getCellRangeByPosition( 0, 1, nLastColIdx, nLastRowIdx ) );
    1330             :         // merge the range
    1331           1 :         xMerge->merge( sal_True );
    1332           2 :     }
    1333           2 : }
    1334             : 
    1335          46 : util::TriState lclGetMergedState( const uno::Reference< table::XCellRange >& rxCellRange ) throw (uno::RuntimeException)
    1336             : {
    1337             :     /*  1) Check if range is completely inside one single merged range. To do
    1338             :         this, try to extend from top-left cell only (not from entire range).
    1339             :         This will exclude cases where this range consists of several merged
    1340             :         ranges (or parts of them). */
    1341          46 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxCellRange );
    1342          46 :     uno::Reference< table::XCellRange > xTopLeft( rxCellRange->getCellRangeByPosition( 0, 0, 0, 0 ), uno::UNO_SET_THROW );
    1343          92 :     uno::Reference< sheet::XSheetCellRange > xExpanded( lclExpandToMerged( xTopLeft, false ), uno::UNO_SET_THROW );
    1344          46 :     table::CellRangeAddress aExpAddr = lclGetRangeAddress( xExpanded );
    1345             :     // check that expanded range has more than one cell (really merged)
    1346          46 :     if( ((aExpAddr.StartColumn < aExpAddr.EndColumn) || (aExpAddr.StartRow < aExpAddr.EndRow)) && ScUnoConversion::Contains( aExpAddr, aRangeAddr ) )
    1347          14 :         return util::TriState_YES;
    1348             : 
    1349             :     /*  2) Check if this range contains any merged cells (completely or
    1350             :         partly). This seems to be hardly possible via API, as
    1351             :         XMergeable::getIsMerged() returns only true, if the top-left cell of a
    1352             :         merged range is part of this range, so cases where just the lower part
    1353             :         of a merged range is part of this range are not covered. */
    1354          32 :     ScRange aScRange;
    1355          32 :     ScUnoConversion::FillScRange( aScRange, aRangeAddr );
    1356          32 :     bool bHasMerged = getDocumentFromRange( rxCellRange ).HasAttrib( aScRange, HASATTR_MERGED | HASATTR_OVERLAPPED );
    1357          78 :     return bHasMerged ? util::TriState_INDETERMINATE : util::TriState_NO;
    1358             : }
    1359             : 
    1360             : } // namespace
    1361             : 
    1362             : css::uno::Reference< excel::XRange >
    1363           5 : ScVbaRange::getRangeObjectForName(
    1364             :         const uno::Reference< uno::XComponentContext >& xContext, const OUString& sRangeName,
    1365             :         ScDocShell* pDocSh, formula::FormulaGrammar::AddressConvention eConv ) throw ( uno::RuntimeException )
    1366             : {
    1367           5 :     table::CellRangeAddress refAddr;
    1368           5 :     return getRangeForName( xContext, sRangeName, pDocSh, refAddr, eConv );
    1369             : }
    1370             : 
    1371          12 : table::CellRangeAddress getCellRangeAddressForVBARange( const uno::Any& aParam, ScDocShell* pDocSh,  formula::FormulaGrammar::AddressConvention aConv = formula::FormulaGrammar::CONV_XL_A1) throw ( uno::RuntimeException )
    1372             : {
    1373          12 :     uno::Reference< table::XCellRange > xRangeParam;
    1374          12 :     switch ( aParam.getValueTypeClass() )
    1375             :     {
    1376             :         case uno::TypeClass_STRING:
    1377             :         {
    1378           0 :             OUString rString;
    1379           0 :             aParam >>= rString;
    1380           0 :             ScRangeList aCellRanges;
    1381           0 :             ScRange refRange;
    1382           0 :             if ( getScRangeListForAddress ( rString, pDocSh, refRange, aCellRanges, aConv ) )
    1383             :             {
    1384           0 :                 if ( aCellRanges.size() == 1 )
    1385             :                 {
    1386           0 :                     table::CellRangeAddress aRangeAddress;
    1387           0 :                     ScUnoConversion::FillApiRange( aRangeAddress, *aCellRanges.front() );
    1388           0 :                     return aRangeAddress;
    1389             :                 }
    1390           0 :             }
    1391             :         }
    1392           0 :         break;
    1393             : 
    1394             :         case uno::TypeClass_INTERFACE:
    1395             :         {
    1396          12 :             uno::Reference< excel::XRange > xRange;
    1397          12 :             aParam >>= xRange;
    1398          12 :             if ( xRange.is() )
    1399          12 :                 xRange->getCellRange() >>= xRangeParam;
    1400             :         }
    1401          12 :         break;
    1402             : 
    1403             :         default:
    1404           0 :             throw uno::RuntimeException("Can't extact CellRangeAddress from type" );
    1405             :     }
    1406          12 :     return lclGetRangeAddress( xRangeParam );
    1407             : }
    1408             : 
    1409             : static uno::Reference< XCollection >
    1410           2 : lcl_setupBorders( const uno::Reference< excel::XRange >& xParentRange, const uno::Reference<uno::XComponentContext>& xContext,  const uno::Reference< table::XCellRange >& xRange  ) throw( uno::RuntimeException )
    1411             : {
    1412           2 :     uno::Reference< XHelperInterface > xParent( xParentRange, uno::UNO_QUERY_THROW );
    1413           2 :     ScDocument& rDoc = getDocumentFromRange(xRange);
    1414           2 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    1415           2 :      uno::Reference< XCollection > borders( new ScVbaBorders( xParent, xContext, xRange, aPalette ) );
    1416           2 :     return borders;
    1417             : }
    1418             : 
    1419          18 : ScVbaRange::ScVbaRange( uno::Sequence< uno::Any> const & args,
    1420          18 :     uno::Reference< uno::XComponentContext> const & xContext )  throw ( lang::IllegalArgumentException, uno::RuntimeException ) : ScVbaRange_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext, getXSomethingFromArgs< beans::XPropertySet >( args, 1, false ), getModelFromXIf( getXSomethingFromArgs< uno::XInterface >( args, 1 ) ), true ), mbIsRows( false ), mbIsColumns( false )
    1421             : {
    1422          18 :     mxRange.set( mxPropertySet, uno::UNO_QUERY );
    1423          18 :     mxRanges.set( mxPropertySet, uno::UNO_QUERY );
    1424          18 :     uno::Reference< container::XIndexAccess >  xIndex;
    1425          18 :     if ( mxRange.is() )
    1426             :     {
    1427          16 :         xIndex = new SingleRangeIndexAccess( mxParent, mxContext, mxRange );
    1428             :     }
    1429           2 :     else if ( mxRanges.is() )
    1430             :     {
    1431           2 :         xIndex.set( mxRanges, uno::UNO_QUERY_THROW );
    1432             :     }
    1433          18 :     m_Areas = new ScVbaRangeAreas( mxParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1434          18 : }
    1435             : 
    1436        3493 : ScVbaRange::ScVbaRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange, bool bIsRows, bool bIsColumns ) throw( lang::IllegalArgumentException )
    1437             : : ScVbaRange_BASE( xParent, xContext, uno::Reference< beans::XPropertySet >( xRange, uno::UNO_QUERY_THROW ), getModelFromRange( xRange), true ), mxRange( xRange ),
    1438             :                 mbIsRows( bIsRows ),
    1439        3493 :                 mbIsColumns( bIsColumns )
    1440             : {
    1441        3493 :     if  ( !xContext.is() )
    1442           0 :         throw lang::IllegalArgumentException("context is not set ", uno::Reference< uno::XInterface >() , 1 );
    1443        3493 :     if  ( !xRange.is() )
    1444           0 :         throw lang::IllegalArgumentException("range is not set ", uno::Reference< uno::XInterface >() , 1 );
    1445             : 
    1446        3493 :     uno::Reference< container::XIndexAccess > xIndex( new SingleRangeIndexAccess( mxParent, mxContext, xRange ) );
    1447        3493 :     m_Areas = new ScVbaRangeAreas( mxParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1448             : 
    1449        3493 : }
    1450             : 
    1451          78 : ScVbaRange::ScVbaRange(const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges, bool bIsRows, bool bIsColumns)
    1452             :     throw (lang::IllegalArgumentException, uno::RuntimeException)
    1453          78 : : ScVbaRange_BASE( xParent, xContext, uno::Reference< beans::XPropertySet >( xRanges, uno::UNO_QUERY_THROW ), getModelFromXIf( uno::Reference< uno::XInterface >( xRanges, uno::UNO_QUERY_THROW ) ), true ), mxRanges( xRanges ),mbIsRows( bIsRows ), mbIsColumns( bIsColumns )
    1454             : 
    1455             : {
    1456          78 :     uno::Reference< container::XIndexAccess >  xIndex( mxRanges, uno::UNO_QUERY_THROW );
    1457          78 :     m_Areas  = new ScVbaRangeAreas( xParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1458             : 
    1459          78 : }
    1460             : 
    1461        7160 : ScVbaRange::~ScVbaRange()
    1462             : {
    1463        7160 : }
    1464             : 
    1465           3 : uno::Reference< XCollection >& ScVbaRange::getBorders()
    1466             : {
    1467           3 :     if ( !m_Borders.is() )
    1468             :     {
    1469           2 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    1470           2 :         m_Borders = lcl_setupBorders( this, mxContext, uno::Reference< table::XCellRange >( xRange->getCellRange(), uno::UNO_QUERY_THROW ) );
    1471             :     }
    1472           3 :     return m_Borders;
    1473             : }
    1474             : 
    1475             : void
    1476         932 : ScVbaRange::visitArray( ArrayVisitor& visitor )
    1477             : {
    1478         932 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( mxRange );
    1479         932 :     sal_Int32 nRowCount = aRangeAddr.EndRow - aRangeAddr.StartRow + 1;
    1480         932 :     sal_Int32 nColCount = aRangeAddr.EndColumn - aRangeAddr.StartColumn + 1;
    1481        2081 :     for ( sal_Int32 i=0; i<nRowCount; ++i )
    1482             :     {
    1483        9122 :         for ( sal_Int32 j=0; j<nColCount; ++j )
    1484             :         {
    1485        7973 :             uno::Reference< table::XCell > xCell( mxRange->getCellByPosition( j, i ), uno::UNO_QUERY_THROW );
    1486             : 
    1487        7973 :             visitor.visitNode( i, j, xCell );
    1488        7973 :         }
    1489             :     }
    1490         932 : }
    1491             : 
    1492             : uno::Any
    1493         630 : ScVbaRange::getValue( ValueGetter& valueGetter) throw (uno::RuntimeException)
    1494             : {
    1495         630 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    1496             :     // single cell range
    1497         630 :     if ( isSingleCellRange() )
    1498             :     {
    1499         599 :         visitArray( valueGetter );
    1500         599 :         return valueGetter.getValue();
    1501             :     }
    1502          31 :     sal_Int32 nRowCount = xColumnRowRange->getRows()->getCount();
    1503          31 :     sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
    1504             :     // multi cell range ( return array )
    1505          62 :     Dim2ArrayValueGetter arrayGetter( nRowCount, nColCount, valueGetter );
    1506          31 :     visitArray( arrayGetter );
    1507         661 :     return uno::makeAny( script::ArrayWrapper( false, arrayGetter.getValue() ) );
    1508             : }
    1509             : 
    1510             : uno::Any SAL_CALL
    1511         590 : ScVbaRange::getValue() throw (uno::RuntimeException, std::exception)
    1512             : {
    1513             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1514             :     // Test is performed only because m_xRange is NOT set to be
    1515             :     // the first range in m_Areas ( to force failure while
    1516             :     // the implementations for each method are being updated )
    1517         590 :     if ( m_Areas->getCount() > 1 )
    1518             :     {
    1519           7 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1520           7 :         return xRange->getValue();
    1521             :     }
    1522             : 
    1523         583 :     CellValueGetter valueGetter;
    1524         583 :     return getValue( valueGetter );
    1525             : 
    1526             : }
    1527             : 
    1528             : void
    1529         302 : ScVbaRange::setValue( const uno::Any& aValue, ValueSetter& valueSetter, bool bFireEvent ) throw (uno::RuntimeException)
    1530             : {
    1531         302 :     uno::TypeClass aClass = aValue.getValueTypeClass();
    1532         302 :     if ( aClass == uno::TypeClass_SEQUENCE )
    1533             :     {
    1534           5 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    1535          10 :         uno::Any aConverted;
    1536             :         try
    1537             :         {
    1538             :             // test for single dimension, could do
    1539             :             // with a better test than this
    1540           5 :             if ( aValue.getValueTypeName().indexOf('[') ==  aValue.getValueTypeName().lastIndexOf('[') )
    1541             :             {
    1542           3 :                 aConverted = xConverter->convertTo( aValue, cppu::UnoType<uno::Sequence< uno::Any >>::get() );
    1543           3 :                 Dim1ArrayValueSetter setter( aConverted, valueSetter );
    1544           3 :                 visitArray( setter );
    1545             :             }
    1546             :             else
    1547             :             {
    1548           2 :                 aConverted = xConverter->convertTo( aValue, cppu::UnoType<uno::Sequence< uno::Sequence< uno::Any > >>::get() );
    1549           2 :                 Dim2ArrayValueSetter setter( aConverted, valueSetter );
    1550           2 :                 visitArray( setter );
    1551             :             }
    1552             :         }
    1553           0 :         catch ( const uno::Exception& e )
    1554             :         {
    1555             :             OSL_TRACE("Bahhh, caught exception %s",
    1556             :                 OUStringToOString( e.Message,
    1557             :                     RTL_TEXTENCODING_UTF8 ).getStr() );
    1558           5 :         }
    1559             :     }
    1560             :     else
    1561             :     {
    1562         297 :         visitArray( valueSetter );
    1563             :     }
    1564         302 :     if( bFireEvent ) fireChangeEvent();
    1565         302 : }
    1566             : 
    1567             : void SAL_CALL
    1568         296 : ScVbaRange::setValue( const uno::Any  &aValue ) throw (uno::RuntimeException, std::exception)
    1569             : {
    1570             :     // If this is a multiple selection apply setValue over all areas
    1571         296 :     if ( m_Areas->getCount() > 1 )
    1572             :     {
    1573           9 :         AreasVisitor aVisitor( m_Areas );
    1574          18 :         RangeValueProcessor valueProcessor( aValue );
    1575           9 :         aVisitor.visit( valueProcessor );
    1576         314 :         return;
    1577             :     }
    1578         287 :     CellValueSetter valueSetter( aValue );
    1579         287 :     setValue( aValue, valueSetter, true );
    1580             : }
    1581             : 
    1582             : void SAL_CALL
    1583          53 : ScVbaRange::Clear() throw (uno::RuntimeException, std::exception)
    1584             : {
    1585             :     using namespace ::com::sun::star::sheet::CellFlags;
    1586          53 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | FORMULA | HARDATTR | EDITATTR | FORMATTED;
    1587          53 :     ClearContents( nFlags, true );
    1588          53 : }
    1589             : 
    1590             : //helper ClearContent
    1591             : void
    1592          77 : ScVbaRange::ClearContents( sal_Int32 nFlags, bool bFireEvent ) throw (uno::RuntimeException)
    1593             : {
    1594             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1595             :     // Test is performed only because m_xRange is NOT set to be
    1596             :     // the first range in m_Areas ( to force failure while
    1597             :     // the implementations for each method are being updated )
    1598          77 :     if ( m_Areas->getCount() > 1 )
    1599             :     {
    1600           7 :         sal_Int32 nItems = m_Areas->getCount();
    1601          21 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    1602             :         {
    1603          14 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1604          14 :             ScVbaRange* pRange = getImplementation( xRange );
    1605          14 :             if ( pRange )
    1606          14 :                 pRange->ClearContents( nFlags, false ); // do not fire for single ranges
    1607          14 :         }
    1608             :         // fire change event for the entire range list
    1609           7 :         if( bFireEvent ) fireChangeEvent();
    1610          14 :         return;
    1611             :     }
    1612             : 
    1613          70 :     uno::Reference< sheet::XSheetOperation > xSheetOperation(mxRange, uno::UNO_QUERY_THROW);
    1614          70 :     xSheetOperation->clearContents( nFlags );
    1615          70 :     if( bFireEvent ) fireChangeEvent();
    1616             : }
    1617             : 
    1618             : void SAL_CALL
    1619           0 : ScVbaRange::ClearComments() throw (uno::RuntimeException, std::exception)
    1620             : {
    1621           0 :     ClearContents( sheet::CellFlags::ANNOTATION, false );
    1622           0 : }
    1623             : 
    1624             : void SAL_CALL
    1625           9 : ScVbaRange::ClearContents() throw (uno::RuntimeException, std::exception)
    1626             : {
    1627             :     using namespace ::com::sun::star::sheet::CellFlags;
    1628           9 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | FORMULA;
    1629           9 :     ClearContents( nFlags, true );
    1630           9 : }
    1631             : 
    1632             : void SAL_CALL
    1633           1 : ScVbaRange::ClearFormats() throw (uno::RuntimeException, std::exception)
    1634             : {
    1635             :         // FIXME: need to check if we need to combine FORMATTED
    1636             :     using namespace ::com::sun::star::sheet::CellFlags;
    1637           1 :         sal_Int32 nFlags = HARDATTR | FORMATTED | EDITATTR;
    1638           1 :         ClearContents( nFlags, false );
    1639           1 : }
    1640             : 
    1641             : void
    1642          16 : ScVbaRange::setFormulaValue( const uno::Any& rFormula, formula::FormulaGrammar::Grammar eGram, bool bFireEvent ) throw (uno::RuntimeException)
    1643             : {
    1644             :     // If this is a multiple selection apply setFormula over all areas
    1645          16 :     if ( m_Areas->getCount() > 1 )
    1646             :     {
    1647           1 :         AreasVisitor aVisitor( m_Areas );
    1648           2 :         RangeFormulaProcessor valueProcessor( rFormula );
    1649           1 :         aVisitor.visit( valueProcessor );
    1650          18 :         return;
    1651             :     }
    1652          15 :     CellFormulaValueSetter formulaValueSetter( rFormula, &getScDocument(), eGram );
    1653          15 :     setValue( rFormula, formulaValueSetter, bFireEvent );
    1654             : }
    1655             : 
    1656             : uno::Any
    1657          48 : ScVbaRange::getFormulaValue( formula::FormulaGrammar::Grammar eGram ) throw (uno::RuntimeException)
    1658             : {
    1659             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1660             :     // Test is performed only because m_xRange is NOT set to be
    1661             :     // the first range in m_Areas ( to force failure while
    1662             :     // the implementations for each method are being updated )
    1663          48 :     if ( m_Areas->getCount() > 1 )
    1664             :     {
    1665           1 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1666           1 :         return xRange->getFormula();
    1667             :     }
    1668          47 :     CellFormulaValueGetter valueGetter( &getScDocument(), eGram );
    1669          47 :     return getValue( valueGetter );
    1670             : 
    1671             : }
    1672             : 
    1673             : void
    1674          14 : ScVbaRange::setFormula(const uno::Any &rFormula ) throw (uno::RuntimeException, std::exception)
    1675             : {
    1676             :     // #FIXME converting "=$a$1" e.g. CONV_XL_A1 -> CONV_OOO                            // results in "=$a$1:a1", temporalily disable conversion
    1677          14 :     setFormulaValue( rFormula,formula::FormulaGrammar::GRAM_NATIVE_XL_A1, true );
    1678          14 : }
    1679             : 
    1680             : uno::Any
    1681           5 : ScVbaRange::getFormulaR1C1() throw (::com::sun::star::uno::RuntimeException, std::exception)
    1682             : {
    1683           5 :     return getFormulaValue( formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1 );
    1684             : }
    1685             : 
    1686             : void
    1687           2 : ScVbaRange::setFormulaR1C1(const uno::Any& rFormula ) throw (uno::RuntimeException, std::exception)
    1688             : {
    1689           2 :     setFormulaValue( rFormula,formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1, true );
    1690           2 : }
    1691             : 
    1692             : uno::Any
    1693          43 : ScVbaRange::getFormula() throw (::com::sun::star::uno::RuntimeException, std::exception)
    1694             : {
    1695          43 :     return getFormulaValue( formula::FormulaGrammar::GRAM_NATIVE_XL_A1 );
    1696             : }
    1697             : 
    1698             : sal_Int32
    1699          67 : ScVbaRange::getCount() throw (uno::RuntimeException, std::exception)
    1700             : {
    1701             :     // If this is a multiple selection apply setValue over all areas
    1702          67 :     if ( m_Areas->getCount() > 1 )
    1703             :     {
    1704          11 :         AreasVisitor aVisitor( m_Areas );
    1705          22 :         RangeCountProcessor valueProcessor;
    1706          11 :         aVisitor.visit( valueProcessor );
    1707          22 :         return valueProcessor.value();
    1708             :     }
    1709          56 :     sal_Int32 rowCount = 0;
    1710          56 :     sal_Int32 colCount = 0;
    1711          56 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    1712          56 :     rowCount = xColumnRowRange->getRows()->getCount();
    1713          56 :     colCount = xColumnRowRange->getColumns()->getCount();
    1714             : 
    1715          56 :     if( IsRows() )
    1716          28 :         return rowCount;
    1717          28 :     if( IsColumns() )
    1718          11 :         return colCount;
    1719          17 :     return rowCount * colCount;
    1720             : }
    1721             : 
    1722             : sal_Int32
    1723         928 : ScVbaRange::getRow() throw (uno::RuntimeException, std::exception)
    1724             : {
    1725             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1726             :     // Test is performed only because m_xRange is NOT set to be
    1727             :     // the first range in m_Areas ( to force failure while
    1728             :     // the implementations for each method are being updated )
    1729         928 :     if ( m_Areas->getCount() > 1 )
    1730             :     {
    1731           5 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1732           5 :         return xRange->getRow();
    1733             :     }
    1734         923 :     uno::Reference< sheet::XCellAddressable > xCellAddressable(mxRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW );
    1735         923 :     return xCellAddressable->getCellAddress().Row + 1; // Zero value indexing
    1736             : }
    1737             : 
    1738             : sal_Int32
    1739         926 : ScVbaRange::getColumn() throw (uno::RuntimeException, std::exception)
    1740             : {
    1741             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1742             :     // Test is performed only because m_xRange is NOT set to be
    1743             :     // the first range in m_Areas ( to force failure while
    1744             :     // the implementations for each method are being updated )
    1745         926 :     if ( m_Areas->getCount() > 1 )
    1746             :     {
    1747           5 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1748           5 :         return xRange->getColumn();
    1749             :     }
    1750         921 :     uno::Reference< sheet::XCellAddressable > xCellAddressable(mxRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW );
    1751         921 :     return xCellAddressable->getCellAddress().Column + 1; // Zero value indexing
    1752             : }
    1753             : 
    1754             : uno::Any
    1755          32 : ScVbaRange::HasFormula() throw (uno::RuntimeException, std::exception)
    1756             : {
    1757          32 :     if ( m_Areas->getCount() > 1 )
    1758             :     {
    1759           8 :         sal_Int32 nItems = m_Areas->getCount();
    1760           8 :         uno::Any aResult = aNULL();
    1761          20 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    1762             :         {
    1763          14 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1764             :             // if the HasFormula for any area is different to another
    1765             :             // return null
    1766          14 :             if ( index > 1 )
    1767           6 :                 if ( aResult != xRange->HasFormula() )
    1768           0 :                     return aNULL();
    1769          14 :             aResult = xRange->HasFormula();
    1770          14 :             if ( aNULL() == aResult )
    1771           2 :                 return aNULL();
    1772          12 :         }
    1773           6 :         return aResult;
    1774             :     }
    1775          24 :     uno::Reference< uno::XInterface > xIf( mxRange, uno::UNO_QUERY_THROW );
    1776          24 :     ScCellRangesBase* pThisRanges = dynamic_cast< ScCellRangesBase * > ( xIf.get() );
    1777          24 :     if ( pThisRanges )
    1778             :     {
    1779          24 :         uno::Reference<uno::XInterface>  xRanges( pThisRanges->queryFormulaCells( ( sheet::FormulaResult::ERROR | sheet::FormulaResult::VALUE |  sheet::FormulaResult::STRING ) ), uno::UNO_QUERY_THROW );
    1780          24 :         ScCellRangesBase* pFormulaRanges = dynamic_cast< ScCellRangesBase * > ( xRanges.get() );
    1781             :         // check if there are no formula cell, return false
    1782          24 :         if ( pFormulaRanges->GetRangeList().empty() )
    1783          14 :             return uno::makeAny(sal_False);
    1784             : 
    1785             :         // chech if there are holes (where some cells are not formulas)
    1786             :         // or returned range is not equal to this range
    1787          20 :         if (  ( pFormulaRanges->GetRangeList().size() > 1 )
    1788          10 :            || ( pFormulaRanges->GetRangeList().front()->aStart != pThisRanges->GetRangeList().front()->aStart )
    1789          18 :            || ( pFormulaRanges->GetRangeList().front()->aEnd   != pThisRanges->GetRangeList().front()->aEnd   )
    1790             :            )
    1791           2 :             return aNULL(); // should return aNULL;
    1792             :     }
    1793           8 :     return uno::makeAny( sal_True );
    1794             : }
    1795             : void
    1796          13 : ScVbaRange::fillSeries( sheet::FillDirection nFillDirection, sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode, double fStep, double fEndValue ) throw( uno::RuntimeException )
    1797             : {
    1798          13 :     if ( m_Areas->getCount() > 1 )
    1799             :     {
    1800             :         // Multi-Area Range
    1801           4 :         uno::Reference< XCollection > xCollection( m_Areas, uno::UNO_QUERY_THROW );
    1802          12 :         for ( sal_Int32 index = 1; index <= xCollection->getCount(); ++index )
    1803             :         {
    1804           8 :             uno::Reference< excel::XRange > xRange( xCollection->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    1805           8 :             ScVbaRange* pThisRange = getImplementation( xRange );
    1806           8 :             pThisRange->fillSeries( nFillDirection, nFillMode, nFillDateMode, fStep, fEndValue );
    1807             : 
    1808           8 :         }
    1809          17 :         return;
    1810             :     }
    1811             : 
    1812           9 :     uno::Reference< sheet::XCellSeries > xCellSeries(mxRange, uno::UNO_QUERY_THROW );
    1813           9 :     xCellSeries->fillSeries( nFillDirection, nFillMode, nFillDateMode, fStep, fEndValue );
    1814           9 :     fireChangeEvent();
    1815             : }
    1816             : 
    1817             : void
    1818           1 : ScVbaRange::FillLeft() throw (uno::RuntimeException, std::exception)
    1819             : {
    1820             :     fillSeries(sheet::FillDirection_TO_LEFT,
    1821           1 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1822           1 : }
    1823             : 
    1824             : void
    1825           2 : ScVbaRange::FillRight() throw (uno::RuntimeException, std::exception)
    1826             : {
    1827             :     fillSeries(sheet::FillDirection_TO_RIGHT,
    1828           2 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1829           2 : }
    1830             : 
    1831             : void
    1832           1 : ScVbaRange::FillUp() throw (uno::RuntimeException, std::exception)
    1833             : {
    1834             :     fillSeries(sheet::FillDirection_TO_TOP,
    1835           1 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1836           1 : }
    1837             : 
    1838             : void
    1839           1 : ScVbaRange::FillDown() throw (uno::RuntimeException, std::exception)
    1840             : {
    1841             :     fillSeries(sheet::FillDirection_TO_BOTTOM,
    1842           1 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1843           1 : }
    1844             : 
    1845             : OUString
    1846          36 : ScVbaRange::getText() throw (uno::RuntimeException, std::exception)
    1847             : {
    1848             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1849             :     // Test is performed only because m_xRange is NOT set to be
    1850             :     // the first range in m_Areas ( to force failure while
    1851             :     // the implementations for each method are being updated )
    1852          36 :     if ( m_Areas->getCount() > 1 )
    1853             :     {
    1854          14 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1855          14 :         return xRange->getText();
    1856             :     }
    1857          22 :     uno::Reference< text::XTextRange > xTextRange(mxRange->getCellByPosition(0,0), uno::UNO_QUERY_THROW );
    1858          22 :     return xTextRange->getString();
    1859             : }
    1860             : 
    1861             : uno::Reference< excel::XRange >
    1862           2 : ScVbaRange::Offset( const ::uno::Any &nRowOff, const uno::Any &nColOff ) throw (uno::RuntimeException, std::exception)
    1863             : {
    1864           2 :     SCROW nRowOffset = 0;
    1865           2 :     SCCOL nColOffset = 0;
    1866           2 :     bool bIsRowOffset = ( nRowOff >>= nRowOffset );
    1867           2 :     bool bIsColumnOffset = ( nColOff >>= nColOffset );
    1868           2 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    1869             : 
    1870           2 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    1871             : 
    1872           6 :     for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    1873             :     {
    1874           4 :         ScRange* pRange = aCellRanges[ i ];
    1875           4 :         if ( bIsColumnOffset )
    1876             :         {
    1877           4 :             pRange->aStart.SetCol( pRange->aStart.Col() + nColOffset );
    1878           4 :             pRange->aEnd.SetCol( pRange->aEnd.Col() + nColOffset );
    1879             :         }
    1880           4 :         if ( bIsRowOffset )
    1881             :         {
    1882           4 :             pRange->aStart.SetRow( pRange->aStart.Row() + nRowOffset );
    1883           4 :             pRange->aEnd.SetRow( pRange->aEnd.Row() + nRowOffset );
    1884             :         }
    1885             :     }
    1886             : 
    1887           2 :     if ( aCellRanges.size() > 1 ) // Multi-Area
    1888             :     {
    1889           2 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pUnoRangesBase->GetDocShell(), aCellRanges ) );
    1890           2 :         return new ScVbaRange( mxParent, mxContext, xRanges );
    1891             :     }
    1892             :     // normal range
    1893           0 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), *aCellRanges.front() ) );
    1894           2 :     return new ScVbaRange( mxParent, mxContext, xRange  );
    1895             : }
    1896             : 
    1897             : uno::Reference< excel::XRange >
    1898           8 : ScVbaRange::CurrentRegion() throw (uno::RuntimeException, std::exception)
    1899             : {
    1900             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1901             :     // Test is performed only because m_xRange is NOT set to be
    1902             :     // the first range in m_Areas ( to force failure while
    1903             :     // the implementations for each method are being updated )
    1904           8 :     if ( m_Areas->getCount() > 1 )
    1905             :     {
    1906           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1907           0 :         return xRange->CurrentRegion();
    1908             :     }
    1909             : 
    1910           8 :     RangeHelper helper( mxRange );
    1911             :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor =
    1912          16 :         helper.getSheetCellCursor();
    1913           8 :     xSheetCellCursor->collapseToCurrentRegion();
    1914          16 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    1915          16 :     return RangeHelper::createRangeFromRange( mxParent, mxContext, helper.getCellRangeFromSheet(), xCellRangeAddressable );
    1916             : }
    1917             : 
    1918             : uno::Reference< excel::XRange >
    1919           0 : ScVbaRange::CurrentArray() throw (uno::RuntimeException, std::exception)
    1920             : {
    1921             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1922             :     // Test is performed only because m_xRange is NOT set to be
    1923             :     // the first range in m_Areas ( to force failure while
    1924             :     // the implementations for each method are being updated )
    1925           0 :     if ( m_Areas->getCount() > 1 )
    1926             :     {
    1927           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1928           0 :         return xRange->CurrentArray();
    1929             :     }
    1930           0 :     RangeHelper helper( mxRange );
    1931             :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor =
    1932           0 :         helper.getSheetCellCursor();
    1933           0 :     xSheetCellCursor->collapseToCurrentArray();
    1934           0 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    1935           0 :     return RangeHelper::createRangeFromRange( mxParent, mxContext, helper.getCellRangeFromSheet(), xCellRangeAddressable );
    1936             : }
    1937             : 
    1938             : uno::Any
    1939           2 : ScVbaRange::getFormulaArray() throw (uno::RuntimeException, std::exception)
    1940             : {
    1941             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1942             :     // Test is performed only because m_xRange is NOT set to be
    1943             :     // the first range in m_Areas ( to force failure while
    1944             :     // the implementations for each method are being updated )
    1945           2 :     if ( m_Areas->getCount() > 1 )
    1946             :     {
    1947           1 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1948           1 :         return xRange->getFormulaArray();
    1949             :     }
    1950             : 
    1951             :     // return a formula if there is one or else an array
    1952             :     // still not sure when the return as array code should run
    1953             :     // ( I think it is if there is more than one formula ) at least
    1954             :     // that is what the doc says ( but I am not even sure how to detect that )
    1955             :     // for the moment any tests we have pass
    1956           1 :     uno::Reference< sheet::XArrayFormulaRange> xFormulaArray( mxRange, uno::UNO_QUERY_THROW );
    1957           1 :     if ( xFormulaArray.is() && !xFormulaArray->getArrayFormula().isEmpty() )
    1958           0 :         return uno::makeAny( xFormulaArray->getArrayFormula() );
    1959             : 
    1960           2 :     uno::Reference< sheet::XCellRangeFormula> xCellRangeFormula( mxRange, uno::UNO_QUERY_THROW );
    1961           2 :     uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    1962           2 :     uno::Any aSingleValueOrMatrix;
    1963             :     // When dealing with a single element ( embedded in the sequence of sequence ) unwrap and return
    1964             :     // that value
    1965           2 :     uno::Sequence< uno::Sequence<rtl::OUString> > aTmpSeq = xCellRangeFormula->getFormulaArray();
    1966           1 :     if ( aTmpSeq.getLength() == 1 )
    1967             :     {
    1968           0 :         if ( aTmpSeq[ 0 ].getLength() == 1  )
    1969           0 :             aSingleValueOrMatrix <<= aTmpSeq[ 0 ][ 0 ];
    1970             :     }
    1971             :     else
    1972           1 :         aSingleValueOrMatrix = xConverter->convertTo( uno::makeAny( aTmpSeq ) , cppu::UnoType<uno::Sequence< uno::Sequence< uno::Any > >>::get()  ) ;
    1973           2 :     return aSingleValueOrMatrix;
    1974             : }
    1975             : 
    1976             : void
    1977           2 : ScVbaRange::setFormulaArray(const uno::Any& rFormula) throw (uno::RuntimeException, std::exception)
    1978             : {
    1979             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1980             :     // Test is performed only because m_xRange is NOT set to be
    1981             :     // the first range in m_Areas ( to force failure while
    1982             :     // the implementations for each method are being updated )
    1983           2 :     if ( m_Areas->getCount() > 1 )
    1984             :     {
    1985           1 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1986           3 :         return xRange->setFormulaArray( rFormula );
    1987             :     }
    1988             :     // #TODO need to distinguish between getFormula and getFormulaArray e.g. (R1C1)
    1989             :     // but for the moment its just easier to treat them the same for setting
    1990             :     // seems
    1991           1 :     uno::Reference< lang::XMultiServiceFactory > xModelFactory( getUnoModel(), uno::UNO_QUERY_THROW );
    1992           2 :     uno::Reference< sheet::XFormulaParser > xParser( xModelFactory->createInstance( "com.sun.star.sheet.FormulaParser" ), uno::UNO_QUERY_THROW );
    1993           2 :     uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY_THROW);
    1994             : 
    1995           1 :     table::CellRangeAddress aRangeAddress = xSource->getRangeAddress();
    1996             :     // #TODO check if api orders the address
    1997             :     // e.g. do we need to order the RangeAddress to get the topleft ( or can we assume it
    1998             :     // is in the correct order )
    1999           1 :     table::CellAddress aAddress;
    2000           1 :     aAddress.Sheet = aRangeAddress.Sheet;
    2001           1 :     aAddress.Column = aRangeAddress.StartColumn;
    2002           1 :     aAddress.Row = aRangeAddress.StartRow;
    2003           2 :     OUString sFormula;
    2004           1 :     rFormula >>= sFormula;
    2005           2 :     uno::Sequence<sheet::FormulaToken> aTokens = xParser->parseFormula( sFormula, aAddress );
    2006           2 :     ScTokenArray aTokenArray;
    2007           1 :     (void)ScTokenConversion::ConvertToTokenArray( getScDocument(), aTokenArray, aTokens );
    2008             : 
    2009           2 :     getScDocShell()->GetDocFunc().EnterMatrix( *getScRangeList()[0], NULL, &aTokenArray, OUString(), true, true, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
    2010             : }
    2011             : 
    2012             : OUString
    2013           0 : ScVbaRange::Characters(const uno::Any& Start, const uno::Any& Length) throw (uno::RuntimeException, std::exception)
    2014             : {
    2015             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    2016             :     // Test is performed only because m_xRange is NOT set to be
    2017             :     // the first range in m_Areas ( to force failure while
    2018             :     // the implementations for each method are being updated )
    2019           0 :     if ( m_Areas->getCount() > 1 )
    2020             :     {
    2021           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    2022           0 :         return xRange->Characters( Start, Length );
    2023             :     }
    2024             : 
    2025           0 :     long nIndex = 0, nCount = 0;
    2026           0 :     OUString rString;
    2027           0 :     uno::Reference< text::XTextRange > xTextRange(mxRange, ::uno::UNO_QUERY_THROW );
    2028           0 :     rString = xTextRange->getString();
    2029           0 :     if( !( Start >>= nIndex ) && !( Length >>= nCount ) )
    2030           0 :         return rString;
    2031           0 :     if(!( Start >>= nIndex ) )
    2032           0 :         nIndex = 1;
    2033           0 :     if(!( Length >>= nCount ) )
    2034           0 :         nIndex = rString.getLength();
    2035           0 :     return rString.copy( --nIndex, nCount ); // Zero value indexing
    2036             : }
    2037             : 
    2038             : OUString
    2039         453 : ScVbaRange::Address(  const uno::Any& RowAbsolute, const uno::Any& ColumnAbsolute, const uno::Any& ReferenceStyle, const uno::Any& External, const uno::Any& RelativeTo ) throw (uno::RuntimeException, std::exception)
    2040             : {
    2041         453 :     if ( m_Areas->getCount() > 1 )
    2042             :     {
    2043             :         // Multi-Area Range
    2044          41 :         OUString sAddress;
    2045          82 :         uno::Reference< XCollection > xCollection( m_Areas, uno::UNO_QUERY_THROW );
    2046          82 :                 uno::Any aExternalCopy = External;
    2047         128 :         for ( sal_Int32 index = 1; index <= xCollection->getCount(); ++index )
    2048             :         {
    2049          87 :             uno::Reference< excel::XRange > xRange( xCollection->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    2050          87 :             if ( index > 1 )
    2051             :             {
    2052          46 :                 sAddress += OUString( ',' );
    2053             :                                 // force external to be false
    2054             :                                 // only first address should have the
    2055             :                                 // document and sheet specifications
    2056          46 :                                 aExternalCopy = uno::makeAny(sal_False);
    2057             :             }
    2058          87 :             sAddress += xRange->Address( RowAbsolute, ColumnAbsolute, ReferenceStyle, aExternalCopy, RelativeTo );
    2059          87 :         }
    2060          82 :         return sAddress;
    2061             : 
    2062             :     }
    2063         412 :     ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2064         412 :     if ( ReferenceStyle.hasValue() )
    2065             :     {
    2066          14 :         sal_Int32 refStyle = excel::XlReferenceStyle::xlA1;
    2067          14 :         ReferenceStyle >>= refStyle;
    2068          14 :         if ( refStyle == excel::XlReferenceStyle::xlR1C1 )
    2069          14 :             dDetails = ScAddress::Details( formula::FormulaGrammar::CONV_XL_R1C1, 0, 0 );
    2070             :     }
    2071         412 :     sal_uInt16 nFlags = SCA_VALID;
    2072         412 :     ScDocShell* pDocShell =  getScDocShell();
    2073         412 :     ScDocument& rDoc =  pDocShell->GetDocument();
    2074             : 
    2075         412 :     RangeHelper thisRange( mxRange );
    2076         412 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    2077         412 :     ScRange aRange( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCROW >( thisAddress.StartRow ), static_cast< SCTAB >( thisAddress.Sheet ), static_cast< SCCOL >( thisAddress.EndColumn ), static_cast< SCROW >( thisAddress.EndRow ), static_cast< SCTAB >( thisAddress.Sheet ) );
    2078         412 :     sal_uInt16 ROW_ABSOLUTE = ( SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE );
    2079         412 :     sal_uInt16 COL_ABSOLUTE = ( SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE );
    2080             :     // default
    2081         412 :     nFlags |= ( SCA_TAB_ABSOLUTE | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB2_ABSOLUTE | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE );
    2082         412 :     if ( RowAbsolute.hasValue() )
    2083             :     {
    2084           1 :         bool bVal = true;
    2085           1 :         RowAbsolute >>= bVal;
    2086           1 :         if ( !bVal )
    2087           1 :             nFlags &= ~ROW_ABSOLUTE;
    2088             :     }
    2089         412 :     if ( ColumnAbsolute.hasValue() )
    2090             :     {
    2091           1 :         bool bVal = true;
    2092           1 :         ColumnAbsolute >>= bVal;
    2093           1 :         if ( !bVal )
    2094           1 :             nFlags &= ~COL_ABSOLUTE;
    2095             :     }
    2096         412 :     if ( External.hasValue() )
    2097             :     {
    2098          51 :         bool bLocal = false;
    2099          51 :         External >>= bLocal;
    2100          51 :         if (  bLocal )
    2101           5 :             nFlags |= SCA_TAB_3D | SCA_FORCE_DOC;
    2102             :     }
    2103         412 :     if ( RelativeTo.hasValue() )
    2104             :     {
    2105             :         // #TODO should I throw an error if R1C1 is not set?
    2106             : 
    2107           0 :         table::CellRangeAddress refAddress = getCellRangeAddressForVBARange( RelativeTo, pDocShell );
    2108           0 :         dDetails = ScAddress::Details( formula::FormulaGrammar::CONV_XL_R1C1, static_cast< SCROW >( refAddress.StartRow ), static_cast< SCCOL >( refAddress.StartColumn ) );
    2109             :     }
    2110         412 :     return aRange.Format(nFlags, &rDoc, dDetails);
    2111             : }
    2112             : 
    2113             : uno::Reference < excel::XFont >
    2114          10 : ScVbaRange::Font() throw ( script::BasicErrorException, uno::RuntimeException)
    2115             : {
    2116          10 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY );
    2117          10 :     ScDocument& rDoc = getScDocument();
    2118          10 :     if ( mxRange.is() )
    2119           1 :         xProps.set(mxRange, ::uno::UNO_QUERY );
    2120           9 :     else if ( mxRanges.is() )
    2121           9 :         xProps.set(mxRanges, ::uno::UNO_QUERY );
    2122             : 
    2123          10 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    2124          10 :     ScCellRangeObj* pRangeObj = NULL;
    2125             :     try
    2126             :     {
    2127          10 :         pRangeObj = getCellRangeObj();
    2128             :     }
    2129           0 :     catch( uno::Exception& )
    2130             :     {
    2131             :     }
    2132          10 :     return  new ScVbaFont( this, mxContext, aPalette, xProps, pRangeObj );
    2133             : }
    2134             : 
    2135             : uno::Reference< excel::XRange >
    2136         109 : ScVbaRange::Cells( const uno::Any &nRowIndex, const uno::Any &nColumnIndex ) throw(uno::RuntimeException, std::exception)
    2137             : {
    2138             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    2139             :     // Test is performed only because m_xRange is NOT set to be
    2140             :     // the first range in m_Areas ( to force failure while
    2141             :     // the implementations for each method are being updated )
    2142         109 :     if ( m_Areas->getCount() > 1 )
    2143             :     {
    2144           8 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    2145           8 :         return xRange->Cells( nRowIndex, nColumnIndex );
    2146             :     }
    2147             : 
    2148             :     // Performance: Use a common helper method for ScVbaRange::Cells and ScVbaWorksheet::Cells,
    2149             :     // instead of creating a new ScVbaRange object in often-called ScVbaWorksheet::Cells
    2150         101 :     return CellsHelper( mxParent, mxContext, mxRange, nRowIndex, nColumnIndex );
    2151             : }
    2152             : 
    2153             : // static
    2154             : uno::Reference< excel::XRange >
    2155         327 : ScVbaRange::CellsHelper( const uno::Reference< ov::XHelperInterface >& xParent,
    2156             :                          const uno::Reference< uno::XComponentContext >& xContext,
    2157             :                          const uno::Reference< css::table::XCellRange >& xRange,
    2158             :                          const uno::Any &nRowIndex, const uno::Any &nColumnIndex ) throw(uno::RuntimeException)
    2159             : {
    2160         327 :     sal_Int32 nRow = 0, nColumn = 0;
    2161             : 
    2162         327 :     bool bIsIndex = nRowIndex.hasValue();
    2163         327 :     bool bIsColumnIndex = nColumnIndex.hasValue();
    2164             : 
    2165             :     // Sometimes we might get a float or a double or whatever
    2166             :     // set in the Any, we should convert as appropriate
    2167             :     // #FIXME - perhaps worth turning this into some sort of
    2168             :     // conversion routine e.g. bSuccess = getValueFromAny( nRow, nRowIndex, cppu::UnoType<sal_Int32>::get() )
    2169         327 :     uno::Any aRowIndexAny = nRowIndex;
    2170         327 :     if ( aRowIndexAny.hasValue() && !( aRowIndexAny >>= nRow ) )
    2171             :     {
    2172           0 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( xContext );
    2173           0 :         uno::Any aConverted;
    2174             :         try
    2175             :         {
    2176           0 :             aConverted = xConverter->convertTo( aRowIndexAny, cppu::UnoType<sal_Int32>::get() );
    2177           0 :             bIsIndex = ( aConverted >>= nRow );
    2178             :         }
    2179           0 :         catch( uno::Exception& ) {} // silence any errors
    2180             :     }
    2181             : 
    2182         654 :     uno::Any aColumnAny = nColumnIndex;
    2183             : 
    2184         327 :     if ( bIsColumnIndex )
    2185             :     {
    2186             :          // Column index can be a col address e.g Cells( 1, "B" ) etc.
    2187         318 :         OUString sCol;
    2188         318 :         if ( nColumnIndex >>= sCol )
    2189             :         {
    2190         205 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2191         205 :             ScRange tmpRange;
    2192         205 :             sal_uInt16 flags = tmpRange.ParseCols( sCol, &getDocumentFromRange( xRange ), dDetails );
    2193         205 :             if ( ( flags & 0x200 ) != 0x200 )
    2194           0 :                throw uno::RuntimeException();
    2195         205 :             nColumn = tmpRange.aStart.Col() + 1;
    2196             :         }
    2197             :         else
    2198             :         {
    2199         113 :             if ( !( aColumnAny >>= nColumn ) )
    2200             :             {
    2201           0 :                 uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( xContext );
    2202           0 :                 uno::Any aConverted;
    2203             :                 try
    2204             :                 {
    2205           0 :                     aConverted = xConverter->convertTo( aColumnAny, cppu::UnoType<sal_Int32>::get() );
    2206           0 :                     bIsColumnIndex = ( aConverted >>= nColumn );
    2207             :                 }
    2208           0 :                 catch( uno::Exception& ) {} // silence any errors
    2209             :             }
    2210         318 :        }
    2211             :     }
    2212         654 :     RangeHelper thisRange( xRange );
    2213         327 :     table::CellRangeAddress thisRangeAddress =  thisRange.getCellRangeAddressable()->getRangeAddress();
    2214         654 :     uno::Reference< table::XCellRange > xSheetRange = thisRange.getCellRangeFromSheet();
    2215         327 :     if( !bIsIndex && !bIsColumnIndex ) // .Cells
    2216             :         // #FIXE needs proper parent ( Worksheet )
    2217           2 :         return uno::Reference< excel::XRange >( new ScVbaRange( xParent, xContext, xRange ) );
    2218             : 
    2219         325 :     sal_Int32 nIndex = --nRow;
    2220         325 :     if( bIsIndex && !bIsColumnIndex ) // .Cells(n)
    2221             :     {
    2222           7 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, ::uno::UNO_QUERY_THROW);
    2223           7 :         sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
    2224             : 
    2225           7 :         if ( !nIndex || nIndex < 0 )
    2226           4 :             nRow = 0;
    2227             :         else
    2228           3 :             nRow = nIndex / nColCount;
    2229           7 :         nColumn = nIndex % nColCount;
    2230             :     }
    2231             :     else
    2232         318 :         --nColumn;
    2233         325 :     nRow = nRow + thisRangeAddress.StartRow;
    2234         325 :     nColumn =  nColumn + thisRangeAddress.StartColumn;
    2235         652 :     return new ScVbaRange( xParent, xContext, xSheetRange->getCellRangeByPosition( nColumn, nRow, nColumn, nRow ) );
    2236             : }
    2237             : 
    2238             : void
    2239         200 : ScVbaRange::Select() throw (uno::RuntimeException, std::exception)
    2240             : {
    2241         200 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2242         200 :     if ( !pUnoRangesBase )
    2243           0 :         throw uno::RuntimeException("Failed to access underlying uno range object"  );
    2244         200 :     ScDocShell* pShell = pUnoRangesBase->GetDocShell();
    2245         200 :     if ( pShell )
    2246             :     {
    2247         200 :         uno::Reference< frame::XModel > xModel( pShell->GetModel(), uno::UNO_QUERY_THROW );
    2248         400 :         uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2249         200 :         if ( mxRanges.is() )
    2250           3 :             xSelection->select( uno::Any( lclExpandToMerged( mxRanges, true ) ) );
    2251             :         else
    2252         197 :             xSelection->select( uno::Any( lclExpandToMerged( mxRange, true ) ) );
    2253             :         // set focus on document e.g.
    2254             :         // ThisComponent.CurrentController.Frame.getContainerWindow.SetFocus
    2255             :         try
    2256             :         {
    2257         200 :             uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2258         400 :             uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_QUERY_THROW );
    2259         400 :             uno::Reference< awt::XWindow > xWin( xFrame->getContainerWindow(), uno::UNO_QUERY_THROW );
    2260         400 :             xWin->setFocus();
    2261             :         }
    2262           0 :         catch( uno::Exception& )
    2263             :         {
    2264         200 :         }
    2265             :     }
    2266         200 : }
    2267             : 
    2268           4 : bool cellInRange( const table::CellRangeAddress& rAddr, const sal_Int32& nCol, const sal_Int32& nRow )
    2269             : {
    2270           6 :     if ( nCol >= rAddr.StartColumn && nCol <= rAddr.EndColumn &&
    2271           3 :         nRow >= rAddr.StartRow && nRow <= rAddr.EndRow )
    2272           1 :         return true;
    2273           3 :     return false;
    2274             : }
    2275             : 
    2276           3 : void setCursor(  const SCCOL& nCol, const SCROW& nRow, const uno::Reference< frame::XModel >& xModel,  bool bInSel = true )
    2277             : {
    2278           3 :     ScTabViewShell* pShell = excel::getBestViewShell( xModel );
    2279           3 :     if ( pShell )
    2280             :     {
    2281           3 :         if ( bInSel )
    2282           1 :             pShell->SetCursor( nCol, nRow );
    2283             :         else
    2284           2 :             pShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_NONE, false, false, true, false );
    2285             :     }
    2286           3 : }
    2287             : 
    2288             : void
    2289           4 : ScVbaRange::Activate() throw (uno::RuntimeException, std::exception)
    2290             : {
    2291             :     // get first cell of current range
    2292           4 :     uno::Reference< table::XCellRange > xCellRange;
    2293           4 :     if ( mxRanges.is() )
    2294             :     {
    2295           1 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW  );
    2296           1 :         xCellRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    2297             :     }
    2298             :     else
    2299           3 :         xCellRange.set( mxRange, uno::UNO_QUERY_THROW );
    2300             : 
    2301           8 :     RangeHelper thisRange( xCellRange );
    2302           8 :     uno::Reference< sheet::XCellRangeAddressable > xThisRangeAddress = thisRange.getCellRangeAddressable();
    2303           4 :     table::CellRangeAddress thisRangeAddress = xThisRangeAddress->getRangeAddress();
    2304           8 :         uno::Reference< frame::XModel > xModel;
    2305           4 :         ScDocShell* pShell = getScDocShell();
    2306             : 
    2307           4 :         if ( pShell )
    2308           4 :             xModel = pShell->GetModel();
    2309             : 
    2310           4 :         if ( !xModel.is() )
    2311           0 :             throw uno::RuntimeException();
    2312             : 
    2313             :     // get current selection
    2314           8 :     uno::Reference< sheet::XCellRangeAddressable > xRange( xModel->getCurrentSelection(), ::uno::UNO_QUERY);
    2315             : 
    2316           8 :     uno::Reference< sheet::XSheetCellRanges > xRanges( xModel->getCurrentSelection(), ::uno::UNO_QUERY);
    2317             : 
    2318           4 :     if ( xRanges.is() )
    2319             :     {
    2320           0 :         uno::Sequence< table::CellRangeAddress > nAddrs = xRanges->getRangeAddresses();
    2321           0 :         for ( sal_Int32 index = 0; index < nAddrs.getLength(); ++index )
    2322             :         {
    2323           0 :             if ( cellInRange( nAddrs[index], thisRangeAddress.StartColumn, thisRangeAddress.StartRow ) )
    2324             :             {
    2325           0 :                 setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel );
    2326           4 :                 return;
    2327             :             }
    2328             : 
    2329           0 :         }
    2330             :     }
    2331             : 
    2332           4 :     if ( xRange.is() && cellInRange( xRange->getRangeAddress(), thisRangeAddress.StartColumn, thisRangeAddress.StartRow ) )
    2333           1 :         setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel );
    2334             :     else
    2335             :     {
    2336             :         // if this range is multi cell select the range other
    2337             :         // wise just position the cell at this single range position
    2338           3 :         if ( isSingleCellRange() )
    2339             :             // This top-leftmost cell of this Range is not in the current
    2340             :             // selection so just select this range
    2341           2 :             setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel, false  );
    2342             :         else
    2343           1 :             Select();
    2344           4 :     }
    2345             : 
    2346             : }
    2347             : 
    2348             : uno::Reference< excel::XRange >
    2349          83 : ScVbaRange::Rows(const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    2350             : {
    2351          83 :     OUString sAddress;
    2352             : 
    2353          83 :     if ( aIndex.hasValue() )
    2354             :     {
    2355          27 :         sal_Int32 nValue = 0;
    2356          27 :         ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2357          27 :         ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2358             : 
    2359          27 :         ScRange aRange = *aCellRanges.front();
    2360          27 :         if( aIndex >>= nValue )
    2361             :         {
    2362          23 :             aRange.aStart.SetRow( aRange.aStart.Row() + --nValue );
    2363          23 :             aRange.aEnd.SetRow( aRange.aStart.Row() );
    2364             :         }
    2365           4 :         else if ( aIndex >>= sAddress )
    2366             :         {
    2367           4 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2368           4 :             ScRange tmpRange;
    2369           4 :             tmpRange.ParseRows( sAddress, &getDocumentFromRange( mxRange ), dDetails );
    2370           4 :             SCROW nStartRow = tmpRange.aStart.Row();
    2371           4 :             SCROW nEndRow = tmpRange.aEnd.Row();
    2372             : 
    2373           4 :             aRange.aStart.SetRow( aRange.aStart.Row() + nStartRow );
    2374           4 :             aRange.aEnd.SetRow( aRange.aStart.Row() + ( nEndRow  - nStartRow ));
    2375             :         }
    2376             :         else
    2377           0 :             throw uno::RuntimeException("Illegal param" );
    2378             : 
    2379          27 :         if ( aRange.aStart.Row() < 0 || aRange.aEnd.Row() < 0 )
    2380           0 :             throw uno::RuntimeException("Internal failure, illegal param" );
    2381             :         // return a normal range ( even for multi-selection
    2382          54 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange ) );
    2383          54 :         return new ScVbaRange( mxParent, mxContext, xRange, true  );
    2384             :     }
    2385             :     // Rows() - no params
    2386          56 :     if ( m_Areas->getCount() > 1 )
    2387          14 :         return new ScVbaRange(  mxParent, mxContext, mxRanges, true );
    2388          42 :     return new ScVbaRange(  mxParent, mxContext, mxRange, true );
    2389             : }
    2390             : 
    2391             : uno::Reference< excel::XRange >
    2392          75 : ScVbaRange::Columns(const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    2393             : {
    2394          75 :     OUString sAddress;
    2395             : 
    2396          75 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2397         150 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2398             : 
    2399          75 :     ScRange aRange = *aCellRanges.front();
    2400          75 :     if ( aIndex.hasValue() )
    2401             :     {
    2402          34 :         sal_Int32 nValue = 0;
    2403          34 :         if ( aIndex >>= nValue )
    2404             :         {
    2405          21 :             aRange.aStart.SetCol( aRange.aStart.Col() + static_cast< SCCOL > ( --nValue ) );
    2406          21 :             aRange.aEnd.SetCol( aRange.aStart.Col() );
    2407             :         }
    2408             : 
    2409          13 :         else if ( aIndex >>= sAddress )
    2410             :         {
    2411          13 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2412          13 :             ScRange tmpRange;
    2413          13 :             tmpRange.ParseCols( sAddress, &getDocumentFromRange( mxRange ), dDetails );
    2414          13 :             SCCOL nStartCol = tmpRange.aStart.Col();
    2415          13 :             SCCOL nEndCol = tmpRange.aEnd.Col();
    2416             : 
    2417          13 :             aRange.aStart.SetCol( aRange.aStart.Col() + nStartCol );
    2418          13 :             aRange.aEnd.SetCol( aRange.aStart.Col() + ( nEndCol  - nStartCol ));
    2419             :         }
    2420             :         else
    2421           0 :             throw uno::RuntimeException("Illegal param" );
    2422             : 
    2423          34 :         if ( aRange.aStart.Col() < 0 || aRange.aEnd.Col() < 0 )
    2424           0 :             throw uno::RuntimeException("Internal failure, illegal param" );
    2425             :     }
    2426             :     // Columns() - no params
    2427         150 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange ) );
    2428         150 :     return new ScVbaRange( mxParent, mxContext, xRange, false, true  );
    2429             : }
    2430             : 
    2431             : void
    2432           2 : ScVbaRange::setMergeCells( const uno::Any& aIsMerged ) throw (script::BasicErrorException, uno::RuntimeException)
    2433             : {
    2434           2 :     bool bMerge = extractBoolFromAny( aIsMerged );
    2435             : 
    2436           2 :     if( mxRanges.is() )
    2437             :     {
    2438           0 :         sal_Int32 nCount = mxRanges->getCount();
    2439             : 
    2440             :         // VBA does nothing (no error) if the own ranges overlap somehow
    2441           0 :         ::std::vector< table::CellRangeAddress > aList;
    2442           0 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2443             :         {
    2444           0 :             uno::Reference< sheet::XCellRangeAddressable > xRangeAddr( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2445           0 :             table::CellRangeAddress aAddress = xRangeAddr->getRangeAddress();
    2446           0 :             for( ::std::vector< table::CellRangeAddress >::const_iterator aIt = aList.begin(), aEnd = aList.end(); aIt != aEnd; ++aIt )
    2447           0 :                 if( ScUnoConversion::Intersects( *aIt, aAddress ) )
    2448           0 :                     return;
    2449           0 :             aList.push_back( aAddress );
    2450           0 :         }
    2451             : 
    2452             :         // (un)merge every range after it has been extended to intersecting merged ranges from sheet
    2453           0 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2454             :         {
    2455           0 :             uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2456           0 :             lclExpandAndMerge( xRange, bMerge );
    2457           0 :         }
    2458           0 :         return;
    2459             :     }
    2460             : 
    2461             :     // otherwise, merge single range
    2462           2 :     lclExpandAndMerge( mxRange, bMerge );
    2463             : }
    2464             : 
    2465             : uno::Any
    2466          42 : ScVbaRange::getMergeCells() throw (script::BasicErrorException, uno::RuntimeException)
    2467             : {
    2468          42 :     if( mxRanges.is() )
    2469             :     {
    2470           6 :         sal_Int32 nCount = mxRanges->getCount();
    2471          14 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2472             :         {
    2473          10 :             uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2474          10 :             util::TriState eMerged = lclGetMergedState( xRange );
    2475             :             /*  Excel always returns NULL, if one range of the range list is
    2476             :                 partly or completely merged. Even if all ranges are completely
    2477             :                 merged, the return value is still NULL. */
    2478          10 :             if( eMerged != util::TriState_NO )
    2479           2 :                 return aNULL();
    2480           8 :         }
    2481             :         // no range is merged anyhow, return false
    2482           4 :         return uno::Any( false );
    2483             :     }
    2484             : 
    2485             :     // otherwise, check single range
    2486          36 :     switch( lclGetMergedState( mxRange ) )
    2487             :     {
    2488          14 :         case util::TriState_YES:    return uno::Any( true );
    2489          22 :         case util::TriState_NO:     return uno::Any( false );
    2490           0 :         default:                    return aNULL();
    2491             :     }
    2492             : }
    2493             : 
    2494             : void
    2495          12 : ScVbaRange::Copy(const ::uno::Any& Destination) throw (uno::RuntimeException, std::exception)
    2496             : {
    2497          12 :     if ( m_Areas->getCount() > 1 )
    2498           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2499          12 :     if ( Destination.hasValue() )
    2500             :     {
    2501           1 :         uno::Reference< excel::XRange > xRange( Destination, uno::UNO_QUERY_THROW );
    2502           2 :         uno::Any aRange = xRange->getCellRange();
    2503           2 :         uno::Reference< table::XCellRange > xCellRange;
    2504           1 :         aRange >>= xCellRange;
    2505           2 :         uno::Reference< sheet::XSheetCellRange > xSheetCellRange(xCellRange, ::uno::UNO_QUERY_THROW);
    2506           2 :         uno::Reference< sheet::XSpreadsheet > xSheet = xSheetCellRange->getSpreadsheet();
    2507           2 :         uno::Reference< table::XCellRange > xDest( xSheet, uno::UNO_QUERY_THROW );
    2508           2 :         uno::Reference< sheet::XCellRangeMovement > xMover( xSheet, uno::UNO_QUERY_THROW);
    2509           1 :         uno::Reference< sheet::XCellAddressable > xDestination( xDest->getCellByPosition(
    2510           2 :                                                 xRange->getColumn()-1,xRange->getRow()-1), uno::UNO_QUERY_THROW );
    2511           2 :         uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY);
    2512           1 :         xMover->copyRange( xDestination->getCellAddress(), xSource->getRangeAddress() );
    2513           1 :         if ( ScVbaRange* pRange = getImplementation( xRange ) )
    2514           2 :             pRange->fireChangeEvent();
    2515             :     }
    2516             :     else
    2517             :     {
    2518          11 :         uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    2519          11 :         Select();
    2520          11 :         excel::implnCopy( xModel );
    2521             :     }
    2522          12 : }
    2523             : 
    2524             : void
    2525           1 : ScVbaRange::Cut(const ::uno::Any& Destination) throw (uno::RuntimeException, std::exception)
    2526             : {
    2527           1 :     if ( m_Areas->getCount() > 1 )
    2528           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2529           1 :     if (Destination.hasValue())
    2530             :     {
    2531           1 :         uno::Reference< excel::XRange > xRange( Destination, uno::UNO_QUERY_THROW );
    2532           2 :         uno::Reference< table::XCellRange > xCellRange( xRange->getCellRange(), uno::UNO_QUERY_THROW );
    2533           2 :         uno::Reference< sheet::XSheetCellRange > xSheetCellRange(xCellRange, ::uno::UNO_QUERY_THROW );
    2534           2 :         uno::Reference< sheet::XSpreadsheet > xSheet = xSheetCellRange->getSpreadsheet();
    2535           2 :         uno::Reference< table::XCellRange > xDest( xSheet, uno::UNO_QUERY_THROW );
    2536           2 :         uno::Reference< sheet::XCellRangeMovement > xMover( xSheet, uno::UNO_QUERY_THROW);
    2537           1 :         uno::Reference< sheet::XCellAddressable > xDestination( xDest->getCellByPosition(
    2538           2 :                                                 xRange->getColumn()-1,xRange->getRow()-1), uno::UNO_QUERY);
    2539           2 :         uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY);
    2540           2 :         xMover->moveRange( xDestination->getCellAddress(), xSource->getRangeAddress() );
    2541             :     }
    2542             :     else
    2543             :     {
    2544           0 :         uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    2545           0 :         Select();
    2546           0 :         excel::implnCut( xModel );
    2547             :     }
    2548           1 : }
    2549             : 
    2550             : void
    2551           2 : ScVbaRange::setNumberFormat( const uno::Any& aFormat ) throw ( script::BasicErrorException, uno::RuntimeException)
    2552             : {
    2553           2 :     OUString sFormat;
    2554           2 :     aFormat >>= sFormat;
    2555           2 :     if ( m_Areas->getCount() > 1 )
    2556             :     {
    2557           0 :         sal_Int32 nItems = m_Areas->getCount();
    2558           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2559             :         {
    2560           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2561           0 :             xRange->setNumberFormat( aFormat );
    2562           0 :         }
    2563           2 :         return;
    2564             :     }
    2565           4 :     NumFormatHelper numFormat( mxRange );
    2566           4 :     numFormat.setNumberFormat( sFormat );
    2567             : }
    2568             : 
    2569             : uno::Any
    2570           3 : ScVbaRange::getNumberFormat() throw ( script::BasicErrorException, uno::RuntimeException)
    2571             : {
    2572             : 
    2573           3 :     if ( m_Areas->getCount() > 1 )
    2574             :     {
    2575           0 :         sal_Int32 nItems = m_Areas->getCount();
    2576           0 :         uno::Any aResult = aNULL();
    2577           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2578             :         {
    2579           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2580             :             // if the numberformat of one area is different to another
    2581             :             // return null
    2582           0 :             if ( index > 1 )
    2583           0 :                 if ( aResult != xRange->getNumberFormat() )
    2584           0 :                     return aNULL();
    2585           0 :             aResult = xRange->getNumberFormat();
    2586           0 :             if ( aNULL() == aResult )
    2587           0 :                 return aNULL();
    2588           0 :         }
    2589           0 :         return aResult;
    2590             :     }
    2591           3 :     NumFormatHelper numFormat( mxRange );
    2592           6 :     OUString sFormat = numFormat.getNumberFormatString();
    2593           3 :     if ( !sFormat.isEmpty() )
    2594           2 :         return uno::makeAny( sFormat );
    2595           4 :     return aNULL();
    2596             : }
    2597             : 
    2598             : uno::Reference< excel::XRange >
    2599           2 : ScVbaRange::Resize( const uno::Any &RowSize, const uno::Any &ColumnSize ) throw (uno::RuntimeException, std::exception)
    2600             : {
    2601           2 :     long nRowSize = 0, nColumnSize = 0;
    2602           2 :     bool bIsRowChanged = ( RowSize >>= nRowSize ), bIsColumnChanged = ( ColumnSize >>= nColumnSize );
    2603           2 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, ::uno::UNO_QUERY_THROW);
    2604           4 :     uno::Reference< sheet::XSheetCellRange > xSheetRange(mxRange, ::uno::UNO_QUERY_THROW);
    2605           4 :     uno::Reference< sheet::XSheetCellCursor > xCursor( xSheetRange->getSpreadsheet()->createCursorByRange(xSheetRange), ::uno::UNO_QUERY_THROW );
    2606             : 
    2607           2 :     if( !bIsRowChanged )
    2608           0 :         nRowSize = xColumnRowRange->getRows()->getCount();
    2609           2 :     if( !bIsColumnChanged )
    2610           0 :         nColumnSize = xColumnRowRange->getColumns()->getCount();
    2611             : 
    2612           2 :     xCursor->collapseToSize( nColumnSize, nRowSize );
    2613           4 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xCursor, ::uno::UNO_QUERY_THROW );
    2614           4 :     uno::Reference< table::XCellRange > xRange( xSheetRange->getSpreadsheet(), ::uno::UNO_QUERY_THROW );
    2615           2 :     return new ScVbaRange( mxParent, mxContext,xRange->getCellRangeByPosition(
    2616           2 :                                         xCellRangeAddressable->getRangeAddress().StartColumn,
    2617           2 :                                         xCellRangeAddressable->getRangeAddress().StartRow,
    2618           2 :                                         xCellRangeAddressable->getRangeAddress().EndColumn,
    2619          12 :                                         xCellRangeAddressable->getRangeAddress().EndRow ) );
    2620             : }
    2621             : 
    2622             : void
    2623          18 : ScVbaRange::setWrapText( const uno::Any& aIsWrapped ) throw (script::BasicErrorException, uno::RuntimeException)
    2624             : {
    2625          18 :     if ( m_Areas->getCount() > 1 )
    2626             :     {
    2627           5 :         sal_Int32 nItems = m_Areas->getCount();
    2628          15 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2629             :         {
    2630          10 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2631          10 :             xRange->setWrapText( aIsWrapped );
    2632          10 :         }
    2633          10 :         return;
    2634             :     }
    2635             : 
    2636          13 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY_THROW );
    2637          13 :     bool bIsWrapped = extractBoolFromAny( aIsWrapped );
    2638          13 :     xProps->setPropertyValue( "IsTextWrapped", uno::Any( bIsWrapped ) );
    2639             : }
    2640             : 
    2641             : uno::Any
    2642          34 : ScVbaRange::getWrapText() throw (script::BasicErrorException, uno::RuntimeException)
    2643             : {
    2644          34 :     if ( m_Areas->getCount() > 1 )
    2645             :     {
    2646           5 :         sal_Int32 nItems = m_Areas->getCount();
    2647           5 :         uno::Any aResult;
    2648          14 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2649             :         {
    2650          10 :                 uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2651          10 :                 if ( index > 1 )
    2652           5 :                 if ( aResult != xRange->getWrapText() )
    2653           1 :                     return aNULL();
    2654           9 :             aResult = xRange->getWrapText();
    2655           9 :         }
    2656           4 :         return aResult;
    2657             :     }
    2658             : 
    2659          29 :     SfxItemSet* pDataSet = getCurrentDataSet();
    2660             : 
    2661          29 :     SfxItemState eState = pDataSet->GetItemState( ATTR_LINEBREAK, true, NULL);
    2662          29 :     if ( eState == SfxItemState::DONTCARE )
    2663           1 :         return aNULL();
    2664             : 
    2665          28 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY_THROW );
    2666          56 :     uno::Any aValue = xProps->getPropertyValue( "IsTextWrapped" );
    2667          56 :     return aValue;
    2668             : }
    2669             : 
    2670           9 : uno::Reference< excel::XInterior > ScVbaRange::Interior( ) throw ( script::BasicErrorException, uno::RuntimeException)
    2671             : {
    2672           9 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    2673           9 :         return new ScVbaInterior ( this, mxContext, xProps, &getScDocument() );
    2674             : }
    2675             : uno::Reference< excel::XRange >
    2676         280 : ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2 ) throw (uno::RuntimeException, std::exception)
    2677             : {
    2678         280 :     return Range( Cell1, Cell2, false );
    2679             : }
    2680             : uno::Reference< excel::XRange >
    2681         845 : ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2, bool bForceUseInpuRangeTab ) throw (uno::RuntimeException)
    2682             : 
    2683             : {
    2684         845 :     uno::Reference< table::XCellRange > xCellRange = mxRange;
    2685             : 
    2686         845 :     if ( m_Areas->getCount() > 1 )
    2687             :     {
    2688           1 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
    2689           1 :         xCellRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    2690             :     }
    2691             :     else
    2692         844 :         xCellRange.set( mxRange );
    2693             : 
    2694        1690 :     RangeHelper thisRange( xCellRange );
    2695        1690 :     uno::Reference< table::XCellRange > xRanges = thisRange.getCellRangeFromSheet();
    2696        1690 :     uno::Reference< sheet::XCellRangeAddressable > xAddressable( xRanges, uno::UNO_QUERY_THROW );
    2697             : 
    2698             :     uno::Reference< table::XCellRange > xReferrer =
    2699        2535 :         xRanges->getCellRangeByPosition( getColumn()-1, getRow()-1,
    2700         845 :                 xAddressable->getRangeAddress().EndColumn,
    2701        4225 :                 xAddressable->getRangeAddress().EndRow );
    2702             :     // xAddressable now for this range
    2703         845 :     xAddressable.set( xReferrer, uno::UNO_QUERY_THROW );
    2704             : 
    2705         845 :     if( !Cell1.hasValue() )
    2706           0 :         throw uno::RuntimeException( "Invalid Argument" );
    2707             : 
    2708         845 :     table::CellRangeAddress resultAddress;
    2709         845 :     table::CellRangeAddress parentRangeAddress = xAddressable->getRangeAddress();
    2710             : 
    2711         845 :     ScRange aRange;
    2712             :     // Cell1 defined only
    2713         845 :     if ( !Cell2.hasValue() )
    2714             :     {
    2715         839 :         OUString sName;
    2716         839 :         Cell1 >>= sName;
    2717        1678 :         RangeHelper referRange( xReferrer );
    2718         839 :         table::CellRangeAddress referAddress = referRange.getCellRangeAddressable()->getRangeAddress();
    2719        1678 :         return getRangeForName( mxContext, sName, getScDocShell(), referAddress );
    2720             : 
    2721             :     }
    2722             :     else
    2723             :     {
    2724           6 :         table::CellRangeAddress  cell1, cell2;
    2725           6 :         cell1 = getCellRangeAddressForVBARange( Cell1, getScDocShell() );
    2726             :         // Cell1 & Cell2 defined
    2727             :         // Excel seems to combine the range as the range defined by
    2728             :         // the combination of Cell1 & Cell2
    2729             : 
    2730           6 :         cell2 = getCellRangeAddressForVBARange( Cell2, getScDocShell() );
    2731             : 
    2732           6 :         resultAddress.StartColumn = ( cell1.StartColumn <  cell2.StartColumn ) ? cell1.StartColumn : cell2.StartColumn;
    2733           6 :         resultAddress.StartRow = ( cell1.StartRow <  cell2.StartRow ) ? cell1.StartRow : cell2.StartRow;
    2734           6 :         resultAddress.EndColumn = ( cell1.EndColumn >  cell2.EndColumn ) ? cell1.EndColumn : cell2.EndColumn;
    2735           6 :         resultAddress.EndRow = ( cell1.EndRow >  cell2.EndRow ) ? cell1.EndRow : cell2.EndRow;
    2736           6 :         if ( bForceUseInpuRangeTab )
    2737             :         {
    2738             :             // this is a call from Application.Range( x,y )
    2739             :             // its possiblefor x or y to specify a different sheet from
    2740             :             // the current or active on ( but they must be the same )
    2741           2 :             if ( cell1.Sheet != cell2.Sheet )
    2742           0 :                 throw uno::RuntimeException();
    2743           2 :             parentRangeAddress.Sheet = cell1.Sheet;
    2744             :         }
    2745             :         else
    2746             :         {
    2747             :             // this is not a call from Application.Range( x,y )
    2748             :             // if a different sheet from this range is specified it's
    2749             :             // an error
    2750           4 :             if ( parentRangeAddress.Sheet != cell1.Sheet
    2751           3 :             || parentRangeAddress.Sheet != cell2.Sheet
    2752             :             )
    2753           1 :                 throw uno::RuntimeException();
    2754             : 
    2755             :         }
    2756           5 :         ScUnoConversion::FillScRange( aRange, resultAddress );
    2757             :     }
    2758           5 :     ScRange parentAddress;
    2759           5 :     ScUnoConversion::FillScRange( parentAddress, parentRangeAddress);
    2760           5 :     if ( aRange.aStart.Col() >= 0 && aRange.aStart.Row() >= 0 && aRange.aEnd.Col() >= 0 && aRange.aEnd.Row() >= 0 )
    2761             :     {
    2762           5 :         sal_Int32 nStartX = parentAddress.aStart.Col() + aRange.aStart.Col();
    2763           5 :         sal_Int32 nStartY = parentAddress.aStart.Row() + aRange.aStart.Row();
    2764           5 :         sal_Int32 nEndX = parentAddress.aStart.Col() + aRange.aEnd.Col();
    2765           5 :         sal_Int32 nEndY = parentAddress.aStart.Row() + aRange.aEnd.Row();
    2766             : 
    2767          10 :         if ( nStartX <= nEndX && nEndX <= parentAddress.aEnd.Col() &&
    2768          10 :              nStartY <= nEndY && nEndY <= parentAddress.aEnd.Row() )
    2769             :         {
    2770           5 :             ScRange aNew( (SCCOL)nStartX, (SCROW)nStartY, parentAddress.aStart.Tab(),
    2771          10 :                           (SCCOL)nEndX, (SCROW)nEndY, parentAddress.aEnd.Tab() );
    2772           5 :             xCellRange = new ScCellRangeObj( getScDocShell(), aNew );
    2773             :         }
    2774             :     }
    2775             : 
    2776         850 :     return new ScVbaRange( mxParent, mxContext, xCellRange );
    2777             : 
    2778             : }
    2779             : 
    2780             : // Allow access to underlying openoffice uno api ( useful for debugging
    2781             : // with openoffice basic )
    2782         375 : uno::Any SAL_CALL ScVbaRange::getCellRange(  ) throw (uno::RuntimeException, std::exception)
    2783             : {
    2784         375 :     uno::Any aAny;
    2785         375 :     if ( mxRanges.is() )
    2786           0 :         aAny <<= mxRanges;
    2787         375 :     else if ( mxRange.is() )
    2788         375 :         aAny <<= mxRange;
    2789         375 :     return aAny;
    2790             : }
    2791             : 
    2792         287 : uno::Any ScVbaRange::getCellRange( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
    2793             : {
    2794         287 :     if( ScVbaRange* pVbaRange = getImplementation( rxRange ) )
    2795         574 :         return pVbaRange->getCellRange();
    2796           0 :     throw uno::RuntimeException();
    2797             : }
    2798             : 
    2799          12 : static InsertDeleteFlags getPasteFlags (sal_Int32 Paste)
    2800             : {
    2801          12 :     InsertDeleteFlags nFlags = IDF_NONE;
    2802          12 :     switch (Paste) {
    2803             :         case excel::XlPasteType::xlPasteComments:
    2804           0 :         nFlags = IDF_NOTE;break;
    2805             :         case excel::XlPasteType::xlPasteFormats:
    2806           1 :         nFlags = IDF_ATTRIB;break;
    2807             :         case excel::XlPasteType::xlPasteFormulas:
    2808           1 :         nFlags = IDF_FORMULA;break;
    2809             :         case excel::XlPasteType::xlPasteFormulasAndNumberFormats :
    2810             :         case excel::XlPasteType::xlPasteValues:
    2811           1 :         nFlags = ( IDF_VALUE | IDF_DATETIME | IDF_STRING | IDF_SPECIAL_BOOLEAN ); break;
    2812             :         case excel::XlPasteType::xlPasteValuesAndNumberFormats:
    2813           0 :         nFlags = IDF_VALUE | IDF_ATTRIB; break;
    2814             :         case excel::XlPasteType::xlPasteColumnWidths:
    2815             :         case excel::XlPasteType::xlPasteValidation:
    2816           0 :         nFlags = IDF_NONE;break;
    2817             :     case excel::XlPasteType::xlPasteAll:
    2818             :         case excel::XlPasteType::xlPasteAllExceptBorders:
    2819             :     default:
    2820           9 :         nFlags = IDF_ALL;break;
    2821             :     }
    2822          12 :     return nFlags;
    2823             : }
    2824             : 
    2825             : static sal_uInt16
    2826          12 : getPasteFormulaBits( sal_Int32 Operation)
    2827             : {
    2828          12 :     sal_uInt16 nFormulaBits = PASTE_NOFUNC ;
    2829          12 :     switch (Operation)
    2830             :     {
    2831             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationAdd:
    2832           1 :         nFormulaBits = PASTE_ADD;break;
    2833             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationSubtract:
    2834           1 :         nFormulaBits = PASTE_SUB;break;
    2835             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationMultiply:
    2836           1 :         nFormulaBits = PASTE_MUL;break;
    2837             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationDivide:
    2838           1 :         nFormulaBits = PASTE_DIV;break;
    2839             : 
    2840             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationNone:
    2841             :     default:
    2842           8 :         nFormulaBits = PASTE_NOFUNC; break;
    2843             :     }
    2844             : 
    2845          12 : return nFormulaBits;
    2846             : }
    2847             : void SAL_CALL
    2848          12 : ScVbaRange::PasteSpecial( const uno::Any& Paste, const uno::Any& Operation, const uno::Any& SkipBlanks, const uno::Any& Transpose ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2849             : {
    2850          12 :     if ( m_Areas->getCount() > 1 )
    2851           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2852          12 :     ScDocShell* pShell = getScDocShell();
    2853             : 
    2854          12 :     if (!pShell)
    2855           0 :         throw uno::RuntimeException("That command cannot be used with no ScDocShell" );
    2856             : 
    2857          12 :     uno::Reference< frame::XModel > xModel(pShell->GetModel(), uno::UNO_QUERY_THROW);
    2858          24 :     uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2859             :     // select this range
    2860          12 :     xSelection->select( uno::makeAny( mxRange ) );
    2861             :     // set up defaults
    2862          12 :     sal_Int32 nPaste = excel::XlPasteType::xlPasteAll;
    2863          12 :     sal_Int32 nOperation = excel::XlPasteSpecialOperation::xlPasteSpecialOperationNone;
    2864          12 :     bool bTranspose = false;
    2865          12 :     bool bSkipBlanks = false;
    2866             : 
    2867          12 :     if ( Paste.hasValue() )
    2868           3 :         Paste >>= nPaste;
    2869          12 :     if ( Operation.hasValue() )
    2870           4 :         Operation >>= nOperation;
    2871          12 :     if ( SkipBlanks.hasValue() )
    2872           1 :         SkipBlanks >>= bSkipBlanks;
    2873          12 :     if ( Transpose.hasValue() )
    2874           1 :         Transpose >>= bTranspose;
    2875             : 
    2876          12 :     InsertDeleteFlags nFlags = getPasteFlags(nPaste);
    2877          12 :     sal_uInt16 nFormulaBits = getPasteFormulaBits(nOperation);
    2878          24 :     excel::implnPasteSpecial(pShell->GetModel(), nFlags,nFormulaBits,bSkipBlanks,bTranspose);
    2879          12 : }
    2880             : 
    2881             : uno::Reference< excel::XRange >
    2882          18 : ScVbaRange::getEntireColumnOrRow( bool bColumn ) throw (uno::RuntimeException)
    2883             : {
    2884          18 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2885             :     // copy the range list
    2886          18 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2887             : 
    2888          45 :     for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    2889             :     {
    2890          27 :         ScRange* pRange = aCellRanges[ i ];
    2891          27 :         if ( bColumn )
    2892             :         {
    2893          14 :             pRange->aStart.SetRow( 0 );
    2894          14 :             pRange->aEnd.SetRow( MAXROW );
    2895             :         }
    2896             :         else
    2897             :         {
    2898          13 :             pRange->aStart.SetCol( 0 );
    2899          13 :             pRange->aEnd.SetCol( MAXCOL );
    2900             :         }
    2901             :     }
    2902          18 :     if ( aCellRanges.size() > 1 ) // Multi-Area
    2903             :     {
    2904           9 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pUnoRangesBase->GetDocShell(), aCellRanges ) );
    2905             : 
    2906           9 :         return new ScVbaRange( mxParent, mxContext, xRanges, !bColumn, bColumn );
    2907             :     }
    2908          18 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), *aCellRanges.front() ) );
    2909          27 :     return new ScVbaRange( mxParent, mxContext, xRange, !bColumn, bColumn  );
    2910             : }
    2911             : 
    2912             : uno::Reference< excel::XRange > SAL_CALL
    2913           9 : ScVbaRange::getEntireRow() throw (uno::RuntimeException, std::exception)
    2914             : {
    2915           9 :     return getEntireColumnOrRow(false);
    2916             : }
    2917             : 
    2918             : uno::Reference< excel::XRange > SAL_CALL
    2919           9 : ScVbaRange::getEntireColumn() throw (uno::RuntimeException, std::exception)
    2920             : {
    2921           9 :     return getEntireColumnOrRow();
    2922             : }
    2923             : 
    2924             : uno::Reference< excel::XComment > SAL_CALL
    2925           0 : ScVbaRange::AddComment( const uno::Any& Text ) throw (uno::RuntimeException, std::exception)
    2926             : {
    2927             :     // if there is already a comment in the top-left cell then throw
    2928           0 :     if( getComment().is() )
    2929           0 :         throw uno::RuntimeException();
    2930             : 
    2931             :     // workaround: Excel allows to create empty comment, Calc does not
    2932           0 :     OUString aNoteText;
    2933           0 :     if( Text.hasValue() && !(Text >>= aNoteText) )
    2934           0 :         throw uno::RuntimeException();
    2935           0 :     if( aNoteText.isEmpty() )
    2936           0 :         aNoteText = " ";
    2937             : 
    2938             :     // try to create a new annotation
    2939           0 :     table::CellRangeAddress aRangePos = lclGetRangeAddress( mxRange );
    2940           0 :     table::CellAddress aNotePos( aRangePos.Sheet, aRangePos.StartColumn, aRangePos.StartRow );
    2941           0 :     uno::Reference< sheet::XSheetCellRange > xCellRange( mxRange, uno::UNO_QUERY_THROW );
    2942           0 :     uno::Reference< sheet::XSheetAnnotationsSupplier > xAnnosSupp( xCellRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
    2943           0 :     uno::Reference< sheet::XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), uno::UNO_SET_THROW );
    2944           0 :     xAnnos->insertNew( aNotePos, aNoteText );
    2945           0 :     return new ScVbaComment( this, mxContext, getUnoModel(), mxRange );
    2946             : }
    2947             : 
    2948             : uno::Reference< excel::XComment > SAL_CALL
    2949           0 : ScVbaRange::getComment() throw (uno::RuntimeException, std::exception)
    2950             : {
    2951             :     // intentional behavior to return a null object if no
    2952             :     // comment defined
    2953           0 :     uno::Reference< excel::XComment > xComment( new ScVbaComment( this, mxContext, getUnoModel(), mxRange ) );
    2954           0 :     if ( xComment->Text( uno::Any(), uno::Any(), uno::Any() ).isEmpty() )
    2955           0 :         return NULL;
    2956           0 :     return xComment;
    2957             : 
    2958             : }
    2959             : 
    2960             : uno::Reference< beans::XPropertySet >
    2961          87 : getRowOrColumnProps( const uno::Reference< table::XCellRange >& xCellRange, bool bRows ) throw ( uno::RuntimeException )
    2962             : {
    2963          87 :     uno::Reference< table::XColumnRowRange > xColRow( xCellRange, uno::UNO_QUERY_THROW );
    2964          87 :     uno::Reference< beans::XPropertySet > xProps;
    2965          87 :     if ( bRows )
    2966          53 :         xProps.set( xColRow->getRows(), uno::UNO_QUERY_THROW );
    2967             :     else
    2968          34 :         xProps.set( xColRow->getColumns(), uno::UNO_QUERY_THROW );
    2969          87 :     return xProps;
    2970             : }
    2971             : 
    2972             : uno::Any SAL_CALL
    2973          71 : ScVbaRange::getHidden() throw (uno::RuntimeException, std::exception)
    2974             : {
    2975             :     // if multi-area result is the result of the
    2976             :     // first area
    2977          71 :     if ( m_Areas->getCount() > 1 )
    2978             :     {
    2979           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(sal_Int32(1)), uno::Any() ), uno::UNO_QUERY_THROW );
    2980           0 :         return xRange->getHidden();
    2981             :     }
    2982          71 :     bool bIsVisible = false;
    2983             :     try
    2984             :     {
    2985          71 :         uno::Reference< beans::XPropertySet > xProps = getRowOrColumnProps( mxRange, mbIsRows );
    2986          71 :         if ( !( xProps->getPropertyValue( ISVISIBLE ) >>= bIsVisible ) )
    2987           0 :             throw uno::RuntimeException("Failed to get IsVisible property" );
    2988             :     }
    2989           0 :     catch( const uno::Exception& e )
    2990             :     {
    2991           0 :         throw uno::RuntimeException( e.Message );
    2992             :     }
    2993          71 :     return uno::makeAny( !bIsVisible );
    2994             : }
    2995             : 
    2996             : void SAL_CALL
    2997          16 : ScVbaRange::setHidden( const uno::Any& _hidden ) throw (uno::RuntimeException, std::exception)
    2998             : {
    2999          16 :     if ( m_Areas->getCount() > 1 )
    3000             :     {
    3001           0 :         sal_Int32 nItems = m_Areas->getCount();
    3002           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    3003             :         {
    3004           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    3005           0 :             xRange->setHidden( _hidden );
    3006           0 :         }
    3007          16 :         return;
    3008             :     }
    3009             : 
    3010          16 :     bool bHidden = extractBoolFromAny( _hidden );
    3011             :     try
    3012             :     {
    3013          16 :         uno::Reference< beans::XPropertySet > xProps = getRowOrColumnProps( mxRange, mbIsRows );
    3014          16 :         xProps->setPropertyValue( ISVISIBLE, uno::Any( !bHidden ) );
    3015             :     }
    3016           0 :     catch( const uno::Exception& e )
    3017             :     {
    3018           0 :         throw uno::RuntimeException( e.Message );
    3019             :     }
    3020             : }
    3021             : 
    3022             : sal_Bool SAL_CALL
    3023          25 : ScVbaRange::Replace( const OUString& What, const OUString& Replacement, const uno::Any& LookAt, const uno::Any& SearchOrder, const uno::Any& MatchCase, const uno::Any& MatchByte, const uno::Any& SearchFormat, const uno::Any& ReplaceFormat  ) throw (uno::RuntimeException, std::exception)
    3024             : {
    3025          25 :     if ( m_Areas->getCount() > 1 )
    3026             :     {
    3027          21 :         for ( sal_Int32 index = 1; index <= m_Areas->getCount(); ++index )
    3028             :         {
    3029          14 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    3030          14 :             xRange->Replace( What, Replacement,  LookAt, SearchOrder, MatchCase, MatchByte, SearchFormat, ReplaceFormat );
    3031          14 :         }
    3032           7 :         return sal_True; // seems to return true always ( or at least I haven't found the trick of
    3033             :     }
    3034             : 
    3035             :     // sanity check required params
    3036          18 :     if ( What.isEmpty()  )
    3037           0 :         throw uno::RuntimeException("Range::Replace, missing params" );
    3038          18 :     OUString sWhat = VBAToRegexp( What);
    3039             :     // #TODO #FIXME SearchFormat & ReplacesFormat are not processed
    3040             :     // What do we do about MatchByte.. we don't seem to support that
    3041          18 :     const SvxSearchItem& globalSearchOptions = ScGlobal::GetSearchItem();
    3042          36 :     SvxSearchItem newOptions( globalSearchOptions );
    3043             : 
    3044          18 :     sal_Int16 nLook =  globalSearchOptions.GetWordOnly() ?  excel::XlLookAt::xlPart : excel::XlLookAt::xlWhole;
    3045          18 :     sal_Int16 nSearchOrder = globalSearchOptions.GetRowDirection() ? excel::XlSearchOrder::xlByRows : excel::XlSearchOrder::xlByColumns;
    3046             : 
    3047          36 :     uno::Reference< util::XReplaceable > xReplace( mxRange, uno::UNO_QUERY );
    3048          18 :     if ( xReplace.is() )
    3049             :     {
    3050             :         uno::Reference< util::XReplaceDescriptor > xDescriptor =
    3051          18 :             xReplace->createReplaceDescriptor();
    3052             : 
    3053          18 :         xDescriptor->setSearchString( sWhat);
    3054          18 :         xDescriptor->setPropertyValue( SC_UNO_SRCHREGEXP, uno::makeAny( sal_True ) );
    3055          18 :         xDescriptor->setReplaceString( Replacement);
    3056          18 :         if ( LookAt.hasValue() )
    3057             :         {
    3058             :             // sets SearchWords ( true is Cell match )
    3059           6 :             nLook =  ::comphelper::getINT16( LookAt );
    3060           6 :             bool bSearchWords = false;
    3061           6 :             if ( nLook == excel::XlLookAt::xlPart )
    3062           4 :                 bSearchWords = false;
    3063           2 :             else if ( nLook == excel::XlLookAt::xlWhole )
    3064           2 :                 bSearchWords = true;
    3065             :             else
    3066           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for LookAt" );
    3067             :             // set global search props ( affects the find dialog
    3068             :             // and of course the defaults for this method
    3069           6 :             newOptions.SetWordOnly( bSearchWords );
    3070           6 :             xDescriptor->setPropertyValue( SC_UNO_SRCHWORDS, uno::makeAny( bSearchWords ) );
    3071             :         }
    3072             :         // sets SearchByRow ( true for Rows )
    3073          18 :         if ( SearchOrder.hasValue() )
    3074             :         {
    3075          17 :             nSearchOrder =  ::comphelper::getINT16( SearchOrder );
    3076          17 :             bool bSearchByRow = false;
    3077          17 :             if ( nSearchOrder == excel::XlSearchOrder::xlByColumns )
    3078          17 :                 bSearchByRow = false;
    3079           0 :             else if ( nSearchOrder == excel::XlSearchOrder::xlByRows )
    3080           0 :                 bSearchByRow = true;
    3081             :             else
    3082           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for SearchOrder" );
    3083             : 
    3084          17 :             newOptions.SetRowDirection( bSearchByRow );
    3085          17 :             xDescriptor->setPropertyValue( SC_UNO_SRCHBYROW, uno::makeAny( bSearchByRow ) );
    3086             :         }
    3087          18 :         if ( MatchCase.hasValue() )
    3088             :         {
    3089          17 :             bool bMatchCase = false;
    3090             : 
    3091             :             // SearchCaseSensitive
    3092          17 :             MatchCase >>= bMatchCase;
    3093          17 :             xDescriptor->setPropertyValue( SC_UNO_SRCHCASE, uno::makeAny( bMatchCase ) );
    3094             :         }
    3095             : 
    3096          18 :         ScGlobal::SetSearchItem( newOptions );
    3097             :         // ignore MatchByte for the moment, its not supported in
    3098             :         // OOo.org afaik
    3099             : 
    3100          36 :         uno::Reference< util::XSearchDescriptor > xSearch( xDescriptor, uno::UNO_QUERY );
    3101          36 :         uno::Reference< container::XIndexAccess > xIndexAccess = xReplace->findAll( xSearch );
    3102          18 :         xReplace->replaceAll( xSearch );
    3103          18 :         if ( xIndexAccess.is() && xIndexAccess->getCount() > 0 )
    3104             :         {
    3105          32 :             for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); ++i )
    3106             :             {
    3107          18 :                 uno::Reference< table::XCellRange > xCellRange( xIndexAccess->getByIndex( i ), uno::UNO_QUERY );
    3108          18 :                 if ( xCellRange.is() )
    3109             :                 {
    3110          18 :                     uno::Reference< excel::XRange > xRange( new ScVbaRange( mxParent, mxContext, xCellRange ) );
    3111          36 :                     uno::Reference< container::XEnumerationAccess > xEnumAccess( xRange, uno::UNO_QUERY_THROW );
    3112          36 :                     uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
    3113         305 :                     while ( xEnum->hasMoreElements() )
    3114             :                     {
    3115         269 :                         uno::Reference< excel::XRange > xNextRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
    3116         269 :                         ScVbaRange* pRange = dynamic_cast< ScVbaRange * > ( xNextRange.get() );
    3117         269 :                         if ( pRange )
    3118         269 :                             pRange->fireChangeEvent();
    3119         287 :                     }
    3120             :                 }
    3121          18 :             }
    3122          18 :         }
    3123             :     }
    3124          36 :     return sal_True; // always
    3125             : }
    3126             : 
    3127             : uno::Reference< excel::XRange > SAL_CALL
    3128           4 : ScVbaRange::Find( const uno::Any& What, const uno::Any& After, const uno::Any& LookIn, const uno::Any& LookAt, const uno::Any& SearchOrder, const uno::Any& SearchDirection, const uno::Any& MatchCase, const uno::Any& /*MatchByte*/, const uno::Any& /*SearchFormat*/ ) throw (uno::RuntimeException, std::exception)
    3129             : {
    3130             :     // return a Range object that represents the first cell where that information is found.
    3131           4 :     OUString sWhat;
    3132           4 :     sal_Int32 nWhat = 0;
    3133           4 :     double fWhat = 0.0;
    3134             : 
    3135             :     // string.
    3136           4 :     if( What >>= sWhat )
    3137             :     {
    3138           4 :         if( sWhat.isEmpty() )
    3139           0 :             throw uno::RuntimeException("Range::Find, missing params" );
    3140             :     }
    3141           0 :     else if( What >>= nWhat )
    3142             :     {
    3143           0 :         sWhat = OUString::number( nWhat );
    3144             :     }
    3145           0 :     else if( What >>= fWhat )
    3146             :     {
    3147           0 :         sWhat = OUString::number( fWhat );
    3148             :     }
    3149             :     else
    3150           0 :         throw uno::RuntimeException("Range::Find, missing params" );
    3151             : 
    3152           8 :     OUString sSearch = VBAToRegexp( sWhat );
    3153             : 
    3154           4 :     const SvxSearchItem& globalSearchOptions = ScGlobal::GetSearchItem();
    3155           8 :     SvxSearchItem newOptions( globalSearchOptions );
    3156             : 
    3157           4 :     sal_Int16 nSearchOrder = globalSearchOptions.GetRowDirection() ? excel::XlSearchOrder::xlByRows : excel::XlSearchOrder::xlByColumns;
    3158             : 
    3159           8 :     uno::Reference< util::XSearchable > xSearch( mxRange, uno::UNO_QUERY );
    3160           4 :     if( xSearch.is() )
    3161             :     {
    3162           4 :         uno::Reference< util::XSearchDescriptor > xDescriptor = xSearch->createSearchDescriptor();
    3163           4 :         xDescriptor->setSearchString( sSearch );
    3164           4 :         xDescriptor->setPropertyValue( SC_UNO_SRCHREGEXP, uno::Any( true ) );
    3165             : 
    3166           4 :         uno::Reference< excel::XRange > xAfterRange;
    3167           4 :         uno::Reference< table::XCellRange > xStartCell;
    3168           4 :         if( After >>= xAfterRange )
    3169             :         {
    3170             :             // After must be a single cell in the range
    3171           4 :             if( xAfterRange->getCount() > 1 )
    3172           0 :                 throw uno::RuntimeException("After must be a single cell." );
    3173           4 :             uno::Reference< excel::XRange > xCell( Cells( uno::makeAny( xAfterRange->getRow() ), uno::makeAny( xAfterRange->getColumn() ) ), uno::UNO_QUERY );
    3174           4 :             if( !xCell.is() )
    3175           0 :                 throw uno::RuntimeException("After must be in range." );
    3176           4 :             xStartCell.set( xAfterRange->getCellRange(), uno::UNO_QUERY_THROW );
    3177             :         }
    3178             : 
    3179             :         // LookIn
    3180           4 :         if( LookIn.hasValue() )
    3181             :         {
    3182           4 :             sal_Int32 nLookIn = 0;
    3183           4 :             if( LookIn >>= nLookIn )
    3184             :             {
    3185             :                 SvxSearchCellType nSearchType;
    3186           4 :                 switch( nLookIn )
    3187             :                 {
    3188             :                     case excel::XlFindLookIn::xlComments :
    3189           0 :                         nSearchType = SvxSearchCellType::NOTE; // Notes
    3190           0 :                     break;
    3191             :                     case excel::XlFindLookIn::xlFormulas :
    3192           0 :                         nSearchType = SvxSearchCellType::FORMULA;
    3193           0 :                     break;
    3194             :                     case excel::XlFindLookIn::xlValues :
    3195           4 :                         nSearchType = SvxSearchCellType::VALUE;
    3196           4 :                     break;
    3197             :                     default:
    3198           0 :                         throw uno::RuntimeException("Range::Replace, illegal value for LookIn." );
    3199             :                 }
    3200           4 :                 newOptions.SetCellType( nSearchType );
    3201           4 :                 xDescriptor->setPropertyValue( "SearchType", uno::makeAny( static_cast<sal_uInt16>(nSearchType) ) );
    3202             :             }
    3203             :         }
    3204             : 
    3205             :         // LookAt
    3206           4 :         if ( LookAt.hasValue() )
    3207             :         {
    3208           0 :             sal_Int16 nLookAt = ::comphelper::getINT16( LookAt );
    3209           0 :             bool bSearchWords = false;
    3210           0 :             if ( nLookAt == excel::XlLookAt::xlPart )
    3211           0 :                 bSearchWords = false;
    3212           0 :             else if ( nLookAt == excel::XlLookAt::xlWhole )
    3213           0 :                 bSearchWords = true;
    3214             :             else
    3215           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for LookAt" );
    3216           0 :             newOptions.SetWordOnly( bSearchWords );
    3217           0 :             xDescriptor->setPropertyValue( SC_UNO_SRCHWORDS, uno::makeAny( bSearchWords ) );
    3218             :         }
    3219             : 
    3220             :         // SearchOrder
    3221           4 :         if ( SearchOrder.hasValue() )
    3222             :         {
    3223           4 :             nSearchOrder =  ::comphelper::getINT16( SearchOrder );
    3224           4 :             bool bSearchByRow = false;
    3225           4 :             if ( nSearchOrder == excel::XlSearchOrder::xlByColumns )
    3226           0 :                 bSearchByRow = false;
    3227           4 :             else if ( nSearchOrder == excel::XlSearchOrder::xlByRows )
    3228           4 :                 bSearchByRow = true;
    3229             :             else
    3230           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for SearchOrder" );
    3231             : 
    3232           4 :             newOptions.SetRowDirection( bSearchByRow );
    3233           4 :             xDescriptor->setPropertyValue( SC_UNO_SRCHBYROW, uno::makeAny( bSearchByRow ) );
    3234             :         }
    3235             : 
    3236             :         // SearchDirection
    3237           4 :         if ( SearchDirection.hasValue() )
    3238             :         {
    3239           4 :             sal_Int32 nSearchDirection = 0;
    3240           4 :             if( SearchDirection >>= nSearchDirection )
    3241             :             {
    3242           4 :                 bool bSearchBackwards = false;
    3243           4 :                 if ( nSearchDirection == excel::XlSearchDirection::xlNext )
    3244           0 :                     bSearchBackwards = false;
    3245           4 :                 else if( nSearchDirection == excel::XlSearchDirection::xlPrevious )
    3246           4 :                     bSearchBackwards = true;
    3247             :                 else
    3248           0 :                     throw uno::RuntimeException("Range::Replace, illegal value for SearchDirection" );
    3249           4 :                 newOptions.SetBackward( bSearchBackwards );
    3250           4 :                 xDescriptor->setPropertyValue( "SearchBackwards", uno::makeAny( bSearchBackwards ) );
    3251             :             }
    3252             :         }
    3253             : 
    3254             :         // MatchCase
    3255           4 :         bool bMatchCase = false;
    3256           4 :         if ( MatchCase.hasValue() )
    3257             :         {
    3258             :             // SearchCaseSensitive
    3259           0 :             if( !( MatchCase >>= bMatchCase ) )
    3260           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for MatchCase" );
    3261             :         }
    3262           4 :         xDescriptor->setPropertyValue( SC_UNO_SRCHCASE, uno::makeAny( bMatchCase ) );
    3263             : 
    3264             :         // MatchByte
    3265             :         // SearchFormat
    3266             :         // ignore
    3267             : 
    3268           4 :         ScGlobal::SetSearchItem( newOptions );
    3269             : 
    3270           4 :         uno::Reference< uno::XInterface > xInterface = xStartCell.is() ? xSearch->findNext( xStartCell, xDescriptor) : xSearch->findFirst( xDescriptor );
    3271           4 :         uno::Reference< table::XCellRange > xCellRange( xInterface, uno::UNO_QUERY );
    3272             :         // if we are searching from a starting cell and failed to find a match
    3273             :         // then try from the beginning
    3274           4 :         if ( !xCellRange.is() && xStartCell.is() )
    3275             :         {
    3276           4 :             xInterface = xSearch->findFirst( xDescriptor );
    3277           4 :             xCellRange.set( xInterface, uno::UNO_QUERY );
    3278             :         }
    3279           4 :         if ( xCellRange.is() )
    3280             :         {
    3281           4 :             uno::Reference< excel::XRange > xResultRange = new ScVbaRange( mxParent, mxContext, xCellRange );
    3282           4 :             if( xResultRange.is() )
    3283             :             {
    3284           4 :                 return xResultRange;
    3285           0 :             }
    3286           0 :         }
    3287             : 
    3288             :     }
    3289             : 
    3290           4 :     return uno::Reference< excel::XRange >();
    3291             : }
    3292             : 
    3293           0 : uno::Reference< table::XCellRange > processKey( const uno::Any& Key, uno::Reference<  uno::XComponentContext >& xContext, ScDocShell* pDocSh )
    3294             : {
    3295           0 :     uno::Reference< excel::XRange > xKeyRange;
    3296           0 :     if ( Key.getValueType() == cppu::UnoType<excel::XRange>::get() )
    3297             :     {
    3298           0 :         xKeyRange.set( Key, uno::UNO_QUERY_THROW );
    3299             :     }
    3300           0 :     else if ( Key.getValueType() == ::cppu::UnoType<OUString>::get()  )
    3301             : 
    3302             :     {
    3303           0 :         OUString sRangeName = ::comphelper::getString( Key );
    3304           0 :         table::CellRangeAddress  aRefAddr;
    3305           0 :         if ( !pDocSh )
    3306           0 :             throw uno::RuntimeException("Range::Sort no docshell to calculate key param" );
    3307           0 :         xKeyRange = getRangeForName( xContext, sRangeName, pDocSh, aRefAddr );
    3308             :     }
    3309             :     else
    3310           0 :         throw uno::RuntimeException("Range::Sort illegal type value for key param" );
    3311           0 :     uno::Reference< table::XCellRange > xKey;
    3312           0 :     xKey.set( xKeyRange->getCellRange(), uno::UNO_QUERY_THROW );
    3313           0 :     return xKey;
    3314             : }
    3315             : 
    3316             : // helper method for Sort
    3317           0 : sal_Int32 findSortPropertyIndex( const uno::Sequence< beans::PropertyValue >& props,
    3318             : const OUString& sPropName ) throw( uno::RuntimeException )
    3319             : {
    3320           0 :     const beans::PropertyValue* pProp = props.getConstArray();
    3321           0 :     sal_Int32 nItems = props.getLength();
    3322             : 
    3323           0 :      sal_Int32 count=0;
    3324           0 :     for ( ; count < nItems; ++count, ++pProp )
    3325           0 :         if ( pProp->Name.equals( sPropName ) )
    3326           0 :             return count;
    3327           0 :     if ( count == nItems )
    3328           0 :         throw uno::RuntimeException("Range::Sort unknown sort property" );
    3329           0 :     return -1; //should never reach here ( satisfy compiler )
    3330             : }
    3331             : 
    3332             : // helper method for Sort
    3333           0 : void updateTableSortField( const uno::Reference< table::XCellRange >& xParentRange,
    3334             :     const uno::Reference< table::XCellRange >& xColRowKey, sal_Int16 nOrder,
    3335             :     table::TableSortField& aTableField, bool bIsSortColumn, bool bMatchCase ) throw ( uno::RuntimeException )
    3336             : {
    3337           0 :         RangeHelper parentRange( xParentRange );
    3338           0 :         RangeHelper colRowRange( xColRowKey );
    3339             : 
    3340           0 :         table::CellRangeAddress parentRangeAddress = parentRange.getCellRangeAddressable()->getRangeAddress();
    3341             : 
    3342           0 :         table::CellRangeAddress colRowKeyAddress = colRowRange.getCellRangeAddressable()->getRangeAddress();
    3343             : 
    3344             :         // make sure that upper left poing of key range is within the
    3345             :         // parent range
    3346           0 :         if (  ( !bIsSortColumn && colRowKeyAddress.StartColumn >= parentRangeAddress.StartColumn &&
    3347           0 :             colRowKeyAddress.StartColumn <= parentRangeAddress.EndColumn ) || ( bIsSortColumn &&
    3348           0 :             colRowKeyAddress.StartRow >= parentRangeAddress.StartRow &&
    3349           0 :             colRowKeyAddress.StartRow <= parentRangeAddress.EndRow  ) )
    3350             :         {
    3351             :             //determine col/row index
    3352           0 :             if ( bIsSortColumn )
    3353           0 :                 aTableField.Field = colRowKeyAddress.StartRow - parentRangeAddress.StartRow;
    3354             :             else
    3355           0 :                 aTableField.Field = colRowKeyAddress.StartColumn - parentRangeAddress.StartColumn;
    3356           0 :             aTableField.IsCaseSensitive = bMatchCase;
    3357             : 
    3358           0 :             if ( nOrder ==  excel::XlSortOrder::xlAscending )
    3359           0 :                 aTableField.IsAscending = sal_True;
    3360             :             else
    3361           0 :                 aTableField.IsAscending = false;
    3362             :         }
    3363             :         else
    3364           0 :             throw uno::RuntimeException("Illegal Key param" );
    3365             : 
    3366           0 : }
    3367             : 
    3368             : void SAL_CALL
    3369           0 : ScVbaRange::Sort( const uno::Any& Key1, const uno::Any& Order1, const uno::Any& Key2, const uno::Any& /*Type*/, const uno::Any& Order2, const uno::Any& Key3, const uno::Any& Order3, const uno::Any& Header, const uno::Any& OrderCustom, const uno::Any& MatchCase, const uno::Any& Orientation, const uno::Any& SortMethod,  const uno::Any& DataOption1, const uno::Any& DataOption2, const uno::Any& DataOption3  ) throw (uno::RuntimeException, std::exception)
    3370             : {
    3371             :     // #TODO# #FIXME# can we do something with Type
    3372           0 :     if ( m_Areas->getCount() > 1 )
    3373           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    3374             : 
    3375           0 :     sal_Int16 nDataOption1 = excel::XlSortDataOption::xlSortNormal;
    3376           0 :     sal_Int16 nDataOption2 = excel::XlSortDataOption::xlSortNormal;
    3377           0 :     sal_Int16 nDataOption3 = excel::XlSortDataOption::xlSortNormal;
    3378             : 
    3379           0 :     ScDocument& rDoc = getScDocument();
    3380             : 
    3381           0 :     RangeHelper thisRange( mxRange );
    3382           0 :     table::CellRangeAddress thisRangeAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3383           0 :     ScSortParam aSortParam;
    3384           0 :     SCTAB nTab = thisRangeAddress.Sheet;
    3385           0 :     rDoc.GetSortParam( aSortParam, nTab );
    3386             : 
    3387           0 :     if ( DataOption1.hasValue() )
    3388           0 :         DataOption1 >>= nDataOption1;
    3389           0 :     if ( DataOption2.hasValue() )
    3390           0 :         DataOption2 >>= nDataOption2;
    3391           0 :     if ( DataOption3.hasValue() )
    3392           0 :         DataOption3 >>= nDataOption3;
    3393             : 
    3394             :     // 1) #TODO #FIXME need to process DataOption[1..3] not used currently
    3395             :     // 2) #TODO #FIXME need to refactor this ( below ) into a IsSingleCell() method
    3396           0 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    3397             : 
    3398             :     // set up defaults
    3399             : 
    3400           0 :     sal_Int16 nOrder1 = aSortParam.maKeyState[1].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3401           0 :     sal_Int16 nOrder2 = aSortParam.maKeyState[2].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3402           0 :     sal_Int16 nOrder3 = aSortParam.maKeyState[3].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3403             : 
    3404           0 :     sal_Int16 nCustom = aSortParam.nUserIndex;
    3405           0 :     sal_Int16 nSortMethod = excel::XlSortMethod::xlPinYin;
    3406           0 :     bool bMatchCase = aSortParam.bCaseSens;
    3407             : 
    3408             :     // seems to work opposite to expected, see below
    3409           0 :     sal_Int16 nOrientation = aSortParam.bByRow ?  excel::XlSortOrientation::xlSortColumns :  excel::XlSortOrientation::xlSortRows;
    3410             : 
    3411           0 :     if ( Orientation.hasValue() )
    3412             :     {
    3413             :         // Documentation says xlSortRows is default but that doesn't appear to be
    3414             :         // the case. Also it appears that xlSortColumns is the default which
    3415             :         // strangely enough sorts by Row
    3416           0 :         nOrientation = ::comphelper::getINT16( Orientation );
    3417             :         // persist new option to be next calls default
    3418           0 :         if ( nOrientation == excel::XlSortOrientation::xlSortRows )
    3419           0 :             aSortParam.bByRow = false;
    3420             :         else
    3421           0 :             aSortParam.bByRow = true;
    3422             : 
    3423             :     }
    3424             : 
    3425           0 :     bool bIsSortColumns=false; // sort by row
    3426             : 
    3427           0 :     if ( nOrientation == excel::XlSortOrientation::xlSortRows )
    3428           0 :         bIsSortColumns = true;
    3429           0 :     sal_Int16 nHeader = 0;
    3430           0 :     nHeader = aSortParam.nCompatHeader;
    3431           0 :     bool bContainsHeader = false;
    3432             : 
    3433           0 :     if ( Header.hasValue() )
    3434             :     {
    3435           0 :         nHeader = ::comphelper::getINT16( Header );
    3436           0 :         aSortParam.nCompatHeader = nHeader;
    3437             :     }
    3438             : 
    3439           0 :     if ( nHeader == excel::XlYesNoGuess::xlGuess )
    3440             :     {
    3441           0 :         bool bHasColHeader = rDoc.HasColHeader(  static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), static_cast< SCCOL >( thisRangeAddress.EndColumn ), static_cast< SCROW >( thisRangeAddress.EndRow ), static_cast< SCTAB >( thisRangeAddress.Sheet ));
    3442           0 :         bool bHasRowHeader = rDoc.HasRowHeader(  static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), static_cast< SCCOL >( thisRangeAddress.EndColumn ), static_cast< SCROW >( thisRangeAddress.EndRow ), static_cast< SCTAB >( thisRangeAddress.Sheet ) );
    3443           0 :         if ( bHasColHeader || bHasRowHeader )
    3444           0 :             nHeader =  excel::XlYesNoGuess::xlYes;
    3445             :         else
    3446           0 :             nHeader =  excel::XlYesNoGuess::xlNo;
    3447           0 :         aSortParam.nCompatHeader = nHeader;
    3448             :     }
    3449             : 
    3450           0 :     if ( nHeader == excel::XlYesNoGuess::xlYes )
    3451           0 :         bContainsHeader = true;
    3452             : 
    3453           0 :     if ( SortMethod.hasValue() )
    3454             :     {
    3455           0 :         nSortMethod = ::comphelper::getINT16( SortMethod );
    3456             :     }
    3457             : 
    3458           0 :     if ( OrderCustom.hasValue() )
    3459             :     {
    3460           0 :         OrderCustom >>= nCustom;
    3461           0 :         --nCustom; // 0-based in OOo
    3462           0 :         aSortParam.nUserIndex = nCustom;
    3463             :     }
    3464             : 
    3465           0 :     if ( MatchCase.hasValue() )
    3466             :     {
    3467           0 :         MatchCase >>= bMatchCase;
    3468           0 :         aSortParam.bCaseSens = bMatchCase;
    3469             :     }
    3470             : 
    3471           0 :     if ( Order1.hasValue() )
    3472             :     {
    3473           0 :         nOrder1 = ::comphelper::getINT16(Order1);
    3474           0 :         if (  nOrder1 == excel::XlSortOrder::xlAscending )
    3475           0 :             aSortParam.maKeyState[0].bAscending  = true;
    3476             :         else
    3477           0 :             aSortParam.maKeyState[0].bAscending  = false;
    3478             : 
    3479             :     }
    3480           0 :     if ( Order2.hasValue() )
    3481             :     {
    3482           0 :         nOrder2 = ::comphelper::getINT16(Order2);
    3483           0 :         if ( nOrder2 == excel::XlSortOrder::xlAscending )
    3484           0 :             aSortParam.maKeyState[1].bAscending  = true;
    3485             :         else
    3486           0 :             aSortParam.maKeyState[1].bAscending  = false;
    3487             :     }
    3488           0 :     if ( Order3.hasValue() )
    3489             :     {
    3490           0 :         nOrder3 = ::comphelper::getINT16(Order3);
    3491           0 :         if ( nOrder3 == excel::XlSortOrder::xlAscending )
    3492           0 :             aSortParam.maKeyState[2].bAscending  = true;
    3493             :         else
    3494           0 :             aSortParam.maKeyState[2].bAscending  = false;
    3495             :     }
    3496             : 
    3497           0 :     uno::Reference< table::XCellRange > xKey1;
    3498           0 :     uno::Reference< table::XCellRange > xKey2;
    3499           0 :     uno::Reference< table::XCellRange > xKey3;
    3500           0 :     ScDocShell* pDocShell = getScDocShell();
    3501           0 :     xKey1 = processKey( Key1, mxContext, pDocShell );
    3502           0 :     if ( !xKey1.is() )
    3503           0 :         throw uno::RuntimeException("Range::Sort needs a key1 param" );
    3504             : 
    3505           0 :     if ( Key2.hasValue() )
    3506           0 :         xKey2 = processKey( Key2, mxContext, pDocShell );
    3507           0 :     if ( Key3.hasValue() )
    3508           0 :         xKey3 = processKey( Key3, mxContext, pDocShell );
    3509             : 
    3510           0 :     uno::Reference< util::XSortable > xSort( mxRange, uno::UNO_QUERY_THROW );
    3511           0 :     uno::Sequence< beans::PropertyValue > sortDescriptor = xSort->createSortDescriptor();
    3512           0 :     sal_Int32 nTableSortFieldIndex = findSortPropertyIndex( sortDescriptor, OUString( "SortFields" ) );
    3513             : 
    3514           0 :     uno::Sequence< table::TableSortField > sTableFields(1);
    3515           0 :     sal_Int32 nTableIndex = 0;
    3516           0 :     updateTableSortField(  mxRange, xKey1, nOrder1, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3517             : 
    3518           0 :     if ( xKey2.is() )
    3519             :     {
    3520           0 :         sTableFields.realloc( sTableFields.getLength() + 1 );
    3521           0 :         updateTableSortField(  mxRange, xKey2, nOrder2, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3522             :     }
    3523           0 :     if ( xKey3.is()  )
    3524             :     {
    3525           0 :         sTableFields.realloc( sTableFields.getLength() + 1 );
    3526           0 :         updateTableSortField(  mxRange, xKey3, nOrder3, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3527             :     }
    3528           0 :     sortDescriptor[ nTableSortFieldIndex ].Value <<= sTableFields;
    3529             : 
    3530           0 :     sal_Int32 nIndex =  findSortPropertyIndex( sortDescriptor,  OUString("IsSortColumns") );
    3531           0 :     sortDescriptor[ nIndex ].Value <<= bIsSortColumns;
    3532             : 
    3533           0 :     nIndex =    findSortPropertyIndex( sortDescriptor, CONTS_HEADER );
    3534           0 :     sortDescriptor[ nIndex ].Value <<= bContainsHeader;
    3535             : 
    3536           0 :     rDoc.SetSortParam( aSortParam, nTab );
    3537           0 :     xSort->sort( sortDescriptor );
    3538             : 
    3539             :     // #FIXME #TODO
    3540             :     // The SortMethod param is not processed ( not sure what its all about, need to
    3541           0 :     (void)nSortMethod;
    3542           0 : }
    3543             : 
    3544             : uno::Reference< excel::XRange > SAL_CALL
    3545          90 : ScVbaRange::End( ::sal_Int32 Direction )  throw (uno::RuntimeException, std::exception)
    3546             : {
    3547          90 :     if ( m_Areas->getCount() > 1 )
    3548             :     {
    3549           7 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    3550           7 :         return xRange->End( Direction );
    3551             :     }
    3552             : 
    3553             :     // #FIXME #TODO
    3554             :     // euch! found my orig implementation sucked, so
    3555             :     // trying this even suckier one ( really need to use/expose code in
    3556             :     // around  ScTabView::MoveCursorArea(), thats the bit that calcutes
    3557             :     // where the cursor should go )
    3558             :     // Main problem with this method is the ultra hacky attempt to preserve
    3559             :     // the ActiveCell, there should be no need to go to these extremes
    3560             : 
    3561             :     // Save ActiveSheet/ActiveCell pos ( to restore later )
    3562          83 :     uno::Any aDft;
    3563         166 :     uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
    3564         166 :     uno::Reference< excel::XWorksheet > sActiveSheet = xApplication->getActiveSheet();
    3565         166 :     OUString sActiveCell = xApplication->getActiveCell()->Address(aDft, aDft, aDft, aDft, aDft );
    3566             : 
    3567             :     // position current cell upper left of this range
    3568          83 :     Cells( uno::makeAny( (sal_Int32) 1 ), uno::makeAny( (sal_Int32) 1 ) )->Select();
    3569             : 
    3570         166 :     uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    3571             : 
    3572          83 :     SfxViewFrame* pViewFrame = excel::getViewFrame( xModel );
    3573          83 :     if ( pViewFrame )
    3574             :     {
    3575          83 :         SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
    3576             :         // Hoping this will make sure this slot is called
    3577             :         // synchronously
    3578         166 :         SfxBoolItem sfxAsync( SID_ASYNCHRON, false );
    3579          83 :         aArgs.Put( sfxAsync, sfxAsync.Which() );
    3580          83 :         SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
    3581             : 
    3582          83 :         sal_uInt16 nSID = 0;
    3583             : 
    3584          83 :         switch( Direction )
    3585             :         {
    3586             :             case excel::XlDirection::xlDown:
    3587          20 :                 nSID = SID_CURSORBLKDOWN;
    3588          20 :                 break;
    3589             :             case excel::XlDirection::xlUp:
    3590          21 :                 nSID = SID_CURSORBLKUP;
    3591          21 :                 break;
    3592             :             case excel::XlDirection::xlToLeft:
    3593          21 :                 nSID = SID_CURSORBLKLEFT;
    3594          21 :                 break;
    3595             :             case excel::XlDirection::xlToRight:
    3596          21 :                 nSID = SID_CURSORBLKRIGHT;
    3597          21 :                 break;
    3598             :             default:
    3599           0 :                 throw uno::RuntimeException(": Invalid ColumnIndex" );
    3600             :         }
    3601          83 :         if ( pDispatcher )
    3602             :         {
    3603          83 :             pDispatcher->Execute( nSID, (SfxCallMode)SfxCallMode::SYNCHRON, aArgs );
    3604          83 :         }
    3605             :     }
    3606             : 
    3607             :     // result is the ActiveCell
    3608          83 :     OUString sMoved =    xApplication->getActiveCell()->Address(aDft, aDft, aDft, aDft, aDft );
    3609             : 
    3610         166 :     uno::Any aVoid;
    3611         166 :     uno::Reference< excel::XRange > resultCell;
    3612          83 :     resultCell.set( xApplication->getActiveSheet()->Range( uno::makeAny( sMoved ), aVoid ), uno::UNO_QUERY_THROW );
    3613             : 
    3614             :     // restore old ActiveCell
    3615         166 :     uno::Reference< excel::XRange > xOldActiveCell( sActiveSheet->Range( uno::makeAny( sActiveCell ), aVoid ), uno::UNO_QUERY_THROW );
    3616          83 :     xOldActiveCell->Select();
    3617             : 
    3618             : 
    3619             :     // return result
    3620         249 :     return resultCell;
    3621             : }
    3622             : 
    3623             : bool
    3624         642 : ScVbaRange::isSingleCellRange()
    3625             : {
    3626         642 :     uno::Reference< sheet::XCellRangeAddressable > xAddressable( mxRange, uno::UNO_QUERY );
    3627         642 :     if ( xAddressable.is() )
    3628             :     {
    3629         641 :         table::CellRangeAddress aRangeAddr = xAddressable->getRangeAddress();
    3630         641 :         return ( aRangeAddr.EndColumn == aRangeAddr.StartColumn && aRangeAddr.EndRow == aRangeAddr.StartRow );
    3631             :     }
    3632           1 :     return false;
    3633             : }
    3634             : 
    3635             : uno::Reference< excel::XCharacters > SAL_CALL
    3636           0 : ScVbaRange::characters( const uno::Any& Start, const uno::Any& Length ) throw (uno::RuntimeException, std::exception)
    3637             : {
    3638           0 :     if ( !isSingleCellRange() )
    3639           0 :         throw uno::RuntimeException("Can't create Characters property for multicell range " );
    3640           0 :     uno::Reference< text::XSimpleText > xSimple(mxRange->getCellByPosition(0,0) , uno::UNO_QUERY_THROW );
    3641           0 :     ScDocument& rDoc = getDocumentFromRange(mxRange);
    3642             : 
    3643           0 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    3644           0 :     return new ScVbaCharacters( this, mxContext, aPalette, xSimple, Start, Length );
    3645             : }
    3646             : 
    3647             :  void SAL_CALL
    3648           3 : ScVbaRange::Delete( const uno::Any& Shift ) throw (uno::RuntimeException, std::exception)
    3649             : {
    3650           3 :     if ( m_Areas->getCount() > 1 )
    3651             :     {
    3652           0 :         sal_Int32 nItems = m_Areas->getCount();
    3653           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    3654             :         {
    3655           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    3656           0 :             xRange->Delete( Shift );
    3657           0 :         }
    3658           0 :         return;
    3659             :     }
    3660           3 :     sheet::CellDeleteMode mode = sheet::CellDeleteMode_NONE ;
    3661           3 :     RangeHelper thisRange( mxRange );
    3662           3 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3663           3 :     if ( Shift.hasValue() )
    3664             :     {
    3665           2 :         sal_Int32 nShift = 0;
    3666           2 :         Shift >>= nShift;
    3667           2 :         switch ( nShift )
    3668             :         {
    3669             :             case excel::XlDeleteShiftDirection::xlShiftUp:
    3670           1 :                 mode = sheet::CellDeleteMode_UP;
    3671           1 :                 break;
    3672             :             case excel::XlDeleteShiftDirection::xlShiftToLeft:
    3673           1 :                 mode = sheet::CellDeleteMode_LEFT;
    3674           1 :                 break;
    3675             :             default:
    3676           0 :                 throw uno::RuntimeException("Illegal parameter " );
    3677             :         }
    3678             :     }
    3679             :     else
    3680             :         {
    3681           1 :         bool bFullRow = ( thisAddress.StartColumn == 0 && thisAddress.EndColumn == MAXCOL );
    3682           1 :             sal_Int32 nCols = thisAddress.EndColumn - thisAddress.StartColumn;
    3683           1 :             sal_Int32 nRows = thisAddress.EndRow - thisAddress.StartRow;
    3684           1 :         if ( mbIsRows || bFullRow || ( nCols >=  nRows ) )
    3685           0 :             mode = sheet::CellDeleteMode_UP;
    3686             :         else
    3687           1 :             mode = sheet::CellDeleteMode_LEFT;
    3688             :     }
    3689           3 :     uno::Reference< sheet::XCellRangeMovement > xCellRangeMove( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    3690           3 :     xCellRangeMove->removeRange( thisAddress, mode );
    3691             : 
    3692             : }
    3693             : 
    3694             : //XElementAccess
    3695             : sal_Bool SAL_CALL
    3696           0 : ScVbaRange::hasElements() throw (uno::RuntimeException, std::exception)
    3697             : {
    3698           0 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY );
    3699           0 :     if ( xColumnRowRange.is() )
    3700           0 :         if ( xColumnRowRange->getRows()->getCount() ||
    3701           0 :             xColumnRowRange->getColumns()->getCount() )
    3702           0 :             return sal_True;
    3703           0 :     return false;
    3704             : }
    3705             : 
    3706             : // XEnumerationAccess
    3707             : uno::Reference< container::XEnumeration > SAL_CALL
    3708          18 : ScVbaRange::createEnumeration() throw (uno::RuntimeException, std::exception)
    3709             : {
    3710          18 :     if ( mbIsColumns || mbIsRows )
    3711             :     {
    3712           0 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY );
    3713           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3714           0 :                 sal_Int32 nElems = 0;
    3715           0 :         if ( mbIsColumns )
    3716           0 :             nElems = xColumnRowRange->getColumns()->getCount();
    3717             :         else
    3718           0 :             nElems = xColumnRowRange->getRows()->getCount();
    3719           0 :                 return new ColumnsRowEnumeration( mxContext, xRange, nElems );
    3720             : 
    3721             :     }
    3722          18 :     return new CellsEnumeration( mxParent, mxContext, m_Areas );
    3723             : }
    3724             : 
    3725             : OUString SAL_CALL
    3726           0 : ScVbaRange::getDefaultMethodName(  ) throw (uno::RuntimeException, std::exception)
    3727             : {
    3728           0 :     return OUString( "Item" );
    3729             : }
    3730             : 
    3731             : // returns calc internal col. width ( in points )
    3732             : double
    3733          27 : ScVbaRange::getCalcColWidth(const table::CellRangeAddress& rAddress)
    3734             :     throw (uno::RuntimeException, std::exception)
    3735             : {
    3736          27 :     ScDocument& rDoc = getScDocument();
    3737          27 :     sal_uInt16 nWidth = rDoc.GetOriginalWidth( static_cast< SCCOL >( rAddress.StartColumn ), static_cast< SCTAB >( rAddress.Sheet ) );
    3738          27 :     double nPoints = lcl_TwipsToPoints( nWidth );
    3739          27 :     nPoints = lcl_Round2DecPlaces( nPoints );
    3740          27 :     return nPoints;
    3741             : }
    3742             : 
    3743             : double
    3744          42 : ScVbaRange::getCalcRowHeight(const table::CellRangeAddress& rAddress)
    3745             :     throw (uno::RuntimeException, std::exception)
    3746             : {
    3747          42 :     ScDocument& rDoc = getDocumentFromRange( mxRange );
    3748          42 :     sal_uInt16 nWidth = rDoc.GetOriginalHeight( rAddress.StartRow, rAddress.Sheet );
    3749          42 :     double nPoints = lcl_TwipsToPoints( nWidth );
    3750          42 :     nPoints = lcl_Round2DecPlaces( nPoints );
    3751          42 :     return nPoints;
    3752             : }
    3753             : 
    3754             : // return Char Width in points
    3755          10 : double getDefaultCharWidth( ScDocShell* pDocShell )
    3756             : {
    3757          10 :     ScDocument& rDoc = pDocShell->GetDocument();
    3758          10 :     OutputDevice* pRefDevice = rDoc.GetRefDevice();
    3759          10 :     ScPatternAttr* pAttr = rDoc.GetDefPattern();
    3760          10 :     vcl::Font aDefFont;
    3761          10 :     pAttr->GetFont( aDefFont, SC_AUTOCOL_BLACK, pRefDevice );
    3762          10 :     pRefDevice->SetFont( aDefFont );
    3763          10 :     long nCharWidth = pRefDevice->GetTextWidth( OUString( '0' ) );        // 1/100th mm
    3764          10 :     return lcl_hmmToPoints( nCharWidth );
    3765             : }
    3766             : 
    3767             : uno::Any SAL_CALL
    3768          11 : ScVbaRange::getColumnWidth() throw (uno::RuntimeException, std::exception)
    3769             : {
    3770          11 :     sal_Int32 nLen = m_Areas->getCount();
    3771          11 :     if ( nLen > 1 )
    3772             :     {
    3773           5 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3774           5 :         return xRange->getColumnWidth();
    3775             :     }
    3776             : 
    3777           6 :     double nColWidth =  0;
    3778           6 :     ScDocShell* pShell = getScDocShell();
    3779           6 :     if ( pShell )
    3780             :     {
    3781           6 :         double defaultCharWidth = getDefaultCharWidth( pShell );
    3782           6 :         RangeHelper thisRange( mxRange );
    3783           6 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3784           6 :         sal_Int32 nStartCol = thisAddress.StartColumn;
    3785           6 :         sal_Int32 nEndCol = thisAddress.EndColumn;
    3786           6 :         sal_uInt16 nColTwips = 0;
    3787          18 :         for( sal_Int32 nCol = nStartCol ; nCol <= nEndCol; ++nCol )
    3788             :         {
    3789          14 :             thisAddress.StartColumn = nCol;
    3790          14 :             sal_uInt16 nCurTwips = pShell->GetDocument().GetOriginalWidth( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCTAB >( thisAddress.Sheet ) );
    3791          14 :             if ( nCol == nStartCol )
    3792           6 :                 nColTwips =  nCurTwips;
    3793          14 :             if ( nColTwips != nCurTwips )
    3794           2 :                 return aNULL();
    3795             :         }
    3796           4 :         nColWidth = lcl_TwipsToPoints( nColTwips );
    3797           4 :         if ( nColWidth != 0.0 )
    3798           4 :             nColWidth = ( nColWidth / defaultCharWidth ) - fExtraWidth;
    3799             :     }
    3800           4 :     nColWidth = lcl_Round2DecPlaces( nColWidth );
    3801           4 :     return uno::makeAny( nColWidth );
    3802             : }
    3803             : 
    3804             : void SAL_CALL
    3805           7 : ScVbaRange::setColumnWidth( const uno::Any& _columnwidth ) throw (uno::RuntimeException, std::exception)
    3806             : {
    3807           7 :     sal_Int32 nLen = m_Areas->getCount();
    3808           7 :     if ( nLen > 1 )
    3809             :     {
    3810           6 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    3811             :         {
    3812           3 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3813           3 :             xRange->setColumnWidth( _columnwidth );
    3814           3 :         }
    3815           6 :         return;
    3816             :     }
    3817           4 :     double nColWidth = 0;
    3818           4 :     _columnwidth >>= nColWidth;
    3819           4 :     nColWidth = lcl_Round2DecPlaces( nColWidth );
    3820           4 :     ScDocShell* pDocShell = getScDocShell();
    3821           4 :     if ( pDocShell )
    3822             :     {
    3823           4 :         if ( nColWidth != 0.0 )
    3824           4 :             nColWidth = ( nColWidth + fExtraWidth ) * getDefaultCharWidth( pDocShell );
    3825           4 :         RangeHelper thisRange( mxRange );
    3826           4 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3827           4 :         sal_uInt16 nTwips = lcl_pointsToTwips( nColWidth );
    3828             : 
    3829           8 :         std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(thisAddress.StartColumn, thisAddress.EndColumn));
    3830             :         // #163561# use mode SC_SIZE_DIRECT: hide for width 0, show for other values
    3831           4 :         pDocShell->GetDocFunc().SetWidthOrHeight(
    3832          12 :             true, aColArr, thisAddress.Sheet, SC_SIZE_DIRECT, nTwips, true, true);
    3833             :     }
    3834             : }
    3835             : 
    3836             : uno::Any SAL_CALL
    3837          17 : ScVbaRange::getWidth() throw (uno::RuntimeException, std::exception)
    3838             : {
    3839          17 :     if ( m_Areas->getCount() > 1 )
    3840             :     {
    3841           8 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3842           8 :         return xRange->getWidth();
    3843             :     }
    3844           9 :     uno::Reference< table::XColumnRowRange > xColRowRange( mxRange, uno::UNO_QUERY_THROW );
    3845          18 :     uno::Reference< container::XIndexAccess > xIndexAccess( xColRowRange->getColumns(), uno::UNO_QUERY_THROW );
    3846           9 :     sal_Int32 nElems = xIndexAccess->getCount();
    3847           9 :     double nWidth = 0;
    3848          36 :     for ( sal_Int32 index=0; index<nElems; ++index )
    3849             :     {
    3850          27 :         uno::Reference< sheet::XCellRangeAddressable > xAddressable( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
    3851          27 :         double nTmpWidth = getCalcColWidth( xAddressable->getRangeAddress() );
    3852          27 :         nWidth += nTmpWidth;
    3853          27 :     }
    3854          18 :     return uno::makeAny( nWidth );
    3855             : }
    3856             : 
    3857             : uno::Any SAL_CALL
    3858          81 : ScVbaRange::Areas( const uno::Any& item) throw (uno::RuntimeException, std::exception)
    3859             : {
    3860          81 :     if ( !item.hasValue() )
    3861          70 :         return uno::makeAny( m_Areas );
    3862          11 :     return m_Areas->Item( item, uno::Any() );
    3863             : }
    3864             : 
    3865             : uno::Reference< excel::XRange >
    3866          55 : ScVbaRange::getArea( sal_Int32 nIndex ) throw( css::uno::RuntimeException )
    3867             : {
    3868          55 :     if ( !m_Areas.is() )
    3869           0 :         throw uno::RuntimeException("No areas available" );
    3870          55 :     uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( ++nIndex ), uno::Any() ), uno::UNO_QUERY_THROW );
    3871          55 :     return xRange;
    3872             : }
    3873             : 
    3874             : uno::Any
    3875           3 : ScVbaRange::Borders( const uno::Any& item ) throw( script::BasicErrorException, uno::RuntimeException )
    3876             : {
    3877           3 :     if ( !item.hasValue() )
    3878           3 :         return uno::makeAny( getBorders() );
    3879           0 :     return getBorders()->Item( item, uno::Any() );
    3880             : }
    3881             : 
    3882             : uno::Any SAL_CALL
    3883           0 : ScVbaRange::BorderAround( const css::uno::Any& LineStyle, const css::uno::Any& Weight,
    3884             :                 const css::uno::Any& ColorIndex, const css::uno::Any& Color ) throw (css::uno::RuntimeException, std::exception)
    3885             : {
    3886           0 :     sal_Int32 nCount = getBorders()->getCount();
    3887             : 
    3888           0 :     for( sal_Int32 i = 0; i < nCount; i++ )
    3889             :     {
    3890           0 :         const sal_Int32 nLineType = supportedIndexTable[i];
    3891           0 :         switch( nLineType )
    3892             :         {
    3893             :             case excel::XlBordersIndex::xlEdgeLeft:
    3894             :             case excel::XlBordersIndex::xlEdgeTop:
    3895             :             case excel::XlBordersIndex::xlEdgeBottom:
    3896             :             case excel::XlBordersIndex::xlEdgeRight:
    3897             :             {
    3898           0 :                 uno::Reference< excel::XBorder > xBorder( m_Borders->Item( uno::makeAny( nLineType ), uno::Any() ), uno::UNO_QUERY_THROW );
    3899           0 :                 if( LineStyle.hasValue() )
    3900             :                 {
    3901           0 :                     xBorder->setLineStyle( LineStyle );
    3902             :                 }
    3903           0 :                 if( Weight.hasValue() )
    3904             :                 {
    3905           0 :                     xBorder->setWeight( Weight );
    3906             :                 }
    3907           0 :                 if( ColorIndex.hasValue() )
    3908             :                 {
    3909           0 :                     xBorder->setColorIndex( ColorIndex );
    3910             :                 }
    3911           0 :                 if( Color.hasValue() )
    3912             :                 {
    3913           0 :                     xBorder->setColor( Color );
    3914             :                 }
    3915           0 :                 break;
    3916             :             }
    3917             :             case excel::XlBordersIndex::xlInsideVertical:
    3918             :             case excel::XlBordersIndex::xlInsideHorizontal:
    3919             :             case excel::XlBordersIndex::xlDiagonalDown:
    3920             :             case excel::XlBordersIndex::xlDiagonalUp:
    3921           0 :                 break;
    3922             :             default:
    3923           0 :                 return uno::makeAny( false );
    3924             :         }
    3925             :     }
    3926           0 :     return uno::makeAny( sal_True );
    3927             : }
    3928             : 
    3929             : uno::Any SAL_CALL
    3930          11 : ScVbaRange::getRowHeight()
    3931             :     throw (uno::RuntimeException, std::exception)
    3932             : {
    3933          11 :     sal_Int32 nLen = m_Areas->getCount();
    3934          11 :     if ( nLen > 1 )
    3935             :     {
    3936           5 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3937           5 :         return xRange->getRowHeight();
    3938             :     }
    3939             : 
    3940             :     // if any row's RowHeight in the
    3941             :     // range is different from any other then return NULL
    3942           6 :     RangeHelper thisRange( mxRange );
    3943           6 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3944             : 
    3945           6 :     sal_Int32 nStartRow = thisAddress.StartRow;
    3946           6 :     sal_Int32 nEndRow = thisAddress.EndRow;
    3947           6 :         sal_uInt16 nRowTwips = 0;
    3948             :     // #TODO probably possible to use the SfxItemSet ( and see if
    3949             :     //  SfxItemState::DONTCARE is set ) to improve performance
    3950             : // #CHECKME looks like this is general behaviour not just row Range specific
    3951             : //  if ( mbIsRows )
    3952           6 :     ScDocShell* pShell = getScDocShell();
    3953           6 :     if ( pShell )
    3954             :     {
    3955          27 :         for ( sal_Int32 nRow = nStartRow ; nRow <= nEndRow; ++nRow )
    3956             :         {
    3957          23 :             thisAddress.StartRow = nRow;
    3958          23 :             sal_uInt16 nCurTwips = pShell->GetDocument().GetOriginalHeight( thisAddress.StartRow, thisAddress.Sheet );
    3959          23 :             if ( nRow == nStartRow )
    3960           6 :                 nRowTwips = nCurTwips;
    3961          23 :             if ( nRowTwips != nCurTwips )
    3962           2 :                 return aNULL();
    3963             :         }
    3964             :     }
    3965           4 :     double nHeight = lcl_Round2DecPlaces( lcl_TwipsToPoints( nRowTwips ) );
    3966           4 :     return uno::makeAny( nHeight );
    3967             : }
    3968             : 
    3969             : void SAL_CALL
    3970           7 : ScVbaRange::setRowHeight( const uno::Any& _rowheight) throw (uno::RuntimeException, std::exception)
    3971             : {
    3972           7 :     sal_Int32 nLen = m_Areas->getCount();
    3973           7 :     if ( nLen > 1 )
    3974             :     {
    3975           6 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    3976             :         {
    3977           3 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3978           3 :             xRange->setRowHeight( _rowheight );
    3979           3 :         }
    3980           6 :         return;
    3981             :     }
    3982           4 :     double nHeight = 0; // Incoming height is in points
    3983           4 :         _rowheight >>= nHeight;
    3984           4 :     nHeight = lcl_Round2DecPlaces( nHeight );
    3985           4 :     RangeHelper thisRange( mxRange );
    3986           4 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3987           4 :     sal_uInt16 nTwips = lcl_pointsToTwips( nHeight );
    3988             : 
    3989           4 :     ScDocShell* pDocShell = getDocShellFromRange( mxRange );
    3990           8 :     std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(thisAddress.StartRow, thisAddress.EndRow));
    3991           4 :     pDocShell->GetDocFunc().SetWidthOrHeight(
    3992          12 :         false, aRowArr, thisAddress.Sheet, SC_SIZE_ORIGINAL, nTwips, true, true);
    3993             : }
    3994             : 
    3995             : uno::Any SAL_CALL
    3996           0 : ScVbaRange::getPageBreak() throw (uno::RuntimeException, std::exception)
    3997             : {
    3998           0 :     sal_Int32 nPageBreak = excel::XlPageBreak::xlPageBreakNone;
    3999           0 :     ScDocShell* pShell = getDocShellFromRange( mxRange );
    4000           0 :     if ( pShell )
    4001             :     {
    4002           0 :         RangeHelper thisRange( mxRange );
    4003           0 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4004           0 :         bool bColumn = false;
    4005             : 
    4006           0 :         if (thisAddress.StartRow==0)
    4007           0 :             bColumn = true;
    4008             : 
    4009           0 :         uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4010           0 :         if ( xModel.is() )
    4011             :         {
    4012           0 :             ScDocument& rDoc = getDocumentFromRange( mxRange );
    4013             : 
    4014           0 :             ScBreakType nBreak = BREAK_NONE;
    4015           0 :             if ( !bColumn )
    4016           0 :                 nBreak = rDoc.HasRowBreak(thisAddress.StartRow, thisAddress.Sheet);
    4017             :             else
    4018           0 :                 nBreak = rDoc.HasColBreak(thisAddress.StartColumn, thisAddress.Sheet);
    4019             : 
    4020           0 :             if (nBreak & BREAK_PAGE)
    4021           0 :                 nPageBreak = excel::XlPageBreak::xlPageBreakAutomatic;
    4022             : 
    4023           0 :             if (nBreak & BREAK_MANUAL)
    4024           0 :                 nPageBreak = excel::XlPageBreak::xlPageBreakManual;
    4025           0 :         }
    4026             :     }
    4027             : 
    4028           0 :     return uno::makeAny( nPageBreak );
    4029             : }
    4030             : 
    4031             : void SAL_CALL
    4032           0 : ScVbaRange::setPageBreak( const uno::Any& _pagebreak) throw (uno::RuntimeException, std::exception)
    4033             : {
    4034           0 :     sal_Int32 nPageBreak = 0;
    4035           0 :     _pagebreak >>= nPageBreak;
    4036             : 
    4037           0 :     ScDocShell* pShell = getDocShellFromRange( mxRange );
    4038           0 :     if ( pShell )
    4039             :     {
    4040           0 :         RangeHelper thisRange( mxRange );
    4041           0 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4042           0 :         if ((thisAddress.StartColumn==0) && (thisAddress.StartRow==0))
    4043           0 :             return;
    4044           0 :         bool bColumn = false;
    4045             : 
    4046           0 :         if (thisAddress.StartRow==0)
    4047           0 :             bColumn = true;
    4048             : 
    4049           0 :         ScAddress aAddr( static_cast<SCCOL>(thisAddress.StartColumn), thisAddress.StartRow, thisAddress.Sheet );
    4050           0 :         uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4051           0 :         if ( xModel.is() )
    4052             :         {
    4053           0 :             ScTabViewShell* pViewShell = excel::getBestViewShell( xModel );
    4054           0 :             if ( nPageBreak == excel::XlPageBreak::xlPageBreakManual )
    4055           0 :                 pViewShell->InsertPageBreak( bColumn, true, &aAddr);
    4056           0 :             else if ( nPageBreak == excel::XlPageBreak::xlPageBreakNone )
    4057           0 :                 pViewShell->DeletePageBreak( bColumn, true, &aAddr);
    4058           0 :         }
    4059             :     }
    4060             : }
    4061             : 
    4062             : uno::Any SAL_CALL
    4063          14 : ScVbaRange::getHeight() throw (uno::RuntimeException, std::exception)
    4064             : {
    4065          14 :     if ( m_Areas->getCount() > 1 )
    4066             :     {
    4067           7 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    4068           7 :         return xRange->getHeight();
    4069             :     }
    4070             : 
    4071           7 :     uno::Reference< table::XColumnRowRange > xColRowRange( mxRange, uno::UNO_QUERY_THROW );
    4072          14 :     uno::Reference< container::XIndexAccess > xIndexAccess( xColRowRange->getRows(), uno::UNO_QUERY_THROW );
    4073           7 :     sal_Int32 nElems = xIndexAccess->getCount();
    4074           7 :     double nHeight = 0;
    4075          49 :     for ( sal_Int32 index=0; index<nElems; ++index )
    4076             :     {
    4077          42 :             uno::Reference< sheet::XCellRangeAddressable > xAddressable( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
    4078          42 :         nHeight += getCalcRowHeight(xAddressable->getRangeAddress() );
    4079          42 :     }
    4080          14 :     return uno::makeAny( nHeight );
    4081             : }
    4082             : 
    4083             : awt::Point
    4084           6 : ScVbaRange::getPosition() throw ( uno::RuntimeException )
    4085             : {
    4086           6 :         awt::Point aPoint;
    4087           6 :     uno::Reference< beans::XPropertySet > xProps;
    4088           6 :     if ( mxRange.is() )
    4089           6 :         xProps.set( mxRange, uno::UNO_QUERY_THROW );
    4090             :     else
    4091           0 :         xProps.set( mxRanges, uno::UNO_QUERY_THROW );
    4092           6 :     xProps->getPropertyValue( POSITION ) >>= aPoint;
    4093           6 :     return aPoint;
    4094             : }
    4095             : uno::Any SAL_CALL
    4096           6 : ScVbaRange::getLeft() throw (uno::RuntimeException, std::exception)
    4097             : {
    4098             :     // helperapi returns the first ranges left ( and top below )
    4099           6 :     if ( m_Areas->getCount() > 1 )
    4100           3 :         return getArea( 0 )->getLeft();
    4101           3 :     awt::Point aPoint = getPosition();
    4102           3 :     return uno::makeAny( lcl_hmmToPoints( aPoint.X ) );
    4103             : }
    4104             : 
    4105             : uno::Any SAL_CALL
    4106           6 : ScVbaRange::getTop() throw (uno::RuntimeException, std::exception)
    4107             : {
    4108             :     // helperapi returns the first ranges top
    4109           6 :     if ( m_Areas->getCount() > 1 )
    4110           3 :         return getArea( 0 )->getTop();
    4111           3 :     awt::Point aPoint= getPosition();
    4112           3 :     return uno::makeAny( lcl_hmmToPoints( aPoint.Y ) );
    4113             : }
    4114             : 
    4115           0 : uno::Reference< sheet::XCellRangeReferrer > getNamedRange( const uno::Reference< uno::XInterface >& xIf, const uno::Reference< table::XCellRange >& thisRange )
    4116             : {
    4117           0 :     uno::Reference< beans::XPropertySet > xProps( xIf, uno::UNO_QUERY_THROW );
    4118           0 :     uno::Reference< container::XNameAccess > xNameAccess( xProps->getPropertyValue( "NamedRanges" ), uno::UNO_QUERY_THROW );
    4119             : 
    4120           0 :     uno::Sequence< OUString > sNames = xNameAccess->getElementNames();
    4121             : //    uno::Reference< table::XCellRange > thisRange( getCellRange(), uno::UNO_QUERY_THROW );
    4122           0 :     uno::Reference< sheet::XCellRangeReferrer > xNamedRange;
    4123           0 :     for ( sal_Int32 i=0; i < sNames.getLength(); ++i )
    4124             :     {
    4125           0 :         uno::Reference< sheet::XCellRangeReferrer > xName( xNameAccess->getByName( sNames[ i ] ), uno::UNO_QUERY );
    4126           0 :         if ( xName.is() )
    4127             :         {
    4128           0 :             if ( thisRange == xName->getReferredCells() )
    4129             :             {
    4130           0 :                 xNamedRange = xName;
    4131           0 :                 break;
    4132             :             }
    4133             :         }
    4134           0 :     }
    4135           0 :     return xNamedRange;
    4136             : }
    4137             : 
    4138             : uno::Reference< excel::XName >
    4139           0 : ScVbaRange::getName() throw (uno::RuntimeException, std::exception)
    4140             : {
    4141           0 :     uno::Reference< beans::XPropertySet > xProps( getUnoModel(), uno::UNO_QUERY );
    4142           0 :     uno::Reference< table::XCellRange > thisRange( getCellRange(), uno::UNO_QUERY_THROW );
    4143             :     // Application range
    4144           0 :     uno::Reference< sheet::XCellRangeReferrer > xNamedRange = getNamedRange( xProps, thisRange );
    4145             : 
    4146           0 :     if ( !xNamedRange.is() )
    4147             :     {
    4148             :         // not in application range then assume it might be in
    4149             :         // sheet namedranges
    4150           0 :         RangeHelper aRange( thisRange );
    4151           0 :         uno::Reference< sheet::XSpreadsheet > xSheet = aRange.getSpreadSheet();
    4152           0 :         xProps.set( xSheet, uno::UNO_QUERY );
    4153             :         // impl here
    4154           0 :         xNamedRange = getNamedRange( xProps, thisRange );
    4155             :     }
    4156           0 :     if ( xProps.is() && xNamedRange.is() )
    4157             :     {
    4158           0 :         uno::Reference< sheet::XNamedRanges > xNamedRanges( xProps, uno::UNO_QUERY_THROW );
    4159           0 :         uno::Reference< sheet::XNamedRange > xName( xNamedRange, uno::UNO_QUERY_THROW );
    4160           0 :         return new ScVbaName( mxParent, mxContext, xName, xNamedRanges, getUnoModel() );
    4161             :     }
    4162           0 :     return uno::Reference< excel::XName >();
    4163             : }
    4164             : 
    4165             : uno::Reference< excel::XWorksheet >
    4166          15 : ScVbaRange::getWorksheet() throw (uno::RuntimeException, std::exception)
    4167             : {
    4168             :     // #TODO #FIXME parent should always be set up ( currently thats not
    4169             :     // the case )
    4170          15 :     uno::Reference< excel::XWorksheet > xSheet( getParent(), uno::UNO_QUERY );
    4171          15 :     if ( !xSheet.is() )
    4172             :     {
    4173           0 :         uno::Reference< table::XCellRange > xRange = mxRange;
    4174             : 
    4175           0 :         if ( mxRanges.is() ) // assign xRange to first range
    4176             :         {
    4177           0 :             uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
    4178           0 :             xRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    4179             :         }
    4180           0 :         ScDocShell* pDocShell = getDocShellFromRange(xRange);
    4181           0 :         RangeHelper rHelper(xRange);
    4182             :         // parent should be Thisworkbook
    4183           0 :            xSheet.set( new ScVbaWorksheet( uno::Reference< XHelperInterface >(), mxContext,rHelper.getSpreadSheet(),pDocShell->GetModel()) );
    4184             :     }
    4185          15 :     return xSheet;
    4186             : }
    4187             : 
    4188             : // #TODO remove this ugly application processing
    4189             : // Process an application Range request e.g. 'Range("a1,b2,a4:b6")
    4190             : uno::Reference< excel::XRange >
    4191         671 : ScVbaRange::ApplicationRange( const uno::Reference< uno::XComponentContext >& xContext, const css::uno::Any &Cell1, const css::uno::Any &Cell2 ) throw (css::uno::RuntimeException)
    4192             : {
    4193             :     // Although the documentation seems clear that Range without a
    4194             :     // qualifier then it's a shortcut for ActiveSheet.Range
    4195             :     // however, similarly Application.Range is apparently also a
    4196             :     // shortcut for ActiveSheet.Range
    4197             :     // The is however a subtle behavioural difference I've come across
    4198             :     // wrt to named ranges.
    4199             :     // If a named range "test" exists { Sheet1!$A1 } and the active sheet
    4200             :     // is Sheet2 then the following will fail
    4201             :     // msgbox ActiveSheet.Range("test").Address ' failes
    4202             :     // msgbox WorkSheets("Sheet2").Range("test").Address
    4203             :     // but !!!
    4204             :     // msgbox Range("test").Address ' works
    4205             :     // msgbox Application.Range("test").Address ' works
    4206             : 
    4207             :     // Single param Range
    4208         671 :     OUString sRangeName;
    4209         671 :     Cell1 >>= sRangeName;
    4210         671 :     if ( Cell1.hasValue() && !Cell2.hasValue() && !sRangeName.isEmpty() )
    4211             :     {
    4212             :         static const char sNamedRanges[] = "NamedRanges";
    4213         669 :         uno::Reference< beans::XPropertySet > xPropSet( getCurrentExcelDoc(xContext), uno::UNO_QUERY_THROW );
    4214             : 
    4215        1232 :         uno::Reference< container::XNameAccess > xNamed( xPropSet->getPropertyValue( sNamedRanges ), uno::UNO_QUERY_THROW );
    4216        1232 :         uno::Reference< sheet::XCellRangeReferrer > xReferrer;
    4217             :         try
    4218             :         {
    4219         669 :             xReferrer.set ( xNamed->getByName( sRangeName ), uno::UNO_QUERY );
    4220             :         }
    4221         557 :         catch( uno::Exception& /*e*/ )
    4222             :         {
    4223             :             // do nothing
    4224             :         }
    4225         669 :         if ( xReferrer.is() )
    4226             :         {
    4227         112 :             uno::Reference< table::XCellRange > xRange = xReferrer->getReferredCells();
    4228         112 :             if ( xRange.is() )
    4229             :             {
    4230         106 :                 uno::Reference< excel::XRange > xVbRange =  new ScVbaRange( excel::getUnoSheetModuleObj( xRange ), xContext, xRange );
    4231         106 :                 return xVbRange;
    4232           6 :             }
    4233         563 :         }
    4234             :     }
    4235             : 
    4236        1130 :     uno::Reference< sheet::XSpreadsheetView > xView( getCurrentExcelDoc(xContext)->getCurrentController(), uno::UNO_QUERY );
    4237        1130 :     uno::Reference< table::XCellRange > xSheetRange( xView->getActiveSheet(), uno::UNO_QUERY_THROW );
    4238         565 :     ScVbaRange* pRange = new ScVbaRange( excel::getUnoSheetModuleObj( xSheetRange ), xContext, xSheetRange );
    4239        1130 :     uno::Reference< excel::XRange > xVbSheetRange( pRange );
    4240        1236 :     return pRange->Range( Cell1, Cell2, true );
    4241             : }
    4242             : 
    4243             : // Helper functions for AutoFilter
    4244           4 : static ScDBData* lcl_GetDBData_Impl( ScDocShell* pDocShell, sal_Int16 nSheet )
    4245             : {
    4246           4 :     ScDBData* pRet = NULL;
    4247           4 :     if (pDocShell)
    4248             :     {
    4249           4 :         pRet = pDocShell->GetDocument().GetAnonymousDBData(nSheet);
    4250             :     }
    4251           4 :     return pRet;
    4252             : }
    4253             : 
    4254           3 : static void lcl_SelectAll( ScDocShell* pDocShell, ScQueryParam& aParam )
    4255             : {
    4256           3 :     if ( pDocShell )
    4257             :     {
    4258           3 :         ScViewData* pViewData = ScDocShell::GetViewData();
    4259           3 :         if ( pViewData )
    4260             :         {
    4261             :             OSL_TRACE("Pushing out SelectAll query");
    4262           3 :             pViewData->GetView()->Query( aParam, NULL, true );
    4263             :         }
    4264             :     }
    4265           3 : }
    4266             : 
    4267           4 : static ScQueryParam lcl_GetQueryParam( ScDocShell* pDocShell, sal_Int16 nSheet )
    4268             : {
    4269           4 :     ScDBData* pDBData = lcl_GetDBData_Impl( pDocShell, nSheet );
    4270           4 :     ScQueryParam aParam;
    4271           4 :     if (pDBData)
    4272             :     {
    4273           4 :         pDBData->GetQueryParam( aParam );
    4274             :     }
    4275           4 :     return aParam;
    4276             : }
    4277             : 
    4278           3 : static void lcl_SetAllQueryForField( ScDocShell* pDocShell, SCCOLROW nField, sal_Int16 nSheet )
    4279             : {
    4280           3 :     ScQueryParam aParam = lcl_GetQueryParam( pDocShell, nSheet );
    4281           3 :     aParam.RemoveEntryByField(nField);
    4282           3 :     lcl_SelectAll( pDocShell, aParam );
    4283           3 : }
    4284             : 
    4285             : // Modifies sCriteria, and nOp depending on the value of sCriteria
    4286          10 : static void lcl_setTableFieldsFromCriteria( OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField2& rFilterField )
    4287             : {
    4288             :     // #TODO make this more efficient and cycle through
    4289             :     // sCriteria1 character by character to pick up <,<>,=, * etc.
    4290             :     // right now I am more concerned with just getting it to work right
    4291             : 
    4292          10 :     sCriteria1 = sCriteria1.trim();
    4293             :     // table of translation of criteria text to FilterOperators
    4294             :     // <>searchtext - NOT_EQUAL
    4295             :     //  =searchtext - EQUAL
    4296             :     //  *searchtext - startwith
    4297             :     //  <>*searchtext - doesn't startwith
    4298             :     //  *searchtext* - contains
    4299             :     //  <>*searchtext* - doesn't contain
    4300             :     // [>|>=|<=|...]searchtext for GREATER_value, GREATER_EQUAL_value etc.
    4301          10 :     bool bIsNumeric = false;
    4302          10 :     if ( sCriteria1.startsWith( EQUALS ) )
    4303             :     {
    4304           4 :         if ( sCriteria1.getLength() == (sal_Int32)strlen(EQUALS) )
    4305           1 :             rFilterField.Operator = sheet::FilterOperator2::EMPTY;
    4306             :         else
    4307             :         {
    4308           3 :             rFilterField.Operator = sheet::FilterOperator2::EQUAL;
    4309           3 :             sCriteria1 = sCriteria1.copy( strlen(EQUALS) );
    4310           3 :             sCriteria1 = VBAToRegexp( sCriteria1 );
    4311             :             // UseRegularExpressions
    4312           3 :             if ( xDescProps.is() )
    4313           2 :                 xDescProps->setPropertyValue( "UseRegularExpressions", uno::Any( sal_True ) );
    4314             :         }
    4315             : 
    4316             :     }
    4317           6 :     else if ( sCriteria1.startsWith( NOTEQUALS ) )
    4318             :     {
    4319           2 :         if ( sCriteria1.getLength() == (sal_Int32)strlen(NOTEQUALS) )
    4320           1 :             rFilterField.Operator = sheet::FilterOperator2::NOT_EMPTY;
    4321             :         else
    4322             :         {
    4323           1 :             rFilterField.Operator = sheet::FilterOperator2::NOT_EQUAL;
    4324           1 :             sCriteria1 = sCriteria1.copy( strlen(NOTEQUALS) );
    4325           1 :             sCriteria1 = VBAToRegexp( sCriteria1 );
    4326             :             // UseRegularExpressions
    4327           1 :             if ( xDescProps.is() )
    4328           1 :                 xDescProps->setPropertyValue( "UseRegularExpressions", uno::Any( sal_True ) );
    4329             :         }
    4330             :     }
    4331           4 :     else if ( sCriteria1.startsWith( GREATERTHAN ) )
    4332             :     {
    4333           1 :         bIsNumeric = true;
    4334           1 :         if ( sCriteria1.startsWith( GREATERTHANEQUALS ) )
    4335             :         {
    4336           1 :             sCriteria1 = sCriteria1.copy( strlen(GREATERTHANEQUALS) );
    4337           1 :             rFilterField.Operator = sheet::FilterOperator2::GREATER_EQUAL;
    4338             :         }
    4339             :         else
    4340             :         {
    4341           0 :             sCriteria1 = sCriteria1.copy( strlen(GREATERTHAN) );
    4342           0 :             rFilterField.Operator = sheet::FilterOperator2::GREATER;
    4343             :         }
    4344             : 
    4345             :     }
    4346           3 :     else if ( sCriteria1.startsWith( LESSTHAN ) )
    4347             :     {
    4348           2 :         bIsNumeric = true;
    4349           2 :         if ( sCriteria1.startsWith( LESSTHANEQUALS ) )
    4350             :         {
    4351           1 :             sCriteria1 = sCriteria1.copy( strlen(LESSTHANEQUALS) );
    4352           1 :             rFilterField.Operator = sheet::FilterOperator2::LESS_EQUAL;
    4353             :         }
    4354             :         else
    4355             :         {
    4356           1 :             sCriteria1 = sCriteria1.copy( strlen(LESSTHAN) );
    4357           1 :             rFilterField.Operator = sheet::FilterOperator2::LESS;
    4358             :         }
    4359             : 
    4360             :     }
    4361             :     else
    4362           1 :         rFilterField.Operator = sheet::FilterOperator2::EQUAL;
    4363             : 
    4364          10 :     if ( bIsNumeric )
    4365             :     {
    4366           3 :         rFilterField.IsNumeric= sal_True;
    4367           3 :         rFilterField.NumericValue = sCriteria1.toDouble();
    4368             :     }
    4369          10 :     rFilterField.StringValue = sCriteria1;
    4370          10 : }
    4371             : 
    4372             : void SAL_CALL
    4373          12 : ScVbaRange::AutoFilter( const uno::Any& aField, const uno::Any& Criteria1, const uno::Any& Operator, const uno::Any& Criteria2, const uno::Any& VisibleDropDown )
    4374             :     throw (uno::RuntimeException, std::exception)
    4375             : {
    4376             :     // Is there an existing autofilter
    4377          12 :     RangeHelper thisRange( mxRange );
    4378          12 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4379          12 :     sal_Int16 nSheet = thisAddress.Sheet;
    4380          12 :     ScDocShell* pShell = getScDocShell();
    4381          12 :     bool bHasAuto = false;
    4382          24 :     uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet );
    4383          12 :     if ( xDataBaseRange.is() )
    4384          11 :         bHasAuto = true;
    4385             : 
    4386          24 :     uno::Reference< table::XCellRange > xFilterRange;
    4387          12 :     if ( !bHasAuto )
    4388             :     {
    4389           1 :         if (  m_Areas->getCount() > 1 )
    4390           0 :             throw uno::RuntimeException( STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY );
    4391             : 
    4392           1 :         table::CellRangeAddress autoFiltAddress;
    4393             :         //CurrentRegion()
    4394           1 :         if ( isSingleCellRange() )
    4395             :         {
    4396           0 :             uno::Reference< excel::XRange > xCurrent( CurrentRegion() );
    4397           0 :             if ( xCurrent.is() )
    4398             :             {
    4399           0 :                 ScVbaRange* pRange = getImplementation( xCurrent );
    4400           0 :                 if ( pRange )
    4401             :                 {
    4402           0 :                     if ( pRange->isSingleCellRange() )
    4403           0 :                        throw uno::RuntimeException("Can't create AutoFilter" );
    4404           0 :                     RangeHelper currentRegion( pRange->mxRange );
    4405           0 :                     autoFiltAddress = currentRegion.getCellRangeAddressable()->getRangeAddress();
    4406             :                 }
    4407           0 :             }
    4408             :         }
    4409             :         else // multi-cell range
    4410             :         {
    4411           1 :             RangeHelper multiCellRange( mxRange );
    4412           1 :             autoFiltAddress = multiCellRange.getCellRangeAddressable()->getRangeAddress();
    4413             :             // #163530# Filter box shows only entry of first row
    4414           1 :             ScDocument* pDocument = ( pShell ? &pShell->GetDocument() : NULL );
    4415           1 :             if ( pDocument )
    4416             :             {
    4417           1 :                 SCCOL nStartCol = autoFiltAddress.StartColumn;
    4418           1 :                 SCROW nStartRow = autoFiltAddress.StartRow;
    4419           1 :                 SCCOL nEndCol = autoFiltAddress.EndColumn;
    4420           1 :                 SCROW nEndRow = autoFiltAddress.EndRow;
    4421           1 :                 pDocument->GetDataArea( autoFiltAddress.Sheet, nStartCol, nStartRow, nEndCol, nEndRow, true, true );
    4422           1 :                 autoFiltAddress.StartColumn = nStartCol;
    4423           1 :                 autoFiltAddress.StartRow = nStartRow;
    4424           1 :                 autoFiltAddress.EndColumn = nEndCol;
    4425           1 :                 autoFiltAddress.EndRow = nEndRow;
    4426           1 :             }
    4427             :         }
    4428             : 
    4429           1 :         uno::Reference< sheet::XUnnamedDatabaseRanges > xDBRanges = excel::GetUnnamedDataBaseRanges( pShell );
    4430           1 :         if ( xDBRanges.is() )
    4431             :         {
    4432             :             OSL_TRACE("Going to add new autofilter range.. sheet %i", nSheet );
    4433           1 :             if ( !xDBRanges->hasByTable( nSheet ) )
    4434           1 :                 xDBRanges->setByTable( autoFiltAddress );
    4435           1 :             xDataBaseRange.set( xDBRanges->getByTable(nSheet ), uno::UNO_QUERY_THROW );
    4436             :         }
    4437           1 :         if ( !xDataBaseRange.is() )
    4438           0 :             throw uno::RuntimeException("Failed to find the autofilter placeholder range" );
    4439             : 
    4440           2 :         uno::Reference< beans::XPropertySet > xDBRangeProps( xDataBaseRange, uno::UNO_QUERY_THROW );
    4441             :         // set autofilt
    4442           1 :         xDBRangeProps->setPropertyValue( "AutoFilter", uno::Any(sal_True) );
    4443             :                 // set header (autofilter always need column headers)
    4444           2 :         uno::Reference< beans::XPropertySet > xFiltProps( xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY_THROW );
    4445           1 :         bool bHasColHeader = false;
    4446           1 :         ScDocument* pDoc = pShell ? &pShell->GetDocument() : NULL;
    4447           1 :         if (pDoc)
    4448             :         {
    4449           1 :             bHasColHeader = pDoc->HasColHeader(  static_cast< SCCOL >( autoFiltAddress.StartColumn ), static_cast< SCROW >( autoFiltAddress.StartRow ), static_cast< SCCOL >( autoFiltAddress.EndColumn ), static_cast< SCROW >( autoFiltAddress.EndRow ), static_cast< SCTAB >( autoFiltAddress.Sheet ) );
    4450             :         }
    4451           2 :         xFiltProps->setPropertyValue( "ContainsHeader", uno::Any( bHasColHeader ) );
    4452             :     }
    4453             : 
    4454          12 :     sal_Int32 nField = 0; // *IS* 1 based
    4455          24 :     OUString sCriteria1;
    4456          12 :     sal_Int32 nOperator = excel::XlAutoFilterOperator::xlAnd;
    4457             : 
    4458          12 :     bool bVisible = true;
    4459          12 :     VisibleDropDown >>= bVisible;
    4460             : 
    4461          12 :     if ( bVisible == bHasAuto ) // dropdown is displayed/notdisplayed as required
    4462          11 :         bVisible = false;
    4463          12 :     sheet::FilterConnection nConn = sheet::FilterConnection_AND;
    4464          12 :     double nCriteria1 = 0;
    4465             : 
    4466          12 :     bool bHasCritValue = Criteria1.hasValue();
    4467          12 :     bool bCritHasNumericValue = false; // not sure if a numeric criteria is possible
    4468          12 :     if ( bHasCritValue )
    4469           9 :         bCritHasNumericValue = ( Criteria1 >>= nCriteria1 );
    4470             : 
    4471          12 :     if (  !aField.hasValue() && ( Criteria1.hasValue() || Operator.hasValue() || Criteria2.hasValue() ) )
    4472           0 :         throw uno::RuntimeException();
    4473          24 :     uno::Any Field( aField );
    4474          12 :     if ( !( Field >>= nField ) )
    4475             :     {
    4476           1 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    4477             :         try
    4478             :         {
    4479           1 :             Field = xConverter->convertTo( aField, cppu::UnoType<sal_Int32>::get() );
    4480             :         }
    4481           1 :         catch( uno::Exception& )
    4482             :         {
    4483           1 :         }
    4484             :     }
    4485             :     // Use the normal uno api, sometimes e.g. when you want to use ALL as the filter
    4486             :     // we can't use refresh as the uno interface doesn't have a concept of ALL
    4487             :     // in this case we just call the core calc functionality -
    4488          12 :     if ( ( Field >>= nField )  )
    4489             :     {
    4490          11 :         bool bAll = false;
    4491             : 
    4492             :         uno::Reference< sheet::XSheetFilterDescriptor2 > xDesc(
    4493          11 :                 xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
    4494          11 :         if ( xDesc.is() )
    4495             :         {
    4496          11 :             uno::Sequence< sheet::TableFilterField2 > sTabFilts;
    4497          22 :             uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
    4498          11 :         if ( Criteria1.hasValue() )
    4499             :         {
    4500           9 :             sTabFilts.realloc( 1 );
    4501           9 :             sTabFilts[0].Operator = sheet::FilterOperator2::EQUAL;// sensible default
    4502           9 :             if ( !bCritHasNumericValue )
    4503             :             {
    4504           9 :                 Criteria1 >>= sCriteria1;
    4505           9 :                 sTabFilts[0].IsNumeric = bCritHasNumericValue;
    4506           9 :                 if ( bHasCritValue && !sCriteria1.isEmpty() )
    4507           9 :                     lcl_setTableFieldsFromCriteria( sCriteria1, xDescProps, sTabFilts[0]  );
    4508             :                 else
    4509           0 :                     bAll = true;
    4510             :             }
    4511             :             else // numeric
    4512             :             {
    4513           0 :                 sTabFilts[0].IsNumeric = sal_True;
    4514           0 :                 sTabFilts[0].NumericValue = nCriteria1;
    4515             :             }
    4516             :         }
    4517             :         else // no value specified
    4518           2 :             bAll = true;
    4519             :         // not sure what the relationship between Criteria1 and Operator is,
    4520             :         // e.g. can you have a Operator without a Criteria ? in openoffice it
    4521          11 :         if ( Operator.hasValue()  && ( Operator >>= nOperator ) )
    4522             :         {
    4523             :             // if it's a bottom/top Ten(Percent/Value) and there
    4524             :             // is no value specified for criteria1 set it to 10
    4525           6 :             if ( !bCritHasNumericValue && sCriteria1.isEmpty() && ( nOperator != excel::XlAutoFilterOperator::xlOr ) && ( nOperator != excel::XlAutoFilterOperator::xlAnd ) )
    4526             :             {
    4527           0 :                 sTabFilts[0].IsNumeric = sal_True;
    4528           0 :                 sTabFilts[0].NumericValue = 10;
    4529           0 :                 bAll = false;
    4530             :             }
    4531           6 :             switch ( nOperator )
    4532             :             {
    4533             :                 case excel::XlAutoFilterOperator::xlBottom10Items:
    4534           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_VALUES;
    4535           0 :                     break;
    4536             :                 case excel::XlAutoFilterOperator::xlBottom10Percent:
    4537           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_PERCENT;
    4538           0 :                     break;
    4539             :                 case excel::XlAutoFilterOperator::xlTop10Items:
    4540           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::TOP_VALUES;
    4541           0 :                     break;
    4542             :                 case excel::XlAutoFilterOperator::xlTop10Percent:
    4543           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::TOP_PERCENT;
    4544           0 :                     break;
    4545             :                 case excel::XlAutoFilterOperator::xlOr:
    4546           1 :                     nConn = sheet::FilterConnection_OR;
    4547           1 :                     break;
    4548             :                 case excel::XlAutoFilterOperator::xlAnd:
    4549           5 :                     nConn = sheet::FilterConnection_AND;
    4550           5 :                     break;
    4551             :                 default:
    4552           0 :                     throw uno::RuntimeException("UnknownOption" );
    4553             : 
    4554             :             }
    4555             : 
    4556             :         }
    4557          11 :         if ( !bAll )
    4558             :         {
    4559           9 :             sTabFilts[0].Connection = sheet::FilterConnection_AND;
    4560           9 :             sTabFilts[0].Field = (nField - 1);
    4561             : 
    4562           9 :             OUString sCriteria2;
    4563           9 :             if ( Criteria2.hasValue() ) // there is a Criteria2
    4564             :             {
    4565           1 :                 sTabFilts.realloc(2);
    4566           1 :                 sTabFilts[1].Field = sTabFilts[0].Field;
    4567           1 :                 sTabFilts[1].Connection = nConn;
    4568             : 
    4569           1 :                 if ( Criteria2 >>= sCriteria2 )
    4570             :                 {
    4571           1 :                     if ( !sCriteria2.isEmpty() )
    4572             :                     {
    4573           1 :                         uno::Reference< beans::XPropertySet > xProps;
    4574           1 :                         lcl_setTableFieldsFromCriteria( sCriteria2, xProps,  sTabFilts[1] );
    4575           1 :                         sTabFilts[1].IsNumeric = false;
    4576             :                     }
    4577             :                 }
    4578             :                 else // numeric
    4579             :                 {
    4580           0 :                     Criteria2 >>= sTabFilts[1].NumericValue;
    4581           0 :                     sTabFilts[1].IsNumeric = sal_True;
    4582           0 :                     sTabFilts[1].Operator = sheet::FilterOperator2::EQUAL;
    4583             :                 }
    4584           9 :             }
    4585             :         }
    4586             : 
    4587          11 :         xDesc->setFilterFields2( sTabFilts );
    4588          11 :         if ( !bAll )
    4589             :         {
    4590           9 :             xDataBaseRange->refresh();
    4591             :         }
    4592             :         else
    4593             :             // was 0 based now seems to be 1
    4594          13 :             lcl_SetAllQueryForField( pShell, nField, nSheet );
    4595          11 :         }
    4596             :     }
    4597             :     else
    4598             :     {
    4599             :         // this is just to toggle autofilter on and off ( not to be confused with
    4600             :         // a VisibleDropDown option combined with a field, in that case just the
    4601             :         // button should be disabled ) - currently we don't support that
    4602           1 :         uno::Reference< beans::XPropertySet > xDBRangeProps( xDataBaseRange, uno::UNO_QUERY_THROW );
    4603           1 :         if ( bHasAuto )
    4604             :         {
    4605             :             // find the any field with the query and select all
    4606           1 :             ScQueryParam aParam = lcl_GetQueryParam( pShell, nSheet );
    4607           9 :             for (SCSIZE i = 0; i< aParam.GetEntryCount(); ++i)
    4608             :             {
    4609           8 :                 ScQueryEntry& rEntry = aParam.GetEntry(i);
    4610           8 :                 if ( rEntry.bDoQuery )
    4611           1 :                     lcl_SetAllQueryForField( pShell, rEntry.nField, nSheet );
    4612             :             }
    4613             :             // remove exising filters
    4614             :             uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
    4615           2 :                     xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
    4616           1 :             if( xSheetFilterDescriptor.is() )
    4617           2 :                 xSheetFilterDescriptor->setFilterFields2( uno::Sequence< sheet::TableFilterField2 >() );
    4618             :         }
    4619           1 :         xDBRangeProps->setPropertyValue( "AutoFilter", uno::Any(!bHasAuto) );
    4620             : 
    4621          12 :     }
    4622          12 : }
    4623             : 
    4624             : void SAL_CALL
    4625           1 : ScVbaRange::Insert( const uno::Any& Shift, const uno::Any& /*CopyOrigin*/ ) throw (uno::RuntimeException, std::exception)
    4626             : {
    4627             :     // It appears ( from the web ) that the undocumented CopyOrigin
    4628             :     // param should contain member of enum XlInsertFormatOrigin
    4629             :     // which can have values xlFormatFromLeftOrAbove or xlFormatFromRightOrBelow
    4630             :     // #TODO investigate resultant behaviour using these constants
    4631             :     // currently just processing Shift
    4632             : 
    4633           1 :     sheet::CellInsertMode mode = sheet::CellInsertMode_NONE;
    4634           1 :     if ( Shift.hasValue() )
    4635             :     {
    4636           1 :         sal_Int32 nShift = 0;
    4637           1 :         Shift >>= nShift;
    4638           1 :         switch ( nShift )
    4639             :         {
    4640             :             case excel::XlInsertShiftDirection::xlShiftToRight:
    4641           1 :                 mode = sheet::CellInsertMode_RIGHT;
    4642           1 :                 break;
    4643             :             case excel::XlInsertShiftDirection::xlShiftDown:
    4644           0 :                 mode = sheet::CellInsertMode_DOWN;
    4645           0 :                 break;
    4646             :             default:
    4647           0 :                 throw uno::RuntimeException("Illegal parameter " );
    4648             :         }
    4649             :     }
    4650             :     else
    4651             :     {
    4652           0 :         if ( getRow() >=  getColumn() )
    4653           0 :             mode = sheet::CellInsertMode_DOWN;
    4654             :         else
    4655           0 :             mode = sheet::CellInsertMode_RIGHT;
    4656             :     }
    4657           1 :     RangeHelper thisRange( mxRange );
    4658           1 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4659           2 :     uno::Reference< sheet::XCellRangeMovement > xCellRangeMove( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4660           1 :     xCellRangeMove->insertCells( thisAddress, mode );
    4661             : 
    4662             :     // Paste from clipboard only if the clipboard content was copied via VBA, and not already pasted via VBA again.
    4663             :     // "Insert" behavior should not depend on random clipboard content previously copied by the user.
    4664           1 :     ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
    4665           1 :     if ( pClipObj && pClipObj->GetUseInApi() )
    4666             :     {
    4667             :         // After the insert ( this range ) actually has moved
    4668           0 :         ScRange aRange( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCROW >( thisAddress.StartRow ), static_cast< SCTAB >( thisAddress.Sheet ), static_cast< SCCOL >( thisAddress.EndColumn ), static_cast< SCROW >( thisAddress.EndRow ), static_cast< SCTAB >( thisAddress.Sheet ) );
    4669           0 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getDocShellFromRange( mxRange ) , aRange ) );
    4670           0 :         uno::Reference< excel::XRange > xVbaRange( new ScVbaRange( mxParent, mxContext, xRange, mbIsRows, mbIsColumns ) );
    4671           0 :         xVbaRange->PasteSpecial( uno::Any(), uno::Any(), uno::Any(), uno::Any() );
    4672           1 :     }
    4673           1 : }
    4674             : 
    4675             : void SAL_CALL
    4676           4 : ScVbaRange::Autofit() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    4677             : {
    4678           4 :     sal_Int32 nLen = m_Areas->getCount();
    4679           4 :     if ( nLen > 1 )
    4680             :     {
    4681           2 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    4682             :         {
    4683           1 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    4684           1 :             xRange->Autofit();
    4685           1 :         }
    4686           5 :         return;
    4687             :     }
    4688             :         // if the range is a not a row or column range autofit will
    4689             :         // throw an error
    4690             : 
    4691           3 :         if ( !( mbIsColumns || mbIsRows ) )
    4692           0 :             DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    4693           3 :         ScDocShell* pDocShell = getDocShellFromRange( mxRange );
    4694           3 :         if ( pDocShell )
    4695             :         {
    4696           3 :             RangeHelper thisRange( mxRange );
    4697           3 :             table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4698             : 
    4699           6 :             std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(thisAddress.StartColumn,thisAddress.EndColumn));
    4700           3 :             bool bDirection = true;
    4701           3 :             if ( mbIsRows )
    4702             :             {
    4703           1 :                 bDirection = false;
    4704           1 :                 aColArr[0].mnStart = thisAddress.StartRow;
    4705           1 :                 aColArr[0].mnEnd = thisAddress.EndRow;
    4706             :             }
    4707           3 :             pDocShell->GetDocFunc().SetWidthOrHeight(
    4708           9 :                 bDirection, aColArr, thisAddress.Sheet, SC_SIZE_OPTIMAL, 0, true, true);
    4709             :     }
    4710             : }
    4711             : 
    4712             : uno::Any SAL_CALL
    4713           0 : ScVbaRange::Hyperlinks( const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    4714             : {
    4715             :     /*  The range object always returns a new Hyperlinks object containing a
    4716             :         fixed list of existing hyperlinks in the range.
    4717             :         See vbahyperlinks.hxx for more details. */
    4718             : 
    4719             :     // get the global hyperlink object of the sheet (sheet should always be the parent of a Range object)
    4720           0 :     uno::Reference< excel::XWorksheet > xWorksheet( getParent(), uno::UNO_QUERY_THROW );
    4721           0 :     uno::Reference< excel::XHyperlinks > xSheetHlinks( xWorksheet->Hyperlinks( uno::Any() ), uno::UNO_QUERY_THROW );
    4722           0 :     ScVbaHyperlinksRef xScSheetHlinks( dynamic_cast< ScVbaHyperlinks* >( xSheetHlinks.get() ) );
    4723           0 :     if( !xScSheetHlinks.is() )
    4724           0 :         throw uno::RuntimeException("Cannot obtain hyperlinks implementation object" );
    4725             : 
    4726             :     // create a new local hyperlinks object based on the sheet hyperlinks
    4727           0 :     ScVbaHyperlinksRef xHlinks( new ScVbaHyperlinks( getParent(), mxContext, xScSheetHlinks, getScRangeList() ) );
    4728           0 :     if( aIndex.hasValue() )
    4729           0 :         return xHlinks->Item( aIndex, uno::Any() );
    4730           0 :     return uno::Any( uno::Reference< excel::XHyperlinks >( xHlinks.get() ) );
    4731             : }
    4732             : 
    4733             : css::uno::Reference< excel::XValidation > SAL_CALL
    4734          20 : ScVbaRange::getValidation() throw (css::uno::RuntimeException, std::exception)
    4735             : {
    4736          20 :     if ( !m_xValidation.is() )
    4737           1 :         m_xValidation = new ScVbaValidation( this, mxContext, mxRange );
    4738          20 :     return m_xValidation;
    4739             : }
    4740             : 
    4741             : namespace {
    4742             : 
    4743           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCell >& rxCell ) throw (uno::RuntimeException)
    4744             : {
    4745             :     /*  TODO/FIXME: We need an apostroph-prefix property at the cell to
    4746             :         implement this correctly. For now, return an apostroph for every text
    4747             :         cell.
    4748             : 
    4749             :         TODO/FIXME: When Application.TransitionNavigKeys is supported and true,
    4750             :         this function needs to inspect the cell formatting and return different
    4751             :         prefixes according to the horizontal cell alignment.
    4752             :      */
    4753           0 :     return (rxCell->getType() == table::CellContentType_TEXT) ? '\'' : 0;
    4754             : }
    4755             : 
    4756           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCellRange >& rxRange ) throw (uno::RuntimeException)
    4757             : {
    4758             :     /*  This implementation is able to handle different prefixes (needed if
    4759             :         Application.TransitionNavigKeys is true). The function lclGetPrefixChar
    4760             :         for single cells called from here may return any prefix. If that
    4761             :         function returns an empty prefix (NUL character) or different non-empty
    4762             :         prefixes for two cells, this function returns 0.
    4763             :      */
    4764           0 :     sal_Unicode cCurrPrefix = 0;
    4765           0 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxRange );
    4766           0 :     sal_Int32 nEndCol = aRangeAddr.EndColumn - aRangeAddr.StartColumn;
    4767           0 :     sal_Int32 nEndRow = aRangeAddr.EndRow - aRangeAddr.StartRow;
    4768           0 :     for( sal_Int32 nRow = 0; nRow <= nEndRow; ++nRow )
    4769             :     {
    4770           0 :         for( sal_Int32 nCol = 0; nCol <= nEndCol; ++nCol )
    4771             :         {
    4772           0 :             uno::Reference< table::XCell > xCell( rxRange->getCellByPosition( nCol, nRow ), uno::UNO_SET_THROW );
    4773           0 :             sal_Unicode cNewPrefix = lclGetPrefixChar( xCell );
    4774           0 :             if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) )
    4775           0 :                 return 0;
    4776           0 :             cCurrPrefix = cNewPrefix;
    4777           0 :         }
    4778             :     }
    4779             :     // all cells contain the same prefix - return it
    4780           0 :     return cCurrPrefix;
    4781             : }
    4782             : 
    4783           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< sheet::XSheetCellRangeContainer >& rxRanges ) throw (uno::RuntimeException)
    4784             : {
    4785           0 :     sal_Unicode cCurrPrefix = 0;
    4786           0 :     uno::Reference< container::XEnumerationAccess > xRangesEA( rxRanges, uno::UNO_QUERY_THROW );
    4787           0 :     uno::Reference< container::XEnumeration > xRangesEnum( xRangesEA->createEnumeration(), uno::UNO_SET_THROW );
    4788           0 :     while( xRangesEnum->hasMoreElements() )
    4789             :     {
    4790           0 :         uno::Reference< table::XCellRange > xRange( xRangesEnum->nextElement(), uno::UNO_QUERY_THROW );
    4791           0 :         sal_Unicode cNewPrefix = lclGetPrefixChar( xRange );
    4792           0 :         if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) )
    4793           0 :             return 0;
    4794           0 :         cCurrPrefix = cNewPrefix;
    4795           0 :     }
    4796             :     // all ranges contain the same prefix - return it
    4797           0 :     return cCurrPrefix;
    4798             : }
    4799             : 
    4800           0 : inline uno::Any lclGetPrefixVariant( sal_Unicode cPrefixChar )
    4801             : {
    4802           0 :     return uno::Any( (cPrefixChar == 0) ? OUString() : OUString( cPrefixChar ) );
    4803             : }
    4804             : 
    4805             : } // namespace
    4806             : 
    4807           0 : uno::Any SAL_CALL ScVbaRange::getPrefixCharacter() throw (uno::RuntimeException, std::exception)
    4808             : {
    4809             :     /*  (1) If Application.TransitionNavigKeys is false, this function returns
    4810             :         an apostroph character if the text cell begins with an apostroph
    4811             :         character (formula return values are not taken into account); otherwise
    4812             :         an empty string.
    4813             : 
    4814             :         (2) If Application.TransitionNavigKeys is true, this function returns
    4815             :         an apostroph character, if the cell is left-aligned; a double-quote
    4816             :         character, if the cell is right-aligned; a circumflex character, if the
    4817             :         cell is centered; a backslash character, if the cell is set to filled;
    4818             :         or an empty string, if nothing of the above.
    4819             : 
    4820             :         If a range or a list of ranges contains texts with leading apostroph
    4821             :         character as well as other cells, this function returns an empty
    4822             :         string.
    4823             :      */
    4824             : 
    4825           0 :     if( mxRange.is() )
    4826           0 :         return lclGetPrefixVariant( lclGetPrefixChar( mxRange ) );
    4827           0 :     if( mxRanges.is() )
    4828           0 :         return lclGetPrefixVariant( lclGetPrefixChar( mxRanges ) );
    4829           0 :     throw uno::RuntimeException("Unexpected empty Range object" );
    4830             : }
    4831             : 
    4832           3 : uno::Any ScVbaRange::getShowDetail() throw ( css::uno::RuntimeException, std::exception)
    4833             : {
    4834             :     // #FIXME, If the specified range is in a PivotTable report
    4835             : 
    4836             :     // In MSO VBA, the specified range must be a single summary column or row in an outline. otherwise throw exception
    4837           3 :     if( m_Areas->getCount() > 1 )
    4838           0 :         throw uno::RuntimeException("Can not get Range.ShowDetail attribute " );
    4839             : 
    4840           3 :     RangeHelper helper( mxRange );
    4841           6 :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = helper.getSheetCellCursor();
    4842           3 :     xSheetCellCursor->collapseToCurrentRegion();
    4843           6 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    4844           3 :     table::CellRangeAddress aOutlineAddress = xCellRangeAddressable->getRangeAddress();
    4845             : 
    4846             :     // check if the specified range is a single summary column or row.
    4847           3 :     table::CellRangeAddress thisAddress = helper.getCellRangeAddressable()->getRangeAddress();
    4848           3 :     if( (thisAddress.StartRow == thisAddress.EndRow &&  thisAddress.EndRow == aOutlineAddress.EndRow ) ||
    4849           0 :         (thisAddress.StartColumn == thisAddress.EndColumn && thisAddress.EndColumn == aOutlineAddress.EndColumn ))
    4850             :     {
    4851           3 :         bool bColumn = thisAddress.StartRow != thisAddress.EndRow;
    4852           3 :         ScDocument& rDoc = getDocumentFromRange( mxRange );
    4853           3 :         ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable(static_cast<SCTAB>(thisAddress.Sheet), true);
    4854           3 :         const ScOutlineArray& rOutlineArray =  bColumn ? pOutlineTable->GetColArray(): pOutlineTable->GetRowArray();
    4855           3 :         SCCOLROW nPos = bColumn ? (SCCOLROW)(thisAddress.EndColumn-1):(SCCOLROW)(thisAddress.EndRow-1);
    4856           3 :         const ScOutlineEntry* pEntry = rOutlineArray.GetEntryByPos( 0, nPos );
    4857           3 :         if( pEntry )
    4858             :         {
    4859           3 :             const bool bShowDetail = !pEntry->IsHidden();
    4860           3 :             return uno::makeAny( bShowDetail );
    4861           0 :         }
    4862             :     }
    4863             :     else
    4864             :     {
    4865           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4866             :     }
    4867           3 :     return aNULL();
    4868             : }
    4869             : 
    4870           2 : void ScVbaRange::setShowDetail(const uno::Any& aShowDetail) throw ( css::uno::RuntimeException, std::exception)
    4871             : {
    4872             :     // #FIXME, If the specified range is in a PivotTable report
    4873             : 
    4874             :     // In MSO VBA, the specified range must be a single summary column or row in an outline. otherwise throw exception
    4875           2 :     if( m_Areas->getCount() > 1 )
    4876           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4877             : 
    4878           2 :     bool bShowDetail = extractBoolFromAny( aShowDetail );
    4879             : 
    4880           2 :     RangeHelper helper( mxRange );
    4881           4 :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = helper.getSheetCellCursor();
    4882           2 :     xSheetCellCursor->collapseToCurrentRegion();
    4883           4 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    4884           2 :     table::CellRangeAddress aOutlineAddress = xCellRangeAddressable->getRangeAddress();
    4885             : 
    4886             :     // check if the specified range is a single summary column or row.
    4887           2 :     table::CellRangeAddress thisAddress = helper.getCellRangeAddressable()->getRangeAddress();
    4888           2 :     if( (thisAddress.StartRow == thisAddress.EndRow &&  thisAddress.EndRow == aOutlineAddress.EndRow ) ||
    4889           0 :         (thisAddress.StartColumn == thisAddress.EndColumn && thisAddress.EndColumn == aOutlineAddress.EndColumn ))
    4890             :     {
    4891             :         // #FIXME, seems there is a different behavior between MSO and OOo.
    4892             :         //  In OOo, the showDetail will show all the level entrys, while only show the first level entry in MSO
    4893           2 :         uno::Reference< sheet::XSheetOutline > xSheetOutline( helper.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4894           2 :         if( bShowDetail )
    4895           1 :             xSheetOutline->showDetail( aOutlineAddress );
    4896             :         else
    4897           1 :             xSheetOutline->hideDetail( aOutlineAddress );
    4898             :     }
    4899             :     else
    4900             :     {
    4901           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4902           2 :     }
    4903           2 : }
    4904             : 
    4905             : uno::Reference< excel::XRange > SAL_CALL
    4906           1 : ScVbaRange::MergeArea() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    4907             : {
    4908           1 :     uno::Reference< sheet::XSheetCellRange > xMergeShellCellRange(mxRange->getCellRangeByPosition(0,0,0,0), uno::UNO_QUERY_THROW);
    4909           2 :     uno::Reference< sheet::XSheetCellCursor > xMergeSheetCursor(xMergeShellCellRange->getSpreadsheet()->createCursorByRange( xMergeShellCellRange ), uno::UNO_QUERY_THROW);
    4910           1 :     if( xMergeSheetCursor.is() )
    4911             :     {
    4912           1 :         xMergeSheetCursor->collapseToMergedArea();
    4913           1 :         uno::Reference<sheet::XCellRangeAddressable> xMergeCellAddress(xMergeSheetCursor, uno::UNO_QUERY_THROW);
    4914           1 :         if( xMergeCellAddress.is() )
    4915             :         {
    4916           1 :             table::CellRangeAddress aCellAddress = xMergeCellAddress->getRangeAddress();
    4917           1 :             if( aCellAddress.StartColumn ==0 && aCellAddress.EndColumn==0 &&
    4918           0 :                 aCellAddress.StartRow==0 && aCellAddress.EndRow==0)
    4919             :             {
    4920           0 :                 return new ScVbaRange( mxParent,mxContext,mxRange );
    4921             :             }
    4922             :             else
    4923             :             {
    4924             :                 ScRange refRange( static_cast< SCCOL >( aCellAddress.StartColumn ), static_cast< SCROW >( aCellAddress.StartRow ), static_cast< SCTAB >( aCellAddress.Sheet ),
    4925           1 :                                   static_cast< SCCOL >( aCellAddress.EndColumn ), static_cast< SCROW >( aCellAddress.EndRow ), static_cast< SCTAB >( aCellAddress.Sheet ) );
    4926           1 :                 uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell() , refRange ) );
    4927           1 :                 return new ScVbaRange( mxParent, mxContext,xRange );
    4928             :             }
    4929           0 :         }
    4930             :     }
    4931           1 :     return new ScVbaRange( mxParent, mxContext, mxRange );
    4932             : }
    4933             : 
    4934             : void SAL_CALL
    4935           0 : ScVbaRange::PrintOut( const uno::Any& From, const uno::Any& To, const uno::Any& Copies, const uno::Any& Preview, const uno::Any& ActivePrinter, const uno::Any& PrintToFile, const uno::Any& Collate, const uno::Any& PrToFileName ) throw (uno::RuntimeException, std::exception)
    4936             : {
    4937           0 :     ScDocShell* pShell = NULL;
    4938             : 
    4939           0 :     sal_Int32 nItems = m_Areas->getCount();
    4940           0 :     uno::Sequence<  table::CellRangeAddress > printAreas( nItems );
    4941           0 :     uno::Reference< sheet::XPrintAreas > xPrintAreas;
    4942           0 :     for ( sal_Int32 index=1; index <= nItems; ++index )
    4943             :     {
    4944           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    4945             : 
    4946           0 :         RangeHelper thisRange( xRange->getCellRange() );
    4947           0 :         table::CellRangeAddress rangeAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4948           0 :         if ( index == 1 )
    4949             :         {
    4950           0 :             ScVbaRange* pRange = getImplementation( xRange );
    4951             :             // initialise the doc shell and the printareas
    4952           0 :             pShell = getDocShellFromRange( pRange->mxRange );
    4953           0 :             xPrintAreas.set( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4954             :         }
    4955           0 :         printAreas[ index - 1 ] = rangeAddress;
    4956           0 :     }
    4957           0 :     if ( pShell )
    4958             :     {
    4959           0 :         if ( xPrintAreas.is() )
    4960             :         {
    4961           0 :             xPrintAreas->setPrintAreas( printAreas );
    4962           0 :             uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4963           0 :             PrintOutHelper( excel::getBestViewShell( xModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, true );
    4964             :         }
    4965           0 :     }
    4966           0 : }
    4967             : 
    4968             : void SAL_CALL
    4969           0 : ScVbaRange::AutoFill(  const uno::Reference< excel::XRange >& Destination, const uno::Any& Type ) throw (uno::RuntimeException, std::exception)
    4970             : {
    4971           0 :     uno::Reference< excel::XRange > xDest( Destination, uno::UNO_QUERY_THROW );
    4972           0 :     ScVbaRange* pRange = getImplementation( xDest );
    4973           0 :     RangeHelper destRangeHelper( pRange->mxRange );
    4974           0 :     table::CellRangeAddress destAddress = destRangeHelper.getCellRangeAddressable()->getRangeAddress();
    4975             : 
    4976           0 :     RangeHelper thisRange( mxRange );
    4977           0 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4978           0 :     ScRange sourceRange;
    4979           0 :     ScRange destRange;
    4980             : 
    4981           0 :     ScUnoConversion::FillScRange( destRange, destAddress );
    4982           0 :     ScUnoConversion::FillScRange( sourceRange, thisAddress );
    4983             : 
    4984           0 :     FillDir eDir = FILL_TO_BOTTOM;
    4985           0 :     double fStep = 1.0;
    4986             : 
    4987           0 :     ScRange aRange( destRange );
    4988           0 :     ScRange aSourceRange( destRange );
    4989             : 
    4990             :     // default to include the number of Rows in the source range;
    4991           0 :     SCCOLROW nSourceCount = ( sourceRange.aEnd.Row() - sourceRange.aStart.Row() ) + 1;
    4992           0 :     SCCOLROW nCount = 0;
    4993             : 
    4994           0 :     if ( sourceRange != destRange )
    4995             :     {
    4996             :         // Find direction of fill, vertical or horizontal
    4997           0 :         if ( sourceRange.aStart == destRange.aStart )
    4998             :         {
    4999           0 :             if ( sourceRange.aEnd.Row() == destRange.aEnd.Row() )
    5000             :             {
    5001           0 :                 nSourceCount = ( sourceRange.aEnd.Col() - sourceRange.aStart.Col() + 1 );
    5002           0 :                 aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) );
    5003           0 :                 eDir = FILL_TO_RIGHT;
    5004           0 :                 nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col();
    5005             :             }
    5006           0 :             else if ( sourceRange.aEnd.Col() == destRange.aEnd.Col() )
    5007             :             {
    5008           0 :                 aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount ) - 1 );
    5009           0 :                 nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row();
    5010           0 :                 eDir = FILL_TO_BOTTOM;
    5011             :             }
    5012             :         }
    5013             : 
    5014           0 :         else if ( aSourceRange.aEnd == destRange.aEnd )
    5015             :         {
    5016           0 :             if ( sourceRange.aStart.Col() == destRange.aStart.Col() )
    5017             :             {
    5018           0 :                 aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) );
    5019           0 :                 nCount = aSourceRange.aStart.Row() - aRange.aStart.Row();
    5020           0 :                 eDir = FILL_TO_TOP;
    5021           0 :                 fStep = -fStep;
    5022             :             }
    5023           0 :             else if ( sourceRange.aStart.Row() == destRange.aStart.Row() )
    5024             :             {
    5025           0 :                 nSourceCount = ( sourceRange.aEnd.Col() - sourceRange.aStart.Col() ) + 1;
    5026           0 :                 aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) );
    5027           0 :                 nCount = aSourceRange.aStart.Col() - aRange.aStart.Col();
    5028           0 :                 eDir = FILL_TO_LEFT;
    5029           0 :                 fStep = -fStep;
    5030             :             }
    5031             :         }
    5032             :     }
    5033             : 
    5034           0 :     FillCmd eCmd = FILL_AUTO;
    5035           0 :     FillDateCmd eDateCmd = FILL_DAY;
    5036             : 
    5037           0 :     if ( Type.hasValue() )
    5038             :     {
    5039           0 :         sal_Int16 nFillType = excel::XlAutoFillType::xlFillDefault;
    5040           0 :         Type >>= nFillType;
    5041           0 :         switch ( nFillType )
    5042             :         {
    5043             :             case excel::XlAutoFillType::xlFillCopy:
    5044           0 :                 eCmd =  FILL_SIMPLE;
    5045           0 :                 fStep = 0.0;
    5046           0 :                 break;
    5047             :             case excel::XlAutoFillType::xlFillDays:
    5048           0 :                 eCmd = FILL_DATE;
    5049           0 :                 break;
    5050             :             case excel::XlAutoFillType::xlFillMonths:
    5051           0 :                 eCmd = FILL_DATE;
    5052           0 :                 eDateCmd = FILL_MONTH;
    5053           0 :                 break;
    5054             :             case excel::XlAutoFillType::xlFillWeekdays:
    5055           0 :                 eCmd = FILL_DATE;
    5056           0 :                 eDateCmd = FILL_WEEKDAY;
    5057           0 :                 break;
    5058             :             case excel::XlAutoFillType::xlFillYears:
    5059           0 :                 eCmd = FILL_DATE;
    5060           0 :                 eDateCmd = FILL_YEAR;
    5061           0 :                 break;
    5062             :             case excel::XlAutoFillType::xlGrowthTrend:
    5063           0 :                 eCmd = FILL_GROWTH;
    5064           0 :                 break;
    5065             :             case excel::XlAutoFillType::xlFillFormats:
    5066           0 :                 throw uno::RuntimeException("xlFillFormat not supported for AutoFill" );
    5067             :             case excel::XlAutoFillType::xlFillValues:
    5068             :             case excel::XlAutoFillType::xlFillSeries:
    5069             :             case excel::XlAutoFillType::xlLinearTrend:
    5070           0 :                 eCmd = FILL_LINEAR;
    5071           0 :                 break;
    5072             :             case excel::XlAutoFillType::xlFillDefault:
    5073             :             default:
    5074           0 :                 eCmd =  FILL_AUTO;
    5075           0 :                 break;
    5076             :         }
    5077             :     }
    5078           0 :     double fEndValue =  MAXDOUBLE;
    5079           0 :     ScDocShell* pDocSh = getDocShellFromRange( mxRange );
    5080           0 :     pDocSh->GetDocFunc().FillAuto( aSourceRange, NULL, eDir, eCmd, eDateCmd,
    5081           0 :                                    nCount, fStep, fEndValue, true, true );
    5082           0 : }
    5083             : sal_Bool SAL_CALL
    5084           1 : ScVbaRange::GoalSeek( const uno::Any& Goal, const uno::Reference< excel::XRange >& ChangingCell ) throw (uno::RuntimeException, std::exception)
    5085             : {
    5086           1 :     ScDocShell* pDocShell = getScDocShell();
    5087           1 :     bool bRes = true;
    5088           1 :     ScVbaRange* pRange = static_cast< ScVbaRange* >( ChangingCell.get() );
    5089           1 :     if ( pDocShell && pRange )
    5090             :     {
    5091           1 :         uno::Reference< sheet::XGoalSeek > xGoalSeek(  pDocShell->GetModel(), uno::UNO_QUERY_THROW );
    5092           2 :         RangeHelper thisRange( mxRange );
    5093           1 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5094           2 :         RangeHelper changingCellRange( pRange->mxRange );
    5095           1 :         table::CellRangeAddress changingCellAddr = changingCellRange.getCellRangeAddressable()->getRangeAddress();
    5096           2 :         OUString sGoal = getAnyAsString( Goal );
    5097           1 :         table::CellAddress thisCell( thisAddress.Sheet, thisAddress.StartColumn, thisAddress.StartRow );
    5098           1 :         table::CellAddress changingCell( changingCellAddr.Sheet, changingCellAddr.StartColumn, changingCellAddr.StartRow );
    5099           1 :         sheet::GoalResult res = xGoalSeek->seekGoal( thisCell, changingCell, sGoal );
    5100           1 :         ChangingCell->setValue( uno::makeAny( res.Result ) );
    5101             : 
    5102             :         // openoffice behaves differently, result is 0 if the divergence is too great
    5103             :                 // but... if it detects 0 is the value it requires then it will use that
    5104             :         // e.g. divergence & result both = 0.0 does NOT mean there is an error
    5105           1 :         if ( ( res.Divergence != 0.0 ) && ( res.Result == 0.0 ) )
    5106           1 :             bRes = false;
    5107             :     }
    5108             :     else
    5109           0 :         bRes = false;
    5110           1 :     return bRes;
    5111             : }
    5112             : 
    5113             : void
    5114           2 : ScVbaRange::Calculate(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5115             : {
    5116           2 :     getWorksheet()->Calculate();
    5117           2 : }
    5118             : 
    5119             : uno::Reference< excel::XRange > SAL_CALL
    5120          20 : ScVbaRange::Item( const uno::Any& row, const uno::Any& column ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5121             : {
    5122          20 :     if ( mbIsRows || mbIsColumns )
    5123             :     {
    5124          12 :         if ( column.hasValue() )
    5125           0 :             DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5126          12 :         uno::Reference< excel::XRange > xRange;
    5127          12 :         if ( mbIsColumns )
    5128           7 :             xRange = Columns( row );
    5129             :         else
    5130           5 :             xRange = Rows( row );
    5131          12 :         return xRange;
    5132             :     }
    5133           8 :     return Cells( row, column );
    5134             : }
    5135             : 
    5136             : void
    5137           1 : ScVbaRange::AutoOutline(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5138             : {
    5139             :     // #TODO #FIXME needs to check for summary row/col ( whatever they are )
    5140             :     // not valid for multi Area Addresses
    5141           1 :     if ( m_Areas->getCount() > 1 )
    5142           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY);
    5143             :     // So needs to either span an entire Row or a just be a single cell
    5144             :     // ( that contains a summary RowColumn )
    5145             :     // also the Single cell cause doesn't seem to be handled specially in
    5146             :     // this code ( ported from the helperapi RangeImpl.java,
    5147             :     // RangeRowsImpl.java, RangesImpl.java, RangeSingleCellImpl.java
    5148           1 :     RangeHelper thisRange( mxRange );
    5149           1 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5150             : 
    5151           1 :     if ( isSingleCellRange() || mbIsRows )
    5152             :     {
    5153           1 :         uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5154           1 :         xSheetOutline->autoOutline( thisAddress );
    5155             :     }
    5156             :     else
    5157           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    5158           1 : }
    5159             : 
    5160             : void SAL_CALL
    5161           8 : ScVbaRange:: ClearOutline(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5162             : {
    5163           8 :     if ( m_Areas->getCount() > 1 )
    5164             :     {
    5165           2 :         sal_Int32 nItems = m_Areas->getCount();
    5166           6 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5167             :         {
    5168           4 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5169           4 :             xRange->ClearOutline();
    5170           4 :         }
    5171           4 :         return;
    5172             :     }
    5173           6 :     RangeHelper thisRange( mxRange );
    5174          12 :     uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5175          12 :     xSheetOutline->clearOutline();
    5176             : }
    5177             : 
    5178             : void
    5179           6 : ScVbaRange::groupUnGroup( bool bUnGroup ) throw ( script::BasicErrorException, uno::RuntimeException )
    5180             : {
    5181           6 :     if ( m_Areas->getCount() > 1 )
    5182           0 :          DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY);
    5183           6 :     table::TableOrientation nOrient = table::TableOrientation_ROWS;
    5184           6 :     if ( mbIsColumns )
    5185           0 :         nOrient = table::TableOrientation_COLUMNS;
    5186           6 :     RangeHelper thisRange( mxRange );
    5187           6 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5188          12 :     uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5189           6 :     if ( bUnGroup )
    5190           2 :             xSheetOutline->ungroup( thisAddress, nOrient );
    5191             :     else
    5192          10 :             xSheetOutline->group( thisAddress, nOrient );
    5193           6 : }
    5194             : 
    5195             : void SAL_CALL
    5196           4 : ScVbaRange::Group(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5197             : {
    5198           4 :     groupUnGroup();
    5199           4 : }
    5200             : void SAL_CALL
    5201           2 : ScVbaRange::Ungroup(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5202             : {
    5203           2 :     groupUnGroup(true);
    5204           2 : }
    5205             : 
    5206           5 : static void lcl_mergeCellsOfRange( const uno::Reference< table::XCellRange >& xCellRange, bool _bMerge = true ) throw ( uno::RuntimeException )
    5207             : {
    5208           5 :         uno::Reference< util::XMergeable > xMergeable( xCellRange, uno::UNO_QUERY_THROW );
    5209           5 :         xMergeable->merge(_bMerge);
    5210           5 : }
    5211             : void SAL_CALL
    5212           4 : ScVbaRange::Merge( const uno::Any& Across ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5213             : {
    5214           4 :     if ( m_Areas->getCount() > 1 )
    5215             :     {
    5216           0 :         sal_Int32 nItems = m_Areas->getCount();
    5217           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5218             :         {
    5219           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5220           0 :             xRange->Merge(Across);
    5221           0 :         }
    5222           0 :         return;
    5223             :     }
    5224           4 :     uno::Reference< table::XCellRange > oCellRange;
    5225           4 :     bool bAcross = false;
    5226           4 :     Across >>= bAcross;
    5227           4 :     if ( !bAcross )
    5228           3 :         lcl_mergeCellsOfRange( mxRange );
    5229             :     else
    5230             :     {
    5231           1 :         uno::Reference< excel::XRange > oRangeRowsImpl = Rows( uno::Any() );
    5232             :         // #TODO #FIXME this seems incredibly lame, this can't be right
    5233           3 :         for (sal_Int32 i=1; i <= oRangeRowsImpl->getCount();i++)
    5234             :         {
    5235           2 :             oRangeRowsImpl->Cells( uno::makeAny( i ), uno::Any() )->Merge( uno::makeAny( false ) );
    5236           1 :         }
    5237           4 :     }
    5238             : }
    5239             : 
    5240             : void SAL_CALL
    5241           2 : ScVbaRange::UnMerge(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5242             : {
    5243           2 :     if ( m_Areas->getCount() > 1 )
    5244             :     {
    5245           0 :         sal_Int32 nItems = m_Areas->getCount();
    5246           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5247             :         {
    5248           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5249           0 :             xRange->UnMerge();
    5250           0 :         }
    5251           2 :         return;
    5252             :     }
    5253           2 :     lcl_mergeCellsOfRange( mxRange, false);
    5254             : }
    5255             : 
    5256             : uno::Any SAL_CALL
    5257           0 : ScVbaRange::getStyle() throw (css::script::BasicErrorException, uno::RuntimeException, std::exception)
    5258             : {
    5259           0 :     if ( m_Areas->getCount() > 1 )
    5260             :     {
    5261           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW  );
    5262           0 :         return xRange->getStyle();
    5263             :     }
    5264           0 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    5265           0 :     OUString sStyleName;
    5266           0 :     xProps->getPropertyValue( CELLSTYLE ) >>= sStyleName;
    5267           0 :     ScDocShell* pShell = getScDocShell();
    5268           0 :     uno::Reference< frame::XModel > xModel( pShell->GetModel() );
    5269           0 :     uno::Reference< excel::XStyle > xStyle = new ScVbaStyle( this, mxContext,  sStyleName, xModel );
    5270           0 :     return uno::makeAny( xStyle );
    5271             : }
    5272             : void SAL_CALL
    5273           0 : ScVbaRange::setStyle( const uno::Any& _style ) throw (uno::RuntimeException, std::exception)
    5274             : {
    5275           0 :     if ( m_Areas->getCount() > 1 )
    5276             :     {
    5277           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW );
    5278           0 :         xRange->setStyle( _style );
    5279           0 :         return;
    5280             :     }
    5281           0 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    5282           0 :     uno::Reference< excel::XStyle > xStyle;
    5283           0 :     _style >>= xStyle;
    5284           0 :     xProps->setPropertyValue( CELLSTYLE, uno::makeAny( xStyle->getName() ) );
    5285             : }
    5286             : 
    5287             : uno::Reference< excel::XRange >
    5288           0 : ScVbaRange::PreviousNext( bool bIsPrevious )
    5289             : {
    5290           0 :     ScMarkData markedRange;
    5291           0 :     ScRange refRange;
    5292           0 :     RangeHelper thisRange( mxRange );
    5293             : 
    5294           0 :     ScUnoConversion::FillScRange( refRange, thisRange.getCellRangeAddressable()->getRangeAddress());
    5295           0 :     markedRange. SetMarkArea( refRange );
    5296           0 :     short nMove = bIsPrevious ? -1 : 1;
    5297             : 
    5298           0 :     SCCOL nNewX = refRange.aStart.Col();
    5299           0 :     SCROW nNewY = refRange.aStart.Row();
    5300           0 :     SCTAB nTab = refRange.aStart.Tab();
    5301             : 
    5302           0 :     ScDocument& rDoc = getScDocument();
    5303           0 :     rDoc.GetNextPos( nNewX,nNewY, nTab, nMove,0, true,true, markedRange );
    5304           0 :     refRange.aStart.SetCol( nNewX );
    5305           0 :     refRange.aStart.SetRow( nNewY );
    5306           0 :     refRange.aStart.SetTab( nTab );
    5307           0 :     refRange.aEnd.SetCol( nNewX );
    5308           0 :     refRange.aEnd.SetRow( nNewY );
    5309           0 :     refRange.aEnd.SetTab( nTab );
    5310             : 
    5311           0 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell() , refRange ) );
    5312             : 
    5313           0 :     return new ScVbaRange( mxParent, mxContext, xRange );
    5314             : }
    5315             : 
    5316             : uno::Reference< excel::XRange > SAL_CALL
    5317           0 : ScVbaRange::Next() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5318             : {
    5319           0 :     if ( m_Areas->getCount() > 1 )
    5320             :     {
    5321           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ) , uno::UNO_QUERY_THROW  );
    5322           0 :         return xRange->Next();
    5323             :     }
    5324           0 :     return PreviousNext( false );
    5325             : }
    5326             : 
    5327             : uno::Reference< excel::XRange > SAL_CALL
    5328           0 : ScVbaRange::Previous() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5329             : {
    5330           0 :     if ( m_Areas->getCount() > 1 )
    5331             :     {
    5332           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW  );
    5333           0 :         return xRange->Previous();
    5334             :     }
    5335           0 :     return PreviousNext( true );
    5336             : }
    5337             : 
    5338             : uno::Reference< excel::XRange > SAL_CALL
    5339           7 : ScVbaRange::SpecialCells( const uno::Any& _oType, const uno::Any& _oValue)
    5340             :     throw (script::BasicErrorException, uno::RuntimeException,
    5341             :            std::exception)
    5342             : {
    5343           7 :     bool bIsSingleCell = isSingleCellRange();
    5344           7 :     bool bIsMultiArea = ( m_Areas->getCount() > 1 );
    5345           7 :     ScVbaRange* pRangeToUse = this;
    5346           7 :     uno::Reference< excel::XRange > xUsedRange( getWorksheet()->getUsedRange() );
    5347           7 :     sal_Int32 nType = 0;
    5348           7 :     if ( !( _oType >>= nType ) )
    5349           0 :         DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5350           7 :     switch(nType)
    5351             :     {
    5352             :         case excel::XlCellType::xlCellTypeSameFormatConditions:
    5353             :         case excel::XlCellType::xlCellTypeAllValidation:
    5354             :         case excel::XlCellType::xlCellTypeSameValidation:
    5355           0 :             DebugHelper::basicexception(SbERR_NOT_IMPLEMENTED, OUString());
    5356           0 :             break;
    5357             :         case excel::XlCellType::xlCellTypeBlanks:
    5358             :         case excel::XlCellType::xlCellTypeComments:
    5359             :         case excel::XlCellType::xlCellTypeConstants:
    5360             :         case excel::XlCellType::xlCellTypeFormulas:
    5361             :         case excel::XlCellType::xlCellTypeVisible:
    5362             :         case excel::XlCellType::xlCellTypeLastCell:
    5363             :         {
    5364           7 :             if ( bIsMultiArea )
    5365             :             {
    5366             :                 // need to process each area, gather the results and
    5367             :                 // create a new range from those
    5368           0 :                 std::vector< table::CellRangeAddress > rangeResults;
    5369           0 :                 sal_Int32 nItems = ( m_Areas->getCount() + 1 );
    5370           0 :                 for ( sal_Int32 index=1; index <= nItems; ++index )
    5371             :                 {
    5372           0 :                     uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5373           0 :                     xRange = xRange->SpecialCells( _oType,  _oValue);
    5374           0 :                     ScVbaRange* pRange = getImplementation( xRange );
    5375           0 :                     if ( xRange.is() && pRange )
    5376             :                     {
    5377           0 :                         sal_Int32 nElems = ( pRange->m_Areas->getCount() + 1 );
    5378           0 :                         for ( sal_Int32 nArea = 1; nArea < nElems; ++nArea )
    5379             :                         {
    5380           0 :                             uno::Reference< excel::XRange > xTmpRange( m_Areas->Item( uno::makeAny( nArea ), uno::Any() ), uno::UNO_QUERY_THROW );
    5381           0 :                             RangeHelper rHelper( xTmpRange->getCellRange() );
    5382           0 :                             rangeResults.push_back( rHelper.getCellRangeAddressable()->getRangeAddress() );
    5383           0 :                         }
    5384             :                     }
    5385           0 :                 }
    5386           0 :                 ScRangeList aCellRanges;
    5387           0 :                 std::vector< table::CellRangeAddress >::iterator it = rangeResults.begin();
    5388           0 :                 std::vector< table::CellRangeAddress >::iterator it_end = rangeResults.end();
    5389           0 :                 for ( ; it != it_end; ++ it )
    5390             :                 {
    5391           0 :                     ScRange refRange;
    5392           0 :                     ScUnoConversion::FillScRange( refRange, *it );
    5393           0 :                     aCellRanges.Append( refRange );
    5394             :                 }
    5395             :                 // Single range
    5396           0 :                 if ( aCellRanges.size() == 1 )
    5397             :                 {
    5398           0 :                     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell(), *aCellRanges.front() ) );
    5399           0 :                     return new ScVbaRange( mxParent, mxContext, xRange );
    5400             :                 }
    5401           0 :                 uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( getScDocShell(), aCellRanges ) );
    5402             : 
    5403           0 :                 return new ScVbaRange( mxParent, mxContext, xRanges );
    5404             :             }
    5405           7 :             else if ( bIsSingleCell )
    5406             :             {
    5407           0 :                 pRangeToUse = static_cast< ScVbaRange* >( xUsedRange.get() );
    5408             :             }
    5409             : 
    5410           7 :             break;
    5411             :         }
    5412             :         default:
    5413           0 :         DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5414           0 :             break;
    5415             :     }
    5416           7 :     if ( !pRangeToUse )
    5417           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString() );
    5418           7 :     return pRangeToUse->SpecialCellsImpl( nType, _oValue );
    5419             : }
    5420             : 
    5421           0 : static sal_Int32 lcl_getFormulaResultFlags(const uno::Any& aType) throw ( script::BasicErrorException )
    5422             : {
    5423           0 :     sal_Int32 nType = excel::XlSpecialCellsValue::xlNumbers;
    5424           0 :     aType >>= nType;
    5425           0 :     sal_Int32 nRes = sheet::FormulaResult::VALUE;
    5426             : 
    5427           0 :     switch(nType)
    5428             :     {
    5429             :         case excel::XlSpecialCellsValue::xlErrors:
    5430           0 :             nRes= sheet::FormulaResult::ERROR;
    5431           0 :             break;
    5432             :         case excel::XlSpecialCellsValue::xlLogical:
    5433             :             //TODO bc93774: ask NN if this is really an appropriate substitute
    5434           0 :             nRes = sheet::FormulaResult::VALUE;
    5435           0 :             break;
    5436             :         case excel::XlSpecialCellsValue::xlNumbers:
    5437           0 :             nRes = sheet::FormulaResult::VALUE;
    5438           0 :             break;
    5439             :         case excel::XlSpecialCellsValue::xlTextValues:
    5440           0 :             nRes = sheet::FormulaResult::STRING;
    5441           0 :             break;
    5442             :         default:
    5443           0 :             DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5444             :     }
    5445           0 :     return nRes;
    5446             : }
    5447             : 
    5448             : uno::Reference< excel::XRange >
    5449           7 : ScVbaRange::SpecialCellsImpl( sal_Int32 nType, const uno::Any& _oValue) throw ( script::BasicErrorException )
    5450             : {
    5451           7 :     uno::Reference< excel::XRange > xRange;
    5452             :     try
    5453             :     {
    5454           7 :         uno::Reference< sheet::XCellRangesQuery > xQuery( mxRange, uno::UNO_QUERY_THROW );
    5455          14 :         uno::Reference< excel::XRange > oLocRangeImpl;
    5456          14 :         uno::Reference< sheet::XSheetCellRanges > xLocSheetCellRanges;
    5457           7 :         switch(nType)
    5458             :         {
    5459             :             case excel::XlCellType::xlCellTypeAllFormatConditions:
    5460             :             case excel::XlCellType::xlCellTypeSameFormatConditions:
    5461             :             case excel::XlCellType::xlCellTypeAllValidation:
    5462             :             case excel::XlCellType::xlCellTypeSameValidation:
    5463             :                 // Shouldn't get here ( should be filtered out by
    5464             :                 // ScVbaRange::SpecialCells()
    5465           0 :                 DebugHelper::basicexception(SbERR_NOT_IMPLEMENTED, OUString());
    5466           0 :                 break;
    5467             :             case excel::XlCellType::xlCellTypeBlanks:
    5468           0 :                 xLocSheetCellRanges = xQuery->queryEmptyCells();
    5469           0 :                 break;
    5470             :             case excel::XlCellType::xlCellTypeComments:
    5471           0 :                 xLocSheetCellRanges = xQuery->queryContentCells(sheet::CellFlags::ANNOTATION);
    5472           0 :                 break;
    5473             :             case excel::XlCellType::xlCellTypeConstants:
    5474           0 :                 xLocSheetCellRanges = xQuery->queryContentCells(23);
    5475           0 :                 break;
    5476             :             case excel::XlCellType::xlCellTypeFormulas:
    5477             :             {
    5478           0 :                 sal_Int32 nFormulaResult = lcl_getFormulaResultFlags(_oValue);
    5479           0 :                 xLocSheetCellRanges = xQuery->queryFormulaCells(nFormulaResult);
    5480           0 :                 break;
    5481             :             }
    5482             :             case excel::XlCellType::xlCellTypeLastCell:
    5483           0 :                 xRange = Cells( uno::makeAny( getCount() ), uno::Any() );
    5484             :             case excel::XlCellType::xlCellTypeVisible:
    5485           7 :                 xLocSheetCellRanges = xQuery->queryVisibleCells();
    5486           7 :                 break;
    5487             :             default:
    5488           0 :                 DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5489           0 :                 break;
    5490             :         }
    5491           7 :         if (xLocSheetCellRanges.is())
    5492             :         {
    5493           7 :             xRange = lcl_makeXRangeFromSheetCellRanges( getParent(), mxContext, xLocSheetCellRanges, getScDocShell() );
    5494           7 :         }
    5495             :     }
    5496           0 :     catch (uno::Exception& )
    5497             :     {
    5498           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_NOCELLSWEREFOUND);
    5499             :     }
    5500           7 :     return xRange;
    5501             : }
    5502             : 
    5503             : void SAL_CALL
    5504           0 : ScVbaRange::RemoveSubtotal(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5505             : {
    5506           0 :     uno::Reference< sheet::XSubTotalCalculatable > xSub( mxRange, uno::UNO_QUERY_THROW );
    5507           0 :     xSub->removeSubTotals();
    5508           0 : }
    5509             : 
    5510             : void SAL_CALL
    5511           0 : ScVbaRange::Subtotal( ::sal_Int32 _nGroupBy, ::sal_Int32 _nFunction, const uno::Sequence< ::sal_Int32 >& _nTotalList, const uno::Any& aReplace, const uno::Any& PageBreaks, const uno::Any& /*SummaryBelowData*/ ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5512             : {
    5513             :     try
    5514             :     {
    5515           0 :         bool bDoReplace = false;
    5516           0 :         aReplace >>= bDoReplace;
    5517           0 :         bool bAddPageBreaks = false;
    5518           0 :         PageBreaks >>= bAddPageBreaks;
    5519             : 
    5520           0 :         uno::Reference< sheet::XSubTotalCalculatable> xSub(mxRange, uno::UNO_QUERY_THROW );
    5521           0 :         uno::Reference< sheet::XSubTotalDescriptor > xSubDesc = xSub->createSubTotalDescriptor(sal_True);
    5522           0 :         uno::Reference< beans::XPropertySet > xSubDescPropertySet( xSubDesc, uno::UNO_QUERY_THROW );
    5523           0 :         xSubDescPropertySet->setPropertyValue(INSERTPAGEBREAKS, uno::makeAny( bAddPageBreaks));
    5524           0 :         sal_Int32 nLen = _nTotalList.getLength();
    5525           0 :         uno::Sequence< sheet::SubTotalColumn > aColumns( nLen );
    5526           0 :         for (int i = 0; i < nLen; i++)
    5527             :         {
    5528           0 :             aColumns[i].Column = _nTotalList[i] - 1;
    5529           0 :             switch (_nFunction)
    5530             :             {
    5531             :                 case excel::XlConsolidationFunction::xlAverage:
    5532           0 :                     aColumns[i].Function = sheet::GeneralFunction_AVERAGE;
    5533           0 :                     break;
    5534             :                 case excel::XlConsolidationFunction::xlCount:
    5535           0 :                     aColumns[i].Function = sheet::GeneralFunction_COUNT;
    5536           0 :                     break;
    5537             :                 case excel::XlConsolidationFunction::xlCountNums:
    5538           0 :                     aColumns[i].Function = sheet::GeneralFunction_COUNTNUMS;
    5539           0 :                     break;
    5540             :                 case excel::XlConsolidationFunction::xlMax:
    5541           0 :                     aColumns[i].Function = sheet::GeneralFunction_MAX;
    5542           0 :                     break;
    5543             :                 case excel::XlConsolidationFunction::xlMin:
    5544           0 :                     aColumns[i].Function = sheet::GeneralFunction_MIN;
    5545           0 :                     break;
    5546             :                 case excel::XlConsolidationFunction::xlProduct:
    5547           0 :                     aColumns[i].Function = sheet::GeneralFunction_PRODUCT;
    5548           0 :                     break;
    5549             :                 case excel::XlConsolidationFunction::xlStDev:
    5550           0 :                     aColumns[i].Function = sheet::GeneralFunction_STDEV;
    5551           0 :                     break;
    5552             :                 case excel::XlConsolidationFunction::xlStDevP:
    5553           0 :                     aColumns[i].Function = sheet::GeneralFunction_STDEVP;
    5554           0 :                     break;
    5555             :                 case excel::XlConsolidationFunction::xlSum:
    5556           0 :                     aColumns[i].Function = sheet::GeneralFunction_SUM;
    5557           0 :                     break;
    5558             :                 case excel::XlConsolidationFunction::xlUnknown:
    5559           0 :                     aColumns[i].Function = sheet::GeneralFunction_NONE;
    5560           0 :                     break;
    5561             :                 case excel::XlConsolidationFunction::xlVar:
    5562           0 :                     aColumns[i].Function = sheet::GeneralFunction_VAR;
    5563           0 :                     break;
    5564             :                 case excel::XlConsolidationFunction::xlVarP:
    5565           0 :                     aColumns[i].Function = sheet::GeneralFunction_VARP;
    5566           0 :                     break;
    5567             :                 default:
    5568           0 :                     DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString()) ;
    5569           0 :                     return;
    5570             :             }
    5571             :         }
    5572           0 :         xSubDesc->addNew(aColumns, _nGroupBy - 1);
    5573           0 :         xSub->applySubTotals(xSubDesc, bDoReplace);
    5574             :     }
    5575           0 :     catch (const uno::Exception&)
    5576             :     {
    5577           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    5578             :     }
    5579             : }
    5580             : 
    5581             : OUString
    5582           0 : ScVbaRange::getServiceImplName()
    5583             : {
    5584           0 :     return OUString("ScVbaRange");
    5585             : }
    5586             : 
    5587             : uno::Sequence< OUString >
    5588           0 : ScVbaRange::getServiceNames()
    5589             : {
    5590           0 :     static uno::Sequence< OUString > aServiceNames;
    5591           0 :     if ( aServiceNames.getLength() == 0 )
    5592             :     {
    5593           0 :         aServiceNames.realloc( 1 );
    5594           0 :         aServiceNames[ 0 ] = "ooo.vba.excel.Range";
    5595             :     }
    5596           0 :     return aServiceNames;
    5597             : }
    5598             : 
    5599             : sal_Bool SAL_CALL
    5600           0 : ScVbaRange::hasError() throw (uno::RuntimeException, std::exception)
    5601             : {
    5602           0 :     double dResult = 0.0;
    5603           0 :     uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
    5604           0 :     uno::Reference< script::XInvocation > xInvoc( xApplication->WorksheetFunction(), uno::UNO_QUERY_THROW );
    5605             : 
    5606             :     static const char FunctionName[] = "IsError";
    5607           0 :     uno::Sequence< uno::Any > Params(1);
    5608           0 :     uno::Reference< excel::XRange > aRange( this );
    5609           0 :     Params[0] = uno::makeAny( aRange );
    5610           0 :     uno::Sequence< sal_Int16 > OutParamIndex;
    5611           0 :     uno::Sequence< uno::Any > OutParam;
    5612           0 :     xInvoc->invoke( FunctionName, Params, OutParamIndex, OutParam ) >>= dResult;
    5613           0 :     return dResult > 0.0;
    5614             : }
    5615             : 
    5616             : namespace range
    5617             : {
    5618             : namespace sdecl = comphelper::service_decl;
    5619           3 : sdecl::vba_service_class_<ScVbaRange, sdecl::with_args<true> > serviceImpl;
    5620           3 : extern sdecl::ServiceDecl const serviceDecl(
    5621             :     serviceImpl,
    5622             :     "SvVbaRange",
    5623             :     "ooo.vba.excel.Range" );
    5624           9 : }
    5625             : 
    5626             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11