| /************************************************************** |
| * |
| * 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; |
| } |
| |
| |
| |