Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / table4.cxx
blobb7112bbc661b92cdf882a99df7c2aef915ab4ba4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
45 #include "attrib.hxx"
46 #include "patattr.hxx"
47 #include "formulacell.hxx"
48 #include "table.hxx"
49 #include "globstr.hrc"
50 #include "global.hxx"
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"
64 #include <math.h>
65 #include <boost/scoped_ptr.hpp>
67 // STATIC DATA -----------------------------------------------------------
69 #define _D_MAX_LONG_ (double) 0x7fffffff
71 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
73 namespace {
75 short lcl_DecompValueString( OUString& rValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
77 if ( rValue.isEmpty() )
79 nVal = 0;
80 return 0;
82 const sal_Unicode* p = rValue.getStr();
83 sal_Int32 nNeg = 0;
84 sal_Int32 nNum = 0;
85 if ( p[nNum] == '-' )
86 nNum = nNeg = 1;
87 while ( p[nNum] && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
88 nNum++;
90 sal_Unicode cNext = p[nNum]; // 0 if at the end
91 sal_Unicode cLast = p[rValue.getLength()-1];
93 // #i5550# If there are numbers at the beginning and the end,
94 // prefer the one at the beginning only if it's followed by a space.
95 // Otherwise, use the number at the end, to enable things like IP addresses.
96 if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(OUString(cLast)) ) )
97 { // number at the beginning
98 nVal = rValue.copy( 0, nNum ).toInt32();
99 // any number with a leading zero sets the minimum number of digits
100 if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
101 *pMinDigits = nNum - nNeg;
102 rValue = rValue.copy(nNum);
103 return -1;
105 else
107 nNeg = 0;
108 sal_Int32 nEnd = nNum = rValue.getLength() - 1;
109 while ( nNum && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
110 nNum--;
111 if ( p[nNum] == '-' )
113 nNum--;
114 nNeg = 1;
116 if ( nNum < nEnd - nNeg )
117 { // number at the end
118 nVal = rValue.copy( nNum + 1 ).toInt32();
119 // any number with a leading zero sets the minimum number of digits
120 if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
121 *pMinDigits = nEnd - nNum - nNeg;
122 rValue = rValue.copy(0, nNum + 1);
123 return 1;
126 nVal = 0;
127 return 0;
130 OUString lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
132 if ( nMinDigits <= 1 )
133 return OUString::number( nValue ); // simple case...
134 else
136 OUString aStr = OUString::number( std::abs( nValue ) );
137 if ( aStr.getLength() < nMinDigits )
139 OUStringBuffer aZero;
140 comphelper::string::padToLength(aZero, nMinDigits - aStr.getLength(), '0');
141 aStr = aZero.makeStringAndClear() + aStr;
143 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
144 if ( nValue < 0 )
145 aStr = "-" + aStr;
146 return aStr;
150 void setSuffixCell(
151 ScColumn& rColumn, SCROW nRow, sal_Int32 nValue, sal_uInt16 nDigits, const OUString& rSuffix,
152 CellType eCellType, bool bIsOrdinalSuffix )
154 ScDocument& rDoc = rColumn.GetDoc();
155 OUString aValue = lcl_ValueString(nValue, nDigits);
156 if (!bIsOrdinalSuffix)
158 rColumn.SetRawString(nRow, aValue += rSuffix);
159 return;
162 OUString aOrdinalSuffix = ScGlobal::GetOrdinalSuffix(nValue);
163 if (eCellType != CELLTYPE_EDIT)
165 rColumn.SetRawString(nRow, aValue += aOrdinalSuffix);
166 return;
169 EditEngine aEngine(rDoc.GetEnginePool());
170 aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
172 SfxItemSet aAttr = aEngine.GetEmptyItemSet();
173 aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
174 aEngine.SetText( aValue );
175 aEngine.QuickInsertText(
176 aOrdinalSuffix,
177 ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
179 aEngine.QuickSetAttribs(
180 aAttr,
181 ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
183 // Text object instance will be owned by the cell.
184 rColumn.SetEditText(nRow, aEngine.CreateTextObject());
189 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
190 FillCmd& rCmd, FillDateCmd& rDateCmd,
191 double& rInc, sal_uInt16& rMinDigits,
192 ScUserListData*& rListData, sal_uInt16& rListIndex)
194 OSL_ENSURE( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: invalid range" );
196 rInc = 0.0;
197 rMinDigits = 0;
198 rListData = NULL;
199 rCmd = FILL_SIMPLE;
200 if ( (nScFillModeMouseModifier & KEY_MOD1) )
201 return ; // Ctrl-key: Copy
203 SCCOL nAddX;
204 SCROW nAddY;
205 SCSIZE nCount;
206 if (nCol1 == nCol2)
208 nAddX = 0;
209 nAddY = 1;
210 nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
212 else
214 nAddX = 1;
215 nAddY = 0;
216 nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
219 SCCOL nCol = nCol1;
220 SCROW nRow = nRow1;
222 ScRefCellValue aFirstCell = GetCellValue(nCol, nRow);
223 CellType eCellType = aFirstCell.meType;
225 if (eCellType == CELLTYPE_VALUE)
227 sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
228 bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
229 if (bDate)
231 if (nCount > 1)
233 double nVal;
234 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
235 Date aDate1 = aNullDate;
236 nVal = aFirstCell.mfValue;
237 aDate1 += (long)nVal;
238 Date aDate2 = aNullDate;
239 nVal = GetValue(nCol+nAddX, nRow+nAddY);
240 aDate2 += (long)nVal;
241 if ( aDate1 != aDate2 )
243 long nCmpInc = 0;
244 FillDateCmd eType;
245 long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
246 long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
247 long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
248 if ( nDDiff )
250 eType = FILL_DAY;
251 nCmpInc = aDate2 - aDate1;
253 else
255 eType = FILL_MONTH;
256 nCmpInc = nMDiff + 12 * nYDiff;
259 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
260 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
261 bool bVal = true;
262 for (sal_uInt16 i=1; i<nCount && bVal; i++)
264 ScRefCellValue aCell = GetCellValue(nCol,nRow);
265 if (aCell.meType == CELLTYPE_VALUE)
267 nVal = aCell.mfValue;
268 aDate2 = aNullDate + (long) nVal;
269 if ( eType == FILL_DAY )
271 if ( aDate2-aDate1 != nCmpInc )
272 bVal = false;
274 else
276 nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
277 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
278 nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
279 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
280 bVal = false;
282 aDate1 = aDate2;
283 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
284 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
286 else
287 bVal = false; // kein Datum passt auch nicht
289 if (bVal)
291 if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
293 eType = FILL_YEAR;
294 nCmpInc /= 12;
296 rCmd = FILL_DATE;
297 rDateCmd = eType;
298 rInc = nCmpInc;
302 else // single date -> increment by days
304 rCmd = FILL_DATE;
305 rDateCmd = FILL_DAY;
306 rInc = 1.0;
309 else
311 if (nCount > 1)
313 double nVal1 = aFirstCell.mfValue;
314 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
315 rInc = nVal2 - nVal1;
316 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
317 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
318 bool bVal = true;
319 for (sal_uInt16 i=1; i<nCount && bVal; i++)
321 ScRefCellValue aCell = GetCellValue(nCol,nRow);
322 if (aCell.meType == CELLTYPE_VALUE)
324 nVal2 = aCell.mfValue;
325 double nDiff = nVal2 - nVal1;
326 if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
327 bVal = false;
328 nVal1 = nVal2;
330 else
331 bVal = false;
332 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
333 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
335 if (bVal)
336 rCmd = FILL_LINEAR;
340 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
342 OUString aStr;
343 GetString(nCol, nRow, aStr);
345 // fdo#39500 don't deduce increment from multiple equal list entries
346 bool bAllSame = true;
347 for (sal_uInt16 i = 0; i < nCount; ++i)
349 OUString aTestStr;
350 GetString(static_cast<SCCOL>(nCol + i* nAddX), static_cast<SCROW>(nRow + i * nAddY), aTestStr);
351 if(aStr != aTestStr)
353 bAllSame = false;
354 break;
357 if(bAllSame && nCount > 1)
358 return;
360 rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
361 if (rListData)
363 rListData->GetSubIndex(aStr, rListIndex);
364 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
365 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
366 for (sal_uInt16 i=1; i<nCount && rListData; i++)
368 GetString(nCol, nRow, aStr);
369 if (!rListData->GetSubIndex(aStr, rListIndex))
370 rListData = NULL;
371 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
372 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
375 else if ( nCount > 1 )
377 // pass rMinDigits to all DecompValueString calls
378 // -> longest number defines rMinDigits
380 sal_Int32 nVal1;
381 short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
382 if ( nFlag1 )
384 sal_Int32 nVal2;
385 GetString( nCol+nAddX, nRow+nAddY, aStr );
386 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
387 if ( nFlag1 == nFlag2 )
389 rInc = (double)nVal2 - (double)nVal1;
390 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
391 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
392 bool bVal = true;
393 for (sal_uInt16 i=1; i<nCount && bVal; i++)
395 ScRefCellValue aCell = GetCellValue(nCol, nRow);
396 CellType eType = aCell.meType;
397 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
399 aStr = aCell.getString(pDocument);
400 nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
401 if ( nFlag1 == nFlag2 )
403 double nDiff = (double)nVal2 - (double)nVal1;
404 if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
405 bVal = false;
406 nVal1 = nVal2;
408 else
409 bVal = false;
411 else
412 bVal = false;
413 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
414 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
416 if (bVal)
417 rCmd = FILL_LINEAR;
421 else
423 // call DecompValueString to set rMinDigits
424 sal_Int32 nDummy;
425 lcl_DecompValueString( aStr, nDummy, &rMinDigits );
430 void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, bool /* bFirst */, ScFormulaCell* pSrcCell,
431 SCCOL nDestCol, SCROW nDestRow, bool bLast )
434 pDocument->SetNoListening( true ); // still the wrong reference
435 ScAddress aAddr( nDestCol, nDestRow, nTab );
436 ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
437 aCol[nDestCol].SetFormulaCell(nDestRow, pDestCell);
439 if ( bLast && pDestCell->GetMatrixFlag() )
441 ScAddress aOrg;
442 if ( pDestCell->GetMatrixOrigin( aOrg ) )
444 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
446 ScFormulaCell* pOrgCell = pDocument->GetFormulaCell(aOrg);
447 if (pOrgCell && pOrgCell->GetMatrixFlag() == MM_FORMULA)
449 ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
450 nDestCol - aOrg.Col() + 1,
451 nDestRow - aOrg.Row() + 1 );
453 else
455 OSL_FAIL( "FillFormula: MatrixOrigin no forumla cell with MM_FORMULA" );
458 else
460 OSL_FAIL( "FillFormula: MatrixOrigin bottom right" );
463 else
465 OSL_FAIL( "FillFormula: no MatrixOrigin" );
468 pDocument->SetNoListening( false );
469 pDestCell->StartListeningTo( pDocument );
473 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
474 sal_uLong nFillCount, FillDir eFillDir, ScProgress* pProgress )
476 if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
477 return;
480 // Detect direction
483 bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
484 bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
486 sal_uLong nCol = 0;
487 sal_uLong nRow = 0;
488 sal_uLong& rInner = bVertical ? nRow : nCol; // loop variables
489 sal_uLong& rOuter = bVertical ? nCol : nRow;
490 sal_uLong nOStart;
491 sal_uLong nOEnd;
492 sal_uLong nIStart;
493 sal_uLong nIEnd;
494 sal_uLong nISrcStart;
495 sal_uLong nISrcEnd;
496 ScRange aFillRange;
498 if (bVertical)
500 nOStart = nCol1;
501 nOEnd = nCol2;
502 if (bPositive)
504 nISrcStart = nRow1;
505 nISrcEnd = nRow2;
506 nIStart = nRow2 + 1;
507 nIEnd = nRow2 + nFillCount;
508 aFillRange = ScRange(nCol1, nRow2+1, 0, nCol2, nRow2 + nFillCount, 0);
510 else
512 nISrcStart = nRow2;
513 nISrcEnd = nRow1;
514 nIStart = nRow1 - 1;
515 nIEnd = nRow1 - nFillCount;
516 aFillRange = ScRange(nCol1, nRow1-1, 0, nCol2, nRow2 - nFillCount, 0);
519 else
521 nOStart = nRow1;
522 nOEnd = nRow2;
523 if (bPositive)
525 nISrcStart = nCol1;
526 nISrcEnd = nCol2;
527 nIStart = nCol2 + 1;
528 nIEnd = nCol2 + nFillCount;
529 aFillRange = ScRange(nCol2 + 1, nRow1, 0, nCol2 + nFillCount, nRow2, 0);
531 else
533 nISrcStart = nCol2;
534 nISrcEnd = nCol1;
535 nIStart = nCol1 - 1;
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);
545 if (!bHasFiltered)
547 if (bVertical)
548 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
549 else
550 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
553 sal_uLong nProgress = 0;
554 if (pProgress)
555 nProgress = pProgress->GetState();
558 // execute
561 sal_uLong nActFormCnt = 0;
562 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
564 sal_uLong nMaxFormCnt = 0; // for formulas
566 // transfer attributes
568 const ScPatternAttr* pSrcPattern = NULL;
569 const ScStyleSheet* pStyleSheet = NULL;
570 sal_uLong nAtSrc = nISrcStart;
571 ScPatternAttr* pNewPattern = NULL;
572 bool bGetPattern = true;
573 rInner = nIStart;
574 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
576 if (!ColHidden(nCol) && !RowHidden(nRow))
578 if ( bGetPattern )
580 delete pNewPattern;
581 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
582 pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
583 else // rInner&:=nCol, rOuter&:=nRow
584 pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
585 bGetPattern = false;
586 pStyleSheet = pSrcPattern->GetStyleSheet();
587 // do not transfer ATTR_MERGE / ATTR_MERGE_FLAG
588 const SfxItemSet& rSet = pSrcPattern->GetItemSet();
589 if ( rSet.GetItemState(ATTR_MERGE, false) == SFX_ITEM_SET
590 || rSet.GetItemState(ATTR_MERGE_FLAG, false) == SFX_ITEM_SET )
592 pNewPattern = new ScPatternAttr( *pSrcPattern );
593 SfxItemSet& rNewSet = pNewPattern->GetItemSet();
594 rNewSet.ClearItem(ATTR_MERGE);
595 rNewSet.ClearItem(ATTR_MERGE_FLAG);
597 else
598 pNewPattern = NULL;
601 const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
602 const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
604 if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
606 // set all attributes at once (en bloc)
607 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
609 // Default is already present (DeleteArea)
610 SCROW nY1 = static_cast<SCROW>(std::min( nIStart, nIEnd ));
611 SCROW nY2 = static_cast<SCROW>(std::max( nIStart, nIEnd ));
612 if ( pStyleSheet )
613 aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
614 if ( pNewPattern )
615 aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
616 else
617 aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
619 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
620 itr != itrEnd; ++itr)
622 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
623 ScRangeList aRange = pCondFormat->GetRange();
624 aRange.Join(ScRange(nCol, nY1, nTab, nCol, nY2, nTab));
625 pCondFormat->AddRange(aRange);
630 break;
633 if ( bHasFiltered )
634 DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
635 static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
637 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
639 // Transfer template too
640 //! Merge ApplyPattern to AttrArray ??
641 if ( pStyleSheet )
642 aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
644 // Use ApplyPattern instead of SetPattern to keep old MergeFlags
645 if ( pNewPattern )
646 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
647 else
648 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
650 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
651 itr != itrEnd; ++itr)
653 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
654 ScRangeList aRange = pCondFormat->GetRange();
655 aRange.Join(ScRange(nCol, nRow, nTab, nCol, nRow, nTab));
656 pCondFormat->AddRange(aRange);
660 if (nAtSrc==nISrcEnd)
662 if ( nAtSrc != nISrcStart )
663 { // More than one source cell
664 nAtSrc = nISrcStart;
665 bGetPattern = true;
668 else if (bPositive)
670 ++nAtSrc;
671 bGetPattern = true;
673 else
675 --nAtSrc;
676 bGetPattern = true;
680 if (rInner == nIEnd) break;
681 if (bPositive) ++rInner; else --rInner;
683 if ( pNewPattern )
684 delete pNewPattern;
686 // Analyse
688 FillCmd eFillCmd;
689 FillDateCmd eDateCmd;
690 double nInc;
691 sal_uInt16 nMinDigits;
692 ScUserListData* pListData = NULL;
693 sal_uInt16 nListIndex;
694 if (bVertical)
695 FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
696 static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
697 nInc,nMinDigits, pListData,nListIndex);
698 else
699 FillAnalyse(nCol1,static_cast<SCROW>(nRow),
700 nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
701 nInc,nMinDigits, pListData,nListIndex);
703 if (pListData)
705 sal_uInt16 nListCount = pListData->GetSubCount();
706 if ( !bPositive )
708 // nListIndex of FillAnalyse points to the last entry -> adjust
709 sal_uLong nSub = nISrcStart - nISrcEnd;
710 for (sal_uLong i=0; i<nSub; i++)
712 if (nListIndex == 0) nListIndex = nListCount;
713 --nListIndex;
717 rInner = nIStart;
718 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720 if(!ColHidden(nCol) && !RowHidden(nRow))
722 if (bPositive)
724 ++nListIndex;
725 if (nListIndex >= nListCount) nListIndex = 0;
727 else
729 if (nListIndex == 0) nListIndex = nListCount;
730 --nListIndex;
732 aCol[nCol].SetRawString(static_cast<SCROW>(nRow), pListData->GetSubStr(nListIndex));
735 if (rInner == nIEnd) break;
736 if (bPositive) ++rInner; else --rInner;
738 if(pProgress)
740 nProgress += nIMax - nIMin + 1;
741 pProgress->SetStateOnPercent( nProgress );
744 else if (eFillCmd == FILL_SIMPLE) // fill with pattern/sample
746 sal_uLong nSource = nISrcStart;
747 double nDelta;
748 if ( (nScFillModeMouseModifier & KEY_MOD1) )
749 nDelta = 0.0;
750 else if ( bPositive )
751 nDelta = 1.0;
752 else
753 nDelta = -1.0;
754 double nVal = 0.0;
755 sal_uLong nFormulaCounter = nActFormCnt;
756 bool bFirst = true;
757 bool bGetCell = true;
758 sal_uInt16 nCellDigits = 0;
759 short nHeadNoneTail = 0;
760 sal_Int32 nStringValue = 0;
761 OUString aValue;
762 ScCellValue aSrcCell;
763 CellType eCellType = CELLTYPE_NONE;
764 bool bIsOrdinalSuffix = false;
766 rInner = nIStart;
767 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
769 if(!ColHidden(nCol) && !RowHidden(nRow))
771 if ( bGetCell )
773 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
774 aSrcCell = aCol[nCol].GetCellValue(static_cast<SCROW>(nSource));
775 else // rInner&:=nCol, rOuter&:=nRow
776 aSrcCell = aCol[nSource].GetCellValue(static_cast<SCROW>(nRow));
778 bGetCell = false;
779 if (!aSrcCell.isEmpty())
781 eCellType = aSrcCell.meType;
782 switch (eCellType)
784 case CELLTYPE_VALUE:
785 nVal = aSrcCell.mfValue;
786 break;
787 case CELLTYPE_STRING:
788 case CELLTYPE_EDIT:
789 if ( eCellType == CELLTYPE_STRING )
790 aValue = aSrcCell.mpString->getString();
791 else
792 aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
793 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered )
795 nCellDigits = 0; // look at each source cell individually
796 nHeadNoneTail = lcl_DecompValueString(
797 aValue, nStringValue, &nCellDigits );
799 bIsOrdinalSuffix = aValue.equals(
800 ScGlobal::GetOrdinalSuffix( nStringValue));
802 break;
803 default:
805 // added to avoid warnings
809 else
810 eCellType = CELLTYPE_NONE;
813 switch (eCellType)
815 case CELLTYPE_VALUE:
816 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal + nDelta);
817 break;
818 case CELLTYPE_STRING:
819 case CELLTYPE_EDIT:
820 if ( nHeadNoneTail )
822 // #i48009# with the "nStringValue+(long)nDelta" expression within the
823 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
824 // so nNextValue is now calculated ahead.
825 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
827 OUString aStr;
828 if ( nHeadNoneTail < 0 )
830 setSuffixCell(
831 aCol[nCol], static_cast<SCROW>(nRow),
832 nNextValue, nCellDigits, aValue,
833 eCellType, bIsOrdinalSuffix);
835 else
837 aStr = aValue + lcl_ValueString( nNextValue, nCellDigits );
838 aCol[nCol].SetRawString(static_cast<SCROW>(nRow), aStr);
841 else
842 aSrcCell.commit(aCol[nCol], nRow);
844 break;
845 case CELLTYPE_FORMULA :
846 FillFormula( nFormulaCounter, bFirst, aSrcCell.mpFormula,
847 static_cast<SCCOL>(nCol),
848 static_cast<SCROW>(nRow), (rInner == nIEnd) );
849 if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
850 nMaxFormCnt = nFormulaCounter - nActFormCnt;
851 break;
852 default:
854 // added to avoid warnings
858 if (nSource==nISrcEnd)
860 if ( nSource != nISrcStart )
861 { // More than one source cell
862 nSource = nISrcStart;
863 bGetCell = true;
865 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
867 if ( bPositive )
868 nDelta += 1.0;
869 else
870 nDelta -= 1.0;
872 nFormulaCounter = nActFormCnt;
873 bFirst = false;
875 else if (bPositive)
877 ++nSource;
878 bGetCell = true;
880 else
882 --nSource;
883 bGetCell = true;
887 if (rInner == nIEnd) break;
888 if (bPositive) ++rInner; else --rInner;
890 // Progress in inner loop only for expensive cells,
891 // and even then not individually for each one
893 ++nProgress;
894 if ( pProgress && (eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT) )
895 pProgress->SetStateOnPercent( nProgress );
898 if (pProgress)
899 pProgress->SetStateOnPercent( nProgress );
901 else
903 if (!bPositive)
904 nInc = -nInc;
905 double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
906 if (bVertical)
907 FillSeries( static_cast<SCCOL>(nCol), nRow1,
908 static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
909 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
910 pProgress );
911 else
912 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
913 static_cast<SCROW>(nRow), nFillCount, eFillDir,
914 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
915 pProgress );
916 if (pProgress)
917 nProgress = pProgress->GetState();
920 nActFormCnt += nMaxFormCnt;
924 OUString ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
926 OUString aValue;
928 SCCOL nCol1 = rSource.aStart.Col();
929 SCROW nRow1 = rSource.aStart.Row();
930 SCCOL nCol2 = rSource.aEnd.Col();
931 SCROW nRow2 = rSource.aEnd.Row();
932 bool bOk = true;
933 long nIndex = 0;
934 sal_uLong nSrcCount = 0;
935 FillDir eFillDir = FILL_TO_BOTTOM;
936 if ( nEndX == nCol2 && nEndY == nRow2 ) // empty
937 bOk = false;
938 else if ( nEndX == nCol2 ) // to up / down
940 nEndX = nCol2 = nCol1; // use only first column
941 nSrcCount = nRow2 - nRow1 + 1;
942 nIndex = ((long)nEndY) - nRow1; // can be negative
943 if ( nEndY >= nRow1 )
944 eFillDir = FILL_TO_BOTTOM;
945 else
946 eFillDir = FILL_TO_TOP;
948 else if ( nEndY == nRow2 ) // to left / right
950 nEndY = nRow2 = nRow1; // use only first row
951 nSrcCount = nCol2 - nCol1 + 1;
952 nIndex = ((long)nEndX) - nCol1; // can be negative
953 if ( nEndX >= nCol1 )
954 eFillDir = FILL_TO_RIGHT;
955 else
956 eFillDir = FILL_TO_LEFT;
958 else // direction not clear
959 bOk = false;
961 if ( bOk )
963 FillCmd eFillCmd;
964 FillDateCmd eDateCmd;
965 double nInc;
966 sal_uInt16 nMinDigits;
967 ScUserListData* pListData = NULL;
968 sal_uInt16 nListIndex;
970 FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
972 if ( pListData ) // user defined list
974 sal_uInt16 nListCount = pListData->GetSubCount();
975 if ( nListCount )
977 sal_uLong nSub = nSrcCount - 1; // nListIndex is from last source entry
978 while ( nIndex < sal::static_int_cast<long>(nSub) )
979 nIndex += nListCount;
980 sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
981 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
984 else if ( eFillCmd == FILL_SIMPLE ) // fill with pattern/sample
986 if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
988 long nBegin = 0;
989 long nEnd = 0;
990 if (nEndY > nRow1)
992 nBegin = nRow2+1;
993 nEnd = nEndY;
995 else
997 nBegin = nEndY;
998 nEnd = nRow1 -1;
1001 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
1002 long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
1004 if (nIndex > 0)
1005 nIndex = nIndex - nFiltered;
1006 else
1007 nIndex = nIndex + nFiltered;
1010 long nPosIndex = nIndex;
1011 while ( nPosIndex < 0 )
1012 nPosIndex += nSrcCount;
1013 sal_uLong nPos = nPosIndex % nSrcCount;
1014 SCCOL nSrcX = nCol1;
1015 SCROW nSrcY = nRow1;
1016 if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
1017 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
1018 else
1019 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
1021 ScRefCellValue aCell = GetCellValue(nSrcX, nSrcY);
1022 if (!aCell.isEmpty())
1024 sal_Int32 nDelta;
1025 if (nIndex >= 0)
1026 nDelta = nIndex / nSrcCount;
1027 else
1028 nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
1030 CellType eType = aCell.meType;
1031 switch ( eType )
1033 case CELLTYPE_STRING:
1034 case CELLTYPE_EDIT:
1036 aValue = aCell.getString(pDocument);
1038 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1040 sal_Int32 nVal;
1041 sal_uInt16 nCellDigits = 0; // look at each source cell individually
1042 short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1043 if ( nFlag < 0 )
1045 if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
1046 aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1048 aValue = lcl_ValueString( nVal + nDelta, nCellDigits ) + aValue;
1050 else if ( nFlag > 0 )
1051 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1054 break;
1055 case CELLTYPE_VALUE:
1057 // overflow is possible...
1058 double nVal = aCell.mfValue;
1059 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1060 nVal += (double) nDelta;
1062 Color* pColor;
1063 sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1064 OUString sTmp(aValue);
1065 pDocument->GetFormatTable()->GetOutputString( nVal, nNumFmt, sTmp, &pColor );
1066 aValue = sTmp;
1068 break;
1069 // not for formulas
1070 default:
1072 // added to avoid warnings
1077 else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // values
1079 bool bValueOk;
1080 double nStart;
1081 sal_Int32 nVal = 0;
1082 short nHeadNoneTail = 0;
1083 ScRefCellValue aCell = GetCellValue(nCol1, nRow1);
1084 if (!aCell.isEmpty())
1086 CellType eType = aCell.meType;
1087 switch ( eType )
1089 case CELLTYPE_STRING:
1090 case CELLTYPE_EDIT:
1092 aValue = aCell.getString(pDocument);
1093 nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1094 if ( nHeadNoneTail )
1095 nStart = (double)nVal;
1096 else
1097 nStart = 0.0;
1099 break;
1100 case CELLTYPE_VALUE:
1101 nStart = aCell.mfValue;
1102 break;
1103 case CELLTYPE_FORMULA:
1104 nStart = aCell.mpFormula->GetValue();
1105 break;
1106 default:
1107 nStart = 0.0;
1110 else
1111 nStart = 0.0;
1112 if ( eFillCmd == FILL_LINEAR )
1114 double nAdd = nInc;
1115 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1116 SubTotal::SafePlus( nStart, nAdd ) );
1118 else // date
1120 bValueOk = true;
1121 sal_uInt16 nDayOfMonth = 0;
1122 if ( nIndex < 0 )
1124 nIndex = -nIndex;
1125 nInc = -nInc;
1127 for (long i=0; i<nIndex; i++)
1128 IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1131 if (bValueOk)
1133 if ( nHeadNoneTail )
1135 if ( nHeadNoneTail < 0 )
1137 if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
1138 aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1140 aValue = lcl_ValueString( (sal_Int32)nStart, nMinDigits ) + aValue;
1142 else
1143 aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1145 else
1147 //! Zahlformat je nach Index holen?
1148 Color* pColor;
1149 sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
1150 OUString sTmp(aValue);
1151 pDocument->GetFormatTable()->GetOutputString( nStart, nNumFmt, sTmp, &pColor );
1152 aValue = sTmp;
1156 else
1158 OSL_FAIL("GetAutoFillPreview: invalid mode");
1162 return aValue;
1165 void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
1167 if (eCmd == FILL_DAY)
1169 rVal += nStep;
1170 return;
1173 // class Date limits
1174 const sal_uInt16 nMinYear = 1583;
1175 const sal_uInt16 nMaxYear = 9956;
1177 long nInc = (long) nStep; // upper/lower limits ?
1178 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1179 Date aDate = aNullDate;
1180 aDate += (long)rVal;
1181 switch (eCmd)
1183 case FILL_WEEKDAY:
1185 aDate += nInc;
1186 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1187 if (nInc >= 0)
1189 if (eWeekDay == SATURDAY)
1190 aDate += 2;
1191 else if (eWeekDay == SUNDAY)
1192 aDate += 1;
1194 else
1196 if (eWeekDay == SATURDAY)
1197 aDate -= 1;
1198 else if (eWeekDay == SUNDAY)
1199 aDate -= 2;
1202 break;
1203 case FILL_MONTH:
1205 if ( nDayOfMonth == 0 )
1206 nDayOfMonth = aDate.GetDay(); // init
1207 long nMonth = aDate.GetMonth();
1208 long nYear = aDate.GetYear();
1210 nMonth += nInc;
1212 if (nInc >= 0)
1214 if (nMonth > 12)
1216 long nYAdd = (nMonth-1) / 12;
1217 nMonth -= nYAdd * 12;
1218 nYear += nYAdd;
1221 else
1223 if (nMonth < 1)
1225 long nYAdd = 1 - nMonth / 12; // positive
1226 nMonth += nYAdd * 12;
1227 nYear -= nYAdd;
1231 if ( nYear < nMinYear )
1232 aDate = Date( 1,1, nMinYear );
1233 else if ( nYear > nMaxYear )
1234 aDate = Date( 31,12, nMaxYear );
1235 else
1237 aDate.SetMonth((sal_uInt16) nMonth);
1238 aDate.SetYear((sal_uInt16) nYear);
1239 aDate.SetDay( std::min( Date::GetDaysInMonth( nMonth, nYear), nDayOfMonth ) );
1242 break;
1243 case FILL_YEAR:
1245 long nYear = aDate.GetYear();
1246 nYear += nInc;
1247 if ( nYear < nMinYear )
1248 aDate = Date( 1,1, nMinYear );
1249 else if ( nYear > nMaxYear )
1250 aDate = Date( 31,12, nMaxYear );
1251 else
1252 aDate.SetYear((sal_uInt16) nYear);
1254 break;
1255 default:
1257 // added to avoid warnings
1261 rVal = aDate - aNullDate;
1264 namespace
1267 bool HiddenRowColumn(sal_uLong nRowColumn, bool bVertical, ScTable* pTable)
1269 if(bVertical)
1271 return pTable->RowHidden(static_cast<SCROW>(nRowColumn));
1273 else
1275 return pTable->ColHidden(static_cast<SCCOL>(nRowColumn));
1281 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1282 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1283 double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
1284 bool bAttribs, ScProgress* pProgress )
1287 // Detect direction
1290 bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1291 bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1293 sal_uLong nCol = 0;
1294 sal_uLong nRow = 0;
1295 sal_uLong& rInner = bVertical ? nRow : nCol; // loop variables
1296 sal_uLong& rOuter = bVertical ? nCol : nRow;
1297 sal_uLong nOStart;
1298 sal_uLong nOEnd;
1299 sal_uLong nIStart;
1300 sal_uLong nIEnd;
1301 sal_uLong nISource;
1302 ScRange aFillRange;
1304 if (bVertical)
1306 nFillCount += (nRow2 - nRow1);
1307 if (nFillCount == 0)
1308 return;
1309 nOStart = nCol1;
1310 nOEnd = nCol2;
1311 if (bPositive)
1313 nISource = nRow1;
1314 nIStart = nRow1 + 1;
1315 nIEnd = nRow1 + nFillCount;
1316 aFillRange = ScRange(nCol1, nRow1 + 1, nTab, nCol2, nRow1 + nFillCount, nTab);
1318 else
1320 nISource = nRow2;
1321 nIStart = nRow2 - 1;
1322 nIEnd = nRow2 - nFillCount;
1323 aFillRange = ScRange(nCol1, nRow2 -1, nTab, nCol2, nRow2 - nFillCount, nTab);
1326 else
1328 nFillCount += (nCol2 - nCol1);
1329 if (nFillCount == 0)
1330 return;
1331 nOStart = nRow1;
1332 nOEnd = nRow2;
1333 if (bPositive)
1335 nISource = nCol1;
1336 nIStart = nCol1 + 1;
1337 nIEnd = nCol1 + nFillCount;
1338 aFillRange = ScRange(nCol1 + 1, nRow1, nTab, nCol1 + nFillCount, nRow2, nTab);
1340 else
1342 nISource = nCol2;
1343 nIStart = nCol2 - 1;
1344 nIEnd = nCol2 - nFillCount;
1345 aFillRange = ScRange(nCol2 - 1, nRow1, nTab, nCol2 - nFillCount, nRow2, nTab);
1349 sal_uLong nIMin = nIStart;
1350 sal_uLong nIMax = nIEnd;
1351 PutInOrder(nIMin,nIMax);
1352 sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1354 bool bIsFiltered = IsDataFiltered(aFillRange);
1355 if (!bIsFiltered)
1357 if (bVertical)
1358 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1359 else
1360 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1363 sal_uLong nProgress = 0;
1364 if (pProgress)
1365 nProgress = pProgress->GetState();
1368 // execute
1371 sal_uLong nActFormCnt = 0;
1372 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1374 rInner = nISource;
1376 // Source cell value. We need to clone the value since it may be inserted repeatedly.
1377 ScCellValue aSrcCell = aCol[nCol].GetCellValue(static_cast<SCROW>(nRow));
1379 if (bAttribs)
1381 const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1383 const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
1384 const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
1386 if (bVertical)
1388 // if not filtered use the faster method
1389 // hidden cols/rows should be skiped
1390 if(!bIsFiltered)
1392 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1393 static_cast<SCROW>(nIMax), *pSrcPattern, true );
1395 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1396 itr != itrEnd; ++itr)
1398 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1399 ScRangeList aRange = pCondFormat->GetRange();
1400 aRange.Join(ScRange(nCol, nIMin, nTab, nCol, nIMax, nTab));
1401 pCondFormat->AddRange(aRange);
1404 else
1406 for(SCROW nAtRow = static_cast<SCROW>(nIMin); nAtRow <= static_cast<SCROW>(nIMax); ++nAtRow)
1408 if(!RowHidden(nAtRow))
1410 aCol[nCol].SetPatternArea( static_cast<SCROW>(nAtRow),
1411 static_cast<SCROW>(nAtRow), *pSrcPattern, true);
1412 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1413 itr != itrEnd; ++itr)
1415 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1416 ScRangeList aRange = pCondFormat->GetRange();
1417 aRange.Join(ScRange(nCol, nAtRow, nTab, nCol, nAtRow, nTab));
1418 pCondFormat->AddRange(aRange);
1425 else
1426 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1427 if(!ColHidden(nAtCol))
1429 aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, true);
1430 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1431 itr != itrEnd; ++itr)
1433 ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1434 ScRangeList aRange = pCondFormat->GetRange();
1435 aRange.Join(ScRange(nAtCol, static_cast<SCROW>(nRow), nTab, nAtCol, static_cast<SCROW>(nRow), nTab));
1436 pCondFormat->AddRange(aRange);
1441 if (!aSrcCell.isEmpty())
1443 CellType eCellType = aSrcCell.meType;
1445 if (eFillCmd == FILL_SIMPLE) // copy
1447 if (eCellType == CELLTYPE_FORMULA)
1449 bool bFirst = true;
1450 for (rInner = nIMin; rInner <= nIMax; rInner++)
1452 if(HiddenRowColumn(rInner, bVertical, this))
1453 continue;
1454 sal_uLong nInd = nActFormCnt;
1455 FillFormula(nInd, bFirst, aSrcCell.mpFormula,
1456 static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1457 bFirst = false;
1458 if(pProgress)
1459 pProgress->SetStateOnPercent( ++nProgress );
1462 else
1464 for (rInner = nIMin; rInner <= nIMax; rInner++)
1466 if(HiddenRowColumn(rInner, bVertical, this))
1467 continue;
1468 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1469 aSrcCell.commit(aCol[nCol], aDestPos.Row());
1471 nProgress += nIMax - nIMin + 1;
1472 if(pProgress)
1473 pProgress->SetStateOnPercent( nProgress );
1476 else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1478 double nStartVal;
1479 if (eCellType == CELLTYPE_VALUE)
1480 nStartVal = aSrcCell.mfValue;
1481 else
1482 nStartVal = aSrcCell.mpFormula->GetValue();
1483 double nVal = nStartVal;
1484 long nIndex = 0;
1486 bool bError = false;
1487 bool bOverflow = false;
1489 sal_uInt16 nDayOfMonth = 0;
1490 rInner = nIStart;
1491 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1493 if(!ColHidden(nCol) && !RowHidden(nRow))
1495 if (!bError && !bOverflow)
1497 switch (eFillCmd)
1499 case FILL_LINEAR:
1501 // use multiplication instead of repeated addition
1502 // to avoid accumulating rounding errors
1503 nVal = nStartVal;
1504 double nAdd = nStepValue;
1505 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1506 !SubTotal::SafePlus( nVal, nAdd ) )
1507 bError = true;
1509 break;
1510 case FILL_GROWTH:
1511 if (!SubTotal::SafeMult(nVal, nStepValue))
1512 bError = true;
1513 break;
1514 case FILL_DATE:
1515 if (fabs(nVal) > _D_MAX_LONG_)
1516 bError = true;
1517 else
1518 IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1519 break;
1520 default:
1522 // added to avoid warnings
1526 if (nStepValue >= 0)
1528 if (nVal > nMaxValue) // target value reached ?
1530 nVal = nMaxValue;
1531 bOverflow = true;
1534 else
1536 if (nVal < nMaxValue)
1538 nVal = nMaxValue;
1539 bOverflow = true;
1544 if (bError)
1545 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1546 else if (bOverflow)
1547 aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
1548 else
1549 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1552 if (rInner == nIEnd)
1553 break;
1554 if (bPositive)
1556 ++rInner;
1558 else
1560 --rInner;
1563 nProgress += nIMax - nIMin + 1;
1564 if(pProgress)
1565 pProgress->SetStateOnPercent( nProgress );
1567 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1569 if ( nStepValue >= 0 )
1571 if ( nMaxValue >= (double)LONG_MAX )
1572 nMaxValue = (double)LONG_MAX - 1;
1574 else
1576 if ( nMaxValue <= (double)LONG_MIN )
1577 nMaxValue = (double)LONG_MIN + 1;
1579 OUString aValue;
1580 if (eCellType == CELLTYPE_STRING)
1581 aValue = aSrcCell.mpString->getString();
1582 else
1583 aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
1584 sal_Int32 nStringValue;
1585 sal_uInt16 nMinDigits = nArgMinDigits;
1586 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1587 if ( nHeadNoneTail )
1589 double nStartVal = (double)nStringValue;
1590 double nVal = nStartVal;
1591 long nIndex = 0;
1592 bool bError = false;
1593 bool bOverflow = false;
1595 bool bIsOrdinalSuffix = aValue.equals( ScGlobal::GetOrdinalSuffix(
1596 (sal_Int32)nStartVal));
1598 rInner = nIStart;
1599 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1601 if(!ColHidden(nCol) && !RowHidden(nRow))
1603 if (!bError && !bOverflow)
1605 switch (eFillCmd)
1607 case FILL_LINEAR:
1609 // use multiplication instead of repeated addition
1610 // to avoid accumulating rounding errors
1611 nVal = nStartVal;
1612 double nAdd = nStepValue;
1613 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1614 !SubTotal::SafePlus( nVal, nAdd ) )
1615 bError = true;
1617 break;
1618 case FILL_GROWTH:
1619 if (!SubTotal::SafeMult(nVal, nStepValue))
1620 bError = true;
1621 break;
1622 default:
1624 // added to avoid warnings
1628 if (nStepValue >= 0)
1630 if (nVal > nMaxValue) // target value reached ?
1632 nVal = nMaxValue;
1633 bOverflow = true;
1636 else
1638 if (nVal < nMaxValue)
1640 nVal = nMaxValue;
1641 bOverflow = true;
1646 if (bError)
1647 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1648 else if (bOverflow)
1649 aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
1650 else
1652 nStringValue = (sal_Int32)nVal;
1653 OUString aStr;
1654 if ( nHeadNoneTail < 0 )
1656 setSuffixCell(
1657 aCol[nCol], static_cast<SCROW>(nRow),
1658 nStringValue, nMinDigits, aValue,
1659 eCellType, bIsOrdinalSuffix);
1661 else
1663 aStr = aValue;
1664 aStr += lcl_ValueString( nStringValue, nMinDigits );
1665 aCol[nCol].SetRawString(static_cast<SCROW>(nRow), aStr);
1670 if (rInner == nIEnd) break;
1671 if (bPositive) ++rInner; else --rInner;
1674 if(pProgress)
1676 nProgress += nIMax - nIMin + 1;
1677 pProgress->SetStateOnPercent( nProgress );
1681 else if(pProgress)
1683 nProgress += nIMax - nIMin + 1;
1684 pProgress->SetStateOnPercent( nProgress );
1686 ++nActFormCnt;
1690 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1691 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1692 double nStepValue, double nMaxValue, ScProgress* pProgress)
1694 if (eFillCmd == FILL_AUTO)
1695 FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, pProgress);
1696 else
1697 FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1698 eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, true, pProgress);
1702 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1703 const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
1705 ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
1706 ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
1707 if (pData)
1709 ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1713 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1714 sal_uInt16 nFormatNo )
1716 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1718 ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
1719 ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
1720 if (pData)
1722 ScPatternAttr* pPatternAttrs[16];
1723 for (sal_uInt8 i = 0; i < 16; ++i)
1725 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1726 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1729 SCCOL nCol = nStartCol;
1730 SCROW nRow = nStartRow;
1731 sal_uInt16 nIndex = 0;
1732 // Left top corner
1733 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1734 // Left column
1735 if (pData->IsEqualData(4, 8))
1736 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1737 else
1739 nIndex = 4;
1740 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1742 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1743 if (nIndex == 4)
1744 nIndex = 8;
1745 else
1746 nIndex = 4;
1749 // Left bottom corner
1750 nRow = nEndRow;
1751 nIndex = 12;
1752 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1753 // Right top corner
1754 nCol = nEndCol;
1755 nRow = nStartRow;
1756 nIndex = 3;
1757 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1758 // Right column
1759 if (pData->IsEqualData(7, 11))
1760 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1761 else
1763 nIndex = 7;
1764 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1766 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1767 if (nIndex == 7)
1768 nIndex = 11;
1769 else
1770 nIndex = 7;
1773 // Right bottom corner
1774 nRow = nEndRow;
1775 nIndex = 15;
1776 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1777 nRow = nStartRow;
1778 nIndex = 1;
1779 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1781 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1782 if (nIndex == 1)
1783 nIndex = 2;
1784 else
1785 nIndex = 1;
1787 // Bottom row
1788 nRow = nEndRow;
1789 nIndex = 13;
1790 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1792 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1793 if (nIndex == 13)
1794 nIndex = 14;
1795 else
1796 nIndex = 13;
1798 // Boddy
1799 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1800 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1801 else
1803 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1805 nIndex = 5;
1806 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1808 AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1809 if (nIndex == 5)
1810 nIndex = 6;
1811 else
1812 nIndex = 5;
1815 else
1817 nIndex = 5;
1818 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1820 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1822 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1823 if ((nIndex == 5) || (nIndex == 9))
1825 if (nIndex == 5)
1826 nIndex = 9;
1827 else
1828 nIndex = 5;
1830 else
1832 if (nIndex == 6)
1833 nIndex = 10;
1834 else
1835 nIndex = 6;
1837 } // for nRow
1838 if ((nIndex == 5) || (nIndex == 9))
1839 nIndex = 6;
1840 else
1841 nIndex = 5;
1842 } // for nCol
1843 } // if not equal Column
1844 } // if not all equal
1846 for (sal_uInt8 j = 0; j < 16; ++j)
1847 delete pPatternAttrs[j];
1848 } // if AutoFormatData != NULL
1849 } // if ValidColRow
1852 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
1854 sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
1855 ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1856 rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1859 #define LF_LEFT 1
1860 #define LF_TOP 2
1861 #define LF_RIGHT 4
1862 #define LF_BOTTOM 8
1863 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1865 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
1867 const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1868 const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1869 const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1870 const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1871 const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1873 SvxBoxItem aBox( ATTR_BORDER );
1874 if (nFlags & LF_LEFT)
1876 if (pLeftBox)
1878 if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1879 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1880 else
1881 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1883 else
1884 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1886 if (nFlags & LF_TOP)
1888 if (pTopBox)
1890 if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1891 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1892 else
1893 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1895 else
1896 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1898 if (nFlags & LF_RIGHT)
1900 if (pRightBox)
1902 if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1903 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1904 else
1905 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1907 else
1908 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1910 if (nFlags & LF_BOTTOM)
1912 if (pBottomBox)
1914 if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1915 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1916 else
1917 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1919 else
1920 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1922 rData.PutItem( nIndex, aBox );
1925 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1927 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1929 if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1931 // Left top corner
1932 GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1933 GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1934 // Left column
1935 GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1936 GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1937 GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1938 if (nEndRow - nStartRow >= 4)
1939 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1940 else
1941 rData.CopyItem( 8, 4, ATTR_BORDER );
1942 // Left bottom corner
1943 GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1944 GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1945 // Right top corner
1946 GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1947 GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1948 // Right column
1949 GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1950 GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1951 GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1952 if (nEndRow - nStartRow >= 4)
1953 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1954 else
1955 rData.CopyItem( 11, 7, ATTR_BORDER );
1956 // Right bottom corner
1957 GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1958 GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1959 // Top row
1960 GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1961 GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1962 GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1963 if (nEndCol - nStartCol >= 4)
1964 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1965 else
1966 rData.CopyItem( 2, 1, ATTR_BORDER );
1967 // Bottom row
1968 GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1969 GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1970 GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1971 if (nEndCol - nStartCol >= 4)
1972 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1973 else
1974 rData.CopyItem( 14, 13, ATTR_BORDER );
1975 // Body
1976 GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1977 GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1978 GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1979 GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1980 GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1981 if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1983 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1984 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1985 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1987 else
1989 rData.CopyItem( 6, 5, ATTR_BORDER );
1990 rData.CopyItem( 9, 5, ATTR_BORDER );
1991 rData.CopyItem( 10, 5, ATTR_BORDER );
1997 void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
1999 if (ValidColRow(nCol, nRow))
2000 aCol[nCol].SetError( nRow, nError );
2003 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
2005 for (SCCOL i=0; i <= MAXCOL; i++)
2006 aCol[i].UpdateInsertTabAbs(nTable);
2009 bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel,
2010 const ScMarkData& rMark) const
2012 if (rRow == MAXROW+2) // end of table
2014 rRow = 0;
2015 rCol = 0;
2017 else
2019 rRow++;
2020 if (rRow == MAXROW+1)
2022 rCol++;
2023 rRow = 0;
2026 if (rCol == MAXCOL+1)
2027 return true;
2028 else
2030 bool bStop = false;
2031 while (!bStop)
2033 if (ValidCol(rCol))
2035 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
2036 if (bStop)
2037 return true;
2038 else /*if (rRow == MAXROW+1) */
2040 rCol++;
2041 rRow = 0;
2044 else
2045 return true;
2048 return false;
2051 bool ScTable::TestTabRefAbs(SCTAB nTable) const
2053 for (SCCOL i=0; i <= MAXCOL; i++)
2054 if (aCol[i].TestTabRefAbs(nTable))
2055 return true;
2056 return false;
2059 void ScTable::CompileDBFormula()
2061 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
2064 void ScTable::CompileDBFormula( bool bCreateFormulaString )
2066 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
2069 void ScTable::CompileNameFormula( bool bCreateFormulaString )
2071 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
2074 void ScTable::CompileColRowNameFormula()
2076 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();
2084 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */