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