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: worksheetbuffer.cxx,v $
10 * $Revision: 1.6.2.1 $
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 #include "oox/xls/worksheetbuffer.hxx"
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/container/XIndexAccess.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XNamed.hpp>
36 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
37 #include <com/sun/star/sheet/XExternalSheetName.hpp>
38 #include <com/sun/star/sheet/XSheetLinkable.hpp>
39 #include "properties.hxx"
40 #include "oox/helper/attributelist.hxx"
41 #include "oox/helper/propertyset.hxx"
42 #include "oox/helper/recordinputstream.hxx"
43 #include "oox/core/filterbase.hxx"
44 #include "oox/xls/biffinputstream.hxx"
45 #include "oox/xls/excelhandlers.hxx"
47 using ::rtl::OUString
;
48 using ::rtl::OUStringBuffer
;
49 using ::com::sun::star::uno::Reference
;
50 using ::com::sun::star::uno::Exception
;
51 using ::com::sun::star::uno::UNO_QUERY_THROW
;
52 using ::com::sun::star::container::XIndexAccess
;
53 using ::com::sun::star::container::XNameAccess
;
54 using ::com::sun::star::container::XNamed
;
55 using ::com::sun::star::sheet::XSpreadsheetDocument
;
56 using ::com::sun::star::sheet::XSpreadsheets
;
61 // ============================================================================
63 SheetInfoModel::SheetInfoModel() :
66 mnState( XML_visible
)
70 // ============================================================================
72 WorksheetBuffer::WorksheetBuffer( const WorkbookHelper
& rHelper
) :
73 WorkbookHelper( rHelper
)
77 /*static*/ OUString
WorksheetBuffer::getBaseFileName( const OUString
& rUrl
)
79 sal_Int32 nFileNamePos
= ::std::max
< sal_Int32
>( rUrl
.lastIndexOf( '/' ) + 1, 0 );
80 sal_Int32 nExtPos
= rUrl
.lastIndexOf( '.' );
81 if( nExtPos
<= nFileNamePos
) nExtPos
= rUrl
.getLength();
82 return rUrl
.copy( nFileNamePos
, nExtPos
- nFileNamePos
);
85 void WorksheetBuffer::initializeSingleSheet()
87 OSL_ENSURE( maSheetInfos
.empty(), "WorksheetBuffer::initializeSingleSheet - invalid call" );
88 SheetInfoModel aModel
;
89 aModel
.maName
= getBaseFileName( getBaseFilter().getFileUrl() );
90 insertSheet( aModel
);
93 void WorksheetBuffer::importSheet( const AttributeList
& rAttribs
)
95 SheetInfoModel aModel
;
96 aModel
.maRelId
= rAttribs
.getString( R_TOKEN( id
), OUString() );
97 aModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
98 aModel
.mnSheetId
= rAttribs
.getInteger( XML_sheetId
, -1 );
99 aModel
.mnState
= rAttribs
.getToken( XML_state
, XML_visible
);
100 insertSheet( aModel
);
103 void WorksheetBuffer::importSheet( RecordInputStream
& rStrm
)
106 SheetInfoModel aModel
;
107 rStrm
>> nState
>> aModel
.mnSheetId
>> aModel
.maRelId
>> aModel
.maName
;
108 static const sal_Int32 spnStates
[] = { XML_visible
, XML_hidden
, XML_veryHidden
};
109 aModel
.mnState
= STATIC_ARRAY_SELECT( spnStates
, nState
, XML_visible
);
110 insertSheet( aModel
);
113 void WorksheetBuffer::importSheet( BiffInputStream
& rStrm
)
115 SheetInfoModel aModel
;
116 if( getBiff() >= BIFF5
)
118 rStrm
.enableDecoder( false );
119 aModel
.mnBiffHandle
= rStrm
.readuInt32();
120 rStrm
.enableDecoder( true );
121 sal_uInt16 nState
= rStrm
.readuInt16();
122 static const sal_Int32 spnStates
[] = { XML_visible
, XML_hidden
, XML_veryHidden
};
123 aModel
.mnState
= STATIC_ARRAY_SELECT( spnStates
, nState
, XML_visible
);
125 aModel
.maName
= (getBiff() == BIFF8
) ?
126 rStrm
.readUniStringBody( rStrm
.readuInt8() ) :
127 rStrm
.readByteStringUC( false, getTextEncoding() );
128 insertSheet( aModel
);
131 sal_Int16
WorksheetBuffer::insertEmptySheet( const OUString
& rPreferredName
, bool bVisible
)
133 return createSheet( rPreferredName
, SAL_MAX_INT32
, bVisible
).first
;
136 sal_Int32
WorksheetBuffer::getWorksheetCount() const
138 return static_cast< sal_Int32
>( maSheetInfos
.size() );
141 OUString
WorksheetBuffer::getWorksheetRelId( sal_Int32 nWorksheet
) const
143 const SheetInfo
* pSheetInfo
= maSheetInfos
.get( nWorksheet
).get();
144 return pSheetInfo
? pSheetInfo
->maRelId
: OUString();
147 sal_Int64
WorksheetBuffer::getBiffRecordHandle( sal_Int32 nWorksheet
) const
149 const SheetInfo
* pSheetInfo
= maSheetInfos
.get( nWorksheet
).get();
150 return pSheetInfo
? pSheetInfo
->mnBiffHandle
: -1;
153 sal_Int16
WorksheetBuffer::getCalcSheetIndex( sal_Int32 nWorksheet
) const
155 const SheetInfo
* pSheetInfo
= maSheetInfos
.get( nWorksheet
).get();
156 return pSheetInfo
? pSheetInfo
->mnCalcSheet
: -1;
159 OUString
WorksheetBuffer::getCalcSheetName( sal_Int32 nWorksheet
) const
161 const SheetInfo
* pSheetInfo
= maSheetInfos
.get( nWorksheet
).get();
162 return pSheetInfo
? pSheetInfo
->maCalcName
: OUString();
165 sal_Int16
WorksheetBuffer::getCalcSheetIndex( const OUString
& rWorksheetName
) const
167 const SheetInfo
* pSheetInfo
= maSheetInfosByName
.get( rWorksheetName
).get();
168 return pSheetInfo
? pSheetInfo
->mnCalcSheet
: -1;
171 OUString
WorksheetBuffer::getCalcSheetName( const OUString
& rWorksheetName
) const
173 if( const SheetInfo
* pSheetInfo
= maSheetInfosByName
.get( rWorksheetName
).get() )
175 bool bIsQuoted
= pSheetInfo
->maName
!= rWorksheetName
;
176 return bIsQuoted
? pSheetInfo
->maCalcQuotedName
: pSheetInfo
->maCalcName
;
181 // private --------------------------------------------------------------------
185 OUString
lclQuoteName( const OUString
& rName
)
187 OUStringBuffer
aBuffer( rName
);
188 // duplicate all quote characters
189 for( sal_Int32 nPos
= aBuffer
.getLength() - 1; nPos
>= 0; --nPos
)
190 if( aBuffer
.charAt( nPos
) == '\'' )
191 aBuffer
.insert( nPos
, sal_Unicode( '\'' ) );
192 // add outer quotes and return
193 return aBuffer
.insert( 0, sal_Unicode( '\'' ) ).append( sal_Unicode( '\'' ) ).makeStringAndClear();
198 WorksheetBuffer::SheetInfo::SheetInfo( const SheetInfoModel
& rModel
, sal_Int16 nCalcSheet
, const OUString
& rCalcName
) :
199 SheetInfoModel( rModel
),
200 maCalcName( rCalcName
),
201 maCalcQuotedName( lclQuoteName( rCalcName
) ),
202 mnCalcSheet( nCalcSheet
)
206 WorksheetBuffer::IndexNamePair
WorksheetBuffer::createSheet( const OUString
& rPreferredName
, sal_Int32 nSheetPos
, bool bVisible
)
210 Reference
< XSpreadsheets
> xSheets( getDocument()->getSheets(), UNO_QUERY_THROW
);
211 Reference
< XIndexAccess
> xSheetsIA( xSheets
, UNO_QUERY_THROW
);
212 Reference
< XNameAccess
> xSheetsNA( xSheets
, UNO_QUERY_THROW
);
213 sal_Int16 nCalcSheet
= -1;
214 OUString aSheetName
= (rPreferredName
.getLength() == 0) ? CREATE_OUSTRING( "Sheet" ) : rPreferredName
;
215 PropertySet aPropSet
;
216 if( nSheetPos
< xSheetsIA
->getCount() )
218 nCalcSheet
= static_cast< sal_Int16
>( nSheetPos
);
219 // existing sheet - try to rename
220 Reference
< XNamed
> xSheetName( xSheetsIA
->getByIndex( nSheetPos
), UNO_QUERY_THROW
);
221 if( xSheetName
->getName() != aSheetName
)
223 aSheetName
= ContainerHelper::getUnusedName( xSheetsNA
, aSheetName
, ' ' );
224 xSheetName
->setName( aSheetName
);
226 aPropSet
.set( xSheetName
);
230 nCalcSheet
= static_cast< sal_Int16
>( xSheetsIA
->getCount() );
231 // new sheet - insert with unused name
232 aSheetName
= ContainerHelper::getUnusedName( xSheetsNA
, aSheetName
, ' ' );
233 xSheets
->insertNewByName( aSheetName
, nCalcSheet
);
234 aPropSet
.set( xSheetsIA
->getByIndex( nCalcSheet
) );
238 aPropSet
.setProperty( PROP_IsVisible
, bVisible
);
240 // return final sheet index if sheet exists
241 return IndexNamePair( nCalcSheet
, aSheetName
);
245 OSL_ENSURE( false, "WorksheetBuffer::createSheet - cannot insert or rename worksheet" );
247 return IndexNamePair( -1, OUString() );
250 void WorksheetBuffer::insertSheet( const SheetInfoModel
& rModel
)
252 sal_Int32 nWorksheet
= static_cast< sal_Int32
>( maSheetInfos
.size() );
253 IndexNamePair aIndexName
= createSheet( rModel
.maName
, nWorksheet
, rModel
.mnState
== XML_visible
);
254 ::boost::shared_ptr
< SheetInfo
> xSheetInfo( new SheetInfo( rModel
, aIndexName
.first
, aIndexName
.second
) );
255 maSheetInfos
.push_back( xSheetInfo
);
256 maSheetInfosByName
[ rModel
.maName
] = xSheetInfo
;
257 maSheetInfosByName
[ lclQuoteName( rModel
.maName
) ] = xSheetInfo
;
260 // ============================================================================