Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / excel.cxx
blobca87efc2988c3e27bc673b60068284a8d20ee958
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sfx2/docfile.hxx>
21 #include <sfx2/frame.hxx>
22 #include <sfx2/sfxsids.hrc>
23 #include <sot/storage.hxx>
24 #include <sot/exchange.hxx>
25 #include <filter/msfilter/classids.hxx>
26 #include <tools/globname.hxx>
27 #include <com/sun/star/ucb/ContentCreationException.hpp>
28 #include <unotools/streamwrap.hxx>
29 #include <osl/diagnose.h>
30 #include <filter.hxx>
31 #include <document.hxx>
32 #include <xistream.hxx>
33 #include <xltools.hxx>
34 #include <docoptio.hxx>
36 #include <docsh.hxx>
37 #include <scerrors.hxx>
38 #include <imp_op.hxx>
39 #include <excimp8.hxx>
40 #include <exp_op.hxx>
41 #include <scdll.hxx>
43 #include <memory>
45 ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat )
47 // check the passed Calc document
48 OSL_ENSURE( pDocument, "::ScImportExcel - no document" );
49 if( !pDocument ) return SCERR_IMPORT_INTERNAL; // should not happen
51 /* Import all BIFF versions regardless on eFormat, needed for import of
52 external cells (file type detection returns Excel4.0). */
53 if( (eFormat != EIF_AUTO) && (eFormat != EIF_BIFF_LE4) && (eFormat != EIF_BIFF5) && (eFormat != EIF_BIFF8) )
55 OSL_FAIL( "::ScImportExcel - wrong file format specification" );
56 return SCERR_IMPORT_FORMAT;
59 // check the input stream from medium
60 SvStream* pMedStrm = rMedium.GetInStream();
61 OSL_ENSURE( pMedStrm, "::ScImportExcel - medium without input stream" );
62 if( !pMedStrm ) return SCERR_IMPORT_OPEN; // should not happen
64 SvStream* pBookStrm = nullptr; // The "Book"/"Workbook" stream containing main data.
65 XclBiff eBiff = EXC_BIFF_UNKNOWN; // The BIFF version of the main stream.
67 // try to open an OLE storage
68 tools::SvRef<SotStorage> xRootStrg;
69 tools::SvRef<SotStorageStream> xStrgStrm;
70 if( SotStorage::IsStorageFile( pMedStrm ) )
72 xRootStrg = new SotStorage( pMedStrm, false );
73 if( xRootStrg->GetError() )
74 xRootStrg = nullptr;
77 // try to open "Book" or "Workbook" stream in OLE storage
78 if( xRootStrg.is() )
80 // try to open the "Book" stream
81 tools::SvRef<SotStorageStream> xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK );
82 XclBiff eBookBiff = xBookStrm.is() ? XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN;
84 // try to open the "Workbook" stream
85 tools::SvRef<SotStorageStream> xWorkbookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_WORKBOOK );
86 XclBiff eWorkbookBiff = xWorkbookStrm.is() ? XclImpStream::DetectBiffVersion( *xWorkbookStrm ) : EXC_BIFF_UNKNOWN;
88 // decide which stream to use
89 if( (eWorkbookBiff != EXC_BIFF_UNKNOWN) && ((eBookBiff == EXC_BIFF_UNKNOWN) || (eWorkbookBiff > eBookBiff)) )
91 /* Only "Workbook" stream exists; or both streams exist,
92 and "Workbook" has higher BIFF version than "Book" stream. */
93 xStrgStrm = xWorkbookStrm;
94 eBiff = eWorkbookBiff;
96 else if( eBookBiff != EXC_BIFF_UNKNOWN )
98 /* Only "Book" stream exists; or both streams exist,
99 and "Book" has higher BIFF version than "Workbook" stream. */
100 xStrgStrm = xBookStrm;
101 eBiff = eBookBiff;
104 pBookStrm = xStrgStrm.get();
107 // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
108 if( !pBookStrm )
110 eBiff = XclImpStream::DetectBiffVersion( *pMedStrm );
111 if( eBiff != EXC_BIFF_UNKNOWN )
112 pBookStrm = pMedStrm;
115 // try to import the file
116 ErrCode eRet = SCERR_IMPORT_UNKNOWN_BIFF;
117 if( pBookStrm )
119 pBookStrm->SetBufferSize( 0x8000 ); // still needed?
121 XclImpRootData aImpData( eBiff, rMedium, xRootStrg, *pDocument, RTL_TEXTENCODING_MS_1252 );
122 std::unique_ptr< ImportExcel > xFilter;
123 switch( eBiff )
125 case EXC_BIFF2:
126 case EXC_BIFF3:
127 case EXC_BIFF4:
128 case EXC_BIFF5:
129 xFilter.reset( new ImportExcel( aImpData, *pBookStrm ) );
130 break;
131 case EXC_BIFF8:
132 xFilter.reset( new ImportExcel8( aImpData, *pBookStrm ) );
133 break;
134 default: DBG_ERROR_BIFF();
137 eRet = xFilter ? xFilter->Read() : SCERR_IMPORT_INTERNAL;
140 return eRet;
143 static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
144 SvStream* pMedStrm, bool bBiff8, rtl_TextEncoding eNach )
146 // try to open an OLE storage
147 tools::SvRef<SotStorage> xRootStrg = new SotStorage( pMedStrm, false );
148 if( xRootStrg->GetError() ) return SCERR_IMPORT_OPEN;
150 // create BIFF dependent strings
151 OUString aStrmName, aClipName, aClassName;
152 if( bBiff8 )
154 aStrmName = EXC_STREAM_WORKBOOK;
155 aClipName = "Biff8";
156 aClassName = "Microsoft Excel 97-Tabelle";
158 else
160 aStrmName = EXC_STREAM_BOOK;
161 aClipName = "Biff5";
162 aClassName = "Microsoft Excel 5.0-Tabelle";
165 // open the "Book"/"Workbook" stream
166 tools::SvRef<SotStorageStream> xStrgStrm = ScfTools::OpenStorageStreamWrite( xRootStrg, aStrmName );
167 if( !xStrgStrm.is() || xStrgStrm->GetError() ) return SCERR_IMPORT_OPEN;
169 xStrgStrm->SetBufferSize( 0x8000 ); // still needed?
171 ErrCode eRet = SCERR_IMPORT_UNKNOWN_BIFF;
172 XclExpRootData aExpData( bBiff8 ? EXC_BIFF8 : EXC_BIFF5, rMedium, xRootStrg, *pDocument, eNach );
173 if ( bBiff8 )
175 ExportBiff8 aFilter( aExpData, *xStrgStrm );
176 eRet = aFilter.Write();
178 else
180 ExportBiff5 aFilter( aExpData, *xStrgStrm );
181 eRet = aFilter.Write();
184 if( eRet == SCWARN_IMPORT_RANGE_OVERFLOW )
185 eRet = SCWARN_EXPORT_MAXROW;
187 SvGlobalName aGlobName(MSO_EXCEL5_CLASSID);
188 SotClipboardFormatId nClip = SotExchange::RegisterFormatName( aClipName );
189 xRootStrg->SetClass( aGlobName, nClip, aClassName );
191 xStrgStrm->Commit();
192 xRootStrg->Commit();
194 return eRet;
197 ErrCode ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium& rMedium, ScDocument *pDocument,
198 ExportFormatExcel eFormat, rtl_TextEncoding eNach )
200 if( eFormat != ExpBiff5 && eFormat != ExpBiff8 )
201 return SCERR_IMPORT_NI;
203 // check the passed Calc document
204 OSL_ENSURE( pDocument, "::ScExportExcel5 - no document" );
205 if( !pDocument ) return SCERR_IMPORT_INTERNAL; // should not happen
207 // check the output stream from medium
208 SvStream* pMedStrm = rMedium.GetOutStream();
209 OSL_ENSURE( pMedStrm, "::ScExportExcel5 - medium without output stream" );
210 if( !pMedStrm ) return SCERR_IMPORT_OPEN; // should not happen
212 ErrCode eRet = lcl_ExportExcelBiff(rMedium, pDocument, pMedStrm, eFormat == ExpBiff8, eNach);
213 return eRet;
216 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportCalcRTF(SvStream &rStream)
218 ScDLL::Init();
219 ScDocument aDocument;
220 ScDocOptions aDocOpt = aDocument.GetDocOptions();
221 aDocOpt.SetLookUpColRowNames(false);
222 aDocument.SetDocOptions(aDocOpt);
223 aDocument.MakeTable(0);
224 aDocument.EnableExecuteLink(false);
225 aDocument.SetInsertingFromOtherDoc(true);
226 ScRange aRange;
227 return ScFormatFilter::Get().ScImportRTF(rStream, OUString(), &aDocument, aRange) == ERRCODE_NONE;
230 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportXLS(SvStream& rStream)
232 ScDLL::Init();
233 SfxMedium aMedium;
234 css::uno::Reference<css::io::XInputStream> xStm(new utl::OInputStreamWrapper(rStream));
235 aMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_INPUTSTREAM, css::uno::makeAny(xStm)));
237 ScDocShellRef xDocShell = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT |
238 SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS |
239 SfxModelFlags::DISABLE_DOCUMENT_RECOVERY);
241 xDocShell->DoInitNew();
243 ScDocument& rDoc = xDocShell->GetDocument();
245 ScDocOptions aDocOpt = rDoc.GetDocOptions();
246 aDocOpt.SetLookUpColRowNames(false);
247 rDoc.SetDocOptions(aDocOpt);
248 rDoc.MakeTable(0);
249 rDoc.EnableExecuteLink(false);
250 rDoc.SetInsertingFromOtherDoc(true);
251 rDoc.InitDrawLayer(xDocShell.get());
252 bool bRet(false);
255 bRet = ScFormatFilter::Get().ScImportExcel(aMedium, &rDoc, EIF_AUTO) == ERRCODE_NONE;
257 catch (const css::ucb::ContentCreationException&)
260 catch (const std::out_of_range&)
263 xDocShell->DoClose();
264 xDocShell.clear();
265 return bRet;
268 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportDIF(SvStream &rStream)
270 ScDLL::Init();
271 ScDocument aDocument;
272 ScDocOptions aDocOpt = aDocument.GetDocOptions();
273 aDocOpt.SetLookUpColRowNames(false);
274 aDocument.SetDocOptions(aDocOpt);
275 aDocument.MakeTable(0);
276 aDocument.EnableExecuteLink(false);
277 aDocument.SetInsertingFromOtherDoc(true);
278 return ScFormatFilter::Get().ScImportDif(rStream, &aDocument, ScAddress(0, 0, 0), RTL_TEXTENCODING_IBM_850) == ERRCODE_NONE;
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */