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