xref: /trunk/main/sc/source/ui/vba/excelvbahelper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "excelvbahelper.hxx"
29 
30 #include <comphelper/processfactory.hxx>
31 #include <com/sun/star/sheet/XSheetCellRange.hpp>
32 #include "docuno.hxx"
33 #include "tabvwsh.hxx"
34 #include "transobj.hxx"
35 #include "scmod.hxx"
36 #include "cellsuno.hxx"
37 
38 namespace ooo {
39 namespace vba {
40 namespace excel {
41 
42 using namespace ::com::sun::star;
43 using namespace ::ooo::vba;
44 
45 // ============================================================================
46 
47 ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
48 {
49     ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
50     if ( !pScCellRangesBase )
51     {
52         throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying doc shell uno range object" ) ), uno::Reference< uno::XInterface >() );
53     }
54     return pScCellRangesBase->GetDocShell();
55 }
56 
57 ScDocument* GetDocumentFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
58 {
59         ScDocShell* pDocShell = GetDocShellFromRange( xRange );
60         if ( !pDocShell )
61         {
62                 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying document from uno range object" ) ), uno::Reference< uno::XInterface >() );
63         }
64         return pDocShell->GetDocument();
65 }
66 
67 void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
68 {
69     ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
70     Fraction aFract( nZoom, 100 );
71     pViewSh->GetViewData()->SetZoom( aFract, aFract, nTabs );
72     pViewSh->RefreshZoom();
73 }
74 bool isInPrintPreview( SfxViewFrame* pView )
75 {
76     sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0;
77     if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() >
78 nViewNo && !pView->GetObjectShell()->IsInPlaceActive() )
79     {
80         SfxViewFactory &rViewFactory =
81             pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
82         if (  pView->GetCurViewId() == rViewFactory.GetOrdinal() )
83             return true;
84     }
85     return false;
86 }
87 
88 const ::rtl::OUString REPLACE_CELLS_WARNING(  RTL_CONSTASCII_USTRINGPARAM( "ReplaceCellsWarning"));
89 
90 class PasteCellsWarningReseter
91 {
92 private:
93     bool bInitialWarningState;
94     static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException )
95     {
96         static uno::Reference< beans::XPropertySet > xTmpProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
97         static uno::Reference<uno::XComponentContext > xContext( xTmpProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW );
98         static uno::Reference<lang::XMultiComponentFactory > xServiceManager(
99                 xContext->getServiceManager(), uno::UNO_QUERY_THROW );
100         static uno::Reference< beans::XPropertySet > xProps( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.GlobalSheetSettings" ) ) ,xContext ), uno::UNO_QUERY_THROW );
101         return xProps;
102     }
103 
104     bool getReplaceCellsWarning() throw ( uno::RuntimeException )
105     {
106         sal_Bool res = sal_False;
107         getGlobalSheetSettings()->getPropertyValue( REPLACE_CELLS_WARNING ) >>= res;
108         return ( res == sal_True );
109     }
110 
111     void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
112     {
113         getGlobalSheetSettings()->setPropertyValue( REPLACE_CELLS_WARNING, uno::makeAny( bState ) );
114     }
115 public:
116     PasteCellsWarningReseter() throw ( uno::RuntimeException )
117     {
118         bInitialWarningState = getReplaceCellsWarning();
119         if ( bInitialWarningState )
120             setReplaceCellsWarning( false );
121     }
122     ~PasteCellsWarningReseter()
123     {
124         if ( bInitialWarningState )
125         {
126             // don't allow dtor to throw
127             try
128             {
129                 setReplaceCellsWarning( true );
130             }
131             catch ( uno::Exception& /*e*/ ){}
132         }
133     }
134 };
135 
136 void
137 implnPaste( const uno::Reference< frame::XModel>& xModel )
138 {
139     PasteCellsWarningReseter resetWarningBox;
140     ScTabViewShell* pViewShell = getBestViewShell( xModel );
141     if ( pViewShell )
142     {
143         pViewShell->PasteFromSystem();
144         pViewShell->CellContentChanged();
145     }
146 }
147 
148 
149 void
150 implnCopy( const uno::Reference< frame::XModel>& xModel )
151 {
152     ScTabViewShell* pViewShell = getBestViewShell( xModel );
153     if ( pViewShell )
154     {
155         pViewShell->CopyToClip(NULL,false,false,true);
156 
157         // mark the copied transfer object so it is used in ScVbaRange::Insert
158         ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
159         if (pClipObj)
160             pClipObj->SetUseInApi( true );
161     }
162 }
163 
164 void
165 implnCut( const uno::Reference< frame::XModel>& xModel )
166 {
167     ScTabViewShell* pViewShell =  getBestViewShell( xModel );
168     if ( pViewShell )
169     {
170         pViewShell->CutToClip( NULL, sal_True );
171 
172         // mark the copied transfer object so it is used in ScVbaRange::Insert
173         ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
174         if (pClipObj)
175             pClipObj->SetUseInApi( true );
176     }
177 }
178 
179 void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose)
180 {
181     PasteCellsWarningReseter resetWarningBox;
182     sal_Bool bAsLink(sal_False), bOtherDoc(sal_False);
183     InsCellCmd eMoveMode = INS_NONE;
184 
185     ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
186     if ( pTabViewShell )
187     {
188         ScViewData* pView = pTabViewShell->GetViewData();
189         Window* pWin = ( pView != NULL ) ? pView->GetActiveWin() : NULL;
190         if ( pView && pWin )
191         {
192             if ( bAsLink && bOtherDoc )
193                 pTabViewShell->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK
194             else
195             {
196                 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
197                 ScDocument* pDoc = NULL;
198                 if ( pOwnClip )
199                 {
200                     pDoc = pOwnClip->GetDocument();
201                     pOwnClip->SetUseInApi( false );     // don't use in Insert after it was pasted once
202                 }
203                 pTabViewShell->PasteFromClip( nFlags, pDoc,
204                     nFunction, bSkipEmpty, bTranspose, bAsLink,
205                     eMoveMode, IDF_NONE, sal_True );
206                 pTabViewShell->CellContentChanged();
207             }
208         }
209     }
210 
211 }
212 
213 ScDocShell*
214 getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
215 {
216     uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
217     ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
218     ScDocShell* pDocShell = NULL;
219     if ( pModel )
220         pDocShell = (ScDocShell*)pModel->GetEmbeddedObject();
221     return pDocShell;
222 
223 }
224 
225 ScTabViewShell*
226 getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
227 {
228     ScDocShell* pDocShell = getDocShell( xModel );
229     if ( pDocShell )
230         return pDocShell->GetBestViewShell();
231     return NULL;
232 }
233 
234 ScTabViewShell*
235 getCurrentBestViewShell(  const uno::Reference< uno::XComponentContext >& xContext )
236 {
237     uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
238     return getBestViewShell( xModel );
239 }
240 
241 SfxViewFrame*
242 getViewFrame( const uno::Reference< frame::XModel >& xModel )
243 {
244     ScTabViewShell* pViewShell = getBestViewShell( xModel );
245     if ( pViewShell )
246         return pViewShell->GetViewFrame();
247     return NULL;
248 }
249 
250 uno::Reference< XHelperInterface >
251 getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
252 {
253     uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
254     rtl::OUString sCodeName;
255     xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
256     // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
257     // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
258     // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
259     // the document in the future could fix this, especially IF the switching of the vba mode takes care to
260     // create the special document module objects if they don't exist.
261     return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
262 }
263 
264 uno::Reference< XHelperInterface >
265 getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
266 {
267     uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
268     uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
269     return getUnoSheetModuleObj( xSheet );
270 }
271 
272 uno::Reference< XHelperInterface >
273 getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
274 {
275     uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
276     uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
277     uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
278     return getUnoSheetModuleObj( xRange );
279 }
280 
281 uno::Reference< XHelperInterface >
282 getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
283 {
284     uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
285     uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
286     return getUnoSheetModuleObj( xSheet );
287 }
288 
289 uno::Reference< XHelperInterface >
290 getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
291 {
292     uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
293     uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
294     uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
295     return getUnoSheetModuleObj( xSheet );
296 }
297 
298 SfxItemSet*
299 ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
300 {
301     return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
302 }
303 
304 // ============================================================================
305 
306 } // namespace excel
307 } // namespace vba
308 } // namespace ooo
309