1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #include "scitems.hxx"
21 #include <comphelper/string.hxx>
22 #include <svx/algitem.hxx>
23 #include <editeng/boxitem.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/contouritem.hxx>
26 #include <editeng/colritem.hxx>
27 #include <editeng/crossedoutitem.hxx>
28 #include <editeng/fhgtitem.hxx>
29 #include <editeng/fontitem.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/postitem.hxx>
32 #include <editeng/shdditem.hxx>
33 #include <editeng/udlnitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <svx/rotmodit.hxx>
36 #include <editeng/editobj.hxx>
37 #include <editeng/editeng.hxx>
38 #include <editeng/eeitem.hxx>
39 #include <editeng/escapementitem.hxx>
40 #include <svl/zforlist.hxx>
41 #include <vcl/keycodes.hxx>
42 #include <rtl/math.hxx>
43 #include <unotools/charclass.hxx>
46 #include "patattr.hxx"
47 #include "formulacell.hxx"
49 #include "globstr.hrc"
51 #include "document.hxx"
52 #include "autoform.hxx"
53 #include "userlist.hxx"
54 #include "zforauto.hxx"
55 #include "subtotal.hxx"
56 #include <formula/errorcodes.hxx>
57 #include "rangenam.hxx"
58 #include "docpool.hxx"
59 #include "progress.hxx"
60 #include "segmenttree.hxx"
61 #include "conditio.hxx"
62 #include "editutil.hxx"
63 #include <columnspanset.hxx>
64 #include <listenercontext.hxx>
67 #include <boost/scoped_ptr.hpp>
69 // STATIC DATA -----------------------------------------------------------
71 #define _D_MAX_LONG_ (double) 0x7fffffff
73 extern sal_uInt16 nScFillModeMouseModifier
; // global.cxx
77 short lcl_DecompValueString( OUString
& rValue
, sal_Int32
& nVal
, sal_uInt16
* pMinDigits
= NULL
)
79 if ( rValue
.isEmpty() )
84 const sal_Unicode
* p
= rValue
.getStr();
89 while ( p
[nNum
] && CharClass::isAsciiNumeric( OUString(p
[nNum
]) ) )
92 sal_Unicode cNext
= p
[nNum
]; // 0 if at the end
93 sal_Unicode cLast
= p
[rValue
.getLength()-1];
95 // #i5550# If there are numbers at the beginning and the end,
96 // prefer the one at the beginning only if it's followed by a space.
97 // Otherwise, use the number at the end, to enable things like IP addresses.
98 if ( nNum
> nNeg
&& ( cNext
== 0 || cNext
== ' ' || !CharClass::isAsciiNumeric(OUString(cLast
)) ) )
99 { // number at the beginning
100 nVal
= rValue
.copy( 0, nNum
).toInt32();
101 // any number with a leading zero sets the minimum number of digits
102 if ( p
[nNeg
] == '0' && pMinDigits
&& ( nNum
- nNeg
> *pMinDigits
) )
103 *pMinDigits
= nNum
- nNeg
;
104 rValue
= rValue
.copy(nNum
);
110 sal_Int32 nEnd
= nNum
= rValue
.getLength() - 1;
111 while ( nNum
&& CharClass::isAsciiNumeric( OUString(p
[nNum
]) ) )
113 if ( p
[nNum
] == '-' )
118 if ( nNum
< nEnd
- nNeg
)
119 { // number at the end
120 nVal
= rValue
.copy( nNum
+ 1 ).toInt32();
121 // any number with a leading zero sets the minimum number of digits
122 if ( p
[nNum
+1+nNeg
] == '0' && pMinDigits
&& ( nEnd
- nNum
- nNeg
> *pMinDigits
) )
123 *pMinDigits
= nEnd
- nNum
- nNeg
;
124 rValue
= rValue
.copy(0, nNum
+ 1);
132 OUString
lcl_ValueString( sal_Int32 nValue
, sal_uInt16 nMinDigits
)
134 if ( nMinDigits
<= 1 )
135 return OUString::number( nValue
); // simple case...
138 OUString aStr
= OUString::number( std::abs( nValue
) );
139 if ( aStr
.getLength() < nMinDigits
)
141 OUStringBuffer aZero
;
142 comphelper::string::padToLength(aZero
, nMinDigits
- aStr
.getLength(), '0');
143 aStr
= aZero
.makeStringAndClear() + aStr
;
145 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
153 ScColumn
& rColumn
, SCROW nRow
, sal_Int32 nValue
, sal_uInt16 nDigits
, const OUString
& rSuffix
,
154 CellType eCellType
, bool bIsOrdinalSuffix
)
156 ScDocument
& rDoc
= rColumn
.GetDoc();
157 OUString aValue
= lcl_ValueString(nValue
, nDigits
);
158 if (!bIsOrdinalSuffix
)
160 rColumn
.SetRawString(nRow
, aValue
+= rSuffix
);
164 OUString aOrdinalSuffix
= ScGlobal::GetOrdinalSuffix(nValue
);
165 if (eCellType
!= CELLTYPE_EDIT
)
167 rColumn
.SetRawString(nRow
, aValue
+= aOrdinalSuffix
);
171 EditEngine
aEngine(rDoc
.GetEnginePool());
172 aEngine
.SetEditTextObjectPool(rDoc
.GetEditPool());
174 SfxItemSet aAttr
= aEngine
.GetEmptyItemSet();
175 aAttr
.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT
, EE_CHAR_ESCAPEMENT
));
176 aEngine
.SetText( aValue
);
177 aEngine
.QuickInsertText(
179 ESelection(0, aValue
.getLength(), 0, aValue
.getLength() + aOrdinalSuffix
.getLength()));
181 aEngine
.QuickSetAttribs(
183 ESelection(0, aValue
.getLength(), 0, aValue
.getLength() + aOrdinalSuffix
.getLength()));
185 // Text object instance will be owned by the cell.
186 rColumn
.SetEditText(nRow
, aEngine
.CreateTextObject());
191 void ScTable::FillAnalyse( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
192 FillCmd
& rCmd
, FillDateCmd
& rDateCmd
,
193 double& rInc
, sal_uInt16
& rMinDigits
,
194 ScUserListData
*& rListData
, sal_uInt16
& rListIndex
)
196 OSL_ENSURE( nCol1
==nCol2
|| nRow1
==nRow2
, "FillAnalyse: invalid range" );
202 if ( (nScFillModeMouseModifier
& KEY_MOD1
) )
203 return ; // Ctrl-key: Copy
212 nCount
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
218 nCount
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
224 ScRefCellValue aFirstCell
= GetCellValue(nCol
, nRow
);
225 CellType eCellType
= aFirstCell
.meType
;
227 if (eCellType
== CELLTYPE_VALUE
)
229 sal_uInt32 nFormat
= static_cast<const SfxUInt32Item
*>(GetAttr(nCol
,nRow
,ATTR_VALUE_FORMAT
))->GetValue();
230 bool bDate
= ( pDocument
->GetFormatTable()->GetType(nFormat
) == css::util::NumberFormat::DATE
);
236 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
237 Date aDate1
= aNullDate
;
238 nVal
= aFirstCell
.mfValue
;
239 aDate1
+= (long)nVal
;
240 Date aDate2
= aNullDate
;
241 nVal
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
242 aDate2
+= (long)nVal
;
243 if ( aDate1
!= aDate2
)
247 long nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
248 long nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
249 long nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
253 nCmpInc
= aDate2
- aDate1
;
258 nCmpInc
= nMDiff
+ 12 * nYDiff
;
261 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
262 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
264 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
266 ScRefCellValue aCell
= GetCellValue(nCol
,nRow
);
267 if (aCell
.meType
== CELLTYPE_VALUE
)
269 nVal
= aCell
.mfValue
;
270 aDate2
= aNullDate
+ (long) nVal
;
271 if ( eType
== FILL_DAY
)
273 if ( aDate2
-aDate1
!= nCmpInc
)
278 nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
279 nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
280 nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
281 if (nDDiff
|| ( nMDiff
+ 12 * nYDiff
!= nCmpInc
))
285 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
286 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
289 bVal
= false; // No date is also not ok
293 if ( eType
== FILL_MONTH
&& ( nCmpInc
% 12 == 0 ) )
304 else // single date -> increment by days
315 double nVal1
= aFirstCell
.mfValue
;
316 double nVal2
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
317 rInc
= nVal2
- nVal1
;
318 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
319 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
321 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
323 ScRefCellValue aCell
= GetCellValue(nCol
,nRow
);
324 if (aCell
.meType
== CELLTYPE_VALUE
)
326 nVal2
= aCell
.mfValue
;
327 double nDiff
= nVal2
- nVal1
;
328 if ( !::rtl::math::approxEqual( nDiff
, rInc
, 13 ) )
334 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
335 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
342 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
345 GetString(nCol
, nRow
, aStr
);
347 // fdo#39500 don't deduce increment from multiple equal list entries
348 bool bAllSame
= true;
349 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
352 GetString(static_cast<SCCOL
>(nCol
+ i
* nAddX
), static_cast<SCROW
>(nRow
+ i
* nAddY
), aTestStr
);
359 if(bAllSame
&& nCount
> 1)
362 rListData
= const_cast<ScUserListData
*>(ScGlobal::GetUserList()->GetData(aStr
));
365 (void)rListData
->GetSubIndex(aStr
, rListIndex
);
366 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
367 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
368 for (sal_uInt16 i
=1; i
<nCount
&& rListData
; i
++)
370 (void)GetString(nCol
, nRow
, aStr
);
371 if (!rListData
->GetSubIndex(aStr
, rListIndex
))
373 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
374 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
377 else if ( nCount
> 1 )
379 // pass rMinDigits to all DecompValueString calls
380 // -> longest number defines rMinDigits
383 short nFlag1
= lcl_DecompValueString( aStr
, nVal1
, &rMinDigits
);
387 GetString( nCol
+nAddX
, nRow
+nAddY
, aStr
);
388 short nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
389 if ( nFlag1
== nFlag2
)
391 rInc
= (double)nVal2
- (double)nVal1
;
392 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
393 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
395 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
397 ScRefCellValue aCell
= GetCellValue(nCol
, nRow
);
398 CellType eType
= aCell
.meType
;
399 if ( eType
== CELLTYPE_STRING
|| eType
== CELLTYPE_EDIT
)
401 aStr
= aCell
.getString(pDocument
);
402 nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
403 if ( nFlag1
== nFlag2
)
405 double nDiff
= (double)nVal2
- (double)nVal1
;
406 if ( !::rtl::math::approxEqual( nDiff
, rInc
, 13 ) )
415 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
416 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
425 // call DecompValueString to set rMinDigits
427 lcl_DecompValueString( aStr
, nDummy
, &rMinDigits
);
432 void ScTable::FillFormula(
433 ScFormulaCell
* pSrcCell
, SCCOL nDestCol
, SCROW nDestRow
, bool bLast
)
436 pDocument
->SetNoListening( true ); // still the wrong reference
437 ScAddress
aAddr( nDestCol
, nDestRow
, nTab
);
438 ScFormulaCell
* pDestCell
= new ScFormulaCell( *pSrcCell
, *pDocument
, aAddr
);
439 aCol
[nDestCol
].SetFormulaCell(nDestRow
, pDestCell
);
441 if ( bLast
&& pDestCell
->GetMatrixFlag() )
444 if ( pDestCell
->GetMatrixOrigin( aOrg
) )
446 if ( nDestCol
>= aOrg
.Col() && nDestRow
>= aOrg
.Row() )
448 ScFormulaCell
* pOrgCell
= pDocument
->GetFormulaCell(aOrg
);
449 if (pOrgCell
&& pOrgCell
->GetMatrixFlag() == MM_FORMULA
)
451 pOrgCell
->SetMatColsRows(
452 nDestCol
- aOrg
.Col() + 1,
453 nDestRow
- aOrg
.Row() + 1 );
457 OSL_FAIL( "FillFormula: MatrixOrigin no forumla cell with MM_FORMULA" );
462 OSL_FAIL( "FillFormula: MatrixOrigin bottom right" );
467 OSL_FAIL( "FillFormula: no MatrixOrigin" );
470 pDocument
->SetNoListening( false );
471 pDestCell
->StartListeningTo( pDocument
);
475 void ScTable::FillAuto( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
476 sal_uLong nFillCount
, FillDir eFillDir
, ScProgress
* pProgress
)
478 if ( (nFillCount
== 0) || !ValidColRow(nCol1
, nRow1
) || !ValidColRow(nCol2
, nRow2
) )
483 bool bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
484 bool bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
488 SCCOLROW
& rInner
= bVertical
? nRow
: nCol
; // loop variables
489 SCCOLROW
& rOuter
= bVertical
? nCol
: nRow
;
507 nIEnd
= nRow2
+ nFillCount
;
508 aFillRange
= ScRange(nCol1
, nRow2
+1, 0, nCol2
, nRow2
+ nFillCount
, 0);
515 nIEnd
= nRow1
- nFillCount
;
516 aFillRange
= ScRange(nCol1
, nRow1
-1, 0, nCol2
, nRow2
- nFillCount
, 0);
528 nIEnd
= nCol2
+ nFillCount
;
529 aFillRange
= ScRange(nCol2
+ 1, nRow1
, 0, nCol2
+ nFillCount
, nRow2
, 0);
536 nIEnd
= nCol1
- nFillCount
;
537 aFillRange
= ScRange(nCol1
- 1, nRow1
, 0, nCol1
- nFillCount
, nRow2
, 0);
540 sal_uLong nIMin
= nIStart
;
541 sal_uLong nIMax
= nIEnd
;
542 PutInOrder(nIMin
,nIMax
);
543 bool bHasFiltered
= IsDataFiltered(aFillRange
);
548 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), IDF_AUTOFILL
);
550 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, IDF_AUTOFILL
);
553 sal_uLong nProgress
= 0;
555 nProgress
= pProgress
->GetState();
559 sal_uLong nActFormCnt
= 0;
560 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
562 sal_uLong nMaxFormCnt
= 0; // for formulas
564 // transfer attributes
566 const ScPatternAttr
* pSrcPattern
= NULL
;
567 const ScStyleSheet
* pStyleSheet
= NULL
;
568 SCCOLROW nAtSrc
= nISrcStart
;
569 ScPatternAttr
* pNewPattern
= NULL
;
570 bool bGetPattern
= true;
572 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
574 if (!ColHidden(nCol
) && !RowHidden(nRow
))
579 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
580 pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nAtSrc
));
581 else // rInner&:=nCol, rOuter&:=nRow
582 pSrcPattern
= aCol
[nAtSrc
].GetPattern(static_cast<SCROW
>(nRow
));
584 pStyleSheet
= pSrcPattern
->GetStyleSheet();
585 // do not transfer ATTR_MERGE / ATTR_MERGE_FLAG
586 const SfxItemSet
& rSet
= pSrcPattern
->GetItemSet();
587 if ( rSet
.GetItemState(ATTR_MERGE
, false) == SfxItemState::SET
588 || rSet
.GetItemState(ATTR_MERGE_FLAG
, false) == SfxItemState::SET
)
590 pNewPattern
= new ScPatternAttr( *pSrcPattern
);
591 SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
592 rNewSet
.ClearItem(ATTR_MERGE
);
593 rNewSet
.ClearItem(ATTR_MERGE_FLAG
);
599 const ScCondFormatItem
& rCondFormatItem
= static_cast<const ScCondFormatItem
&>(pSrcPattern
->GetItem(ATTR_CONDITIONAL
));
600 const std::vector
<sal_uInt32
>& rCondFormatIndex
= rCondFormatItem
.GetCondFormatData();
602 if ( bVertical
&& nISrcStart
== nISrcEnd
&& !bHasFiltered
)
604 // set all attributes at once (en bloc)
605 if (pNewPattern
|| pSrcPattern
!= pDocument
->GetDefPattern())
607 // Default is already present (DeleteArea)
608 SCROW nY1
= static_cast<SCROW
>(std::min( nIStart
, nIEnd
));
609 SCROW nY2
= static_cast<SCROW
>(std::max( nIStart
, nIEnd
));
611 aCol
[nCol
].ApplyStyleArea( nY1
, nY2
, *pStyleSheet
);
613 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pNewPattern
);
615 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pSrcPattern
);
617 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
618 itr
!= itrEnd
; ++itr
)
620 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
621 ScRangeList aRange
= pCondFormat
->GetRange();
622 aRange
.Join(ScRange(nCol
, nY1
, nTab
, nCol
, nY2
, nTab
));
623 pCondFormat
->SetRange(aRange
);
631 DeleteArea(static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
),
632 static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), IDF_AUTOFILL
);
634 if ( pSrcPattern
!= aCol
[nCol
].GetPattern( static_cast<SCROW
>(nRow
) ) )
636 // Transfer template too
637 //TODO: Merge ApplyPattern to AttrArray ??
639 aCol
[nCol
].ApplyStyle( static_cast<SCROW
>(nRow
), *pStyleSheet
);
641 // Use ApplyPattern instead of SetPattern to keep old MergeFlags
643 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pNewPattern
);
645 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pSrcPattern
);
647 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
648 itr
!= itrEnd
; ++itr
)
650 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
651 ScRangeList aRange
= pCondFormat
->GetRange();
652 aRange
.Join(ScRange(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
));
653 pCondFormat
->SetRange(aRange
);
657 if (nAtSrc
==nISrcEnd
)
659 if ( nAtSrc
!= nISrcStart
)
660 { // More than one source cell
677 if (rInner
== nIEnd
) break;
678 if (bPositive
) ++rInner
; else --rInner
;
686 FillDateCmd eDateCmd
;
688 sal_uInt16 nMinDigits
;
689 ScUserListData
* pListData
= NULL
;
690 sal_uInt16 nListIndex
;
692 FillAnalyse(static_cast<SCCOL
>(nCol
),nRow1
,
693 static_cast<SCCOL
>(nCol
),nRow2
, eFillCmd
,eDateCmd
,
694 nInc
,nMinDigits
, pListData
,nListIndex
);
696 FillAnalyse(nCol1
,static_cast<SCROW
>(nRow
),
697 nCol2
,static_cast<SCROW
>(nRow
), eFillCmd
,eDateCmd
,
698 nInc
,nMinDigits
, pListData
,nListIndex
);
702 sal_uInt16 nListCount
= pListData
->GetSubCount();
705 // nListIndex of FillAnalyse points to the last entry -> adjust
706 sal_uLong nSub
= nISrcStart
- nISrcEnd
;
707 for (sal_uLong i
=0; i
<nSub
; i
++)
709 if (nListIndex
== 0) nListIndex
= nListCount
;
715 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
717 if(!ColHidden(nCol
) && !RowHidden(nRow
))
722 if (nListIndex
>= nListCount
) nListIndex
= 0;
726 if (nListIndex
== 0) nListIndex
= nListCount
;
729 aCol
[nCol
].SetRawString(static_cast<SCROW
>(nRow
), pListData
->GetSubStr(nListIndex
));
732 if (rInner
== nIEnd
) break;
733 if (bPositive
) ++rInner
; else --rInner
;
737 nProgress
+= nIMax
- nIMin
+ 1;
738 pProgress
->SetStateOnPercent( nProgress
);
741 else if (eFillCmd
== FILL_SIMPLE
) // fill with pattern/sample
744 nISrcStart
, nISrcEnd
, nIStart
, nIEnd
, rInner
, nCol
, nRow
,
745 nActFormCnt
, nMaxFormCnt
, bHasFiltered
, bVertical
, bPositive
, pProgress
, nProgress
);
751 double nEndVal
= (nInc
>=0.0) ? MAXDOUBLE
: -MAXDOUBLE
;
753 FillSeries( static_cast<SCCOL
>(nCol
), nRow1
,
754 static_cast<SCCOL
>(nCol
), nRow2
, nFillCount
, eFillDir
,
755 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, false,
758 FillSeries( nCol1
, static_cast<SCROW
>(nRow
), nCol2
,
759 static_cast<SCROW
>(nRow
), nFillCount
, eFillDir
,
760 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, false,
763 nProgress
= pProgress
->GetState();
766 nActFormCnt
+= nMaxFormCnt
;
770 OUString
ScTable::GetAutoFillPreview( const ScRange
& rSource
, SCCOL nEndX
, SCROW nEndY
)
774 SCCOL nCol1
= rSource
.aStart
.Col();
775 SCROW nRow1
= rSource
.aStart
.Row();
776 SCCOL nCol2
= rSource
.aEnd
.Col();
777 SCROW nRow2
= rSource
.aEnd
.Row();
780 sal_uLong nSrcCount
= 0;
781 FillDir eFillDir
= FILL_TO_BOTTOM
;
782 if ( nEndX
== nCol2
&& nEndY
== nRow2
) // empty
784 else if ( nEndX
== nCol2
) // to up / down
786 nEndX
= nCol2
= nCol1
; // use only first column
787 nSrcCount
= nRow2
- nRow1
+ 1;
788 nIndex
= ((long)nEndY
) - nRow1
; // can be negative
789 if ( nEndY
>= nRow1
)
790 eFillDir
= FILL_TO_BOTTOM
;
792 eFillDir
= FILL_TO_TOP
;
794 else if ( nEndY
== nRow2
) // to left / right
796 nEndY
= nRow2
= nRow1
; // use only first row
797 nSrcCount
= nCol2
- nCol1
+ 1;
798 nIndex
= ((long)nEndX
) - nCol1
; // can be negative
799 if ( nEndX
>= nCol1
)
800 eFillDir
= FILL_TO_RIGHT
;
802 eFillDir
= FILL_TO_LEFT
;
804 else // direction not clear
810 FillDateCmd eDateCmd
;
812 sal_uInt16 nMinDigits
;
813 ScUserListData
* pListData
= NULL
;
814 sal_uInt16 nListIndex
;
816 FillAnalyse(nCol1
,nRow1
, nCol2
,nRow2
, eFillCmd
,eDateCmd
, nInc
,nMinDigits
, pListData
,nListIndex
);
818 if ( pListData
) // user defined list
820 sal_uInt16 nListCount
= pListData
->GetSubCount();
823 sal_uLong nSub
= nSrcCount
- 1; // nListIndex is from last source entry
824 while ( nIndex
< sal::static_int_cast
<long>(nSub
) )
825 nIndex
+= nListCount
;
826 sal_uLong nPos
= ( nListIndex
+ nIndex
- nSub
) % nListCount
;
827 aValue
= pListData
->GetSubStr(sal::static_int_cast
<sal_uInt16
>(nPos
));
830 else if ( eFillCmd
== FILL_SIMPLE
) // fill with pattern/sample
832 if ((eFillDir
== FILL_TO_BOTTOM
)||(eFillDir
== FILL_TO_TOP
))
847 long nNonFiltered
= CountNonFilteredRows(nBegin
, nEnd
);
848 long nFiltered
= nEnd
+ 1 - nBegin
- nNonFiltered
;
851 nIndex
= nIndex
- nFiltered
;
853 nIndex
= nIndex
+ nFiltered
;
856 long nPosIndex
= nIndex
;
857 while ( nPosIndex
< 0 )
858 nPosIndex
+= nSrcCount
;
859 sal_uLong nPos
= nPosIndex
% nSrcCount
;
862 if ( eFillDir
== FILL_TO_TOP
|| eFillDir
== FILL_TO_BOTTOM
)
863 nSrcY
= sal::static_int_cast
<SCROW
>( nSrcY
+ static_cast<SCROW
>(nPos
) );
865 nSrcX
= sal::static_int_cast
<SCCOL
>( nSrcX
+ static_cast<SCCOL
>(nPos
) );
867 ScRefCellValue aCell
= GetCellValue(nSrcX
, nSrcY
);
868 if (!aCell
.isEmpty())
872 nDelta
= nIndex
/ nSrcCount
;
874 nDelta
= ( nIndex
- nSrcCount
+ 1 ) / nSrcCount
; // -1 -> -1
876 CellType eType
= aCell
.meType
;
879 case CELLTYPE_STRING
:
882 aValue
= aCell
.getString(pDocument
);
884 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
887 sal_uInt16 nCellDigits
= 0; // look at each source cell individually
888 short nFlag
= lcl_DecompValueString( aValue
, nVal
, &nCellDigits
);
891 if (aValue
.equals( ScGlobal::GetOrdinalSuffix( nVal
)))
892 aValue
= ScGlobal::GetOrdinalSuffix( nVal
+ nDelta
);
894 aValue
= lcl_ValueString( nVal
+ nDelta
, nCellDigits
) + aValue
;
896 else if ( nFlag
> 0 )
897 aValue
+= lcl_ValueString( nVal
+ nDelta
, nCellDigits
);
903 // overflow is possible...
904 double nVal
= aCell
.mfValue
;
905 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
906 nVal
+= (double) nDelta
;
909 sal_uLong nNumFmt
= GetNumberFormat( nSrcX
, nSrcY
);
910 pDocument
->GetFormatTable()->GetOutputString( nVal
, nNumFmt
, aValue
, &pColor
);
916 // added to avoid warnings
921 else if ( eFillCmd
== FILL_LINEAR
|| eFillCmd
== FILL_DATE
) // values
926 short nHeadNoneTail
= 0;
927 ScRefCellValue aCell
= GetCellValue(nCol1
, nRow1
);
928 if (!aCell
.isEmpty())
930 CellType eType
= aCell
.meType
;
933 case CELLTYPE_STRING
:
936 aValue
= aCell
.getString(pDocument
);
937 nHeadNoneTail
= lcl_DecompValueString( aValue
, nVal
);
939 nStart
= (double)nVal
;
945 nStart
= aCell
.mfValue
;
947 case CELLTYPE_FORMULA
:
948 nStart
= aCell
.mpFormula
->GetValue();
956 if ( eFillCmd
== FILL_LINEAR
)
959 bValueOk
= ( SubTotal::SafeMult( nAdd
, (double) nIndex
) &&
960 SubTotal::SafePlus( nStart
, nAdd
) );
965 sal_uInt16 nDayOfMonth
= 0;
971 for (long i
=0; i
<nIndex
; i
++)
972 IncDate( nStart
, nDayOfMonth
, nInc
, eDateCmd
);
979 if ( nHeadNoneTail
< 0 )
981 if (aValue
.equals( ScGlobal::GetOrdinalSuffix( nVal
)))
982 aValue
= ScGlobal::GetOrdinalSuffix( (sal_Int32
)nStart
);
984 aValue
= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
) + aValue
;
987 aValue
+= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
);
991 //TODO: get number format according to Index?
993 sal_uLong nNumFmt
= GetNumberFormat( nCol1
, nRow1
);
994 pDocument
->GetFormatTable()->GetOutputString( nStart
, nNumFmt
, aValue
, &pColor
);
1000 OSL_FAIL("GetAutoFillPreview: invalid mode");
1007 void ScTable::IncDate(double& rVal
, sal_uInt16
& nDayOfMonth
, double nStep
, FillDateCmd eCmd
)
1009 if (eCmd
== FILL_DAY
)
1015 // class Date limits
1016 const sal_uInt16 nMinYear
= 1583;
1017 const sal_uInt16 nMaxYear
= 9956;
1019 long nInc
= (long) nStep
; // upper/lower limits ?
1020 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
1021 Date aDate
= aNullDate
;
1022 aDate
+= (long)rVal
;
1028 DayOfWeek eWeekDay
= aDate
.GetDayOfWeek();
1031 if (eWeekDay
== SATURDAY
)
1033 else if (eWeekDay
== SUNDAY
)
1038 if (eWeekDay
== SATURDAY
)
1040 else if (eWeekDay
== SUNDAY
)
1047 if ( nDayOfMonth
== 0 )
1048 nDayOfMonth
= aDate
.GetDay(); // init
1049 long nMonth
= aDate
.GetMonth();
1050 long nYear
= aDate
.GetYear();
1058 long nYAdd
= (nMonth
-1) / 12;
1059 nMonth
-= nYAdd
* 12;
1067 long nYAdd
= 1 - nMonth
/ 12; // positive
1068 nMonth
+= nYAdd
* 12;
1073 if ( nYear
< nMinYear
)
1074 aDate
= Date( 1,1, nMinYear
);
1075 else if ( nYear
> nMaxYear
)
1076 aDate
= Date( 31,12, nMaxYear
);
1079 aDate
.SetMonth((sal_uInt16
) nMonth
);
1080 aDate
.SetYear((sal_uInt16
) nYear
);
1081 aDate
.SetDay( std::min( Date::GetDaysInMonth( nMonth
, nYear
), nDayOfMonth
) );
1087 long nYear
= aDate
.GetYear();
1089 if ( nYear
< nMinYear
)
1090 aDate
= Date( 1,1, nMinYear
);
1091 else if ( nYear
> nMaxYear
)
1092 aDate
= Date( 31,12, nMaxYear
);
1094 aDate
.SetYear((sal_uInt16
) nYear
);
1099 // added to avoid warnings
1103 rVal
= aDate
- aNullDate
;
1108 bool HiddenRowColumn(ScTable
* pTable
, SCCOLROW nRowColumn
, bool bVertical
, SCCOLROW
& rLastPos
)
1110 bool bHidden
= false;
1114 bHidden
= pTable
->RowHidden(nRowColumn
, NULL
, &nLast
);
1120 bHidden
= pTable
->ColHidden(static_cast<SCCOL
>(nRowColumn
), NULL
, &nLast
);
1128 void ScTable::FillFormulaVertical(
1129 const ScFormulaCell
& rSrcCell
,
1130 SCCOLROW
& rInner
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
,
1131 ScProgress
* pProgress
, sal_uLong
& rProgress
)
1133 // rInner is the row position when filling vertically. Also, when filling
1134 // across hidden regions, it may create multiple dis-jointed spans of
1137 bool bHidden
= false;
1138 SCCOLROW nHiddenLast
= -1;
1140 SCCOLROW nRowStart
= -1, nRowEnd
= -1;
1141 std::vector
<sc::RowSpan
> aSpans
;
1142 PutInOrder(nRow1
, nRow2
);
1143 for (rInner
= nRow1
; rInner
<= nRow2
; ++rInner
)
1145 if (rInner
> nHiddenLast
)
1146 bHidden
= HiddenRowColumn(this, rInner
, true, nHiddenLast
);
1152 nRowEnd
= rInner
- 1;
1153 aSpans
.push_back(sc::RowSpan(nRowStart
, nRowEnd
));
1156 rInner
= nHiddenLast
;
1166 nRowEnd
= rInner
- 1;
1167 aSpans
.push_back(sc::RowSpan(nRowStart
, nRowEnd
));
1173 aCol
[nCol
].DeleteRanges(aSpans
, IDF_VALUE
| IDF_DATETIME
| IDF_STRING
| IDF_FORMULA
| IDF_OUTLINE
, false);
1174 aCol
[nCol
].CloneFormulaCell(rSrcCell
, sc::CellTextAttr(), aSpans
, NULL
);
1176 boost::shared_ptr
<sc::ColumnBlockPositionSet
> pSet(new sc::ColumnBlockPositionSet(*pDocument
));
1177 sc::StartListeningContext
aStartCxt(*pDocument
, pSet
);
1178 sc::EndListeningContext
aEndCxt(*pDocument
, pSet
);
1180 SCROW nStartRow
= aSpans
.front().mnRow1
;
1181 SCROW nEndRow
= aSpans
.back().mnRow2
;
1182 aCol
[nCol
].EndListeningFormulaCells(aEndCxt
, nStartRow
, nEndRow
, &nStartRow
, &nEndRow
);
1183 aCol
[nCol
].StartListeningFormulaCells(aStartCxt
, aEndCxt
, nStartRow
, nEndRow
);
1185 std::vector
<sc::RowSpan
>::const_iterator it
= aSpans
.begin(), itEnd
= aSpans
.end();
1186 for (; it
!= itEnd
; ++it
)
1187 aCol
[nCol
].SetDirty(it
->mnRow1
, it
->mnRow2
, ScColumn::BROADCAST_NONE
);
1189 rProgress
+= nRow2
- nRow1
+ 1;
1191 pProgress
->SetStateOnPercent(rProgress
);
1194 void ScTable::FillSeriesSimple(
1195 ScCellValue
& rSrcCell
, SCCOLROW
& rInner
, SCCOLROW nIMin
, SCCOLROW nIMax
,
1196 SCCOLROW
& rCol
, SCCOLROW
& rRow
, bool bVertical
, ScProgress
* pProgress
, sal_uLong
& rProgress
)
1198 bool bHidden
= false;
1199 SCCOLROW nHiddenLast
= -1;
1203 switch (rSrcCell
.meType
)
1205 case CELLTYPE_FORMULA
:
1207 FillFormulaVertical(
1208 *rSrcCell
.mpFormula
, rInner
, rCol
, nIMin
, nIMax
, pProgress
, rProgress
);
1213 for (rInner
= nIMin
; rInner
<= nIMax
; ++rInner
)
1215 if (rInner
> nHiddenLast
)
1216 bHidden
= HiddenRowColumn(this, rInner
, bVertical
, nHiddenLast
);
1220 rInner
= nHiddenLast
;
1224 ScAddress
aDestPos(rCol
, rRow
, nTab
);
1225 rSrcCell
.commit(aCol
[rCol
], aDestPos
.Row());
1227 rProgress
+= nIMax
- nIMin
+ 1;
1229 pProgress
->SetStateOnPercent(rProgress
);
1235 switch (rSrcCell
.meType
)
1237 case CELLTYPE_FORMULA
:
1239 for (rInner
= nIMin
; rInner
<= nIMax
; ++rInner
)
1241 if (rInner
> nHiddenLast
)
1242 bHidden
= HiddenRowColumn(this, rInner
, bVertical
, nHiddenLast
);
1247 FillFormula(rSrcCell
.mpFormula
, rCol
, rRow
, (rInner
== nIMax
));
1249 pProgress
->SetStateOnPercent(++rProgress
);
1255 for (rInner
= nIMin
; rInner
<= nIMax
; ++rInner
)
1257 if (rInner
> nHiddenLast
)
1258 bHidden
= HiddenRowColumn(this, rInner
, bVertical
, nHiddenLast
);
1263 ScAddress
aDestPos(rCol
, rRow
, nTab
);
1264 rSrcCell
.commit(aCol
[rCol
], aDestPos
.Row());
1266 rProgress
+= nIMax
- nIMin
+ 1;
1268 pProgress
->SetStateOnPercent(rProgress
);
1274 void ScTable::FillAutoSimple(
1275 SCCOLROW nISrcStart
, SCCOLROW nISrcEnd
, SCCOLROW nIStart
, SCCOLROW nIEnd
,
1276 SCCOLROW
& rInner
, SCCOLROW
& rCol
, SCCOLROW
& rRow
, sal_uLong nActFormCnt
,
1277 sal_uLong nMaxFormCnt
, bool bHasFiltered
, bool bVertical
, bool bPositive
,
1278 ScProgress
* pProgress
, sal_uLong
& rProgress
)
1280 SCCOLROW nSource
= nISrcStart
;
1282 if ( (nScFillModeMouseModifier
& KEY_MOD1
) )
1284 else if ( bPositive
)
1288 sal_uLong nFormulaCounter
= nActFormCnt
;
1289 bool bGetCell
= true;
1290 sal_uInt16 nCellDigits
= 0;
1291 short nHeadNoneTail
= 0;
1292 sal_Int32 nStringValue
= 0;
1294 ScCellValue aSrcCell
;
1295 bool bIsOrdinalSuffix
= false;
1297 bool bColHidden
= false, bRowHidden
= false;
1298 SCCOL nColHiddenLast
= -1;
1299 SCROW nRowHiddenLast
= -1;
1302 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1304 if (rCol
> nColHiddenLast
)
1305 bColHidden
= ColHidden(rCol
, NULL
, &nColHiddenLast
);
1306 if (rRow
> nRowHiddenLast
)
1307 bRowHidden
= RowHidden(rRow
, NULL
, &nRowHiddenLast
);
1309 if (!bColHidden
&& !bRowHidden
)
1313 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
1315 aSrcCell
= aCol
[rCol
].GetCellValue(nSource
);
1316 if (nISrcStart
== nISrcEnd
&& aSrcCell
.meType
== CELLTYPE_FORMULA
)
1318 FillFormulaVertical(*aSrcCell
.mpFormula
, rInner
, rCol
, nIStart
, nIEnd
, pProgress
, rProgress
);
1322 else // rInner&:=nCol, rOuter&:=nRow
1323 aSrcCell
= aCol
[nSource
].GetCellValue(rRow
);
1326 if (!aSrcCell
.isEmpty())
1328 switch (aSrcCell
.meType
)
1330 case CELLTYPE_STRING
:
1332 if (aSrcCell
.meType
== CELLTYPE_STRING
)
1333 aValue
= aSrcCell
.mpString
->getString();
1335 aValue
= ScEditUtil::GetString(*aSrcCell
.mpEditText
, pDocument
);
1336 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) && !bHasFiltered
)
1338 nCellDigits
= 0; // look at each source cell individually
1339 nHeadNoneTail
= lcl_DecompValueString(
1340 aValue
, nStringValue
, &nCellDigits
);
1342 bIsOrdinalSuffix
= aValue
.equals(
1343 ScGlobal::GetOrdinalSuffix( nStringValue
));
1348 // added to avoid warnings
1354 switch (aSrcCell
.meType
)
1356 case CELLTYPE_VALUE
:
1357 aCol
[rCol
].SetValue(rRow
, aSrcCell
.mfValue
+ nDelta
);
1359 case CELLTYPE_STRING
:
1361 if ( nHeadNoneTail
)
1363 // #i48009# with the "nStringValue+(long)nDelta" expression within the
1364 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
1365 // so nNextValue is now calculated ahead.
1366 sal_Int32 nNextValue
= nStringValue
+(sal_Int32
)nDelta
;
1369 if ( nHeadNoneTail
< 0 )
1373 nNextValue
, nCellDigits
, aValue
,
1374 aSrcCell
.meType
, bIsOrdinalSuffix
);
1378 aStr
= aValue
+ lcl_ValueString( nNextValue
, nCellDigits
);
1379 aCol
[rCol
].SetRawString(rRow
, aStr
);
1383 aSrcCell
.commit(aCol
[rCol
], rRow
);
1386 case CELLTYPE_FORMULA
:
1388 aSrcCell
.mpFormula
, rCol
, rRow
, (rInner
== nIEnd
));
1389 if (nFormulaCounter
- nActFormCnt
> nMaxFormCnt
)
1390 nMaxFormCnt
= nFormulaCounter
- nActFormCnt
;
1394 // added to avoid warnings
1398 if (nSource
== nISrcEnd
)
1400 if ( nSource
!= nISrcStart
)
1401 { // More than one source cell
1402 nSource
= nISrcStart
;
1405 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1412 nFormulaCounter
= nActFormCnt
;
1426 if (rInner
== nIEnd
)
1433 // Progress in inner loop only for expensive cells,
1434 // and even then not individually for each one
1437 if ( pProgress
&& (aSrcCell
.meType
== CELLTYPE_FORMULA
|| aSrcCell
.meType
== CELLTYPE_EDIT
) )
1438 pProgress
->SetStateOnPercent( rProgress
);
1442 pProgress
->SetStateOnPercent( rProgress
);
1445 void ScTable::FillSeries( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1446 sal_uLong nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1447 double nStepValue
, double nMaxValue
, sal_uInt16 nArgMinDigits
,
1448 bool bAttribs
, ScProgress
* pProgress
)
1450 // The term 'inner' here refers to the loop in the filling direction i.e.
1451 // when filling vertically, the inner position is the row position whereas
1452 // when filling horizontally the column position becomes the inner
1453 // position. The term 'outer' refers to the column position when filling
1454 // vertically, or the row position when filling horizontally. The fill is
1455 // performed once in each 'outer' position e.g. when filling vertically,
1456 // we perform the fill once in each column.
1460 bool bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
1461 bool bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
1465 SCCOLROW
& rInner
= bVertical
? nRow
: nCol
; // loop variables
1466 SCCOLROW
& rOuter
= bVertical
? nCol
: nRow
;
1476 nFillCount
+= (nRow2
- nRow1
);
1477 if (nFillCount
== 0)
1484 nISource
= nRow1
; // top row of the source range.
1485 nIStart
= nRow1
+ 1; // first row where we start filling.
1486 nIEnd
= nRow1
+ nFillCount
;
1487 aFillRange
= ScRange(nCol1
, nRow1
+ 1, nTab
, nCol2
, nRow1
+ nFillCount
, nTab
);
1493 nIStart
= nRow2
- 1;
1494 nIEnd
= nRow2
- nFillCount
;
1495 aFillRange
= ScRange(nCol1
, nRow2
-1, nTab
, nCol2
, nRow2
- nFillCount
, nTab
);
1500 nFillCount
+= (nCol2
- nCol1
);
1501 if (nFillCount
== 0)
1509 nIStart
= nCol1
+ 1;
1510 nIEnd
= nCol1
+ nFillCount
;
1511 aFillRange
= ScRange(nCol1
+ 1, nRow1
, nTab
, nCol1
+ nFillCount
, nRow2
, nTab
);
1517 nIStart
= nCol2
- 1;
1518 nIEnd
= nCol2
- nFillCount
;
1519 aFillRange
= ScRange(nCol2
- 1, nRow1
, nTab
, nCol2
- nFillCount
, nRow2
, nTab
);
1523 SCCOLROW nIMin
= nIStart
;
1524 SCCOLROW nIMax
= nIEnd
;
1525 PutInOrder(nIMin
,nIMax
);
1526 InsertDeleteFlags nDel
= bAttribs
? IDF_AUTOFILL
: (IDF_AUTOFILL
& IDF_CONTENTS
);
1528 bool bIsFiltered
= IsDataFiltered(aFillRange
);
1532 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), nDel
);
1534 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, nDel
);
1537 sal_uLong nProgress
= 0;
1539 nProgress
= pProgress
->GetState();
1541 // Perform the fill once per each 'outer' position i.e. one per column
1542 // when filling vertically.
1544 sal_uLong nActFormCnt
= 0;
1545 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
1549 // Source cell value. We need to clone the value since it may be inserted repeatedly.
1550 ScCellValue aSrcCell
= aCol
[nCol
].GetCellValue(static_cast<SCROW
>(nRow
));
1554 const ScPatternAttr
* pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nRow
));
1556 const ScCondFormatItem
& rCondFormatItem
= static_cast<const ScCondFormatItem
&>(pSrcPattern
->GetItem(ATTR_CONDITIONAL
));
1557 const std::vector
<sal_uInt32
>& rCondFormatIndex
= rCondFormatItem
.GetCondFormatData();
1561 // if not filtered use the faster method
1562 // hidden cols/rows should be skipped
1565 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nIMin
),
1566 static_cast<SCROW
>(nIMax
), *pSrcPattern
, true );
1568 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1569 itr
!= itrEnd
; ++itr
)
1571 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1572 ScRangeList aRange
= pCondFormat
->GetRange();
1573 aRange
.Join(ScRange(nCol
, nIMin
, nTab
, nCol
, nIMax
, nTab
));
1574 pCondFormat
->SetRange(aRange
);
1579 for(SCROW nAtRow
= static_cast<SCROW
>(nIMin
); nAtRow
<= static_cast<SCROW
>(nIMax
); ++nAtRow
)
1581 if(!RowHidden(nAtRow
))
1583 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nAtRow
),
1584 static_cast<SCROW
>(nAtRow
), *pSrcPattern
, true);
1585 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1586 itr
!= itrEnd
; ++itr
)
1588 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1589 ScRangeList aRange
= pCondFormat
->GetRange();
1590 aRange
.Join(ScRange(nCol
, nAtRow
, nTab
, nCol
, nAtRow
, nTab
));
1591 pCondFormat
->SetRange(aRange
);
1599 for (SCCOL nAtCol
= static_cast<SCCOL
>(nIMin
); nAtCol
<= sal::static_int_cast
<SCCOL
>(nIMax
); nAtCol
++)
1600 if(!ColHidden(nAtCol
))
1602 aCol
[nAtCol
].SetPattern(static_cast<SCROW
>(nRow
), *pSrcPattern
, true);
1603 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1604 itr
!= itrEnd
; ++itr
)
1606 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1607 ScRangeList aRange
= pCondFormat
->GetRange();
1608 aRange
.Join(ScRange(nAtCol
, static_cast<SCROW
>(nRow
), nTab
, nAtCol
, static_cast<SCROW
>(nRow
), nTab
));
1609 pCondFormat
->SetRange(aRange
);
1614 if (!aSrcCell
.isEmpty())
1616 CellType eCellType
= aSrcCell
.meType
;
1618 if (eFillCmd
== FILL_SIMPLE
) // copy
1620 FillSeriesSimple(aSrcCell
, rInner
, nIMin
, nIMax
, nCol
, nRow
, bVertical
, pProgress
, nProgress
);
1622 else if (eCellType
== CELLTYPE_VALUE
|| eCellType
== CELLTYPE_FORMULA
)
1625 if (eCellType
== CELLTYPE_VALUE
)
1626 nStartVal
= aSrcCell
.mfValue
;
1628 nStartVal
= aSrcCell
.mpFormula
->GetValue();
1629 double nVal
= nStartVal
;
1632 bool bError
= false;
1633 bool bOverflow
= false;
1635 sal_uInt16 nDayOfMonth
= 0;
1637 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1639 if(!ColHidden(nCol
) && !RowHidden(nRow
))
1641 if (!bError
&& !bOverflow
)
1647 // use multiplication instead of repeated addition
1648 // to avoid accumulating rounding errors
1650 double nAdd
= nStepValue
;
1651 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1652 !SubTotal::SafePlus( nVal
, nAdd
) )
1657 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1661 if (fabs(nVal
) > _D_MAX_LONG_
)
1664 IncDate(nVal
, nDayOfMonth
, nStepValue
, eFillDateCmd
);
1668 // added to avoid warnings
1672 if (nStepValue
>= 0)
1674 if (nVal
> nMaxValue
) // target value reached ?
1682 if (nVal
< nMaxValue
)
1691 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1693 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errIllegalFPOperation
);
1695 aCol
[nCol
].SetValue(static_cast<SCROW
>(nRow
), nVal
);
1698 if (rInner
== nIEnd
)
1709 nProgress
+= nIMax
- nIMin
+ 1;
1711 pProgress
->SetStateOnPercent( nProgress
);
1713 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
1715 if ( nStepValue
>= 0 )
1717 if ( nMaxValue
>= (double)LONG_MAX
)
1718 nMaxValue
= (double)LONG_MAX
- 1;
1722 if ( nMaxValue
<= (double)LONG_MIN
)
1723 nMaxValue
= (double)LONG_MIN
+ 1;
1726 if (eCellType
== CELLTYPE_STRING
)
1727 aValue
= aSrcCell
.mpString
->getString();
1729 aValue
= ScEditUtil::GetString(*aSrcCell
.mpEditText
, pDocument
);
1730 sal_Int32 nStringValue
;
1731 sal_uInt16 nMinDigits
= nArgMinDigits
;
1732 short nHeadNoneTail
= lcl_DecompValueString( aValue
, nStringValue
, &nMinDigits
);
1733 if ( nHeadNoneTail
)
1735 double nStartVal
= (double)nStringValue
;
1736 double nVal
= nStartVal
;
1738 bool bError
= false;
1739 bool bOverflow
= false;
1741 bool bIsOrdinalSuffix
= aValue
.equals( ScGlobal::GetOrdinalSuffix(
1742 (sal_Int32
)nStartVal
));
1745 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1747 if(!ColHidden(nCol
) && !RowHidden(nRow
))
1749 if (!bError
&& !bOverflow
)
1755 // use multiplication instead of repeated addition
1756 // to avoid accumulating rounding errors
1758 double nAdd
= nStepValue
;
1759 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1760 !SubTotal::SafePlus( nVal
, nAdd
) )
1765 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1770 // added to avoid warnings
1774 if (nStepValue
>= 0)
1776 if (nVal
> nMaxValue
) // target value reached ?
1784 if (nVal
< nMaxValue
)
1793 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1795 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errIllegalFPOperation
);
1798 nStringValue
= (sal_Int32
)nVal
;
1800 if ( nHeadNoneTail
< 0 )
1803 aCol
[nCol
], static_cast<SCROW
>(nRow
),
1804 nStringValue
, nMinDigits
, aValue
,
1805 eCellType
, bIsOrdinalSuffix
);
1810 aStr
+= lcl_ValueString( nStringValue
, nMinDigits
);
1811 aCol
[nCol
].SetRawString(static_cast<SCROW
>(nRow
), aStr
);
1816 if (rInner
== nIEnd
) break;
1817 if (bPositive
) ++rInner
; else --rInner
;
1822 nProgress
+= nIMax
- nIMin
+ 1;
1823 pProgress
->SetStateOnPercent( nProgress
);
1829 nProgress
+= nIMax
- nIMin
+ 1;
1830 pProgress
->SetStateOnPercent( nProgress
);
1836 void ScTable::Fill( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1837 sal_uLong nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1838 double nStepValue
, double nMaxValue
, ScProgress
* pProgress
)
1840 if (eFillCmd
== FILL_AUTO
)
1841 FillAuto(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
, pProgress
);
1843 FillSeries(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
,
1844 eFillCmd
, eFillDateCmd
, nStepValue
, nMaxValue
, 0, true, pProgress
);
1847 void ScTable::AutoFormatArea(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1848 const ScPatternAttr
& rAttr
, sal_uInt16 nFormatNo
)
1850 ScAutoFormat
& rFormat
= *ScGlobal::GetOrCreateAutoFormat();
1851 ScAutoFormatData
* pData
= rFormat
.findByIndex(nFormatNo
);
1854 ApplyPatternArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
);
1858 void ScTable::AutoFormat( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1859 sal_uInt16 nFormatNo
)
1861 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1863 ScAutoFormat
& rFormat
= *ScGlobal::GetOrCreateAutoFormat();
1864 ScAutoFormatData
* pData
= rFormat
.findByIndex(nFormatNo
);
1867 ScPatternAttr
* pPatternAttrs
[16];
1868 for (sal_uInt8 i
= 0; i
< 16; ++i
)
1870 pPatternAttrs
[i
] = new ScPatternAttr(pDocument
->GetPool());
1871 pData
->FillToItemSet(i
, pPatternAttrs
[i
]->GetItemSet(), *pDocument
);
1874 SCCOL nCol
= nStartCol
;
1875 SCROW nRow
= nStartRow
;
1876 sal_uInt16 nIndex
= 0;
1878 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1880 if (pData
->IsEqualData(4, 8))
1881 AutoFormatArea(nStartCol
, nStartRow
+ 1, nStartCol
, nEndRow
- 1, *pPatternAttrs
[4], nFormatNo
);
1885 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1887 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1894 // Left bottom corner
1897 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1902 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1904 if (pData
->IsEqualData(7, 11))
1905 AutoFormatArea(nEndCol
, nStartRow
+ 1, nEndCol
, nEndRow
- 1, *pPatternAttrs
[7], nFormatNo
);
1909 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1911 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1918 // Right bottom corner
1921 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1924 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1926 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1935 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1937 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1944 if ((pData
->IsEqualData(5, 6)) && (pData
->IsEqualData(9, 10)) && (pData
->IsEqualData(5, 9)))
1945 AutoFormatArea(nStartCol
+ 1, nStartRow
+ 1, nEndCol
-1, nEndRow
- 1, *pPatternAttrs
[5], nFormatNo
);
1948 if ((pData
->IsEqualData(5, 9)) && (pData
->IsEqualData(6, 10)))
1951 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1953 AutoFormatArea(nCol
, nStartRow
+ 1, nCol
, nEndRow
- 1, *pPatternAttrs
[nIndex
], nFormatNo
);
1963 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1965 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1967 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1968 if ((nIndex
== 5) || (nIndex
== 9))
1983 if ((nIndex
== 5) || (nIndex
== 9))
1988 } // if not equal Column
1989 } // if not all equal
1991 for (sal_uInt8 j
= 0; j
< 16; ++j
)
1992 delete pPatternAttrs
[j
];
1993 } // if AutoFormatData != NULL
1997 void ScTable::GetAutoFormatAttr(SCCOL nCol
, SCROW nRow
, sal_uInt16 nIndex
, ScAutoFormatData
& rData
)
1999 sal_uInt32 nFormatIndex
= GetNumberFormat( nCol
, nRow
);
2000 ScNumFormatAbbrev
aNumFormat( nFormatIndex
, *pDocument
->GetFormatTable() );
2001 rData
.GetFromItemSet( nIndex
, GetPattern( nCol
, nRow
)->GetItemSet(), aNumFormat
);
2008 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
2010 void ScTable::GetAutoFormatFrame(SCCOL nCol
, SCROW nRow
, sal_uInt16 nFlags
, sal_uInt16 nIndex
, ScAutoFormatData
& rData
)
2012 const SvxBoxItem
* pTheBox
= static_cast<const SvxBoxItem
*>(GetAttr(nCol
, nRow
, ATTR_BORDER
));
2013 const SvxBoxItem
* pLeftBox
= static_cast<const SvxBoxItem
*>(GetAttr(nCol
- 1, nRow
, ATTR_BORDER
));
2014 const SvxBoxItem
* pTopBox
= static_cast<const SvxBoxItem
*>(GetAttr(nCol
, nRow
- 1, ATTR_BORDER
));
2015 const SvxBoxItem
* pRightBox
= static_cast<const SvxBoxItem
*>(GetAttr(nCol
+ 1, nRow
, ATTR_BORDER
));
2016 const SvxBoxItem
* pBottomBox
= static_cast<const SvxBoxItem
*>(GetAttr(nCol
, nRow
+ 1, ATTR_BORDER
));
2018 SvxBoxItem
aBox( ATTR_BORDER
);
2019 if (nFlags
& LF_LEFT
)
2023 if (ScHasPriority(pTheBox
->GetLeft(), pLeftBox
->GetRight()))
2024 aBox
.SetLine(pTheBox
->GetLeft(), SvxBoxItemLine::LEFT
);
2026 aBox
.SetLine(pLeftBox
->GetRight(), SvxBoxItemLine::LEFT
);
2029 aBox
.SetLine(pTheBox
->GetLeft(), SvxBoxItemLine::LEFT
);
2031 if (nFlags
& LF_TOP
)
2035 if (ScHasPriority(pTheBox
->GetTop(), pTopBox
->GetBottom()))
2036 aBox
.SetLine(pTheBox
->GetTop(), SvxBoxItemLine::TOP
);
2038 aBox
.SetLine(pTopBox
->GetBottom(), SvxBoxItemLine::TOP
);
2041 aBox
.SetLine(pTheBox
->GetTop(), SvxBoxItemLine::TOP
);
2043 if (nFlags
& LF_RIGHT
)
2047 if (ScHasPriority(pTheBox
->GetRight(), pRightBox
->GetLeft()))
2048 aBox
.SetLine(pTheBox
->GetRight(), SvxBoxItemLine::RIGHT
);
2050 aBox
.SetLine(pRightBox
->GetLeft(), SvxBoxItemLine::RIGHT
);
2053 aBox
.SetLine(pTheBox
->GetRight(), SvxBoxItemLine::RIGHT
);
2055 if (nFlags
& LF_BOTTOM
)
2059 if (ScHasPriority(pTheBox
->GetBottom(), pBottomBox
->GetTop()))
2060 aBox
.SetLine(pTheBox
->GetBottom(), SvxBoxItemLine::BOTTOM
);
2062 aBox
.SetLine(pBottomBox
->GetTop(), SvxBoxItemLine::BOTTOM
);
2065 aBox
.SetLine(pTheBox
->GetBottom(), SvxBoxItemLine::BOTTOM
);
2067 rData
.PutItem( nIndex
, aBox
);
2070 void ScTable::GetAutoFormatData(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
, ScAutoFormatData
& rData
)
2072 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
2074 if ((nEndCol
- nStartCol
>= 3) && (nEndRow
- nStartRow
>= 3))
2077 GetAutoFormatAttr(nStartCol
, nStartRow
, 0, rData
);
2078 GetAutoFormatFrame(nStartCol
, nStartRow
, LF_ALL
, 0, rData
);
2080 GetAutoFormatAttr(nStartCol
, nStartRow
+ 1, 4, rData
);
2081 GetAutoFormatAttr(nStartCol
, nStartRow
+ 2, 8, rData
);
2082 GetAutoFormatFrame(nStartCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 4, rData
);
2083 if (nEndRow
- nStartRow
>= 4)
2084 GetAutoFormatFrame(nStartCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 8, rData
);
2086 rData
.CopyItem( 8, 4, ATTR_BORDER
);
2087 // Left bottom corner
2088 GetAutoFormatAttr(nStartCol
, nEndRow
, 12, rData
);
2089 GetAutoFormatFrame(nStartCol
, nEndRow
, LF_ALL
, 12, rData
);
2091 GetAutoFormatAttr(nEndCol
, nStartRow
, 3, rData
);
2092 GetAutoFormatFrame(nEndCol
, nStartRow
, LF_ALL
, 3, rData
);
2094 GetAutoFormatAttr(nEndCol
, nStartRow
+ 1, 7, rData
);
2095 GetAutoFormatAttr(nEndCol
, nStartRow
+ 2, 11, rData
);
2096 GetAutoFormatFrame(nEndCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 7, rData
);
2097 if (nEndRow
- nStartRow
>= 4)
2098 GetAutoFormatFrame(nEndCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 11, rData
);
2100 rData
.CopyItem( 11, 7, ATTR_BORDER
);
2101 // Right bottom corner
2102 GetAutoFormatAttr(nEndCol
, nEndRow
, 15, rData
);
2103 GetAutoFormatFrame(nEndCol
, nEndRow
, LF_ALL
, 15, rData
);
2105 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
, 1, rData
);
2106 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
, 2, rData
);
2107 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 1, rData
);
2108 if (nEndCol
- nStartCol
>= 4)
2109 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 2, rData
);
2111 rData
.CopyItem( 2, 1, ATTR_BORDER
);
2113 GetAutoFormatAttr(nStartCol
+ 1, nEndRow
, 13, rData
);
2114 GetAutoFormatAttr(nStartCol
+ 2, nEndRow
, 14, rData
);
2115 GetAutoFormatFrame(nStartCol
+ 1, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 13, rData
);
2116 if (nEndCol
- nStartCol
>= 4)
2117 GetAutoFormatFrame(nStartCol
+ 2, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 14, rData
);
2119 rData
.CopyItem( 14, 13, ATTR_BORDER
);
2121 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 1, 5, rData
);
2122 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 1, 6, rData
);
2123 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 2, 9, rData
);
2124 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 2, 10, rData
);
2125 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 5, rData
);
2126 if ((nEndCol
- nStartCol
>= 4) && (nEndRow
- nStartRow
>= 4))
2128 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 6, rData
);
2129 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 9, rData
);
2130 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 10, rData
);
2134 rData
.CopyItem( 6, 5, ATTR_BORDER
);
2135 rData
.CopyItem( 9, 5, ATTR_BORDER
);
2136 rData
.CopyItem( 10, 5, ATTR_BORDER
);
2142 void ScTable::SetError( SCCOL nCol
, SCROW nRow
, sal_uInt16 nError
)
2144 if (ValidColRow(nCol
, nRow
))
2145 aCol
[nCol
].SetError( nRow
, nError
);
2148 void ScTable::UpdateInsertTabAbs(SCTAB nTable
)
2150 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
2151 aCol
[i
].UpdateInsertTabAbs(nTable
);
2154 bool ScTable::GetNextSpellingCell(SCCOL
& rCol
, SCROW
& rRow
, bool bInSel
,
2155 const ScMarkData
& rMark
) const
2157 if (rRow
== MAXROW
+2) // end of table
2165 if (rRow
== MAXROW
+1)
2171 if (rCol
== MAXCOL
+1)
2180 bStop
= aCol
[rCol
].GetNextSpellingCell(rRow
, bInSel
, rMark
);
2183 else /*if (rRow == MAXROW+1) */
2196 bool ScTable::TestTabRefAbs(SCTAB nTable
) const
2198 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
2199 if (aCol
[i
].TestTabRefAbs(nTable
))
2204 void ScTable::CompileDBFormula( sc::CompileFormulaContext
& rCxt
)
2206 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
2207 aCol
[i
].CompileDBFormula(rCxt
);
2210 void ScTable::CompileColRowNameFormula( sc::CompileFormulaContext
& rCxt
)
2212 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
2213 aCol
[i
].CompileColRowNameFormula(rCxt
);
2216 SCSIZE
ScTable::GetPatternCount( SCCOL nCol
) const
2218 if( ValidCol( nCol
) )
2219 return aCol
[nCol
].GetPatternCount();
2224 SCSIZE
ScTable::GetPatternCount( SCCOL nCol
, SCROW nRow1
, SCROW nRow2
) const
2226 if( ValidCol( nCol
) && ValidRow( nRow1
) && ValidRow( nRow2
) )
2227 return aCol
[nCol
].GetPatternCount( nRow1
, nRow2
);
2232 bool ScTable::ReservePatternCount( SCCOL nCol
, SCSIZE nReserve
)
2234 if( ValidCol( nCol
) )
2235 return aCol
[nCol
].ReservePatternCount( nReserve
);
2240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */