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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/app.hxx>
30 #include <sfx2/frame.hxx>
31 #include <sfx2/request.hxx>
32 #include <sot/storage.hxx>
33 #include <sot/exchange.hxx>
34 #include <tools/globname.hxx>
35 #include <comphelper/mediadescriptor.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <com/sun/star/document/XFilter.hpp>
39 #include <com/sun/star/document/XImporter.hpp>
40 #include "scitems.hxx"
41 #include <svl/stritem.hxx>
42 #include "filter.hxx"
43 #include "document.hxx"
44 #include "xistream.hxx"
45
46 #include "scerrors.hxx"
47 #include "root.hxx"
48 #include "imp_op.hxx"
49 #include "excimp8.hxx"
50 #include "exp_op.hxx"
51
52
ScImportExcel(SfxMedium & rMedium,ScDocument * pDocument,const EXCIMPFORMAT eFormat)53 FltError ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat )
54 {
55 // check the passed Calc document
56 DBG_ASSERT( pDocument, "::ScImportExcel - no document" );
57 if( !pDocument ) return eERR_INTERN; // should not happen
58
59 /* Import all BIFF versions regardless on eFormat, needed for import of
60 external cells (file type detection returns Excel4.0). */
61 if( (eFormat != EIF_AUTO) && (eFormat != EIF_BIFF_LE4) && (eFormat != EIF_BIFF5) && (eFormat != EIF_BIFF8) )
62 {
63 DBG_ERRORFILE( "::ScImportExcel - wrong file format specification" );
64 return eERR_FORMAT;
65 }
66
67 // check the input stream from medium
68 SvStream* pMedStrm = rMedium.GetInStream();
69 DBG_ASSERT( pMedStrm, "::ScImportExcel - medium without input stream" );
70 if( !pMedStrm ) return eERR_OPEN; // should not happen
71
72 #if OSL_DEBUG_LEVEL > 0
73 using namespace ::com::sun::star;
74 using namespace ::comphelper;
75
76 /* Environment variable "OOO_OOXBIFFFILTER":
77 - "1" = use new OOX filter for import;
78 - undef/other = use old sc filter for import (OOX only as file dumper). */
79 const sal_Char* pcFileName = ::getenv( "OOO_OOXBIFFFILTER" );
80 bool bUseOoxFilter = pcFileName && (*pcFileName == '1') && (*(pcFileName + 1) == 0);
81 if( SfxObjectShell* pDocShell = pDocument->GetDocumentShell() ) try
82 {
83 uno::Reference< lang::XComponent > xComponent( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
84
85 uno::Sequence< beans::NamedValue > aArgSeq( 1 );
86 aArgSeq[ 0 ].Name = CREATE_OUSTRING( "UseBiffFilter" );
87 aArgSeq[ 0 ].Value <<= bUseOoxFilter;
88
89 uno::Sequence< uno::Any > aArgs( 2 );
90 aArgs[ 0 ] <<= getProcessServiceFactory();
91 aArgs[ 1 ] <<= aArgSeq;
92 uno::Reference< document::XImporter > xImporter( ScfApiHelper::CreateInstanceWithArgs(
93 CREATE_OUSTRING( "com.sun.star.comp.oox.xls.ExcelBiffFilter" ), aArgs ), uno::UNO_QUERY_THROW );
94 xImporter->setTargetDocument( xComponent );
95
96 MediaDescriptor aMediaDesc;
97 SfxItemSet* pItemSet = rMedium.GetItemSet();
98 if( pItemSet )
99 {
100 SFX_ITEMSET_ARG( pItemSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False);
101 if( pFileNameItem )
102 aMediaDesc[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pFileNameItem->GetValue() );
103
104 SFX_ITEMSET_ARG( pItemSet, pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False);
105 if( pPasswordItem )
106 aMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pPasswordItem->GetValue() );
107
108 SFX_ITEMSET_ARG( pItemSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False);
109 if( pEncryptionDataItem )
110 aMediaDesc[ MediaDescriptor::PROP_ENCRYPTIONDATA() ] = pEncryptionDataItem->GetValue();
111 }
112 aMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium.GetInputStream();
113 aMediaDesc[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium.GetInteractionHandler();
114
115 // call the filter
116 uno::Reference< document::XFilter > xFilter( xImporter, uno::UNO_QUERY_THROW );
117 bool bResult = xFilter->filter( aMediaDesc.getAsConstPropertyValueList() );
118
119 // if filter returns false, document is invalid, or dumper has disabled import -> exit here
120 if( !bResult )
121 return ERRCODE_ABORT;
122
123 // if OOX filter has been used, exit with OK code
124 if( bUseOoxFilter )
125 return eERR_OK;
126 }
127 catch( uno::Exception& )
128 {
129 if( bUseOoxFilter )
130 return ERRCODE_ABORT;
131 // else ignore exception and import the document with this filter
132 }
133 #endif
134
135 SvStream* pBookStrm = 0; // The "Book"/"Workbook" stream containing main data.
136 XclBiff eBiff = EXC_BIFF_UNKNOWN; // The BIFF version of the main stream.
137
138 // try to open an OLE storage
139 SotStorageRef xRootStrg;
140 SotStorageStreamRef xStrgStrm;
141 if( SotStorage::IsStorageFile( pMedStrm ) )
142 {
143 xRootStrg = new SotStorage( pMedStrm, sal_False );
144 if( xRootStrg->GetError() )
145 xRootStrg = 0;
146 }
147
148 // try to open "Book" or "Workbook" stream in OLE storage
149 if( xRootStrg.Is() )
150 {
151 // try to open the "Book" stream
152 SotStorageStreamRef xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK );
153 XclBiff eBookBiff = xBookStrm.Is() ? XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN;
154
155 // try to open the "Workbook" stream
156 SotStorageStreamRef xWorkbookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_WORKBOOK );
157 XclBiff eWorkbookBiff = xWorkbookStrm.Is() ? XclImpStream::DetectBiffVersion( *xWorkbookStrm ) : EXC_BIFF_UNKNOWN;
158
159 // decide which stream to use
160 if( (eWorkbookBiff != EXC_BIFF_UNKNOWN) && ((eBookBiff == EXC_BIFF_UNKNOWN) || (eWorkbookBiff > eBookBiff)) )
161 {
162 /* Only "Workbook" stream exists; or both streams exist,
163 and "Workbook" has higher BIFF version than "Book" stream. */
164 xStrgStrm = xWorkbookStrm;
165 eBiff = eWorkbookBiff;
166 }
167 else if( eBookBiff != EXC_BIFF_UNKNOWN )
168 {
169 /* Only "Book" stream exists; or both streams exist,
170 and "Book" has higher BIFF version than "Workbook" stream. */
171 xStrgStrm = xBookStrm;
172 eBiff = eBookBiff;
173 }
174
175 pBookStrm = xStrgStrm;
176 }
177
178 // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
179 if( !pBookStrm )
180 {
181 eBiff = XclImpStream::DetectBiffVersion( *pMedStrm );
182 if( eBiff != EXC_BIFF_UNKNOWN )
183 pBookStrm = pMedStrm;
184 }
185
186 // try to import the file
187 FltError eRet = eERR_UNKN_BIFF;
188 if( pBookStrm )
189 {
190 pBookStrm->SetBufferSize( 0x8000 ); // still needed?
191
192 XclImpRootData aImpData( eBiff, rMedium, xRootStrg, *pDocument, RTL_TEXTENCODING_MS_1252 );
193 ::std::auto_ptr< ImportExcel > xFilter;
194 switch( eBiff )
195 {
196 case EXC_BIFF2:
197 case EXC_BIFF3:
198 case EXC_BIFF4:
199 case EXC_BIFF5:
200 xFilter.reset( new ImportExcel( aImpData, *pBookStrm ) );
201 break;
202 case EXC_BIFF8:
203 xFilter.reset( new ImportExcel8( aImpData, *pBookStrm ) );
204 break;
205 default: DBG_ERROR_BIFF();
206 }
207
208 eRet = xFilter.get() ? xFilter->Read() : eERR_INTERN;
209 }
210
211 return eRet;
212 }
213
214
lcl_ExportExcelBiff(SfxMedium & rMedium,ScDocument * pDocument,SvStream * pMedStrm,sal_Bool bBiff8,CharSet eNach)215 static FltError lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
216 SvStream* pMedStrm, sal_Bool bBiff8, CharSet eNach )
217 {
218 // try to open an OLE storage
219 SotStorageRef xRootStrg = new SotStorage( pMedStrm, sal_False );
220 if( xRootStrg->GetError() ) return eERR_OPEN;
221
222 // create BIFF dependent strings
223 String aStrmName, aClipName, aClassName;
224 if( bBiff8 )
225 {
226 aStrmName = EXC_STREAM_WORKBOOK;
227 aClipName = CREATE_STRING( "Biff8" );
228 aClassName = CREATE_STRING( "Microsoft Excel 97-Tabelle" );
229 }
230 else
231 {
232 aStrmName = EXC_STREAM_BOOK;
233 aClipName = CREATE_STRING( "Biff5" );
234 aClassName = CREATE_STRING( "Microsoft Excel 5.0-Tabelle" );
235 }
236
237 // open the "Book"/"Workbook" stream
238 SotStorageStreamRef xStrgStrm = ScfTools::OpenStorageStreamWrite( xRootStrg, aStrmName );
239 if( !xStrgStrm.Is() || xStrgStrm->GetError() ) return eERR_OPEN;
240
241 xStrgStrm->SetBufferSize( 0x8000 ); // still needed?
242
243 FltError eRet = eERR_UNKN_BIFF;
244 XclExpRootData aExpData( bBiff8 ? EXC_BIFF8 : EXC_BIFF5, rMedium, xRootStrg, *pDocument, eNach );
245 if ( bBiff8 )
246 {
247 ExportBiff8 aFilter( aExpData, *xStrgStrm );
248 eRet = aFilter.Write();
249 }
250 else
251 {
252 ExportBiff5 aFilter( aExpData, *xStrgStrm );
253 eRet = aFilter.Write();
254 }
255
256 if( eRet == eERR_RNGOVRFLW )
257 eRet = SCWARN_EXPORT_MAXROW;
258
259 SvGlobalName aGlobName( 0x00020810, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
260 sal_uInt32 nClip = SotExchange::RegisterFormatName( aClipName );
261 xRootStrg->SetClass( aGlobName, nClip, aClassName );
262
263 xStrgStrm->Commit();
264 xRootStrg->Commit();
265
266 return eRet;
267 }
268
lcl_ExportExcel2007Xml(SfxMedium & rMedium,ScDocument * pDocument,SvStream * pMedStrm,CharSet eNach)269 static FltError lcl_ExportExcel2007Xml( SfxMedium& rMedium, ScDocument *pDocument,
270 SvStream* pMedStrm, CharSet eNach )
271 {
272 SotStorageRef xRootStrg = (SotStorage*) 0;
273
274 XclExpRootData aExpData( EXC_BIFF8, rMedium, xRootStrg, *pDocument, eNach );
275 aExpData.meOutput = EXC_OUTPUT_XML_2007;
276
277 ExportXml2007 aFilter( aExpData, *pMedStrm );
278
279 FltError eRet = aFilter.Write();
280
281 return eRet;
282 }
283
ScExportExcel5(SfxMedium & rMedium,ScDocument * pDocument,ExportFormatExcel eFormat,CharSet eNach)284 FltError ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium& rMedium, ScDocument *pDocument,
285 ExportFormatExcel eFormat, CharSet eNach )
286 {
287 if( eFormat != ExpBiff5 && eFormat != ExpBiff8 && eFormat != Exp2007Xml )
288 return eERR_NI;
289
290 // check the passed Calc document
291 DBG_ASSERT( pDocument, "::ScImportExcel - no document" );
292 if( !pDocument ) return eERR_INTERN; // should not happen
293
294 // check the output stream from medium
295 SvStream* pMedStrm = rMedium.GetOutStream();
296 DBG_ASSERT( pMedStrm, "::ScExportExcel5 - medium without output stream" );
297 if( !pMedStrm ) return eERR_OPEN; // should not happen
298
299 FltError eRet = eERR_UNKN_BIFF;
300 if( eFormat == ExpBiff5 || eFormat == ExpBiff8 )
301 eRet = lcl_ExportExcelBiff( rMedium, pDocument, pMedStrm, eFormat == ExpBiff8, eNach );
302 else if( eFormat == Exp2007Xml )
303 eRet = lcl_ExportExcel2007Xml( rMedium, pDocument, pMedStrm, eNach );
304
305 return eRet;
306 }
307
308
309
310