merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / excel.cxx
blob8365ef0db3f9ce59357e97504767524d81fb1dd3
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>
47 #include "filter.hxx"
48 #include "document.hxx"
49 #include "xistream.hxx"
51 #include "scerrors.hxx"
52 #include "root.hxx"
53 #include "imp_op.hxx"
54 #include "excimp8.hxx"
55 #include "exp_op.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" );
69 return eERR_FORMAT;
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();
103 if( pItemSet )
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();
113 // call the filter
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
118 if( !bResult )
119 return ERRCODE_ABORT;
121 // if OOX filter has been used, exit with OK code
122 if( bUseOoxFilter )
123 return eERR_OK;
125 catch( uno::Exception& )
127 if( bUseOoxFilter )
128 return ERRCODE_ABORT;
129 // else ignore exception and import the document with this filter
131 #endif
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() )
143 xRootStrg = 0;
146 // try to open "Book" or "Workbook" stream in OLE storage
147 if( xRootStrg.Is() )
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;
170 eBiff = eBookBiff;
173 pBookStrm = xStrgStrm;
176 // no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
177 if( !pBookStrm )
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;
186 if( pBookStrm )
188 pBookStrm->SetBufferSize( 0x8000 ); // still needed?
190 XclImpRootData aImpData( eBiff, rMedium, xRootStrg, *pDocument, RTL_TEXTENCODING_MS_1252 );
191 ::std::auto_ptr< ImportExcel > xFilter;
192 switch( eBiff )
194 case EXC_BIFF2:
195 case EXC_BIFF3:
196 case EXC_BIFF4:
197 case EXC_BIFF5:
198 xFilter.reset( new ImportExcel( aImpData, *pBookStrm ) );
199 break;
200 case EXC_BIFF8:
201 xFilter.reset( new ImportExcel8( aImpData, *pBookStrm ) );
202 break;
203 default: DBG_ERROR_BIFF();
206 eRet = xFilter.get() ? xFilter->Read() : eERR_INTERN;
209 return eRet;
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;
222 if( bBiff8 )
224 aStrmName = EXC_STREAM_WORKBOOK;
225 aClipName = CREATE_STRING( "Biff8" );
226 aClassName = CREATE_STRING( "Microsoft Excel 97-Tabelle" );
228 else
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 );
243 if ( bBiff8 )
245 ExportBiff8 aFilter( aExpData, *xStrgStrm );
246 eRet = aFilter.Write();
248 else
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 );
261 xStrgStrm->Commit();
262 xRootStrg->Commit();
264 return eRet;
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();
279 return eRet;
282 FltError ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium& rMedium, ScDocument *pDocument,
283 ExportFormatExcel eFormat, CharSet eNach )
285 if( eFormat != ExpBiff5 && eFormat != ExpBiff8 && eFormat != Exp2007Xml )
286 return eERR_NI;
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 );
303 return eRet;