tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / vba / vbaworksheets.cxx
blob361f9e03cff7fbc5d698f0d7922c72d80c46144a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/viewfrm.hxx>
23 #include <cppuhelper/implbase.hxx>
25 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
26 #include <com/sun/star/container/XEnumerationAccess.hpp>
27 #include <com/sun/star/sheet/XSpreadsheet.hpp>
28 #include <com/sun/star/container/XNamed.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <com/sun/star/script/XTypeConverter.hpp>
32 #include <ooo/vba/excel/XApplication.hpp>
33 #include <tabvwsh.hxx>
35 #include "excelvbahelper.hxx"
36 #include "vbaworksheet.hxx"
37 #include <markdata.hxx>
39 #include <utility>
40 #include <vector>
41 #include <prevwsh.hxx>
42 #include <preview.hxx>
43 using namespace ::ooo::vba;
44 using namespace ::com::sun::star;
46 // a map ( or hashmap ) won't do as we need also to preserve the order
47 // (as added ) of the items
48 typedef std::vector< uno::Reference< sheet::XSpreadsheet > > SheetMap;
50 // #FIXME #TODO the implementation of the Sheets collections sucks,
51 // e.g. there is no support for tracking sheets added/removed from the collection
53 namespace {
55 class WorkSheetsEnumeration : public ::cppu::WeakImplHelper< container::XEnumeration >
57 SheetMap mSheetMap;
58 SheetMap::iterator mIt;
59 public:
60 explicit WorkSheetsEnumeration( SheetMap&& sMap ) : mSheetMap( std::move(sMap) ), mIt( mSheetMap.begin() ) {}
61 virtual sal_Bool SAL_CALL hasMoreElements( ) override
63 return ( mIt != mSheetMap.end() );
65 virtual uno::Any SAL_CALL nextElement( ) override
67 if ( !hasMoreElements() )
68 throw container::NoSuchElementException();
69 uno::Reference< sheet::XSpreadsheet > xSheet( *mIt++ );
70 return uno::Any( xSheet ) ;
74 class SheetCollectionHelper : public ::cppu::WeakImplHelper< container::XNameAccess,
75 container::XIndexAccess,
76 container::XEnumerationAccess >
78 SheetMap mSheetMap;
79 SheetMap::iterator cachePos;
80 public:
81 explicit SheetCollectionHelper( SheetMap&& sMap ) : mSheetMap( std::move(sMap) ), cachePos(mSheetMap.begin()) {}
82 // XElementAccess
83 virtual uno::Type SAL_CALL getElementType( ) override { return cppu::UnoType<sheet::XSpreadsheet>::get(); }
84 virtual sal_Bool SAL_CALL hasElements( ) override { return ( !mSheetMap.empty() ); }
85 // XNameAccess
86 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
88 if ( !hasByName(aName) )
89 throw container::NoSuchElementException();
90 return uno::Any( *cachePos );
92 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
94 uno::Sequence< OUString > sNames( mSheetMap.size() );
95 OUString* pString = sNames.getArray();
97 for ( const auto& rItem : mSheetMap )
99 uno::Reference< container::XNamed > xName( rItem, uno::UNO_QUERY_THROW );
100 *pString = xName->getName();
101 ++pString;
103 return sNames;
105 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
107 cachePos = mSheetMap.begin();
108 SheetMap::iterator it_end = mSheetMap.end();
109 for ( ; cachePos != it_end; ++cachePos )
111 uno::Reference< container::XNamed > xName( *cachePos, uno::UNO_QUERY_THROW );
112 if ( aName == xName->getName() )
113 break;
115 return ( cachePos != it_end );
118 // XElementAccess
119 virtual ::sal_Int32 SAL_CALL getCount( ) override { return mSheetMap.size(); }
120 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
122 if ( Index < 0 || Index >= getCount() )
123 throw lang::IndexOutOfBoundsException();
125 return uno::Any( mSheetMap[ Index ] );
128 // XEnumerationAccess
129 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
131 return new WorkSheetsEnumeration( std::vector(mSheetMap) );
135 class SheetsEnumeration : public EnumerationHelperImpl
137 uno::Reference< frame::XModel > m_xModel;
138 public:
139 /// @throws uno::RuntimeException
140 SheetsEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XEnumeration >& xEnumeration, uno::Reference< frame::XModel > xModel ) : EnumerationHelperImpl( xParent, xContext, xEnumeration ), m_xModel(std::move( xModel )) {}
142 virtual uno::Any SAL_CALL nextElement( ) override
144 uno::Reference< sheet::XSpreadsheet > xSheet( m_xEnumeration->nextElement(), uno::UNO_QUERY_THROW );
145 uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet );
146 uno::Any aRet;
147 if ( !xIf.is() )
149 // if the Sheet is in a document created by the api unfortunately ( at the
150 // moment, it actually won't have the special Document modules
151 uno::Reference< excel::XWorksheet > xNewSheet( new ScVbaWorksheet( m_xParent, m_xContext, xSheet, m_xModel ) );
152 aRet <<= xNewSheet;
154 else
155 aRet <<= xIf;
156 return aRet;
163 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext > & xContext, const uno::Reference< container::XIndexAccess >& xSheets, uno::Reference< frame::XModel > xModel ): ScVbaWorksheets_BASE( xParent, xContext, xSheets ), mxModel(std::move( xModel )), m_xSheets( uno::Reference< sheet::XSpreadsheets >( xSheets, uno::UNO_QUERY ) )
167 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext > & xContext, const uno::Reference< container::XEnumerationAccess >& xEnumAccess, uno::Reference< frame::XModel > xModel ): ScVbaWorksheets_BASE( xParent, xContext, uno::Reference< container::XIndexAccess >( xEnumAccess, uno::UNO_QUERY ) ), mxModel(std::move(xModel))
171 // XEnumerationAccess
172 uno::Type
173 ScVbaWorksheets::getElementType()
175 return cppu::UnoType<excel::XWorksheet>::get();
178 uno::Reference< container::XEnumeration >
179 ScVbaWorksheets::createEnumeration()
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 );
190 uno::Any
191 ScVbaWorksheets::createCollectionObject( const uno::Any& aSource )
193 uno::Reference< sheet::XSpreadsheet > xSheet( aSource, uno::UNO_QUERY );
194 uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet );
195 uno::Any aRet;
196 if ( !xIf.is() )
198 // if the Sheet is in a document created by the api unfortunately ( at the
199 // moment, it actually won't have the special Document modules
200 uno::Reference< excel::XWorksheet > xNewSheet( new ScVbaWorksheet( getParent(), mxContext, xSheet, mxModel ) );
201 aRet <<= xNewSheet;
203 else
204 aRet <<= xIf;
205 return aRet;
208 // XWorksheets
209 uno::Any
210 ScVbaWorksheets::Add( const uno::Any& Before, const uno::Any& After,
211 const uno::Any& Count, const uno::Any& Type )
213 if ( isSelectedSheets() )
214 return uno::Any(); // or should we throw?
216 OUString aStringSheet;
217 bool bBefore(true);
218 SCTAB nSheetIndex = 0;
219 SCTAB nNewSheets = 1, nType = 0;
220 Count >>= nNewSheets;
221 Type >>= nType;
222 SCTAB nCount = 0;
224 uno::Reference< excel::XWorksheet > xBeforeAfterSheet;
226 if ( Before.hasValue() )
228 if ( Before >>= xBeforeAfterSheet )
229 aStringSheet = xBeforeAfterSheet->getName();
230 else
231 Before >>= aStringSheet;
234 if (aStringSheet.isEmpty() && After.hasValue() )
236 if ( After >>= xBeforeAfterSheet )
237 aStringSheet = xBeforeAfterSheet->getName();
238 else
239 After >>= aStringSheet;
240 bBefore = false;
242 if (aStringSheet.isEmpty())
244 uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
245 aStringSheet = xApplication->getActiveWorkbook()->getActiveSheet()->getName();
246 bBefore = true;
248 nCount = static_cast< SCTAB >( m_xIndexAccess->getCount() );
249 for (SCTAB i=0; i < nCount; i++)
251 uno::Reference< sheet::XSpreadsheet > xSheet(m_xIndexAccess->getByIndex(i), uno::UNO_QUERY);
252 uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
253 if (xNamed->getName() == aStringSheet)
255 nSheetIndex = i;
256 break;
260 if(!bBefore)
261 nSheetIndex++;
263 SCTAB nSheetName = nCount + 1;
264 OUString aStringBase( u"Sheet"_ustr );
265 uno::Any result;
266 for (SCTAB i=0; i < nNewSheets; i++, nSheetName++)
268 OUString aStringName = aStringBase + OUString::number(nSheetName);
269 while (m_xNameAccess->hasByName(aStringName))
271 nSheetName++;
272 aStringName = aStringBase + OUString::number(nSheetName);
274 m_xSheets->insertNewByName(aStringName, nSheetIndex + i);
275 result = getItemByStringIndex( aStringName );
277 uno::Reference< excel::XWorksheet > xNewSheet( result, uno::UNO_QUERY );
278 if ( xNewSheet.is() )
279 xNewSheet->Activate();
280 return result;
283 void
284 ScVbaWorksheets::Delete()
286 // #TODO #INVESTIGATE
287 // mmm this method could be trouble if the underlying
288 // uno objects ( the m_xIndexAccess etc ) aren't aware of the
289 // contents that are deleted
290 sal_Int32 nElems = getCount();
291 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
293 uno::Reference< excel::XWorksheet > xSheet( Item( uno::Any( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
294 xSheet->Delete();
298 bool
299 ScVbaWorksheets::isSelectedSheets() const
301 return !m_xSheets.is();
304 void SAL_CALL
305 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 )
307 sal_Int32 nTo = 0;
308 sal_Int32 nFrom = 0;
309 bool bSelection = false;
310 From >>= nFrom;
311 To >>= nTo;
313 if ( !( nFrom || nTo ) )
314 if ( isSelectedSheets() )
315 bSelection = true;
317 PrintOutHelper( excel::getBestViewShell( mxModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, bSelection );
320 uno::Any SAL_CALL
321 ScVbaWorksheets::getVisible()
323 bool bVisible = true;
324 uno::Reference< container::XEnumeration > xEnum( createEnumeration(), uno::UNO_SET_THROW );
325 while ( xEnum->hasMoreElements() )
327 uno::Reference< excel::XWorksheet > xSheet( xEnum->nextElement(), uno::UNO_QUERY_THROW );
328 if ( xSheet->getVisible() == 0 )
330 bVisible = false;
331 break;
334 return uno::Any( bVisible );
337 void SAL_CALL
338 ScVbaWorksheets::setVisible( const uno::Any& _visible )
340 bool bState = false;
341 if ( !(_visible >>= bState) )
342 throw uno::RuntimeException(u"Visible property doesn't support non boolean #FIXME"_ustr );
344 uno::Reference< container::XEnumeration > xEnum( createEnumeration(), uno::UNO_SET_THROW );
345 while ( xEnum->hasMoreElements() )
347 uno::Reference< excel::XWorksheet > xSheet( xEnum->nextElement(), uno::UNO_QUERY_THROW );
348 xSheet->setVisible( bState ? 1 : 0 );
353 void SAL_CALL
354 ScVbaWorksheets::Select( const uno::Any& Replace )
356 ScTabViewShell* pViewShell = excel::getBestViewShell( mxModel );
357 if ( !pViewShell )
358 throw uno::RuntimeException(u"Cannot obtain view shell"_ustr );
360 ScMarkData& rMarkData = pViewShell->GetViewData().GetMarkData();
361 bool bReplace = true;
362 Replace >>= bReplace;
363 // Replace is defaulted to True, meaning this current collection
364 // becomes the Selection, if it were false then the current selection would
365 // be extended
366 bool bSelectSingle = bReplace;
367 sal_Int32 nElems = getCount();
368 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
370 uno::Reference< excel::XWorksheet > xSheet( Item( uno::Any( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
371 ScVbaWorksheet* pSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
372 if ( bSelectSingle )
374 rMarkData.SelectOneTable( static_cast< SCTAB >( pSheet->getSheetID() ) );
375 bSelectSingle = false;
377 else
378 rMarkData.SelectTable( static_cast< SCTAB >( pSheet->getSheetID() ), true );
383 void SAL_CALL
384 ScVbaWorksheets::Copy ( const uno::Any& Before, const uno::Any& After)
386 uno::Reference<excel::XWorksheet> xSheet;
387 sal_Int32 nElems = getCount();
388 bool bAfter = After.hasValue();
389 std::vector< uno::Reference< excel::XWorksheet > > Sheets;
390 sal_Int32 nItem = 0;
392 for ( nItem = 1; nItem <= nElems; ++nItem)
394 uno::Reference<excel::XWorksheet> xWorksheet(Item( uno::Any( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
395 Sheets.push_back(xWorksheet);
397 bool bNewDoc = (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()));
399 uno::Reference< excel::XWorksheet > xSrcSheet;
400 if ( bNewDoc )
402 bAfter = true;
403 xSrcSheet = Sheets.at(0);
404 ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
405 xSheet = pSrcSheet->createSheetCopyInNewDoc(xSrcSheet->getName());
406 nItem = 1;
408 else
410 nItem=0;
413 for (; nItem < nElems; ++nItem )
415 xSrcSheet = Sheets[nItem];
416 ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
417 if ( bAfter )
418 xSheet = pSrcSheet->createSheetCopy(xSheet, bAfter);
419 else
420 pSrcSheet->createSheetCopy(xSheet, bAfter);
424 //ScVbaCollectionBaseImpl
425 uno::Any SAL_CALL
426 ScVbaWorksheets::Item(const uno::Any& Index, const uno::Any& Index2)
428 if ( Index.getValueTypeClass() == uno::TypeClass_SEQUENCE )
430 const uno::Reference< script::XTypeConverter >& xConverter = getTypeConverter(mxContext);
431 uno::Any aConverted = xConverter->convertTo( Index, cppu::UnoType<uno::Sequence< uno::Any >>::get() );
432 SheetMap aSheets;
433 uno::Sequence< uno::Any > sIndices;
434 aConverted >>= sIndices;
435 for (const auto& rIndex : sIndices)
437 uno::Reference< excel::XWorksheet > xWorkSheet( ScVbaWorksheets_BASE::Item( rIndex, Index2 ), uno::UNO_QUERY_THROW );
438 ScVbaWorksheet* pWorkSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xWorkSheet );
439 uno::Reference< sheet::XSpreadsheet > xSheet( pWorkSheet->getSheet() , uno::UNO_SET_THROW );
440 uno::Reference< container::XNamed > xName( xSheet, uno::UNO_QUERY_THROW );
441 aSheets.push_back( xSheet );
443 uno::Reference< container::XIndexAccess > xIndexAccess = new SheetCollectionHelper( std::move(aSheets) );
444 uno::Reference< XCollection > xSelectedSheets( new ScVbaWorksheets( getParent(), mxContext, xIndexAccess, mxModel ) );
445 return uno::Any( xSelectedSheets );
447 return ScVbaWorksheets_BASE::Item( Index, Index2 );
450 OUString
451 ScVbaWorksheets::getServiceImplName()
453 return u"ScVbaWorksheets"_ustr;
456 css::uno::Sequence<OUString>
457 ScVbaWorksheets::getServiceNames()
459 static uno::Sequence< OUString > const sNames
461 u"ooo.vba.excel.Worksheets"_ustr
463 return sNames;
466 bool ScVbaWorksheets::nameExists( const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, std::u16string_view name, SCTAB& nTab )
468 if (!xSpreadDoc.is())
469 throw lang::IllegalArgumentException( u"nameExists() xSpreadDoc is null"_ustr, uno::Reference< uno::XInterface >(), 1 );
470 uno::Reference <container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
471 if ( xIndex.is() )
473 SCTAB nCount = static_cast< SCTAB >( xIndex->getCount() );
474 for (SCTAB i=0; i < nCount; i++)
476 uno::Reference< container::XNamed > xNamed( xIndex->getByIndex(i), uno::UNO_QUERY_THROW );
477 if (xNamed->getName() == name)
479 nTab = i;
480 return true;
484 return false;
487 void ScVbaWorksheets::PrintPreview( const css::uno::Any& /*EnableChanges*/ )
489 // need test, print preview current active sheet
490 // !! TODO !! get view shell from controller
491 ScTabViewShell* pViewShell = excel::getBestViewShell( mxModel );
492 SfxViewFrame* pViewFrame = nullptr;
493 if ( pViewShell )
494 pViewFrame = &pViewShell->GetViewFrame();
495 if ( !pViewFrame )
496 return;
498 if ( pViewFrame->GetFrame().IsInPlace() )
499 return;
501 dispatchExecute( pViewShell, SID_VIEWSHELL1 );
502 SfxViewShell* pShell = SfxViewShell::Get( pViewFrame->GetFrame().GetFrameInterface()->getController() );
504 ScPreviewShell* pPrvShell = dynamic_cast< ScPreviewShell* >( pShell );
505 if ( !pPrvShell )
506 return;
508 ScPreview* pPrvView = pPrvShell->GetPreview();
509 const ScDocument& rDoc = pViewShell->GetViewData().GetDocument();
510 ScMarkData aMarkData(rDoc.GetSheetLimits());
511 sal_Int32 nElems = getCount();
512 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
514 uno::Reference< excel::XWorksheet > xSheet( Item( uno::Any( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
515 ScVbaWorksheet* pSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
516 if ( pSheet )
517 aMarkData.SelectTable(static_cast< SCTAB >( pSheet->getSheetID() ), true );
519 // save old selection, setting the selectedtabs in the preview
520 // can affect the current selection when preview has been
521 // closed
522 ScMarkData::MarkedTabsType aOldTabs = pPrvView->GetSelectedTabs();
523 pPrvView->SetSelectedTabs( aMarkData );
524 // force update
525 pPrvView->DataChanged(false);
526 // set sensible first page
527 tools::Long nPage = pPrvView->GetFirstPage( 1 );
528 pPrvView->SetPageNo( nPage );
529 WaitUntilPreviewIsClosed( pViewFrame );
530 // restore old tab selection
531 pViewShell = excel::getBestViewShell( mxModel );
532 pViewShell->GetViewData().GetMarkData().SetSelectedTabs(aOldTabs);
536 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */