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 #include "vbaworksheets.hxx"
20
21 #include <sfx2/viewfrm.hxx>
22
23 #include <cppuhelper/implbase.hxx>
24
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>
31
32 #include <ooo/vba/excel/XApplication.hpp>
33 #include <tabvwsh.hxx>
34
35 #include "excelvbahelper.hxx"
36 #include "vbaworksheet.hxx"
37 #include <markdata.hxx>
38
39 #include <vector>
40 #include <prevwsh.hxx>
41 #include <preview.hxx>
42 using namespace ::ooo::vba;
43 using namespace ::com::sun::star;
44
45 // a map ( or hashmap ) won't do as we need also to preserve the order
46 // (as added ) of the items
47 typedef std::vector< uno::Reference< sheet::XSpreadsheet > > SheetMap;
48
49 // #FIXME #TODO the implementation of the Sheets collections sucks,
50 // e.g. there is no support for tracking sheets added/removed from the collection
51
52 class WorkSheetsEnumeration : public ::cppu::WeakImplHelper< container::XEnumeration >
53 {
54 SheetMap mSheetMap;
55 SheetMap::iterator mIt;
56 public:
WorkSheetsEnumeration(const SheetMap & sMap)57 explicit WorkSheetsEnumeration( const SheetMap& sMap ) : mSheetMap( sMap ), mIt( mSheetMap.begin() ) {}
hasMoreElements()58 virtual sal_Bool SAL_CALL hasMoreElements( ) override
59 {
60 return ( mIt != mSheetMap.end() );
61 }
nextElement()62 virtual uno::Any SAL_CALL nextElement( ) override
63 {
64 if ( !hasMoreElements() )
65 throw container::NoSuchElementException();
66 uno::Reference< sheet::XSpreadsheet > xSheet( *mIt++ );
67 return uno::makeAny( xSheet ) ;
68 }
69 };
70
71 class SheetCollectionHelper : public ::cppu::WeakImplHelper< container::XNameAccess,
72 container::XIndexAccess,
73 container::XEnumerationAccess >
74 {
75 SheetMap mSheetMap;
76 SheetMap::iterator cachePos;
77 public:
SheetCollectionHelper(const SheetMap & sMap)78 explicit SheetCollectionHelper( const SheetMap& sMap ) : mSheetMap( sMap ), cachePos(mSheetMap.begin()) {}
79 // XElementAccess
getElementType()80 virtual uno::Type SAL_CALL getElementType( ) override { return cppu::UnoType<sheet::XSpreadsheet>::get(); }
hasElements()81 virtual sal_Bool SAL_CALL hasElements( ) override { return ( !mSheetMap.empty() ); }
82 // XNameAccess
getByName(const OUString & aName)83 virtual uno::Any SAL_CALL getByName( const OUString& aName ) override
84 {
85 if ( !hasByName(aName) )
86 throw container::NoSuchElementException();
87 return uno::makeAny( *cachePos );
88 }
getElementNames()89 virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override
90 {
91 uno::Sequence< OUString > sNames( mSheetMap.size() );
92 OUString* pString = sNames.getArray();
93
94 for ( const auto& rItem : mSheetMap )
95 {
96 uno::Reference< container::XNamed > xName( rItem, uno::UNO_QUERY_THROW );
97 *pString = xName->getName();
98 ++pString;
99 }
100 return sNames;
101 }
hasByName(const OUString & aName)102 virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
103 {
104 cachePos = mSheetMap.begin();
105 SheetMap::iterator it_end = mSheetMap.end();
106 for ( ; cachePos != it_end; ++cachePos )
107 {
108 uno::Reference< container::XNamed > xName( *cachePos, uno::UNO_QUERY_THROW );
109 if ( aName == xName->getName() )
110 break;
111 }
112 return ( cachePos != it_end );
113 }
114
115 // XElementAccess
getCount()116 virtual ::sal_Int32 SAL_CALL getCount( ) override { return mSheetMap.size(); }
getByIndex(::sal_Int32 Index)117 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
118 {
119 if ( Index < 0 || Index >= getCount() )
120 throw lang::IndexOutOfBoundsException();
121
122 return uno::makeAny( mSheetMap[ Index ] );
123
124 }
125 // XEnumerationAccess
createEnumeration()126 virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration( ) override
127 {
128 return new WorkSheetsEnumeration( mSheetMap );
129 }
130 };
131
132 class SheetsEnumeration : public EnumerationHelperImpl
133 {
134 uno::Reference< frame::XModel > m_xModel;
135 public:
136 /// @throws uno::RuntimeException
SheetsEnumeration(const uno::Reference<XHelperInterface> & xParent,const uno::Reference<uno::XComponentContext> & xContext,const uno::Reference<container::XEnumeration> & xEnumeration,const uno::Reference<frame::XModel> & xModel)137 SheetsEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XEnumeration >& xEnumeration, const uno::Reference< frame::XModel >& xModel ) : EnumerationHelperImpl( xParent, xContext, xEnumeration ), m_xModel( xModel ) {}
138
nextElement()139 virtual uno::Any SAL_CALL nextElement( ) override
140 {
141 uno::Reference< sheet::XSpreadsheet > xSheet( m_xEnumeration->nextElement(), uno::UNO_QUERY_THROW );
142 uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet );
143 uno::Any aRet;
144 if ( !xIf.is() )
145 {
146 // if the Sheet is in a document created by the api unfortunately ( at the
147 // moment, it actually won't have the special Document modules
148 uno::Reference< excel::XWorksheet > xNewSheet( new ScVbaWorksheet( m_xParent, m_xContext, xSheet, m_xModel ) );
149 aRet <<= xNewSheet;
150 }
151 else
152 aRet <<= xIf;
153 return aRet;
154 }
155
156 };
157
ScVbaWorksheets(const uno::Reference<XHelperInterface> & xParent,const uno::Reference<css::uno::XComponentContext> & xContext,const uno::Reference<container::XIndexAccess> & xSheets,const uno::Reference<frame::XModel> & xModel)158 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::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 ) )
159 {
160 }
161
ScVbaWorksheets(const uno::Reference<XHelperInterface> & xParent,const uno::Reference<css::uno::XComponentContext> & xContext,const uno::Reference<container::XEnumerationAccess> & xEnumAccess,const uno::Reference<frame::XModel> & xModel)162 ScVbaWorksheets::ScVbaWorksheets( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::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)
163 {
164 }
165
166 // XEnumerationAccess
167 uno::Type
getElementType()168 ScVbaWorksheets::getElementType()
169 {
170 return cppu::UnoType<excel::XWorksheet>::get();
171 }
172
173 uno::Reference< container::XEnumeration >
createEnumeration()174 ScVbaWorksheets::createEnumeration()
175 {
176 if ( !m_xSheets.is() )
177 {
178 uno::Reference< container::XEnumerationAccess > xAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
179 return xAccess->createEnumeration();
180 }
181 uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xSheets, uno::UNO_QUERY_THROW );
182 return new SheetsEnumeration( this, mxContext, xEnumAccess->createEnumeration(), mxModel );
183 }
184
185 uno::Any
createCollectionObject(const uno::Any & aSource)186 ScVbaWorksheets::createCollectionObject( const uno::Any& aSource )
187 {
188 uno::Reference< sheet::XSpreadsheet > xSheet( aSource, uno::UNO_QUERY );
189 uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet );
190 uno::Any aRet;
191 if ( !xIf.is() )
192 {
193 // if the Sheet is in a document created by the api unfortunately ( at the
194 // moment, it actually won't have the special Document modules
195 uno::Reference< excel::XWorksheet > xNewSheet( new ScVbaWorksheet( getParent(), mxContext, xSheet, mxModel ) );
196 aRet <<= xNewSheet;
197 }
198 else
199 aRet <<= xIf;
200 return aRet;
201 }
202
203 // XWorksheets
204 uno::Any
Add(const uno::Any & Before,const uno::Any & After,const uno::Any & Count,const uno::Any & Type)205 ScVbaWorksheets::Add( const uno::Any& Before, const uno::Any& After,
206 const uno::Any& Count, const uno::Any& Type )
207 {
208 if ( isSelectedSheets() )
209 return uno::Any(); // or should we throw?
210
211 OUString aStringSheet;
212 bool bBefore(true);
213 SCTAB nSheetIndex = 0;
214 SCTAB nNewSheets = 1, nType = 0;
215 Count >>= nNewSheets;
216 Type >>= nType;
217 SCTAB nCount = 0;
218
219 uno::Reference< excel::XWorksheet > xBeforeAfterSheet;
220
221 if ( Before.hasValue() )
222 {
223 if ( Before >>= xBeforeAfterSheet )
224 aStringSheet = xBeforeAfterSheet->getName();
225 else
226 Before >>= aStringSheet;
227 }
228
229 if (aStringSheet.isEmpty() && After.hasValue() )
230 {
231 if ( After >>= xBeforeAfterSheet )
232 aStringSheet = xBeforeAfterSheet->getName();
233 else
234 After >>= aStringSheet;
235 bBefore = false;
236 }
237 if (aStringSheet.isEmpty())
238 {
239 uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
240 aStringSheet = xApplication->getActiveWorkbook()->getActiveSheet()->getName();
241 bBefore = true;
242 }
243 nCount = static_cast< SCTAB >( m_xIndexAccess->getCount() );
244 for (SCTAB i=0; i < nCount; i++)
245 {
246 uno::Reference< sheet::XSpreadsheet > xSheet(m_xIndexAccess->getByIndex(i), uno::UNO_QUERY);
247 uno::Reference< container::XNamed > xNamed( xSheet, uno::UNO_QUERY_THROW );
248 if (xNamed->getName() == aStringSheet)
249 {
250 nSheetIndex = i;
251 break;
252 }
253 }
254
255 if(!bBefore)
256 nSheetIndex++;
257
258 SCTAB nSheetName = nCount + 1;
259 OUString aStringBase( "Sheet" );
260 uno::Any result;
261 for (SCTAB i=0; i < nNewSheets; i++, nSheetName++)
262 {
263 OUString aStringName = aStringBase + OUString::number(nSheetName);
264 while (m_xNameAccess->hasByName(aStringName))
265 {
266 nSheetName++;
267 aStringName = aStringBase + OUString::number(nSheetName);
268 }
269 m_xSheets->insertNewByName(aStringName, nSheetIndex + i);
270 result = getItemByStringIndex( aStringName );
271 }
272 uno::Reference< excel::XWorksheet > xNewSheet( result, uno::UNO_QUERY );
273 if ( xNewSheet.is() )
274 xNewSheet->Activate();
275 return result;
276 }
277
278 void
Delete()279 ScVbaWorksheets::Delete()
280 {
281 // #TODO #INVESTIGATE
282 // mmm this method could be trouble if the underlying
283 // uno objects ( the m_xIndexAccess etc ) aren't aware of the
284 // contents that are deleted
285 sal_Int32 nElems = getCount();
286 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
287 {
288 uno::Reference< excel::XWorksheet > xSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
289 xSheet->Delete();
290 }
291 }
292
293 bool
isSelectedSheets() const294 ScVbaWorksheets::isSelectedSheets() const
295 {
296 return !m_xSheets.is();
297 }
298
299 void SAL_CALL
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)300 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 )
301 {
302 sal_Int32 nTo = 0;
303 sal_Int32 nFrom = 0;
304 bool bSelection = false;
305 From >>= nFrom;
306 To >>= nTo;
307
308 if ( !( nFrom || nTo ) )
309 if ( isSelectedSheets() )
310 bSelection = true;
311
312 PrintOutHelper( excel::getBestViewShell( mxModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, bSelection );
313 }
314
315 uno::Any SAL_CALL
getVisible()316 ScVbaWorksheets::getVisible()
317 {
318 bool bVisible = true;
319 uno::Reference< container::XEnumeration > xEnum( createEnumeration(), uno::UNO_SET_THROW );
320 while ( xEnum->hasMoreElements() )
321 {
322 uno::Reference< excel::XWorksheet > xSheet( xEnum->nextElement(), uno::UNO_QUERY_THROW );
323 if ( xSheet->getVisible() == 0 )
324 {
325 bVisible = false;
326 break;
327 }
328 }
329 return uno::makeAny( bVisible );
330 }
331
332 void SAL_CALL
setVisible(const uno::Any & _visible)333 ScVbaWorksheets::setVisible( const uno::Any& _visible )
334 {
335 bool bState = false;
336 if ( !(_visible >>= bState) )
337 throw uno::RuntimeException("Visible property doesn't support non boolean #FIXME" );
338
339 uno::Reference< container::XEnumeration > xEnum( createEnumeration(), uno::UNO_SET_THROW );
340 while ( xEnum->hasMoreElements() )
341 {
342 uno::Reference< excel::XWorksheet > xSheet( xEnum->nextElement(), uno::UNO_QUERY_THROW );
343 xSheet->setVisible( bState ? 1 : 0 );
344 }
345
346 }
347
348 void SAL_CALL
Select(const uno::Any & Replace)349 ScVbaWorksheets::Select( const uno::Any& Replace )
350 {
351 ScTabViewShell* pViewShell = excel::getBestViewShell( mxModel );
352 if ( !pViewShell )
353 throw uno::RuntimeException("Cannot obtain view shell" );
354
355 ScMarkData& rMarkData = pViewShell->GetViewData().GetMarkData();
356 bool bReplace = true;
357 Replace >>= bReplace;
358 // Replace is defaulted to True, meaning this current collection
359 // becomes the Selection, if it were false then the current selection would
360 // be extended
361 bool bSelectSingle = bReplace;
362 sal_Int32 nElems = getCount();
363 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
364 {
365 uno::Reference< excel::XWorksheet > xSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
366 ScVbaWorksheet* pSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
367 if ( bSelectSingle )
368 {
369 rMarkData.SelectOneTable( static_cast< SCTAB >( pSheet->getSheetID() ) );
370 bSelectSingle = false;
371 }
372 else
373 rMarkData.SelectTable( static_cast< SCTAB >( pSheet->getSheetID() ), true );
374 }
375
376 }
377
378 void SAL_CALL
Copy(const uno::Any & Before,const uno::Any & After)379 ScVbaWorksheets::Copy ( const uno::Any& Before, const uno::Any& After)
380 {
381 uno::Reference<excel::XWorksheet> xSheet;
382 sal_Int32 nElems = getCount();
383 bool bAfter = After.hasValue();
384 std::vector< uno::Reference< excel::XWorksheet > > Sheets;
385 sal_Int32 nItem = 0;
386
387 for ( nItem = 1; nItem <= nElems; ++nItem)
388 {
389 uno::Reference<excel::XWorksheet> xWorksheet(Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
390 Sheets.push_back(xWorksheet);
391 }
392 bool bNewDoc = (!(Before >>= xSheet) && !(After >>=xSheet)&& !(Before.hasValue()) && !(After.hasValue()));
393
394 uno::Reference< excel::XWorksheet > xSrcSheet;
395 if ( bNewDoc )
396 {
397 bAfter = true;
398 xSrcSheet = Sheets.at(0);
399 ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
400 xSheet = pSrcSheet->createSheetCopyInNewDoc(xSrcSheet->getName());
401 nItem = 1;
402 }
403 else
404 {
405 nItem=0;
406 }
407
408 for (; nItem < nElems; ++nItem )
409 {
410 xSrcSheet = Sheets[nItem];
411 ScVbaWorksheet* pSrcSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSrcSheet );
412 if ( bAfter )
413 xSheet = pSrcSheet->createSheetCopy(xSheet, bAfter);
414 else
415 pSrcSheet->createSheetCopy(xSheet, bAfter);
416 }
417 }
418
419 //ScVbaCollectionBaseImpl
420 uno::Any SAL_CALL
Item(const uno::Any & Index,const uno::Any & Index2)421 ScVbaWorksheets::Item(const uno::Any& Index, const uno::Any& Index2)
422 {
423 if ( Index.getValueTypeClass() == uno::TypeClass_SEQUENCE )
424 {
425 const uno::Reference< script::XTypeConverter >& xConverter = getTypeConverter(mxContext);
426 uno::Any aConverted = xConverter->convertTo( Index, cppu::UnoType<uno::Sequence< uno::Any >>::get() );
427 SheetMap aSheets;
428 uno::Sequence< uno::Any > sIndices;
429 aConverted >>= sIndices;
430 for( const auto& rIndex : std::as_const(sIndices) )
431 {
432 uno::Reference< excel::XWorksheet > xWorkSheet( ScVbaWorksheets_BASE::Item( rIndex, Index2 ), uno::UNO_QUERY_THROW );
433 ScVbaWorksheet* pWorkSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xWorkSheet );
434 uno::Reference< sheet::XSpreadsheet > xSheet( pWorkSheet->getSheet() , uno::UNO_SET_THROW );
435 uno::Reference< container::XNamed > xName( xSheet, uno::UNO_QUERY_THROW );
436 aSheets.push_back( xSheet );
437 }
438 uno::Reference< container::XIndexAccess > xIndexAccess = new SheetCollectionHelper( aSheets );
439 uno::Reference< XCollection > xSelectedSheets( new ScVbaWorksheets( getParent(), mxContext, xIndexAccess, mxModel ) );
440 return uno::makeAny( xSelectedSheets );
441 }
442 return ScVbaWorksheets_BASE::Item( Index, Index2 );
443 }
444
445 OUString
getServiceImplName()446 ScVbaWorksheets::getServiceImplName()
447 {
448 return "ScVbaWorksheets";
449 }
450
451 css::uno::Sequence<OUString>
getServiceNames()452 ScVbaWorksheets::getServiceNames()
453 {
454 static uno::Sequence< OUString > const sNames
455 {
456 "ooo.vba.excel.Worksheets"
457 };
458 return sNames;
459 }
460
nameExists(const uno::Reference<sheet::XSpreadsheetDocument> & xSpreadDoc,const OUString & name,SCTAB & nTab)461 bool ScVbaWorksheets::nameExists( const uno::Reference <sheet::XSpreadsheetDocument>& xSpreadDoc, const OUString & name, SCTAB& nTab )
462 {
463 if (!xSpreadDoc.is())
464 throw lang::IllegalArgumentException( "nameExists() xSpreadDoc is null", uno::Reference< uno::XInterface >(), 1 );
465 uno::Reference <container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
466 if ( xIndex.is() )
467 {
468 SCTAB nCount = static_cast< SCTAB >( xIndex->getCount() );
469 for (SCTAB i=0; i < nCount; i++)
470 {
471 uno::Reference< container::XNamed > xNamed( xIndex->getByIndex(i), uno::UNO_QUERY_THROW );
472 if (xNamed->getName() == name)
473 {
474 nTab = i;
475 return true;
476 }
477 }
478 }
479 return false;
480 }
481
PrintPreview(const css::uno::Any &)482 void ScVbaWorksheets::PrintPreview( const css::uno::Any& /*EnableChanges*/ )
483 {
484 // need test, print preview current active sheet
485 // !! TODO !! get view shell from controller
486 ScTabViewShell* pViewShell = excel::getBestViewShell( mxModel );
487 SfxViewFrame* pViewFrame = nullptr;
488 if ( pViewShell )
489 pViewFrame = pViewShell->GetViewFrame();
490 if ( pViewFrame )
491 {
492 if ( !pViewFrame->GetFrame().IsInPlace() )
493 {
494 dispatchExecute( pViewShell, SID_VIEWSHELL1 );
495 SfxViewShell* pShell = SfxViewShell::Get( pViewFrame->GetFrame().GetFrameInterface()->getController() );
496
497 if ( dynamic_cast<const ScPreviewShell*>( pShell) != nullptr )
498 {
499 ScPreviewShell* pPrvShell = static_cast< ScPreviewShell* >( pShell );
500 ScPreview* pPrvView = pPrvShell->GetPreview();
501 const ScDocument& rDoc = *pViewShell->GetViewData().GetDocument();
502 ScMarkData aMarkData(rDoc.MaxRow(), rDoc.MaxCol());
503 sal_Int32 nElems = getCount();
504 for ( sal_Int32 nItem = 1; nItem <= nElems; ++nItem )
505 {
506 uno::Reference< excel::XWorksheet > xSheet( Item( uno::makeAny( nItem ), uno::Any() ), uno::UNO_QUERY_THROW );
507 ScVbaWorksheet* pSheet = excel::getImplFromDocModuleWrapper<ScVbaWorksheet>( xSheet );
508 if ( pSheet )
509 aMarkData.SelectTable(static_cast< SCTAB >( pSheet->getSheetID() ), true );
510 }
511 // save old selection, setting the selectedtabs in the preview
512 // can affect the current selection when preview has been
513 // closed
514 ScMarkData::MarkedTabsType aOldTabs = pPrvView->GetSelectedTabs();
515 pPrvView->SetSelectedTabs( aMarkData );
516 // force update
517 pPrvView->DataChanged(false);
518 // set sensible first page
519 long nPage = pPrvView->GetFirstPage( 1 );
520 pPrvView->SetPageNo( nPage );
521 WaitUntilPreviewIsClosed( pViewFrame );
522 // restore old tab selection
523 pViewShell = excel::getBestViewShell( mxModel );
524 pViewShell->GetViewData().GetMarkData().SetSelectedTabs(aOldTabs);
525 }
526 }
527 }
528
529 }
530
531 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
532