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