LibreOffice Module sc (master)  1
externallinkfragment.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 <externallinkfragment.hxx>
21 
22 #include <com/sun/star/sheet/XExternalSheetCache.hpp>
25 #include <oox/token/namespaces.hxx>
26 #include <oox/token/tokens.hxx>
27 #include <osl/diagnose.h>
28 #include <addressconverter.hxx>
29 #include <unitconverter.hxx>
30 #include <biffhelper.hxx>
31 
32 namespace oox::xls {
33 
34 using namespace ::com::sun::star::sheet;
35 using namespace ::com::sun::star::uno;
36 using namespace ::oox::core;
37 
39  WorkbookFragmentBase& rFragment, const Reference< XExternalSheetCache >& rxSheetCache )
40  : WorkbookContextBase(rFragment)
41  , mxSheetCache(rxSheetCache)
42  , mnCurrType(XML_TOKEN_INVALID)
43 {
44  OSL_ENSURE( mxSheetCache.is(), "ExternalSheetDataContext::ExternalSheetDataContext - missing sheet cache" );
45 }
46 
48 {
49  switch( getCurrentElement() )
50  {
51  case XLS_TOKEN( sheetData ):
52  if( nElement == XLS_TOKEN( row ) ) return this;
53  break;
54  case XLS_TOKEN( row ):
55  if( nElement == XLS_TOKEN( cell ) ) { importCell( rAttribs ); return this; }
56  break;
57  case XLS_TOKEN( cell ):
58  if( nElement == XLS_TOKEN( v ) ) return this; // collect characters in onCharacters()
59  break;
60  }
61  return nullptr;
62 }
63 
64 void ExternalSheetDataContext::onCharacters( const OUString& rChars )
65 {
66  if( !isCurrentElement( XLS_TOKEN( v ) ) )
67  return;
68 
69  switch( mnCurrType )
70  {
71  case XML_b:
72  case XML_n:
73  setCellValue( Any( rChars.toDouble() ) );
74  break;
75  case XML_e:
76  setCellValue( Any( BiffHelper::calcDoubleFromError( getUnitConverter().calcBiffErrorCode( rChars ) ) ) );
77  break;
78  case XML_str:
79  setCellValue( Any( rChars ) );
80  break;
81  }
83 }
84 
86 {
87  switch( getCurrentElement() )
88  {
90  if( nRecId == BIFF12_ID_EXTROW ) { maCurrPos.SetRow( rStrm.readInt32() ); return this; }
91  break;
92  case BIFF12_ID_EXTROW:
93  switch( nRecId )
94  {
95  case BIFF12_ID_EXTCELL_BLANK: importExtCellBlank( rStrm ); break;
96  case BIFF12_ID_EXTCELL_BOOL: importExtCellBool( rStrm ); break;
97  case BIFF12_ID_EXTCELL_DOUBLE: importExtCellDouble( rStrm ); break;
98  case BIFF12_ID_EXTCELL_ERROR: importExtCellError( rStrm ); break;
99  case BIFF12_ID_EXTCELL_STRING: importExtCellString( rStrm ); break;
100  }
101  break;
102  }
103  return nullptr;
104 }
105 
106 // private --------------------------------------------------------------------
107 
109 {
110  if( getAddressConverter().convertToCellAddress( maCurrPos, rAttribs.getString( XML_r, OUString() ), 0, false ) )
111  mnCurrType = rAttribs.getToken( XML_t, XML_n );
112  else
114 }
115 
117 {
118  maCurrPos.SetCol( rStrm.readInt32() );
119  setCellValue( Any( OUString() ) );
120 }
121 
123 {
124  maCurrPos.SetCol( rStrm.readInt32() );
125  double fValue = (rStrm.readuInt8() == 0) ? 0.0 : 1.0;
126  setCellValue( Any( fValue ) );
127 }
128 
130 {
131  maCurrPos.SetCol( rStrm.readInt32() );
132  setCellValue( Any( rStrm.readDouble() ) );
133 }
134 
136 {
137  maCurrPos.SetCol( rStrm.readInt32() );
139 }
140 
142 {
143  maCurrPos.SetCol( rStrm.readInt32() );
144  setCellValue( Any( BiffHelper::readString( rStrm ) ) );
145 }
146 
147 void ExternalSheetDataContext::setCellValue( const Any& rValue )
148 {
149  if( mxSheetCache.is() && getAddressConverter().checkCellAddress( maCurrPos, false ) ) try
150  {
151  mxSheetCache->setCellValue( maCurrPos.Col(), maCurrPos.Row(), rValue );
152  }
153  catch( Exception& )
154  {
155  }
156 }
157 
159  const OUString& rFragmentPath, ExternalLink& rExtLink ) :
160  WorkbookFragmentBase( rHelper, rFragmentPath ),
161  mrExtLink( rExtLink ),
162  mnResultType( XML_TOKEN_INVALID )
163 {
164 }
165 
167 {
168  switch( getCurrentElement() )
169  {
170  case XML_ROOT_CONTEXT:
171  if( nElement == XLS_TOKEN( externalLink ) ) return this;
172  break;
173 
174  case XLS_TOKEN( externalLink ):
175  switch( nElement )
176  {
177  case XLS_TOKEN( externalBook ): mrExtLink.importExternalBook( getRelations(), rAttribs ); return this;
178  case XLS_TOKEN( ddeLink ): mrExtLink.importDdeLink( rAttribs ); return this;
179  case XLS_TOKEN( oleLink ): mrExtLink.importOleLink( getRelations(), rAttribs ); return this;
180  }
181  break;
182 
183  case XLS_TOKEN( externalBook ):
184  switch( nElement )
185  {
186  case XLS_TOKEN( sheetNames ):
187  case XLS_TOKEN( definedNames ):
188  case XLS_TOKEN( sheetDataSet ): return this;
189  }
190  break;
191 
192  case XLS_TOKEN( sheetNames ):
193  if( nElement == XLS_TOKEN( sheetName ) ) mrExtLink.importSheetName( rAttribs );
194  break;
195  case XLS_TOKEN( definedNames ):
196  if( nElement == XLS_TOKEN( definedName ) ) mrExtLink.importDefinedName( rAttribs );
197  break;
198  case XLS_TOKEN( sheetDataSet ):
199  if( (nElement == XLS_TOKEN( sheetData )) && (mrExtLink.getLinkType() == ExternalLinkType::External) )
200  return createSheetDataContext( rAttribs.getInteger( XML_sheetId, -1 ) );
201  break;
202 
203  case XLS_TOKEN( ddeLink ):
204  if( nElement == XLS_TOKEN( ddeItems ) ) return this;
205  break;
206  case XLS_TOKEN( ddeItems ):
207  if( nElement == XLS_TOKEN( ddeItem ) )
208  {
209  mxExtName = mrExtLink.importDdeItem( rAttribs );
210  return this;
211  }
212  break;
213  case XLS_TOKEN( ddeItem ):
214  if( nElement == XLS_TOKEN( values ) )
215  {
216  if( mxExtName ) mxExtName->importValues( rAttribs );
217  return this;
218  }
219  break;
220  case XLS_TOKEN( values ):
221  if( nElement == XLS_TOKEN( value ) )
222  {
223  mnResultType = rAttribs.getToken( XML_t, XML_n );
224  return this;
225  }
226  break;
227  case XLS_TOKEN( value ):
228  if( nElement == XLS_TOKEN( val ) ) return this; // collect value in onCharacters()
229  break;
230 
231  case XLS_TOKEN( oleLink ):
232  if( nElement == XLS_TOKEN( oleItems ) ) return this;
233  break;
234  case XLS_TOKEN( oleItems ):
235  if( nElement == XLS_TOKEN( oleItem ) ) mxExtName = mrExtLink.importOleItem( rAttribs );
236  break;
237  }
238  return nullptr;
239 }
240 
241 void ExternalLinkFragment::onCharacters( const OUString& rChars )
242 {
243  if( isCurrentElement( XLS_TOKEN( val ) ) )
244  maResultValue = rChars;
245 }
246 
248 {
249  if( !(isCurrentElement( XLS_TOKEN( value ) ) && mxExtName) )
250  return;
251 
252  switch( mnResultType )
253  {
254  case XML_b:
255  mxExtName->appendResultValue( maResultValue.toDouble() );
256  break;
257  case XML_e:
258  mxExtName->appendResultValue( BiffHelper::calcDoubleFromError( getUnitConverter().calcBiffErrorCode( maResultValue ) ) );
259  break;
260  case XML_n:
261  mxExtName->appendResultValue( maResultValue.toDouble() );
262  break;
263  case XML_str:
264  mxExtName->appendResultValue( maResultValue );
265  break;
266  default:
267  mxExtName->appendResultValue( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) );
268  }
269 }
270 
272 {
273  switch( getCurrentElement() )
274  {
275  case XML_ROOT_CONTEXT:
276  if( nRecId == BIFF12_ID_EXTERNALBOOK )
277  {
278  mrExtLink.importExternalBook( getRelations(), rStrm );
279  return this;
280  }
281  break;
282 
284  switch( nRecId )
285  {
288  return createSheetDataContext( rStrm.readInt32() );
289  break;
290 
292  case BIFF12_ID_EXTERNALNAME: mxExtName = mrExtLink.importExternalName( rStrm ); return this;
293  }
294  break;
295 
297  switch( nRecId )
298  {
299  case BIFF12_ID_EXTERNALNAMEFLAGS: if( mxExtName ) mxExtName->importExternalNameFlags( rStrm ); break;
300  case BIFF12_ID_DDEITEMVALUES: if( mxExtName ) mxExtName->importDdeItemValues( rStrm ); return this;
301  }
302  break;
303 
305  switch( nRecId )
306  {
307  case BIFF12_ID_DDEITEM_BOOL: if( mxExtName ) mxExtName->importDdeItemBool( rStrm ); break;
308  case BIFF12_ID_DDEITEM_DOUBLE: if( mxExtName ) mxExtName->importDdeItemDouble( rStrm ); break;
309  case BIFF12_ID_DDEITEM_ERROR: if( mxExtName ) mxExtName->importDdeItemError( rStrm ); break;
310  case BIFF12_ID_DDEITEM_STRING: if( mxExtName ) mxExtName->importDdeItemString( rStrm ); break;
311  }
312  break;
313  }
314  return nullptr;
315 }
316 
318 {
319  return new ExternalSheetDataContext( *this, mrExtLink.getSheetCache( nSheetId ) );
320 }
321 
322 const RecordInfo* ExternalLinkFragment::getRecordInfos() const
323 {
324  static const RecordInfo spRecInfos[] =
325  {
329  { BIFF12_ID_EXTROW, -1 },
331  { -1, -1 }
332  };
333  return spRecInfos;
334 }
335 
336 } // namespace oox::xls
337 
338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Helper class to provide access to global workbook data.
const sal_Int32 BIFF12_ID_EXTCELL_ERROR
Definition: biffhelper.hxx:104
ExternalLinkFragment(const WorkbookHelper &rHelper, const OUString &rFragmentPath, ExternalLink &rExtLink)
void importExtCellString(SequenceInputStream &rStrm)
Imports the EXTCELL_STRING from the passed stream.
virtual void onEndElement() override
sal_Int32 mnCurrType
Position of current cell.
bool checkCellAddress(const ScAddress &rAddress, bool bTrackOverflow)
Checks the passed cell address if it fits into the spreadsheet limits.
const sal_Int32 BIFF12_ID_EXTERNALNAMEFLAGS
Definition: biffhelper.hxx:116
SCROW Row() const
Definition: address.hxx:262
const sal_uInt8 BIFF_ERR_NA
Definition: biffhelper.hxx:567
std::vector< char * > values
UnitConverter & getUnitConverter() const
Returns the measurement unit converter.
const sal_Int32 BIFF12_ID_DDEITEM_ERROR
Definition: biffhelper.hxx:92
OptValue< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
bool isCurrentElement(sal_Int32 nElement) const
Link refers to the current sheet.
static double calcDoubleFromError(sal_uInt8 nErrorCode)
Converts the passed BIFF error to a double containing the respective Calc error code.
Definition: biffhelper.cxx:56
virtual void onCharacters(const OUString &rChars) override
virtual void onCharacters(const OUString &rChars) override
void setCellValue(const css::uno::Any &rValue)
Sets the passed cell value to the current position in the sheet cache.
::oox::core::ContextHandlerRef createSheetDataContext(sal_Int32 nSheetId)
void importExtCellDouble(SequenceInputStream &rStrm)
Imports the EXTCELL_DOUBLE from the passed stream.
const sal_Int32 BIFF12_ID_DDEITEM_BOOL
Definition: biffhelper.hxx:90
OptValue< OUString > getString(sal_Int32 nAttrToken) const
ScAddress maCurrPos
The sheet cache used to store external cell values.
virtual ::oox::core::ContextHandlerRef onCreateRecordContext(sal_Int32 nRecId, SequenceInputStream &rStrm) override
const sal_Int32 BIFF12_ID_EXTERNALBOOK
Definition: biffhelper.hxx:107
Fragment handler derived from the WorkbookHelper helper class.
void SetRow(SCROW nRowP)
Definition: address.hxx:275
void importExtCellBlank(SequenceInputStream &rStrm)
Imports the EXTCELL_BLANK from the passed stream.
void SetCol(SCCOL nColP)
Definition: address.hxx:279
void importCell(const AttributeList &rAttribs)
Imports cell settings from a c element.
virtual const ::oox::core::RecordInfo * getRecordInfos() const override
const sal_Int32 BIFF12_ID_EXTCELL_DOUBLE
Definition: biffhelper.hxx:103
static OUString readString(SequenceInputStream &rStrm, bool b32BitLen=true)
Reads a BIFF12 string with leading 16-bit or 32-bit length field.
Definition: biffhelper.cxx:78
sal_Int32 getCurrentElement() const
XML_TOKEN_INVALID
ExternalSheetDataContext(WorkbookFragmentBase &rFragment, const css::uno::Reference< css::sheet::XExternalSheetCache > &rxSheetCache)
const sal_Int32 BIFF12_ID_DDEITEMVALUES
Definition: biffhelper.hxx:89
const sal_Int32 BIFF12_ID_EXTCELL_BLANK
Definition: biffhelper.hxx:101
const sal_Int32 BIFF12_ID_EXTROW
Definition: biffhelper.hxx:114
SCCOL Col() const
Definition: address.hxx:267
Context handler derived from the WorkbookHelper helper class.
float v
const sal_Int32 BIFF12_ID_EXTCELL_BOOL
Definition: biffhelper.hxx:102
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
const sal_Int32 BIFF12_ID_DDEITEM_DOUBLE
Definition: biffhelper.hxx:91
virtual ::oox::core::ContextHandlerRef onCreateRecordContext(sal_Int32 nRecId, SequenceInputStream &rStrm) override
void importExtCellError(SequenceInputStream &rStrm)
Imports the EXTCELL_ERROR from the passed stream.
css::uno::Reference< css::sheet::XExternalSheetCache > mxSheetCache
This class implements importing the sheetData element in external sheets.
Any value
const sal_Int32 BIFF12_ID_EXTSHEETNAMES
Definition: biffhelper.hxx:117
const sal_Int32 BIFF12_ID_DDEITEM_STRING
Definition: biffhelper.hxx:93
const sal_Int32 XML_ROOT_CONTEXT
void importExtCellBool(SequenceInputStream &rStrm)
Imports the EXTCELL_BOOL from the passed stream.
const sal_Int32 BIFF12_ID_EXTSHEETDATA
Definition: biffhelper.hxx:115
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const AttributeList &rAttribs) override
const sal_Int32 BIFF12_ID_EXTERNALNAME
Definition: biffhelper.hxx:108
const sal_Int32 BIFF12_ID_EXTCELL_STRING
Definition: biffhelper.hxx:105
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
AddressConverter & getAddressConverter() const
Returns the converter for string to cell address/range conversion.