LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/ui/vba - vbarange.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1930 2945 65.5 %
Date: 2013-07-09 Functions: 224 297 75.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10