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

Generated by: LCOV version 1.10