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 20 #include <excelfilter.hxx> 21 22 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 23 #include <osl/diagnose.h> 24 #include <sal/log.hxx> 25 26 #include <excelvbaproject.hxx> 27 #include <stylesbuffer.hxx> 28 #include <themebuffer.hxx> 29 #include <workbookfragment.hxx> 30 #include <xestream.hxx> 31 32 #include <addressconverter.hxx> 33 #include <document.hxx> 34 #include <docsh.hxx> 35 #include <scerrors.hxx> 36 #include <vcl/svapp.hxx> 37 #include <vcl/weld.hxx> 38 #include <svtools/sfxecode.hxx> 39 #include <svtools/ehdl.hxx> 40 #include <tools/urlobj.hxx> 41 #include <tools/diagnose_ex.h> 42 43 namespace oox { 44 namespace xls { 45 46 using namespace ::com::sun::star::lang; 47 using namespace ::com::sun::star::sheet; 48 using namespace ::com::sun::star::uno; 49 using namespace ::oox::core; 50 51 using ::oox::drawingml::table::TableStyleListPtr; 52 53 ExcelFilter::ExcelFilter( const Reference< XComponentContext >& rxContext ) : 54 XmlFilterBase( rxContext ), 55 mpBookGlob( nullptr ) 56 { 57 } 58 59 ExcelFilter::~ExcelFilter() 60 { 61 OSL_ENSURE( !mpBookGlob, "ExcelFilter::~ExcelFilter - workbook data not cleared" ); 62 } 63 64 void ExcelFilter::registerWorkbookGlobals( WorkbookGlobals& rBookGlob ) 65 { 66 mpBookGlob = &rBookGlob; 67 } 68 69 WorkbookGlobals& ExcelFilter::getWorkbookGlobals() const 70 { 71 OSL_ENSURE( mpBookGlob, "ExcelFilter::getWorkbookGlobals - missing workbook data" ); 72 return *mpBookGlob; 73 } 74 75 void ExcelFilter::unregisterWorkbookGlobals() 76 { 77 mpBookGlob = nullptr; 78 } 79 80 bool ExcelFilter::importDocument() 81 { 82 /* To activate the XLSX/XLSB dumper, insert the full path to the file 83 file:///<path-to-oox-module>/source/dump/xlsbdumper.ini 84 into the environment variable OOO_XLSBDUMPER and start the office with 85 this variable (nonpro only). */ 86 //OOX_DUMP_FILE( ::oox::dump::xlsb::Dumper ); 87 88 OUString aWorkbookPath = getFragmentPathFromFirstTypeFromOfficeDoc( "officeDocument" ); 89 if( aWorkbookPath.isEmpty() ) 90 return false; 91 92 try 93 { 94 try 95 { 96 importDocumentProperties(); 97 } 98 catch( const Exception& ) 99 { 100 TOOLS_WARN_EXCEPTION("sc", "exception when importing document properties"); 101 } 102 catch( ... ) 103 { 104 SAL_WARN("sc", "exception when importing document properties"); 105 } 106 /* Construct the WorkbookGlobals object referred to by every instance of 107 the class WorkbookHelper, and execute the import filter by constructing 108 an instance of WorkbookFragment and loading the file. */ 109 WorkbookGlobalsRef xBookGlob(WorkbookHelper::constructGlobals(*this)); 110 if (xBookGlob.get()) 111 { 112 rtl::Reference<FragmentHandler> xWorkbookFragment( new WorkbookFragment(*xBookGlob, aWorkbookPath)); 113 bool bRet = importFragment( xWorkbookFragment); 114 if (bRet) 115 { 116 const WorkbookFragment* pWF = static_cast<const WorkbookFragment*>(xWorkbookFragment.get()); 117 const AddressConverter& rAC = pWF->getAddressConverter(); 118 if (rAC.isTabOverflow() || rAC.isColOverflow() || rAC.isRowOverflow()) 119 { 120 const ScDocument& rDoc = pWF->getScDocument(); 121 if (rDoc.IsUserInteractionEnabled()) 122 { 123 // Show data loss warning. 124 125 INetURLObject aURL( getFileUrl()); 126 SfxErrorContext aContext( ERRCTX_SFX_OPENDOC, 127 aURL.getName( INetURLObject::LAST_SEGMENT, true, 128 INetURLObject::DecodeMechanism::WithCharset), 129 nullptr, RID_ERRCTX); 130 131 OUString aWarning; 132 aContext.GetString( ERRCODE_NONE.MakeWarning(), aWarning); 133 aWarning += ":\n"; 134 135 OUString aMsg; 136 if (rAC.isTabOverflow()) 137 { 138 if (ErrorHandler::GetErrorString( SCWARN_IMPORT_SHEET_OVERFLOW, aMsg)) 139 aWarning += aMsg; 140 } 141 if (rAC.isColOverflow()) 142 { 143 if (!aMsg.isEmpty()) 144 aWarning += "\n"; 145 if (ErrorHandler::GetErrorString( SCWARN_IMPORT_COLUMN_OVERFLOW, aMsg)) 146 aWarning += aMsg; 147 } 148 if (rAC.isRowOverflow()) 149 { 150 if (!aMsg.isEmpty()) 151 aWarning += "\n"; 152 if (ErrorHandler::GetErrorString( SCWARN_IMPORT_ROW_OVERFLOW, aMsg)) 153 aWarning += aMsg; 154 } 155 156 /* XXX displaying a dialog here is ugly and should 157 * rather happen at UI level instead of at the filter 158 * level, but it seems there's no way to transport 159 * detailed information other than returning true or 160 * false at this point? */ 161 162 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(), 163 VclMessageType::Warning, VclButtonsType::Ok, 164 aWarning)); 165 xWarn->run(); 166 } 167 } 168 } 169 return bRet; 170 } 171 } 172 catch (...) 173 { 174 } 175 176 return false; 177 } 178 179 bool ExcelFilter::exportDocument() throw() 180 { 181 return false; 182 } 183 184 const ::oox::drawingml::Theme* ExcelFilter::getCurrentTheme() const 185 { 186 return &WorkbookHelper( getWorkbookGlobals() ).getTheme(); 187 } 188 189 ::oox::vml::Drawing* ExcelFilter::getVmlDrawing() 190 { 191 return nullptr; 192 } 193 194 TableStyleListPtr ExcelFilter::getTableStyles() 195 { 196 return TableStyleListPtr(); 197 } 198 199 ::oox::drawingml::chart::ChartConverter* ExcelFilter::getChartConverter() 200 { 201 return WorkbookHelper( getWorkbookGlobals() ).getChartConverter(); 202 } 203 204 void ExcelFilter::useInternalChartDataTable( bool bInternal ) 205 { 206 return WorkbookHelper( getWorkbookGlobals() ).useInternalChartDataTable( bInternal ); 207 } 208 209 GraphicHelper* ExcelFilter::implCreateGraphicHelper() const 210 { 211 return new ExcelGraphicHelper( getWorkbookGlobals() ); 212 } 213 214 ::oox::ole::VbaProject* ExcelFilter::implCreateVbaProject() const 215 { 216 return new ExcelVbaProject( getComponentContext(), Reference< XSpreadsheetDocument >( getModel(), UNO_QUERY ) ); 217 } 218 219 sal_Bool SAL_CALL ExcelFilter::filter( const css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) 220 { 221 if ( XmlFilterBase::filter( rDescriptor ) ) 222 return true; 223 224 if ( isExportFilter() ) 225 { 226 bool bExportVBA = exportVBA(); 227 Reference< XExporter > xExporter( 228 new XclExpXmlStream( getComponentContext(), bExportVBA, isExportTemplate() ) ); 229 230 Reference< XComponent > xDocument = getModel(); 231 Reference< XFilter > xFilter( xExporter, UNO_QUERY ); 232 233 if ( xFilter.is() ) 234 { 235 xExporter->setSourceDocument( xDocument ); 236 if ( xFilter->filter( rDescriptor ) ) 237 return true; 238 } 239 } 240 241 return false; 242 } 243 244 OUString ExcelFilter::getImplementationName() 245 { 246 return "com.sun.star.comp.oox.xls.ExcelFilter"; 247 } 248 249 } // namespace xls 250 } // namespace oox 251 252 253 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* 254 com_sun_star_comp_oox_xls_ExcelFilter_get_implementation(css::uno::XComponentContext* context, 255 css::uno::Sequence<css::uno::Any> const &) 256 { 257 return cppu::acquire(new oox::xls::ExcelFilter(context)); 258 } 259 260 261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 262
