xref: /core/sc/source/filter/oox/excelfilter.cxx (revision 09cd0e36)
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