LibreOffice Module sc (master) 1
worksheetbuffer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
24#include <worksheetbuffer.hxx>
25
26#include <com/sun/star/container/XIndexAccess.hpp>
27#include <com/sun/star/container/XNamed.hpp>
28#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
29#include <osl/diagnose.h>
30#include <rtl/ustrbuf.hxx>
34#include <oox/token/namespaces.hxx>
35#include <oox/token/tokens.hxx>
36#include <document.hxx>
37#include <documentimport.hxx>
38#include <biffhelper.hxx>
39#include <globstr.hrc>
40#include <scresid.hxx>
41
42namespace oox::xls {
43
44using namespace ::com::sun::star::container;
45using namespace ::com::sun::star::sheet;
46using namespace ::com::sun::star::uno;
47
49 mnSheetId( -1 ),
50 mnState( XML_visible )
51{
52}
53
55 WorkbookHelper( rHelper )
56{
57}
58
60{
61 SheetInfoModel aModel;
62 aModel.maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
63 aModel.maName = rAttribs.getXString( XML_name, OUString() );
64 aModel.mnSheetId = rAttribs.getInteger( XML_sheetId, -1 );
65 aModel.mnState = rAttribs.getToken( XML_state, XML_visible );
66 insertSheet( aModel );
67}
68
70{
71 sal_Int32 nState;
72 SheetInfoModel aModel;
73 nState = rStrm.readInt32();
74 aModel.mnSheetId = rStrm.readInt32();
75 rStrm >> aModel.maRelId >> aModel.maName;
76 static const sal_Int32 spnStates[] = { XML_visible, XML_hidden, XML_veryHidden };
77 aModel.mnState = STATIC_ARRAY_SELECT( spnStates, nState, XML_visible );
78 insertSheet( aModel );
79}
80
81sal_Int16 WorksheetBuffer::insertEmptySheet( const OUString& rPreferredName )
82{
83 IndexNamePair aIndexName = createSheet( rPreferredName, SAL_MAX_INT32 );
84 ScDocument& rDoc = getScDocument();
85
86 rDoc.SetVisible( aIndexName.first, false );
87 return aIndexName.first;
88}
89
91{
92 return static_cast< sal_Int32 >( maSheetInfos.size() );
93}
94
96{
97 const ScDocumentImport& rDoc = getDocImport();
98 return rDoc.getSheetCount();
99}
100
101OUString WorksheetBuffer::getWorksheetRelId( sal_Int32 nWorksheet ) const
102{
103 const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get();
104 return pSheetInfo ? pSheetInfo->maRelId : OUString();
105}
106
107sal_Int16 WorksheetBuffer::getCalcSheetIndex( sal_Int32 nWorksheet ) const
108{
109 const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get();
110 return pSheetInfo ? pSheetInfo->mnCalcSheet : -1;
111}
112
113OUString WorksheetBuffer::getCalcSheetName( sal_Int32 nWorksheet ) const
114{
115 const SheetInfo* pSheetInfo = maSheetInfos.get( nWorksheet ).get();
116 return pSheetInfo ? pSheetInfo->maCalcName : OUString();
117}
118
119void WorksheetBuffer::convertSheetNameRef( OUString& sSheetNameRef ) const
120{
121 if( !sSheetNameRef.startsWith("#") )
122 return;
123
124 sal_Int32 nSepPos = sSheetNameRef.lastIndexOf( '!' );
125 if( nSepPos <= 0 )
126 return;
127
128 // Do not attempt to blindly convert '#SheetName!A1' to
129 // '#SheetName.A1', it can be #SheetName!R1C1 as well. Hyperlink
130 // handler has to handle all, but prefer '#SheetName.A1' if
131 // possible.
132 if (nSepPos < sSheetNameRef.getLength() - 1)
133 {
134 ScRange aRange;
135 if ((aRange.ParseAny( sSheetNameRef.copy( nSepPos + 1 ), getScDocument(),
137 sSheetNameRef = sSheetNameRef.replaceAt( nSepPos, 1, rtl::OUStringChar( '.' ) );
138 }
139 // #i66592# convert sheet names that have been renamed on import
140 OUString aSheetName = sSheetNameRef.copy( 1, nSepPos - 1 );
141 OUString aCalcName = getCalcSheetName( aSheetName );
142 if( !aCalcName.isEmpty() )
143 sSheetNameRef = sSheetNameRef.replaceAt( 1, nSepPos - 1, aCalcName );
144}
145
146sal_Int16 WorksheetBuffer::getCalcSheetIndex( const OUString& rWorksheetName ) const
147{
148 const SheetInfo* pSheetInfo = maSheetInfosByName.get( rWorksheetName ).get();
149 return pSheetInfo ? pSheetInfo->mnCalcSheet : -1;
150}
151
152OUString WorksheetBuffer::getCalcSheetName( const OUString& rWorksheetName ) const
153{
154 if( const SheetInfo* pSheetInfo = maSheetInfosByName.get( rWorksheetName ).get() )
155 {
156 bool bIsQuoted = pSheetInfo->maName != rWorksheetName;
157 return bIsQuoted ? pSheetInfo->maCalcQuotedName : pSheetInfo->maCalcName;
158 }
159 return OUString();
160}
161
162// private --------------------------------------------------------------------
163
164namespace {
165
166OUString lclQuoteName( std::u16string_view rName )
167{
168 OUStringBuffer aBuffer( rName );
169 // duplicate all quote characters
170 for( sal_Int32 nPos = aBuffer.getLength() - 1; nPos >= 0; --nPos )
171 if( aBuffer[nPos] == '\'' )
172 aBuffer.insert( nPos, '\'' );
173 // add outer quotes and return
174 return aBuffer.insert( 0, '\'' ).append( '\'' ).makeStringAndClear();
175}
176
177} // namespace
178
179WorksheetBuffer::SheetInfo::SheetInfo( const SheetInfoModel& rModel, sal_Int16 nCalcSheet, const OUString& rCalcName ) :
180 SheetInfoModel( rModel ),
181 maCalcName( rCalcName ),
182 maCalcQuotedName( lclQuoteName( rCalcName ) ),
183 mnCalcSheet( nCalcSheet )
184{
185}
186
187WorksheetBuffer::IndexNamePair WorksheetBuffer::createSheet( const OUString& rPreferredName, sal_Int32 nSheetPos )
188{
189 //FIXME: Rewrite this block using ScDocument[Import] instead of UNO
190 try
191 {
192 Reference< XSpreadsheets > xSheets( getDocument()->getSheets(), UNO_SET_THROW );
193 Reference< XIndexAccess > xSheetsIA( xSheets, UNO_QUERY_THROW );
194 sal_Int16 nCalcSheet = -1;
195 OUString aSheetName = rPreferredName.isEmpty() ? ScResId(STR_TABLE_DEF) : rPreferredName;
196 if( nSheetPos < xSheetsIA->getCount() )
197 {
198 nCalcSheet = static_cast< sal_Int16 >( nSheetPos );
199 // existing sheet - try to rename
200 Reference< XNamed > xSheetName( xSheetsIA->getByIndex( nSheetPos ), UNO_QUERY_THROW );
201 if( xSheetName->getName() != aSheetName )
202 {
203 aSheetName = ContainerHelper::getUnusedName( xSheets, aSheetName, ' ' );
204 xSheetName->setName( aSheetName );
205 }
206 }
207 else
208 {
209 nCalcSheet = static_cast< sal_Int16 >( xSheetsIA->getCount() );
210 // new sheet - insert with unused name
211 aSheetName = ContainerHelper::getUnusedName( xSheets, aSheetName, ' ' );
212 xSheets->insertNewByName( aSheetName, nCalcSheet );
213 }
214
215 // return final sheet index if sheet exists
216 return IndexNamePair( nCalcSheet, aSheetName );
217 }
218 catch (const Exception&)
219 {
220 OSL_FAIL( "WorksheetBuffer::createSheet - cannot insert or rename worksheet" );
221 }
222 return IndexNamePair( -1, OUString() );
223}
224
226{
227 sal_Int32 nWorksheet = static_cast< sal_Int32 >( maSheetInfos.size() );
228 IndexNamePair aIndexName = createSheet( rModel.maName, nWorksheet );
229 auto xSheetInfo = std::make_shared<SheetInfo>( rModel, aIndexName.first, aIndexName.second );
230 maSheetInfos.push_back( xSheetInfo );
231 maSheetInfosByName[ rModel.maName ] = xSheetInfo;
232 maSheetInfosByName[ lclQuoteName( rModel.maName ) ] = xSheetInfo;
233}
234
235void WorksheetBuffer::finalizeImport( sal_Int16 nActiveSheet )
236{
237 ScDocument& rDoc = getScDocument();
238
239 for ( const auto& aSheetInfo: maSheetInfos )
240 {
241 // make sure at least 1 sheet (the active one) is visible
242 if ( aSheetInfo->mnCalcSheet == nActiveSheet)
243 rDoc.SetVisible( aSheetInfo->mnCalcSheet, true );
244 else
245 rDoc.SetVisible( aSheetInfo->mnCalcSheet, aSheetInfo->mnState == XML_visible );
246 }
247}
248
249} // namespace oox::xls
250
251/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Accessor class to ScDocument.
SCTAB getSheetCount() const
SC_DLLPUBLIC void SetVisible(SCTAB nTab, bool bVisible)
Definition: document.cxx:884
ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1733
std::optional< OUString > getXString(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
std::optional< OUString > getString(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getToken(sal_Int32 nAttrToken) const
static OUString getUnusedName(const css::uno::Reference< css::container::XNameAccess > &rxNameAccess, const OUString &rSuggestedName, sal_Unicode cSeparator)
Helper class to provide access to global workbook data.
ScDocumentImport & getDocImport()
const css::uno::Reference< css::sheet::XSpreadsheetDocument > & getDocument() const
Returns a reference to the source/target spreadsheet document model.
void convertSheetNameRef(OUString &sSheetNameRef) const
Converts sSheetNameRef (e.g.
RefVector< SheetInfo > maSheetInfos
OUString getWorksheetRelId(sal_Int32 nWorksheet) const
Returns the OOXML relation identifier of the specified worksheet.
OUString getCalcSheetName(sal_Int32 nWorksheet) const
Returns the finalized name of the specified worksheet.
IndexNamePair createSheet(const OUString &rPreferredName, sal_Int32 nSheetPos)
Creates a new sheet in the Calc document.
sal_Int32 getWorksheetCount() const
Returns the number of original sheets contained in the workbook.
sal_Int16 getCalcSheetIndex(sal_Int32 nWorksheet) const
Returns the Calc index of the specified worksheet.
::std::pair< sal_Int16, OUString > IndexNamePair
void importSheet(const AttributeList &rAttribs)
Imports the attributes of a sheet element.
RefMap< OUString, SheetInfo, IgnoreCaseCompare > maSheetInfosByName
sal_Int16 insertEmptySheet(const OUString &rPreferredName)
Inserts a new empty sheet into the document.
sal_Int32 getAllSheetCount() const
Returns the number of all sheets, workbook + dummy ones (pivot table cache records )
WorksheetBuffer(const WorkbookHelper &rHelper)
void finalizeImport(sal_Int16 nActiveSheet)
void insertSheet(const SheetInfoModel &rModel)
Creates a new sheet in the Calc document and inserts the related SheetInfo.
sal_Int32 nState
#define STATIC_ARRAY_SELECT(array, index, def)
@ Exception
void SvStream & rStrm
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
Contains data from the 'sheet' element describing a sheet in the workbook.
SheetInfoModel()
Visibility state.
OUString maName
Relation identifier for the sheet substream.
sal_Int32 mnState
Sheet identifier.
sal_Int32 mnSheetId
Original name of the sheet.
SheetInfo(const SheetInfoModel &rModel, sal_Int16 nCalcSheet, const OUString &rCalcName)
#define SAL_MAX_INT32
std::unique_ptr< char[]> aBuffer