blob: 6cb35c667a802231b4d400a1e3233695bd793a52 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include <sfx2/docfile.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/app.hxx>
#include <sfx2/frame.hxx>
#include <sfx2/request.hxx>
#include <sot/storage.hxx>
#include <sot/exchange.hxx>
#include <tools/globname.hxx>
#include <comphelper/mediadescriptor.hxx>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/document/XFilter.hpp>
#include <com/sun/star/document/XImporter.hpp>
#include "scitems.hxx"
#include <svl/stritem.hxx>
#include "filter.hxx"
#include "document.hxx"
#include "xistream.hxx"
#include "scerrors.hxx"
#include "root.hxx"
#include "imp_op.hxx"
#include "excimp8.hxx"
#include "exp_op.hxx"
FltError ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat )
{
// check the passed Calc document
DBG_ASSERT( pDocument, "::ScImportExcel - no document" );
if( !pDocument ) return eERR_INTERN; // should not happen
/* Import all BIFF versions regardless on eFormat, needed for import of
external cells (file type detection returns Excel4.0). */
if( (eFormat != EIF_AUTO) && (eFormat != EIF_BIFF_LE4) && (eFormat != EIF_BIFF5) && (eFormat != EIF_BIFF8) )
{
DBG_ERRORFILE( "::ScImportExcel - wrong file format specification" );
return eERR_FORMAT;
}
// check the input stream from medium
SvStream* pMedStrm = rMedium.GetInStream();
DBG_ASSERT( pMedStrm, "::ScImportExcel - medium without input stream" );
if( !pMedStrm ) return eERR_OPEN; // should not happen
#if OSL_DEBUG_LEVEL > 0
using namespace ::com::sun::star;
using namespace ::comphelper;
/* Environment variable "OOO_OOXBIFFFILTER":
- "1" = use new OOX filter for import;
- undef/other = use old sc filter for import (OOX only as file dumper). */
const sal_Char* pcFileName = ::getenv( "OOO_OOXBIFFFILTER" );
bool bUseOoxFilter = pcFileName && (*pcFileName == '1') && (*(pcFileName + 1) == 0);
if( SfxObjectShell* pDocShell = pDocument->GetDocumentShell() ) try
{
uno::Reference< lang::XComponent > xComponent( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
uno::Sequence< beans::NamedValue > aArgSeq( 1 );
aArgSeq[ 0 ].Name = CREATE_OUSTRING( "UseBiffFilter" );
aArgSeq[ 0 ].Value <<= bUseOoxFilter;
uno::Sequence< uno::Any > aArgs( 2 );
aArgs[ 0 ] <<= getProcessServiceFactory();
aArgs[ 1 ] <<= aArgSeq;
uno::Reference< document::XImporter > xImporter( ScfApiHelper::CreateInstanceWithArgs(
CREATE_OUSTRING( "com.sun.star.comp.oox.xls.ExcelBiffFilter" ), aArgs ), uno::UNO_QUERY_THROW );
xImporter->setTargetDocument( xComponent );
MediaDescriptor aMediaDesc;
SfxItemSet* pItemSet = rMedium.GetItemSet();
if( pItemSet )
{
SFX_ITEMSET_ARG( pItemSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False);
if( pFileNameItem )
aMediaDesc[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pFileNameItem->GetValue() );
SFX_ITEMSET_ARG( pItemSet, pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False);
if( pPasswordItem )
aMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pPasswordItem->GetValue() );
SFX_ITEMSET_ARG( pItemSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False);
if( pEncryptionDataItem )
aMediaDesc[ MediaDescriptor::PROP_ENCRYPTIONDATA() ] = pEncryptionDataItem->GetValue();
}
aMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium.GetInputStream();
aMediaDesc[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium.GetInteractionHandler();
// call the filter
uno::Reference< document::XFilter > xFilter( xImporter, uno::UNO_QUERY_THROW );
bool bResult = xFilter->filter( aMediaDesc.getAsConstPropertyValueList() );
// if filter returns false, document is invalid, or dumper has disabled import -> exit here
if( !bResult )
return ERRCODE_ABORT;
// if OOX filter has been used, exit with OK code
if( bUseOoxFilter )
return eERR_OK;
}
catch( uno::Exception& )
{
if( bUseOoxFilter )
return ERRCODE_ABORT;
// else ignore exception and import the document with this filter
}
#endif
SvStream* pBookStrm = 0; // The "Book"/"Workbook" stream containing main data.
XclBiff eBiff = EXC_BIFF_UNKNOWN; // The BIFF version of the main stream.
// try to open an OLE storage
SotStorageRef xRootStrg;
SotStorageStreamRef xStrgStrm;
if( SotStorage::IsStorageFile( pMedStrm ) )
{
xRootStrg = new SotStorage( pMedStrm, sal_False );
if( xRootStrg->GetError() )
xRootStrg = 0;
}
// try to open "Book" or "Workbook" stream in OLE storage
if( xRootStrg.Is() )
{
// try to open the "Book" stream
SotStorageStreamRef xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK );
XclBiff eBookBiff = xBookStrm.Is() ? XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN;
// try to open the "Workbook" stream
SotStorageStreamRef xWorkbookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_WORKBOOK );
XclBiff eWorkbookBiff = xWorkbookStrm.Is() ? XclImpStream::DetectBiffVersion( *xWorkbookStrm ) : EXC_BIFF_UNKNOWN;
// decide which stream to use
if( (eWorkbookBiff != EXC_BIFF_UNKNOWN) && ((eBookBiff == EXC_BIFF_UNKNOWN) || (eWorkbookBiff > eBookBiff)) )
{
/* Only "Workbook" stream exists; or both streams exist,
and "Workbook" has higher BIFF version than "Book" stream. */
xStrgStrm = xWorkbookStrm;
eBiff = eWorkbookBiff;
}
else if( eBookBiff != EXC_BIFF_UNKNOWN )
{
/* Only "Book" stream exists; or both streams exist,
and "Book" has higher BIFF version than "Workbook" stream. */
xStrgStrm = xBookStrm;
eBiff = eBookBiff;
}
pBookStrm = xStrgStrm;
}
// no "Book" or "Workbook" stream found, try plain input stream from medium (even for BIFF5+)
if( !pBookStrm )
{
eBiff = XclImpStream::DetectBiffVersion( *pMedStrm );
if( eBiff != EXC_BIFF_UNKNOWN )
pBookStrm = pMedStrm;
}
// try to import the file
FltError eRet = eERR_UNKN_BIFF;
if( pBookStrm )
{
pBookStrm->SetBufferSize( 0x8000 ); // still needed?
XclImpRootData aImpData( eBiff, rMedium, xRootStrg, *pDocument, RTL_TEXTENCODING_MS_1252 );
::std::auto_ptr< ImportExcel > xFilter;
switch( eBiff )
{
case EXC_BIFF2:
case EXC_BIFF3:
case EXC_BIFF4:
case EXC_BIFF5:
xFilter.reset( new ImportExcel( aImpData, *pBookStrm ) );
break;
case EXC_BIFF8:
xFilter.reset( new ImportExcel8( aImpData, *pBookStrm ) );
break;
default: DBG_ERROR_BIFF();
}
eRet = xFilter.get() ? xFilter->Read() : eERR_INTERN;
}
return eRet;
}
static FltError lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument,
SvStream* pMedStrm, sal_Bool bBiff8, CharSet eNach )
{
// try to open an OLE storage
SotStorageRef xRootStrg = new SotStorage( pMedStrm, sal_False );
if( xRootStrg->GetError() ) return eERR_OPEN;
// create BIFF dependent strings
String aStrmName, aClipName, aClassName;
if( bBiff8 )
{
aStrmName = EXC_STREAM_WORKBOOK;
aClipName = CREATE_STRING( "Biff8" );
aClassName = CREATE_STRING( "Microsoft Excel 97-Tabelle" );
}
else
{
aStrmName = EXC_STREAM_BOOK;
aClipName = CREATE_STRING( "Biff5" );
aClassName = CREATE_STRING( "Microsoft Excel 5.0-Tabelle" );
}
// open the "Book"/"Workbook" stream
SotStorageStreamRef xStrgStrm = ScfTools::OpenStorageStreamWrite( xRootStrg, aStrmName );
if( !xStrgStrm.Is() || xStrgStrm->GetError() ) return eERR_OPEN;
xStrgStrm->SetBufferSize( 0x8000 ); // still needed?
FltError eRet = eERR_UNKN_BIFF;
XclExpRootData aExpData( bBiff8 ? EXC_BIFF8 : EXC_BIFF5, rMedium, xRootStrg, *pDocument, eNach );
if ( bBiff8 )
{
ExportBiff8 aFilter( aExpData, *xStrgStrm );
eRet = aFilter.Write();
}
else
{
ExportBiff5 aFilter( aExpData, *xStrgStrm );
eRet = aFilter.Write();
}
if( eRet == eERR_RNGOVRFLW )
eRet = SCWARN_EXPORT_MAXROW;
SvGlobalName aGlobName( 0x00020810, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
sal_uInt32 nClip = SotExchange::RegisterFormatName( aClipName );
xRootStrg->SetClass( aGlobName, nClip, aClassName );
xStrgStrm->Commit();
xRootStrg->Commit();
return eRet;
}
static FltError lcl_ExportExcel2007Xml( SfxMedium& rMedium, ScDocument *pDocument,
SvStream* pMedStrm, CharSet eNach )
{
SotStorageRef xRootStrg = (SotStorage*) 0;
XclExpRootData aExpData( EXC_BIFF8, rMedium, xRootStrg, *pDocument, eNach );
aExpData.meOutput = EXC_OUTPUT_XML_2007;
ExportXml2007 aFilter( aExpData, *pMedStrm );
FltError eRet = aFilter.Write();
return eRet;
}
FltError ScFormatFilterPluginImpl::ScExportExcel5( SfxMedium& rMedium, ScDocument *pDocument,
ExportFormatExcel eFormat, CharSet eNach )
{
if( eFormat != ExpBiff5 && eFormat != ExpBiff8 && eFormat != Exp2007Xml )
return eERR_NI;
// check the passed Calc document
DBG_ASSERT( pDocument, "::ScImportExcel - no document" );
if( !pDocument ) return eERR_INTERN; // should not happen
// check the output stream from medium
SvStream* pMedStrm = rMedium.GetOutStream();
DBG_ASSERT( pMedStrm, "::ScExportExcel5 - medium without output stream" );
if( !pMedStrm ) return eERR_OPEN; // should not happen
FltError eRet = eERR_UNKN_BIFF;
if( eFormat == ExpBiff5 || eFormat == ExpBiff8 )
eRet = lcl_ExportExcelBiff( rMedium, pDocument, pMedStrm, eFormat == ExpBiff8, eNach );
else if( eFormat == Exp2007Xml )
eRet = lcl_ExportExcel2007Xml( rMedium, pDocument, pMedStrm, eNach );
return eRet;
}