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