1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vbaworksheets.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 #include "vbaworksheets.hxx"
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/app.hxx>
34 #include <sfx2/bindings.hxx>
35 #include <sfx2/request.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/itemwrapper.hxx>
38 #include <svtools/itemset.hxx>
39 #include <svtools/eitem.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <cppuhelper/implbase3.hxx>
44 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
45 #include <com/sun/star/container/XEnumerationAccess.hpp>
46 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
47 #include <com/sun/star/container/XNamed.hpp>
48 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <ooo/vba/excel/XApplication.hpp>
52 #include <tools/string.hxx>
53 #include "tabvwsh.hxx"
55 #include "vbaglobals.hxx"
56 #include "vbaworksheet.hxx"
57 #include "vbaworkbook.hxx"
59 using namespace ::ooo::vba
;
60 using namespace ::com::sun::star
;
63 typedef ::cppu::WeakImplHelper1
< container::XEnumeration
> SheetEnumeration_BASE
;
64 typedef ::cppu::WeakImplHelper3
< container::XNameAccess
, container::XIndexAccess
, container::XEnumerationAccess
> SheetCollectionHelper_BASE
;
65 // a map ( or hashmap ) wont do as we need also to preserve the order
66 // (as added ) of the items
67 typedef std::vector
< uno::Reference
< sheet::XSpreadsheet
> > SheetMap
;
69 class WorkSheetsEnumeration
: public SheetEnumeration_BASE
72 SheetMap::iterator mIt
;
74 WorkSheetsEnumeration( const SheetMap
& sMap
) : mSheetMap( sMap
), mIt( mSheetMap
.begin() ) {}
75 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (uno::RuntimeException
)
77 return ( mIt
!= mSheetMap
.end() );
79 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
81 if ( !hasMoreElements() )
82 throw container::NoSuchElementException();
83 uno::Reference
< sheet::XSpreadsheet
> xSheet( *mIt
++ );
84 return uno::makeAny( xSheet
) ;
88 class SheetCollectionHelper
: public SheetCollectionHelper_BASE
91 SheetMap::iterator cachePos
;
93 SheetCollectionHelper( const SheetMap
& sMap
) : mSheetMap( sMap
), cachePos(mSheetMap
.begin()) {}
95 virtual uno::Type SAL_CALL
getElementType( ) throw (uno::RuntimeException
) { return sheet::XSpreadsheet::static_type(0); }
96 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (uno::RuntimeException
) { return ( mSheetMap
.size() > 0 ); }
98 virtual uno::Any SAL_CALL
getByName( const ::rtl::OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
100 if ( !hasByName(aName
) )
101 throw container::NoSuchElementException();
102 return uno::makeAny( *cachePos
);
104 virtual uno::Sequence
< ::rtl::OUString
> SAL_CALL
getElementNames( ) throw (uno::RuntimeException
)
106 uno::Sequence
< rtl::OUString
> sNames( mSheetMap
.size() );
107 rtl::OUString
* pString
= sNames
.getArray();
108 SheetMap::iterator it
= mSheetMap
.begin();
109 SheetMap::iterator it_end
= mSheetMap
.end();
111 for ( ; it
!= it_end
; ++it
, ++pString
)
113 uno::Reference
< container::XNamed
> xName( *it
, uno::UNO_QUERY_THROW
);
114 *pString
= xName
->getName();
118 virtual ::sal_Bool SAL_CALL
hasByName( const ::rtl::OUString
& aName
) throw (uno::RuntimeException
)
120 cachePos
= mSheetMap
.begin();
121 SheetMap::iterator it_end
= mSheetMap
.end();
122 for ( ; cachePos
!= it_end
; ++cachePos
)
124 uno::Reference
< container::XNamed
> xName( *cachePos
, uno::UNO_QUERY_THROW
);
125 if ( aName
.equals( xName
->getName() ) )
128 return ( cachePos
!= it_end
);
132 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (uno::RuntimeException
) { return mSheetMap
.size(); }
133 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
)
135 if ( Index
< 0 || Index
>= getCount() )
136 throw lang::IndexOutOfBoundsException();
138 return uno::makeAny( mSheetMap
[ Index
] );
141 // XEnumerationAccess
142 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
createEnumeration( ) throw (uno::RuntimeException
)
144 return new WorkSheetsEnumeration( mSheetMap
);
148 class SheetsEnumeration
: public EnumerationHelperImpl
150 uno::Reference
< frame::XModel
> m_xModel
;
151 uno::WeakReference
< XHelperInterface
> m_xParent
;
153 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( xContext
, xEnumeration
), m_xModel( xModel
), m_xParent( xParent
) {}
155 virtual uno::Any SAL_CALL
nextElement( ) throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
157 uno::Reference
< sheet::XSpreadsheet
> xSheet( m_xEnumeration
->nextElement(), uno::UNO_QUERY_THROW
);
158 return uno::makeAny( uno::Reference
< excel::XWorksheet
> ( new ScVbaWorksheet( m_xParent
, m_xContext
, xSheet
, m_xModel
) ) );
163 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
) )
167 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
)
171 // XEnumerationAccess
173 ScVbaWorksheets::getElementType() throw (uno::RuntimeException
)
175 return excel::XWorksheet::static_type(0);
178 uno::Reference
< container::XEnumeration
>
179 ScVbaWorksheets::createEnumeration() throw (uno::RuntimeException
)
181 if ( !m_xSheets
.is() )
183 uno::Reference
< container::XEnumerationAccess
> xAccess( m_xIndexAccess
, uno::UNO_QUERY_THROW
);
184 return xAccess
->createEnumeration();
186 uno::Reference
< container::XEnumerationAccess
> xEnumAccess( m_xSheets
, uno::UNO_QUERY_THROW
);
187 return new SheetsEnumeration( this, mxContext
, xEnumAccess
->createEnumeration(), mxModel
);
191 ScVbaWorksheets::createCollectionObject( const uno::Any
& aSource
)
193 uno::Reference
< sheet::XSpreadsheet
> xSheet( aSource
, uno::UNO_QUERY
);
194 return uno::makeAny( uno::Reference
< excel::XWorksheet
> ( new ScVbaWorksheet( getParent(), mxContext
, xSheet
, mxModel
) ) );
199 ScVbaWorksheets::Add( const uno::Any
& Before
, const uno::Any
& After
,
200 const uno::Any
& Count
, const uno::Any
& Type
) throw (uno::RuntimeException
)
202 if ( isSelectedSheets() )
203 return uno::Any(); // or should we throw?
205 rtl::OUString aStringSheet
;
206 sal_Bool
bBefore(sal_True
);
207 SCTAB nSheetIndex
= 0;
208 SCTAB nNewSheets
= 1, nType
= 0;
209 Count
>>= nNewSheets
;
213 uno::Reference
< excel::XWorksheet
> xBeforeAfterSheet
;
215 if ( Before
.hasValue() )
217 if ( Before
>>= xBeforeAfterSheet
)
218 aStringSheet
= xBeforeAfterSheet
->getName();
220 Before
>>= aStringSheet
;
223 if (!aStringSheet
.getLength() && After
.hasValue() )
225 if ( After
>>= xBeforeAfterSheet
)
226 aStringSheet
= xBeforeAfterSheet
->getName();
228 After
>>= aStringSheet
;
231 if (!aStringSheet
.getLength())
233 uno::Reference
< excel::XApplication
> xApplication( Application(), uno::UNO_QUERY_THROW
);
234 aStringSheet
= xApplication
->getActiveWorkbook()->getActiveSheet()->getName();
237 nCount
= static_cast< SCTAB
>( m_xIndexAccess
->getCount() );
238 for (SCTAB i
=0; i
< nCount
; i
++)
240 uno::Reference
< sheet::XSpreadsheet
> xSheet(m_xIndexAccess
->getByIndex(i
), uno::UNO_QUERY
);
241 uno::Reference
< container::XNamed
> xNamed( xSheet
, uno::UNO_QUERY_THROW
);
242 if (xNamed
->getName() == aStringSheet
)
252 SCTAB nSheetName
= nCount
+ 1L;
253 String
aStringBase( RTL_CONSTASCII_USTRINGPARAM("Sheet") );
255 for (SCTAB i
=0; i
< nNewSheets
; i
++, nSheetName
++)
257 String aStringName
= aStringBase
;
258 aStringName
+= String::CreateFromInt32(nSheetName
);
259 while (m_xNameAccess
->hasByName(aStringName
))
262 aStringName
= aStringBase
;
263 aStringName
+= String::CreateFromInt32(nSheetName
);
265 m_xSheets
->insertNewByName(aStringName
, nSheetIndex
+ i
);
266 result
= getItemByStringIndex( aStringName
);
268 uno::Reference
< excel::XWorksheet
> xNewSheet( result
, uno::UNO_QUERY
);
269 if ( xNewSheet
.is() )
270 xNewSheet
->Activate();
275 ScVbaWorksheets::Delete() throw (uno::RuntimeException
)
277 // #TODO #INVESTIGATE
278 // mmm this method could be trouble if the underlying
279 // uno objects ( the m_xIndexAccess etc ) aren't aware of the
280 // contents that are deleted
281 sal_Int32 nElems
= getCount();
282 for ( sal_Int32 nItem
= 1; nItem
<= nElems
; ++nItem
)
284 uno::Reference
< excel::XWorksheet
> xSheet( Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
290 ScVbaWorksheets::isSelectedSheets()
292 return !m_xSheets
.is();
296 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
)
300 sal_Int16 nCopies
= 1;
301 sal_Bool bCollate
= sal_False
;
302 sal_Bool bSelection
= sal_False
;
306 if ( nCopies
> 1 ) // Collate only useful when more that 1 copy
307 Collate
>>= bCollate
;
309 if ( !( nFrom
|| nTo
) )
310 if ( isSelectedSheets() )
311 bSelection
= sal_True
;
313 PrintOutHelper( excel::getBestViewShell( mxModel
), From
, To
, Copies
, Preview
, ActivePrinter
, PrintToFile
, Collate
, PrToFileName
, bSelection
);
317 ScVbaWorksheets::getVisible() throw (uno::RuntimeException
)
319 sal_Bool bVisible
= sal_True
;
320 uno::Reference
< container::XEnumeration
> xEnum( createEnumeration(), uno::UNO_QUERY_THROW
);
321 while ( xEnum
->hasMoreElements() )
323 uno::Reference
< excel::XWorksheet
> xSheet( xEnum
->nextElement(), uno::UNO_QUERY_THROW
);
324 if ( xSheet
->getVisible() == sal_False
)
326 bVisible
= sal_False
;
330 return uno::makeAny( bVisible
);
334 ScVbaWorksheets::setVisible( const uno::Any
& _visible
) throw (uno::RuntimeException
)
336 sal_Bool bState
= sal_False
;
337 if ( _visible
>>= bState
)
339 uno::Reference
< container::XEnumeration
> xEnum( createEnumeration(), uno::UNO_QUERY_THROW
);
340 while ( xEnum
->hasMoreElements() )
342 uno::Reference
< excel::XWorksheet
> xSheet( xEnum
->nextElement(), uno::UNO_QUERY_THROW
);
343 xSheet
->setVisible( bState
);
347 throw uno::RuntimeException( rtl::OUString(
348 RTL_CONSTASCII_USTRINGPARAM( "Visible property doesn't support non boolean #FIXME" ) ), uno::Reference
< uno::XInterface
>() );
352 ScVbaWorksheets::Select( const uno::Any
& Replace
) throw (uno::RuntimeException
)
354 ScTabViewShell
* pViewShell
= excel::getBestViewShell( mxModel
);
356 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot obtain view shell" ) ), uno::Reference
< uno::XInterface
>() );
358 ScMarkData
& rMarkData
= pViewShell
->GetViewData()->GetMarkData();
359 sal_Bool bReplace
= sal_True
;
360 Replace
>>= bReplace
;
361 // Replace is defaulted to True, meanining this current collection
362 // becomes the Selection, if it were false then the current selection would
364 bool bSelectSingle
= bReplace
;
365 sal_Int32 nElems
= getCount();
366 for ( sal_Int32 nItem
= 1; nItem
<= nElems
; ++nItem
)
368 uno::Reference
< excel::XWorksheet
> xSheet( Item( uno::makeAny( nItem
), uno::Any() ), uno::UNO_QUERY_THROW
);
369 ScVbaWorksheet
* pSheet
= dynamic_cast< ScVbaWorksheet
* >( xSheet
.get() );
374 rMarkData
.SelectOneTable( static_cast< SCTAB
>( pSheet
->getSheetID() ) );
375 bSelectSingle
= false;
378 rMarkData
.SelectTable( static_cast< SCTAB
>( pSheet
->getSheetID() ), TRUE
);
386 //ScVbaCollectionBaseImpl
388 ScVbaWorksheets::Item( const uno::Any
& Index
, const uno::Any
& Index2
) throw (uno::RuntimeException
)
390 if ( Index
.getValueTypeClass() == uno::TypeClass_SEQUENCE
)
392 uno::Reference
< script::XTypeConverter
> xConverter
= getTypeConverter(mxContext
);
394 aConverted
= xConverter
->convertTo( Index
, getCppuType((uno::Sequence
< uno::Any
>*)0) );
396 uno::Sequence
< uno::Any
> sIndices
;
397 aConverted
>>= sIndices
;
398 sal_Int32 nElems
= sIndices
.getLength();
399 for( sal_Int32 index
= 0; index
< nElems
; ++index
)
401 uno::Reference
< excel::XWorksheet
> xWorkSheet( ScVbaWorksheets_BASE::Item( sIndices
[ index
], Index2
), uno::UNO_QUERY_THROW
);
402 ScVbaWorksheet
* pWorkSheet
= dynamic_cast< ScVbaWorksheet
* >( xWorkSheet
.get() );
405 uno::Reference
< sheet::XSpreadsheet
> xSheet( pWorkSheet
->getSheet() , uno::UNO_QUERY_THROW
);
406 uno::Reference
< container::XNamed
> xName( xSheet
, uno::UNO_QUERY_THROW
);
407 mSheets
.push_back( xSheet
);
410 uno::Reference
< container::XIndexAccess
> xIndexAccess
= new SheetCollectionHelper( mSheets
);
411 uno::Reference
< XCollection
> xSelectedSheets( new ScVbaWorksheets( this->getParent(), mxContext
, xIndexAccess
, mxModel
) );
412 return uno::makeAny( xSelectedSheets
);
414 return ScVbaWorksheets_BASE::Item( Index
, Index2
);
418 ScVbaWorksheets::getItemByStringIndex( const rtl::OUString
& sIndex
) throw (uno::RuntimeException
)
420 return ScVbaWorksheets_BASE::getItemByStringIndex( sIndex
);
424 ScVbaWorksheets::getServiceImplName()
426 static rtl::OUString
sImplName( RTL_CONSTASCII_USTRINGPARAM("ScVbaWorksheets") );
430 css::uno::Sequence
<rtl::OUString
>
431 ScVbaWorksheets::getServiceNames()
433 static uno::Sequence
< rtl::OUString
> sNames
;
434 if ( sNames
.getLength() == 0 )
437 sNames
[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.excel.Worksheets") );