1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: excel.cxx,v $
10 * $Revision: 1.26.32.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include <sfx2/docfile.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <sfx2/app.hxx>
37 #include <sot/storage.hxx>
38 #include <sot/exchange.hxx>
39 #include <tools/globname.hxx>
40 #include <comphelper/mediadescriptor.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/beans/NamedValue.hpp>
43 #include <com/sun/star/document/XFilter.hpp>
44 #include <com/sun/star/document/XImporter.hpp>
45 #include "scitems.hxx"
46 #include <svtools/stritem.hxx>
48 #include "document.hxx"
49 #include "xistream.hxx"
51 #include "scerrors.hxx"
54 #include "excimp8.hxx"
58 FltError
ScFormatFilterPluginImpl::ScImportExcel( SfxMedium
& rMedium
, ScDocument
* pDocument
, const EXCIMPFORMAT eFormat
)
60 // check the passed Calc document
61 DBG_ASSERT( pDocument
, "::ScImportExcel - no document" );
62 if( !pDocument
) return eERR_INTERN
; // should not happen
64 /* Import all BIFF versions regardless on eFormat, needed for import of
65 external cells (file type detection returns Excel4.0). */
66 if( (eFormat
!= EIF_AUTO
) && (eFormat
!= EIF_BIFF_LE4
) && (eFormat
!= EIF_BIFF5
) && (eFormat
!= EIF_BIFF8
) )
68 DBG_ERRORFILE( "::ScImportExcel - wrong file format specification" );
72 // check the input stream from medium
73 SvStream
* pMedStrm
= rMedium
.GetInStream();
74 DBG_ASSERT( pMedStrm
, "::ScImportExcel - medium without input stream" );
75 if( !pMedStrm
) return eERR_OPEN
; // should not happen
77 #if OSL_DEBUG_LEVEL > 0
78 using namespace ::com::sun::star
;
79 using namespace ::comphelper
;
81 /* Environment variable "OOO_OOXBIFFFILTER":
82 - "1" = use new OOX filter for import;
83 - undef/other = use old sc filter for import (OOX only as file dumper). */
84 const sal_Char
* pcFileName
= ::getenv( "OOO_OOXBIFFFILTER" );
85 bool bUseOoxFilter
= pcFileName
&& (*pcFileName
== '1') && (*(pcFileName
+ 1) == 0);
86 if( SfxObjectShell
* pDocShell
= pDocument
->GetDocumentShell() ) try
88 uno::Reference
< lang::XComponent
> xComponent( pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
90 uno::Sequence
< beans::NamedValue
> aArgSeq( 1 );
91 aArgSeq
[ 0 ].Name
= CREATE_OUSTRING( "UseBiffFilter" );
92 aArgSeq
[ 0 ].Value
<<= bUseOoxFilter
;
94 uno::Sequence
< uno::Any
> aArgs( 2 );
95 aArgs
[ 0 ] <<= getProcessServiceFactory();
96 aArgs
[ 1 ] <<= aArgSeq
;
97 uno::Reference
< document::XImporter
> xImporter( ScfApiHelper::CreateInstanceWithArgs(
98 CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ), aArgs
), uno::UNO_QUERY_THROW
);
99 xImporter
->setTargetDocument( xComponent
);
101 MediaDescriptor aMediaDesc
;
102 SfxItemSet
* pItemSet
= rMedium
.GetItemSet();
105 if( const SfxStringItem
* pItem
= static_cast< const SfxStringItem
* >( pItemSet
->GetItem( SID_FILE_NAME
) ) )
106 aMediaDesc
[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pItem
->GetValue() );
107 if( const SfxStringItem
* pItem
= static_cast< const SfxStringItem
* >( pItemSet
->GetItem( SID_PASSWORD
) ) )
108 aMediaDesc
[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pItem
->GetValue() );
110 aMediaDesc
[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium
.GetInputStream();
111 aMediaDesc
[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium
.GetInteractionHandler();
114 uno::Reference
< document::XFilter
> xFilter( xImporter
, uno::UNO_QUERY_THROW
);
115 bool bResult
= xFilter
->filter( aMediaDesc
.getAsConstPropertyValueList() );
117 // if filter returns false, document is invalid, or dumper has disabled import -> exit here
119 return ERRCODE_ABORT
;
121 // if OOX filter has been used, exit with OK code
125 catch( uno::Exception
& )
128 return ERRCODE_ABORT
;
129 // else ignore exception and import the document with this filter
133 SvStream
* pBookStrm
= 0; // The "Book"/"Workbook" stream containing main data.
134 XclBiff eBiff
= EXC_BIFF_UNKNOWN
; // The BIFF version of the main stream.
136 // try to open an OLE storage
137 SotStorageRef xRootStrg
;
138 SotStorageStreamRef xStrgStrm
;
139 if( SotStorage::IsStorageFile( pMedStrm
) )
141 xRootStrg
= new SotStorage( pMedStrm
, FALSE
);
142 if( xRootStrg
->GetError() )
146 // try to open "Book" or "Workbook" stream in OLE storage
149 // try to open the "Book" stream
150 SotStorageStreamRef xBookStrm
= ScfTools::OpenStorageStreamRead( xRootStrg
, EXC_STREAM_BOOK
);
151 XclBiff eBookBiff
= xBookStrm
.Is() ? XclImpStream::DetectBiffVersion( *xBookStrm
) : EXC_BIFF_UNKNOWN
;
153 // try to open the "Workbook" stream
154 SotStorageStreamRef xWorkbookStrm
= ScfTools::OpenStorageStreamRead( xRootStrg
, EXC_STREAM_WORKBOOK
);
155 XclBiff eWorkbookBiff
= xWorkbookStrm
.Is() ? XclImpStream::DetectBiffVersion( *xWorkbookStrm
) : EXC_BIFF_UNKNOWN
;
157 // decide which stream to use
158 if( (eWorkbookBiff
!= EXC_BIFF_UNKNOWN
) && ((eBookBiff
== EXC_BIFF_UNKNOWN
) || (eWorkbookBiff
> eBookBiff
)) )
160 /* Only "Workbook" stream exists; or both streams exist,
161 and "Workbook" has higher BIFF version than "Book" stream. */
162 xStrgStrm
= xWorkbookStrm
;
163 eBiff
= eWorkbookBiff
;
165 else if( eBookBiff
!= EXC_BIFF_UNKNOWN
)
167 /* Only "Book" stream exists; or both streams exist,
168 and "Book" has higher BIFF version than "Workbook" stream. */
169 xStrgStrm
= xBookStrm
;
173 pBookStrm
= xStrgStrm
;
176 // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
179 eBiff
= XclImpStream::DetectBiffVersion( *pMedStrm
);
180 if( eBiff
!= EXC_BIFF_UNKNOWN
)
181 pBookStrm
= pMedStrm
;
184 // try to import the file
185 FltError eRet
= eERR_UNKN_BIFF
;
188 pBookStrm
->SetBufferSize( 0x8000 ); // still needed?
190 XclImpRootData
aImpData( eBiff
, rMedium
, xRootStrg
, *pDocument
, RTL_TEXTENCODING_MS_1252
);
191 ::std::auto_ptr
< ImportExcel
> xFilter
;
198 xFilter
.reset( new ImportExcel( aImpData
, *pBookStrm
) );
201 xFilter
.reset( new ImportExcel8( aImpData
, *pBookStrm
) );
203 default: DBG_ERROR_BIFF();
206 eRet
= xFilter
.get() ? xFilter
->Read() : eERR_INTERN
;
213 static FltError
lcl_ExportExcelBiff( SfxMedium
& rMedium
, ScDocument
*pDocument
,
214 SvStream
* pMedStrm
, BOOL bBiff8
, CharSet eNach
)
216 // try to open an OLE storage
217 SotStorageRef xRootStrg
= new SotStorage( pMedStrm
, FALSE
);
218 if( xRootStrg
->GetError() ) return eERR_OPEN
;
220 // create BIFF dependent strings
221 String aStrmName
, aClipName
, aClassName
;
224 aStrmName
= EXC_STREAM_WORKBOOK
;
225 aClipName
= CREATE_STRING( "Biff8" );
226 aClassName
= CREATE_STRING( "Microsoft Excel 97-Tabelle" );
230 aStrmName
= EXC_STREAM_BOOK
;
231 aClipName
= CREATE_STRING( "Biff5" );
232 aClassName
= CREATE_STRING( "Microsoft Excel 5.0-Tabelle" );
235 // open the "Book"/"Workbook" stream
236 SotStorageStreamRef xStrgStrm
= ScfTools::OpenStorageStreamWrite( xRootStrg
, aStrmName
);
237 if( !xStrgStrm
.Is() || xStrgStrm
->GetError() ) return eERR_OPEN
;
239 xStrgStrm
->SetBufferSize( 0x8000 ); // still needed?
241 FltError eRet
= eERR_UNKN_BIFF
;
242 XclExpRootData
aExpData( bBiff8
? EXC_BIFF8
: EXC_BIFF5
, rMedium
, xRootStrg
, *pDocument
, eNach
);
245 ExportBiff8
aFilter( aExpData
, *xStrgStrm
);
246 eRet
= aFilter
.Write();
250 ExportBiff5
aFilter( aExpData
, *xStrgStrm
);
251 eRet
= aFilter
.Write();
254 if( eRet
== eERR_RNGOVRFLW
)
255 eRet
= SCWARN_EXPORT_MAXROW
;
257 SvGlobalName
aGlobName( 0x00020810, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
258 sal_uInt32 nClip
= SotExchange::RegisterFormatName( aClipName
);
259 xRootStrg
->SetClass( aGlobName
, nClip
, aClassName
);
267 static FltError
lcl_ExportExcel2007Xml( SfxMedium
& rMedium
, ScDocument
*pDocument
,
268 SvStream
* pMedStrm
, CharSet eNach
)
270 SotStorageRef xRootStrg
= (SotStorage
*) 0;
272 XclExpRootData
aExpData( EXC_BIFF8
, rMedium
, xRootStrg
, *pDocument
, eNach
);
273 aExpData
.meOutput
= EXC_OUTPUT_XML_2007
;
275 ExportXml2007
aFilter( aExpData
, *pMedStrm
);
277 FltError eRet
= aFilter
.Write();
282 FltError
ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium
& rMedium
, ScDocument
*pDocument
,
283 ExportFormatExcel eFormat
, CharSet eNach
)
285 if( eFormat
!= ExpBiff5
&& eFormat
!= ExpBiff8
&& eFormat
!= Exp2007Xml
)
288 // check the passed Calc document
289 DBG_ASSERT( pDocument
, "::ScImportExcel - no document" );
290 if( !pDocument
) return eERR_INTERN
; // should not happen
292 // check the output stream from medium
293 SvStream
* pMedStrm
= rMedium
.GetOutStream();
294 DBG_ASSERT( pMedStrm
, "::ScExportExcel5 - medium without output stream" );
295 if( !pMedStrm
) return eERR_OPEN
; // should not happen
297 FltError eRet
= eERR_UNKN_BIFF
;
298 if( eFormat
== ExpBiff5
|| eFormat
== ExpBiff8
)
299 eRet
= lcl_ExportExcelBiff( rMedium
, pDocument
, pMedStrm
, eFormat
== ExpBiff8
, eNach
);
300 else if( eFormat
== Exp2007Xml
)
301 eRet
= lcl_ExportExcel2007Xml( rMedium
, pDocument
, pMedStrm
, eNach
);