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