1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #include "oox/xls/worksheetbuffer.hxx" 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir #include <com/sun/star/container/XIndexAccess.hpp> 31*cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 32*cdf0e10cSrcweir #include <com/sun/star/container/XNamed.hpp> 33*cdf0e10cSrcweir #include <com/sun/star/sheet/XExternalSheetName.hpp> 34*cdf0e10cSrcweir #include <com/sun/star/sheet/XSheetLinkable.hpp> 35*cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 36*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 37*cdf0e10cSrcweir #include "oox/core/filterbase.hxx" 38*cdf0e10cSrcweir #include "oox/helper/attributelist.hxx" 39*cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx" 40*cdf0e10cSrcweir #include "oox/helper/propertyset.hxx" 41*cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx" 42*cdf0e10cSrcweir #include "oox/xls/excelhandlers.hxx" 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir namespace oox { 45*cdf0e10cSrcweir namespace xls { 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir // ============================================================================ 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir using namespace ::com::sun::star::container; 50*cdf0e10cSrcweir using namespace ::com::sun::star::sheet; 51*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir using ::rtl::OUString; 54*cdf0e10cSrcweir using ::rtl::OUStringBuffer; 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir // ============================================================================ 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir SheetInfoModel::SheetInfoModel() : 59*cdf0e10cSrcweir mnBiffHandle( -1 ), 60*cdf0e10cSrcweir mnSheetId( -1 ), 61*cdf0e10cSrcweir mnState( XML_visible ) 62*cdf0e10cSrcweir { 63*cdf0e10cSrcweir } 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir // ============================================================================ 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir WorksheetBuffer::WorksheetBuffer( const WorkbookHelper& rHelper ) : 68*cdf0e10cSrcweir WorkbookHelper( rHelper ) 69*cdf0e10cSrcweir { 70*cdf0e10cSrcweir } 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir /*static*/ OUString WorksheetBuffer::getBaseFileName( const OUString& rUrl ) 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir sal_Int32 nFileNamePos = ::std::max< sal_Int32 >( rUrl.lastIndexOf( '/' ) + 1, 0 ); 75*cdf0e10cSrcweir sal_Int32 nExtPos = rUrl.lastIndexOf( '.' ); 76*cdf0e10cSrcweir if( nExtPos <= nFileNamePos ) nExtPos = rUrl.getLength(); 77*cdf0e10cSrcweir return rUrl.copy( nFileNamePos, nExtPos - nFileNamePos ); 78*cdf0e10cSrcweir } 79*cdf0e10cSrcweir 80*cdf0e10cSrcweir void WorksheetBuffer::initializeSingleSheet() 81*cdf0e10cSrcweir { 82*cdf0e10cSrcweir OSL_ENSURE( maSheetInfos.empty(), "WorksheetBuffer::initializeSingleSheet - invalid call" ); 83*cdf0e10cSrcweir SheetInfoModel aModel; 84*cdf0e10cSrcweir aModel.maName = getBaseFileName( getBaseFilter().getFileUrl() ); 85*cdf0e10cSrcweir insertSheet( aModel ); 86*cdf0e10cSrcweir } 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir void WorksheetBuffer::importSheet( const AttributeList& rAttribs ) 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir SheetInfoModel aModel; 91*cdf0e10cSrcweir aModel.maRelId = rAttribs.getString( R_TOKEN( id ), OUString() ); 92*cdf0e10cSrcweir aModel.maName = rAttribs.getXString( XML_name, OUString() ); 93*cdf0e10cSrcweir aModel.mnSheetId = rAttribs.getInteger( XML_sheetId, -1 ); 94*cdf0e10cSrcweir aModel.mnState = rAttribs.getToken( XML_state, XML_visible ); 95*cdf0e10cSrcweir insertSheet( aModel ); 96*cdf0e10cSrcweir } 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir void WorksheetBuffer::importSheet( SequenceInputStream& rStrm ) 99*cdf0e10cSrcweir { 100*cdf0e10cSrcweir sal_Int32 nState; 101*cdf0e10cSrcweir SheetInfoModel aModel; 102*cdf0e10cSrcweir rStrm >> nState >> aModel.mnSheetId >> aModel.maRelId >> aModel.maName; 103*cdf0e10cSrcweir static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden }; 104*cdf0e10cSrcweir aModel.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible ); 105*cdf0e10cSrcweir insertSheet( aModel ); 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir void WorksheetBuffer::importSheet( BiffInputStream& rStrm ) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir SheetInfoModel aModel; 111*cdf0e10cSrcweir if( getBiff() >= BIFF5 ) 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir rStrm.enableDecoder( false ); 114*cdf0e10cSrcweir aModel.mnBiffHandle = rStrm.readuInt32(); 115*cdf0e10cSrcweir rStrm.enableDecoder( true ); 116*cdf0e10cSrcweir sal_uInt16 nState = rStrm.readuInt16(); 117*cdf0e10cSrcweir static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden }; 118*cdf0e10cSrcweir aModel.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible ); 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir aModel.maName = (getBiff() == BIFF8) ? 121*cdf0e10cSrcweir rStrm.readUniStringBody( rStrm.readuInt8() ) : 122*cdf0e10cSrcweir rStrm.readByteStringUC( false, getTextEncoding() ); 123*cdf0e10cSrcweir insertSheet( aModel ); 124*cdf0e10cSrcweir } 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir sal_Int16 WorksheetBuffer::insertEmptySheet( const OUString& rPreferredName, bool bVisible ) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir return createSheet( rPreferredName, SAL_MAX_INT32, bVisible ).first; 129*cdf0e10cSrcweir } 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir sal_Int32 WorksheetBuffer::getWorksheetCount() const 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir return static_cast< sal_Int32 >( maSheetInfos.size() ); 134*cdf0e10cSrcweir } 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir OUString WorksheetBuffer::getWorksheetRelId( sal_Int32 nWorksheet ) const 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get(); 139*cdf0e10cSrcweir return pSheetInfo ? pSheetInfo->maRelId : OUString(); 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir sal_Int64 WorksheetBuffer::getBiffRecordHandle( sal_Int32 nWorksheet ) const 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get(); 145*cdf0e10cSrcweir return pSheetInfo ? pSheetInfo->mnBiffHandle : -1; 146*cdf0e10cSrcweir } 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir sal_Int16 WorksheetBuffer::getCalcSheetIndex( sal_Int32 nWorksheet ) const 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get(); 151*cdf0e10cSrcweir return pSheetInfo ? pSheetInfo->mnCalcSheet : -1; 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir OUString WorksheetBuffer::getCalcSheetName( sal_Int32 nWorksheet ) const 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get(); 157*cdf0e10cSrcweir return pSheetInfo ? pSheetInfo->maCalcName : OUString(); 158*cdf0e10cSrcweir } 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir sal_Int16 WorksheetBuffer::getCalcSheetIndex( const OUString& rWorksheetName ) const 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir const SheetInfo* pSheetInfo = maSheetInfosByName.get( rWorksheetName ).get(); 163*cdf0e10cSrcweir return pSheetInfo ? pSheetInfo->mnCalcSheet : -1; 164*cdf0e10cSrcweir } 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir OUString WorksheetBuffer::getCalcSheetName( const OUString& rWorksheetName ) const 167*cdf0e10cSrcweir { 168*cdf0e10cSrcweir if( const SheetInfo* pSheetInfo = maSheetInfosByName.get( rWorksheetName ).get() ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir bool bIsQuoted = pSheetInfo->maName != rWorksheetName; 171*cdf0e10cSrcweir return bIsQuoted ? pSheetInfo->maCalcQuotedName : pSheetInfo->maCalcName; 172*cdf0e10cSrcweir } 173*cdf0e10cSrcweir return OUString(); 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir // private -------------------------------------------------------------------- 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir namespace { 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir OUString lclQuoteName( const OUString& rName ) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir OUStringBuffer aBuffer( rName ); 183*cdf0e10cSrcweir // duplicate all quote characters 184*cdf0e10cSrcweir for( sal_Int32 nPos = aBuffer.getLength() - 1; nPos >= 0; --nPos ) 185*cdf0e10cSrcweir if( aBuffer.charAt( nPos ) == '\'' ) 186*cdf0e10cSrcweir aBuffer.insert( nPos, sal_Unicode( '\'' ) ); 187*cdf0e10cSrcweir // add outer quotes and return 188*cdf0e10cSrcweir return aBuffer.insert( 0, sal_Unicode( '\'' ) ).append( sal_Unicode( '\'' ) ).makeStringAndClear(); 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir } // namespace 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir WorksheetBuffer::SheetInfo::SheetInfo( const SheetInfoModel& rModel, sal_Int16 nCalcSheet, const OUString& rCalcName ) : 194*cdf0e10cSrcweir SheetInfoModel( rModel ), 195*cdf0e10cSrcweir maCalcName( rCalcName ), 196*cdf0e10cSrcweir maCalcQuotedName( lclQuoteName( rCalcName ) ), 197*cdf0e10cSrcweir mnCalcSheet( nCalcSheet ) 198*cdf0e10cSrcweir { 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir WorksheetBuffer::IndexNamePair WorksheetBuffer::createSheet( const OUString& rPreferredName, sal_Int32 nSheetPos, bool bVisible ) 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir try 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir Reference< XSpreadsheets > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW ); 206*cdf0e10cSrcweir Reference< XIndexAccess > xSheetsIA( xSheets, UNO_QUERY_THROW ); 207*cdf0e10cSrcweir Reference< XNameAccess > xSheetsNA( xSheets, UNO_QUERY_THROW ); 208*cdf0e10cSrcweir sal_Int16 nCalcSheet = -1; 209*cdf0e10cSrcweir OUString aSheetName = (rPreferredName.getLength() == 0) ? CREATE_OUSTRING( "Sheet" ) : rPreferredName; 210*cdf0e10cSrcweir PropertySet aPropSet; 211*cdf0e10cSrcweir if( nSheetPos < xSheetsIA->getCount() ) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir nCalcSheet = static_cast< sal_Int16 >( nSheetPos ); 214*cdf0e10cSrcweir // existing sheet - try to rename 215*cdf0e10cSrcweir Reference< XNamed > xSheetName( xSheetsIA->getByIndex( nSheetPos ), UNO_QUERY_THROW ); 216*cdf0e10cSrcweir if( xSheetName->getName() != aSheetName ) 217*cdf0e10cSrcweir { 218*cdf0e10cSrcweir aSheetName = ContainerHelper::getUnusedName( xSheetsNA, aSheetName, ' ' ); 219*cdf0e10cSrcweir xSheetName->setName( aSheetName ); 220*cdf0e10cSrcweir } 221*cdf0e10cSrcweir aPropSet.set( xSheetName ); 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir else 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir nCalcSheet = static_cast< sal_Int16 >( xSheetsIA->getCount() ); 226*cdf0e10cSrcweir // new sheet - insert with unused name 227*cdf0e10cSrcweir aSheetName = ContainerHelper::getUnusedName( xSheetsNA, aSheetName, ' ' ); 228*cdf0e10cSrcweir xSheets->insertNewByName( aSheetName, nCalcSheet ); 229*cdf0e10cSrcweir aPropSet.set( xSheetsIA->getByIndex( nCalcSheet ) ); 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir // sheet properties 233*cdf0e10cSrcweir aPropSet.setProperty( PROP_IsVisible, bVisible ); 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir // return final sheet index if sheet exists 236*cdf0e10cSrcweir return IndexNamePair( nCalcSheet, aSheetName ); 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir catch( Exception& ) 239*cdf0e10cSrcweir { 240*cdf0e10cSrcweir OSL_ENSURE( false, "WorksheetBuffer::createSheet - cannot insert or rename worksheet" ); 241*cdf0e10cSrcweir } 242*cdf0e10cSrcweir return IndexNamePair( -1, OUString() ); 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir void WorksheetBuffer::insertSheet( const SheetInfoModel& rModel ) 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir sal_Int32 nWorksheet = static_cast< sal_Int32 >( maSheetInfos.size() ); 248*cdf0e10cSrcweir IndexNamePair aIndexName = createSheet( rModel.maName, nWorksheet, rModel.mnState == XML_visible ); 249*cdf0e10cSrcweir ::boost::shared_ptr< SheetInfo > xSheetInfo( new SheetInfo( rModel, aIndexName.first, aIndexName.second ) ); 250*cdf0e10cSrcweir maSheetInfos.push_back( xSheetInfo ); 251*cdf0e10cSrcweir maSheetInfosByName[ rModel.maName ] = xSheetInfo; 252*cdf0e10cSrcweir maSheetInfosByName[ lclQuoteName( rModel.maName ) ] = xSheetInfo; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir // ============================================================================ 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir } // namespace xls 258*cdf0e10cSrcweir } // namespace oox 259