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