1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 // INCLUDE --------------------------------------------------------------- 30 31 #include <tools/debug.hxx> 32 33 #include "consoli.hxx" 34 #include "document.hxx" 35 #include "olinetab.hxx" 36 #include "globstr.hrc" 37 #include "subtotal.hxx" 38 #include "formula/errorcodes.hxx" 39 #include "cell.hxx" 40 41 #include <math.h> 42 #include <string.h> 43 44 #define SC_CONS_NOTFOUND -1 45 46 // STATIC DATA ----------------------------------------------------------- 47 48 /* Strings bei Gelegenheit ganz raus... 49 static sal_uInt16 nFuncRes[] = { // Reihenfolge wie bei enum ScSubTotalFunc 50 0, // none 51 STR_PIVOTFUNC_AVG, 52 STR_PIVOTFUNC_COUNT, 53 STR_PIVOTFUNC_COUNT2, 54 STR_PIVOTFUNC_MAX, 55 STR_PIVOTFUNC_MIN, 56 STR_PIVOTFUNC_PROD, 57 STR_PIVOTFUNC_STDDEV, 58 STR_PIVOTFUNC_STDDEV2, 59 STR_PIVOTFUNC_SUM, 60 STR_PIVOTFUNC_VAR, 61 STR_PIVOTFUNC_VAR2 }; 62 */ 63 64 static OpCode eOpCodeTable[] = { // Reihenfolge wie bei enum ScSubTotalFunc 65 ocBad, // none 66 ocAverage, 67 ocCount, 68 ocCount2, 69 ocMax, 70 ocMin, 71 ocProduct, 72 ocStDev, 73 ocStDevP, 74 ocSum, 75 ocVar, 76 ocVarP }; 77 78 // ----------------------------------------------------------------------- 79 80 void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab ) 81 { 82 ScReferenceEntry* pOldData = pData; 83 pData = new ScReferenceEntry[ nFullSize+1 ]; 84 if (pOldData) 85 { 86 memmove( pData, pOldData, nCount * sizeof(ScReferenceEntry) ); 87 delete[] pOldData; 88 } 89 while (nCount < nFullSize) 90 { 91 pData[nCount].nCol = SC_CONS_NOTFOUND; 92 pData[nCount].nRow = SC_CONS_NOTFOUND; 93 pData[nCount].nTab = SC_CONS_NOTFOUND; 94 ++nCount; 95 } 96 pData[nCount].nCol = nCol; 97 pData[nCount].nRow = nRow; 98 pData[nCount].nTab = nTab; 99 ++nCount; 100 nFullSize = nCount; 101 } 102 103 template< typename T > 104 void lcl_AddString( String**& pData, T& nCount, const String& rInsert ) 105 { 106 String** pOldData = pData; 107 pData = new String*[ nCount+1 ]; 108 if (pOldData) 109 { 110 memmove( pData, pOldData, nCount * sizeof(String*) ); 111 delete[] pOldData; 112 } 113 pData[nCount] = new String(rInsert); 114 ++nCount; 115 } 116 117 // ----------------------------------------------------------------------- 118 119 ScConsData::ScConsData() : 120 eFunction(SUBTOTAL_FUNC_SUM), 121 bReference(sal_False), 122 bColByName(sal_False), 123 bRowByName(sal_False), 124 bSubTitles(sal_False), 125 nColCount(0), 126 nRowCount(0), 127 ppUsed(NULL), 128 ppSum(NULL), 129 ppCount(NULL), 130 ppSumSqr(NULL), 131 ppRefs(NULL), 132 ppColHeaders(NULL), 133 ppRowHeaders(NULL), 134 nDataCount(0), 135 nTitleCount(0), 136 ppTitles(NULL), 137 ppTitlePos(NULL), 138 bCornerUsed(sal_False) 139 { 140 } 141 142 ScConsData::~ScConsData() 143 { 144 DeleteData(); 145 } 146 147 148 #define DELETEARR(ppArray,nCount) \ 149 { \ 150 sal_uLong i; \ 151 if (ppArray) \ 152 for(i=0; i<nCount; i++) \ 153 delete[] ppArray[i]; \ 154 delete[] ppArray; \ 155 ppArray = NULL; \ 156 } 157 158 #define DELETESTR(ppArray,nCount) \ 159 { \ 160 sal_uLong i; \ 161 if (ppArray) \ 162 for(i=0; i<nCount; i++) \ 163 delete ppArray[i]; \ 164 delete[] ppArray; \ 165 ppArray = NULL; \ 166 } 167 168 void ScConsData::DeleteData() 169 { 170 if (ppRefs) 171 { 172 for (SCSIZE i=0; i<nColCount; i++) 173 { 174 for (SCSIZE j=0; j<nRowCount; j++) 175 if (ppUsed[i][j]) 176 ppRefs[i][j].Clear(); 177 delete[] ppRefs[i]; 178 } 179 delete[] ppRefs; 180 ppRefs = NULL; 181 } 182 183 // DELETEARR( ppData1, nColCount ); 184 // DELETEARR( ppData2, nColCount ); 185 DELETEARR( ppCount, nColCount ); 186 DELETEARR( ppSum, nColCount ); 187 DELETEARR( ppSumSqr,nColCount ); 188 DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!! 189 DELETEARR( ppTitlePos, nRowCount ); 190 DELETESTR( ppColHeaders, nColCount ); 191 DELETESTR( ppRowHeaders, nRowCount ); 192 DELETESTR( ppTitles, nTitleCount ); 193 nTitleCount = 0; 194 nDataCount = 0; 195 196 if (bColByName) nColCount = 0; // sonst stimmt ppColHeaders nicht 197 if (bRowByName) nRowCount = 0; 198 199 bCornerUsed = sal_False; 200 aCornerText.Erase(); 201 } 202 203 #undef DELETEARR 204 #undef DELETESTR 205 206 void ScConsData::InitData( sal_Bool bDelete ) 207 { 208 if (bDelete) 209 DeleteData(); 210 211 if (bReference && nColCount && !ppRefs) 212 { 213 ppRefs = new ScReferenceList*[nColCount]; 214 for (SCSIZE i=0; i<nColCount; i++) 215 ppRefs[i] = new ScReferenceList[nRowCount]; 216 } 217 else if (nColCount && !ppCount) 218 { 219 ppCount = new double*[nColCount]; 220 ppSum = new double*[nColCount]; 221 ppSumSqr = new double*[nColCount]; 222 for (SCSIZE i=0; i<nColCount; i++) 223 { 224 ppCount[i] = new double[nRowCount]; 225 ppSum[i] = new double[nRowCount]; 226 ppSumSqr[i] = new double[nRowCount]; 227 } 228 } 229 230 if (nColCount && !ppUsed) 231 { 232 ppUsed = new sal_Bool*[nColCount]; 233 for (SCSIZE i=0; i<nColCount; i++) 234 { 235 ppUsed[i] = new sal_Bool[nRowCount]; 236 memset( ppUsed[i], 0, nRowCount * sizeof(sal_Bool) ); 237 } 238 } 239 240 if (nRowCount && nDataCount && !ppTitlePos) 241 { 242 ppTitlePos = new SCSIZE*[nRowCount]; 243 for (SCSIZE i=0; i<nRowCount; i++) 244 { 245 ppTitlePos[i] = new SCSIZE[nDataCount]; 246 memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //! unnoetig ? 247 } 248 } 249 250 // CornerText: einzelner String 251 } 252 253 void ScConsData::DoneFields() 254 { 255 InitData(sal_False); 256 } 257 258 void ScConsData::SetSize( SCCOL nCols, SCROW nRows ) 259 { 260 DeleteData(); 261 nColCount = static_cast<SCSIZE>(nCols); 262 nRowCount = static_cast<SCSIZE>(nRows); 263 } 264 265 void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const 266 { 267 rCols = static_cast<SCCOL>(nColCount); 268 rRows = static_cast<SCROW>(nRowCount); 269 } 270 271 void ScConsData::SetFlags( ScSubTotalFunc eFunc, sal_Bool bColName, sal_Bool bRowName, sal_Bool bRef ) 272 { 273 DeleteData(); 274 bReference = bRef; 275 bColByName = bColName; 276 if (bColName) nColCount = 0; 277 bRowByName = bRowName; 278 if (bRowName) nRowCount = 0; 279 eFunction = eFunc; 280 } 281 282 void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab, 283 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) 284 { 285 ++nDataCount; 286 287 String aTitle; 288 289 SCCOL nStartCol = nCol1; 290 SCROW nStartRow = nRow1; 291 if (bColByName) ++nStartRow; 292 if (bRowByName) ++nStartCol; 293 294 if (bColByName) 295 { 296 for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++) 297 { 298 pSrcDoc->GetString( nCol, nRow1, nTab, aTitle ); 299 if (aTitle.Len()) 300 { 301 sal_Bool bFound = sal_False; 302 for (SCSIZE i=0; i<nColCount && !bFound; i++) 303 if ( *ppColHeaders[i] == aTitle ) 304 bFound = sal_True; 305 if (!bFound) 306 lcl_AddString( ppColHeaders, nColCount, aTitle ); 307 } 308 } 309 } 310 311 if (bRowByName) 312 { 313 for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++) 314 { 315 pSrcDoc->GetString( nCol1, nRow, nTab, aTitle ); 316 if (aTitle.Len()) 317 { 318 sal_Bool bFound = sal_False; 319 for (SCSIZE i=0; i<nRowCount && !bFound; i++) 320 if ( *ppRowHeaders[i] == aTitle ) 321 bFound = sal_True; 322 if (!bFound) 323 lcl_AddString( ppRowHeaders, nRowCount, aTitle ); 324 } 325 } 326 } 327 } 328 329 void ScConsData::AddName( const String& rName ) 330 { 331 SCSIZE nArrX; 332 SCSIZE nArrY; 333 334 if (bReference) 335 { 336 lcl_AddString( ppTitles, nTitleCount, rName ); 337 338 for (nArrY=0; nArrY<nRowCount; nArrY++) 339 { 340 // Daten auf gleiche Laenge bringen 341 342 SCSIZE nMax = 0; 343 for (nArrX=0; nArrX<nColCount; nArrX++) 344 if (ppUsed[nArrX][nArrY]) 345 nMax = Max( nMax, ppRefs[nArrX][nArrY].GetCount() ); 346 347 for (nArrX=0; nArrX<nColCount; nArrX++) 348 { 349 if (!ppUsed[nArrX][nArrY]) 350 { 351 ppUsed[nArrX][nArrY] = sal_True; 352 ppRefs[nArrX][nArrY].Init(); 353 } 354 ppRefs[nArrX][nArrY].SetFullSize(nMax); 355 } 356 357 // Positionen eintragen 358 359 if (ppTitlePos) 360 if (nTitleCount < nDataCount) 361 ppTitlePos[nArrY][nTitleCount] = nMax; 362 } 363 } 364 } 365 366 // rCount < 0 <=> Fehler aufgetreten 367 368 void lcl_UpdateArray( ScSubTotalFunc eFunc, 369 double& rCount, double& rSum, double& rSumSqr, double nVal ) 370 { 371 if (rCount < 0.0) 372 return; 373 switch (eFunc) 374 { 375 case SUBTOTAL_FUNC_SUM: 376 if (!SubTotal::SafePlus(rSum, nVal)) 377 rCount = -MAXDOUBLE; 378 break; 379 case SUBTOTAL_FUNC_PROD: 380 if (!SubTotal::SafeMult(rSum, nVal)) 381 rCount = -MAXDOUBLE; 382 break; 383 case SUBTOTAL_FUNC_CNT: 384 case SUBTOTAL_FUNC_CNT2: 385 rCount += 1.0; 386 break; 387 case SUBTOTAL_FUNC_AVE: 388 if (!SubTotal::SafePlus(rSum, nVal)) 389 rCount = -MAXDOUBLE; 390 else 391 rCount += 1.0; 392 break; 393 case SUBTOTAL_FUNC_MAX: 394 if (nVal > rSum) 395 rSum = nVal; 396 break; 397 case SUBTOTAL_FUNC_MIN: 398 if (nVal < rSum) 399 rSum = nVal; 400 break; 401 case SUBTOTAL_FUNC_STD: 402 case SUBTOTAL_FUNC_STDP: 403 case SUBTOTAL_FUNC_VAR: 404 case SUBTOTAL_FUNC_VARP: 405 { 406 sal_Bool bOk = SubTotal::SafePlus(rSum, nVal); 407 bOk = bOk && SubTotal::SafeMult(nVal, nVal); 408 bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal); 409 if (!bOk) 410 rCount = -MAXDOUBLE; 411 else 412 rCount += 1.0; 413 break; 414 } 415 default: 416 { 417 // added to avoid warnings 418 } 419 } 420 } 421 422 void lcl_InitArray( ScSubTotalFunc eFunc, 423 double& rCount, double& rSum, double& rSumSqr, double nVal ) 424 { 425 rCount = 1.0; 426 switch (eFunc) 427 { 428 case SUBTOTAL_FUNC_SUM: 429 case SUBTOTAL_FUNC_MAX: 430 case SUBTOTAL_FUNC_MIN: 431 case SUBTOTAL_FUNC_PROD: 432 case SUBTOTAL_FUNC_AVE: 433 rSum = nVal; 434 break; 435 case SUBTOTAL_FUNC_STD: 436 case SUBTOTAL_FUNC_STDP: 437 case SUBTOTAL_FUNC_VAR: 438 case SUBTOTAL_FUNC_VARP: 439 { 440 rSum = nVal; 441 sal_Bool bOk = SubTotal::SafeMult(nVal, nVal); 442 if (bOk) 443 rSumSqr = nVal; 444 else 445 rCount = -MAXDOUBLE; 446 } 447 break; 448 default: 449 break; 450 } 451 } 452 453 double lcl_CalcData( ScSubTotalFunc eFunc, 454 double fCount, double fSum, double fSumSqr) 455 { 456 if (fCount < 0.0) 457 return 0.0; 458 double fVal = 0.0; 459 switch (eFunc) 460 { 461 case SUBTOTAL_FUNC_CNT: 462 case SUBTOTAL_FUNC_CNT2: 463 fVal = fCount; 464 break; 465 case SUBTOTAL_FUNC_SUM: 466 case SUBTOTAL_FUNC_MAX: 467 case SUBTOTAL_FUNC_MIN: 468 case SUBTOTAL_FUNC_PROD: 469 fVal = fSum; 470 break; 471 case SUBTOTAL_FUNC_AVE: 472 if (fCount > 0.0) 473 fVal = fSum / fCount; 474 else 475 fCount = -MAXDOUBLE; 476 break; 477 case SUBTOTAL_FUNC_STD: 478 { 479 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum)) 480 fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0)); 481 else 482 fCount = -MAXDOUBLE; 483 } 484 break; 485 case SUBTOTAL_FUNC_STDP: 486 { 487 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum)) 488 fVal = sqrt((fSumSqr - fSum/fCount)/fCount); 489 else 490 fCount = -MAXDOUBLE; 491 } 492 break; 493 case SUBTOTAL_FUNC_VAR: 494 { 495 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum)) 496 fVal = (fSumSqr - fSum/fCount)/(fCount-1.0); 497 else 498 fCount = -MAXDOUBLE; 499 } 500 break; 501 case SUBTOTAL_FUNC_VARP: 502 { 503 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum)) 504 fVal = (fSumSqr - fSum/fCount)/fCount; 505 else 506 fCount = -MAXDOUBLE; 507 } 508 break; 509 default: 510 { 511 DBG_ERROR("unbekannte Funktion bei Consoli::CalcData"); 512 fCount = -MAXDOUBLE; 513 } 514 break; 515 } 516 return fVal; 517 } 518 519 void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab, 520 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) 521 { 522 PutInOrder(nCol1,nCol2); 523 PutInOrder(nRow1,nRow2); 524 if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName ) 525 { 526 DBG_ASSERT(0,"Bereich zu gross"); 527 nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 ); 528 } 529 if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName ) 530 { 531 DBG_ASSERT(0,"Bereich zu gross"); 532 nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 ); 533 } 534 535 SCCOL nCol; 536 SCROW nRow; 537 538 // Ecke links oben 539 540 if ( bColByName && bRowByName ) 541 { 542 String aThisCorner; 543 pSrcDoc->GetString(nCol1,nRow1,nTab,aThisCorner); 544 if (bCornerUsed) 545 { 546 if (aCornerText != aThisCorner) 547 aCornerText.Erase(); 548 } 549 else 550 { 551 aCornerText = aThisCorner; 552 bCornerUsed = sal_True; 553 } 554 } 555 556 // Titel suchen 557 558 SCCOL nStartCol = nCol1; 559 SCROW nStartRow = nRow1; 560 if (bColByName) ++nStartRow; 561 if (bRowByName) ++nStartCol; 562 String aTitle; 563 SCCOL* pDestCols = NULL; 564 SCROW* pDestRows = NULL; 565 if (bColByName) 566 { 567 pDestCols = new SCCOL[nCol2-nStartCol+1]; 568 for (nCol=nStartCol; nCol<=nCol2; nCol++) 569 { 570 pSrcDoc->GetString(nCol,nRow1,nTab,aTitle); 571 SCCOL nPos = SC_CONS_NOTFOUND; 572 if (aTitle.Len()) 573 { 574 sal_Bool bFound = sal_False; 575 for (SCSIZE i=0; i<nColCount && !bFound; i++) 576 if ( *ppColHeaders[i] == aTitle ) 577 { 578 nPos = static_cast<SCCOL>(i); 579 bFound = sal_True; 580 } 581 DBG_ASSERT(bFound, "Spalte nicht gefunden"); 582 } 583 pDestCols[nCol-nStartCol] = nPos; 584 } 585 } 586 if (bRowByName) 587 { 588 pDestRows = new SCROW[nRow2-nStartRow+1]; 589 for (nRow=nStartRow; nRow<=nRow2; nRow++) 590 { 591 pSrcDoc->GetString(nCol1,nRow,nTab,aTitle); 592 SCROW nPos = SC_CONS_NOTFOUND; 593 if (aTitle.Len()) 594 { 595 sal_Bool bFound = sal_False; 596 for (SCSIZE i=0; i<nRowCount && !bFound; i++) 597 if ( *ppRowHeaders[i] == aTitle ) 598 { 599 nPos = static_cast<SCROW>(i); 600 bFound = sal_True; 601 } 602 DBG_ASSERT(bFound, "Zeile nicht gefunden"); 603 } 604 pDestRows[nRow-nStartRow] = nPos; 605 } 606 } 607 nCol1 = nStartCol; 608 nRow1 = nStartRow; 609 610 // Daten 611 612 sal_Bool bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 ); 613 for (nCol=nCol1; nCol<=nCol2; nCol++) 614 { 615 SCCOL nArrX = nCol-nCol1; 616 if (bColByName) nArrX = pDestCols[nArrX]; 617 if (nArrX != SC_CONS_NOTFOUND) 618 { 619 for (nRow=nRow1; nRow<=nRow2; nRow++) 620 { 621 SCROW nArrY = nRow-nRow1; 622 if (bRowByName) nArrY = pDestRows[nArrY]; 623 if ( nArrY != SC_CONS_NOTFOUND && ( 624 bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab ) 625 : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) ) 626 { 627 if (bReference) 628 { 629 if (ppUsed[nArrX][nArrY]) 630 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab ); 631 else 632 { 633 ppUsed[nArrX][nArrY] = sal_True; 634 ppRefs[nArrX][nArrY].Init(); 635 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab ); 636 } 637 } 638 else 639 { 640 double nVal; 641 pSrcDoc->GetValue( nCol, nRow, nTab, nVal ); 642 if (ppUsed[nArrX][nArrY]) 643 lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY], 644 ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY], 645 nVal); 646 else 647 { 648 ppUsed[nArrX][nArrY] = sal_True; 649 lcl_InitArray( eFunction, ppCount[nArrX][nArrY], 650 ppSum[nArrX][nArrY], 651 ppSumSqr[nArrX][nArrY], nVal ); 652 } 653 } 654 } 655 } 656 } 657 } 658 659 delete[] pDestCols; 660 delete[] pDestRows; 661 } 662 663 // vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo) 664 665 SCROW ScConsData::GetInsertCount() const 666 { 667 SCROW nInsert = 0; 668 SCSIZE nArrX; 669 SCSIZE nArrY; 670 if ( ppRefs && ppUsed ) 671 { 672 for (nArrY=0; nArrY<nRowCount; nArrY++) 673 { 674 SCSIZE nNeeded = 0; 675 for (nArrX=0; nArrX<nColCount; nArrX++) 676 if (ppUsed[nArrX][nArrY]) 677 nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() ); 678 679 nInsert += nNeeded; 680 } 681 } 682 return nInsert; 683 } 684 685 // fertige Daten ins Dokument schreiben 686 //! optimieren nach Spalten? 687 688 void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab ) 689 { 690 OpCode eOpCode = eOpCodeTable[eFunction]; 691 692 SCSIZE nArrX; 693 SCSIZE nArrY; 694 695 // Ecke links oben 696 697 if ( bColByName && bRowByName && aCornerText.Len() ) 698 pDestDoc->SetString( nCol, nRow, nTab, aCornerText ); 699 700 // Titel 701 702 SCCOL nStartCol = nCol; 703 SCROW nStartRow = nRow; 704 if (bColByName) ++nStartRow; 705 if (bRowByName) ++nStartCol; 706 707 if (bColByName) 708 for (SCSIZE i=0; i<nColCount; i++) 709 pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, *ppColHeaders[i] ); 710 if (bRowByName) 711 for (SCSIZE j=0; j<nRowCount; j++) 712 pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, *ppRowHeaders[j] ); 713 714 nCol = nStartCol; 715 nRow = nStartRow; 716 717 // Daten 718 719 if ( ppCount && ppUsed ) // Werte direkt einfuegen 720 { 721 for (nArrX=0; nArrX<nColCount; nArrX++) 722 for (nArrY=0; nArrY<nRowCount; nArrY++) 723 if (ppUsed[nArrX][nArrY]) 724 { 725 double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY], 726 ppSum[nArrX][nArrY], 727 ppSumSqr[nArrX][nArrY]); 728 if (ppCount[nArrX][nArrY] < 0.0) 729 pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX), 730 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue ); 731 else 732 pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX), 733 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal ); 734 } 735 } 736 737 if ( ppRefs && ppUsed ) // Referenzen einfuegen 738 { 739 //! unterscheiden, ob nach Kategorien aufgeteilt 740 String aString; 741 742 ScSingleRefData aSRef; // Daten fuer Referenz-Formelzellen 743 aSRef.InitFlags(); 744 aSRef.SetFlag3D(sal_True); 745 746 ScComplexRefData aCRef; // Daten fuer Summen-Zellen 747 aCRef.InitFlags(); 748 aCRef.Ref1.SetColRel(sal_True); aCRef.Ref1.SetRowRel(sal_True); aCRef.Ref1.SetTabRel(sal_True); 749 aCRef.Ref2.SetColRel(sal_True); aCRef.Ref2.SetRowRel(sal_True); aCRef.Ref2.SetTabRel(sal_True); 750 751 for (nArrY=0; nArrY<nRowCount; nArrY++) 752 { 753 SCSIZE nNeeded = 0; 754 for (nArrX=0; nArrX<nColCount; nArrX++) 755 if (ppUsed[nArrX][nArrY]) 756 nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() ); 757 758 if (nNeeded) 759 { 760 pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded ); 761 762 for (nArrX=0; nArrX<nColCount; nArrX++) 763 if (ppUsed[nArrX][nArrY]) 764 { 765 ScReferenceList& rList = ppRefs[nArrX][nArrY]; 766 SCSIZE nCount = rList.GetCount(); 767 if (nCount) 768 { 769 for (SCSIZE nPos=0; nPos<nCount; nPos++) 770 { 771 ScReferenceEntry aRef = rList.GetEntry(nPos); 772 if (aRef.nTab != SC_CONS_NOTFOUND) 773 { 774 // Referenz einfuegen (absolut, 3d) 775 776 aSRef.nCol = aRef.nCol; 777 aSRef.nRow = aRef.nRow; 778 aSRef.nTab = aRef.nTab; 779 780 ScTokenArray aRefArr; 781 aRefArr.AddSingleReference(aSRef); 782 aRefArr.AddOpCode(ocStop); 783 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX), 784 sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab ); 785 ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr ); 786 pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell ); 787 } 788 } 789 790 // Summe einfuegen (relativ, nicht 3d) 791 792 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX), 793 sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab ); 794 795 aCRef.Ref1.nTab = aCRef.Ref2.nTab = nTab; 796 aCRef.Ref1.nCol = aCRef.Ref2.nCol = sal::static_int_cast<SCsCOL>( nCol+nArrX ); 797 aCRef.Ref1.nRow = nRow+nArrY; 798 aCRef.Ref2.nRow = nRow+nArrY+nNeeded-1; 799 aCRef.CalcRelFromAbs( aDest ); 800 801 ScTokenArray aArr; 802 aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion 803 aArr.AddOpCode(ocOpen); 804 aArr.AddDoubleReference(aCRef); 805 aArr.AddOpCode(ocClose); 806 aArr.AddOpCode(ocStop); 807 ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr ); 808 pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell ); 809 } 810 } 811 812 // Gliederung einfuegen 813 814 ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, sal_True )->GetRowArray(); 815 SCROW nOutStart = nRow+nArrY; 816 SCROW nOutEnd = nRow+nArrY+nNeeded-1; 817 sal_Bool bSize = sal_False; 818 pOutArr->Insert( nOutStart, nOutEnd, bSize ); 819 for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++) 820 pDestDoc->ShowRow( nOutRow, nTab, sal_False ); 821 pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, sal_False ); 822 823 // Zwischentitel 824 825 if (ppTitlePos && ppTitles && ppRowHeaders) 826 { 827 String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") ); 828 for (SCSIZE nPos=0; nPos<nDataCount; nPos++) 829 { 830 SCSIZE nTPos = ppTitlePos[nArrY][nPos]; 831 sal_Bool bDo = sal_True; 832 if (nPos+1<nDataCount) 833 if (ppTitlePos[nArrY][nPos+1] == nTPos) 834 bDo = sal_False; // leer 835 if ( bDo && nTPos < nNeeded ) 836 { 837 aString = *ppRowHeaders[nArrY]; 838 aString += aDelim; 839 aString += *ppTitles[nPos]; 840 pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString ); 841 } 842 } 843 } 844 845 nRow += nNeeded; 846 } 847 } 848 } 849 } 850 851 852 853 854 855