Line data Source code
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 "xecontent.hxx"
21 :
22 : #include <list>
23 : #include <algorithm>
24 : #include <com/sun/star/container/XIndexAccess.hpp>
25 : #include <com/sun/star/frame/XModel.hpp>
26 : #include <com/sun/star/sheet/XAreaLinks.hpp>
27 : #include <com/sun/star/sheet/XAreaLink.hpp>
28 : #include <comphelper/string.hxx>
29 : #include <sfx2/objsh.hxx>
30 : #include <tools/urlobj.hxx>
31 : #include <svl/itemset.hxx>
32 : #include <formula/grammar.hxx>
33 : #include "scitems.hxx"
34 : #include <editeng/eeitem.hxx>
35 : #include <editeng/flditem.hxx>
36 : #include "document.hxx"
37 : #include "validat.hxx"
38 : #include "unonames.hxx"
39 : #include "convuno.hxx"
40 : #include "rangenam.hxx"
41 : #include "tokenarray.hxx"
42 : #include "stlpool.hxx"
43 : #include "patattr.hxx"
44 : #include "fapihelper.hxx"
45 : #include "xehelper.hxx"
46 : #include "xestyle.hxx"
47 : #include "xename.hxx"
48 : #include <rtl/uuid.h>
49 :
50 : using namespace ::oox;
51 :
52 : using ::com::sun::star::uno::Reference;
53 : using ::com::sun::star::uno::Any;
54 : using ::com::sun::star::uno::UNO_QUERY;
55 : using ::com::sun::star::beans::XPropertySet;
56 : using ::com::sun::star::container::XIndexAccess;
57 : using ::com::sun::star::frame::XModel;
58 : using ::com::sun::star::table::CellRangeAddress;
59 : using ::com::sun::star::sheet::XAreaLinks;
60 : using ::com::sun::star::sheet::XAreaLink;
61 :
62 : // Shared string table ========================================================
63 :
64 : /** A single string entry in the hash table. */
65 : struct XclExpHashEntry
66 : {
67 : const XclExpString* mpString; /// Pointer to the string (no ownership).
68 : sal_uInt32 mnSstIndex; /// The SST index of this string.
69 449 : inline explicit XclExpHashEntry( const XclExpString* pString = 0, sal_uInt32 nSstIndex = 0 ) :
70 449 : mpString( pString ), mnSstIndex( nSstIndex ) {}
71 : };
72 :
73 : /** Function object for strict weak ordering. */
74 : struct XclExpHashEntrySWO
75 : {
76 83 : inline bool operator()( const XclExpHashEntry& rLeft, const XclExpHashEntry& rRight ) const
77 83 : { return *rLeft.mpString < *rRight.mpString; }
78 : };
79 :
80 : /** Implementation of the SST export.
81 : @descr Stores all passed strings in a hash table and prevents repeated
82 : insertion of equal strings. */
83 72 : class XclExpSstImpl
84 : {
85 : public:
86 : explicit XclExpSstImpl();
87 :
88 : /** Inserts the passed string, if not already inserted, and returns the unique SST index. */
89 : sal_uInt32 Insert( XclExpStringRef xString );
90 :
91 : /** Writes the complete SST and EXTSST records. */
92 : void Save( XclExpStream& rStrm );
93 : void SaveXml( XclExpXmlStream& rStrm );
94 :
95 : private:
96 : typedef ::std::list< XclExpStringRef > XclExpStringList;
97 : typedef ::std::vector< XclExpHashEntry > XclExpHashVec;
98 : typedef ::std::vector< XclExpHashVec > XclExpHashTab;
99 :
100 : XclExpStringList maStringList; /// List of unique strings (in SST ID order).
101 : XclExpHashTab maHashTab; /// Hashed table that manages string pointers.
102 : sal_uInt32 mnTotal; /// Total count of strings (including doubles).
103 : sal_uInt32 mnSize; /// Size of the SST (count of unique strings).
104 : };
105 :
106 : const sal_uInt32 EXC_SST_HASHTABLE_SIZE = 2048;
107 :
108 72 : XclExpSstImpl::XclExpSstImpl() :
109 : maHashTab( EXC_SST_HASHTABLE_SIZE ),
110 : mnTotal( 0 ),
111 72 : mnSize( 0 )
112 : {
113 72 : }
114 :
115 449 : sal_uInt32 XclExpSstImpl::Insert( XclExpStringRef xString )
116 : {
117 : OSL_ENSURE( xString.get(), "XclExpSstImpl::Insert - empty pointer not allowed" );
118 449 : if( !xString.get() )
119 0 : xString.reset( new XclExpString );
120 :
121 449 : ++mnTotal;
122 449 : sal_uInt32 nSstIndex = 0;
123 :
124 : // calculate hash value in range [0,EXC_SST_HASHTABLE_SIZE)
125 449 : sal_uInt16 nHash = xString->GetHash();
126 449 : (nHash ^= (nHash / EXC_SST_HASHTABLE_SIZE)) %= EXC_SST_HASHTABLE_SIZE;
127 :
128 449 : XclExpHashVec& rVec = maHashTab[ nHash ];
129 449 : XclExpHashEntry aEntry( xString.get(), mnSize );
130 449 : XclExpHashVec::iterator aIt = ::std::lower_bound( rVec.begin(), rVec.end(), aEntry, XclExpHashEntrySWO() );
131 449 : if( (aIt == rVec.end()) || (*aIt->mpString != *xString) )
132 : {
133 372 : nSstIndex = mnSize;
134 372 : maStringList.push_back( xString );
135 372 : rVec.insert( aIt, aEntry );
136 372 : ++mnSize;
137 : }
138 : else
139 : {
140 77 : nSstIndex = aIt->mnSstIndex;
141 : }
142 :
143 449 : return nSstIndex;
144 : }
145 :
146 17 : void XclExpSstImpl::Save( XclExpStream& rStrm )
147 : {
148 17 : if( maStringList.empty() )
149 27 : return;
150 :
151 7 : SvMemoryStream aExtSst( 8192 );
152 :
153 7 : sal_uInt32 nBucket = mnSize;
154 14 : while( nBucket > 0x0100 )
155 0 : nBucket /= 2;
156 :
157 7 : sal_uInt16 nPerBucket = llimit_cast< sal_uInt16 >( nBucket, 8 );
158 7 : sal_uInt16 nBucketIndex = 0;
159 :
160 : // *** write the SST record ***
161 :
162 7 : rStrm.StartRecord( EXC_ID_SST, 8 );
163 :
164 7 : rStrm << mnTotal << mnSize;
165 143 : for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
166 : {
167 136 : if( !nBucketIndex )
168 : {
169 : // write bucket info before string to get correct record position
170 7 : sal_uInt32 nStrmPos = static_cast< sal_uInt32 >( rStrm.GetSvStreamPos() );
171 7 : sal_uInt16 nRecPos = rStrm.GetRawRecPos() + 4;
172 7 : aExtSst.WriteUInt32( nStrmPos ) // stream position
173 14 : .WriteUInt16( nRecPos ) // position from start of SST or CONTINUE
174 7 : .WriteUInt16( 0 ); // reserved
175 : }
176 :
177 136 : rStrm << **aIt;
178 :
179 136 : if( ++nBucketIndex == nPerBucket )
180 3 : nBucketIndex = 0;
181 : }
182 :
183 7 : rStrm.EndRecord();
184 :
185 : // *** write the EXTSST record ***
186 :
187 7 : rStrm.StartRecord( EXC_ID_EXTSST, 0 );
188 :
189 7 : rStrm << nPerBucket;
190 7 : rStrm.SetSliceSize( 8 ); // size of one bucket info
191 7 : aExtSst.Seek( STREAM_SEEK_TO_BEGIN );
192 7 : rStrm.CopyFromStream( aExtSst );
193 :
194 7 : rStrm.EndRecord();
195 : }
196 :
197 55 : void XclExpSstImpl::SaveXml( XclExpXmlStream& rStrm )
198 : {
199 55 : if( maStringList.empty() )
200 77 : return;
201 :
202 : sax_fastparser::FSHelperPtr pSst = rStrm.CreateOutputStream(
203 : OUString( "xl/sharedStrings.xml"),
204 : OUString( "sharedStrings.xml" ),
205 33 : rStrm.GetCurrentStream()->getOutputStream(),
206 : "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
207 33 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" );
208 33 : rStrm.PushStream( pSst );
209 :
210 : pSst->startElement( XML_sst,
211 : XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
212 : XML_count, OString::number( mnTotal ).getStr(),
213 : XML_uniqueCount, OString::number( mnSize ).getStr(),
214 33 : FSEND );
215 :
216 269 : for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
217 : {
218 236 : pSst->startElement( XML_si, FSEND );
219 236 : (*aIt)->WriteXml( rStrm );
220 236 : pSst->endElement( XML_si );
221 : }
222 :
223 33 : pSst->endElement( XML_sst );
224 :
225 33 : rStrm.PopStream();
226 : }
227 :
228 72 : XclExpSst::XclExpSst() :
229 72 : mxImpl( new XclExpSstImpl )
230 : {
231 72 : }
232 :
233 144 : XclExpSst::~XclExpSst()
234 : {
235 144 : }
236 :
237 449 : sal_uInt32 XclExpSst::Insert( XclExpStringRef xString )
238 : {
239 449 : return mxImpl->Insert( xString );
240 : }
241 :
242 17 : void XclExpSst::Save( XclExpStream& rStrm )
243 : {
244 17 : mxImpl->Save( rStrm );
245 17 : }
246 :
247 55 : void XclExpSst::SaveXml( XclExpXmlStream& rStrm )
248 : {
249 55 : mxImpl->SaveXml( rStrm );
250 55 : }
251 :
252 : // Merged cells ===============================================================
253 :
254 129 : XclExpMergedcells::XclExpMergedcells( const XclExpRoot& rRoot ) :
255 129 : XclExpRoot( rRoot )
256 : {
257 129 : }
258 :
259 6 : void XclExpMergedcells::AppendRange( const ScRange& rRange, sal_uInt32 nBaseXFId )
260 : {
261 6 : if( GetBiff() == EXC_BIFF8 )
262 : {
263 6 : maMergedRanges.Append( rRange );
264 6 : maBaseXFIds.push_back( nBaseXFId );
265 : }
266 6 : }
267 :
268 34 : sal_uInt32 XclExpMergedcells::GetBaseXFId( const ScAddress& rPos ) const
269 : {
270 : OSL_ENSURE( maBaseXFIds.size() == maMergedRanges.size(), "XclExpMergedcells::GetBaseXFId - invalid lists" );
271 34 : ScfUInt32Vec::const_iterator aIt = maBaseXFIds.begin();
272 34 : ScRangeList& rNCRanges = const_cast< ScRangeList& >( maMergedRanges );
273 50 : for ( size_t i = 0, nRanges = rNCRanges.size(); i < nRanges; ++i, ++aIt )
274 : {
275 50 : const ScRange* pScRange = rNCRanges[ i ];
276 50 : if( pScRange->In( rPos ) )
277 34 : return *aIt;
278 : }
279 0 : return EXC_XFID_NOTFOUND;
280 : }
281 :
282 29 : void XclExpMergedcells::Save( XclExpStream& rStrm )
283 : {
284 29 : if( GetBiff() == EXC_BIFF8 )
285 : {
286 29 : XclRangeList aXclRanges;
287 29 : GetAddressConverter().ConvertRangeList( aXclRanges, maMergedRanges, true );
288 29 : size_t nFirstRange = 0;
289 29 : size_t nRemainingRanges = aXclRanges.size();
290 60 : while( nRemainingRanges > 0 )
291 : {
292 2 : size_t nRangeCount = ::std::min< size_t >( nRemainingRanges, EXC_MERGEDCELLS_MAXCOUNT );
293 2 : rStrm.StartRecord( EXC_ID_MERGEDCELLS, 2 + 8 * nRangeCount );
294 2 : aXclRanges.WriteSubList( rStrm, nFirstRange, nRangeCount );
295 2 : rStrm.EndRecord();
296 2 : nFirstRange += nRangeCount;
297 2 : nRemainingRanges -= nRangeCount;
298 29 : }
299 : }
300 29 : }
301 :
302 100 : void XclExpMergedcells::SaveXml( XclExpXmlStream& rStrm )
303 : {
304 100 : size_t nCount = maMergedRanges.size();
305 100 : if( !nCount )
306 198 : return;
307 2 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
308 : rWorksheet->startElement( XML_mergeCells,
309 : XML_count, OString::number( nCount ).getStr(),
310 2 : FSEND );
311 5 : for( size_t i = 0; i < nCount; ++i )
312 : {
313 3 : if( const ScRange* pRange = maMergedRanges[ i ] )
314 : {
315 : rWorksheet->singleElement( XML_mergeCell,
316 : XML_ref, XclXmlUtils::ToOString( *pRange ).getStr(),
317 3 : FSEND );
318 : }
319 : }
320 2 : rWorksheet->endElement( XML_mergeCells );
321 : }
322 :
323 : // Hyperlinks =================================================================
324 :
325 3 : XclExpHyperlink::XclExpHyperlink( const XclExpRoot& rRoot, const SvxURLField& rUrlField, const ScAddress& rScPos ) :
326 : XclExpRecord( EXC_ID_HLINK ),
327 : maScPos( rScPos ),
328 3 : mxVarData( new SvMemoryStream ),
329 : mnFlags( 0 ),
330 6 : mbSetDisplay( true )
331 : {
332 3 : const OUString& rUrl = rUrlField.GetURL();
333 3 : const OUString& rRepr = rUrlField.GetRepresentation();
334 3 : INetURLObject aUrlObj( rUrl );
335 3 : const INetProtocol eProtocol = aUrlObj.GetProtocol();
336 3 : bool bWithRepr = !rRepr.isEmpty();
337 6 : XclExpStream aXclStrm( *mxVarData, rRoot ); // using in raw write mode.
338 :
339 : // description
340 3 : if( bWithRepr )
341 : {
342 0 : XclExpString aDescr( rRepr, EXC_STR_FORCEUNICODE, 255 );
343 0 : aXclStrm << sal_uInt32( aDescr.Len() + 1 ); // string length + 1 trailing zero word
344 0 : aDescr.WriteBuffer( aXclStrm ); // NO flags
345 0 : aXclStrm << sal_uInt16( 0 );
346 :
347 0 : mnFlags |= EXC_HLINK_DESCR;
348 0 : m_Repr = rRepr;
349 : }
350 :
351 : // file link or URL
352 3 : if( eProtocol == INetProtocol::File || eProtocol == INetProtocol::Smb )
353 : {
354 : sal_uInt16 nLevel;
355 : bool bRel;
356 : /* TODO: should we differentiate between BIFF and OOXML and write IURI
357 : * encoded for OOXML? */
358 0 : OUString aFileName( BuildFileName( nLevel, bRel, rUrl, rRoot, false ) );
359 :
360 0 : if( eProtocol == INetProtocol::Smb )
361 : {
362 : // #n382718# (and #n261623#) Convert smb notation to '\\'
363 0 : aFileName = aUrlObj.GetMainURL( INetURLObject::NO_DECODE );
364 0 : aFileName = aFileName.copy(4); // skip the 'smb:' part
365 0 : aFileName = aFileName.replace('/', '\\');
366 : }
367 :
368 0 : if( !bRel )
369 0 : mnFlags |= EXC_HLINK_ABS;
370 0 : mnFlags |= EXC_HLINK_BODY;
371 :
372 : OString aAsciiLink(OUStringToOString(aFileName,
373 0 : rRoot.GetTextEncoding()));
374 0 : XclExpString aLink( aFileName, EXC_STR_FORCEUNICODE, 255 );
375 0 : aXclStrm << XclTools::maGuidFileMoniker
376 0 : << nLevel
377 0 : << sal_uInt32( aAsciiLink.getLength() + 1 ); // string length + 1 trailing zero byte
378 0 : aXclStrm.Write( aAsciiLink.getStr(), aAsciiLink.getLength() );
379 0 : aXclStrm << sal_uInt8( 0 )
380 0 : << sal_uInt32( 0xDEADFFFF );
381 0 : aXclStrm.WriteZeroBytes( 20 );
382 0 : aXclStrm << sal_uInt32( aLink.GetBufferSize() + 6 )
383 0 : << sal_uInt32( aLink.GetBufferSize() ) // byte count, not string length
384 0 : << sal_uInt16( 0x0003 );
385 0 : aLink.WriteBuffer( aXclStrm ); // NO flags
386 :
387 0 : if (m_Repr.isEmpty())
388 0 : m_Repr = aFileName;
389 :
390 0 : msTarget = XclXmlUtils::ToOUString( aLink );
391 : // ooxml expects the file:/// part appended ( or at least
392 : // ms2007 does, ms2010 is more tolerant )
393 0 : msTarget = "file:///" + msTarget;
394 : }
395 3 : else if( eProtocol != INetProtocol::NotValid )
396 : {
397 2 : XclExpString aUrl( aUrlObj.GetURLNoMark(), EXC_STR_FORCEUNICODE, 255 );
398 2 : aXclStrm << XclTools::maGuidUrlMoniker
399 4 : << sal_uInt32( aUrl.GetBufferSize() + 2 ); // byte count + 1 trailing zero word
400 2 : aUrl.WriteBuffer( aXclStrm ); // NO flags
401 2 : aXclStrm << sal_uInt16( 0 );
402 :
403 2 : mnFlags |= EXC_HLINK_BODY | EXC_HLINK_ABS;
404 2 : if (m_Repr.isEmpty())
405 2 : m_Repr = rUrl;
406 :
407 2 : msTarget = XclXmlUtils::ToOUString( aUrl );
408 : }
409 1 : else if( !rUrl.isEmpty() && rUrl[0] == '#' ) // hack for #89066#
410 : {
411 1 : OUString aTextMark( rUrl.copy( 1 ) );
412 :
413 1 : sal_Int32 nSepPos = aTextMark.indexOf( '.' );
414 1 : if(nSepPos != -1)
415 : {
416 1 : aTextMark = aTextMark.replaceAt( nSepPos, 1, "!" );
417 1 : OUString aSheetName( aTextMark.copy(0, nSepPos));
418 :
419 1 : if ( aSheetName.indexOf(' ') != -1 && aSheetName[0] != '\'')
420 : {
421 0 : aTextMark = "'" + aTextMark.replaceAt(nSepPos, 0, "'");
422 1 : }
423 : }
424 :
425 1 : mxTextMark.reset( new XclExpString( aTextMark, EXC_STR_FORCEUNICODE, 255 ) );
426 : }
427 :
428 : // text mark
429 3 : if( !mxTextMark.get() && aUrlObj.HasMark() )
430 0 : mxTextMark.reset( new XclExpString( aUrlObj.GetMark(), EXC_STR_FORCEUNICODE, 255 ) );
431 :
432 3 : if( mxTextMark.get() )
433 : {
434 1 : aXclStrm << sal_uInt32( mxTextMark->Len() + 1 ); // string length + 1 trailing zero word
435 1 : mxTextMark->WriteBuffer( aXclStrm ); // NO flags
436 1 : aXclStrm << sal_uInt16( 0 );
437 :
438 1 : mnFlags |= EXC_HLINK_MARK;
439 : }
440 :
441 6 : SetRecSize( 32 + mxVarData->Tell() );
442 3 : }
443 :
444 3 : XclExpHyperlink::~XclExpHyperlink()
445 : {
446 3 : }
447 :
448 0 : OUString XclExpHyperlink::BuildFileName(
449 : sal_uInt16& rnLevel, bool& rbRel, const OUString& rUrl, const XclExpRoot& rRoot, bool bEncoded )
450 : {
451 0 : INetURLObject aURLObject( rUrl );
452 0 : OUString aDosName( bEncoded ? aURLObject.GetURLPath() : aURLObject.getFSysPath( INetURLObject::FSYS_DOS ) );
453 0 : rnLevel = 0;
454 0 : rbRel = rRoot.IsRelUrl();
455 :
456 0 : if( rbRel )
457 : {
458 : // try to convert to relative file name
459 0 : OUString aTmpName( aDosName );
460 0 : aDosName = INetURLObject::GetRelURL( rRoot.GetBasePath(), rUrl,
461 : INetURLObject::WAS_ENCODED,
462 0 : (bEncoded ? INetURLObject::DECODE_TO_IURI : INetURLObject::DECODE_WITH_CHARSET));
463 :
464 0 : if (aDosName.startsWith(INET_FILE_SCHEME))
465 : {
466 : // not converted to rel -> back to old, return absolute flag
467 0 : aDosName = aTmpName;
468 0 : rbRel = false;
469 : }
470 0 : else if (aDosName.startsWith("./"))
471 : {
472 0 : aDosName = aDosName.copy(2);
473 : }
474 : else
475 : {
476 0 : while (aDosName.startsWith("../"))
477 : {
478 0 : aDosName = aDosName.copy(3);
479 0 : ++rnLevel;
480 : }
481 0 : }
482 : }
483 0 : return aDosName;
484 : }
485 :
486 0 : void XclExpHyperlink::WriteBody( XclExpStream& rStrm )
487 : {
488 0 : sal_uInt16 nXclCol = static_cast< sal_uInt16 >( maScPos.Col() );
489 0 : sal_uInt16 nXclRow = static_cast< sal_uInt16 >( maScPos.Row() );
490 0 : rStrm << nXclRow << nXclRow << nXclCol << nXclCol;
491 0 : WriteEmbeddedData( rStrm );
492 0 : }
493 :
494 3 : void XclExpHyperlink::WriteEmbeddedData( XclExpStream& rStrm )
495 : {
496 3 : rStrm << XclTools::maGuidStdLink
497 3 : << sal_uInt32( 2 )
498 6 : << mnFlags;
499 :
500 3 : mxVarData->Seek( STREAM_SEEK_TO_BEGIN );
501 3 : rStrm.CopyFromStream( *mxVarData );
502 3 : }
503 :
504 0 : void XclExpHyperlink::SaveXml( XclExpXmlStream& rStrm )
505 : {
506 0 : OUString sId = !msTarget.isEmpty() ? rStrm.addRelation( rStrm.GetCurrentStream()->getOutputStream(),
507 : XclXmlUtils::ToOUString( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
508 0 : msTarget, true ) : OUString();
509 0 : rStrm.GetCurrentStream()->singleElement( XML_hyperlink,
510 : XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(),
511 0 : FSNS( XML_r, XML_id ), !sId.isEmpty()
512 0 : ? XclXmlUtils::ToOString( sId ).getStr()
513 : : NULL,
514 0 : XML_location, mxTextMark.get() != NULL
515 0 : ? XclXmlUtils::ToOString( *mxTextMark ).getStr()
516 : : NULL,
517 : // OOXTODO: XML_tooltip, from record HLinkTooltip 800h wzTooltip
518 : XML_display, mbSetDisplay
519 0 : ? XclXmlUtils::ToOString(m_Repr).getStr()
520 : : NULL,
521 0 : FSEND );
522 0 : }
523 :
524 : // Label ranges ===============================================================
525 :
526 29 : XclExpLabelranges::XclExpLabelranges( const XclExpRoot& rRoot ) :
527 29 : XclExpRoot( rRoot )
528 : {
529 29 : SCTAB nScTab = GetCurrScTab();
530 : // row label ranges
531 29 : FillRangeList( maRowRanges, rRoot.GetDoc().GetRowNameRangesRef(), nScTab );
532 : // row labels only over 1 column (restriction of Excel97/2000/XP)
533 29 : for ( size_t i = 0, nRanges = maRowRanges.size(); i < nRanges; ++i )
534 : {
535 0 : ScRange* pScRange = maRowRanges[ i ];
536 0 : if( pScRange->aStart.Col() != pScRange->aEnd.Col() )
537 0 : pScRange->aEnd.SetCol( pScRange->aStart.Col() );
538 : }
539 : // col label ranges
540 29 : FillRangeList( maColRanges, rRoot.GetDoc().GetColNameRangesRef(), nScTab );
541 29 : }
542 :
543 58 : void XclExpLabelranges::FillRangeList( ScRangeList& rScRanges,
544 : ScRangePairListRef xLabelRangesRef, SCTAB nScTab )
545 : {
546 58 : for ( size_t i = 0, nPairs = xLabelRangesRef->size(); i < nPairs; ++i )
547 : {
548 0 : ScRangePair* pRangePair = (*xLabelRangesRef)[i];
549 0 : const ScRange& rScRange = pRangePair->GetRange( 0 );
550 0 : if( rScRange.aStart.Tab() == nScTab )
551 0 : rScRanges.Append( rScRange );
552 : }
553 58 : }
554 :
555 29 : void XclExpLabelranges::Save( XclExpStream& rStrm )
556 : {
557 29 : XclExpAddressConverter& rAddrConv = GetAddressConverter();
558 58 : XclRangeList aRowXclRanges, aColXclRanges;
559 29 : rAddrConv.ConvertRangeList( aRowXclRanges, maRowRanges, false );
560 29 : rAddrConv.ConvertRangeList( aColXclRanges, maColRanges, false );
561 29 : if( !aRowXclRanges.empty() || !aColXclRanges.empty() )
562 : {
563 0 : rStrm.StartRecord( EXC_ID_LABELRANGES, 4 + 8 * (aRowXclRanges.size() + aColXclRanges.size()) );
564 0 : rStrm << aRowXclRanges << aColXclRanges;
565 0 : rStrm.EndRecord();
566 29 : }
567 29 : }
568 :
569 : // Conditional formatting ====================================================
570 :
571 : /** Represents a CF record that contains one condition of a conditional format. */
572 20 : class XclExpCFImpl : protected XclExpRoot
573 : {
574 : public:
575 : explicit XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority = 0 );
576 :
577 : /** Writes the body of the CF record. */
578 : void WriteBody( XclExpStream& rStrm );
579 : void SaveXml( XclExpXmlStream& rStrm );
580 :
581 : private:
582 : const ScCondFormatEntry& mrFormatEntry; /// Calc conditional format entry.
583 : XclFontData maFontData; /// Font formatting attributes.
584 : XclExpCellBorder maBorder; /// Border formatting attributes.
585 : XclExpCellArea maArea; /// Pattern formatting attributes.
586 : XclTokenArrayRef mxTokArr1; /// Formula for first condition.
587 : XclTokenArrayRef mxTokArr2; /// Formula for second condition.
588 : sal_uInt32 mnFontColorId; /// Font color ID.
589 : sal_uInt8 mnType; /// Type of the condition (cell/formula).
590 : sal_uInt8 mnOperator; /// Comparison operator for cell type.
591 : sal_Int32 mnPriority; /// Priority of this entry; needed for oox export
592 : bool mbFontUsed; /// true = Any font attribute used.
593 : bool mbHeightUsed; /// true = Font height used.
594 : bool mbWeightUsed; /// true = Font weight used.
595 : bool mbColorUsed; /// true = Font color used.
596 : bool mbUnderlUsed; /// true = Font underline type used.
597 : bool mbItalicUsed; /// true = Font posture used.
598 : bool mbStrikeUsed; /// true = Font strikeout used.
599 : bool mbBorderUsed; /// true = Border attribute used.
600 : bool mbPattUsed; /// true = Pattern attribute used.
601 : };
602 :
603 10 : XclExpCFImpl::XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority ) :
604 : XclExpRoot( rRoot ),
605 : mrFormatEntry( rFormatEntry ),
606 : mnFontColorId( 0 ),
607 : mnType( EXC_CF_TYPE_CELL ),
608 : mnOperator( EXC_CF_CMP_NONE ),
609 : mnPriority( nPriority ),
610 : mbFontUsed( false ),
611 : mbHeightUsed( false ),
612 : mbWeightUsed( false ),
613 : mbColorUsed( false ),
614 : mbUnderlUsed( false ),
615 : mbItalicUsed( false ),
616 : mbStrikeUsed( false ),
617 : mbBorderUsed( false ),
618 10 : mbPattUsed( false )
619 : {
620 : /* Get formatting attributes here, and not in WriteBody(). This is needed to
621 : correctly insert all colors into the palette. */
622 :
623 10 : if( SfxStyleSheetBase* pStyleSheet = GetDoc().GetStyleSheetPool()->Find( mrFormatEntry.GetStyle(), SFX_STYLE_FAMILY_PARA ) )
624 : {
625 10 : const SfxItemSet& rItemSet = pStyleSheet->GetItemSet();
626 :
627 : // font
628 10 : mbHeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_HEIGHT, true );
629 10 : mbWeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_WEIGHT, true );
630 10 : mbColorUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_COLOR, true );
631 10 : mbUnderlUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_UNDERLINE, true );
632 10 : mbItalicUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_POSTURE, true );
633 10 : mbStrikeUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_CROSSEDOUT, true );
634 10 : mbFontUsed = mbHeightUsed || mbWeightUsed || mbColorUsed || mbUnderlUsed || mbItalicUsed || mbStrikeUsed;
635 10 : if( mbFontUsed )
636 : {
637 0 : vcl::Font aFont;
638 0 : ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW );
639 0 : maFontData.FillFromVclFont( aFont );
640 0 : mnFontColorId = GetPalette().InsertColor( maFontData.maColor, EXC_COLOR_CELLTEXT );
641 : }
642 :
643 : // border
644 10 : mbBorderUsed = ScfTools::CheckItem( rItemSet, ATTR_BORDER, true );
645 10 : if( mbBorderUsed )
646 0 : maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
647 :
648 : // pattern
649 10 : mbPattUsed = ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, true );
650 10 : if( mbPattUsed )
651 0 : maArea.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
652 : }
653 :
654 : // *** mode and comparison operator ***
655 :
656 10 : bool bFmla2 = false;
657 10 : switch( rFormatEntry.GetOperation() )
658 : {
659 0 : case SC_COND_NONE: mnType = EXC_CF_TYPE_NONE; break;
660 0 : case SC_COND_BETWEEN: mnOperator = EXC_CF_CMP_BETWEEN; bFmla2 = true; break;
661 0 : case SC_COND_NOTBETWEEN: mnOperator = EXC_CF_CMP_NOT_BETWEEN; bFmla2 = true; break;
662 0 : case SC_COND_EQUAL: mnOperator = EXC_CF_CMP_EQUAL; break;
663 0 : case SC_COND_NOTEQUAL: mnOperator = EXC_CF_CMP_NOT_EQUAL; break;
664 0 : case SC_COND_GREATER: mnOperator = EXC_CF_CMP_GREATER; break;
665 0 : case SC_COND_LESS: mnOperator = EXC_CF_CMP_LESS; break;
666 0 : case SC_COND_EQGREATER: mnOperator = EXC_CF_CMP_GREATER_EQUAL; break;
667 0 : case SC_COND_EQLESS: mnOperator = EXC_CF_CMP_LESS_EQUAL; break;
668 2 : case SC_COND_DIRECT: mnType = EXC_CF_TYPE_FMLA; break;
669 8 : default: mnType = EXC_CF_TYPE_NONE;
670 : OSL_FAIL( "XclExpCF::WriteBody - unknown condition type" );
671 : }
672 :
673 : // *** formulas ***
674 :
675 10 : XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
676 :
677 10 : boost::scoped_ptr< ScTokenArray > xScTokArr( mrFormatEntry.CreateTokenArry( 0 ) );
678 10 : mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
679 :
680 10 : if( bFmla2 )
681 : {
682 0 : xScTokArr.reset( mrFormatEntry.CreateTokenArry( 1 ) );
683 0 : mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
684 10 : }
685 10 : }
686 :
687 0 : void XclExpCFImpl::WriteBody( XclExpStream& rStrm )
688 : {
689 : // *** mode and comparison operator ***
690 :
691 0 : rStrm << mnType << mnOperator;
692 :
693 : // *** formula sizes ***
694 :
695 0 : sal_uInt16 nFmlaSize1 = mxTokArr1.get() ? mxTokArr1->GetSize() : 0;
696 0 : sal_uInt16 nFmlaSize2 = mxTokArr2.get() ? mxTokArr2->GetSize() : 0;
697 0 : rStrm << nFmlaSize1 << nFmlaSize2;
698 :
699 : // *** formatting blocks ***
700 :
701 0 : if( mbFontUsed || mbBorderUsed || mbPattUsed )
702 : {
703 0 : sal_uInt32 nFlags = EXC_CF_ALLDEFAULT;
704 :
705 0 : ::set_flag( nFlags, EXC_CF_BLOCK_FONT, mbFontUsed );
706 0 : ::set_flag( nFlags, EXC_CF_BLOCK_BORDER, mbBorderUsed );
707 0 : ::set_flag( nFlags, EXC_CF_BLOCK_AREA, mbPattUsed );
708 :
709 : // attributes used -> set flags to 0.
710 0 : ::set_flag( nFlags, EXC_CF_BORDER_ALL, !mbBorderUsed );
711 0 : ::set_flag( nFlags, EXC_CF_AREA_ALL, !mbPattUsed );
712 :
713 0 : rStrm << nFlags << sal_uInt16( 0 );
714 :
715 0 : if( mbFontUsed )
716 : {
717 : // font height, 0xFFFFFFFF indicates unused
718 0 : sal_uInt32 nHeight = mbHeightUsed ? maFontData.mnHeight : 0xFFFFFFFF;
719 : // font style: italic and strikeout
720 0 : sal_uInt32 nStyle = 0;
721 0 : ::set_flag( nStyle, EXC_CF_FONT_STYLE, maFontData.mbItalic );
722 0 : ::set_flag( nStyle, EXC_CF_FONT_STRIKEOUT, maFontData.mbStrikeout );
723 : // font color, 0xFFFFFFFF indicates unused
724 0 : sal_uInt32 nColor = mbColorUsed ? GetPalette().GetColorIndex( mnFontColorId ) : 0xFFFFFFFF;
725 : // font used flags for italic, weight, and strikeout -> 0 = used, 1 = default
726 0 : sal_uInt32 nFontFlags1 = EXC_CF_FONT_ALLDEFAULT;
727 0 : ::set_flag( nFontFlags1, EXC_CF_FONT_STYLE, !(mbItalicUsed || mbWeightUsed) );
728 0 : ::set_flag( nFontFlags1, EXC_CF_FONT_STRIKEOUT, !mbStrikeUsed );
729 : // font used flag for underline -> 0 = used, 1 = default
730 0 : sal_uInt32 nFontFlags3 = mbUnderlUsed ? 0 : EXC_CF_FONT_UNDERL;
731 :
732 0 : rStrm.WriteZeroBytesToRecord( 64 );
733 0 : rStrm << nHeight
734 0 : << nStyle
735 0 : << maFontData.mnWeight
736 0 : << EXC_FONTESC_NONE
737 0 : << maFontData.mnUnderline;
738 0 : rStrm.WriteZeroBytesToRecord( 3 );
739 0 : rStrm << nColor
740 0 : << sal_uInt32( 0 )
741 0 : << nFontFlags1
742 0 : << EXC_CF_FONT_ESCAPEM // escapement never used -> set the flag
743 0 : << nFontFlags3;
744 0 : rStrm.WriteZeroBytesToRecord( 16 );
745 0 : rStrm << sal_uInt16( 1 ); // must be 1
746 : }
747 :
748 0 : if( mbBorderUsed )
749 : {
750 0 : sal_uInt16 nLineStyle = 0;
751 0 : sal_uInt32 nLineColor = 0;
752 0 : maBorder.SetFinalColors( GetPalette() );
753 0 : maBorder.FillToCF8( nLineStyle, nLineColor );
754 0 : rStrm << nLineStyle << nLineColor << sal_uInt16( 0 );
755 : }
756 :
757 0 : if( mbPattUsed )
758 : {
759 0 : sal_uInt16 nPattern = 0, nColor = 0;
760 0 : maArea.SetFinalColors( GetPalette() );
761 0 : maArea.FillToCF8( nPattern, nColor );
762 0 : rStrm << nPattern << nColor;
763 0 : }
764 : }
765 : else
766 : {
767 : // no data blocks at all
768 0 : rStrm << sal_uInt32( 0 ) << sal_uInt16( 0 );
769 : }
770 :
771 : // *** formulas ***
772 :
773 0 : if( mxTokArr1.get() )
774 0 : mxTokArr1->WriteArray( rStrm );
775 0 : if( mxTokArr2.get() )
776 0 : mxTokArr2->WriteArray( rStrm );
777 0 : }
778 :
779 : namespace {
780 :
781 10 : const char* GetOperatorString(ScConditionMode eMode, bool& bFrmla2)
782 : {
783 10 : const char *pRet = NULL;
784 10 : switch(eMode)
785 : {
786 : case SC_COND_EQUAL:
787 0 : pRet = "equal";
788 0 : break;
789 : case SC_COND_LESS:
790 0 : pRet = "lessThan";
791 0 : break;
792 : case SC_COND_GREATER:
793 0 : pRet = "greaterThan";
794 0 : break;
795 : case SC_COND_EQLESS:
796 0 : pRet = "lessThanOrEqual";
797 0 : break;
798 : case SC_COND_EQGREATER:
799 0 : pRet = "greaterThanOrEqual";
800 0 : break;
801 : case SC_COND_NOTEQUAL:
802 0 : pRet = "notEqual";
803 0 : break;
804 : case SC_COND_BETWEEN:
805 0 : bFrmla2 = true;
806 0 : pRet = "between";
807 0 : break;
808 : case SC_COND_NOTBETWEEN:
809 0 : bFrmla2 = true;
810 0 : pRet = "notBetween";
811 0 : break;
812 : case SC_COND_DUPLICATE:
813 0 : pRet = NULL;
814 0 : break;
815 : case SC_COND_NOTDUPLICATE:
816 0 : pRet = NULL;
817 0 : break;
818 : case SC_COND_DIRECT:
819 2 : break;
820 : case SC_COND_NONE:
821 : default:
822 8 : break;
823 : }
824 10 : return pRet;
825 : }
826 :
827 10 : const char* GetTypeString(ScConditionMode eMode)
828 : {
829 10 : switch(eMode)
830 : {
831 : case SC_COND_DIRECT:
832 2 : return "expression";
833 : case SC_COND_TOP10:
834 : case SC_COND_TOP_PERCENT:
835 : case SC_COND_BOTTOM10:
836 : case SC_COND_BOTTOM_PERCENT:
837 4 : return "top10";
838 : case SC_COND_ABOVE_AVERAGE:
839 : case SC_COND_BELOW_AVERAGE:
840 : case SC_COND_ABOVE_EQUAL_AVERAGE:
841 : case SC_COND_BELOW_EQUAL_AVERAGE:
842 4 : return "aboveAverage";
843 : case SC_COND_NOTDUPLICATE:
844 0 : return "uniqueValues";
845 : case SC_COND_DUPLICATE:
846 0 : return "duplicateValues";
847 : case SC_COND_ERROR:
848 0 : return "containsErrors";
849 : case SC_COND_NOERROR:
850 0 : return "notContainsErrors";
851 : case SC_COND_BEGINS_WITH:
852 0 : return "beginsWith";
853 : case SC_COND_ENDS_WITH:
854 0 : return "endsWith";
855 : case SC_COND_CONTAINS_TEXT:
856 0 : return "containsText";
857 : case SC_COND_NOT_CONTAINS_TEXT:
858 0 : return "notContainsText";
859 : default:
860 0 : return "cellIs";
861 : }
862 : }
863 :
864 20 : bool IsTopBottomRule(ScConditionMode eMode)
865 : {
866 20 : switch(eMode)
867 : {
868 : case SC_COND_TOP10:
869 : case SC_COND_BOTTOM10:
870 : case SC_COND_TOP_PERCENT:
871 : case SC_COND_BOTTOM_PERCENT:
872 8 : return true;
873 : default:
874 12 : break;
875 : }
876 :
877 12 : return false;
878 : }
879 :
880 20 : bool IsTextRule(ScConditionMode eMode)
881 : {
882 20 : switch(eMode)
883 : {
884 : case SC_COND_BEGINS_WITH:
885 : case SC_COND_ENDS_WITH:
886 : case SC_COND_CONTAINS_TEXT:
887 : case SC_COND_NOT_CONTAINS_TEXT:
888 0 : return true;
889 : default:
890 20 : break;
891 : }
892 :
893 20 : return false;
894 : }
895 :
896 : }
897 :
898 10 : void XclExpCFImpl::SaveXml( XclExpXmlStream& rStrm )
899 : {
900 10 : bool bFmla2 = false;
901 10 : ScConditionMode eOperation = mrFormatEntry.GetOperation();
902 10 : bool nAboveAverage = eOperation == SC_COND_ABOVE_AVERAGE ||
903 10 : eOperation == SC_COND_ABOVE_EQUAL_AVERAGE;
904 10 : bool nEqualAverage = eOperation == SC_COND_ABOVE_EQUAL_AVERAGE ||
905 10 : eOperation == SC_COND_BELOW_EQUAL_AVERAGE;
906 : bool nBottom = eOperation == SC_COND_BOTTOM10
907 10 : || eOperation == SC_COND_BOTTOM_PERCENT;
908 10 : bool nPercent = eOperation == SC_COND_TOP_PERCENT ||
909 10 : eOperation == SC_COND_BOTTOM_PERCENT;
910 10 : OString aRank("0");
911 10 : if(IsTopBottomRule(eOperation))
912 : {
913 : // position and formula grammar are not important
914 : // we only store a number there
915 4 : aRank = XclXmlUtils::ToOString(mrFormatEntry.GetExpression(ScAddress(0,0,0), 0));
916 : }
917 20 : OString aText;
918 10 : if(IsTextRule(eOperation))
919 : {
920 : // we need to write the text without quotes
921 : // we have to actually get the string from
922 : // the token array for that
923 0 : boost::scoped_ptr<ScTokenArray> pTokenArray(mrFormatEntry.CreateTokenArry(0));
924 0 : if(pTokenArray->GetLen())
925 0 : aText = XclXmlUtils::ToOString(pTokenArray->First()->GetString().getString());
926 : }
927 :
928 10 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
929 : rWorksheet->startElement( XML_cfRule,
930 : XML_type, GetTypeString( mrFormatEntry.GetOperation() ),
931 : XML_priority, OString::number( mnPriority + 1 ).getStr(),
932 : XML_operator, GetOperatorString( mrFormatEntry.GetOperation(), bFmla2 ),
933 : XML_aboveAverage, OString::number( int(nAboveAverage) ).getStr(),
934 : XML_equalAverage, OString::number( int(nEqualAverage) ).getStr(),
935 : XML_bottom, OString::number( int(nBottom) ).getStr(),
936 : XML_percent, OString::number( int(nPercent) ).getStr(),
937 : XML_rank, aRank.getStr(),
938 : XML_text, aText.getStr(),
939 10 : XML_dxfId, OString::number( GetDxfs().GetDxfId( mrFormatEntry.GetStyle() ) ).getStr(),
940 10 : FSEND );
941 10 : if(!IsTextRule(eOperation) && !IsTopBottomRule(eOperation))
942 : {
943 6 : rWorksheet->startElement( XML_formula, FSEND );
944 6 : rWorksheet->writeEscaped(XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormatEntry.GetValidSrcPos(),
945 12 : mrFormatEntry.CreateTokenArry(0)));
946 6 : rWorksheet->endElement( XML_formula );
947 6 : if (bFmla2)
948 : {
949 0 : rWorksheet->startElement( XML_formula, FSEND );
950 0 : rWorksheet->writeEscaped(XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormatEntry.GetValidSrcPos(),
951 0 : mrFormatEntry.CreateTokenArry(1)));
952 0 : rWorksheet->endElement( XML_formula );
953 : }
954 : }
955 : // OOXTODO: XML_extLst
956 20 : rWorksheet->endElement( XML_cfRule );
957 10 : }
958 :
959 10 : XclExpCF::XclExpCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority = 0 ) :
960 : XclExpRecord( EXC_ID_CF ),
961 : XclExpRoot( rRoot ),
962 10 : mxImpl( new XclExpCFImpl( rRoot, rFormatEntry, nPriority ) )
963 : {
964 10 : }
965 :
966 20 : XclExpCF::~XclExpCF()
967 : {
968 20 : }
969 :
970 0 : void XclExpCF::WriteBody( XclExpStream& rStrm )
971 : {
972 0 : mxImpl->WriteBody( rStrm );
973 0 : }
974 :
975 10 : void XclExpCF::SaveXml( XclExpXmlStream& rStrm )
976 : {
977 10 : mxImpl->SaveXml( rStrm );
978 10 : }
979 :
980 0 : XclExpDateFormat::XclExpDateFormat( const XclExpRoot& rRoot, const ScCondDateFormatEntry& rFormatEntry, sal_Int32 nPriority ):
981 : XclExpRecord( EXC_ID_CF ),
982 : XclExpRoot( rRoot ),
983 : mrFormatEntry(rFormatEntry),
984 0 : mnPriority(nPriority)
985 : {
986 0 : }
987 :
988 0 : XclExpDateFormat::~XclExpDateFormat()
989 : {
990 0 : }
991 :
992 : namespace {
993 :
994 0 : const char* getTimePeriodString( condformat::ScCondFormatDateType eType )
995 : {
996 0 : switch(eType)
997 : {
998 : case condformat::TODAY:
999 0 : return "today";
1000 : case condformat::YESTERDAY:
1001 0 : return "yesterday";
1002 : case condformat::TOMORROW:
1003 0 : return "yesterday";
1004 : case condformat::THISWEEK:
1005 0 : return "thisWeek";
1006 : case condformat::LASTWEEK:
1007 0 : return "lastWeek";
1008 : case condformat::NEXTWEEK:
1009 0 : return "nextWeek";
1010 : case condformat::THISMONTH:
1011 0 : return "thisMonth";
1012 : case condformat::LASTMONTH:
1013 0 : return "lastMonth";
1014 : case condformat::NEXTMONTH:
1015 0 : return "nextMonth";
1016 : case condformat::LAST7DAYS:
1017 0 : return "last7Days";
1018 : default:
1019 0 : break;
1020 : }
1021 0 : return NULL;
1022 : }
1023 :
1024 : }
1025 :
1026 0 : void XclExpDateFormat::SaveXml( XclExpXmlStream& rStrm )
1027 : {
1028 : // only write the supported entries into OOXML
1029 0 : const char* sTimePeriod = getTimePeriodString(mrFormatEntry.GetDateType());
1030 0 : if(!sTimePeriod)
1031 0 : return;
1032 :
1033 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1034 : rWorksheet->startElement( XML_cfRule,
1035 : XML_type, "timePeriod",
1036 : XML_priority, OString::number( mnPriority + 1 ).getStr(),
1037 : XML_timePeriod, sTimePeriod,
1038 0 : XML_dxfId, OString::number( GetDxfs().GetDxfId( mrFormatEntry.GetStyleName() ) ).getStr(),
1039 0 : FSEND );
1040 0 : rWorksheet->endElement( XML_cfRule);
1041 : }
1042 :
1043 25 : XclExpCfvo::XclExpCfvo(const XclExpRoot& rRoot, const ScColorScaleEntry& rEntry, const ScAddress& rAddr, bool bFirst):
1044 : XclExpRecord(),
1045 : XclExpRoot( rRoot ),
1046 : mrEntry(rEntry),
1047 : maSrcPos(rAddr),
1048 25 : mbFirst(bFirst)
1049 : {
1050 25 : }
1051 :
1052 : namespace {
1053 :
1054 25 : OString getColorScaleType( const ScColorScaleEntry& rEntry, bool bFirst )
1055 : {
1056 25 : switch(rEntry.GetType())
1057 : {
1058 : case COLORSCALE_MIN:
1059 3 : return "min";
1060 : case COLORSCALE_MAX:
1061 3 : return "max";
1062 : case COLORSCALE_PERCENT:
1063 3 : return "percent";
1064 : case COLORSCALE_FORMULA:
1065 3 : return "formula";
1066 : case COLORSCALE_AUTO:
1067 4 : if(bFirst)
1068 2 : return "min";
1069 : else
1070 2 : return "max";
1071 : case COLORSCALE_PERCENTILE:
1072 4 : return "percentile";
1073 : default:
1074 5 : break;
1075 : }
1076 :
1077 5 : return "num";
1078 : }
1079 :
1080 : }
1081 :
1082 25 : void XclExpCfvo::SaveXml( XclExpXmlStream& rStrm )
1083 : {
1084 25 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1085 :
1086 25 : OString aValue;
1087 25 : if(mrEntry.GetType() == COLORSCALE_FORMULA)
1088 : {
1089 3 : OUString aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), maSrcPos,
1090 6 : mrEntry.GetFormula()->Clone());
1091 3 : aValue = OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 );
1092 : }
1093 : else
1094 : {
1095 22 : aValue = OString::number( mrEntry.GetValue() );
1096 : }
1097 :
1098 : rWorksheet->startElement( XML_cfvo,
1099 : XML_type, getColorScaleType(mrEntry, mbFirst).getStr(),
1100 : XML_val, aValue.getStr(),
1101 25 : FSEND );
1102 :
1103 25 : rWorksheet->endElement( XML_cfvo );
1104 25 : }
1105 :
1106 20 : XclExpColScaleCol::XclExpColScaleCol( const XclExpRoot& rRoot, const Color& rColor ):
1107 : XclExpRecord(),
1108 : XclExpRoot( rRoot ),
1109 20 : mrColor( rColor )
1110 : {
1111 20 : }
1112 :
1113 40 : XclExpColScaleCol::~XclExpColScaleCol()
1114 : {
1115 40 : }
1116 :
1117 20 : void XclExpColScaleCol::SaveXml( XclExpXmlStream& rStrm )
1118 : {
1119 20 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1120 :
1121 : rWorksheet->startElement( XML_color,
1122 : XML_rgb, XclXmlUtils::ToOString( mrColor ).getStr(),
1123 20 : FSEND );
1124 :
1125 20 : rWorksheet->endElement( XML_color );
1126 20 : }
1127 :
1128 : namespace {
1129 :
1130 80 : OString createHexStringFromDigit(sal_uInt8 nDigit)
1131 : {
1132 80 : OString aString = OString::number( nDigit, 16 );
1133 80 : if(aString.getLength() == 1)
1134 4 : aString = aString + OString::number(0);
1135 80 : return aString;
1136 : }
1137 :
1138 5 : OString createGuidStringFromInt(sal_uInt8 nGuid[16])
1139 : {
1140 5 : OStringBuffer aBuffer;
1141 5 : aBuffer.append('{');
1142 85 : for(size_t i = 0; i < 16; ++i)
1143 : {
1144 80 : aBuffer.append(createHexStringFromDigit(nGuid[i]));
1145 80 : if(i == 3|| i == 5 || i == 7 || i == 9 )
1146 20 : aBuffer.append('-');
1147 : }
1148 5 : aBuffer.append('}');
1149 10 : OString aString = aBuffer.makeStringAndClear();
1150 10 : return aString.toAsciiUpperCase();
1151 : }
1152 :
1153 5 : OString generateGUIDString()
1154 : {
1155 : sal_uInt8 nGuid[16];
1156 5 : rtl_createUuid(nGuid, NULL, true);
1157 5 : return createGuidStringFromInt(nGuid);
1158 : }
1159 :
1160 : }
1161 :
1162 21 : XclExpCondfmt::XclExpCondfmt( const XclExpRoot& rRoot, const ScConditionalFormat& rCondFormat, XclExtLstRef xExtLst, sal_Int32& rIndex ) :
1163 : XclExpRecord( EXC_ID_CONDFMT ),
1164 21 : XclExpRoot( rRoot )
1165 : {
1166 21 : const ScRangeList& aScRanges = rCondFormat.GetRange();
1167 21 : GetAddressConverter().ConvertRangeList( maXclRanges, aScRanges, true );
1168 21 : if( !maXclRanges.empty() )
1169 : {
1170 21 : std::vector<XclExpExtCondFormatData> aExtEntries;
1171 42 : for( size_t nIndex = 0, nCount = rCondFormat.size(); nIndex < nCount; ++nIndex )
1172 21 : if( const ScFormatEntry* pFormatEntry = rCondFormat.GetEntry( nIndex ) )
1173 : {
1174 21 : if(pFormatEntry->GetType() == condformat::CONDITION)
1175 10 : maCFList.AppendNewRecord( new XclExpCF( GetRoot(), static_cast<const ScCondFormatEntry&>(*pFormatEntry), ++rIndex ) );
1176 11 : else if(pFormatEntry->GetType() == condformat::COLORSCALE)
1177 6 : maCFList.AppendNewRecord( new XclExpColorScale( GetRoot(), static_cast<const ScColorScaleFormat&>(*pFormatEntry), ++rIndex ) );
1178 5 : else if(pFormatEntry->GetType() == condformat::DATABAR)
1179 : {
1180 5 : const ScDataBarFormat& rFormat = static_cast<const ScDataBarFormat&>(*pFormatEntry);
1181 5 : XclExpExtCondFormatData aExtEntry;
1182 5 : aExtEntry.nPriority = -1;
1183 5 : aExtEntry.aGUID = generateGUIDString();
1184 5 : aExtEntry.pEntry = &rFormat;
1185 5 : aExtEntries.push_back(aExtEntry);
1186 :
1187 5 : maCFList.AppendNewRecord( new XclExpDataBar( GetRoot(), rFormat, ++rIndex, aExtEntry.aGUID));
1188 : }
1189 0 : else if(pFormatEntry->GetType() == condformat::ICONSET)
1190 : {
1191 : // don't export iconSet entries that are not in OOXML
1192 0 : const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pFormatEntry);
1193 0 : bool bNeedsExt = false;
1194 0 : switch (rIconSet.GetIconSetData()->eIconSetType)
1195 : {
1196 : case IconSet_3Smilies:
1197 : case IconSet_3ColorSmilies:
1198 : case IconSet_3Stars:
1199 : case IconSet_3Triangles:
1200 : case IconSet_5Boxes:
1201 : {
1202 0 : bNeedsExt = true;
1203 : }
1204 0 : break;
1205 : default:
1206 0 : break;
1207 : }
1208 :
1209 0 : bNeedsExt |= rIconSet.GetIconSetData()->mbCustom;
1210 :
1211 0 : if (bNeedsExt)
1212 : {
1213 0 : XclExpExtCondFormatData aExtEntry;
1214 0 : aExtEntry.nPriority = ++rIndex;
1215 0 : aExtEntry.aGUID = generateGUIDString();
1216 0 : aExtEntry.pEntry = &rIconSet;
1217 0 : aExtEntries.push_back(aExtEntry);
1218 : }
1219 : else
1220 0 : maCFList.AppendNewRecord( new XclExpIconSet( GetRoot(), rIconSet, ++rIndex ) );
1221 : }
1222 0 : else if(pFormatEntry->GetType() == condformat::DATE)
1223 0 : maCFList.AppendNewRecord( new XclExpDateFormat( GetRoot(), static_cast<const ScCondDateFormatEntry&>(*pFormatEntry), ++rIndex ) );
1224 : }
1225 21 : aScRanges.Format( msSeqRef, SCA_VALID, NULL, formula::FormulaGrammar::CONV_XL_A1 );
1226 :
1227 21 : if(!aExtEntries.empty() && xExtLst.get())
1228 : {
1229 5 : XclExpExtRef pParent = xExtLst->GetItem( XclExpExtDataBarType );
1230 5 : if( !pParent.get() )
1231 : {
1232 1 : xExtLst->AddRecord( XclExpExtRef(new XclExpExtCondFormat( *xExtLst.get() )) );
1233 1 : pParent = xExtLst->GetItem( XclExpExtDataBarType );
1234 : }
1235 10 : static_cast<XclExpExtCondFormat*>(xExtLst->GetItem( XclExpExtDataBarType ).get())->AddRecord(
1236 15 : XclExpExtConditionalFormattingRef(new XclExpExtConditionalFormatting( *pParent, aExtEntries, aScRanges)));
1237 21 : }
1238 : }
1239 21 : }
1240 :
1241 42 : XclExpCondfmt::~XclExpCondfmt()
1242 : {
1243 42 : }
1244 :
1245 42 : bool XclExpCondfmt::IsValid() const
1246 : {
1247 42 : return !maCFList.IsEmpty() && !maXclRanges.empty();
1248 : }
1249 :
1250 0 : void XclExpCondfmt::Save( XclExpStream& rStrm )
1251 : {
1252 0 : if( IsValid() )
1253 : {
1254 0 : XclExpRecord::Save( rStrm );
1255 0 : maCFList.Save( rStrm );
1256 : }
1257 0 : }
1258 :
1259 0 : void XclExpCondfmt::WriteBody( XclExpStream& rStrm )
1260 : {
1261 : OSL_ENSURE( !maCFList.IsEmpty(), "XclExpCondfmt::WriteBody - no CF records to write" );
1262 : OSL_ENSURE( !maXclRanges.empty(), "XclExpCondfmt::WriteBody - no cell ranges found" );
1263 :
1264 0 : rStrm << static_cast< sal_uInt16 >( maCFList.GetSize() )
1265 0 : << sal_uInt16( 1 )
1266 0 : << maXclRanges.GetEnclosingRange()
1267 0 : << maXclRanges;
1268 0 : }
1269 :
1270 21 : void XclExpCondfmt::SaveXml( XclExpXmlStream& rStrm )
1271 : {
1272 21 : if( !IsValid() )
1273 21 : return;
1274 :
1275 21 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1276 : rWorksheet->startElement( XML_conditionalFormatting,
1277 : XML_sqref, XclXmlUtils::ToOString( msSeqRef ).getStr(),
1278 : // OOXTODO: XML_pivot,
1279 21 : FSEND );
1280 :
1281 21 : maCFList.SaveXml( rStrm );
1282 :
1283 21 : rWorksheet->endElement( XML_conditionalFormatting );
1284 : }
1285 :
1286 6 : XclExpColorScale::XclExpColorScale( const XclExpRoot& rRoot, const ScColorScaleFormat& rFormat, sal_Int32 nPriority ):
1287 : XclExpRecord(),
1288 : XclExpRoot( rRoot ),
1289 6 : mnPriority( nPriority )
1290 : {
1291 6 : const ScRange* pRange = rFormat.GetRange().front();
1292 6 : ScAddress aAddr = pRange->aStart;
1293 63 : for(ScColorScaleFormat::const_iterator itr = rFormat.begin();
1294 42 : itr != rFormat.end(); ++itr)
1295 : {
1296 : // exact position is not important, we allow only absolute refs
1297 :
1298 15 : XclExpCfvoList::RecordRefType xCfvo( new XclExpCfvo( GetRoot(), *itr, aAddr ) );
1299 15 : maCfvoList.AppendRecord( xCfvo );
1300 30 : XclExpColScaleColList::RecordRefType xClo( new XclExpColScaleCol( GetRoot(), itr->GetColor() ) );
1301 15 : maColList.AppendRecord( xClo );
1302 15 : }
1303 6 : }
1304 :
1305 6 : void XclExpColorScale::SaveXml( XclExpXmlStream& rStrm )
1306 : {
1307 6 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1308 :
1309 : rWorksheet->startElement( XML_cfRule,
1310 : XML_type, "colorScale",
1311 : XML_priority, OString::number( mnPriority + 1 ).getStr(),
1312 6 : FSEND );
1313 :
1314 6 : rWorksheet->startElement( XML_colorScale, FSEND );
1315 :
1316 6 : maCfvoList.SaveXml(rStrm);
1317 6 : maColList.SaveXml(rStrm);
1318 :
1319 6 : rWorksheet->endElement( XML_colorScale );
1320 :
1321 6 : rWorksheet->endElement( XML_cfRule );
1322 6 : }
1323 :
1324 5 : XclExpDataBar::XclExpDataBar( const XclExpRoot& rRoot, const ScDataBarFormat& rFormat, sal_Int32 nPriority, const OString& rGUID):
1325 : XclExpRecord(),
1326 : XclExpRoot( rRoot ),
1327 : mrFormat( rFormat ),
1328 : mnPriority( nPriority ),
1329 5 : maGUID(rGUID)
1330 : {
1331 5 : const ScRange* pRange = rFormat.GetRange().front();
1332 5 : ScAddress aAddr = pRange->aStart;
1333 : // exact position is not important, we allow only absolute refs
1334 5 : mpCfvoLowerLimit.reset( new XclExpCfvo( GetRoot(), *mrFormat.GetDataBarData()->mpLowerLimit.get(), aAddr, true ) );
1335 5 : mpCfvoUpperLimit.reset( new XclExpCfvo( GetRoot(), *mrFormat.GetDataBarData()->mpUpperLimit.get(), aAddr, false ) );
1336 :
1337 5 : mpCol.reset( new XclExpColScaleCol( GetRoot(), mrFormat.GetDataBarData()->maPositiveColor ) );
1338 5 : }
1339 :
1340 5 : void XclExpDataBar::SaveXml( XclExpXmlStream& rStrm )
1341 : {
1342 5 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1343 :
1344 : rWorksheet->startElement( XML_cfRule,
1345 : XML_type, "dataBar",
1346 : XML_priority, OString::number( mnPriority + 1 ).getStr(),
1347 5 : FSEND );
1348 :
1349 : rWorksheet->startElement( XML_dataBar,
1350 5 : XML_showValue, OString::number(int(!mrFormat.GetDataBarData()->mbOnlyBar)),
1351 5 : XML_minLength, OString::number(sal_uInt32(mrFormat.GetDataBarData()->mnMinLength)),
1352 5 : XML_maxLength, OString::number(sal_uInt32(mrFormat.GetDataBarData()->mnMaxLength)),
1353 15 : FSEND );
1354 :
1355 5 : mpCfvoLowerLimit->SaveXml(rStrm);
1356 5 : mpCfvoUpperLimit->SaveXml(rStrm);
1357 5 : mpCol->SaveXml(rStrm);
1358 :
1359 5 : rWorksheet->endElement( XML_dataBar );
1360 :
1361 : // extLst entries for Excel 2010 and 2013
1362 5 : rWorksheet->startElement( XML_extLst, FSEND );
1363 : rWorksheet->startElement( XML_ext,
1364 : FSNS( XML_xmlns, XML_x14 ), "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main",
1365 : XML_uri, "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}",
1366 5 : FSEND );
1367 :
1368 5 : rWorksheet->startElementNS( XML_x14, XML_id, FSEND );
1369 5 : rWorksheet->write( maGUID.getStr() );
1370 5 : rWorksheet->endElementNS( XML_x14, XML_id );
1371 :
1372 5 : rWorksheet->endElement( XML_ext );
1373 5 : rWorksheet->endElement( XML_extLst );
1374 :
1375 5 : rWorksheet->endElement( XML_cfRule );
1376 5 : }
1377 :
1378 0 : XclExpIconSet::XclExpIconSet( const XclExpRoot& rRoot, const ScIconSetFormat& rFormat, sal_Int32 nPriority ):
1379 : XclExpRecord(),
1380 : XclExpRoot( rRoot ),
1381 : mrFormat( rFormat ),
1382 0 : mnPriority( nPriority )
1383 : {
1384 0 : const ScRange* pRange = rFormat.GetRange().front();
1385 0 : ScAddress aAddr = pRange->aStart;
1386 0 : for(ScIconSetFormat::const_iterator itr = rFormat.begin();
1387 0 : itr != rFormat.end(); ++itr)
1388 : {
1389 : // exact position is not important, we allow only absolute refs
1390 :
1391 0 : XclExpCfvoList::RecordRefType xCfvo( new XclExpCfvo( GetRoot(), *itr, aAddr ) );
1392 0 : maCfvoList.AppendRecord( xCfvo );
1393 0 : }
1394 0 : }
1395 :
1396 : namespace {
1397 :
1398 0 : const char* getIconSetName( ScIconSetType eType )
1399 : {
1400 0 : ScIconSetMap* pMap = ScIconSetFormat::getIconSetMap();
1401 0 : for(; pMap->pName; ++pMap)
1402 : {
1403 0 : if(pMap->eType == eType)
1404 0 : return pMap->pName;
1405 : }
1406 :
1407 0 : return "";
1408 : }
1409 :
1410 : }
1411 :
1412 0 : void XclExpIconSet::SaveXml( XclExpXmlStream& rStrm )
1413 : {
1414 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1415 :
1416 : rWorksheet->startElement( XML_cfRule,
1417 : XML_type, "iconSet",
1418 : XML_priority, OString::number( mnPriority + 1 ).getStr(),
1419 0 : FSEND );
1420 :
1421 0 : const char* pIconSetName = getIconSetName(mrFormat.GetIconSetData()->eIconSetType);
1422 : rWorksheet->startElement( XML_iconSet,
1423 : XML_iconSet, pIconSetName,
1424 0 : XML_showValue, mrFormat.GetIconSetData()->mbShowValue ? NULL : "0",
1425 0 : XML_reverse, mrFormat.GetIconSetData()->mbReverse ? "1" : NULL,
1426 0 : FSEND );
1427 :
1428 0 : maCfvoList.SaveXml( rStrm );
1429 :
1430 0 : rWorksheet->endElement( XML_iconSet );
1431 0 : rWorksheet->endElement( XML_cfRule );
1432 0 : }
1433 :
1434 129 : XclExpCondFormatBuffer::XclExpCondFormatBuffer( const XclExpRoot& rRoot, XclExtLstRef xExtLst ) :
1435 129 : XclExpRoot( rRoot )
1436 : {
1437 129 : if( const ScConditionalFormatList* pCondFmtList = GetDoc().GetCondFormList(GetCurrScTab()) )
1438 : {
1439 129 : sal_Int32 nIndex = 0;
1440 450 : for( ScConditionalFormatList::const_iterator itr = pCondFmtList->begin();
1441 300 : itr != pCondFmtList->end(); ++itr)
1442 : {
1443 21 : XclExpCondfmtList::RecordRefType xCondfmtRec( new XclExpCondfmt( GetRoot(), *itr, xExtLst, nIndex ));
1444 21 : if( xCondfmtRec->IsValid() )
1445 21 : maCondfmtList.AppendRecord( xCondfmtRec );
1446 21 : }
1447 : }
1448 129 : }
1449 :
1450 29 : void XclExpCondFormatBuffer::Save( XclExpStream& rStrm )
1451 : {
1452 29 : maCondfmtList.Save( rStrm );
1453 29 : }
1454 :
1455 100 : void XclExpCondFormatBuffer::SaveXml( XclExpXmlStream& rStrm )
1456 : {
1457 100 : maCondfmtList.SaveXml( rStrm );
1458 100 : }
1459 :
1460 : // Validation =================================================================
1461 :
1462 : namespace {
1463 :
1464 : /** Writes a formula for the DV record. */
1465 0 : void lclWriteDvFormula( XclExpStream& rStrm, const XclTokenArray* pXclTokArr )
1466 : {
1467 0 : sal_uInt16 nFmlaSize = pXclTokArr ? pXclTokArr->GetSize() : 0;
1468 0 : rStrm << nFmlaSize << sal_uInt16( 0 );
1469 0 : if( pXclTokArr )
1470 0 : pXclTokArr->WriteArray( rStrm );
1471 0 : }
1472 :
1473 : /** Writes a formula for the DV record, based on a single string. */
1474 0 : void lclWriteDvFormula( XclExpStream& rStrm, const XclExpString& rString )
1475 : {
1476 : // fake a formula with a single tStr token
1477 0 : rStrm << static_cast< sal_uInt16 >( rString.GetSize() + 1 )
1478 0 : << sal_uInt16( 0 )
1479 0 : << EXC_TOKID_STR
1480 0 : << rString;
1481 0 : }
1482 :
1483 0 : const char* lcl_GetValidationType( sal_uInt32 nFlags )
1484 : {
1485 0 : switch( nFlags & EXC_DV_MODE_MASK )
1486 : {
1487 0 : case EXC_DV_MODE_ANY: return "none";
1488 0 : case EXC_DV_MODE_WHOLE: return "whole";
1489 0 : case EXC_DV_MODE_DECIMAL: return "decimal";
1490 0 : case EXC_DV_MODE_LIST: return "list";
1491 0 : case EXC_DV_MODE_DATE: return "date";
1492 0 : case EXC_DV_MODE_TIME: return "time";
1493 0 : case EXC_DV_MODE_TEXTLEN: return "textLength";
1494 0 : case EXC_DV_MODE_CUSTOM: return "custom";
1495 : }
1496 0 : return NULL;
1497 : }
1498 :
1499 0 : const char* lcl_GetOperatorType( sal_uInt32 nFlags )
1500 : {
1501 0 : switch( nFlags & EXC_DV_COND_MASK )
1502 : {
1503 0 : case EXC_DV_COND_BETWEEN: return "between";
1504 0 : case EXC_DV_COND_NOTBETWEEN: return "notBetween";
1505 0 : case EXC_DV_COND_EQUAL: return "equal";
1506 0 : case EXC_DV_COND_NOTEQUAL: return "notEqual";
1507 0 : case EXC_DV_COND_GREATER: return "greaterThan";
1508 0 : case EXC_DV_COND_LESS: return "lessThan";
1509 0 : case EXC_DV_COND_EQGREATER: return "greaterThanOrEqual";
1510 0 : case EXC_DV_COND_EQLESS: return "lessThanOrEqual";
1511 : }
1512 0 : return NULL;
1513 : }
1514 :
1515 : } // namespace
1516 :
1517 0 : XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uLong nScHandle ) :
1518 : XclExpRecord( EXC_ID_DV ),
1519 : XclExpRoot( rRoot ),
1520 : mnFlags( 0 ),
1521 0 : mnScHandle( nScHandle )
1522 : {
1523 0 : if( const ScValidationData* pValData = GetDoc().GetValidationEntry( mnScHandle ) )
1524 : {
1525 : // prompt box - empty string represented by single NUL character
1526 0 : OUString aTitle, aText;
1527 0 : bool bShowPrompt = pValData->GetInput( aTitle, aText );
1528 0 : if( !aTitle.isEmpty() )
1529 0 : maPromptTitle.Assign( aTitle );
1530 : else
1531 0 : maPromptTitle.Assign( '\0' );
1532 0 : if( !aText.isEmpty() )
1533 0 : maPromptText.Assign( aText );
1534 : else
1535 0 : maPromptText.Assign( '\0' );
1536 :
1537 : // error box - empty string represented by single NUL character
1538 : ScValidErrorStyle eScErrorStyle;
1539 0 : bool bShowError = pValData->GetErrMsg( aTitle, aText, eScErrorStyle );
1540 0 : if( !aTitle.isEmpty() )
1541 0 : maErrorTitle.Assign( aTitle );
1542 : else
1543 0 : maErrorTitle.Assign( '\0' );
1544 0 : if( !aText.isEmpty() )
1545 0 : maErrorText.Assign( aText );
1546 : else
1547 0 : maErrorText.Assign( '\0' );
1548 :
1549 : // flags
1550 0 : switch( pValData->GetDataMode() )
1551 : {
1552 0 : case SC_VALID_ANY: mnFlags |= EXC_DV_MODE_ANY; break;
1553 0 : case SC_VALID_WHOLE: mnFlags |= EXC_DV_MODE_WHOLE; break;
1554 0 : case SC_VALID_DECIMAL: mnFlags |= EXC_DV_MODE_DECIMAL; break;
1555 0 : case SC_VALID_LIST: mnFlags |= EXC_DV_MODE_LIST; break;
1556 0 : case SC_VALID_DATE: mnFlags |= EXC_DV_MODE_DATE; break;
1557 0 : case SC_VALID_TIME: mnFlags |= EXC_DV_MODE_TIME; break;
1558 0 : case SC_VALID_TEXTLEN: mnFlags |= EXC_DV_MODE_TEXTLEN; break;
1559 0 : case SC_VALID_CUSTOM: mnFlags |= EXC_DV_MODE_CUSTOM; break;
1560 : default: OSL_FAIL( "XclExpDV::XclExpDV - unknown mode" );
1561 : }
1562 :
1563 0 : switch( pValData->GetOperation() )
1564 : {
1565 : case SC_COND_NONE:
1566 0 : case SC_COND_EQUAL: mnFlags |= EXC_DV_COND_EQUAL; break;
1567 0 : case SC_COND_LESS: mnFlags |= EXC_DV_COND_LESS; break;
1568 0 : case SC_COND_GREATER: mnFlags |= EXC_DV_COND_GREATER; break;
1569 0 : case SC_COND_EQLESS: mnFlags |= EXC_DV_COND_EQLESS; break;
1570 0 : case SC_COND_EQGREATER: mnFlags |= EXC_DV_COND_EQGREATER; break;
1571 0 : case SC_COND_NOTEQUAL: mnFlags |= EXC_DV_COND_NOTEQUAL; break;
1572 0 : case SC_COND_BETWEEN: mnFlags |= EXC_DV_COND_BETWEEN; break;
1573 0 : case SC_COND_NOTBETWEEN: mnFlags |= EXC_DV_COND_NOTBETWEEN; break;
1574 : default: OSL_FAIL( "XclExpDV::XclExpDV - unknown condition" );
1575 : }
1576 0 : switch( eScErrorStyle )
1577 : {
1578 0 : case SC_VALERR_STOP: mnFlags |= EXC_DV_ERROR_STOP; break;
1579 0 : case SC_VALERR_WARNING: mnFlags |= EXC_DV_ERROR_WARNING; break;
1580 0 : case SC_VALERR_INFO: mnFlags |= EXC_DV_ERROR_INFO; break;
1581 : case SC_VALERR_MACRO:
1582 : // set INFO for validity with macro call, delete title
1583 0 : mnFlags |= EXC_DV_ERROR_INFO;
1584 0 : maErrorTitle.Assign( '\0' ); // contains macro name
1585 0 : break;
1586 : default: OSL_FAIL( "XclExpDV::XclExpDV - unknown error style" );
1587 : }
1588 0 : ::set_flag( mnFlags, EXC_DV_IGNOREBLANK, pValData->IsIgnoreBlank() );
1589 0 : ::set_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN, pValData->GetListType() == css::sheet::TableValidationVisibility::INVISIBLE );
1590 0 : ::set_flag( mnFlags, EXC_DV_SHOWPROMPT, bShowPrompt );
1591 0 : ::set_flag( mnFlags, EXC_DV_SHOWERROR, bShowError );
1592 :
1593 : // formulas
1594 0 : XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
1595 0 : boost::scoped_ptr< ScTokenArray > xScTokArr;
1596 :
1597 : // first formula
1598 0 : xScTokArr.reset( pValData->CreateTokenArry( 0 ) );
1599 0 : if( xScTokArr.get() )
1600 : {
1601 0 : if( pValData->GetDataMode() == SC_VALID_LIST )
1602 : {
1603 0 : OUString aString;
1604 0 : if( XclTokenArrayHelper::GetStringList( aString, *xScTokArr, '\n' ) )
1605 : {
1606 0 : OUStringBuffer sFormulaBuf;
1607 0 : sFormulaBuf.append( '"' );
1608 : /* Formula is a list of string tokens -> build the Excel string.
1609 : Data validity is BIFF8 only (important for the XclExpString object).
1610 : Excel uses the NUL character as string list separator. */
1611 0 : mxString1.reset( new XclExpString( EXC_STR_8BITLENGTH ) );
1612 0 : sal_Int32 nTokenCnt = comphelper::string::getTokenCount(aString, '\n');
1613 0 : sal_Int32 nStringIx = 0;
1614 0 : for( sal_Int32 nToken = 0; nToken < nTokenCnt; ++nToken )
1615 : {
1616 0 : OUString aToken( aString.getToken( 0, '\n', nStringIx ) );
1617 0 : if( nToken > 0 )
1618 : {
1619 0 : mxString1->Append(OUString(static_cast<sal_Unicode>('\0')));
1620 0 : sFormulaBuf.append( ',' );
1621 : }
1622 0 : mxString1->Append( aToken );
1623 0 : sFormulaBuf.append( aToken );
1624 0 : }
1625 0 : ::set_flag( mnFlags, EXC_DV_STRINGLIST );
1626 :
1627 0 : sFormulaBuf.append( '"' );
1628 0 : msFormula1 = sFormulaBuf.makeStringAndClear();
1629 : }
1630 : else
1631 : {
1632 : /* All other formulas in validation are stored like conditional
1633 : formatting formulas (with tRefN/tAreaN tokens as value or
1634 : array class). But NOT the cell references and defined names
1635 : in list validation - they are stored as reference class
1636 : tokens... Example:
1637 : 1) Cell must be equal to A1 -> formula is =A1 -> writes tRefNV token
1638 : 2) List is taken from A1 -> formula is =A1 -> writes tRefNR token
1639 : Formula compiler supports this by offering two different functions
1640 : CreateDataValFormula() and CreateListValFormula(). */
1641 0 : if(GetOutput() == EXC_OUTPUT_BINARY)
1642 0 : mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_LISTVAL, *xScTokArr );
1643 : else
1644 0 : msFormula1 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
1645 0 : xScTokArr.get());
1646 0 : }
1647 : }
1648 : else
1649 : {
1650 : // no list validation -> convert the formula
1651 0 : if(GetOutput() == EXC_OUTPUT_BINARY)
1652 0 : mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
1653 : else
1654 0 : msFormula1 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
1655 0 : xScTokArr.get());
1656 : }
1657 : }
1658 :
1659 : // second formula
1660 0 : xScTokArr.reset( pValData->CreateTokenArry( 1 ) );
1661 0 : if( xScTokArr.get() )
1662 : {
1663 0 : if(GetOutput() == EXC_OUTPUT_BINARY)
1664 0 : mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
1665 : else
1666 0 : msFormula2 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
1667 0 : xScTokArr.get());
1668 0 : }
1669 : }
1670 : else
1671 : {
1672 : OSL_FAIL( "XclExpDV::XclExpDV - missing core data" );
1673 0 : mnScHandle = ULONG_MAX;
1674 : }
1675 0 : }
1676 :
1677 0 : XclExpDV::~XclExpDV()
1678 : {
1679 0 : }
1680 :
1681 0 : void XclExpDV::InsertCellRange( const ScRange& rRange )
1682 : {
1683 0 : maScRanges.Join( rRange );
1684 0 : }
1685 :
1686 0 : bool XclExpDV::Finalize()
1687 : {
1688 0 : GetAddressConverter().ConvertRangeList( maXclRanges, maScRanges, true );
1689 0 : return (mnScHandle != ULONG_MAX) && !maXclRanges.empty();
1690 : }
1691 :
1692 0 : void XclExpDV::WriteBody( XclExpStream& rStrm )
1693 : {
1694 : // flags and strings
1695 0 : rStrm << mnFlags << maPromptTitle << maErrorTitle << maPromptText << maErrorText;
1696 : // condition formulas
1697 0 : if( mxString1.get() )
1698 0 : lclWriteDvFormula( rStrm, *mxString1 );
1699 : else
1700 0 : lclWriteDvFormula( rStrm, mxTokArr1.get() );
1701 0 : lclWriteDvFormula( rStrm, mxTokArr2.get() );
1702 : // cell ranges
1703 0 : rStrm << maXclRanges;
1704 0 : }
1705 :
1706 0 : void XclExpDV::SaveXml( XclExpXmlStream& rStrm )
1707 : {
1708 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1709 : rWorksheet->startElement( XML_dataValidation,
1710 0 : XML_allowBlank, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_IGNOREBLANK ) ),
1711 0 : XML_error, XESTRING_TO_PSZ( maErrorText ),
1712 : // OOXTODO: XML_errorStyle,
1713 0 : XML_errorTitle, XESTRING_TO_PSZ( maErrorTitle ),
1714 : // OOXTODO: XML_imeMode,
1715 : XML_operator, lcl_GetOperatorType( mnFlags ),
1716 0 : XML_prompt, XESTRING_TO_PSZ( maPromptText ),
1717 0 : XML_promptTitle, XESTRING_TO_PSZ( maPromptTitle ),
1718 : // showDropDown should have been showNoDropDown - check oox/xlsx import for details
1719 0 : XML_showDropDown, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN ) ),
1720 0 : XML_showErrorMessage, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWERROR ) ),
1721 0 : XML_showInputMessage, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWPROMPT ) ),
1722 : XML_sqref, XclXmlUtils::ToOString( maScRanges ).getStr(),
1723 : XML_type, lcl_GetValidationType( mnFlags ),
1724 0 : FSEND );
1725 0 : if( !msFormula1.isEmpty() )
1726 : {
1727 0 : rWorksheet->startElement( XML_formula1, FSEND );
1728 0 : rWorksheet->writeEscaped( msFormula1 );
1729 0 : rWorksheet->endElement( XML_formula1 );
1730 : }
1731 0 : if( !msFormula2.isEmpty() )
1732 : {
1733 0 : rWorksheet->startElement( XML_formula2, FSEND );
1734 0 : rWorksheet->writeEscaped( msFormula2 );
1735 0 : rWorksheet->endElement( XML_formula2 );
1736 : }
1737 0 : rWorksheet->endElement( XML_dataValidation );
1738 0 : }
1739 :
1740 129 : XclExpDval::XclExpDval( const XclExpRoot& rRoot ) :
1741 : XclExpRecord( EXC_ID_DVAL, 18 ),
1742 129 : XclExpRoot( rRoot )
1743 : {
1744 129 : }
1745 :
1746 258 : XclExpDval::~XclExpDval()
1747 : {
1748 258 : }
1749 :
1750 0 : void XclExpDval::InsertCellRange( const ScRange& rRange, sal_uLong nScHandle )
1751 : {
1752 0 : if( GetBiff() == EXC_BIFF8 )
1753 : {
1754 0 : XclExpDV& rDVRec = SearchOrCreateDv( nScHandle );
1755 0 : rDVRec.InsertCellRange( rRange );
1756 : }
1757 0 : }
1758 :
1759 29 : void XclExpDval::Save( XclExpStream& rStrm )
1760 : {
1761 : // check all records
1762 29 : size_t nPos = maDVList.GetSize();
1763 58 : while( nPos )
1764 : {
1765 0 : --nPos; // backwards to keep nPos valid
1766 0 : XclExpDVRef xDVRec = maDVList.GetRecord( nPos );
1767 0 : if( !xDVRec->Finalize() )
1768 0 : maDVList.RemoveRecord( nPos );
1769 0 : }
1770 :
1771 : // write the DVAL and the DV's
1772 29 : if( !maDVList.IsEmpty() )
1773 : {
1774 0 : XclExpRecord::Save( rStrm );
1775 0 : maDVList.Save( rStrm );
1776 : }
1777 29 : }
1778 :
1779 100 : void XclExpDval::SaveXml( XclExpXmlStream& rStrm )
1780 : {
1781 100 : if( maDVList.IsEmpty() )
1782 200 : return;
1783 :
1784 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1785 : rWorksheet->startElement( XML_dataValidations,
1786 : XML_count, OString::number( maDVList.GetSize() ).getStr(),
1787 : // OOXTODO: XML_disablePrompts,
1788 : // OOXTODO: XML_xWindow,
1789 : // OOXTODO: XML_yWindow,
1790 0 : FSEND );
1791 0 : maDVList.SaveXml( rStrm );
1792 0 : rWorksheet->endElement( XML_dataValidations );
1793 : }
1794 :
1795 0 : XclExpDV& XclExpDval::SearchOrCreateDv( sal_uLong nScHandle )
1796 : {
1797 : // test last found record
1798 0 : if( mxLastFoundDV.get() && (mxLastFoundDV->GetScHandle() == nScHandle) )
1799 0 : return *mxLastFoundDV;
1800 :
1801 : // binary search
1802 0 : size_t nCurrPos = 0;
1803 0 : if( !maDVList.IsEmpty() )
1804 : {
1805 0 : size_t nFirstPos = 0;
1806 0 : size_t nLastPos = maDVList.GetSize() - 1;
1807 0 : bool bLoop = true;
1808 0 : sal_uLong nCurrScHandle = ::std::numeric_limits< sal_uLong >::max();
1809 0 : while( (nFirstPos <= nLastPos) && bLoop )
1810 : {
1811 0 : nCurrPos = (nFirstPos + nLastPos) / 2;
1812 0 : mxLastFoundDV = maDVList.GetRecord( nCurrPos );
1813 0 : nCurrScHandle = mxLastFoundDV->GetScHandle();
1814 0 : if( nCurrScHandle == nScHandle )
1815 0 : bLoop = false;
1816 0 : else if( nCurrScHandle < nScHandle )
1817 0 : nFirstPos = nCurrPos + 1;
1818 0 : else if( nCurrPos )
1819 0 : nLastPos = nCurrPos - 1;
1820 : else // special case for nLastPos = -1
1821 0 : bLoop = false;
1822 : }
1823 0 : if( nCurrScHandle == nScHandle )
1824 0 : return *mxLastFoundDV;
1825 0 : else if( nCurrScHandle < nScHandle )
1826 0 : ++nCurrPos;
1827 : }
1828 :
1829 : // create new DV record
1830 0 : mxLastFoundDV.reset( new XclExpDV( *this, nScHandle ) );
1831 0 : maDVList.InsertRecord( mxLastFoundDV, nCurrPos );
1832 0 : return *mxLastFoundDV;
1833 : }
1834 :
1835 0 : void XclExpDval::WriteBody( XclExpStream& rStrm )
1836 : {
1837 0 : rStrm.WriteZeroBytes( 10 );
1838 0 : rStrm << EXC_DVAL_NOOBJ << static_cast< sal_uInt32 >( maDVList.GetSize() );
1839 0 : }
1840 :
1841 : // Web Queries ================================================================
1842 :
1843 0 : XclExpWebQuery::XclExpWebQuery(
1844 : const OUString& rRangeName,
1845 : const OUString& rUrl,
1846 : const OUString& rSource,
1847 : sal_Int32 nRefrSecs ) :
1848 : maDestRange( rRangeName ),
1849 : maUrl( rUrl ),
1850 : // refresh delay time: seconds -> minutes
1851 0 : mnRefresh( ulimit_cast< sal_Int16 >( (nRefrSecs + 59L) / 60L ) ),
1852 0 : mbEntireDoc( false )
1853 : {
1854 : // comma separated list of HTML table names or indexes
1855 0 : sal_Int32 nTokenCnt = comphelper::string::getTokenCount(rSource, ';');
1856 0 : OUString aNewTables;
1857 0 : OUString aAppendTable;
1858 0 : sal_Int32 nStringIx = 0;
1859 0 : bool bExitLoop = false;
1860 0 : for( sal_Int32 nToken = 0; (nToken < nTokenCnt) && !bExitLoop; ++nToken )
1861 : {
1862 0 : OUString aToken( rSource.getToken( 0, ';', nStringIx ) );
1863 0 : mbEntireDoc = ScfTools::IsHTMLDocName( aToken );
1864 0 : bExitLoop = mbEntireDoc || ScfTools::IsHTMLTablesName( aToken );
1865 0 : if( !bExitLoop && ScfTools::GetHTMLNameFromName( aToken, aAppendTable ) )
1866 0 : aNewTables = ScGlobal::addToken( aNewTables, aAppendTable, ',' );
1867 0 : }
1868 :
1869 0 : if( !bExitLoop ) // neither HTML_all nor HTML_tables found
1870 : {
1871 0 : if( !aNewTables.isEmpty() )
1872 0 : mxQryTables.reset( new XclExpString( aNewTables ) );
1873 : else
1874 0 : mbEntireDoc = true;
1875 0 : }
1876 0 : }
1877 :
1878 0 : XclExpWebQuery::~XclExpWebQuery()
1879 : {
1880 0 : }
1881 :
1882 0 : void XclExpWebQuery::Save( XclExpStream& rStrm )
1883 : {
1884 : OSL_ENSURE( !mbEntireDoc || !mxQryTables.get(), "XclExpWebQuery::Save - illegal mode" );
1885 : sal_uInt16 nFlags;
1886 :
1887 : // QSI record
1888 0 : rStrm.StartRecord( EXC_ID_QSI, 10 + maDestRange.GetSize() );
1889 0 : rStrm << EXC_QSI_DEFAULTFLAGS
1890 0 : << sal_uInt16( 0x0010 )
1891 0 : << sal_uInt16( 0x0012 )
1892 0 : << sal_uInt32( 0x00000000 )
1893 0 : << maDestRange;
1894 0 : rStrm.EndRecord();
1895 :
1896 : // PARAMQRY record
1897 0 : nFlags = 0;
1898 0 : ::insert_value( nFlags, EXC_PQRYTYPE_WEBQUERY, 0, 3 );
1899 0 : ::set_flag( nFlags, EXC_PQRY_WEBQUERY );
1900 0 : ::set_flag( nFlags, EXC_PQRY_TABLES, !mbEntireDoc );
1901 0 : rStrm.StartRecord( EXC_ID_PQRY, 12 );
1902 0 : rStrm << nFlags
1903 0 : << sal_uInt16( 0x0000 )
1904 0 : << sal_uInt16( 0x0001 );
1905 0 : rStrm.WriteZeroBytes( 6 );
1906 0 : rStrm.EndRecord();
1907 :
1908 : // WQSTRING record
1909 0 : rStrm.StartRecord( EXC_ID_WQSTRING, maUrl.GetSize() );
1910 0 : rStrm << maUrl;
1911 0 : rStrm.EndRecord();
1912 :
1913 : // unknown record 0x0802
1914 0 : rStrm.StartRecord( EXC_ID_0802, 16 + maDestRange.GetSize() );
1915 0 : rStrm << EXC_ID_0802; // repeated record id ?!?
1916 0 : rStrm.WriteZeroBytes( 6 );
1917 0 : rStrm << sal_uInt16( 0x0003 )
1918 0 : << sal_uInt32( 0x00000000 )
1919 0 : << sal_uInt16( 0x0010 )
1920 0 : << maDestRange;
1921 0 : rStrm.EndRecord();
1922 :
1923 : // WEBQRYSETTINGS record
1924 0 : nFlags = mxQryTables.get() ? EXC_WQSETT_SPECTABLES : EXC_WQSETT_ALL;
1925 0 : rStrm.StartRecord( EXC_ID_WQSETT, 28 );
1926 0 : rStrm << EXC_ID_WQSETT // repeated record id ?!?
1927 0 : << sal_uInt16( 0x0000 )
1928 0 : << sal_uInt16( 0x0004 )
1929 0 : << sal_uInt16( 0x0000 )
1930 0 : << EXC_WQSETT_DEFAULTFLAGS
1931 0 : << nFlags;
1932 0 : rStrm.WriteZeroBytes( 10 );
1933 0 : rStrm << mnRefresh // refresh delay in minutes
1934 0 : << EXC_WQSETT_FORMATFULL
1935 0 : << sal_uInt16( 0x0000 );
1936 0 : rStrm.EndRecord();
1937 :
1938 : // WEBQRYTABLES record
1939 0 : if( mxQryTables.get() )
1940 : {
1941 0 : rStrm.StartRecord( EXC_ID_WQTABLES, 4 + mxQryTables->GetSize() );
1942 0 : rStrm << EXC_ID_WQTABLES // repeated record id ?!?
1943 0 : << sal_uInt16( 0x0000 )
1944 0 : << *mxQryTables; // comma separated list of source tables
1945 0 : rStrm.EndRecord();
1946 : }
1947 0 : }
1948 :
1949 29 : XclExpWebQueryBuffer::XclExpWebQueryBuffer( const XclExpRoot& rRoot )
1950 : {
1951 29 : SCTAB nScTab = rRoot.GetCurrScTab();
1952 29 : SfxObjectShell* pShell = rRoot.GetDocShell();
1953 29 : if( !pShell ) return;
1954 29 : ScfPropertySet aModelProp( pShell->GetModel() );
1955 29 : if( !aModelProp.Is() ) return;
1956 :
1957 58 : Reference< XAreaLinks > xAreaLinks;
1958 29 : aModelProp.GetProperty( xAreaLinks, SC_UNO_AREALINKS );
1959 29 : if( !xAreaLinks.is() ) return;
1960 :
1961 29 : for( sal_Int32 nIndex = 0, nCount = xAreaLinks->getCount(); nIndex < nCount; ++nIndex )
1962 : {
1963 0 : Reference< XAreaLink > xAreaLink( xAreaLinks->getByIndex( nIndex ), UNO_QUERY );
1964 0 : if( xAreaLink.is() )
1965 : {
1966 0 : CellRangeAddress aDestRange( xAreaLink->getDestArea() );
1967 0 : if( static_cast< SCTAB >( aDestRange.Sheet ) == nScTab )
1968 : {
1969 0 : ScfPropertySet aLinkProp( xAreaLink );
1970 0 : OUString aFilter;
1971 0 : if( aLinkProp.GetProperty( aFilter, SC_UNONAME_FILTER ) &&
1972 0 : (aFilter == EXC_WEBQRY_FILTER) )
1973 : {
1974 : // get properties
1975 0 : OUString /*aFilterOpt,*/ aUrl;
1976 0 : sal_Int32 nRefresh = 0;
1977 :
1978 : // aLinkProp.GetProperty( aFilterOpt, SC_UNONAME_FILTOPT );
1979 0 : aLinkProp.GetProperty( aUrl, SC_UNONAME_LINKURL );
1980 0 : aLinkProp.GetProperty( nRefresh, SC_UNONAME_REFDELAY );
1981 :
1982 0 : OUString aAbsDoc( ScGlobal::GetAbsDocName( aUrl, pShell ) );
1983 0 : INetURLObject aUrlObj( aAbsDoc );
1984 0 : OUString aWebQueryUrl( aUrlObj.getFSysPath( INetURLObject::FSYS_DOS ) );
1985 0 : if( aWebQueryUrl.isEmpty() )
1986 0 : aWebQueryUrl = aAbsDoc;
1987 :
1988 : // find range or create a new range
1989 0 : OUString aRangeName;
1990 0 : ScRange aScDestRange;
1991 0 : ScUnoConversion::FillScRange( aScDestRange, aDestRange );
1992 0 : if( const ScRangeData* pRangeData = rRoot.GetNamedRanges().findByRange( aScDestRange ) )
1993 : {
1994 0 : aRangeName = pRangeData->GetName();
1995 : }
1996 : else
1997 : {
1998 0 : XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
1999 0 : XclExpNameManager& rNameMgr = rRoot.GetNameManager();
2000 :
2001 : // create a new unique defined name containing the range
2002 0 : XclTokenArrayRef xTokArr = rFmlaComp.CreateFormula( EXC_FMLATYPE_WQUERY, aScDestRange );
2003 0 : sal_uInt16 nNameIdx = rNameMgr.InsertUniqueName( aUrlObj.getBase(), xTokArr, nScTab );
2004 0 : aRangeName = rNameMgr.GetOrigName( nNameIdx );
2005 : }
2006 :
2007 : // create and store the web query record
2008 0 : if( !aRangeName.isEmpty() )
2009 : AppendNewRecord( new XclExpWebQuery(
2010 0 : aRangeName, aWebQueryUrl, xAreaLink->getSourceArea(), nRefresh ) );
2011 0 : }
2012 : }
2013 : }
2014 29 : }
2015 30 : }
2016 :
2017 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|