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