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