Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "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>
44 :
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"
63 : #include <columnspanset.hxx>
64 :
65 : #include <math.h>
66 : #include <boost/scoped_ptr.hpp>
67 :
68 : // STATIC DATA -----------------------------------------------------------
69 :
70 : #define _D_MAX_LONG_ (double) 0x7fffffff
71 :
72 : extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
73 :
74 : namespace {
75 :
76 0 : short lcl_DecompValueString( OUString& rValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
77 : {
78 0 : if ( rValue.isEmpty() )
79 : {
80 0 : nVal = 0;
81 0 : return 0;
82 : }
83 0 : const sal_Unicode* p = rValue.getStr();
84 0 : sal_Int32 nNeg = 0;
85 0 : sal_Int32 nNum = 0;
86 0 : if ( p[nNum] == '-' )
87 0 : nNum = nNeg = 1;
88 0 : while ( p[nNum] && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
89 0 : nNum++;
90 :
91 0 : sal_Unicode cNext = p[nNum]; // 0 if at the end
92 0 : sal_Unicode cLast = p[rValue.getLength()-1];
93 :
94 : // #i5550# If there are numbers at the beginning and the end,
95 : // prefer the one at the beginning only if it's followed by a space.
96 : // Otherwise, use the number at the end, to enable things like IP addresses.
97 0 : if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(OUString(cLast)) ) )
98 : { // number at the beginning
99 0 : nVal = rValue.copy( 0, nNum ).toInt32();
100 : // any number with a leading zero sets the minimum number of digits
101 0 : if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
102 0 : *pMinDigits = nNum - nNeg;
103 0 : rValue = rValue.copy(nNum);
104 0 : return -1;
105 : }
106 : else
107 : {
108 0 : nNeg = 0;
109 0 : sal_Int32 nEnd = nNum = rValue.getLength() - 1;
110 0 : while ( nNum && CharClass::isAsciiNumeric( OUString(p[nNum]) ) )
111 0 : nNum--;
112 0 : if ( p[nNum] == '-' )
113 : {
114 0 : nNum--;
115 0 : nNeg = 1;
116 : }
117 0 : if ( nNum < nEnd - nNeg )
118 : { // number at the end
119 0 : nVal = rValue.copy( nNum + 1 ).toInt32();
120 : // any number with a leading zero sets the minimum number of digits
121 0 : if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
122 0 : *pMinDigits = nEnd - nNum - nNeg;
123 0 : rValue = rValue.copy(0, nNum + 1);
124 0 : return 1;
125 : }
126 : }
127 0 : nVal = 0;
128 0 : return 0;
129 : }
130 :
131 0 : OUString lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
132 : {
133 0 : if ( nMinDigits <= 1 )
134 0 : return OUString::number( nValue ); // simple case...
135 : else
136 : {
137 0 : OUString aStr = OUString::number( std::abs( nValue ) );
138 0 : if ( aStr.getLength() < nMinDigits )
139 : {
140 0 : OUStringBuffer aZero;
141 0 : comphelper::string::padToLength(aZero, nMinDigits - aStr.getLength(), '0');
142 0 : aStr = aZero.makeStringAndClear() + aStr;
143 : }
144 : // nMinDigits doesn't include the '-' sign -> add after inserting zeros
145 0 : if ( nValue < 0 )
146 0 : aStr = "-" + aStr;
147 0 : return aStr;
148 : }
149 : }
150 :
151 0 : void setSuffixCell(
152 : ScColumn& rColumn, SCROW nRow, sal_Int32 nValue, sal_uInt16 nDigits, const OUString& rSuffix,
153 : CellType eCellType, bool bIsOrdinalSuffix )
154 : {
155 0 : ScDocument& rDoc = rColumn.GetDoc();
156 0 : OUString aValue = lcl_ValueString(nValue, nDigits);
157 0 : if (!bIsOrdinalSuffix)
158 : {
159 0 : rColumn.SetRawString(nRow, aValue += rSuffix);
160 0 : return;
161 : }
162 :
163 0 : OUString aOrdinalSuffix = ScGlobal::GetOrdinalSuffix(nValue);
164 0 : if (eCellType != CELLTYPE_EDIT)
165 : {
166 0 : rColumn.SetRawString(nRow, aValue += aOrdinalSuffix);
167 0 : return;
168 : }
169 :
170 0 : EditEngine aEngine(rDoc.GetEnginePool());
171 0 : aEngine.SetEditTextObjectPool(rDoc.GetEditPool());
172 :
173 0 : SfxItemSet aAttr = aEngine.GetEmptyItemSet();
174 0 : aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
175 0 : aEngine.SetText( aValue );
176 : aEngine.QuickInsertText(
177 : aOrdinalSuffix,
178 0 : ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
179 :
180 : aEngine.QuickSetAttribs(
181 : aAttr,
182 0 : ESelection(0, aValue.getLength(), 0, aValue.getLength() + aOrdinalSuffix.getLength()));
183 :
184 : // Text object instance will be owned by the cell.
185 0 : rColumn.SetEditText(nRow, aEngine.CreateTextObject());
186 : }
187 :
188 : }
189 :
190 0 : void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
191 : FillCmd& rCmd, FillDateCmd& rDateCmd,
192 : double& rInc, sal_uInt16& rMinDigits,
193 : ScUserListData*& rListData, sal_uInt16& rListIndex)
194 : {
195 : OSL_ENSURE( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: invalid range" );
196 :
197 0 : rInc = 0.0;
198 0 : rMinDigits = 0;
199 0 : rListData = NULL;
200 0 : rCmd = FILL_SIMPLE;
201 0 : if ( (nScFillModeMouseModifier & KEY_MOD1) )
202 0 : return ; // Ctrl-key: Copy
203 :
204 : SCCOL nAddX;
205 : SCROW nAddY;
206 : SCSIZE nCount;
207 0 : if (nCol1 == nCol2)
208 : {
209 0 : nAddX = 0;
210 0 : nAddY = 1;
211 0 : nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
212 : }
213 : else
214 : {
215 0 : nAddX = 1;
216 0 : nAddY = 0;
217 0 : nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
218 : }
219 :
220 0 : SCCOL nCol = nCol1;
221 0 : SCROW nRow = nRow1;
222 :
223 0 : ScRefCellValue aFirstCell = GetCellValue(nCol, nRow);
224 0 : CellType eCellType = aFirstCell.meType;
225 :
226 0 : if (eCellType == CELLTYPE_VALUE)
227 : {
228 0 : sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
229 0 : bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
230 0 : if (bDate)
231 : {
232 0 : if (nCount > 1)
233 : {
234 : double nVal;
235 0 : Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
236 0 : Date aDate1 = aNullDate;
237 0 : nVal = aFirstCell.mfValue;
238 0 : aDate1 += (long)nVal;
239 0 : Date aDate2 = aNullDate;
240 0 : nVal = GetValue(nCol+nAddX, nRow+nAddY);
241 0 : aDate2 += (long)nVal;
242 0 : if ( aDate1 != aDate2 )
243 : {
244 0 : long nCmpInc = 0;
245 : FillDateCmd eType;
246 0 : long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
247 0 : long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
248 0 : long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
249 0 : if ( nDDiff )
250 : {
251 0 : eType = FILL_DAY;
252 0 : nCmpInc = aDate2 - aDate1;
253 : }
254 : else
255 : {
256 0 : eType = FILL_MONTH;
257 0 : nCmpInc = nMDiff + 12 * nYDiff;
258 : }
259 :
260 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
261 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
262 0 : bool bVal = true;
263 0 : for (sal_uInt16 i=1; i<nCount && bVal; i++)
264 : {
265 0 : ScRefCellValue aCell = GetCellValue(nCol,nRow);
266 0 : if (aCell.meType == CELLTYPE_VALUE)
267 : {
268 0 : nVal = aCell.mfValue;
269 0 : aDate2 = aNullDate + (long) nVal;
270 0 : if ( eType == FILL_DAY )
271 : {
272 0 : if ( aDate2-aDate1 != nCmpInc )
273 0 : bVal = false;
274 : }
275 : else
276 : {
277 0 : nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
278 0 : nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
279 0 : nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
280 0 : if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
281 0 : bVal = false;
282 : }
283 0 : aDate1 = aDate2;
284 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
285 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
286 : }
287 : else
288 0 : bVal = false; // kein Datum passt auch nicht
289 0 : }
290 0 : if (bVal)
291 : {
292 0 : if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
293 : {
294 0 : eType = FILL_YEAR;
295 0 : nCmpInc /= 12;
296 : }
297 0 : rCmd = FILL_DATE;
298 0 : rDateCmd = eType;
299 0 : rInc = nCmpInc;
300 : }
301 : }
302 : }
303 : else // single date -> increment by days
304 : {
305 0 : rCmd = FILL_DATE;
306 0 : rDateCmd = FILL_DAY;
307 0 : rInc = 1.0;
308 : }
309 : }
310 : else
311 : {
312 0 : if (nCount > 1)
313 : {
314 0 : double nVal1 = aFirstCell.mfValue;
315 0 : double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
316 0 : rInc = nVal2 - nVal1;
317 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
318 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
319 0 : bool bVal = true;
320 0 : for (sal_uInt16 i=1; i<nCount && bVal; i++)
321 : {
322 0 : ScRefCellValue aCell = GetCellValue(nCol,nRow);
323 0 : if (aCell.meType == CELLTYPE_VALUE)
324 : {
325 0 : nVal2 = aCell.mfValue;
326 0 : double nDiff = nVal2 - nVal1;
327 0 : if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
328 0 : bVal = false;
329 0 : nVal1 = nVal2;
330 : }
331 : else
332 0 : bVal = false;
333 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
334 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
335 0 : }
336 0 : if (bVal)
337 0 : rCmd = FILL_LINEAR;
338 : }
339 : }
340 : }
341 0 : else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
342 : {
343 0 : OUString aStr;
344 0 : GetString(nCol, nRow, aStr);
345 :
346 : // fdo#39500 don't deduce increment from multiple equal list entries
347 0 : bool bAllSame = true;
348 0 : for (sal_uInt16 i = 0; i < nCount; ++i)
349 : {
350 0 : OUString aTestStr;
351 0 : GetString(static_cast<SCCOL>(nCol + i* nAddX), static_cast<SCROW>(nRow + i * nAddY), aTestStr);
352 0 : if(aStr != aTestStr)
353 : {
354 0 : bAllSame = false;
355 0 : break;
356 : }
357 0 : }
358 0 : if(bAllSame && nCount > 1)
359 0 : return;
360 :
361 0 : rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
362 0 : if (rListData)
363 : {
364 0 : rListData->GetSubIndex(aStr, rListIndex);
365 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
366 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
367 0 : for (sal_uInt16 i=1; i<nCount && rListData; i++)
368 : {
369 0 : GetString(nCol, nRow, aStr);
370 0 : if (!rListData->GetSubIndex(aStr, rListIndex))
371 0 : rListData = NULL;
372 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
373 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
374 : }
375 : }
376 0 : else if ( nCount > 1 )
377 : {
378 : // pass rMinDigits to all DecompValueString calls
379 : // -> longest number defines rMinDigits
380 :
381 : sal_Int32 nVal1;
382 0 : short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
383 0 : if ( nFlag1 )
384 : {
385 : sal_Int32 nVal2;
386 0 : GetString( nCol+nAddX, nRow+nAddY, aStr );
387 0 : short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
388 0 : if ( nFlag1 == nFlag2 )
389 : {
390 0 : rInc = (double)nVal2 - (double)nVal1;
391 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
392 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
393 0 : bool bVal = true;
394 0 : for (sal_uInt16 i=1; i<nCount && bVal; i++)
395 : {
396 0 : ScRefCellValue aCell = GetCellValue(nCol, nRow);
397 0 : CellType eType = aCell.meType;
398 0 : if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
399 : {
400 0 : aStr = aCell.getString(pDocument);
401 0 : nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
402 0 : if ( nFlag1 == nFlag2 )
403 : {
404 0 : double nDiff = (double)nVal2 - (double)nVal1;
405 0 : if ( !::rtl::math::approxEqual( nDiff, rInc, 13 ) )
406 0 : bVal = false;
407 0 : nVal1 = nVal2;
408 : }
409 : else
410 0 : bVal = false;
411 : }
412 : else
413 0 : bVal = false;
414 0 : nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
415 0 : nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
416 0 : }
417 0 : if (bVal)
418 0 : rCmd = FILL_LINEAR;
419 : }
420 : }
421 : }
422 : else
423 : {
424 : // call DecompValueString to set rMinDigits
425 : sal_Int32 nDummy;
426 0 : lcl_DecompValueString( aStr, nDummy, &rMinDigits );
427 0 : }
428 0 : }
429 : }
430 :
431 0 : void ScTable::FillFormula(
432 : ScFormulaCell* pSrcCell, SCCOL nDestCol, SCROW nDestRow, bool bLast )
433 : {
434 :
435 0 : pDocument->SetNoListening( true ); // still the wrong reference
436 0 : ScAddress aAddr( nDestCol, nDestRow, nTab );
437 0 : ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
438 0 : aCol[nDestCol].SetFormulaCell(nDestRow, pDestCell);
439 :
440 0 : if ( bLast && pDestCell->GetMatrixFlag() )
441 : {
442 0 : ScAddress aOrg;
443 0 : if ( pDestCell->GetMatrixOrigin( aOrg ) )
444 : {
445 0 : if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
446 : {
447 0 : ScFormulaCell* pOrgCell = pDocument->GetFormulaCell(aOrg);
448 0 : if (pOrgCell && pOrgCell->GetMatrixFlag() == MM_FORMULA)
449 : {
450 : ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
451 0 : nDestCol - aOrg.Col() + 1,
452 0 : nDestRow - aOrg.Row() + 1 );
453 : }
454 : else
455 : {
456 : OSL_FAIL( "FillFormula: MatrixOrigin no forumla cell with MM_FORMULA" );
457 : }
458 : }
459 : else
460 : {
461 : OSL_FAIL( "FillFormula: MatrixOrigin bottom right" );
462 : }
463 : }
464 : else
465 : {
466 : OSL_FAIL( "FillFormula: no MatrixOrigin" );
467 : }
468 : }
469 0 : pDocument->SetNoListening( false );
470 0 : pDestCell->StartListeningTo( pDocument );
471 :
472 0 : }
473 :
474 0 : void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
475 : sal_uLong nFillCount, FillDir eFillDir, ScProgress* pProgress )
476 : {
477 0 : if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
478 0 : return;
479 :
480 :
481 : // Detect direction
482 :
483 :
484 0 : bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
485 0 : bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
486 :
487 0 : SCCOLROW nCol = 0;
488 0 : SCCOLROW nRow = 0;
489 0 : SCCOLROW& rInner = bVertical ? nRow : nCol; // loop variables
490 0 : SCCOLROW& rOuter = bVertical ? nCol : nRow;
491 : SCCOLROW nOStart;
492 : SCCOLROW nOEnd;
493 : SCCOLROW nIStart;
494 : SCCOLROW nIEnd;
495 : SCCOLROW nISrcStart;
496 : SCCOLROW nISrcEnd;
497 0 : ScRange aFillRange;
498 :
499 0 : if (bVertical)
500 : {
501 0 : nOStart = nCol1;
502 0 : nOEnd = nCol2;
503 0 : if (bPositive)
504 : {
505 0 : nISrcStart = nRow1;
506 0 : nISrcEnd = nRow2;
507 0 : nIStart = nRow2 + 1;
508 0 : nIEnd = nRow2 + nFillCount;
509 0 : aFillRange = ScRange(nCol1, nRow2+1, 0, nCol2, nRow2 + nFillCount, 0);
510 : }
511 : else
512 : {
513 0 : nISrcStart = nRow2;
514 0 : nISrcEnd = nRow1;
515 0 : nIStart = nRow1 - 1;
516 0 : nIEnd = nRow1 - nFillCount;
517 0 : aFillRange = ScRange(nCol1, nRow1-1, 0, nCol2, nRow2 - nFillCount, 0);
518 : }
519 : }
520 : else
521 : {
522 0 : nOStart = nRow1;
523 0 : nOEnd = nRow2;
524 0 : if (bPositive)
525 : {
526 0 : nISrcStart = nCol1;
527 0 : nISrcEnd = nCol2;
528 0 : nIStart = nCol2 + 1;
529 0 : nIEnd = nCol2 + nFillCount;
530 0 : aFillRange = ScRange(nCol2 + 1, nRow1, 0, nCol2 + nFillCount, nRow2, 0);
531 : }
532 : else
533 : {
534 0 : nISrcStart = nCol2;
535 0 : nISrcEnd = nCol1;
536 0 : nIStart = nCol1 - 1;
537 0 : nIEnd = nCol1 - nFillCount;
538 0 : aFillRange = ScRange(nCol1 - 1, nRow1, 0, nCol1 - nFillCount, nRow2, 0);
539 : }
540 : }
541 0 : sal_uLong nIMin = nIStart;
542 0 : sal_uLong nIMax = nIEnd;
543 0 : PutInOrder(nIMin,nIMax);
544 0 : bool bHasFiltered = IsDataFiltered(aFillRange);
545 :
546 0 : if (!bHasFiltered)
547 : {
548 0 : if (bVertical)
549 0 : DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
550 : else
551 0 : DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
552 : }
553 :
554 0 : sal_uLong nProgress = 0;
555 0 : if (pProgress)
556 0 : nProgress = pProgress->GetState();
557 :
558 :
559 : // execute
560 :
561 :
562 0 : sal_uLong nActFormCnt = 0;
563 0 : for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
564 : {
565 0 : sal_uLong nMaxFormCnt = 0; // for formulas
566 :
567 : // transfer attributes
568 :
569 0 : const ScPatternAttr* pSrcPattern = NULL;
570 0 : const ScStyleSheet* pStyleSheet = NULL;
571 0 : SCCOLROW nAtSrc = nISrcStart;
572 0 : ScPatternAttr* pNewPattern = NULL;
573 0 : bool bGetPattern = true;
574 0 : rInner = nIStart;
575 : while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
576 : {
577 0 : if (!ColHidden(nCol) && !RowHidden(nRow))
578 : {
579 0 : if ( bGetPattern )
580 : {
581 0 : delete pNewPattern;
582 0 : if (bVertical) // rInner&:=nRow, rOuter&:=nCol
583 0 : pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
584 : else // rInner&:=nCol, rOuter&:=nRow
585 0 : pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
586 0 : bGetPattern = false;
587 0 : pStyleSheet = pSrcPattern->GetStyleSheet();
588 : // do not transfer ATTR_MERGE / ATTR_MERGE_FLAG
589 0 : const SfxItemSet& rSet = pSrcPattern->GetItemSet();
590 0 : if ( rSet.GetItemState(ATTR_MERGE, false) == SFX_ITEM_SET
591 0 : || rSet.GetItemState(ATTR_MERGE_FLAG, false) == SFX_ITEM_SET )
592 : {
593 0 : pNewPattern = new ScPatternAttr( *pSrcPattern );
594 0 : SfxItemSet& rNewSet = pNewPattern->GetItemSet();
595 0 : rNewSet.ClearItem(ATTR_MERGE);
596 0 : rNewSet.ClearItem(ATTR_MERGE_FLAG);
597 : }
598 : else
599 0 : pNewPattern = NULL;
600 : }
601 :
602 0 : const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
603 0 : const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
604 :
605 0 : if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
606 : {
607 : // set all attributes at once (en bloc)
608 0 : if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
609 : {
610 : // Default is already present (DeleteArea)
611 0 : SCROW nY1 = static_cast<SCROW>(std::min( nIStart, nIEnd ));
612 0 : SCROW nY2 = static_cast<SCROW>(std::max( nIStart, nIEnd ));
613 0 : if ( pStyleSheet )
614 0 : aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
615 0 : if ( pNewPattern )
616 0 : aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
617 : else
618 0 : aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
619 :
620 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
621 : itr != itrEnd; ++itr)
622 : {
623 0 : ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
624 0 : ScRangeList aRange = pCondFormat->GetRange();
625 0 : aRange.Join(ScRange(nCol, nY1, nTab, nCol, nY2, nTab));
626 0 : pCondFormat->AddRange(aRange);
627 0 : }
628 : }
629 :
630 :
631 0 : break;
632 : }
633 :
634 0 : if ( bHasFiltered )
635 : DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
636 0 : static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
637 :
638 0 : if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
639 : {
640 : // Transfer template too
641 : //! Merge ApplyPattern to AttrArray ??
642 0 : if ( pStyleSheet )
643 0 : aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
644 :
645 : // Use ApplyPattern instead of SetPattern to keep old MergeFlags
646 0 : if ( pNewPattern )
647 0 : aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
648 : else
649 0 : aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
650 :
651 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
652 : itr != itrEnd; ++itr)
653 : {
654 0 : ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
655 0 : ScRangeList aRange = pCondFormat->GetRange();
656 0 : aRange.Join(ScRange(nCol, nRow, nTab, nCol, nRow, nTab));
657 0 : pCondFormat->AddRange(aRange);
658 0 : }
659 : }
660 :
661 0 : if (nAtSrc==nISrcEnd)
662 : {
663 0 : if ( nAtSrc != nISrcStart )
664 : { // More than one source cell
665 0 : nAtSrc = nISrcStart;
666 0 : bGetPattern = true;
667 : }
668 : }
669 0 : else if (bPositive)
670 : {
671 0 : ++nAtSrc;
672 0 : bGetPattern = true;
673 : }
674 : else
675 : {
676 0 : --nAtSrc;
677 0 : bGetPattern = true;
678 : }
679 : }
680 :
681 0 : if (rInner == nIEnd) break;
682 0 : if (bPositive) ++rInner; else --rInner;
683 : }
684 0 : if ( pNewPattern )
685 0 : delete pNewPattern;
686 :
687 : // Analyse
688 :
689 : FillCmd eFillCmd;
690 : FillDateCmd eDateCmd;
691 : double nInc;
692 : sal_uInt16 nMinDigits;
693 0 : ScUserListData* pListData = NULL;
694 : sal_uInt16 nListIndex;
695 0 : if (bVertical)
696 : FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
697 : static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
698 0 : nInc,nMinDigits, pListData,nListIndex);
699 : else
700 : FillAnalyse(nCol1,static_cast<SCROW>(nRow),
701 : nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
702 0 : nInc,nMinDigits, pListData,nListIndex);
703 :
704 0 : if (pListData)
705 : {
706 0 : sal_uInt16 nListCount = pListData->GetSubCount();
707 0 : if ( !bPositive )
708 : {
709 : // nListIndex of FillAnalyse points to the last entry -> adjust
710 0 : sal_uLong nSub = nISrcStart - nISrcEnd;
711 0 : for (sal_uLong i=0; i<nSub; i++)
712 : {
713 0 : if (nListIndex == 0) nListIndex = nListCount;
714 0 : --nListIndex;
715 : }
716 : }
717 :
718 0 : rInner = nIStart;
719 : while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720 : {
721 0 : if(!ColHidden(nCol) && !RowHidden(nRow))
722 : {
723 0 : if (bPositive)
724 : {
725 0 : ++nListIndex;
726 0 : if (nListIndex >= nListCount) nListIndex = 0;
727 : }
728 : else
729 : {
730 0 : if (nListIndex == 0) nListIndex = nListCount;
731 0 : --nListIndex;
732 : }
733 0 : aCol[nCol].SetRawString(static_cast<SCROW>(nRow), pListData->GetSubStr(nListIndex));
734 : }
735 :
736 0 : if (rInner == nIEnd) break;
737 0 : if (bPositive) ++rInner; else --rInner;
738 : }
739 0 : if(pProgress)
740 : {
741 0 : nProgress += nIMax - nIMin + 1;
742 0 : pProgress->SetStateOnPercent( nProgress );
743 0 : }
744 : }
745 0 : else if (eFillCmd == FILL_SIMPLE) // fill with pattern/sample
746 : {
747 : FillAutoSimple(
748 : nISrcStart, nISrcEnd, nIStart, nIEnd, rInner, nCol, nRow,
749 0 : nActFormCnt, nMaxFormCnt, bHasFiltered, bVertical, bPositive, pProgress, nProgress);
750 : }
751 : else
752 : {
753 0 : if (!bPositive)
754 0 : nInc = -nInc;
755 0 : double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
756 0 : if (bVertical)
757 : FillSeries( static_cast<SCCOL>(nCol), nRow1,
758 : static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
759 : eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
760 0 : pProgress );
761 : else
762 : FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
763 : static_cast<SCROW>(nRow), nFillCount, eFillDir,
764 : eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, false,
765 0 : pProgress );
766 0 : if (pProgress)
767 0 : nProgress = pProgress->GetState();
768 : }
769 :
770 0 : nActFormCnt += nMaxFormCnt;
771 0 : }
772 : }
773 :
774 0 : OUString ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
775 : {
776 0 : OUString aValue;
777 :
778 0 : SCCOL nCol1 = rSource.aStart.Col();
779 0 : SCROW nRow1 = rSource.aStart.Row();
780 0 : SCCOL nCol2 = rSource.aEnd.Col();
781 0 : SCROW nRow2 = rSource.aEnd.Row();
782 0 : bool bOk = true;
783 0 : long nIndex = 0;
784 0 : sal_uLong nSrcCount = 0;
785 0 : FillDir eFillDir = FILL_TO_BOTTOM;
786 0 : if ( nEndX == nCol2 && nEndY == nRow2 ) // empty
787 0 : bOk = false;
788 0 : else if ( nEndX == nCol2 ) // to up / down
789 : {
790 0 : nEndX = nCol2 = nCol1; // use only first column
791 0 : nSrcCount = nRow2 - nRow1 + 1;
792 0 : nIndex = ((long)nEndY) - nRow1; // can be negative
793 0 : if ( nEndY >= nRow1 )
794 0 : eFillDir = FILL_TO_BOTTOM;
795 : else
796 0 : eFillDir = FILL_TO_TOP;
797 : }
798 0 : else if ( nEndY == nRow2 ) // to left / right
799 : {
800 0 : nEndY = nRow2 = nRow1; // use only first row
801 0 : nSrcCount = nCol2 - nCol1 + 1;
802 0 : nIndex = ((long)nEndX) - nCol1; // can be negative
803 0 : if ( nEndX >= nCol1 )
804 0 : eFillDir = FILL_TO_RIGHT;
805 : else
806 0 : eFillDir = FILL_TO_LEFT;
807 : }
808 : else // direction not clear
809 0 : bOk = false;
810 :
811 0 : if ( bOk )
812 : {
813 : FillCmd eFillCmd;
814 : FillDateCmd eDateCmd;
815 : double nInc;
816 : sal_uInt16 nMinDigits;
817 0 : ScUserListData* pListData = NULL;
818 : sal_uInt16 nListIndex;
819 :
820 0 : FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
821 :
822 0 : if ( pListData ) // user defined list
823 : {
824 0 : sal_uInt16 nListCount = pListData->GetSubCount();
825 0 : if ( nListCount )
826 : {
827 0 : sal_uLong nSub = nSrcCount - 1; // nListIndex is from last source entry
828 0 : while ( nIndex < sal::static_int_cast<long>(nSub) )
829 0 : nIndex += nListCount;
830 0 : sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
831 0 : aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
832 : }
833 : }
834 0 : else if ( eFillCmd == FILL_SIMPLE ) // fill with pattern/sample
835 : {
836 0 : if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
837 : {
838 0 : long nBegin = 0;
839 0 : long nEnd = 0;
840 0 : if (nEndY > nRow1)
841 : {
842 0 : nBegin = nRow2+1;
843 0 : nEnd = nEndY;
844 : }
845 : else
846 : {
847 0 : nBegin = nEndY;
848 0 : nEnd = nRow1 -1;
849 : }
850 :
851 0 : long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
852 0 : long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
853 :
854 0 : if (nIndex > 0)
855 0 : nIndex = nIndex - nFiltered;
856 : else
857 0 : nIndex = nIndex + nFiltered;
858 : }
859 :
860 0 : long nPosIndex = nIndex;
861 0 : while ( nPosIndex < 0 )
862 0 : nPosIndex += nSrcCount;
863 0 : sal_uLong nPos = nPosIndex % nSrcCount;
864 0 : SCCOL nSrcX = nCol1;
865 0 : SCROW nSrcY = nRow1;
866 0 : if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
867 0 : nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
868 : else
869 0 : nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
870 :
871 0 : ScRefCellValue aCell = GetCellValue(nSrcX, nSrcY);
872 0 : if (!aCell.isEmpty())
873 : {
874 : sal_Int32 nDelta;
875 0 : if (nIndex >= 0)
876 0 : nDelta = nIndex / nSrcCount;
877 : else
878 0 : nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
879 :
880 0 : CellType eType = aCell.meType;
881 0 : switch ( eType )
882 : {
883 : case CELLTYPE_STRING:
884 : case CELLTYPE_EDIT:
885 : {
886 0 : aValue = aCell.getString(pDocument);
887 :
888 0 : if ( !(nScFillModeMouseModifier & KEY_MOD1) )
889 : {
890 : sal_Int32 nVal;
891 0 : sal_uInt16 nCellDigits = 0; // look at each source cell individually
892 0 : short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
893 0 : if ( nFlag < 0 )
894 : {
895 0 : if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
896 0 : aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
897 :
898 0 : aValue = lcl_ValueString( nVal + nDelta, nCellDigits ) + aValue;
899 : }
900 0 : else if ( nFlag > 0 )
901 0 : aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
902 : }
903 : }
904 0 : break;
905 : case CELLTYPE_VALUE:
906 : {
907 : // overflow is possible...
908 0 : double nVal = aCell.mfValue;
909 0 : if ( !(nScFillModeMouseModifier & KEY_MOD1) )
910 0 : nVal += (double) nDelta;
911 :
912 : Color* pColor;
913 0 : sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
914 0 : pDocument->GetFormatTable()->GetOutputString( nVal, nNumFmt, aValue, &pColor );
915 : }
916 0 : break;
917 : // not for formulas
918 : default:
919 : {
920 : // added to avoid warnings
921 : }
922 : }
923 0 : }
924 : }
925 0 : else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // values
926 : {
927 : bool bValueOk;
928 : double nStart;
929 0 : sal_Int32 nVal = 0;
930 0 : short nHeadNoneTail = 0;
931 0 : ScRefCellValue aCell = GetCellValue(nCol1, nRow1);
932 0 : if (!aCell.isEmpty())
933 : {
934 0 : CellType eType = aCell.meType;
935 0 : switch ( eType )
936 : {
937 : case CELLTYPE_STRING:
938 : case CELLTYPE_EDIT:
939 : {
940 0 : aValue = aCell.getString(pDocument);
941 0 : nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
942 0 : if ( nHeadNoneTail )
943 0 : nStart = (double)nVal;
944 : else
945 0 : nStart = 0.0;
946 : }
947 0 : break;
948 : case CELLTYPE_VALUE:
949 0 : nStart = aCell.mfValue;
950 0 : break;
951 : case CELLTYPE_FORMULA:
952 0 : nStart = aCell.mpFormula->GetValue();
953 0 : break;
954 : default:
955 0 : nStart = 0.0;
956 : }
957 : }
958 : else
959 0 : nStart = 0.0;
960 0 : if ( eFillCmd == FILL_LINEAR )
961 : {
962 0 : double nAdd = nInc;
963 0 : bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
964 0 : SubTotal::SafePlus( nStart, nAdd ) );
965 : }
966 : else // date
967 : {
968 0 : bValueOk = true;
969 0 : sal_uInt16 nDayOfMonth = 0;
970 0 : if ( nIndex < 0 )
971 : {
972 0 : nIndex = -nIndex;
973 0 : nInc = -nInc;
974 : }
975 0 : for (long i=0; i<nIndex; i++)
976 0 : IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
977 : }
978 :
979 0 : if (bValueOk)
980 : {
981 0 : if ( nHeadNoneTail )
982 : {
983 0 : if ( nHeadNoneTail < 0 )
984 : {
985 0 : if (aValue.equals( ScGlobal::GetOrdinalSuffix( nVal)))
986 0 : aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
987 :
988 0 : aValue = lcl_ValueString( (sal_Int32)nStart, nMinDigits ) + aValue;
989 : }
990 : else
991 0 : aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
992 : }
993 : else
994 : {
995 : //! Zahlformat je nach Index holen?
996 : Color* pColor;
997 0 : sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
998 0 : pDocument->GetFormatTable()->GetOutputString( nStart, nNumFmt, aValue, &pColor );
999 : }
1000 0 : }
1001 : }
1002 : else
1003 : {
1004 : OSL_FAIL("GetAutoFillPreview: invalid mode");
1005 : }
1006 : }
1007 :
1008 0 : return aValue;
1009 : }
1010 :
1011 0 : void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
1012 : {
1013 0 : if (eCmd == FILL_DAY)
1014 : {
1015 0 : rVal += nStep;
1016 0 : return;
1017 : }
1018 :
1019 : // class Date limits
1020 0 : const sal_uInt16 nMinYear = 1583;
1021 0 : const sal_uInt16 nMaxYear = 9956;
1022 :
1023 0 : long nInc = (long) nStep; // upper/lower limits ?
1024 0 : Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1025 0 : Date aDate = aNullDate;
1026 0 : aDate += (long)rVal;
1027 0 : switch (eCmd)
1028 : {
1029 : case FILL_WEEKDAY:
1030 : {
1031 0 : aDate += nInc;
1032 0 : DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1033 0 : if (nInc >= 0)
1034 : {
1035 0 : if (eWeekDay == SATURDAY)
1036 0 : aDate += 2;
1037 0 : else if (eWeekDay == SUNDAY)
1038 0 : aDate += 1;
1039 : }
1040 : else
1041 : {
1042 0 : if (eWeekDay == SATURDAY)
1043 0 : aDate -= 1;
1044 0 : else if (eWeekDay == SUNDAY)
1045 0 : aDate -= 2;
1046 : }
1047 : }
1048 0 : break;
1049 : case FILL_MONTH:
1050 : {
1051 0 : if ( nDayOfMonth == 0 )
1052 0 : nDayOfMonth = aDate.GetDay(); // init
1053 0 : long nMonth = aDate.GetMonth();
1054 0 : long nYear = aDate.GetYear();
1055 :
1056 0 : nMonth += nInc;
1057 :
1058 0 : if (nInc >= 0)
1059 : {
1060 0 : if (nMonth > 12)
1061 : {
1062 0 : long nYAdd = (nMonth-1) / 12;
1063 0 : nMonth -= nYAdd * 12;
1064 0 : nYear += nYAdd;
1065 : }
1066 : }
1067 : else
1068 : {
1069 0 : if (nMonth < 1)
1070 : {
1071 0 : long nYAdd = 1 - nMonth / 12; // positive
1072 0 : nMonth += nYAdd * 12;
1073 0 : nYear -= nYAdd;
1074 : }
1075 : }
1076 :
1077 0 : if ( nYear < nMinYear )
1078 0 : aDate = Date( 1,1, nMinYear );
1079 0 : else if ( nYear > nMaxYear )
1080 0 : aDate = Date( 31,12, nMaxYear );
1081 : else
1082 : {
1083 0 : aDate.SetMonth((sal_uInt16) nMonth);
1084 0 : aDate.SetYear((sal_uInt16) nYear);
1085 0 : aDate.SetDay( std::min( Date::GetDaysInMonth( nMonth, nYear), nDayOfMonth ) );
1086 : }
1087 : }
1088 0 : break;
1089 : case FILL_YEAR:
1090 : {
1091 0 : long nYear = aDate.GetYear();
1092 0 : nYear += nInc;
1093 0 : if ( nYear < nMinYear )
1094 0 : aDate = Date( 1,1, nMinYear );
1095 0 : else if ( nYear > nMaxYear )
1096 0 : aDate = Date( 31,12, nMaxYear );
1097 : else
1098 0 : aDate.SetYear((sal_uInt16) nYear);
1099 : }
1100 0 : break;
1101 : default:
1102 : {
1103 : // added to avoid warnings
1104 : }
1105 : }
1106 :
1107 0 : rVal = aDate - aNullDate;
1108 : }
1109 :
1110 : namespace {
1111 :
1112 0 : bool HiddenRowColumn(ScTable* pTable, SCCOLROW nRowColumn, bool bVertical, SCCOLROW& rLastPos)
1113 : {
1114 0 : bool bHidden = false;
1115 0 : if(bVertical)
1116 : {
1117 : SCROW nLast;
1118 0 : bHidden = pTable->RowHidden(nRowColumn, NULL, &nLast);
1119 0 : rLastPos = nLast;
1120 : }
1121 : else
1122 : {
1123 : SCCOL nLast;
1124 0 : bHidden = pTable->ColHidden(static_cast<SCCOL>(nRowColumn), NULL, &nLast);
1125 0 : rLastPos = nLast;
1126 : }
1127 0 : return bHidden;
1128 : }
1129 :
1130 : }
1131 :
1132 0 : void ScTable::FillFormulaVertical(
1133 : const ScFormulaCell& rSrcCell,
1134 : SCCOLROW& rInner, SCCOL nCol, SCROW nRow1, SCROW nRow2,
1135 : ScProgress* pProgress, sal_uLong& rProgress )
1136 : {
1137 0 : bool bHidden = false;
1138 0 : SCCOLROW nHiddenLast = -1;
1139 :
1140 0 : SCCOLROW nRowStart = -1, nRowEnd = -1;
1141 0 : std::vector<sc::RowSpan> aSpans;
1142 0 : for (rInner = nRow1; rInner <= nRow2; ++rInner)
1143 : {
1144 0 : if (rInner > nHiddenLast)
1145 0 : bHidden = HiddenRowColumn(this, rInner, true, nHiddenLast);
1146 :
1147 0 : if (bHidden)
1148 : {
1149 0 : if (nRowStart >= 0)
1150 : {
1151 0 : nRowEnd = rInner - 1;
1152 0 : aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd));
1153 0 : nRowStart = -1;
1154 : }
1155 0 : rInner = nHiddenLast;
1156 0 : continue;
1157 : }
1158 :
1159 0 : if (nRowStart < 0)
1160 0 : nRowStart = rInner;
1161 : }
1162 :
1163 0 : if (nRowStart >= 0)
1164 : {
1165 0 : nRowEnd = rInner - 1;
1166 0 : aSpans.push_back(sc::RowSpan(nRowStart, nRowEnd));
1167 : }
1168 :
1169 0 : aCol[nCol].DeleteRanges(aSpans, IDF_CONTENTS, false);
1170 0 : aCol[nCol].CloneFormulaCell(rSrcCell, aSpans);
1171 :
1172 0 : rProgress += nRow2 - nRow1 + 1;
1173 0 : if (pProgress)
1174 0 : pProgress->SetStateOnPercent(rProgress);
1175 0 : }
1176 :
1177 0 : void ScTable::FillSeriesSimple(
1178 : ScCellValue& rSrcCell, SCCOLROW& rInner, SCCOLROW nIMin, SCCOLROW nIMax,
1179 : SCCOLROW& rCol, SCCOLROW& rRow, bool bVertical, ScProgress* pProgress, sal_uLong& rProgress )
1180 : {
1181 0 : bool bHidden = false;
1182 0 : SCCOLROW nHiddenLast = -1;
1183 :
1184 0 : if (bVertical)
1185 : {
1186 0 : switch (rSrcCell.meType)
1187 : {
1188 : case CELLTYPE_FORMULA:
1189 : {
1190 : FillFormulaVertical(
1191 0 : *rSrcCell.mpFormula, rInner, rCol, nIMin, nIMax, pProgress, rProgress);
1192 : }
1193 0 : break;
1194 : default:
1195 : {
1196 0 : for (rInner = nIMin; rInner <= nIMax; ++rInner)
1197 : {
1198 0 : if (rInner > nHiddenLast)
1199 0 : bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
1200 :
1201 0 : if (bHidden)
1202 : {
1203 0 : rInner = nHiddenLast;
1204 0 : continue;
1205 : }
1206 :
1207 0 : ScAddress aDestPos(rCol, rRow, nTab);
1208 0 : rSrcCell.commit(aCol[rCol], aDestPos.Row());
1209 : }
1210 0 : rProgress += nIMax - nIMin + 1;
1211 0 : if (pProgress)
1212 0 : pProgress->SetStateOnPercent(rProgress);
1213 : }
1214 : }
1215 : }
1216 : else
1217 : {
1218 0 : switch (rSrcCell.meType)
1219 : {
1220 : case CELLTYPE_FORMULA:
1221 : {
1222 0 : for (rInner = nIMin; rInner <= nIMax; ++rInner)
1223 : {
1224 0 : if (rInner > nHiddenLast)
1225 0 : bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
1226 :
1227 0 : if (bHidden)
1228 0 : continue;
1229 :
1230 0 : FillFormula(rSrcCell.mpFormula, rCol, rRow, (rInner == nIMax));
1231 0 : if (pProgress)
1232 0 : pProgress->SetStateOnPercent(++rProgress);
1233 : }
1234 : }
1235 0 : break;
1236 : default:
1237 : {
1238 0 : for (rInner = nIMin; rInner <= nIMax; ++rInner)
1239 : {
1240 0 : if (rInner > nHiddenLast)
1241 0 : bHidden = HiddenRowColumn(this, rInner, bVertical, nHiddenLast);
1242 :
1243 0 : if (bHidden)
1244 0 : continue;
1245 :
1246 0 : ScAddress aDestPos(rCol, rRow, nTab);
1247 0 : rSrcCell.commit(aCol[rCol], aDestPos.Row());
1248 : }
1249 0 : rProgress += nIMax - nIMin + 1;
1250 0 : if (pProgress)
1251 0 : pProgress->SetStateOnPercent(rProgress);
1252 : }
1253 : }
1254 : }
1255 0 : }
1256 :
1257 0 : void ScTable::FillAutoSimple(
1258 : SCCOLROW nISrcStart, SCCOLROW nISrcEnd, SCCOLROW nIStart, SCCOLROW nIEnd,
1259 : SCCOLROW& rInner, SCCOLROW& rCol, SCCOLROW& rRow, sal_uLong nActFormCnt,
1260 : sal_uLong nMaxFormCnt, bool bHasFiltered, bool bVertical, bool bPositive,
1261 : ScProgress* pProgress, sal_uLong& rProgress )
1262 : {
1263 0 : SCCOLROW nSource = nISrcStart;
1264 : double nDelta;
1265 0 : if ( (nScFillModeMouseModifier & KEY_MOD1) )
1266 0 : nDelta = 0.0;
1267 0 : else if ( bPositive )
1268 0 : nDelta = 1.0;
1269 : else
1270 0 : nDelta = -1.0;
1271 0 : sal_uLong nFormulaCounter = nActFormCnt;
1272 0 : bool bGetCell = true;
1273 0 : sal_uInt16 nCellDigits = 0;
1274 0 : short nHeadNoneTail = 0;
1275 0 : sal_Int32 nStringValue = 0;
1276 0 : OUString aValue;
1277 0 : ScCellValue aSrcCell;
1278 0 : bool bIsOrdinalSuffix = false;
1279 :
1280 0 : bool bColHidden = false, bRowHidden = false;
1281 0 : SCCOL nColHiddenLast = -1;
1282 0 : SCROW nRowHiddenLast = -1;
1283 :
1284 0 : rInner = nIStart;
1285 : while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1286 : {
1287 0 : if (rCol > nColHiddenLast)
1288 0 : bColHidden = ColHidden(rCol, NULL, &nColHiddenLast);
1289 0 : if (rRow > nRowHiddenLast)
1290 0 : bRowHidden = RowHidden(rRow, NULL, &nRowHiddenLast);
1291 :
1292 0 : if (!bColHidden && !bRowHidden)
1293 : {
1294 0 : if ( bGetCell )
1295 : {
1296 0 : if (bVertical) // rInner&:=nRow, rOuter&:=nCol
1297 : {
1298 0 : aSrcCell = aCol[rCol].GetCellValue(nSource);
1299 0 : if (aSrcCell.meType == CELLTYPE_FORMULA)
1300 : {
1301 0 : FillFormulaVertical(*aSrcCell.mpFormula, rInner, rCol, nIStart, nIEnd, pProgress, rProgress);
1302 0 : return;
1303 : }
1304 : }
1305 : else // rInner&:=nCol, rOuter&:=nRow
1306 0 : aSrcCell = aCol[nSource].GetCellValue(rRow);
1307 :
1308 0 : bGetCell = false;
1309 0 : if (!aSrcCell.isEmpty())
1310 : {
1311 0 : switch (aSrcCell.meType)
1312 : {
1313 : case CELLTYPE_STRING:
1314 : case CELLTYPE_EDIT:
1315 0 : if (aSrcCell.meType == CELLTYPE_STRING)
1316 0 : aValue = aSrcCell.mpString->getString();
1317 : else
1318 0 : aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
1319 0 : if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered )
1320 : {
1321 0 : nCellDigits = 0; // look at each source cell individually
1322 : nHeadNoneTail = lcl_DecompValueString(
1323 0 : aValue, nStringValue, &nCellDigits );
1324 :
1325 : bIsOrdinalSuffix = aValue.equals(
1326 0 : ScGlobal::GetOrdinalSuffix( nStringValue));
1327 : }
1328 0 : break;
1329 : default:
1330 : {
1331 : // added to avoid warnings
1332 : }
1333 : }
1334 : }
1335 : }
1336 :
1337 0 : switch (aSrcCell.meType)
1338 : {
1339 : case CELLTYPE_VALUE:
1340 0 : aCol[rCol].SetValue(rRow, aSrcCell.mfValue + nDelta);
1341 0 : break;
1342 : case CELLTYPE_STRING:
1343 : case CELLTYPE_EDIT:
1344 0 : if ( nHeadNoneTail )
1345 : {
1346 : // #i48009# with the "nStringValue+(long)nDelta" expression within the
1347 : // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
1348 : // so nNextValue is now calculated ahead.
1349 0 : sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
1350 :
1351 0 : OUString aStr;
1352 0 : if ( nHeadNoneTail < 0 )
1353 : {
1354 : setSuffixCell(
1355 0 : aCol[rCol], rRow,
1356 : nNextValue, nCellDigits, aValue,
1357 0 : aSrcCell.meType, bIsOrdinalSuffix);
1358 : }
1359 : else
1360 : {
1361 0 : aStr = aValue + lcl_ValueString( nNextValue, nCellDigits );
1362 0 : aCol[rCol].SetRawString(rRow, aStr);
1363 0 : }
1364 : }
1365 : else
1366 0 : aSrcCell.commit(aCol[rCol], rRow);
1367 :
1368 0 : break;
1369 : case CELLTYPE_FORMULA :
1370 : FillFormula(
1371 0 : aSrcCell.mpFormula, rCol, rRow, (rInner == nIEnd));
1372 0 : if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
1373 0 : nMaxFormCnt = nFormulaCounter - nActFormCnt;
1374 0 : break;
1375 : default:
1376 : {
1377 : // added to avoid warnings
1378 : }
1379 : }
1380 :
1381 0 : if (nSource == nISrcEnd)
1382 : {
1383 0 : if ( nSource != nISrcStart )
1384 : { // More than one source cell
1385 0 : nSource = nISrcStart;
1386 0 : bGetCell = true;
1387 : }
1388 0 : if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1389 : {
1390 0 : if ( bPositive )
1391 0 : nDelta += 1.0;
1392 : else
1393 0 : nDelta -= 1.0;
1394 : }
1395 0 : nFormulaCounter = nActFormCnt;
1396 : }
1397 0 : else if (bPositive)
1398 : {
1399 0 : ++nSource;
1400 0 : bGetCell = true;
1401 : }
1402 : else
1403 : {
1404 0 : --nSource;
1405 0 : bGetCell = true;
1406 : }
1407 : }
1408 :
1409 0 : if (rInner == nIEnd) break;
1410 0 : if (bPositive) ++rInner; else --rInner;
1411 :
1412 : // Progress in inner loop only for expensive cells,
1413 : // and even then not individually for each one
1414 :
1415 0 : ++rProgress;
1416 0 : if ( pProgress && (aSrcCell.meType == CELLTYPE_FORMULA || aSrcCell.meType == CELLTYPE_EDIT) )
1417 0 : pProgress->SetStateOnPercent( rProgress );
1418 :
1419 : }
1420 0 : if (pProgress)
1421 0 : pProgress->SetStateOnPercent( rProgress );
1422 : }
1423 :
1424 0 : void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1425 : sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1426 : double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
1427 : bool bAttribs, ScProgress* pProgress )
1428 : {
1429 :
1430 : // Detect direction
1431 :
1432 :
1433 0 : bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1434 0 : bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1435 :
1436 0 : SCCOLROW nCol = 0;
1437 0 : SCCOLROW nRow = 0;
1438 0 : SCCOLROW& rInner = bVertical ? nRow : nCol; // loop variables
1439 0 : SCCOLROW& rOuter = bVertical ? nCol : nRow;
1440 : SCCOLROW nOStart;
1441 : SCCOLROW nOEnd;
1442 : SCCOLROW nIStart;
1443 : SCCOLROW nIEnd;
1444 : SCCOLROW nISource;
1445 0 : ScRange aFillRange;
1446 :
1447 0 : if (bVertical)
1448 : {
1449 0 : nFillCount += (nRow2 - nRow1);
1450 0 : if (nFillCount == 0)
1451 0 : return;
1452 0 : nOStart = nCol1;
1453 0 : nOEnd = nCol2;
1454 0 : if (bPositive)
1455 : {
1456 0 : nISource = nRow1;
1457 0 : nIStart = nRow1 + 1;
1458 0 : nIEnd = nRow1 + nFillCount;
1459 0 : aFillRange = ScRange(nCol1, nRow1 + 1, nTab, nCol2, nRow1 + nFillCount, nTab);
1460 : }
1461 : else
1462 : {
1463 0 : nISource = nRow2;
1464 0 : nIStart = nRow2 - 1;
1465 0 : nIEnd = nRow2 - nFillCount;
1466 0 : aFillRange = ScRange(nCol1, nRow2 -1, nTab, nCol2, nRow2 - nFillCount, nTab);
1467 : }
1468 : }
1469 : else
1470 : {
1471 0 : nFillCount += (nCol2 - nCol1);
1472 0 : if (nFillCount == 0)
1473 0 : return;
1474 0 : nOStart = nRow1;
1475 0 : nOEnd = nRow2;
1476 0 : if (bPositive)
1477 : {
1478 0 : nISource = nCol1;
1479 0 : nIStart = nCol1 + 1;
1480 0 : nIEnd = nCol1 + nFillCount;
1481 0 : aFillRange = ScRange(nCol1 + 1, nRow1, nTab, nCol1 + nFillCount, nRow2, nTab);
1482 : }
1483 : else
1484 : {
1485 0 : nISource = nCol2;
1486 0 : nIStart = nCol2 - 1;
1487 0 : nIEnd = nCol2 - nFillCount;
1488 0 : aFillRange = ScRange(nCol2 - 1, nRow1, nTab, nCol2 - nFillCount, nRow2, nTab);
1489 : }
1490 : }
1491 :
1492 0 : SCCOLROW nIMin = nIStart;
1493 0 : SCCOLROW nIMax = nIEnd;
1494 0 : PutInOrder(nIMin,nIMax);
1495 0 : sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1496 :
1497 0 : bool bIsFiltered = IsDataFiltered(aFillRange);
1498 0 : if (!bIsFiltered)
1499 : {
1500 0 : if (bVertical)
1501 0 : DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1502 : else
1503 0 : DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1504 : }
1505 :
1506 0 : sal_uLong nProgress = 0;
1507 0 : if (pProgress)
1508 0 : nProgress = pProgress->GetState();
1509 :
1510 :
1511 : // execute
1512 :
1513 :
1514 0 : sal_uLong nActFormCnt = 0;
1515 0 : for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1516 : {
1517 0 : rInner = nISource;
1518 :
1519 : // Source cell value. We need to clone the value since it may be inserted repeatedly.
1520 0 : ScCellValue aSrcCell = aCol[nCol].GetCellValue(static_cast<SCROW>(nRow));
1521 :
1522 0 : if (bAttribs)
1523 : {
1524 0 : const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1525 :
1526 0 : const ScCondFormatItem& rCondFormatItem = static_cast<const ScCondFormatItem&>(pSrcPattern->GetItem(ATTR_CONDITIONAL));
1527 0 : const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
1528 :
1529 0 : if (bVertical)
1530 : {
1531 : // if not filtered use the faster method
1532 : // hidden cols/rows should be skiped
1533 0 : if(!bIsFiltered)
1534 : {
1535 0 : aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1536 0 : static_cast<SCROW>(nIMax), *pSrcPattern, true );
1537 :
1538 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1539 : itr != itrEnd; ++itr)
1540 : {
1541 0 : ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1542 0 : ScRangeList aRange = pCondFormat->GetRange();
1543 0 : aRange.Join(ScRange(nCol, nIMin, nTab, nCol, nIMax, nTab));
1544 0 : pCondFormat->AddRange(aRange);
1545 0 : }
1546 : }
1547 : else
1548 : {
1549 0 : for(SCROW nAtRow = static_cast<SCROW>(nIMin); nAtRow <= static_cast<SCROW>(nIMax); ++nAtRow)
1550 : {
1551 0 : if(!RowHidden(nAtRow))
1552 : {
1553 0 : aCol[nCol].SetPatternArea( static_cast<SCROW>(nAtRow),
1554 0 : static_cast<SCROW>(nAtRow), *pSrcPattern, true);
1555 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1556 : itr != itrEnd; ++itr)
1557 : {
1558 0 : ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1559 0 : ScRangeList aRange = pCondFormat->GetRange();
1560 0 : aRange.Join(ScRange(nCol, nAtRow, nTab, nCol, nAtRow, nTab));
1561 0 : pCondFormat->AddRange(aRange);
1562 0 : }
1563 : }
1564 : }
1565 :
1566 : }
1567 : }
1568 : else
1569 0 : for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1570 0 : if(!ColHidden(nAtCol))
1571 : {
1572 0 : aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, true);
1573 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatIndex.begin(), itrEnd = rCondFormatIndex.end();
1574 : itr != itrEnd; ++itr)
1575 : {
1576 0 : ScConditionalFormat* pCondFormat = mpCondFormatList->GetFormat(*itr);
1577 0 : ScRangeList aRange = pCondFormat->GetRange();
1578 0 : aRange.Join(ScRange(nAtCol, static_cast<SCROW>(nRow), nTab, nAtCol, static_cast<SCROW>(nRow), nTab));
1579 0 : pCondFormat->AddRange(aRange);
1580 0 : }
1581 : }
1582 : }
1583 :
1584 0 : if (!aSrcCell.isEmpty())
1585 : {
1586 0 : CellType eCellType = aSrcCell.meType;
1587 :
1588 0 : if (eFillCmd == FILL_SIMPLE) // copy
1589 : {
1590 0 : FillSeriesSimple(aSrcCell, rInner, nIMin, nIMax, nCol, nRow, bVertical, pProgress, nProgress);
1591 : }
1592 0 : else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1593 : {
1594 : double nStartVal;
1595 0 : if (eCellType == CELLTYPE_VALUE)
1596 0 : nStartVal = aSrcCell.mfValue;
1597 : else
1598 0 : nStartVal = aSrcCell.mpFormula->GetValue();
1599 0 : double nVal = nStartVal;
1600 0 : long nIndex = 0;
1601 :
1602 0 : bool bError = false;
1603 0 : bool bOverflow = false;
1604 :
1605 0 : sal_uInt16 nDayOfMonth = 0;
1606 0 : rInner = nIStart;
1607 : while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1608 : {
1609 0 : if(!ColHidden(nCol) && !RowHidden(nRow))
1610 : {
1611 0 : if (!bError && !bOverflow)
1612 : {
1613 0 : switch (eFillCmd)
1614 : {
1615 : case FILL_LINEAR:
1616 : {
1617 : // use multiplication instead of repeated addition
1618 : // to avoid accumulating rounding errors
1619 0 : nVal = nStartVal;
1620 0 : double nAdd = nStepValue;
1621 0 : if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1622 0 : !SubTotal::SafePlus( nVal, nAdd ) )
1623 0 : bError = true;
1624 : }
1625 0 : break;
1626 : case FILL_GROWTH:
1627 0 : if (!SubTotal::SafeMult(nVal, nStepValue))
1628 0 : bError = true;
1629 0 : break;
1630 : case FILL_DATE:
1631 0 : if (fabs(nVal) > _D_MAX_LONG_)
1632 0 : bError = true;
1633 : else
1634 0 : IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1635 0 : break;
1636 : default:
1637 : {
1638 : // added to avoid warnings
1639 : }
1640 : }
1641 :
1642 0 : if (nStepValue >= 0)
1643 : {
1644 0 : if (nVal > nMaxValue) // target value reached ?
1645 : {
1646 0 : nVal = nMaxValue;
1647 0 : bOverflow = true;
1648 : }
1649 : }
1650 : else
1651 : {
1652 0 : if (nVal < nMaxValue)
1653 : {
1654 0 : nVal = nMaxValue;
1655 0 : bOverflow = true;
1656 : }
1657 : }
1658 : }
1659 :
1660 0 : if (bError)
1661 0 : aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1662 0 : else if (bOverflow)
1663 0 : aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
1664 : else
1665 0 : aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1666 : }
1667 :
1668 0 : if (rInner == nIEnd)
1669 0 : break;
1670 0 : if (bPositive)
1671 : {
1672 0 : ++rInner;
1673 : }
1674 : else
1675 : {
1676 0 : --rInner;
1677 : }
1678 : }
1679 0 : nProgress += nIMax - nIMin + 1;
1680 0 : if(pProgress)
1681 0 : pProgress->SetStateOnPercent( nProgress );
1682 : }
1683 0 : else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1684 : {
1685 0 : if ( nStepValue >= 0 )
1686 : {
1687 0 : if ( nMaxValue >= (double)LONG_MAX )
1688 0 : nMaxValue = (double)LONG_MAX - 1;
1689 : }
1690 : else
1691 : {
1692 0 : if ( nMaxValue <= (double)LONG_MIN )
1693 0 : nMaxValue = (double)LONG_MIN + 1;
1694 : }
1695 0 : OUString aValue;
1696 0 : if (eCellType == CELLTYPE_STRING)
1697 0 : aValue = aSrcCell.mpString->getString();
1698 : else
1699 0 : aValue = ScEditUtil::GetString(*aSrcCell.mpEditText, pDocument);
1700 : sal_Int32 nStringValue;
1701 0 : sal_uInt16 nMinDigits = nArgMinDigits;
1702 0 : short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1703 0 : if ( nHeadNoneTail )
1704 : {
1705 0 : double nStartVal = (double)nStringValue;
1706 0 : double nVal = nStartVal;
1707 0 : long nIndex = 0;
1708 0 : bool bError = false;
1709 0 : bool bOverflow = false;
1710 :
1711 : bool bIsOrdinalSuffix = aValue.equals( ScGlobal::GetOrdinalSuffix(
1712 0 : (sal_Int32)nStartVal));
1713 :
1714 0 : rInner = nIStart;
1715 : while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1716 : {
1717 0 : if(!ColHidden(nCol) && !RowHidden(nRow))
1718 : {
1719 0 : if (!bError && !bOverflow)
1720 : {
1721 0 : switch (eFillCmd)
1722 : {
1723 : case FILL_LINEAR:
1724 : {
1725 : // use multiplication instead of repeated addition
1726 : // to avoid accumulating rounding errors
1727 0 : nVal = nStartVal;
1728 0 : double nAdd = nStepValue;
1729 0 : if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1730 0 : !SubTotal::SafePlus( nVal, nAdd ) )
1731 0 : bError = true;
1732 : }
1733 0 : break;
1734 : case FILL_GROWTH:
1735 0 : if (!SubTotal::SafeMult(nVal, nStepValue))
1736 0 : bError = true;
1737 0 : break;
1738 : default:
1739 : {
1740 : // added to avoid warnings
1741 : }
1742 : }
1743 :
1744 0 : if (nStepValue >= 0)
1745 : {
1746 0 : if (nVal > nMaxValue) // target value reached ?
1747 : {
1748 0 : nVal = nMaxValue;
1749 0 : bOverflow = true;
1750 : }
1751 : }
1752 : else
1753 : {
1754 0 : if (nVal < nMaxValue)
1755 : {
1756 0 : nVal = nMaxValue;
1757 0 : bOverflow = true;
1758 : }
1759 : }
1760 : }
1761 :
1762 0 : if (bError)
1763 0 : aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1764 0 : else if (bOverflow)
1765 0 : aCol[nCol].SetError(static_cast<SCROW>(nRow), errIllegalFPOperation);
1766 : else
1767 : {
1768 0 : nStringValue = (sal_Int32)nVal;
1769 0 : OUString aStr;
1770 0 : if ( nHeadNoneTail < 0 )
1771 : {
1772 : setSuffixCell(
1773 0 : aCol[nCol], static_cast<SCROW>(nRow),
1774 : nStringValue, nMinDigits, aValue,
1775 0 : eCellType, bIsOrdinalSuffix);
1776 : }
1777 : else
1778 : {
1779 0 : aStr = aValue;
1780 0 : aStr += lcl_ValueString( nStringValue, nMinDigits );
1781 0 : aCol[nCol].SetRawString(static_cast<SCROW>(nRow), aStr);
1782 0 : }
1783 : }
1784 : }
1785 :
1786 0 : if (rInner == nIEnd) break;
1787 0 : if (bPositive) ++rInner; else --rInner;
1788 0 : }
1789 : }
1790 0 : if(pProgress)
1791 : {
1792 0 : nProgress += nIMax - nIMin + 1;
1793 0 : pProgress->SetStateOnPercent( nProgress );
1794 0 : }
1795 : }
1796 : }
1797 0 : else if(pProgress)
1798 : {
1799 0 : nProgress += nIMax - nIMin + 1;
1800 0 : pProgress->SetStateOnPercent( nProgress );
1801 : }
1802 0 : ++nActFormCnt;
1803 0 : }
1804 : }
1805 :
1806 0 : void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1807 : sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1808 : double nStepValue, double nMaxValue, ScProgress* pProgress)
1809 : {
1810 0 : if (eFillCmd == FILL_AUTO)
1811 0 : FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, pProgress);
1812 : else
1813 : FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1814 0 : eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, true, pProgress);
1815 0 : }
1816 :
1817 :
1818 0 : void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1819 : const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
1820 : {
1821 0 : ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
1822 0 : ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
1823 0 : if (pData)
1824 : {
1825 0 : ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1826 : }
1827 0 : }
1828 :
1829 0 : void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1830 : sal_uInt16 nFormatNo )
1831 : {
1832 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1833 : {
1834 0 : ScAutoFormat& rFormat = *ScGlobal::GetOrCreateAutoFormat();
1835 0 : ScAutoFormatData* pData = rFormat.findByIndex(nFormatNo);
1836 0 : if (pData)
1837 : {
1838 : ScPatternAttr* pPatternAttrs[16];
1839 0 : for (sal_uInt8 i = 0; i < 16; ++i)
1840 : {
1841 0 : pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1842 0 : pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1843 : }
1844 :
1845 0 : SCCOL nCol = nStartCol;
1846 0 : SCROW nRow = nStartRow;
1847 0 : sal_uInt16 nIndex = 0;
1848 : // Left top corner
1849 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1850 : // Left column
1851 0 : if (pData->IsEqualData(4, 8))
1852 0 : AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1853 : else
1854 : {
1855 0 : nIndex = 4;
1856 0 : for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1857 : {
1858 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1859 0 : if (nIndex == 4)
1860 0 : nIndex = 8;
1861 : else
1862 0 : nIndex = 4;
1863 : }
1864 : }
1865 : // Left bottom corner
1866 0 : nRow = nEndRow;
1867 0 : nIndex = 12;
1868 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1869 : // Right top corner
1870 0 : nCol = nEndCol;
1871 0 : nRow = nStartRow;
1872 0 : nIndex = 3;
1873 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1874 : // Right column
1875 0 : if (pData->IsEqualData(7, 11))
1876 0 : AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1877 : else
1878 : {
1879 0 : nIndex = 7;
1880 0 : for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1881 : {
1882 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1883 0 : if (nIndex == 7)
1884 0 : nIndex = 11;
1885 : else
1886 0 : nIndex = 7;
1887 : }
1888 : }
1889 : // Right bottom corner
1890 0 : nRow = nEndRow;
1891 0 : nIndex = 15;
1892 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1893 0 : nRow = nStartRow;
1894 0 : nIndex = 1;
1895 0 : for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1896 : {
1897 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1898 0 : if (nIndex == 1)
1899 0 : nIndex = 2;
1900 : else
1901 0 : nIndex = 1;
1902 : }
1903 : // Bottom row
1904 0 : nRow = nEndRow;
1905 0 : nIndex = 13;
1906 0 : for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1907 : {
1908 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1909 0 : if (nIndex == 13)
1910 0 : nIndex = 14;
1911 : else
1912 0 : nIndex = 13;
1913 : }
1914 : // Boddy
1915 0 : if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1916 0 : AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1917 : else
1918 : {
1919 0 : if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1920 : {
1921 0 : nIndex = 5;
1922 0 : for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1923 : {
1924 0 : AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1925 0 : if (nIndex == 5)
1926 0 : nIndex = 6;
1927 : else
1928 0 : nIndex = 5;
1929 : }
1930 : }
1931 : else
1932 : {
1933 0 : nIndex = 5;
1934 0 : for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1935 : {
1936 0 : for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1937 : {
1938 0 : AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1939 0 : if ((nIndex == 5) || (nIndex == 9))
1940 : {
1941 0 : if (nIndex == 5)
1942 0 : nIndex = 9;
1943 : else
1944 0 : nIndex = 5;
1945 : }
1946 : else
1947 : {
1948 0 : if (nIndex == 6)
1949 0 : nIndex = 10;
1950 : else
1951 0 : nIndex = 6;
1952 : }
1953 : } // for nRow
1954 0 : if ((nIndex == 5) || (nIndex == 9))
1955 0 : nIndex = 6;
1956 : else
1957 0 : nIndex = 5;
1958 : } // for nCol
1959 : } // if not equal Column
1960 : } // if not all equal
1961 :
1962 0 : for (sal_uInt8 j = 0; j < 16; ++j)
1963 0 : delete pPatternAttrs[j];
1964 : } // if AutoFormatData != NULL
1965 : } // if ValidColRow
1966 0 : }
1967 :
1968 0 : void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
1969 : {
1970 0 : sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
1971 0 : ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1972 0 : rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1973 0 : }
1974 :
1975 : #define LF_LEFT 1
1976 : #define LF_TOP 2
1977 : #define LF_RIGHT 4
1978 : #define LF_BOTTOM 8
1979 : #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1980 :
1981 0 : void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
1982 : {
1983 0 : const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1984 0 : const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1985 0 : const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1986 0 : const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1987 0 : const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1988 :
1989 0 : SvxBoxItem aBox( ATTR_BORDER );
1990 0 : if (nFlags & LF_LEFT)
1991 : {
1992 0 : if (pLeftBox)
1993 : {
1994 0 : if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1995 0 : aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1996 : else
1997 0 : aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1998 : }
1999 : else
2000 0 : aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
2001 : }
2002 0 : if (nFlags & LF_TOP)
2003 : {
2004 0 : if (pTopBox)
2005 : {
2006 0 : if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
2007 0 : aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
2008 : else
2009 0 : aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
2010 : }
2011 : else
2012 0 : aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
2013 : }
2014 0 : if (nFlags & LF_RIGHT)
2015 : {
2016 0 : if (pRightBox)
2017 : {
2018 0 : if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
2019 0 : aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
2020 : else
2021 0 : aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
2022 : }
2023 : else
2024 0 : aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
2025 : }
2026 0 : if (nFlags & LF_BOTTOM)
2027 : {
2028 0 : if (pBottomBox)
2029 : {
2030 0 : if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
2031 0 : aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
2032 : else
2033 0 : aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
2034 : }
2035 : else
2036 0 : aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
2037 : }
2038 0 : rData.PutItem( nIndex, aBox );
2039 0 : }
2040 :
2041 0 : void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
2042 : {
2043 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2044 : {
2045 0 : if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
2046 : {
2047 : // Left top corner
2048 0 : GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
2049 0 : GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
2050 : // Left column
2051 0 : GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
2052 0 : GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
2053 0 : GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
2054 0 : if (nEndRow - nStartRow >= 4)
2055 0 : GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
2056 : else
2057 0 : rData.CopyItem( 8, 4, ATTR_BORDER );
2058 : // Left bottom corner
2059 0 : GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
2060 0 : GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
2061 : // Right top corner
2062 0 : GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
2063 0 : GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
2064 : // Right column
2065 0 : GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
2066 0 : GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
2067 0 : GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
2068 0 : if (nEndRow - nStartRow >= 4)
2069 0 : GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
2070 : else
2071 0 : rData.CopyItem( 11, 7, ATTR_BORDER );
2072 : // Right bottom corner
2073 0 : GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
2074 0 : GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
2075 : // Top row
2076 0 : GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
2077 0 : GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
2078 0 : GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
2079 0 : if (nEndCol - nStartCol >= 4)
2080 0 : GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
2081 : else
2082 0 : rData.CopyItem( 2, 1, ATTR_BORDER );
2083 : // Bottom row
2084 0 : GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
2085 0 : GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
2086 0 : GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
2087 0 : if (nEndCol - nStartCol >= 4)
2088 0 : GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
2089 : else
2090 0 : rData.CopyItem( 14, 13, ATTR_BORDER );
2091 : // Body
2092 0 : GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
2093 0 : GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
2094 0 : GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
2095 0 : GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
2096 0 : GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
2097 0 : if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
2098 : {
2099 0 : GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
2100 0 : GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
2101 0 : GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
2102 : }
2103 : else
2104 : {
2105 0 : rData.CopyItem( 6, 5, ATTR_BORDER );
2106 0 : rData.CopyItem( 9, 5, ATTR_BORDER );
2107 0 : rData.CopyItem( 10, 5, ATTR_BORDER );
2108 : }
2109 : }
2110 : }
2111 0 : }
2112 :
2113 0 : void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
2114 : {
2115 0 : if (ValidColRow(nCol, nRow))
2116 0 : aCol[nCol].SetError( nRow, nError );
2117 0 : }
2118 :
2119 0 : void ScTable::UpdateInsertTabAbs(SCTAB nTable)
2120 : {
2121 0 : for (SCCOL i=0; i <= MAXCOL; i++)
2122 0 : aCol[i].UpdateInsertTabAbs(nTable);
2123 0 : }
2124 :
2125 0 : bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, bool bInSel,
2126 : const ScMarkData& rMark) const
2127 : {
2128 0 : if (rRow == MAXROW+2) // end of table
2129 : {
2130 0 : rRow = 0;
2131 0 : rCol = 0;
2132 : }
2133 : else
2134 : {
2135 0 : rRow++;
2136 0 : if (rRow == MAXROW+1)
2137 : {
2138 0 : rCol++;
2139 0 : rRow = 0;
2140 : }
2141 : }
2142 0 : if (rCol == MAXCOL+1)
2143 0 : return true;
2144 : else
2145 : {
2146 0 : bool bStop = false;
2147 0 : while (!bStop)
2148 : {
2149 0 : if (ValidCol(rCol))
2150 : {
2151 0 : bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
2152 0 : if (bStop)
2153 0 : return true;
2154 : else /*if (rRow == MAXROW+1) */
2155 : {
2156 0 : rCol++;
2157 0 : rRow = 0;
2158 : }
2159 : }
2160 : else
2161 0 : return true;
2162 : }
2163 : }
2164 0 : return false;
2165 : }
2166 :
2167 0 : bool ScTable::TestTabRefAbs(SCTAB nTable) const
2168 : {
2169 0 : for (SCCOL i=0; i <= MAXCOL; i++)
2170 0 : if (aCol[i].TestTabRefAbs(nTable))
2171 0 : return true;
2172 0 : return false;
2173 : }
2174 :
2175 0 : void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt )
2176 : {
2177 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
2178 0 : aCol[i].CompileDBFormula(rCxt);
2179 0 : }
2180 :
2181 0 : void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString )
2182 : {
2183 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
2184 0 : aCol[i].CompileDBFormula(rCxt, bCreateFormulaString);
2185 0 : }
2186 :
2187 0 : void ScTable::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt )
2188 : {
2189 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
2190 0 : aCol[i].CompileColRowNameFormula(rCxt);
2191 0 : }
2192 :
2193 0 : SCSIZE ScTable::GetPatternCount( SCCOL nCol ) const
2194 : {
2195 0 : if( ValidCol( nCol ) )
2196 0 : return aCol[nCol].GetPatternCount();
2197 : else
2198 0 : return 0;
2199 : }
2200 :
2201 0 : SCSIZE ScTable::GetPatternCount( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
2202 : {
2203 0 : if( ValidCol( nCol ) && ValidRow( nRow1 ) && ValidRow( nRow2 ) )
2204 0 : return aCol[nCol].GetPatternCount( nRow1, nRow2 );
2205 : else
2206 0 : return 0;
2207 : }
2208 :
2209 0 : bool ScTable::ReservePatternCount( SCCOL nCol, SCSIZE nReserve )
2210 : {
2211 0 : if( ValidCol( nCol ) )
2212 0 : return aCol[nCol].ReservePatternCount( nReserve );
2213 : else
2214 0 : return false;
2215 0 : }
2216 :
2217 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|