1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #include "vbaworksheets.hxx"
21 #include <sfx2/dispatch.hxx>
22 #include <sfx2/app.hxx>
23 #include <sfx2/bindings.hxx>
24 #include <sfx2/request.hxx>
25 #include <sfx2/viewfrm.hxx>
26 #include <sfx2/itemwrapper.hxx>
27 #include <svl/itemset.hxx>
28 #include <svl/eitem.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <cppuhelper/implbase3.hxx>
33 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
34 #include <com/sun/star/container/XEnumerationAccess.hpp>
35 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
37 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <ooo/vba/excel/XApplication.hpp>
41 #include "tabvwsh.hxx"
43 #include "vbaglobals.hxx"
44 #include "vbaworksheet.hxx"
45 #include "vbaworkbook.hxx"
46 #include "unonames.hxx"
47 #include "markdata.hxx"
50 #include "prevwsh.hxx"
51 #include "preview.hxx"
52 using namespace ::ooo::vba
;
53 using namespace ::com::sun::star
;
55 typedef ::cppu::WeakImplHelper1
< container::XEnumeration
> SheetEnumeration_BASE
;
56 typedef ::cppu::WeakImplHelper3
< container::XNameAccess
, container::XIndexAccess
, container::XEnumerationAccess
> SheetCollectionHelper_BASE
;
57 // a map ( or hashmap ) wont do as we need also to preserve the order
58 // (as added ) of the items
59 typedef std::vector
< uno::Reference
< sheet::XSpreadsheet
> > SheetMap
;
61 // #FIXME #TODO the implementation of the Sheets collections sucks,
62 // e.g. there is no support for tracking sheets added/removed from the collection
64 class WorkSheetsEnumeration
: public SheetEnumeration_BASE
67 SheetMap::iterator mIt
;
69 WorkSheetsEnumeration( const SheetMap
& sMap
) : mSheetMap( sMap
), mIt( mSheetMap
.begin() ) {}
70 virtual sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
72 return ( mIt
!= mSheetMap
.end() );
74 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
76 if ( !hasMoreElements() )
77 throw container::NoSuchElementException();
78 uno::Reference
< sheet::XSpreadsheet
> xSheet( *mIt
++ );
79 return uno::makeAny( xSheet
) ;
83 class SheetCollectionHelper
: public SheetCollectionHelper_BASE
86 SheetMap::iterator cachePos
;
88 SheetCollectionHelper( const SheetMap
& sMap
) : mSheetMap( sMap
), cachePos(mSheetMap
.begin()) {}
90 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
{ return cppu::UnoType
<sheet::XSpreadsheet
>::get(); }
91 virtual sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
{ return ( !mSheetMap
.empty() ); }
93 virtual uno::Any SAL_CALL
getByName( const OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
95 if ( !hasByName(aName
) )
96 throw container::NoSuchElementException();
97 return uno::makeAny( *cachePos
);
99 virtual uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
101 uno::Sequence
< OUString
> sNames( mSheetMap
.size() );
102 OUString
* pString
= sNames
.getArray();
103 SheetMap::iterator it
= mSheetMap
.begin();
104 SheetMap::iterator it_end
= mSheetMap
.end();
106 for ( ; it
!= it_end
; ++it
, ++pString
)
108 uno::Reference
< container::XNamed
> xName( *it
, uno::UNO_QUERY_THROW
);
109 *pString
= xName
->getName();
113 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
115 cachePos
= mSheetMap
.begin();
116 SheetMap::iterator it_end
= mSheetMap
.end();
117 for ( ; cachePos
!= it_end
; ++cachePos
)
119 uno::Reference
< container::XNamed
> xName( *cachePos
, uno::UNO_QUERY_THROW
);
120 if ( aName
.equals( xName
->getName() ) )
123 return ( cachePos
!= it_end
);
127 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
{ return mSheetMap
.size(); }
128 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
130 if ( Index
< 0 || Index
>= getCount() )
131 throw lang::IndexOutOfBoundsException();
133 return uno::makeAny( mSheetMap
[ Index
] );
136 // XEnumerationAccess
137 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
createEnumeration( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
139 return new WorkSheetsEnumeration( mSheetMap
);
143 class SheetsEnumeration
: public EnumerationHelperImpl
145 uno::Reference
< frame::XModel
> m_xModel
;
147 SheetsEnumeration( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, const uno::Reference
< container::XEnumeration
>& xEnumeration
, const uno::Reference
< frame::XModel
>& xModel
) throw ( uno::RuntimeException
) : EnumerationHelperImpl( xParent
, xContext
, xEnumeration
), m_xModel( xModel
) {}
149 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
151 uno::Reference
< sheet::XSpreadsheet
> xSheet( m_xEnumeration
->nextElement(), uno::UNO_QUERY_THROW
);
152 uno::Reference
< XHelperInterface
> xIf
= excel::getUnoSheetModuleObj( xSheet
);
156 // if the Sheet is in a document created by the api unfortunately ( at the
157 // moment, it actually wont have the special Document modules
158 uno::Reference
< excel::XWorksheet
> xNewSheet( new ScVbaWorksheet( m_xParent
, m_xContext
, xSheet
, m_xModel
) );
168 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< ::com::sun::star::uno::XComponentContext
> & xContext
, const uno::Reference
< container::XIndexAccess
>& xSheets
, const uno::Reference
< frame::XModel
>& xModel
): ScVbaWorksheets_BASE( xParent
, xContext
, xSheets
), mxModel( xModel
), m_xSheets( uno::Reference
< sheet::XSpreadsheets
>( xSheets
, uno::UNO_QUERY
) )
172 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< ::com::sun::star::uno::XComponentContext
> & xContext
, const uno::Reference
< container::XEnumerationAccess
>& xEnumAccess
, const uno::Reference
< frame::XModel
>& xModel
): ScVbaWorksheets_BASE( xParent
, xContext
, uno::Reference
< container::XIndexAccess
>( xEnumAccess
, uno::UNO_QUERY
) ), mxModel(xModel
)
176 // XEnumerationAccess
178 ScVbaWorksheets::getElementType() throw (uno::RuntimeException
)
180 return cppu::UnoType
<excel::XWorksheet
>::get();
183 uno::Reference
< container::XEnumeration
>
184 ScVbaWorksheets::createEnumeration() throw (uno::RuntimeException
)
186 if ( !m_xSheets
.is() )
188 uno::Reference
< container::XEnumerationAccess
> xAccess( m_xIndexAccess
, uno::UNO_QUERY_THROW
);
189 return xAccess
->createEnumeration();
191 uno::Reference
< container::XEnumerationAccess
> xEnumAccess( m_xSheets
, uno::UNO_QUERY_THROW
);
192 return new SheetsEnumeration( this, mxContext
, xEnumAccess
->createEnumeration(), mxModel
);
196 ScVbaWorksheets::createCollectionObject( const uno::Any
& aSource
)
198 uno::Reference
< sheet::XSpreadsheet
> xSheet( aSource
, uno::UNO_QUERY
);
199 uno::Reference
< XHelperInterface
> xIf
= excel::getUnoSheetModuleObj( xSheet
);
203 // if the Sheet is in a document created by the api unfortunately ( at the
204 // moment, it actually wont have the special Document modules
205 uno::Reference
< excel::XWorksheet
> xNewSheet( new ScVbaWorksheet( getParent(), mxContext
, xSheet
, mxModel
) );
215 ScVbaWorksheets::Add( const uno::Any
& Before
, const uno::Any
& After
,
216 const uno::Any
& Count
, const uno::Any
& Type
) throw (uno::RuntimeException
, std::exception
)
218 if ( isSelectedSheets() )
219 return uno::Any(); // or should we throw?
221 OUString aStringSheet
;
223 SCTAB nSheetIndex
= 0;
224 SCTAB nNewSheets
= 1, nType
= 0;
225 Count
>>= nNewSheets
;
229 uno::Reference
< excel::XWorksheet
> xBeforeAfterSheet
;
231 if ( Before
.hasValue() )
233 if ( Before
>>= xBeforeAfterSheet
)
234 aStringSheet
= xBeforeAfterSheet
->getName();
236 Before
>>= aStringSheet
;
239 if (aStringSheet
.isEmpty() && After
.hasValue() )
241 if ( After
>>= xBeforeAfterSheet
)
242 aStringSheet
= xBeforeAfterSheet
->getName();
244 After
>>= aStringSheet
;
247 if (aStringSheet
.isEmpty())
249 uno::Reference
< excel::XApplication
> xApplication( Application(), uno::UNO_QUERY_THROW
);
250 aStringSheet
= xApplication
->getActiveWorkbook()->getActiveSheet()->getName();
253 nCount
= static_cast< SCTAB
>( m_xIndexAccess
->getCount() );
254 for (SCTAB i
=0; i
< nCount
; i
++)
256 uno::Reference
< sheet::XSpreadsheet
> xSheet(m_xIndexAccess
->getByIndex(i
), uno::UNO_QUERY
);
257 uno::Reference
< container::XNamed
> xNamed( xSheet
, uno::UNO_QUERY_THROW
);
258 if (xNamed
->getName() == aStringSheet
)
268 SCTAB nSheetName
= nCount
+ 1L;
269 OUString
aStringBase( "Sheet" );
271 for (SCTAB i
=0; i
< nNewSheets
; i
++, nSheetName
++)
273 OUString aStringName
= aStringBase
+ OUString::number(nSheetName
);
274 while (m_xNameAccess
->hasByName(aStringName
))
277 aStringName
= aStringBase
+ OUString::number(nSheetName
);
279 m_xSheets
->insertNewByName(aStringName
, nSheetIndex
+ i
);
280 result
= getItemByStringIndex( aStringName
);
282 uno::Reference
< excel::XWorksheet
> xNewSheet( result
, uno::UNO_QUERY
);
283 if ( xNewSheet
.is() )
284 xNewSheet
->Activate();
289 ScVbaWorksheets::Delete() throw (uno::RuntimeException
, std::exception
)
291 // #TODO #INVESTIGATE
292 // mmm this method could be trouble if the underlying
293 // uno objects ( the m_xIndexAccess etc ) aren't aware of the
294 // contents that are deleted
295 sal_Int32 nElems
= getCount();
296 for ( sal_Int32 nItem
= 1; nItem
<= nElems
; ++nItem
)
298 uno::Reference
< excel::XWorksheet
> xSheet( Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
304 ScVbaWorksheets::isSelectedSheets()
306 return !m_xSheets
.is();
310 ScVbaWorksheets::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
)
314 sal_Int16 nCopies
= 1;
315 bool bCollate
= false;
316 bool bSelection
= false;
320 if ( nCopies
> 1 ) // Collate only useful when more that 1 copy
321 Collate
>>= bCollate
;
323 if ( !( nFrom
|| nTo
) )
324 if ( isSelectedSheets() )
327 PrintOutHelper( excel::getBestViewShell( mxModel
), From
, To
, Copies
, Preview
, ActivePrinter
, PrintToFile
, Collate
, PrToFileName
, bSelection
);
331 ScVbaWorksheets::getVisible() throw (uno::RuntimeException
, std::exception
)
333 bool bVisible
= true;
334 uno::Reference
< container::XEnumeration
> xEnum( createEnumeration(), uno::UNO_QUERY_THROW
);
335 while ( xEnum
->hasMoreElements() )
337 uno::Reference
< excel::XWorksheet
> xSheet( xEnum
->nextElement(), uno::UNO_QUERY_THROW
);
338 if ( xSheet
->getVisible() == 0 )
344 return uno::makeAny( bVisible
);
348 ScVbaWorksheets::setVisible( const uno::Any
& _visible
) throw (uno::RuntimeException
, std::exception
)
351 if ( _visible
>>= bState
)
353 uno::Reference
< container::XEnumeration
> xEnum( createEnumeration(), uno::UNO_QUERY_THROW
);
354 while ( xEnum
->hasMoreElements() )
356 uno::Reference
< excel::XWorksheet
> xSheet( xEnum
->nextElement(), uno::UNO_QUERY_THROW
);
357 xSheet
->setVisible( bState
? 1 : 0 );
361 throw uno::RuntimeException("Visible property doesn't support non boolean #FIXME" );
365 ScVbaWorksheets::Select( const uno::Any
& Replace
) throw (uno::RuntimeException
, std::exception
)
367 ScTabViewShell
* pViewShell
= excel::getBestViewShell( mxModel
);
369 throw uno::RuntimeException("Cannot obtain view shell" );
371 ScMarkData
& rMarkData
= pViewShell
->GetViewData().GetMarkData();
372 bool bReplace
= true;
373 Replace
>>= bReplace
;
374 // Replace is defaulted to True, meanining this current collection
375 // becomes the Selection, if it were false then the current selection would
377 bool bSelectSingle
= bReplace
;
378 sal_Int32 nElems
= getCount();
379 for ( sal_Int32 nItem
= 1; nItem
<= nElems
; ++nItem
)
381 uno::Reference
< excel::XWorksheet
> xSheet( Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
382 ScVbaWorksheet
* pSheet
= excel::getImplFromDocModuleWrapper
<ScVbaWorksheet
>( xSheet
);
385 rMarkData
.SelectOneTable( static_cast< SCTAB
>( pSheet
->getSheetID() ) );
386 bSelectSingle
= false;
389 rMarkData
.SelectTable( static_cast< SCTAB
>( pSheet
->getSheetID() ), true );
395 ScVbaWorksheets::Copy ( const uno::Any
& Before
, const uno::Any
& After
) throw (css::uno::RuntimeException
, std::exception
)
397 uno::Reference
<excel::XWorksheet
> xSheet
;
398 sal_Int32 nElems
= getCount();
399 bool bAfter
= After
.hasValue();
400 std::vector
< uno::Reference
< excel::XWorksheet
> > Sheets
;
403 for ( nItem
= 1; nItem
<= nElems
; ++nItem
)
405 uno::Reference
<excel::XWorksheet
> xWorksheet(Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
406 Sheets
.push_back(xWorksheet
);
408 bool bNewDoc
= (!(Before
>>= xSheet
) && !(After
>>=xSheet
)&& !(Before
.hasValue()) && !(After
.hasValue()));
410 uno::Reference
< excel::XWorksheet
> xSrcSheet
;
414 xSrcSheet
= Sheets
.at(0);
415 ScVbaWorksheet
* pSrcSheet
= excel::getImplFromDocModuleWrapper
<ScVbaWorksheet
>( xSrcSheet
);
416 xSheet
= pSrcSheet
->createSheetCopyInNewDoc(xSrcSheet
->getName());
424 for (; nItem
< nElems
; ++nItem
)
426 xSrcSheet
= Sheets
[nItem
];
427 ScVbaWorksheet
* pSrcSheet
= excel::getImplFromDocModuleWrapper
<ScVbaWorksheet
>( xSrcSheet
);
429 xSheet
= pSrcSheet
->createSheetCopy(xSheet
, bAfter
);
431 pSrcSheet
->createSheetCopy(xSheet
, bAfter
);
435 //ScVbaCollectionBaseImpl
437 ScVbaWorksheets::Item(const uno::Any
& Index
, const uno::Any
& Index2
)
438 throw (lang::IndexOutOfBoundsException
, script::BasicErrorException
, uno::RuntimeException
)
440 if ( Index
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
442 uno::Reference
< script::XTypeConverter
> xConverter
= getTypeConverter(mxContext
);
444 aConverted
= xConverter
->convertTo( Index
, cppu::UnoType
<uno::Sequence
< uno::Any
>>::get() );
446 uno::Sequence
< uno::Any
> sIndices
;
447 aConverted
>>= sIndices
;
448 sal_Int32 nElems
= sIndices
.getLength();
449 for( sal_Int32 index
= 0; index
< nElems
; ++index
)
451 uno::Reference
< excel::XWorksheet
> xWorkSheet( ScVbaWorksheets_BASE::Item( sIndices
[ index
], Index2
), uno::UNO_QUERY_THROW
);
452 ScVbaWorksheet
* pWorkSheet
= excel::getImplFromDocModuleWrapper
<ScVbaWorksheet
>( xWorkSheet
);
453 uno::Reference
< sheet::XSpreadsheet
> xSheet( pWorkSheet
->getSheet() , uno::UNO_QUERY_THROW
);
454 uno::Reference
< container::XNamed
> xName( xSheet
, uno::UNO_QUERY_THROW
);
455 mSheets
.push_back( xSheet
);
457 uno::Reference
< container::XIndexAccess
> xIndexAccess
= new SheetCollectionHelper( mSheets
);
458 uno::Reference
< XCollection
> xSelectedSheets( new ScVbaWorksheets( this->getParent(), mxContext
, xIndexAccess
, mxModel
) );
459 return uno::makeAny( xSelectedSheets
);
461 return ScVbaWorksheets_BASE::Item( Index
, Index2
);
465 ScVbaWorksheets::getItemByStringIndex( const OUString
& sIndex
) throw (uno::RuntimeException
)
467 return ScVbaWorksheets_BASE::getItemByStringIndex( sIndex
);
471 ScVbaWorksheets::getServiceImplName()
473 return OUString("ScVbaWorksheets");
476 css::uno::Sequence
<OUString
>
477 ScVbaWorksheets::getServiceNames()
479 static uno::Sequence
< OUString
> sNames
;
480 if ( sNames
.getLength() == 0 )
483 sNames
[0] = "ooo.vba.excel.Worksheets";
488 bool ScVbaWorksheets::nameExists( uno::Reference
<sheet::XSpreadsheetDocument
>& xSpreadDoc
, const OUString
& name
, SCTAB
& nTab
) throw ( lang::IllegalArgumentException
, uno::RuntimeException
)
490 if (!xSpreadDoc
.is())
491 throw lang::IllegalArgumentException( "nameExists() xSpreadDoc is null", uno::Reference
< uno::XInterface
>(), 1 );
492 uno::Reference
<container::XIndexAccess
> xIndex( xSpreadDoc
->getSheets(), uno::UNO_QUERY
);
495 SCTAB nCount
= static_cast< SCTAB
>( xIndex
->getCount() );
496 for (SCTAB i
=0; i
< nCount
; i
++)
498 uno::Reference
< container::XNamed
> xNamed( xIndex
->getByIndex(i
), uno::UNO_QUERY_THROW
);
499 if (xNamed
->getName() == name
)
509 void ScVbaWorksheets::PrintPreview( const css::uno::Any
& /*EnableChanges*/ ) throw (css::uno::RuntimeException
, std::exception
)
511 // need test, print preview current active sheet
512 // !! TODO !! get view shell from controller
513 ScTabViewShell
* pViewShell
= excel::getBestViewShell( mxModel
);
514 SfxViewFrame
* pViewFrame
= NULL
;
516 pViewFrame
= pViewShell
->GetViewFrame();
519 if ( !pViewFrame
->GetFrame().IsInPlace() )
521 dispatchExecute( pViewShell
, SID_VIEWSHELL1
);
522 SfxViewShell
* pShell
= SfxViewShell::Get( pViewFrame
->GetFrame().GetFrameInterface()->getController() );
524 if ( pShell
->ISA( ScPreviewShell
) )
526 ScPreviewShell
* pPrvShell
= static_cast< ScPreviewShell
* >( pShell
);
527 ScPreview
* pPrvView
= pPrvShell
->GetPreview();
528 ScMarkData aMarkData
;
529 sal_Int32 nElems
= getCount();
530 for ( sal_Int32 nItem
= 1; nItem
<= nElems
; ++nItem
)
532 uno::Reference
< excel::XWorksheet
> xSheet( Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
533 ScVbaWorksheet
* pSheet
= excel::getImplFromDocModuleWrapper
<ScVbaWorksheet
>( xSheet
);
535 aMarkData
.SelectTable(static_cast< SCTAB
>( pSheet
->getSheetID() ), true );
537 // save old selection, setting the selectedtabs in the preview
538 // can affect the current selection when preview has been
540 ScMarkData::MarkedTabsType aOldTabs
= pPrvView
->GetSelectedTabs();
541 pPrvView
->SetSelectedTabs( aMarkData
);
543 pPrvView
->DataChanged();
544 // set sensible first page
545 long nPage
= pPrvView
->GetFirstPage( 1 );
546 pPrvView
->SetPageNo( nPage
);
547 WaitUntilPreviewIsClosed( pViewFrame
);
548 // restore old tab selection
549 pViewShell
= excel::getBestViewShell( mxModel
);
550 pViewShell
->GetViewData().GetMarkData().SetSelectedTabs(aOldTabs
);
557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */