1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_SC_INC_ADDRESS_HXX
21 #define INCLUDED_SC_INC_ADDRESS_HXX
23 #include <rtl/ustrbuf.hxx>
24 #include <rtl/strbuf.hxx>
32 #include <formula/grammar.hxx>
34 #include <o3tl/typed_flags_set.hxx>
35 #include <com/sun/star/uno/Sequence.hxx>
37 namespace com
{ namespace sun
{ namespace star
{
39 struct ExternalLinkInfo
;
45 /** size_t typedef to be able to find places where code was changed from USHORT
46 to size_t and is used to read/write from/to streams. */
47 typedef size_t SCSIZE
;
49 // Maximum possible value of data type, NOT maximum row value.
50 // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is
51 // included, we should not be using those stupid macros anyway.
54 const SCROW SCROW_MAX
= ::std::numeric_limits
<SCROW
>::max();
55 const SCCOL SCCOL_MAX
= ::std::numeric_limits
<SCCOL
>::max();
56 const SCTAB SCTAB_MAX
= ::std::numeric_limits
<SCTAB
>::max();
57 const SCCOLROW SCCOLROW_MAX
= ::std::numeric_limits
<SCCOLROW
>::max();
58 const SCSIZE SCSIZE_MAX
= ::std::numeric_limits
<SCSIZE
>::max();
60 // The maximum values. Defines are needed for preprocessor checks, for example
61 // in bcaslot.cxx, otherwise type safe constants are preferred.
62 #define MAXROWCOUNT_DEFINE 1048576
63 #define MAXCOLCOUNT_DEFINE 1024
66 const SCROW MAXROWCOUNT
= MAXROWCOUNT_DEFINE
;
67 const SCCOL MAXCOLCOUNT
= MAXCOLCOUNT_DEFINE
;
68 /// limiting to 10000 for now, problem with 32 bit builds for now
69 const SCTAB MAXTABCOUNT
= 10000;
70 const SCCOLROW MAXCOLROWCOUNT
= MAXROWCOUNT
;
72 const SCROW MAXROW
= MAXROWCOUNT
- 1;
73 const SCCOL MAXCOL
= MAXCOLCOUNT
- 1;
74 const SCTAB MAXTAB
= MAXTABCOUNT
- 1;
75 const SCCOLROW MAXCOLROW
= MAXROW
;
76 // Maximun tiled rendering values
77 const SCROW MAXTILEDROW
= 500000;
78 // Limit the initial tab count to prevent users to set the count too high,
79 // which could cause the memory usage of blank documents to exceed the
80 // available system memory.
81 const SCTAB MAXINITTAB
= 1024;
82 const SCTAB MININITTAB
= 1;
85 const SCTAB SC_TAB_APPEND
= SCTAB_MAX
;
86 const SCTAB TABLEID_DOC
= SCTAB_MAX
; // entire document, e.g. protect
87 const SCROW SCROWS32K
= 32000;
88 const SCCOL SCCOL_REPEAT_NONE
= SCCOL_MAX
;
89 const SCROW SCROW_REPEAT_NONE
= SCROW_MAX
;
91 #define MAXROW_30 8191
93 SAL_WARN_UNUSED_RESULT
inline bool ValidCol( SCCOL nCol
)
95 return nCol
>= 0 && nCol
<= MAXCOL
;
98 SAL_WARN_UNUSED_RESULT
inline bool ValidRow( SCROW nRow
)
100 return nRow
>= 0 && nRow
<= MAXROW
;
103 SAL_WARN_UNUSED_RESULT
inline bool ValidTab( SCTAB nTab
)
105 return nTab
>= 0 && nTab
<= MAXTAB
;
108 SAL_WARN_UNUSED_RESULT
inline bool ValidTab( SCTAB nTab
, SCTAB nMaxTab
)
110 return nTab
>= 0 && nTab
<= nMaxTab
;
113 SAL_WARN_UNUSED_RESULT
inline bool ValidColRow( SCCOL nCol
, SCROW nRow
)
115 return ValidCol( nCol
) && ValidRow( nRow
);
118 SAL_WARN_UNUSED_RESULT
inline bool ValidColRowTab( SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
120 return ValidCol( nCol
) && ValidRow( nRow
) && ValidTab( nTab
);
123 SAL_WARN_UNUSED_RESULT
inline SCCOL
SanitizeCol( SCCOL nCol
)
125 return nCol
< 0 ? 0 : std::min(nCol
, MAXCOL
);
128 SAL_WARN_UNUSED_RESULT
inline SCROW
SanitizeRow( SCROW nRow
)
130 return nRow
< 0 ? 0 : std::min(nRow
, MAXROW
);
133 SAL_WARN_UNUSED_RESULT
inline SCTAB
SanitizeTab( SCTAB nTab
)
135 return nTab
< 0 ? 0 : std::min(nTab
, MAXTAB
);
138 // The result of ConvertRef() is a bit group of the following:
139 enum class ScRefFlags
: sal_uInt16
153 // BITS for convenience
154 BITS
= COL_ABS
| ROW_ABS
| TAB_ABS
| TAB_3D
155 | ROW_VALID
| COL_VALID
| TAB_VALID
,
156 // somewhat cheesy kludge to force the display of the document name even for
157 // local references. Requires TAB_3D to be valid
164 TAB_ABS_3D
= TAB_ABS
| TAB_3D
,
166 ADDR_ABS
= VALID
| COL_ABS
| ROW_ABS
| TAB_ABS
,
168 RANGE_ABS
= ADDR_ABS
| COL2_ABS
| ROW2_ABS
| TAB2_ABS
,
170 ADDR_ABS_3D
= ADDR_ABS
| TAB_3D
,
171 RANGE_ABS_3D
= RANGE_ABS
| TAB_3D
176 template<> struct typed_flags
<ScRefFlags
> : is_typed_flags
<ScRefFlags
, 0xffff> {};
178 inline void applyStartToEndFlags(ScRefFlags
&target
,const ScRefFlags source
)
180 target
|= ScRefFlags(static_cast<std::underlying_type
<ScRefFlags
>::type
>(source
) << 4);
182 inline void applyStartToEndFlags(ScRefFlags
&target
)
184 target
|= ScRefFlags(static_cast<std::underlying_type
<ScRefFlags
>::type
>(target
) << 4);
188 class SAL_WARN_UNUSED ScAddress
191 // Even if the fields are in the order "row, column, tab", in all (?) the ScAddress and
192 // ScDocument APIs that take separate row, column, and tab parameters, the parameters are in the
193 // order "column, row, tab", which matches the most common (A1) address syntax, if you ignore
194 // the sheet (tab). Don't let this confuse you, like it confused me for a while.
202 enum Uninitialized
{ UNINITIALIZED
};
203 enum InitializeInvalid
{ INITIALIZE_INVALID
};
207 formula::FormulaGrammar::AddressConvention eConv
;
211 Details( formula::FormulaGrammar::AddressConvention eConvP
, SCROW nRowP
, SCCOL nColP
) :
212 eConv(eConvP
), nRow(nRowP
), nCol(nColP
)
214 Details( formula::FormulaGrammar::AddressConvention eConvP
, ScAddress
const & rAddr
) :
215 eConv(eConvP
), nRow(rAddr
.Row()), nCol(rAddr
.Col())
217 Details( formula::FormulaGrammar::AddressConvention eConvP
) :
218 eConv(eConvP
), nRow(0), nCol(0)
220 /* Use the formula::FormulaGrammar::AddressConvention associated with rAddr::Tab() */
221 Details( const ScDocument
* pDoc
, const ScAddress
& rAddr
);
223 SC_DLLPUBLIC
static const Details detailsOOOa1
;
232 mnFileId(0), mbExternal(false)
237 nRow(0), nCol(0), nTab(0)
239 ScAddress( SCCOL nColP
, SCROW nRowP
, SCTAB nTabP
) :
240 nRow(nRowP
), nCol(nColP
), nTab(nTabP
)
242 /** Yes, it is what it seems to be: Uninitialized. May be used for
243 performance reasons if it is initialized by other means. */
244 ScAddress( Uninitialized
)
246 ScAddress( InitializeInvalid
) :
247 nRow(-1), nCol(-1), nTab(-1)
249 ScAddress( const ScAddress
& rAddress
) :
250 nRow(rAddress
.nRow
), nCol(rAddress
.nCol
), nTab(rAddress
.nTab
)
252 inline ScAddress
& operator=( const ScAddress
& rAddress
);
254 inline void Set( SCCOL nCol
, SCROW nRow
, SCTAB nTab
);
269 void SetRow( SCROW nRowP
)
273 void SetCol( SCCOL nColP
)
277 void SetTab( SCTAB nTabP
)
289 return (nRow
>= 0) && (nCol
>= 0) && (nTab
>= 0);
292 inline void PutInOrder( ScAddress
& rAddress
);
294 void IncRow( SCROW nDelta
= 1 )
296 nRow
= sal::static_int_cast
<SCROW
>(nRow
+ nDelta
);
298 void IncCol( SCCOL nDelta
= 1 )
300 nCol
= sal::static_int_cast
<SCCOL
>(nCol
+ nDelta
);
302 void IncTab( SCTAB nDelta
= 1 )
304 nTab
= sal::static_int_cast
<SCTAB
>(nTab
+ nDelta
);
306 void GetVars( SCCOL
& nColP
, SCROW
& nRowP
, SCTAB
& nTabP
) const
315 If given and Parse() successfully parsed a sheet name it returns
316 the end position (exclusive) behind the sheet name AND a
317 following sheet name separator. This independent of whether the
318 resulting reference is fully valid or not.
320 SC_DLLPUBLIC ScRefFlags
Parse(
321 const OUString
&, const ScDocument
* = nullptr,
322 const Details
& rDetails
= detailsOOOa1
,
323 ExternalInfo
* pExtInfo
= nullptr,
324 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
325 sal_Int32
* pSheetEndPos
= nullptr,
326 const OUString
* pErrRef
= nullptr );
328 SC_DLLPUBLIC
void Format( OStringBuffer
& r
, ScRefFlags nFlags
,
329 const ScDocument
* pDocument
= nullptr,
330 const Details
& rDetails
= detailsOOOa1
) const;
332 SC_DLLPUBLIC OUString
Format( ScRefFlags nFlags
,
333 const ScDocument
* pDocument
= nullptr,
334 const Details
& rDetails
= detailsOOOa1
) const;
338 If FALSE is returned, the positions contain <0 or >MAX...
339 values if shifted out of bounds.
341 The document for the maximum defined sheet number.
343 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT
bool Move( SCCOL nDeltaX
, SCROW nDeltaY
, SCTAB nDeltaZ
,
344 ScAddress
& rErrorPos
, const ScDocument
* pDocument
= nullptr );
346 inline bool operator==( const ScAddress
& rAddress
) const;
347 inline bool operator!=( const ScAddress
& rAddress
) const;
348 inline bool operator<( const ScAddress
& rAddress
) const;
349 inline bool operator<=( const ScAddress
& rAddress
) const;
350 inline bool lessThanByRow( const ScAddress
& rAddress
) const;
352 inline size_t hash() const;
355 * Create a human-readable string representation of the cell address. You
356 * cannot specify precise formatting with this method; use Format() if you
357 * need to specify how the address needs to be formatted.
359 * The address string does not display sheet name.
361 * @return human-readable string representation of the cell address.
363 OUString
GetColRowString() const;
366 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
367 template<typename charT
, typename traits
>
368 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScAddress
& rAddress
)
371 rAddress
.Tab()+1 << "!"
372 "R" << rAddress
.Row()+1 <<
373 "C" << rAddress
.Col()+1;
378 inline void ScAddress::PutInOrder( ScAddress
& rAddress
)
380 if ( rAddress
.Col() < Col() )
382 SCCOL nTmp
= rAddress
.Col();
383 rAddress
.SetCol( Col() );
386 if ( rAddress
.Row() < Row() )
388 SCROW nTmp
= rAddress
.Row();
389 rAddress
.SetRow( Row() );
392 if ( rAddress
.Tab() < Tab() )
394 SCTAB nTmp
= rAddress
.Tab();
395 rAddress
.SetTab( Tab() );
400 inline void ScAddress::Set( SCCOL nColP
, SCROW nRowP
, SCTAB nTabP
)
407 inline ScAddress
& ScAddress::operator=( const ScAddress
& rAddress
)
409 nCol
= rAddress
.nCol
;
410 nRow
= rAddress
.nRow
;
411 nTab
= rAddress
.nTab
;
415 inline bool ScAddress::operator==( const ScAddress
& rAddress
) const
417 return nRow
== rAddress
.nRow
&& nCol
== rAddress
.nCol
&& nTab
== rAddress
.nTab
;
420 inline bool ScAddress::operator!=( const ScAddress
& rAddress
) const
422 return !operator==( rAddress
);
425 /** Less than ordered by tab,col,row. */
426 inline bool ScAddress::operator<( const ScAddress
& rAddress
) const
428 if (nTab
== rAddress
.nTab
)
430 if (nCol
== rAddress
.nCol
)
431 return nRow
< rAddress
.nRow
;
433 return nCol
< rAddress
.nCol
;
436 return nTab
< rAddress
.nTab
;
439 inline bool ScAddress::operator<=( const ScAddress
& rAddress
) const
441 return operator<( rAddress
) || operator==( rAddress
);
444 /** Less than ordered by tab,row,col as needed by row-wise import/export */
445 inline bool ScAddress::lessThanByRow( const ScAddress
& rAddress
) const
447 if (nTab
== rAddress
.nTab
)
449 if (nRow
== rAddress
.nRow
)
450 return nCol
< rAddress
.nCol
;
452 return nRow
< rAddress
.nRow
;
455 return nTab
< rAddress
.nTab
;
458 inline size_t ScAddress::hash() const
460 // Assume that there are not that many addresses with row > 2^16 AND column
461 // > 2^8 AND sheet > 2^8 so we won't have too many collisions.
463 return (static_cast<size_t>(nTab
) << 24) ^
464 (static_cast<size_t>(nCol
) << 16) ^ static_cast<size_t>(nRow
);
466 return (static_cast<size_t>(nTab
) << 28) ^
467 (static_cast<size_t>(nCol
) << 24) ^ static_cast<size_t>(nRow
);
470 struct ScAddressHashFunctor
472 size_t operator()( const ScAddress
& rAddress
) const
474 return rAddress
.hash();
478 inline bool ValidAddress( const ScAddress
& rAddress
)
480 return ValidCol(rAddress
.Col()) && ValidRow(rAddress
.Row()) && ValidTab(rAddress
.Tab());
484 class SAL_WARN_UNUSED ScRange final
494 ScRange( ScAddress::Uninitialized eUninitialized
) :
495 aStart( eUninitialized
), aEnd( eUninitialized
)
497 ScRange( ScAddress::InitializeInvalid eInvalid
) :
498 aStart( eInvalid
), aEnd( eInvalid
)
500 ScRange( const ScAddress
& aInputStart
, const ScAddress
& aInputEnd
) :
501 aStart( aInputStart
), aEnd( aInputEnd
)
503 aStart
.PutInOrder( aEnd
);
505 ScRange( const ScRange
& rRange
) :
506 aStart( rRange
.aStart
), aEnd( rRange
.aEnd
)
508 ScRange( const ScAddress
& rRange
) :
509 aStart( rRange
), aEnd( rRange
)
511 ScRange( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) :
512 aStart( nCol
, nRow
, nTab
), aEnd( aStart
)
514 ScRange( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
, SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
) :
515 aStart( nCol1
, nRow1
, nTab1
), aEnd( nCol2
, nRow2
, nTab2
)
518 ScRange
& operator=( const ScRange
& rRange
)
520 aStart
= rRange
.aStart
;
524 ScRange
& operator=( const ScAddress
& rPos
)
526 aStart
= aEnd
= rPos
;
536 return aStart
.IsValid() && aEnd
.IsValid();
538 inline bool In( const ScAddress
& ) const; ///< is Address& in Range?
539 inline bool In( const ScRange
& ) const; ///< is Range& in Range?
541 SC_DLLPUBLIC ScRefFlags
Parse( const OUString
&, const ScDocument
* = nullptr,
542 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
,
543 ScAddress::ExternalInfo
* pExtInfo
= nullptr,
544 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
545 const OUString
* pErrRef
= nullptr );
547 SC_DLLPUBLIC ScRefFlags
ParseAny( const OUString
&, const ScDocument
*,
548 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
549 SC_DLLPUBLIC ScRefFlags
ParseCols( const OUString
&,
550 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
551 SC_DLLPUBLIC
void ParseRows( const OUString
&,
552 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
);
554 /** Parse an Excel style reference up to and including the sheet name
555 separator '!', including detection of external documents and sheet
556 names, and in case of MOOXML import the bracketed index is used to
557 determine the actual document name passed in pExternalLinks. For
558 internal references (resulting rExternDocName empty), aStart.nTab and
559 aEnd.nTab are set, or -1 if sheet name not found.
560 @param bOnlyAcceptSingle If <TRUE/>, a 3D reference (Sheet1:Sheet2)
561 encountered results in an error (NULL returned).
562 @param pExternalLinks pointer to ExternalLinkInfo sequence, may be
563 NULL for non-filter usage, in which case indices such as [1] are
565 @param pErrRef pointer to "#REF!" string if to be accepted.
567 Pointer to the position after '!' if successfully parsed, and
568 rExternDocName, rStartTabName and/or rEndTabName filled if
569 applicable. ScRefFlags::... flags set in nFlags.
570 Or if no valid document and/or sheet header could be parsed the start
571 position passed with pString.
572 Or NULL if a 3D sheet header could be parsed but
573 bOnlyAcceptSingle==true was given.
575 const sal_Unicode
* Parse_XL_Header( const sal_Unicode
* pString
, const ScDocument
* pDocument
,
576 OUString
& rExternDocName
, OUString
& rStartTabName
,
577 OUString
& rEndTabName
, ScRefFlags
& nFlags
,
578 bool bOnlyAcceptSingle
,
579 const css::uno::Sequence
<css::sheet::ExternalLinkInfo
>* pExternalLinks
= nullptr,
580 const OUString
* pErrRef
= nullptr );
582 /** Returns string with formatted cell range from aStart to aEnd,
583 according to provided address convention.
587 Pointer to document which is used for example to get tab names.
589 Provide information about required address convention.
590 Supported address conventions are:
591 CONV_OOO 'doc'#sheet.A1:sheet2.B2
592 CONV_XL_A1, [doc]sheet:sheet2!A1:B2
593 CONV_XL_OOX, [#]sheet:sheet2!A1:B2
594 CONV_XL_R1C1, [doc]sheet:sheet2!R1C1:R2C2
595 @param bFullAddressNotation
596 If TRUE, the full address notation will be used.
597 For example in case all columns are used, "A1:AMJ177" is full address notation
598 and "1:177" is shortened address notation.
600 String contains formatted cell range in address convention
602 SC_DLLPUBLIC OUString
Format( ScRefFlags nFlags
= ScRefFlags::ZERO
,
603 const ScDocument
* pDocument
= nullptr,
604 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
,
605 bool bFullAddressNotation
= false ) const;
607 inline void GetVars( SCCOL
& nCol1
, SCROW
& nRow1
, SCTAB
& nTab1
,
608 SCCOL
& nCol2
, SCROW
& nRow2
, SCTAB
& nTab2
) const;
609 SC_DLLPUBLIC
void PutInOrder();
613 If FALSE is returned, the positions contain <0 or >MAX...
614 values if shifted out of bounds.
616 The document for the maximum defined sheet number.
618 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT
bool Move( SCCOL aDeltaX
, SCROW aDeltaY
, SCTAB aDeltaZ
,
619 ScRange
& rErrorRange
, const ScDocument
* pDocument
= nullptr );
621 /** Same as Move() but with sticky end col/row anchors. */
622 SC_DLLPUBLIC SAL_WARN_UNUSED_RESULT
bool MoveSticky( SCCOL aDeltaX
, SCROW aDeltaY
, SCTAB aDeltaZ
,
623 ScRange
& rErrorRange
);
625 SC_DLLPUBLIC
void IncColIfNotLessThan(SCCOL nStartCol
, SCCOL nOffset
);
626 SC_DLLPUBLIC
void IncRowIfNotLessThan(SCROW nStartRow
, SCROW nOffset
);
628 SC_DLLPUBLIC
void ExtendTo( const ScRange
& rRange
);
629 SC_DLLPUBLIC
bool Intersects( const ScRange
& rRange
) const; // do two ranges intersect?
631 ScRange
Intersection( const ScRange
& rOther
) const;
633 /// If maximum end column should not be adapted during reference update.
634 inline bool IsEndColSticky() const;
635 /// If maximum end row should not be adapted during reference update.
636 inline bool IsEndRowSticky() const;
638 /** Increment or decrement end column unless sticky or until it becomes
639 sticky. Checks if the range encompasses at least two columns so should
640 be called before adjusting the start column. */
641 void IncEndColSticky( SCCOL nDelta
);
643 /** Increment or decrement end row unless sticky or until it becomes
644 sticky. Checks if the range encompasses at least two rows so should
645 be called before adjusting the start row. */
646 void IncEndRowSticky( SCROW nDelta
);
648 inline bool operator==( const ScRange
& rRange
) const;
649 inline bool operator!=( const ScRange
& rRange
) const;
650 inline bool operator<( const ScRange
& rRange
) const;
651 inline bool operator<=( const ScRange
& rRange
) const;
653 /// Hash 2D area ignoring table number.
654 inline size_t hashArea() const;
655 /// Hash start column and start and end rows.
656 inline size_t hashStartColumn() const;
659 // For use in SAL_DEBUG etc. Output format not guaranteed to be stable.
660 template<typename charT
, typename traits
>
661 inline std::basic_ostream
<charT
, traits
> & operator <<(std::basic_ostream
<charT
, traits
> & stream
, const ScRange
& rRange
)
663 stream
<< rRange
.aStart
;
664 if (rRange
.aEnd
!= rRange
.aStart
)
667 if (rRange
.aEnd
.Tab() != rRange
.aStart
.Tab())
668 stream
<< rRange
.aEnd
;
671 "R" << rRange
.aEnd
.Row()+1 <<
672 "C" << rRange
.aEnd
.Col()+1;
678 inline void ScRange::GetVars( SCCOL
& nCol1
, SCROW
& nRow1
, SCTAB
& nTab1
,
679 SCCOL
& nCol2
, SCROW
& nRow2
, SCTAB
& nTab2
) const
681 aStart
.GetVars( nCol1
, nRow1
, nTab1
);
682 aEnd
.GetVars( nCol2
, nRow2
, nTab2
);
685 inline bool ScRange::IsEndColSticky() const
687 // Only in an actual column range, i.e. not if both columns are MAXCOL.
688 return aEnd
.Col() == MAXCOL
&& aStart
.Col() < aEnd
.Col();
691 inline bool ScRange::IsEndRowSticky() const
693 // Only in an actual row range, i.e. not if both rows are MAXROW.
694 return aEnd
.Row() == MAXROW
&& aStart
.Row() < aEnd
.Row();
697 inline bool ScRange::operator==( const ScRange
& rRange
) const
699 return ( (aStart
== rRange
.aStart
) && (aEnd
== rRange
.aEnd
) );
702 inline bool ScRange::operator!=( const ScRange
& rRange
) const
704 return !operator==( rRange
);
707 /// Sort on upper left corner tab,col,row, if equal then use lower right too.
708 inline bool ScRange::operator<( const ScRange
& r
) const
710 return aStart
< r
.aStart
|| (aStart
== r
.aStart
&& aEnd
< r
.aEnd
) ;
713 inline bool ScRange::operator<=( const ScRange
& rRange
) const
715 return operator<( rRange
) || operator==( rRange
);
718 inline bool ScRange::In( const ScAddress
& rAddress
) const
721 aStart
.Col() <= rAddress
.Col() && rAddress
.Col() <= aEnd
.Col() &&
722 aStart
.Row() <= rAddress
.Row() && rAddress
.Row() <= aEnd
.Row() &&
723 aStart
.Tab() <= rAddress
.Tab() && rAddress
.Tab() <= aEnd
.Tab();
726 inline bool ScRange::In( const ScRange
& rRange
) const
729 aStart
.Col() <= rRange
.aStart
.Col() && rRange
.aEnd
.Col() <= aEnd
.Col() &&
730 aStart
.Row() <= rRange
.aStart
.Row() && rRange
.aEnd
.Row() <= aEnd
.Row() &&
731 aStart
.Tab() <= rRange
.aStart
.Tab() && rRange
.aEnd
.Tab() <= aEnd
.Tab();
734 inline size_t ScRange::hashArea() const
736 // Assume that there are not that many ranges with identical corners so we
737 // won't have too many collisions. Also assume that more lower row and
738 // column numbers are used so that there are not too many conflicts with
739 // the columns hashed into the values, and that start row and column
740 // usually don't exceed certain values. High bits are not masked off and
741 // may overlap with lower bits of other values, e.g. if start column is
742 // greater than assumed.
744 (static_cast<size_t>(aStart
.Row()) << 26) ^ // start row <= 2^6
745 (static_cast<size_t>(aStart
.Col()) << 21) ^ // start column <= 2^5
746 (static_cast<size_t>(aEnd
.Col()) << 15) ^ // end column <= 2^6
747 static_cast<size_t>(aEnd
.Row()); // end row <= 2^15
750 inline size_t ScRange::hashStartColumn() const
752 // Assume that for the start row more lower row numbers are used so that
753 // there are not too many conflicts with the column hashed into the higher
756 (static_cast<size_t>(aStart
.Col()) << 24) ^ // start column <= 2^8
757 (static_cast<size_t>(aStart
.Row()) << 16) ^ // start row <= 2^8
758 static_cast<size_t>(aEnd
.Row());
761 inline bool ValidRange( const ScRange
& rRange
)
763 return ValidAddress(rRange
.aStart
) && ValidAddress(rRange
.aEnd
);
767 class SAL_WARN_UNUSED ScRangePair final
770 std::array
<ScRange
,2> aRange
;
773 ScRangePair( const ScRangePair
& r
)
775 aRange
[0] = r
.aRange
[0];
776 aRange
[1] = r
.aRange
[1];
778 ScRangePair( const ScRange
& rRange1
, const ScRange
& rRange2
)
784 inline ScRangePair
& operator= ( const ScRangePair
& rRange
);
785 const ScRange
& GetRange( sal_uInt16 n
) const
789 ScRange
& GetRange( sal_uInt16 n
)
795 inline ScRangePair
& ScRangePair::operator= ( const ScRangePair
& rRange
)
797 aRange
[0] = rRange
.aRange
[0];
798 aRange
[1] = rRange
.aRange
[1];
803 class SAL_WARN_UNUSED ScRefAddress
812 bRelCol(false), bRelRow(false), bRelTab(false)
814 ScRefAddress( SCCOL nCol
, SCROW nRow
, SCTAB nTab
) :
815 aAdr(nCol
, nRow
, nTab
),
816 bRelCol(false), bRelRow(false), bRelTab(false)
818 ScRefAddress( const ScRefAddress
& rRef
) :
819 aAdr(rRef
.aAdr
), bRelCol(rRef
.bRelCol
), bRelRow(rRef
.bRelRow
),
820 bRelTab(rRef
.bRelTab
)
823 inline ScRefAddress
& operator=( const ScRefAddress
& );
825 bool IsRelCol() const
829 bool IsRelRow() const
833 bool IsRelTab() const
838 void SetRelCol(bool bNewRelCol
)
840 bRelCol
= bNewRelCol
;
842 void SetRelRow(bool bNewRelRow
)
844 bRelRow
= bNewRelRow
;
846 void SetRelTab(bool bNewRelTab
)
848 bRelTab
= bNewRelTab
;
851 inline void Set( const ScAddress
& rAdr
,
852 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
);
853 inline void Set( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
,
854 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
);
856 const ScAddress
& GetAddress() const
874 inline bool operator == ( const ScRefAddress
& r
) const;
876 OUString
GetRefString( const ScDocument
* pDocument
, SCTAB nActTab
,
877 const ScAddress::Details
& rDetails
= ScAddress::detailsOOOa1
) const;
880 inline ScRefAddress
& ScRefAddress::operator=( const ScRefAddress
& rRef
)
883 bRelCol
= rRef
.bRelCol
;
884 bRelRow
= rRef
.bRelRow
;
885 bRelTab
= rRef
.bRelTab
;
889 inline void ScRefAddress::Set( const ScAddress
& rAdr
,
890 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
)
893 bRelCol
= bNewRelCol
;
894 bRelRow
= bNewRelRow
;
895 bRelTab
= bNewRelTab
;
898 inline void ScRefAddress::Set( SCCOL nNewCol
, SCROW nNewRow
, SCTAB nNewTab
,
899 bool bNewRelCol
, bool bNewRelRow
, bool bNewRelTab
)
901 aAdr
.Set( nNewCol
, nNewRow
, nNewTab
);
902 bRelCol
= bNewRelCol
;
903 bRelRow
= bNewRelRow
;
904 bRelTab
= bNewRelTab
;
907 inline bool ScRefAddress::operator==( const ScRefAddress
& rRefAddress
) const
909 return aAdr
== rRefAddress
.aAdr
&&
910 bRelCol
== rRefAddress
.bRelCol
&&
911 bRelRow
== rRefAddress
.bRelRow
&&
912 bRelTab
== rRefAddress
.bRelTab
;
917 // Special values for cells always broadcasting or listening (ScRecalcMode::ALWAYS
919 #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 )
920 #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS )
922 template< typename T
> void PutInOrder( T
& nStart
, T
& nEnd
)
926 std::swap(nStart
, nEnd
);
930 bool ConvertSingleRef( const ScDocument
* pDocument
, const OUString
& rRefString
,
931 SCTAB nDefTab
, ScRefAddress
& rRefAddress
,
932 const ScAddress::Details
& rDetails
,
933 ScAddress::ExternalInfo
* pExtInfo
= nullptr );
935 bool ConvertDoubleRef( const ScDocument
* pDocument
, const OUString
& rRefString
,
936 SCTAB nDefTab
, ScRefAddress
& rStartRefAddress
,
937 ScRefAddress
& rEndRefAddress
,
938 const ScAddress::Details
& rDetails
,
939 ScAddress::ExternalInfo
* pExtInfo
= nullptr );
941 /// append alpha representation of column to buffer
942 SC_DLLPUBLIC
void ScColToAlpha( OUStringBuffer
& rBuffer
, SCCOL nCol
);
944 inline void ScColToAlpha( OUString
& rStr
, SCCOL nCol
)
946 OUStringBuffer
aBuf(2);
947 ScColToAlpha( aBuf
, nCol
);
948 rStr
+= aBuf
.makeStringAndClear();
951 inline OUString
ScColToAlpha( SCCOL nCol
)
953 OUStringBuffer
aBuf(2);
954 ScColToAlpha( aBuf
, nCol
);
955 return aBuf
.makeStringAndClear();
958 /// get column number of A..IV... string
959 bool AlphaToCol( SCCOL
& rCol
, const OUString
& rStr
);
961 #endif // INCLUDED_SC_INC_ADDRESS_HXX
963 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */