1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
31 #include <document.hxx>
32 #include <xistream.hxx>
33 #include <xltools.hxx>
34 #include <docoptio.hxx>
37 #include <scerrors.hxx>
39 #include <excimp8.hxx>
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() )
77 // try to open "Book" or "Workbook" stream in OLE storage
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
;
104 pBookStrm
= xStrgStrm
.get();
107 // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
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
;
119 pBookStrm
->SetBufferSize( 0x8000 ); // still needed?
121 XclImpRootData
aImpData( eBiff
, rMedium
, xRootStrg
, *pDocument
, RTL_TEXTENCODING_MS_1252
);
122 std::unique_ptr
< ImportExcel
> xFilter
;
129 xFilter
.reset( new ImportExcel( aImpData
, *pBookStrm
) );
132 xFilter
.reset( new ImportExcel8( aImpData
, *pBookStrm
) );
134 default: DBG_ERROR_BIFF();
137 eRet
= xFilter
? xFilter
->Read() : SCERR_IMPORT_INTERNAL
;
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
;
154 aStrmName
= EXC_STREAM_WORKBOOK
;
156 aClassName
= "Microsoft Excel 97-Tabelle";
160 aStrmName
= EXC_STREAM_BOOK
;
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
);
175 ExportBiff8
aFilter( aExpData
, *xStrgStrm
);
176 eRet
= aFilter
.Write();
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
);
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
);
216 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportCalcRTF(SvStream
&rStream
)
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);
227 return ScFormatFilter::Get().ScImportRTF(rStream
, OUString(), &aDocument
, aRange
) == ERRCODE_NONE
;
230 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportXLS(SvStream
& rStream
)
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
);
249 rDoc
.EnableExecuteLink(false);
250 rDoc
.SetInsertingFromOtherDoc(true);
251 rDoc
.InitDrawLayer(xDocShell
.get());
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();
268 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportDIF(SvStream
&rStream
)
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: */