1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE ---------------------------------------------------------------
30
31 #include <tools/debug.hxx>
32
33 #include "rangeutl.hxx"
34 #include "document.hxx"
35 #include "global.hxx"
36 #include "dbcolect.hxx"
37 #include "rangenam.hxx"
38 #include "scresid.hxx"
39 #include "globstr.hrc"
40 #include "convuno.hxx"
41 #include "externalrefmgr.hxx"
42 #include "compiler.hxx"
43
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 using ::formula::FormulaGrammar;
47 using namespace ::com::sun::star;
48
49 //------------------------------------------------------------------------
50
MakeArea(const String & rAreaStr,ScArea & rArea,ScDocument * pDoc,SCTAB nTab,ScAddress::Details const & rDetails) const51 sal_Bool ScRangeUtil::MakeArea( const String& rAreaStr,
52 ScArea& rArea,
53 ScDocument* pDoc,
54 SCTAB nTab,
55 ScAddress::Details const & rDetails ) const
56 {
57 // Eingabe in rAreaStr: "$Tabelle1.$A1:$D17"
58
59 // BROKEN BROKEN BROKEN
60 // but it is only used in the consolidate dialog. Ignore for now.
61
62 sal_Bool nSuccess = sal_False;
63 sal_uInt16 nPointPos = rAreaStr.Search('.');
64 sal_uInt16 nColonPos = rAreaStr.Search(':');
65 String aStrArea( rAreaStr );
66 ScRefAddress startPos;
67 ScRefAddress endPos;
68
69 if ( nColonPos == STRING_NOTFOUND )
70 if ( nPointPos != STRING_NOTFOUND )
71 {
72 aStrArea += ':';
73 aStrArea += rAreaStr.Copy( nPointPos+1 ); // '.' nicht mitkopieren
74 }
75
76 nSuccess = ConvertDoubleRef( pDoc, aStrArea, nTab, startPos, endPos, rDetails );
77
78 if ( nSuccess )
79 rArea = ScArea( startPos.Tab(),
80 startPos.Col(), startPos.Row(),
81 endPos.Col(), endPos.Row() );
82
83 return nSuccess;
84 }
85
86 //------------------------------------------------------------------------
87
CutPosString(const String & theAreaStr,String & thePosStr) const88 void ScRangeUtil::CutPosString( const String& theAreaStr,
89 String& thePosStr ) const
90 {
91 String aPosStr;
92 // BROKEN BROKEN BROKEN
93 // but it is only used in the consolidate dialog. Ignore for now.
94
95 sal_uInt16 nColonPos = theAreaStr.Search(':');
96
97 if ( nColonPos != STRING_NOTFOUND )
98 aPosStr = theAreaStr.Copy( 0, nColonPos ); // ':' nicht mitkopieren
99 else
100 aPosStr = theAreaStr;
101
102 thePosStr = aPosStr;
103 }
104
105 //------------------------------------------------------------------------
106
IsAbsTabArea(const String & rAreaStr,ScDocument * pDoc,ScArea *** pppAreas,sal_uInt16 * pAreaCount,sal_Bool,ScAddress::Details const & rDetails) const107 sal_Bool ScRangeUtil::IsAbsTabArea( const String& rAreaStr,
108 ScDocument* pDoc,
109 ScArea*** pppAreas,
110 sal_uInt16* pAreaCount,
111 sal_Bool /* bAcceptCellRef */,
112 ScAddress::Details const & rDetails ) const
113 {
114 DBG_ASSERT( pDoc, "Kein Dokument uebergeben!" );
115 if ( !pDoc )
116 return sal_False;
117
118 // BROKEN BROKEN BROKEN
119 // but it is only used in the consolidate dialog. Ignore for now.
120
121 /*
122 * Erwartet wird ein String der Form
123 * "$Tabelle1.$A$1:$Tabelle3.$D$17"
124 * Wenn bAcceptCellRef == sal_True ist, wird auch ein String der Form
125 * "$Tabelle1.$A$1"
126 * akzeptiert.
127 *
128 * als Ergebnis wird ein ScArea-Array angelegt,
129 * welches ueber ppAreas bekannt gegeben wird und auch
130 * wieder geloescht werden muss!
131 */
132
133 sal_Bool bStrOk = sal_False;
134 String aTempAreaStr(rAreaStr);
135 String aStartPosStr;
136 String aEndPosStr;
137
138 if ( STRING_NOTFOUND == aTempAreaStr.Search(':') )
139 {
140 aTempAreaStr.Append(':');
141 aTempAreaStr.Append(rAreaStr);
142 }
143
144 sal_uInt16 nColonPos = aTempAreaStr.Search(':');
145
146 if ( STRING_NOTFOUND != nColonPos
147 && STRING_NOTFOUND != aTempAreaStr.Search('.') )
148 {
149 ScRefAddress aStartPos;
150 ScRefAddress aEndPos;
151
152 aStartPosStr = aTempAreaStr.Copy( 0, nColonPos );
153 aEndPosStr = aTempAreaStr.Copy( nColonPos+1, STRING_LEN );
154
155 if ( ConvertSingleRef( pDoc, aStartPosStr, 0, aStartPos, rDetails ) )
156 {
157 if ( ConvertSingleRef( pDoc, aEndPosStr, aStartPos.Tab(), aEndPos, rDetails ) )
158 {
159 aStartPos.SetRelCol( sal_False );
160 aStartPos.SetRelRow( sal_False );
161 aStartPos.SetRelTab( sal_False );
162 aEndPos.SetRelCol( sal_False );
163 aEndPos.SetRelRow( sal_False );
164 aEndPos.SetRelTab( sal_False );
165
166 bStrOk = sal_True;
167
168 if ( pppAreas && pAreaCount ) // Array zurueckgegeben?
169 {
170 SCTAB nStartTab = aStartPos.Tab();
171 SCTAB nEndTab = aEndPos.Tab();
172 sal_uInt16 nTabCount = static_cast<sal_uInt16>(nEndTab-nStartTab+1);
173 ScArea** theAreas = new ScArea*[nTabCount];
174 SCTAB nTab = 0;
175 sal_uInt16 i = 0;
176 ScArea theArea( 0, aStartPos.Col(), aStartPos.Row(),
177 aEndPos.Col(), aEndPos.Row() );
178
179 nTab = nStartTab;
180 for ( i=0; i<nTabCount; i++ )
181 {
182 theAreas[i] = new ScArea( theArea );
183 theAreas[i]->nTab = nTab;
184 nTab++;
185 }
186 *pppAreas = theAreas;
187 *pAreaCount = nTabCount;
188 }
189 }
190 }
191 }
192
193 return bStrOk;
194 }
195
196 //------------------------------------------------------------------------
197
IsAbsArea(const String & rAreaStr,ScDocument * pDoc,SCTAB nTab,String * pCompleteStr,ScRefAddress * pStartPos,ScRefAddress * pEndPos,ScAddress::Details const & rDetails) const198 sal_Bool ScRangeUtil::IsAbsArea( const String& rAreaStr,
199 ScDocument* pDoc,
200 SCTAB nTab,
201 String* pCompleteStr,
202 ScRefAddress* pStartPos,
203 ScRefAddress* pEndPos,
204 ScAddress::Details const & rDetails ) const
205 {
206 sal_Bool bIsAbsArea = sal_False;
207 ScRefAddress startPos;
208 ScRefAddress endPos;
209
210 bIsAbsArea = ConvertDoubleRef( pDoc, rAreaStr, nTab, startPos, endPos, rDetails );
211
212 if ( bIsAbsArea )
213 {
214 startPos.SetRelCol( sal_False );
215 startPos.SetRelRow( sal_False );
216 startPos.SetRelTab( sal_False );
217 endPos .SetRelCol( sal_False );
218 endPos .SetRelRow( sal_False );
219 endPos .SetRelTab( sal_False );
220
221 if ( pCompleteStr )
222 {
223 *pCompleteStr = startPos.GetRefString( pDoc, MAXTAB+1, rDetails );
224 *pCompleteStr += ':';
225 *pCompleteStr += endPos .GetRefString( pDoc, nTab, rDetails );
226 }
227
228 if ( pStartPos && pEndPos )
229 {
230 *pStartPos = startPos;
231 *pEndPos = endPos;
232 }
233 }
234
235 return bIsAbsArea;
236 }
237
238 //------------------------------------------------------------------------
239
IsAbsPos(const String & rPosStr,ScDocument * pDoc,SCTAB nTab,String * pCompleteStr,ScRefAddress * pPosTripel,ScAddress::Details const & rDetails) const240 sal_Bool ScRangeUtil::IsAbsPos( const String& rPosStr,
241 ScDocument* pDoc,
242 SCTAB nTab,
243 String* pCompleteStr,
244 ScRefAddress* pPosTripel,
245 ScAddress::Details const & rDetails ) const
246 {
247 sal_Bool bIsAbsPos = sal_False;
248 ScRefAddress thePos;
249
250 bIsAbsPos = ConvertSingleRef( pDoc, rPosStr, nTab, thePos, rDetails );
251 thePos.SetRelCol( sal_False );
252 thePos.SetRelRow( sal_False );
253 thePos.SetRelTab( sal_False );
254
255 if ( bIsAbsPos )
256 {
257 if ( pPosTripel )
258 *pPosTripel = thePos;
259 if ( pCompleteStr )
260 *pCompleteStr = thePos.GetRefString( pDoc, MAXTAB+1, rDetails );
261 }
262
263 return bIsAbsPos;
264 }
265
266 //------------------------------------------------------------------------
267
MakeRangeFromName(const String & rName,ScDocument * pDoc,SCTAB nCurTab,ScRange & rRange,RutlNameScope eScope,ScAddress::Details const & rDetails) const268 sal_Bool ScRangeUtil::MakeRangeFromName (
269 const String& rName,
270 ScDocument* pDoc,
271 SCTAB nCurTab,
272 ScRange& rRange,
273 RutlNameScope eScope,
274 ScAddress::Details const & rDetails ) const
275 {
276 sal_Bool bResult=sal_False;
277 ScRangeUtil aRangeUtil;
278 SCTAB nTab = 0;
279 SCCOL nColStart = 0;
280 SCCOL nColEnd = 0;
281 SCROW nRowStart = 0;
282 SCROW nRowEnd = 0;
283
284 if( eScope==RUTL_NAMES )
285 {
286 ScRangeName& rRangeNames = *(pDoc->GetRangeName());
287 sal_uInt16 nAt = 0;
288
289 if ( rRangeNames.SearchName( rName, nAt ) )
290 {
291 ScRangeData* pData = rRangeNames[nAt];
292 String aStrArea;
293 ScRefAddress aStartPos;
294 ScRefAddress aEndPos;
295
296 pData->GetSymbol( aStrArea );
297
298 if ( IsAbsArea( aStrArea, pDoc, nCurTab,
299 NULL, &aStartPos, &aEndPos, rDetails ) )
300 {
301 nTab = aStartPos.Tab();
302 nColStart = aStartPos.Col();
303 nRowStart = aStartPos.Row();
304 nColEnd = aEndPos.Col();
305 nRowEnd = aEndPos.Row();
306 bResult = sal_True;
307 }
308 else
309 {
310 CutPosString( aStrArea, aStrArea );
311
312 if ( IsAbsPos( aStrArea, pDoc, nCurTab,
313 NULL, &aStartPos, rDetails ) )
314 {
315 nTab = aStartPos.Tab();
316 nColStart = nColEnd = aStartPos.Col();
317 nRowStart = nRowEnd = aStartPos.Row();
318 bResult = sal_True;
319 }
320 }
321 }
322 }
323 else if( eScope==RUTL_DBASE )
324 {
325 ScDBCollection& rDbNames = *(pDoc->GetDBCollection());
326 sal_uInt16 nAt = 0;
327
328 if ( rDbNames.SearchName( rName, nAt ) )
329 {
330 ScDBData* pData = rDbNames[nAt];
331
332 pData->GetArea( nTab, nColStart, nRowStart,
333 nColEnd, nRowEnd );
334 bResult = sal_True;
335 }
336 }
337 else
338 {
339 DBG_ERROR( "ScRangeUtil::MakeRangeFromName" );
340 }
341
342 if( bResult )
343 {
344 rRange = ScRange( nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab );
345 }
346
347 return bResult;
348 }
349
350 //========================================================================
351
AssignString(OUString & rString,const OUString & rNewStr,sal_Bool bAppendStr,sal_Unicode cSeperator)352 void ScRangeStringConverter::AssignString(
353 OUString& rString,
354 const OUString& rNewStr,
355 sal_Bool bAppendStr,
356 sal_Unicode cSeperator)
357 {
358 if( bAppendStr )
359 {
360 if( rNewStr.getLength() )
361 {
362 if( rString.getLength() )
363 rString += rtl::OUString(cSeperator);
364 rString += rNewStr;
365 }
366 }
367 else
368 rString = rNewStr;
369 }
370
IndexOf(const OUString & rString,sal_Unicode cSearchChar,sal_Int32 nOffset,sal_Unicode cQuote)371 sal_Int32 ScRangeStringConverter::IndexOf(
372 const OUString& rString,
373 sal_Unicode cSearchChar,
374 sal_Int32 nOffset,
375 sal_Unicode cQuote )
376 {
377 sal_Int32 nLength = rString.getLength();
378 sal_Int32 nIndex = nOffset;
379 sal_Bool bQuoted = sal_False;
380 sal_Bool bExitLoop = sal_False;
381
382 while( !bExitLoop && (nIndex < nLength) )
383 {
384 sal_Unicode cCode = rString[ nIndex ];
385 bExitLoop = (cCode == cSearchChar) && !bQuoted;
386 bQuoted = (bQuoted != (cCode == cQuote));
387 if( !bExitLoop )
388 nIndex++;
389 }
390 return (nIndex < nLength) ? nIndex : -1;
391 }
392
IndexOfDifferent(const OUString & rString,sal_Unicode cSearchChar,sal_Int32 nOffset)393 sal_Int32 ScRangeStringConverter::IndexOfDifferent(
394 const OUString& rString,
395 sal_Unicode cSearchChar,
396 sal_Int32 nOffset )
397 {
398 sal_Int32 nLength = rString.getLength();
399 sal_Int32 nIndex = nOffset;
400 sal_Bool bExitLoop = sal_False;
401
402 while( !bExitLoop && (nIndex < nLength) )
403 {
404 bExitLoop = (rString[ nIndex ] != cSearchChar);
405 if( !bExitLoop )
406 nIndex++;
407 }
408 return (nIndex < nLength) ? nIndex : -1;
409 }
410
GetTokenByOffset(OUString & rToken,const OUString & rString,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)411 void ScRangeStringConverter::GetTokenByOffset(
412 OUString& rToken,
413 const OUString& rString,
414 sal_Int32& nOffset,
415 sal_Unicode cSeperator,
416 sal_Unicode cQuote)
417 {
418 sal_Int32 nLength = rString.getLength();
419 if( nOffset >= nLength )
420 {
421 rToken = OUString();
422 nOffset = -1;
423 }
424 else
425 {
426 sal_Int32 nTokenEnd = IndexOf( rString, cSeperator, nOffset, cQuote );
427 if( nTokenEnd < 0 )
428 nTokenEnd = nLength;
429 rToken = rString.copy( nOffset, nTokenEnd - nOffset );
430
431 sal_Int32 nNextBegin = IndexOfDifferent( rString, cSeperator, nTokenEnd );
432 nOffset = (nNextBegin < 0) ? nLength : nNextBegin;
433 }
434 }
435
AppendTableName(OUStringBuffer & rBuf,const OUString & rTabName,sal_Unicode)436 void ScRangeStringConverter::AppendTableName(OUStringBuffer& rBuf, const OUString& rTabName, sal_Unicode /* cQuote */)
437 {
438 // quote character is always "'"
439 String aQuotedTab(rTabName);
440 ScCompiler::CheckTabQuotes(aQuotedTab, ::formula::FormulaGrammar::CONV_OOO);
441 rBuf.append(aQuotedTab);
442 }
443
GetTokenCount(const OUString & rString,sal_Unicode cSeperator,sal_Unicode cQuote)444 sal_Int32 ScRangeStringConverter::GetTokenCount( const OUString& rString, sal_Unicode cSeperator, sal_Unicode cQuote )
445 {
446 OUString sToken;
447 sal_Int32 nCount = 0;
448 sal_Int32 nOffset = 0;
449 while( nOffset >= 0 )
450 {
451 GetTokenByOffset( sToken, rString, nOffset, cQuote, cSeperator );
452 if( nOffset >= 0 )
453 nCount++;
454 }
455 return nCount;
456 }
457
458 //___________________________________________________________________
459
GetAddressFromString(ScAddress & rAddress,const OUString & rAddressStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)460 sal_Bool ScRangeStringConverter::GetAddressFromString(
461 ScAddress& rAddress,
462 const OUString& rAddressStr,
463 const ScDocument* pDocument,
464 FormulaGrammar::AddressConvention eConv,
465 sal_Int32& nOffset,
466 sal_Unicode cSeperator,
467 sal_Unicode cQuote )
468 {
469 OUString sToken;
470 GetTokenByOffset( sToken, rAddressStr, nOffset, cSeperator, cQuote );
471 if( nOffset >= 0 )
472 {
473 if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID)
474 return true;
475 }
476 return sal_False;
477 }
478
GetRangeFromString(ScRange & rRange,const OUString & rRangeStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)479 sal_Bool ScRangeStringConverter::GetRangeFromString(
480 ScRange& rRange,
481 const OUString& rRangeStr,
482 const ScDocument* pDocument,
483 FormulaGrammar::AddressConvention eConv,
484 sal_Int32& nOffset,
485 sal_Unicode cSeperator,
486 sal_Unicode cQuote )
487 {
488 OUString sToken;
489 sal_Bool bResult(sal_False);
490 GetTokenByOffset( sToken, rRangeStr, nOffset, cSeperator, cQuote );
491 if( nOffset >= 0 )
492 {
493 sal_Int32 nIndex = IndexOf( sToken, ':', 0, cQuote );
494 String aUIString(sToken);
495
496 if( nIndex < 0 )
497 {
498 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
499 aUIString.Erase( 0, 1 );
500 bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
501 rRange.aEnd = rRange.aStart;
502 }
503 else
504 {
505 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
506 {
507 aUIString.Erase( 0, 1 );
508 --nIndex;
509 }
510
511 if ( nIndex < aUIString.Len() - 1 &&
512 aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' )
513 aUIString.Erase( (xub_StrLen)nIndex + 1, 1 );
514
515 bResult = ((rRange.Parse(aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
516
517 // #i77703# chart ranges in the file format contain both sheet names, even for an external reference sheet.
518 // This isn't parsed by ScRange, so try to parse the two Addresses then.
519 if (!bResult)
520 {
521 bResult = ((rRange.aStart.Parse( aUIString.Copy(0, (xub_StrLen)nIndex), const_cast<ScDocument*>(pDocument),
522 eConv) & SCA_VALID) == SCA_VALID) &&
523 ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument),
524 eConv) & SCA_VALID) == SCA_VALID);
525 }
526 }
527 }
528 return bResult;
529 }
530
GetRangeListFromString(ScRangeList & rRangeList,const OUString & rRangeListStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Unicode cQuote)531 sal_Bool ScRangeStringConverter::GetRangeListFromString(
532 ScRangeList& rRangeList,
533 const OUString& rRangeListStr,
534 const ScDocument* pDocument,
535 FormulaGrammar::AddressConvention eConv,
536 sal_Unicode cSeperator,
537 sal_Unicode cQuote )
538 {
539 sal_Bool bRet = sal_True;
540 DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" );
541 sal_Int32 nOffset = 0;
542 while( nOffset >= 0 )
543 {
544 ScRange* pRange = new ScRange;
545 if( GetRangeFromString( *pRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) )
546 rRangeList.Insert( pRange, LIST_APPEND );
547 else if (nOffset > -1)
548 bRet = sal_False;
549 }
550 return bRet;
551 }
552
553
554 //___________________________________________________________________
555
GetAreaFromString(ScArea & rArea,const OUString & rRangeStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)556 sal_Bool ScRangeStringConverter::GetAreaFromString(
557 ScArea& rArea,
558 const OUString& rRangeStr,
559 const ScDocument* pDocument,
560 FormulaGrammar::AddressConvention eConv,
561 sal_Int32& nOffset,
562 sal_Unicode cSeperator,
563 sal_Unicode cQuote )
564 {
565 ScRange aScRange;
566 sal_Bool bResult(sal_False);
567 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) )
568 {
569 rArea.nTab = aScRange.aStart.Tab();
570 rArea.nColStart = aScRange.aStart.Col();
571 rArea.nRowStart = aScRange.aStart.Row();
572 rArea.nColEnd = aScRange.aEnd.Col();
573 rArea.nRowEnd = aScRange.aEnd.Row();
574 bResult = sal_True;
575 }
576 return bResult;
577 }
578
579
580 //___________________________________________________________________
581
GetAddressFromString(table::CellAddress & rAddress,const OUString & rAddressStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)582 sal_Bool ScRangeStringConverter::GetAddressFromString(
583 table::CellAddress& rAddress,
584 const OUString& rAddressStr,
585 const ScDocument* pDocument,
586 FormulaGrammar::AddressConvention eConv,
587 sal_Int32& nOffset,
588 sal_Unicode cSeperator,
589 sal_Unicode cQuote )
590 {
591 ScAddress aScAddress;
592 sal_Bool bResult(sal_False);
593 if( GetAddressFromString( aScAddress, rAddressStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) )
594 {
595 ScUnoConversion::FillApiAddress( rAddress, aScAddress );
596 bResult = sal_True;
597 }
598 return bResult;
599 }
600
GetRangeFromString(table::CellRangeAddress & rRange,const OUString & rRangeStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Int32 & nOffset,sal_Unicode cSeperator,sal_Unicode cQuote)601 sal_Bool ScRangeStringConverter::GetRangeFromString(
602 table::CellRangeAddress& rRange,
603 const OUString& rRangeStr,
604 const ScDocument* pDocument,
605 FormulaGrammar::AddressConvention eConv,
606 sal_Int32& nOffset,
607 sal_Unicode cSeperator,
608 sal_Unicode cQuote )
609 {
610 ScRange aScRange;
611 sal_Bool bResult(sal_False);
612 if( GetRangeFromString( aScRange, rRangeStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) )
613 {
614 ScUnoConversion::FillApiRange( rRange, aScRange );
615 bResult = sal_True;
616 }
617 return bResult;
618 }
619
GetRangeListFromString(uno::Sequence<table::CellRangeAddress> & rRangeSeq,const OUString & rRangeListStr,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Unicode cQuote)620 sal_Bool ScRangeStringConverter::GetRangeListFromString(
621 uno::Sequence< table::CellRangeAddress >& rRangeSeq,
622 const OUString& rRangeListStr,
623 const ScDocument* pDocument,
624 FormulaGrammar::AddressConvention eConv,
625 sal_Unicode cSeperator,
626 sal_Unicode cQuote )
627 {
628 sal_Bool bRet = sal_True;
629 DBG_ASSERT( rRangeListStr.getLength(), "ScXMLConverter::GetRangeListFromString - empty string!" );
630 table::CellRangeAddress aRange;
631 sal_Int32 nOffset = 0;
632 while( nOffset >= 0 )
633 {
634 if( GetRangeFromString( aRange, rRangeListStr, pDocument, eConv, nOffset, cSeperator, cQuote ) && (nOffset >= 0) )
635 {
636 rRangeSeq.realloc( rRangeSeq.getLength() + 1 );
637 rRangeSeq[ rRangeSeq.getLength() - 1 ] = aRange;
638 }
639 else
640 bRet = sal_False;
641 }
642 return bRet;
643 }
644
645
646 //___________________________________________________________________
647
GetStringFromAddress(OUString & rString,const ScAddress & rAddress,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Bool bAppendStr,sal_uInt16 nFormatFlags)648 void ScRangeStringConverter::GetStringFromAddress(
649 OUString& rString,
650 const ScAddress& rAddress,
651 const ScDocument* pDocument,
652 FormulaGrammar::AddressConvention eConv,
653 sal_Unicode cSeperator,
654 sal_Bool bAppendStr,
655 sal_uInt16 nFormatFlags )
656 {
657 if (pDocument && pDocument->HasTable(rAddress.Tab()))
658 {
659 String sAddress;
660 rAddress.Format( sAddress, nFormatFlags, (ScDocument*) pDocument, eConv );
661 AssignString( rString, sAddress, bAppendStr, cSeperator );
662 }
663 }
664
GetStringFromRange(OUString & rString,const ScRange & rRange,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Bool bAppendStr,sal_uInt16 nFormatFlags)665 void ScRangeStringConverter::GetStringFromRange(
666 OUString& rString,
667 const ScRange& rRange,
668 const ScDocument* pDocument,
669 FormulaGrammar::AddressConvention eConv,
670 sal_Unicode cSeperator,
671 sal_Bool bAppendStr,
672 sal_uInt16 nFormatFlags )
673 {
674 if (pDocument && pDocument->HasTable(rRange.aStart.Tab()))
675 {
676 ScAddress aStartAddress( rRange.aStart );
677 ScAddress aEndAddress( rRange.aEnd );
678 String sStartAddress;
679 String sEndAddress;
680 aStartAddress.Format( sStartAddress, nFormatFlags, (ScDocument*) pDocument, eConv );
681 aEndAddress.Format( sEndAddress, nFormatFlags, (ScDocument*) pDocument, eConv );
682 OUString sOUStartAddress( sStartAddress );
683 sOUStartAddress += OUString(':');
684 sOUStartAddress += OUString( sEndAddress );
685 AssignString( rString, sOUStartAddress, bAppendStr, cSeperator );
686 }
687 }
688
GetStringFromRangeList(OUString & rString,const ScRangeList * pRangeList,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_uInt16 nFormatFlags)689 void ScRangeStringConverter::GetStringFromRangeList(
690 OUString& rString,
691 const ScRangeList* pRangeList,
692 const ScDocument* pDocument,
693 FormulaGrammar::AddressConvention eConv,
694 sal_Unicode cSeperator,
695 sal_uInt16 nFormatFlags )
696 {
697 OUString sRangeListStr;
698 if( pRangeList )
699 {
700 sal_Int32 nCount = pRangeList->Count();
701 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
702 {
703 const ScRange* pRange = pRangeList->GetObject( nIndex );
704 if( pRange )
705 GetStringFromRange( sRangeListStr, *pRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags );
706 }
707 }
708 rString = sRangeListStr;
709 }
710
711
712 //___________________________________________________________________
713
GetStringFromArea(OUString & rString,const ScArea & rArea,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Bool bAppendStr,sal_uInt16 nFormatFlags)714 void ScRangeStringConverter::GetStringFromArea(
715 OUString& rString,
716 const ScArea& rArea,
717 const ScDocument* pDocument,
718 FormulaGrammar::AddressConvention eConv,
719 sal_Unicode cSeperator,
720 sal_Bool bAppendStr,
721 sal_uInt16 nFormatFlags )
722 {
723 ScRange aRange( rArea.nColStart, rArea.nRowStart, rArea.nTab, rArea.nColEnd, rArea.nRowEnd, rArea.nTab );
724 GetStringFromRange( rString, aRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags );
725 }
726
727
728 //___________________________________________________________________
729
GetStringFromAddress(OUString & rString,const table::CellAddress & rAddress,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Bool bAppendStr,sal_uInt16 nFormatFlags)730 void ScRangeStringConverter::GetStringFromAddress(
731 OUString& rString,
732 const table::CellAddress& rAddress,
733 const ScDocument* pDocument,
734 FormulaGrammar::AddressConvention eConv,
735 sal_Unicode cSeperator,
736 sal_Bool bAppendStr,
737 sal_uInt16 nFormatFlags )
738 {
739 ScAddress aScAddress( static_cast<SCCOL>(rAddress.Column), static_cast<SCROW>(rAddress.Row), rAddress.Sheet );
740 GetStringFromAddress( rString, aScAddress, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags );
741 }
742
GetStringFromRange(OUString & rString,const table::CellRangeAddress & rRange,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_Bool bAppendStr,sal_uInt16 nFormatFlags)743 void ScRangeStringConverter::GetStringFromRange(
744 OUString& rString,
745 const table::CellRangeAddress& rRange,
746 const ScDocument* pDocument,
747 FormulaGrammar::AddressConvention eConv,
748 sal_Unicode cSeperator,
749 sal_Bool bAppendStr,
750 sal_uInt16 nFormatFlags )
751 {
752 ScRange aScRange( static_cast<SCCOL>(rRange.StartColumn), static_cast<SCROW>(rRange.StartRow), rRange.Sheet,
753 static_cast<SCCOL>(rRange.EndColumn), static_cast<SCROW>(rRange.EndRow), rRange.Sheet );
754 GetStringFromRange( rString, aScRange, pDocument, eConv, cSeperator, bAppendStr, nFormatFlags );
755 }
756
GetStringFromRangeList(OUString & rString,const uno::Sequence<table::CellRangeAddress> & rRangeSeq,const ScDocument * pDocument,FormulaGrammar::AddressConvention eConv,sal_Unicode cSeperator,sal_uInt16 nFormatFlags)757 void ScRangeStringConverter::GetStringFromRangeList(
758 OUString& rString,
759 const uno::Sequence< table::CellRangeAddress >& rRangeSeq,
760 const ScDocument* pDocument,
761 FormulaGrammar::AddressConvention eConv,
762 sal_Unicode cSeperator,
763 sal_uInt16 nFormatFlags )
764 {
765 OUString sRangeListStr;
766 sal_Int32 nCount = rRangeSeq.getLength();
767 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
768 {
769 const table::CellRangeAddress& rRange = rRangeSeq[ nIndex ];
770 GetStringFromRange( sRangeListStr, rRange, pDocument, eConv, cSeperator, sal_True, nFormatFlags );
771 }
772 rString = sRangeListStr;
773 }
774
lcl_appendCellAddress(rtl::OUStringBuffer & rBuf,ScDocument * pDoc,const ScAddress & rCell,const ScAddress::ExternalInfo & rExtInfo)775 static void lcl_appendCellAddress(
776 rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell,
777 const ScAddress::ExternalInfo& rExtInfo)
778 {
779 if (rExtInfo.mbExternal)
780 {
781 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
782 const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId, true);
783 if (!pFilePath)
784 return;
785
786 sal_Unicode cQuote = '\'';
787 rBuf.append(cQuote);
788 rBuf.append(*pFilePath);
789 rBuf.append(cQuote);
790 rBuf.append(sal_Unicode('#'));
791 rBuf.append(sal_Unicode('$'));
792 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo.maTabName);
793 rBuf.append(sal_Unicode('.'));
794
795 String aAddr;
796 rCell.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO);
797 rBuf.append(aAddr);
798 }
799 else
800 {
801 String aAddr;
802 rCell.Format(aAddr, SCA_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
803 rBuf.append(aAddr);
804 }
805 }
806
lcl_appendCellRangeAddress(rtl::OUStringBuffer & rBuf,ScDocument * pDoc,const ScAddress & rCell1,const ScAddress & rCell2,const ScAddress::ExternalInfo & rExtInfo1,const ScAddress::ExternalInfo & rExtInfo2)807 static void lcl_appendCellRangeAddress(
808 rtl::OUStringBuffer& rBuf, ScDocument* pDoc, const ScAddress& rCell1, const ScAddress& rCell2,
809 const ScAddress::ExternalInfo& rExtInfo1, const ScAddress::ExternalInfo& rExtInfo2)
810 {
811 if (rExtInfo1.mbExternal)
812 {
813 DBG_ASSERT(rExtInfo2.mbExternal, "2nd address is not external!?");
814 DBG_ASSERT(rExtInfo1.mnFileId == rExtInfo2.mnFileId, "File IDs do not match between 1st and 2nd addresses.");
815
816 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
817 const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId, true);
818 if (!pFilePath)
819 return;
820
821 sal_Unicode cQuote = '\'';
822 rBuf.append(cQuote);
823 rBuf.append(*pFilePath);
824 rBuf.append(cQuote);
825 rBuf.append(sal_Unicode('#'));
826 rBuf.append(sal_Unicode('$'));
827 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo1.maTabName);
828 rBuf.append(sal_Unicode('.'));
829
830 String aAddr;
831 rCell1.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO);
832 rBuf.append(aAddr);
833
834 rBuf.appendAscii(":");
835
836 if (rExtInfo1.maTabName != rExtInfo2.maTabName)
837 {
838 rBuf.append(sal_Unicode('$'));
839 ScRangeStringConverter::AppendTableName(rBuf, rExtInfo2.maTabName);
840 rBuf.append(sal_Unicode('.'));
841 }
842
843 rCell2.Format(aAddr, SCA_ABS, NULL, ::formula::FormulaGrammar::CONV_OOO);
844 rBuf.append(aAddr);
845 }
846 else
847 {
848 ScRange aRange;
849 aRange.aStart = rCell1;
850 aRange.aEnd = rCell2;
851 String aAddr;
852 aRange.Format(aAddr, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO);
853 rBuf.append(aAddr);
854 }
855 }
856
GetStringFromXMLRangeString(OUString & rString,const OUString & rXMLRange,ScDocument * pDoc)857 void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc )
858 {
859 const sal_Unicode cSep = ' ';
860 const sal_Unicode cQuote = '\'';
861
862 OUStringBuffer aRetStr;
863 sal_Int32 nOffset = 0;
864 bool bFirst = true;
865
866 while (nOffset >= 0)
867 {
868 OUString aToken;
869 GetTokenByOffset(aToken, rXMLRange, nOffset, cSep, cQuote);
870 if (nOffset < 0)
871 break;
872
873 sal_Int32 nSepPos = IndexOf(aToken, ':', 0, cQuote);
874 if (nSepPos >= 0)
875 {
876 // Cell range
877 OUString aBeginCell = aToken.copy(0, nSepPos);
878 OUString aEndCell = aToken.copy(nSepPos+1);
879
880 if (!aBeginCell.getLength() || !aEndCell.getLength())
881 // both cell addresses must exist for this to work.
882 continue;
883
884 sal_Int32 nEndCellDotPos = aEndCell.indexOf('.');
885 if (nEndCellDotPos <= 0)
886 {
887 // initialize buffer with table name...
888 sal_Int32 nDotPos = IndexOf(aBeginCell, sal_Unicode('.'), 0, cQuote);
889 OUStringBuffer aBuf = aBeginCell.copy(0, nDotPos);
890
891 if (nEndCellDotPos == 0)
892 {
893 // workaround for old syntax (probably pre-chart2 age?)
894 // e.g. Sheet1.A1:.B2
895 aBuf.append(aEndCell);
896 }
897 else if (nEndCellDotPos < 0)
898 {
899 // sheet name in the end cell is omitted (e.g. Sheet2.A1:B2).
900 aBuf.append(sal_Unicode('.'));
901 aBuf.append(aEndCell);
902 }
903 aEndCell = aBuf.makeStringAndClear();
904 }
905
906 ScAddress::ExternalInfo aExtInfo1, aExtInfo2;
907 ScAddress aCell1, aCell2;
908 rtl::OUString aBuf;
909 sal_uInt16 nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1);
910 if ((nRet & SCA_VALID) != SCA_VALID)
911 // first cell is invalid.
912 continue;
913
914 nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2);
915 if ((nRet & SCA_VALID) != SCA_VALID)
916 // second cell is invalid.
917 continue;
918
919 if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal)
920 // external info inconsistency.
921 continue;
922
923 // All looks good!
924
925 if (bFirst)
926 bFirst = false;
927 else
928 aRetStr.appendAscii(";");
929
930 lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2);
931 }
932 else
933 {
934 // Chart always saves ranges using CONV_OOO convention.
935 ScAddress::ExternalInfo aExtInfo;
936 ScAddress aCell;
937 sal_uInt16 nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo);
938 if ((nRet & SCA_VALID) != SCA_VALID)
939 continue;
940
941 // Looks good!
942
943 if (bFirst)
944 bFirst = false;
945 else
946 aRetStr.appendAscii(";");
947
948 lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo);
949 }
950 }
951
952 rString = aRetStr.makeStringAndClear();
953 }
954
955 //========================================================================
956
ScArea(SCTAB tab,SCCOL colStart,SCROW rowStart,SCCOL colEnd,SCROW rowEnd)957 ScArea::ScArea( SCTAB tab,
958 SCCOL colStart, SCROW rowStart,
959 SCCOL colEnd, SCROW rowEnd ) :
960 nTab ( tab ),
961 nColStart( colStart ), nRowStart( rowStart ),
962 nColEnd ( colEnd ), nRowEnd ( rowEnd )
963 {
964 }
965
966 //------------------------------------------------------------------------
967
ScArea(const ScArea & r)968 ScArea::ScArea( const ScArea& r ) :
969 nTab ( r.nTab ),
970 nColStart( r.nColStart ), nRowStart( r.nRowStart ),
971 nColEnd ( r.nColEnd ), nRowEnd ( r.nRowEnd )
972 {
973 }
974
975 //------------------------------------------------------------------------
976
operator =(const ScArea & r)977 ScArea& ScArea::operator=( const ScArea& r )
978 {
979 nTab = r.nTab;
980 nColStart = r.nColStart;
981 nRowStart = r.nRowStart;
982 nColEnd = r.nColEnd;
983 nRowEnd = r.nRowEnd;
984 return *this;
985 }
986
987 //------------------------------------------------------------------------
988
operator ==(const ScArea & r) const989 sal_Bool ScArea::operator==( const ScArea& r ) const
990 {
991 return ( (nTab == r.nTab)
992 && (nColStart == r.nColStart)
993 && (nRowStart == r.nRowStart)
994 && (nColEnd == r.nColEnd)
995 && (nRowEnd == r.nRowEnd) );
996 }
997
998 //------------------------------------------------------------------------
999
ScAreaNameIterator(ScDocument * pDoc)1000 ScAreaNameIterator::ScAreaNameIterator( ScDocument* pDoc )
1001 {
1002 pRangeName = pDoc->GetRangeName();
1003 pDBCollection = pDoc->GetDBCollection();
1004 nPos = 0;
1005 bFirstPass = sal_True;
1006 }
1007
Next(String & rName,ScRange & rRange)1008 sal_Bool ScAreaNameIterator::Next( String& rName, ScRange& rRange )
1009 {
1010 for (;;)
1011 {
1012 if ( bFirstPass ) // erst Bereichsnamen
1013 {
1014 if ( pRangeName && nPos < pRangeName->GetCount() )
1015 {
1016 ScRangeData* pData = (*pRangeName)[nPos++];
1017 if ( pData && pData->IsValidReference(rRange) )
1018 {
1019 rName = pData->GetName();
1020 return sal_True; // gefunden
1021 }
1022 }
1023 else
1024 {
1025 bFirstPass = sal_False;
1026 nPos = 0;
1027 }
1028 }
1029 if ( !bFirstPass ) // dann DB-Bereiche
1030 {
1031 if ( pDBCollection && nPos < pDBCollection->GetCount() )
1032 {
1033 ScDBData* pData = (*pDBCollection)[nPos++];
1034 if ( pData
1035 && !pData->IsInternalUnnamed()
1036 && !pData->IsInternalForAutoFilter() )
1037 {
1038 pData->GetArea( rRange );
1039 rName = pData->GetName();
1040 return sal_True; // gefunden
1041 }
1042 }
1043 else
1044 return sal_False; // gibt nichts mehr
1045 }
1046 }
1047 }
1048
1049
1050
1051
1052