00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "sheet.h"
00035
00036
00037 #include <qmessagebox.h>
00038
00039
00040 #include <math.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <time.h>
00044
00045 #define DEFAULT_COL_WIDTH 50
00046
00047 Sheet::Sheet(int numRows, int numCols, QWidget *parent)
00048 :QTable(numRows, numCols, parent)
00049 {
00050 defaultBorders.right=defaultBorders.bottom=QPen(Qt::gray, 1, Qt::SolidLine);
00051 defaultCellData.data="";
00052 defaultCellData.background=QBrush(Qt::white, Qt::SolidPattern);
00053 defaultCellData.alignment=(Qt::AlignmentFlags)(Qt::AlignLeft | Qt::AlignTop);
00054 defaultCellData.fontColor=Qt::black;
00055 defaultCellData.font=font();
00056 defaultCellData.borders=defaultBorders;
00057
00058 clicksLocked=FALSE;
00059 selectionNo=-1;
00060 setSelectionMode(QTable::Single);
00061
00062 sheetData.setAutoDelete(TRUE);
00063 clipboardData.setAutoDelete(TRUE);
00064 for (int i=0; i<numCols; ++i)
00065 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
00066
00067
00068 connect(this, SIGNAL(currentChanged(int,int)), this, SLOT(slotCellSelected(int,int)));
00069 connect(this, SIGNAL(valueChanged(int,int)), this, SLOT(slotCellChanged(int,int)));
00070 }
00071
00072 Sheet::~Sheet()
00073 {}
00074
00075 typeCellData *Sheet::findCellData(int row, int col)
00076 {
00077 typeCellData *tempCellData;
00078 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
00079 {
00080 if (tempCellData->row==row && tempCellData->col==col) return tempCellData;
00081 }
00082 return NULL;
00083 }
00084
00085 void Sheet::slotCellSelected(int row, int col)
00086 {
00087 typeCellData *cellData=findCellData(row, col);
00088 if (cellData)
00089 {
00090 emit currentDataChanged(cellData->data);
00091 }
00092 else
00093 emit currentDataChanged("");
00094 }
00095
00096 typeCellData *Sheet::createCellData(int row, int col)
00097 {
00098 if (row<0 || col<0) return NULL;
00099 typeCellData *cellData=new typeCellData;
00100 cellData->row=row;
00101 cellData->col=col;
00102 cellData->data=defaultCellData.data;
00103 cellData->borders=defaultCellData.borders;
00104 cellData->alignment=defaultCellData.alignment;
00105 cellData->font=defaultCellData.font;
00106 cellData->fontColor=defaultCellData.fontColor;
00107 cellData->background=defaultCellData.background;
00108 sheetData.append(cellData);
00109 return cellData;
00110 }
00111
00112 void Sheet::slotCellChanged(int row, int col)
00113 {
00114 typeCellData *cellData=findCellData(row, col);
00115 if (!cellData) cellData=createCellData(row, col);
00116 if (cellData) cellData->data=text(row, col);
00117 for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
00118 {
00119
00120
00121 int w1,ii=0;
00122 for(w1=0;w1<=(int)text(row, col).length();w1++)
00123 {
00124 if(text(row,col)[w1]=='(') ii++;
00125 if(text(row,col)[w1]==')') ii--;
00126 };
00127 if(ii==0) setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
00128
00129
00130
00131 };
00132 emit sheetModified();
00133 }
00134
00135
00136 void Sheet::ReCalc(void)
00137 {
00138 typeCellData* cellData;
00139 for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
00140 {
00141
00142
00143 slotCellChanged(cellData->row,cellData->col);
00144 };
00145 };
00146
00147
00148
00149
00150 void Sheet::swapCells(int row1, int col1, int row2, int col2)
00151 {
00152 typeCellData *cellData1=findCellData(row1, col1), *cellData2=findCellData(row2, col2);
00153 if (!cellData1) cellData1=createCellData(row1, col1);
00154 if (!cellData2) cellData2=createCellData(row2, col2);
00155 if (cellData1 && cellData2)
00156 {
00157 QString tempData(cellData1->data);
00158 cellData1->data=cellData2->data;
00159 cellData2->data=tempData;
00160 setText(cellData1->row, cellData1->col, dataParser(findCellName(cellData1->row, cellData1->col), cellData1->data));
00161 setText(cellData2->row, cellData2->col, dataParser(findCellName(cellData2->row, cellData2->col), cellData2->data));
00162 emit sheetModified();
00163 }
00164 }
00165
00166 QString Sheet::getParameter(const QString ¶meters, int paramNo, bool giveError, const QString funcName)
00167 {
00168 QString params(parameters);
00169 int position;
00170 for (int i=0; i<paramNo; ++i)
00171 {
00172 position=params.find(',');
00173 if (position<0)
00174 {
00175 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Too few arguments to function '"+funcName+'\''));
00176
00177 return QString(NULL);
00178 }
00179 params=params.mid(position+1);
00180 }
00181 position=params.find(',');
00182 if (position<0) return params;
00183 return params.left(position);
00184 }
00185
00186 bool Sheet::findRange(const QString &variable1, const QString &variable2, int *row1, int *col1, int *row2, int *col2)
00187 {
00188 int row, col;
00189 if (!findRowColumn(variable1, row1, col1, FALSE) || !findRowColumn(variable2, row2, col2, FALSE)) return FALSE;
00190 if (*row1>*row2)
00191 {
00192 row=*row1;
00193 *row1=*row2;
00194 *row2=row;
00195 }
00196 if (*col1>*col2)
00197 {
00198 col=*col1;
00199 *col1=*col2;
00200 *col2=col;
00201 }
00202 return TRUE;
00203 }
00204
00205 bool Sheet::findRowColumn(const QString &variable, int *row, int *col, bool giveError)
00206 {
00207 int position=variable.find(QRegExp("\\d"));
00208 if (position<1)
00209 {
00210 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Invalid variable: '"+variable+'\''));
00211 return FALSE;
00212 }
00213 *row=variable.mid(position).toInt()-1;
00214 *col=getHeaderColumn(variable.left(position))-1;
00215 return TRUE;
00216 }
00217
00218 QString Sheet::calculateVariable(const QString &variable)
00219 {
00220 bool ok;
00221 printf("calculateVariable=%s,len=%d\r\n",variable.ascii(),variable.length());
00222 if(variable.left(1)=="\"") return QString(variable.mid(1,variable.length()-2));
00223 double tempResult=variable.toDouble(&ok);
00224 if (ok)
00225 {
00226 if(tempResult!=0.0)
00227 {
00228 return QString::number(tempResult);
00229 }
00230 else
00231 {
00232 if(variable!="0" || variable!="0.0") return QString(variable);
00233 return QString::number(tempResult);
00234 };
00235 };
00236
00237 int row, col;
00238 if(findRowColumn(variable, &row, &col, FALSE)) return dataParser(variable, text(row,col));
00239
00240 return QString(variable);
00241 }
00242
00243 double Sheet::BesselI0(double x)
00244 {
00245
00246 double ax,ans;
00247 double y;
00248 if ((ax=fabs(x)) < 3.75)
00249 {
00250 y=x/3.75;
00251 y*=y;
00252 ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
00253 }
00254 else
00255 {
00256 y=3.75/ax;
00257 ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 +y*0.392377e-2))))))));
00258 }
00259 return ans;
00260 };
00261
00262 double Sheet::BesselI1(double x)
00263 {
00264 double ax,ans;
00265 double y;
00266 if ((ax=fabs(x)) < 3.75)
00267 {
00268 y=x/3.75;
00269 y*=y;
00270 ans=ax*(0.5+y*(0.87890594+y*(0.51498869+y*(0.15084934 +y*(0.2658733e-1+y*(0.301532e-2+y*0.32411e-3))))));
00271 }
00272 else
00273 {
00274 y=3.75/ax;
00275 ans=0.2282967e-1+y*(-0.2895312e-1+y*(0.1787654e-1 -y*0.420059e-2)); ans=0.39894228+y*(-0.3988024e-1+y*(-0.362018e-2 +y*(0.163801e-2+y*(-0.1031555e-1+y*ans))));
00276 ans *= (exp(ax)/sqrt(ax));
00277 }
00278 return x < 0.0 ? -ans : ans;
00279 };
00280
00281 double Sheet::BesselI(int n, double x)
00282 {
00283 double ACC=40.0;
00284 double BIGNO=1.0e10;
00285 double BIGNI=1.0e-10;
00286 int j;
00287 double bi,bim,bip,tox,ans;
00288 if (n < 2) return 0.0;
00289 if (x == 0.0) return 0.0; else
00290 {
00291 tox=2.0/fabs(x);
00292 bip=ans=0.0;
00293 bi=1.0;
00294 for (j=2*(n+(int) sqrt(ACC*n));j>0;j--)
00295 {
00296 bim=bip+j*tox*bi;
00297 bip=bi;
00298 bi=bim;
00299 if (fabs(bi) > BIGNO)
00300 {
00301 ans *= BIGNI;
00302 bi *= BIGNI;
00303 bip *= BIGNI;
00304 }
00305 if (j == n) ans=bip;
00306 }
00307 ans *= BesselI0(x)/bi;
00308 return x < 0.0 && (n & 1) ? -ans : ans;
00309 }
00310 };
00311
00312 double Sheet::BesselK0(double x)
00313 {
00314 double y,ans;
00315 if (x <= 2.0)
00316 {
00317 y=x*x/4.0;
00318 ans=(-log(x/2.0)*BesselI0(x))+(-0.57721566+y*(0.42278420 +y*(0.23069756+y*(0.3488590e-1+y*(0.262698e-2 +y*(0.10750e-3+y*0.74e-5))))));
00319 }
00320 else
00321 {
00322 y=2.0/x;
00323 ans=(exp(-x)/sqrt(x))*(1.25331414+y*(-0.7832358e-1 +y*(0.2189568e-1+y*(-0.1062446e-1+y*(0.587872e-2 +y*(-0.251540e-2+y*0.53208e-3))))));
00324 }
00325 return ans;
00326 };
00327
00328 double Sheet::BesselK1(double x)
00329 {
00330 double y,ans;
00331 if (x <= 2.0)
00332 {
00333 y=x*x/4.0;
00334 ans=(log(x/2.0)*BesselI1(x))+(1.0/x)*(1.0+y*(0.15443144 +y*(-0.67278579+y*(-0.18156897+y*(-0.1919402e-1 +y*(-0.110404e-2+y*(-0.4686e-4)))))));
00335 }
00336 else
00337 {
00338 y=2.0/x;
00339 ans=(exp(-x)/sqrt(x))*(1.25331414+y*(0.23498619 +y*(-0.3655620e-1+y*(0.1504268e-1+y*(-0.780353e-2 +y*(0.325614e-2+y*(-0.68245e-3)))))));
00340 }
00341 return ans;
00342 };
00343
00344 double Sheet::BesselK(int n, double x)
00345 {
00346 int j;
00347 double bk,bkm,bkp,tox;
00348 if (n < 2) return 0.0;
00349 tox=2.0/x;
00350 bkm=BesselK0(x);
00351 bk=BesselK1(x);
00352 for (j=1;j<n;j++)
00353 {
00354 bkp=bkm+j*tox*bk;
00355 bkm=bk;
00356 bk=bkp;
00357 }
00358 return bk;
00359 };
00360
00361 double Sheet::BesselJ0(double x)
00362 {
00363 double ax,z;
00364 double xx,y,ans,ans1,ans2;
00365 if ((ax=fabs(x)) < 8.0)
00366 {
00367 y=x*x;
00368 ans1=57568490574.0+y*(-13362590354.0+y*(651619640.7 +y*(-11214424.18+y*(77392.33017+y*(-184.9052456)))));
00369 ans2=57568490411.0+y*(1029532985.0+y*(9494680.718 +y*(59272.64853+y*(267.8532712+y*1.0))));
00370 ans=ans1/ans2;
00371 }
00372 else
00373 {
00374 z=8.0/ax;
00375 y=z*z;
00376 xx=ax-0.785398164;
00377 ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
00378 ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 -y*0.934935152e-7)));
00379 ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
00380 }
00381 return ans;
00382 };
00383
00384 double Sheet::BesselY0(double x)
00385 {
00386 double z;
00387 double xx,y,ans,ans1,ans2;
00388 if (x < 8.0)
00389 {
00390 y=x*x;
00391 ans1 = -2957821389.0+y*(7062834065.0+y*(-512359803.6 +y*(10879881.29+y*(-86327.92757+y*228.4622733))));
00392 ans2=40076544269.0+y*(745249964.8+y*(7189466.438 +y*(47447.26470+y*(226.1030244+y*1.0))));
00393 ans=(ans1/ans2)+0.636619772*BesselJ0(x)*log(x);
00394 }
00395 else
00396 {
00397 z=8.0/x;
00398 y=z*z;
00399 xx=x-0.785398164;
00400 ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
00401 ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 +y*(-0.934945152e-7))));
00402 ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
00403 }
00404 return ans;
00405 };
00406
00407 double Sheet::BesselJ1(double x)
00408 {
00409 double ax,z;
00410 double xx,y,ans,ans1,ans2;
00411 if ((ax=fabs(x)) < 8.0)
00412 {
00413 y=x*x;
00414 ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1 +y*(-2972611.439+y*(15704.48260+y*(-30.16036606))))));
00415 ans2=144725228442.0+y*(2300535178.0+y*(18583304.74 +y*(99447.43394+y*(376.9991397+y*1.0))));
00416 ans=ans1/ans2;
00417 }
00418 else
00419 {
00420 z=8.0/ax; y=z*z; xx=ax-2.356194491;
00421 ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
00422 ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
00423 ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
00424 if (x < 0.0) ans = -ans;
00425 }
00426 return ans;
00427 };
00428
00429 double Sheet::BesselY1(double x)
00430 {
00431 double z;
00432 double xx,y,ans,ans1,ans2;
00433 if (x < 8.0)
00434 {
00435 y=x*x;
00436 ans1=x*(-0.4900604943e13+y*(0.1275274390e13 +y*(-0.5153438139e11+y*(0.7349264551e9 +y*(-0.4237922726e7+y*0.8511937935e4)))));
00437 ans2=0.2499580570e14+y*(0.4244419664e12 +y*(0.3733650367e10+y*(0.2245904002e8 +y*(0.1020426050e6+y*(0.3549632885e3+y)))));
00438 ans=(ans1/ans2)+0.636619772*(BesselJ1(x)*log(x)-1.0/x);
00439 }
00440 else
00441 {
00442 z=8.0/x;
00443 y=z*z;
00444 xx=x-2.356194491;
00445 ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
00446 ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
00447 ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
00448 }
00449 return ans;
00450 };
00451
00452 double Sheet::BesselY(int n, double x)
00453 {
00454 int j;
00455 double by,bym,byp,tox;
00456 if (n < 2) return 0.0;
00457 tox=2.0/x;
00458 by=BesselY1(x);
00459 bym=BesselY0(x);
00460 for (j=1;j<n;j++)
00461 {
00462 byp=j*tox*by-bym;
00463 bym=by;
00464 by=byp;
00465 }
00466 return by;
00467 };
00468
00469 double Sheet::BesselJ(int n, double x)
00470 {
00471 double ACC=40.0;
00472 double BIGNO=1.0e10;
00473 double BIGNI=1.0e-10;
00474 int j,jsum,m;
00475 double ax,bj,bjm,bjp,sum,tox,ans;
00476 if (n < 2) return 0.0;
00477 ax=fabs(x);
00478 if (ax == 0.0) return 0.0;
00479 else if (ax > (double) n)
00480 {
00481 tox=2.0/ax;
00482 bjm=BesselJ0(ax);
00483 bj=BesselJ1(ax);
00484 for (j=1;j<n;j++)
00485 {
00486 bjp=j*tox*bj-bjm;
00487 bjm=bj;
00488 bj=bjp;
00489 }
00490 ans=bj;
00491 }
00492 else
00493 {
00494 tox=2.0/ax;
00495 m=2*((n+(int) sqrt(ACC*n))/2);
00496 jsum=0;
00497 bjp=ans=sum=0.0;
00498 bj=1.0;
00499 for (j=m;j>0;j--)
00500 {
00501 bjm=j*tox*bj-bjp;
00502 bjp=bj;
00503 bj=bjm;
00504 if (fabs(bj) > BIGNO)
00505 {
00506 bj *= BIGNI;
00507 bjp *= BIGNI;
00508 ans *= BIGNI;
00509 sum *= BIGNI;
00510 }
00511 if (jsum) sum += bj;
00512 jsum=!jsum;
00513 if (j == n) ans=bjp;
00514 }
00515 sum=2.0*sum-bj;
00516 ans /= sum;
00517 }
00518 return x < 0.0 && (n & 1) ? -ans : ans;
00519 };
00520
00521 double Sheet::GammaLn(double xx)
00522 {
00523 double x,y,tmp,ser;
00524 static double cof[6]={76.18009172947146,-86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5};
00525 int j;
00526 y=x=xx;
00527 tmp=x+5.5;
00528 tmp -= (x+0.5)*log(tmp);
00529 ser=1.000000000190015;
00530 for (j=0;j<=5;j++) ser += cof[j]/++y;
00531 return -tmp+log(2.5066282746310005*ser/x);
00532 };
00533
00534 double Sheet::Factorial(double n)
00535 {
00536 if (n < 0) return 0.0;
00537 if (n > 100) return 0.0;
00538 return exp(GammaLn(n+1.0));
00539 };
00540
00541 double Sheet::GammaP(double a, double x)
00542 {
00543
00544
00545
00546 double gamser,gammcf,gln;
00547 if (x < 0.0 || a <= 0.0) return 0.0;
00548 if (x < (a+1.0))
00549 {
00550 GammaSeries(&gamser,a,x,&gln);
00551 return gamser;
00552 }
00553 else
00554 {
00555 GammaContinuedFraction(&gammcf,a,x,&gln);
00556 return 1.0-gammcf;
00557 }
00558 };
00559
00560 double Sheet::GammaQ(double a,double x)
00561 {
00562
00563 return (1.0-GammaP(a,x));
00564 };
00565
00566
00567 void Sheet::GammaSeries(double *gamser, double a, double x, double *gln)
00568 {
00569 double EPS=3.0e-7;
00570 int ITMAX=100;
00571 int n;
00572 double sum,del,ap;
00573 *gln=GammaLn(a);
00574 if (x <= 0.0)
00575 {
00576 if (x < 0.0) return;
00577 *gamser=0.0;
00578 return;
00579 }
00580 else
00581 {
00582 ap=a;
00583 del=sum=1.0/a;
00584 for (n=1;n<=ITMAX;n++)
00585 {
00586 ++ap;
00587 del *= x/ap;
00588 sum += del;
00589 if (fabs(del) < fabs(sum)*EPS)
00590 {
00591 *gamser=sum*exp(-x+a*log(x)-(*gln));
00592 return;
00593 }
00594 }
00595 return;
00596 return;
00597 }
00598 };
00599
00600
00601 void Sheet::GammaContinuedFraction(double *gammcf, double a, double x, double *gln)
00602 {
00603 double EPS=3.0e-7;
00604 double FPMIN=1.0e-30;
00605 int ITMAX=100;
00606 int i;
00607 double an,b,c,d,del,h;
00608 *gln=GammaLn(a);
00609 b=x+1.0-a;
00610 c=1.0/FPMIN;
00611 d=1.0/b; h=d;
00612 for (i=1;i<=ITMAX;i++)
00613 {
00614 an = -i*(i-a);
00615 b += 2.0; d=an*d+b;
00616 if (fabs(d) < FPMIN) d=FPMIN;
00617 c=b+an/c;
00618 if (fabs(c) < FPMIN) c=FPMIN;
00619 d=1.0/d; del=d*c; h *= del;
00620 if (fabs(del-1.0) < EPS) break;
00621 }
00622 if (i > ITMAX) return;
00623 *gammcf=exp(-x+a*log(x)-(*gln))*h;
00624 };
00625
00626 double Sheet::ErrorFunction(double x)
00627 {
00628 return x < 0.0 ? -GammaP(0.5,x*x) : GammaP(0.5,x*x);
00629 };
00630
00631 double Sheet::ErrorFunctionComplementary(double x)
00632 {
00633 return x < 0.0 ? 1.0+GammaP(0.5,x*x) : GammaQ(0.5,x*x);
00634 };
00635
00636 double Sheet::Beta(double z, double w)
00637 {
00638 return exp(GammaLn(z)+GammaLn(w)-GammaLn(z+w));
00639 };
00640
00641
00642 double Sheet::BetaContinuedFraction(double a, double b, double x)
00643 {
00644 int MAXIT=100;
00645 double EPS=3.0e-7;
00646 double FPMIN=1.0e-30;
00647 int m,m2;
00648 double aa,c,d,del,h,qab,qam,qap;
00649 qab=a+b;
00650 qap=a+1.0; qam=a-1.0; c=1.0;
00651 d=1.0-qab*x/qap;
00652 if (fabs(d) < FPMIN) d=FPMIN;
00653 d=1.0/d; h=d;
00654 for (m=1;m<=MAXIT;m++)
00655 {
00656 m2=2*m; aa=m*(b-m)*x/((qam+m2)*(a+m2));
00657 d=1.0+aa*d;
00658 if (fabs(d) < FPMIN) d=FPMIN;
00659 c=1.0+aa/c;
00660 if (fabs(c) < FPMIN) c=FPMIN;
00661 d=1.0/d; h *= d*c;
00662 aa = -(a+m)*(qab+m)*x/((a+m2)*(qap+m2)); d=1.0+aa*d;
00663 if (fabs(d) < FPMIN) d=FPMIN;
00664 c=1.0+aa/c;
00665 if (fabs(c) < FPMIN) c=FPMIN; d=1.0/d;
00666 del=d*c; h *= del;
00667 if (fabs(del-1.0) < EPS) break;
00668 }
00669 if (m > MAXIT) return 0.0;
00670 return h;
00671 };
00672
00673 double Sheet::BetaIncomplete(double a, double b, double x)
00674 {
00675 double bt;
00676 if (x < 0.0 || x > 1.0) return 0.0;
00677 if (x == 0.0 || x == 1.0) bt=0.0; else
00678 bt=exp(GammaLn(a+b)-GammaLn(a)-GammaLn(b)+a*log(x)+b*log(1.0-x));
00679 if (x < (a+1.0)/(a+b+2.0)) return bt*BetaContinuedFraction(a,b,x)/a; else
00680 return 1.0-bt*BetaContinuedFraction(b,a,1.0-x)/b;
00681 };
00682
00683
00684
00685 double Sheet::functionSum(const QString ¶m1, const QString ¶m2)
00686 {
00687 int row1, col1, row2, col2, row, col;
00688 double result=0, tempResult;
00689 bool ok;
00690 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00691 {
00692 for (row=row1; row<=row2; ++row)
00693 for (col=col1; col<=col2; ++col)
00694 {
00695 tempResult=text(row, col).toDouble(&ok);
00696 if (ok) result+=tempResult;
00697 }
00698 return result;
00699 }
00700 else
00701 {
00702 double d1=0,d2=0;
00703 d1=calculateVariable(param1).toDouble(&ok);
00704 d2=calculateVariable(param2).toDouble(&ok);
00705 return(d1+d2);
00706 };
00707 return 0;
00708 }
00709
00710 QString Sheet::functionIndex(const QString ¶m1, const QString ¶m2, int indx)
00711 {
00712 int row1, col1, row2, col2, row, col;
00713 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00714 int ii=1;
00715 for (col=col1; col<=col2; ++col)
00716 for (row=row1; row<=row2; ++row)
00717 {
00718 if(ii==indx) return text(row,col);
00719 ii++;
00720 }
00721 return QString("");
00722 }
00723
00724
00725
00726 double Sheet::functionVariancePopulation(const QString ¶m1, const QString ¶m2)
00727 {
00728 int row1, col1, row2, col2, row, col;
00729 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00730 double avg1=functionAvg(param1,param2);
00731 double result=0, tempResult;
00732 int count1=0;
00733 bool ok;
00734 for (row=row1; row<=row2; ++row)
00735 for (col=col1; col<=col2; ++col)
00736 {
00737 tempResult=text(row, col).toDouble(&ok);
00738 if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
00739 }
00740 if(count1>0) result=result/double(count1); else result=0.0;
00741 return result;
00742 };
00743
00744 double Sheet::functionVariance(const QString ¶m1, const QString ¶m2)
00745 {
00746 int row1, col1, row2, col2, row, col;
00747 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00748 double avg1=functionAvg(param1,param2);
00749 double result=0, tempResult;
00750 int count1=0;
00751 bool ok;
00752 for (row=row1; row<=row2; ++row)
00753 for (col=col1; col<=col2; ++col)
00754 {
00755 tempResult=text(row, col).toDouble(&ok);
00756 if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
00757 }
00758 if(count1>1) result=result/double(count1-1); else result=0.0;
00759 return result;
00760 };
00761
00762 double Sheet::functionSkew(const QString ¶m1, const QString ¶m2)
00763 {
00764 int row1, col1, row2, col2, row, col;
00765 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00766 double avg1=functionAvg(param1,param2);
00767 double var1=sqrt(functionVariancePopulation(param1,param2));
00768 if(var1==0.0) return 0.0;
00769 double result=0, tempResult;
00770 int count1=0;
00771 bool ok;
00772 for (row=row1; row<=row2; ++row)
00773 for (col=col1; col<=col2; ++col)
00774 {
00775 tempResult=text(row, col).toDouble(&ok);
00776 if (ok)
00777 {
00778 result=result + (tempResult - avg1)*(tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1);
00779 count1++;
00780 };
00781 }
00782 if(count1>0) result=result/double(count1); else result=0.0;
00783 return result;
00784 };
00785
00786 double Sheet::functionKurt(const QString ¶m1, const QString ¶m2)
00787 {
00788 int row1, col1, row2, col2, row, col;
00789 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00790 double avg1=functionAvg(param1,param2);
00791 double var1=sqrt(functionVariancePopulation(param1,param2));
00792 if(var1==0.0) return 0.0;
00793 double result=0, tempResult;
00794 int count1=0;
00795 bool ok;
00796 for (row=row1; row<=row2; ++row)
00797 for (col=col1; col<=col2; ++col)
00798 {
00799 tempResult=text(row, col).toDouble(&ok);
00800 if (ok)
00801 {
00802 result=result + (tempResult - avg1)*(tempResult - avg1)*
00803 (tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1*var1);
00804 count1++;
00805 };
00806 }
00807 if(count1>0) result=result/double(count1)-3.0; else result=0.0;
00808 return result;
00809 };
00810
00811
00812
00813 double Sheet::functionSumSQ(const QString ¶m1, const QString ¶m2)
00814 {
00815 int row1, col1, row2, col2, row, col;
00816 double result=0, tempResult;
00817 bool ok;
00818 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00819 {
00820 for (row=row1; row<=row2; ++row)
00821 for (col=col1; col<=col2; ++col)
00822 {
00823 tempResult=text(row, col).toDouble(&ok);
00824 if (ok) result+=tempResult*tempResult;
00825 }
00826 return result;
00827 }
00828 else
00829 {
00830 double d1=0,d2=0;
00831 d1=calculateVariable(param1).toDouble(&ok);
00832 d2=calculateVariable(param2).toDouble(&ok);
00833 return(d1*d1+d2*d2);
00834 };
00835 return 0;
00836 }
00837
00838
00839
00840 double Sheet::functionMin(const QString ¶m1, const QString ¶m2)
00841 {
00842 int row1, col1, row2, col2, row, col;
00843 double min=0, tempMin;
00844 bool ok, init=FALSE;
00845 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00846 {
00847 for (row=row1; row<=row2; ++row)
00848 for (col=col1; col<=col2; ++col)
00849 {
00850 tempMin=text(row, col).toDouble(&ok);
00851 if (ok && (!init || tempMin<min))
00852 {
00853 min=tempMin;
00854 init=TRUE;
00855 }
00856 }
00857 return min;
00858 }
00859 else
00860 {
00861 double d1=0,d2=0;
00862 d1=calculateVariable(param1).toDouble(&ok);
00863 d2=calculateVariable(param2).toDouble(&ok);
00864 if(d1<d2) return(d1); else return(d2);
00865 };
00866 return 0;
00867 }
00868
00869 double Sheet::functionMax(const QString ¶m1, const QString ¶m2)
00870 {
00871 int row1, col1, row2, col2, row, col;
00872 double max=0, tempMax;
00873 bool ok, init=FALSE;
00874 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00875 {
00876 for (row=row1; row<=row2; ++row)
00877 for (col=col1; col<=col2; ++col)
00878 {
00879 tempMax=text(row, col).toDouble(&ok);
00880 if (ok && (!init || tempMax>max))
00881 {
00882 max=tempMax;
00883 init=TRUE;
00884 }
00885 };
00886 return max;
00887 }
00888 else
00889 {
00890 double d1=0,d2=0;
00891 d1=calculateVariable(param1).toDouble(&ok);
00892 d2=calculateVariable(param2).toDouble(&ok);
00893 if(d1>d2) return(d1); else return(d2);
00894 };
00895 return 0;
00896 }
00897
00898 double Sheet::functionAvg(const QString ¶m1, const QString ¶m2)
00899 {
00900 double resultSum=functionSum(param1, param2), resultCount=functionCount(param1, param2);
00901 return (resultCount>0 ? resultSum/resultCount : 0);
00902 }
00903
00904 double Sheet::functionCount(const QString ¶m1, const QString ¶m2)
00905 {
00906 int row1, col1, row2, col2, row, col;
00907 int divider=0;
00908 bool ok;
00909 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00910 {
00911 for (row=row1; row<=row2; ++row)
00912 for (col=col1; col<=col2; ++col)
00913 {
00914 text(row, col).toDouble(&ok);
00915 if (ok) ++divider;
00916 };
00917 return divider;
00918 }
00919 else
00920 {
00921 double d1=0,d2=0;int ii=0;
00922 d1=calculateVariable(param1).toDouble(&ok);
00923 if (ok) ii++;
00924 d2=calculateVariable(param2).toDouble(&ok);
00925 if (ok) ii++;
00926 return(ii);
00927 };
00928 return 0;
00929 }
00930
00931 double Sheet::functionCountIf(const QString ¶m1, const QString ¶m2, const QString ¶m3)
00932 {
00933 int row1, col1, row2, col2, row, col;
00934 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00935
00936 int divider=0;
00937 QString s2;
00938 bool ok;
00939 s2=calculateVariable(param3);
00940 for (row=row1; row<=row2; ++row)
00941 for (col=col1; col<=col2; ++col)
00942 {
00943 text(row, col).toDouble(&ok);
00944 if (ok && (s2==text(row,col)) ) ++divider;
00945 }
00946 return divider;
00947 }
00948
00949
00950 QString Sheet::calculateFunction(const QString &func, const QString ¶meters, int NumOfParams)
00951 {
00952 bool ok;
00953 double val1=0.0,val2=0.0,val3=0.0;
00954 long int vali=0;
00955 int w1,w2;
00956 int row,col;
00957 QString s1,s2;
00958
00959 QString function;
00960 function=func.upper();
00961 if (function=="+")
00962 {
00963 s1=calculateVariable(getParameter(parameters, 0));
00964 s2=calculateVariable(getParameter(parameters, 1));
00965 val1=s1.toDouble(&ok)+s2.toDouble(&ok);
00966 return QString::number(val1);
00967
00968 };
00969 if (function=="-")
00970 {
00971 s1=calculateVariable(getParameter(parameters, 0));
00972 s2=calculateVariable(getParameter(parameters, 1));
00973 val1=s1.toDouble(&ok)-s2.toDouble(&ok);
00974 return QString::number(val1);
00975 };
00976 if (function=="*")
00977 {
00978 val1=calculateVariable(
00979 getParameter(parameters, 0)).toDouble(&ok)
00980 *calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00981 return QString::number(val1);
00982 };
00983 if (function=="/")
00984 {
00985 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
00986 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00987 if(val2==0.0) return QString("Err101");
00988 val1=val1/val2;
00989 return QString::number(val1);
00990 };
00991 if (function==">")
00992 {
00993 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
00994 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00995 if(val1>val2) return QString::number(1); else return QString::number(0);
00996 };
00997 if (function=="<")
00998 {
00999 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01000 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01001 if(val1<val2) return QString::number(1); else return QString::number(0);
01002 };
01003 if (function==">=")
01004 {
01005 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01006 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01007 if(val1>=val2) return QString::number(1); else return QString::number(0);
01008 };
01009 if (function=="<=")
01010 {
01011 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01012 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01013 if(val1<=val2) return QString::number(1); else return QString::number(0);
01014 };
01015 if (function=="!=")
01016 {
01017 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01018 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01019 if(val1!=val2) return QString::number(1); else return QString::number(0);
01020 };
01021 if (function=="=="||function=="=")
01022 {
01023 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01024 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01025 if(val1==val2) return QString::number(1); else return QString::number(0);
01026 };
01027
01028
01029 if (function=="ISBLANK")
01030 {
01031 if(findRowColumn(getParameter(parameters, 0), &row, &col, FALSE))
01032 {
01033 if(text(row,col).length()==0) val1=1; else val1=0;
01034 }
01035 else
01036 {
01037 if(findRowColumn(calculateVariable(getParameter(parameters, 0)), &row,&col, FALSE))
01038 {
01039 if(text(row,col).length()==0) val1=1; else val1=0;
01040 }
01041 else
01042 {
01043 val1=0;
01044 };
01045 };
01046 return QString::number(val1);
01047 };
01048
01049
01050 if (function=="ISNUMBER")
01051 {
01052 if(findRowColumn(getParameter(parameters, 0, TRUE, function), &row, &col, FALSE))
01053 {
01054 val1=text(row,col).toDouble(&ok);
01055 if(ok) val1=1; else val1=0;
01056 }
01057 else
01058 {
01059 if(findRowColumn(calculateVariable(getParameter(parameters, 0, TRUE, function)), &row,&col, FALSE))
01060 {
01061 val1=text(row,col).toDouble(&ok);
01062 if(ok) val1=1; else val1=0;
01063 }
01064 else
01065 {
01066 val1=0;
01067 };
01068 };
01069 return QString::number(val1);
01070 };
01071 if (function=="AND")
01072 {
01073 vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
01074 & calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01075 return QString::number(vali);
01076 };
01077 if (function=="OR")
01078 {
01079 vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
01080 | calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01081 return QString::number(vali);
01082 };
01083 if (function=="NOT")
01084 {
01085 vali=!calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok);
01086 return QString::number(vali);
01087 };
01088
01089
01090 if (function=="ABS")
01091 {
01092 val1=fabs(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01093 return QString::number(val1);
01094 };
01095 if (function=="ACOS")
01096 {
01097 val1=acos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01098 return QString::number(val1);
01099 };
01100 if (function=="ACOSH")
01101 {
01102 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01103 if(val1<1.0) return QString::number(0);
01104 val1=acosh(val1);
01105 return QString::number(val1);
01106 };
01107 if (function=="ASIN")
01108 {
01109 val1=asin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01110 return QString::number(val1);
01111 };
01112 if (function=="ASINH")
01113 {
01114 val1=asinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01115 return QString::number(val1);
01116 };
01117 if (function=="ATAN")
01118 {
01119 val1=atan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01120 return QString::number(val1);
01121 };
01122 if (function=="ATAN2")
01123 {
01124 val1=atan2(calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok),
01125 calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01126 return QString::number(val1);
01127 };
01128 if (function=="ATANH")
01129 {
01130 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01131 if(val1<=-1.0 || val1>=1.0) return QString("Err101");
01132 val1=atanh(val1);
01133 return QString::number(val1);
01134 };
01135 if (function=="CEILING")
01136 {
01137
01138 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01139 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01140 if(val2==0.0) return QString::number(val1);
01141 val1=ceil(val1/val2)*val2;
01142 return QString::number(val1);
01143 };
01144 if (function=="COS")
01145 {
01146 val1=cos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01147 return QString::number(val1);
01148 };
01149 if (function=="COSH")
01150 {
01151 val1=cosh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01152 return QString::number(val1);
01153 };
01154 if (function=="DEGREES")
01155 {
01156 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*180.0/M_PI;
01157 return QString::number(val1);
01158 };
01159 if (function=="EXP")
01160 {
01161 val1=exp(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01162 return QString::number(val1);
01163 };
01164 if (function=="FACT")
01165 {
01166 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01167 val2=Factorial(val1);
01168 return QString::number(val2);
01169 };
01170 if (function=="FLOOR")
01171 {
01172
01173 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01174 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01175 if(val2==0.0) return QString::number(val1);
01176 val1=floor(val1/val2)*val2;
01177 return QString::number(val1);
01178 };
01179 if (function=="INT")
01180 {
01181
01182 val1=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01183 return QString::number(val1);
01184 };
01185 if (function=="EVEN")
01186 {
01187
01188 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01189 if(vali % 2 !=0) val1=vali+1; else val1=vali;
01190 return QString::number(val1);
01191 };
01192 if (function=="ODD")
01193 {
01194
01195 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01196 if(vali % 2 !=0) val1=vali; else val1=vali+1;
01197 return QString::number(val1);
01198 };
01199 if (function=="ISEVEN")
01200 {
01201
01202 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01203 if(vali % 2 == 0) val1=1; else val1=0;
01204 return QString::number(val1);
01205 };
01206 if (function=="ISODD")
01207 {
01208
01209 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01210 if(vali % 2 == 0) val1=0; else val1=1;
01211 return QString::number(val1);
01212 };
01213 if (function=="LN")
01214 {
01215
01216 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01217 if(val1<=0.0) return QString("Err101");
01218 val1=log(val1);
01219 return QString::number(val1);
01220 };
01221 if (function=="LOG10")
01222 {
01223
01224 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01225 if(val1<=0.0) return QString("Err101");
01226 val1=log10(val1);
01227 return QString::number(val1);
01228 };
01229 if (function=="LOG")
01230 {
01231
01232 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01233 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01234 if(val1<=0.0 || val2<=0.0 ) return QString("Err101");
01235 val1=log(val1)/log(val2);
01236 return QString::number(val1);
01237 };
01238 if (function=="MOD")
01239 {
01240
01241 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01242 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01243 if(val2==0.0) return QString("Err101");
01244 val1=(int(val1) % int(val2));
01245 return QString::number(val1);
01246 };
01247 if (function=="POWER")
01248 {
01249
01250 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01251 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01252 if(val1<0.0 && (floor(val2)!=val2)) return QString("Err101");
01253 val1=pow(val1,val2);
01254 return QString::number(val1);
01255 };
01256 if (function=="PI")
01257 {
01258 return QString::number(M_PI);
01259 };
01260 if (function=="RADIANS")
01261 {
01262
01263 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*M_PI/180.0;
01264 return QString::number(val1);
01265 };
01266 if (function=="RAND")
01267 {
01268
01269 srand((unsigned int)time((time_t *)NULL));
01270 val1=double(rand())/double(RAND_MAX);
01271 return QString::number(val1);
01272 };
01273 if (function=="RANDBETWEEN")
01274 {
01275
01276
01277 srand((unsigned int)time((time_t *)NULL));
01278 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01279 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01280 val1=fmod(double(rand()),(val2-val1))+val1;
01281 return QString::number(val1);
01282 };
01283 if (function=="ROUND")
01284 {
01285
01286 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01287 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01288 val2=pow(10.0,-val2);
01289 val1=floor(val1/val2)*val2;
01290 return QString::number(val1);
01291 };
01292 if (function=="SIGN")
01293 {
01294 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01295 if(val1>=0.0) return QString::number(1.0); else return QString::number(-1.0);
01296 };
01297 if (function=="CHGSGN")
01298 {
01299 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01300 return QString::number((-1.0)*val1);
01301 };
01302 if (function=="SIN")
01303 {
01304 val1=sin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01305 return QString::number(val1);
01306 };
01307 if (function=="SINH")
01308 {
01309 val1=sinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01310 return QString::number(val1);
01311 };
01312 if (function=="TAN")
01313 {
01314 val1=tan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01315 return QString::number(val1);
01316 };
01317 if (function=="TANH")
01318 {
01319 val1=tanh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01320 return QString::number(val1);
01321 };
01322 if (function=="SQRT")
01323 {
01324 val1=sqrt(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01325 return QString::number(val1);
01326 };
01327
01328
01329
01330 if (function=="CONCATENATE")
01331 {
01332
01333 w1=0;
01334 s1="";
01335 while(getParameter(parameters, w1, FALSE, function)!="")
01336 {
01337 s1=s1+calculateVariable(getParameter(parameters, w1));
01338 w1++;
01339 };
01340 return QString(s1);
01341 };
01342 if (function=="EXACT")
01343 {
01344
01345 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01346 s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
01347 if(s1==s2) return QString::number(1); else return QString::number(0);
01348 };
01349 if (function=="FIND")
01350 {
01351
01352
01353 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01354 s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
01355 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01356 val1=s2.find(s1,vali);
01357 return QString::number(val1);
01358 };
01359 if (function=="LEFT")
01360 {
01361
01362 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01363 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01364 s2=s1.left(vali);
01365 return QString(s2);
01366 };
01367 if (function=="LEN")
01368 {
01369
01370 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01371 return QString::number(s1.length());
01372 };
01373 if (function=="MID")
01374 {
01375
01376 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01377 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01378 w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01379 s2=s1.mid(w1,w2);
01380 return QString(s2);
01381 };
01382 if (function=="REPLACE")
01383 {
01384
01385 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01386 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01387 w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01388 s2=calculateVariable(getParameter(parameters, 3, TRUE, function));
01389 if(w1<0 || w2<0) return QString(s1);
01390 s1=s1.left(w2-1)+s2+s1.right(s1.length()-w1-w2);
01391 return QString(s1);
01392 };
01393 if (function=="REPT")
01394 {
01395
01396 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01397 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01398 for(w2=1;w2<=w1;w2++)
01399 {
01400 s2=s2.append(s1);
01401 };
01402 return QString(s2);
01403 };
01404 if (function=="RIGHT")
01405 {
01406
01407 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01408 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01409 s2=s1.right(vali);
01410 return QString(s2);
01411 };
01412 if (function=="UPPER")
01413 {
01414
01415 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01416 s1=s1.upper();
01417 return QString(s1);
01418 };
01419 if (function=="LOWER")
01420 {
01421
01422 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01423 s1=s1.lower();
01424 return QString(s1);
01425 };
01426 if (function=="IF")
01427 {
01428
01429
01430 val1=getParameter(parameters, 0, TRUE, function).toDouble(&ok);
01431 if(val1==1.0)
01432 {
01433 s1=calculateVariable(getParameter(parameters, 1, TRUE, function));
01434 return QString(s1);
01435 }
01436 else
01437 {
01438 s1=calculateVariable(getParameter(parameters, 2, TRUE, function));
01439 return QString(s1);
01440 };
01441 };
01442 if (function=="SUM")
01443 {
01444
01445 val2=0.0;
01446 for(w1=1;w1<=(NumOfParams/2);w1++)
01447 {
01448 val1=functionSum(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01449 val2=val2+val1;
01450 };
01451 if(NumOfParams%2==1)
01452 {
01453 val2=val2+calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01454 };
01455 return QString::number(val2);
01456 };
01457 if (function=="INDEX")
01458 {
01459 s1=functionIndex(getParameter(parameters,0,TRUE,function), getParameter(parameters, 1, TRUE, function), getParameter(parameters,2,TRUE,function).toInt(&ok));
01460 return QString(s1);
01461 };
01462 if (function=="SUMSQ")
01463 {
01464
01465 val2=0.0;
01466 for(w1=1;w1<=(NumOfParams/2);w1++)
01467 {
01468 val1=functionSumSQ(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01469 val2=val2+val1;
01470 };
01471 if(NumOfParams%2==1)
01472 {
01473 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01474 val2=val2+val1*val1;
01475 };
01476 return QString::number(val2);
01477 };
01478 if (function=="COUNT")
01479 {
01480
01481 val2=0.0;
01482 for(w1=1;w1<=(NumOfParams/2);w1++)
01483 {
01484 val1=functionCount(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01485 val2=val2+val1;
01486 };
01487 if(NumOfParams%2==1)
01488 {
01489 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01490 if(ok) val2=val2+1;
01491 };
01492 return QString::number(val2);
01493 };
01494 if (function=="COUNTIF")
01495 {
01496
01497 val1=functionCountIf(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function), getParameter(parameters, 2, TRUE, function));
01498 return QString::number(val1);
01499 };
01500 if (function=="MIN")
01501 {
01502
01503 val2=0.0;
01504 for(w1=1;w1<=(NumOfParams/2);w1++)
01505 {
01506 val1=functionMin(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01507 val2=val1;
01508 };
01509 if(NumOfParams%2==1)
01510 {
01511 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01512 if(val1<val2) val2=val1;
01513 };
01514 return QString::number(val2);
01515 };
01516 if (function=="MAX")
01517 {
01518
01519 val2=0.0;
01520 for(w1=1;w1<=(NumOfParams/2);w1++)
01521 {
01522 val1=functionMax(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01523 val2=val1;
01524 };
01525 if(NumOfParams%2==1)
01526 {
01527 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01528 if(val1>val2) val2=val1;
01529 };
01530 return QString::number(val2);
01531 };
01532 if (function=="AVERAGE")
01533 {
01534 val1=functionAvg(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01535 return QString::number(val1);
01536 };
01537
01538 if(function=="BESSELI")
01539 {
01540
01541 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01542 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01543 val2=BesselI(vali,val1);
01544 return QString::number(val2);
01545 };
01546 if(function=="BESSELJ")
01547 {
01548
01549 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01550 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01551 val2=BesselJ(vali,val1);
01552 return QString::number(val2);
01553 };
01554 if(function=="BESSELK")
01555 {
01556
01557 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01558 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01559 val2=BesselK(vali,val1);
01560 return QString::number(val2);
01561 };
01562 if(function=="BESSELY")
01563 {
01564
01565 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01566 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01567 val2=BesselY(vali,val1);
01568 return QString::number(val2);
01569 };
01570 if(function=="GAMMALN")
01571 {
01572 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01573 val2=GammaLn(val1);
01574 return QString::number(val2);
01575 };
01576 if(function=="ERF")
01577 {
01578
01579 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01580 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01581 return QString::number(ErrorFunction(val2)-ErrorFunction(val1));
01582 };
01583 if(function=="ERFC")
01584 {
01585
01586 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01587 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01588 return QString::number(ErrorFunctionComplementary(val2)-ErrorFunctionComplementary(val1));
01589 };
01590 if(function=="POISSON")
01591 {
01592
01593 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01594 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01595 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01596 if(vali==1)
01597 {
01598 return QString::number(GammaQ(floor(val1)+1, val2));
01599 }
01600 else
01601 {
01602 return QString::number(exp(-val2)*pow(val2,val1)/exp(GammaLn(val1+1.0)));
01603 };
01604 };
01605 if(function=="CHIDIST")
01606 {
01607
01608 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01609 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01610 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01611 if(vali==1)
01612 {
01613 return QString::number(GammaP(val2/2.0,val1*val1/2.0));
01614 }
01615 else
01616 {
01617 return QString::number(
01618 pow(val1,val2-1.0)*exp(-val1*val1/2)/ ( pow(2,val2/2.0-1.0)*exp(GammaLn(val2/2.0)))
01619 );
01620 };
01621 };
01622 if(function=="CHI2DIST")
01623 {
01624
01625 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01626 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01627 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01628 if(vali==1)
01629 {
01630 return QString::number(GammaP(val2/2.0,val1/2.0));
01631 }
01632 else
01633 {
01634 return QString::number(
01635 pow(val1,val2/2.0-1.0)/(exp(val1/2.0)*pow(sqrt(2.0),val2)*exp(GammaLn(val2/2.0)))
01636 );
01637 };
01638 };
01639 if(function=="BETAI")
01640 {
01641
01642 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01643 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01644 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01645 return QString::number(BetaIncomplete(val2,val3,val1));
01646 };
01647 if(function=="GAMMAP")
01648 {
01649
01650 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01651 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01652 return QString::number(GammaP(val2,val1));
01653 };
01654 if(function=="GAMMAQ")
01655 {
01656
01657 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01658 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01659 return QString::number(GammaQ(val2,val1));
01660 };
01661 if (function=="VAR")
01662 {
01663 val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01664 return QString::number(val1);
01665 };
01666 if (function=="VARP")
01667 {
01668 val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01669 return QString::number(val1);
01670 };
01671 if (function=="STDEV")
01672 {
01673 val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01674 if(val1<=0.0) return QString::number(0.0);
01675 return QString::number(sqrt(val1));
01676 };
01677 if (function=="STDEVP")
01678 {
01679 val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01680 if(val1<=0.0) return QString::number(0.0);
01681 return QString::number(sqrt(val1));
01682 };
01683 if (function=="SKEW")
01684 {
01685 val1=functionSkew(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01686 return QString::number(val1);
01687 };
01688 if (function=="KURT")
01689 {
01690 val1=functionKurt(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01691 return QString::number(val1);
01692 };
01693 if(function=="GAMMADIST")
01694 {
01695
01696 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01697 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01698 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01699 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01700 if(vali==1)
01701 {
01702 if(val3==0.0) return QString::number(0.0);
01703 else
01704 return QString::number(GammaP(val2,val1/val3));
01705 }else
01706 {
01707 return QString::number(
01708 pow(val1,val2-1.0)*exp(-val1/val3) / (pow(val3,val2)*exp(GammaLn(val2)))
01709 );
01710 };
01711 };
01712 if(function=="BETADIST")
01713 {
01714
01715 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01716 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01717 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01718 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01719 if(vali==1)
01720 {
01721 return QString::number(BetaIncomplete(val2,val3,val1));
01722 }else
01723 {
01724 return QString::number(
01725 pow(val1,val2-1.0)*pow(1.0-val1,val3-1.0) / Beta(val2,val3)
01726 );
01727 };
01728 };
01729 if(function=="FDIST")
01730 {
01731
01732 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01733 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01734 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01735 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01736 if(vali==1)
01737 {
01738 return QString::number(
01739 -BetaIncomplete(val3/2,val2/2,val3/(val3+val2*val1))
01740 +BetaIncomplete(val3/2,val2/2,1)
01741 );
01742 }else
01743 {
01744 return QString::number(
01745 pow(val2,val2/2)*pow(val3,val3/2)*pow(val1,val2/2-1)/
01746 (pow(val3+val2*val1,(val2+val3)/2)*Beta(val2/2,val3/2))
01747 );
01748 };
01749 };
01750 if(function=="NORMALDIST")
01751 {
01752
01753 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01754 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01755 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01756 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01757 if(vali==1)
01758 {
01759 return QString::number(
01760 (ErrorFunction((val1-val2)/(sqrt(2)*val3))+1)/2.0
01761 );
01762 }else
01763 {
01764 return QString::number(
01765 exp(-pow(((val1-val2)/val3),2)/2)/(val3*sqrt(2*M_PI))
01766 );
01767 };
01768 };
01769 if(function=="PHI")
01770 {
01771
01772 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01773 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01774 if(vali==1)
01775 {
01776 return QString::number(
01777 (ErrorFunction(val1/(sqrt(2)))+1)/2.0
01778 );
01779 }else
01780 {
01781 return QString::number(
01782 exp(-pow(val1,2)/2)/(sqrt(2*M_PI))
01783 );
01784 };
01785 };
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798 return 0;
01799 };
01800
01801
01802
01803
01804 QString Sheet::dataParserHelper(const QString &data)
01805 {
01806 if(data.left(1)=="""" && data.right(1)=="""") return QString(data);
01807 Expression exp1(data);
01808 exp1.Parse();
01809 QStack<QString> stack1;
01810 stack1.setAutoDelete(TRUE);
01811 int i=0;
01812 QString* s1;
01813 QString* s2=NULL;
01814 int* i1;
01815 int args,tokentype;
01816 QString tempval;
01817 s1=exp1.CompiledBody.first();i1=exp1.CompiledBodyType.first();
01818 while(i<=(int)exp1.CompiledBody.count()-1)
01819 {
01820 args= ((*i1) & 0xFF00)>>8; tokentype=(*i1) & 0x00FF;
01821 if(tokentype==NUMBER_TOKEN)
01822 {
01823 stack1.push(new QString(*s1));
01824
01825 }
01826 else if(tokentype==VARIABLE_TOKEN)
01827 {
01828 stack1.push(new QString(QString(*s1).upper()));
01829
01830
01831
01832 }
01833 else if(tokentype==STRING_TOKEN)
01834 {
01835 stack1.push(new QString(*s1));
01836
01837 }
01838 else if(tokentype==FUNCTION_TOKEN)
01839 {
01840 QString params="";
01841 for(int w1=1;w1<=args;w1++)
01842 {
01843 if((int)stack1.count()!=0) s2=stack1.pop();
01844 params=*s2+params;
01845 params=","+params;
01846 };
01847 params=params.mid(1);
01848 if(params==NULL) params="0";
01849
01850
01851 tempval=calculateFunction(*s1,params,args);
01852 tempval=tempval;
01853 stack1.push(new QString(tempval));
01854 };
01855
01856
01857 if(exp1.CompiledBody.next()!=NULL) s1=exp1.CompiledBody.current(); else break;
01858 if(exp1.CompiledBodyType.next()!=NULL) i1=exp1.CompiledBodyType.current(); else break;
01859 i++;
01860 };
01861 if((int)stack1.count()!=0)s2=stack1.pop(); else s2=new QString("!ERROR");
01862 tempval=*s2;
01863 return(tempval);
01864 };
01865
01866
01867
01868 QString Sheet::dataParser(const QString &cell, const QString &data)
01869 {
01870 QString strippedData(data);
01871 strippedData.replace(QRegExp("\\s"), "");
01872 if (strippedData.isEmpty() || strippedData[0]!='=') return data;
01873 if (listDataParser.find(cell)!=listDataParser.end()) return "0";
01874 listDataParser.append(cell);
01875
01876 strippedData=dataParserHelper(strippedData.remove(0, 1).replace(QRegExp(":"), ","));
01877
01878 int i=0;
01879 QString tempParameter(getParameter(strippedData, i)), result="";
01880 do
01881 {
01882 result+=","+calculateVariable(tempParameter);
01883 tempParameter=getParameter(strippedData, ++i);
01884 }
01885 while (!tempParameter.isNull());
01886 listDataParser.remove(cell);
01887 return result.mid(1);
01888 }
01889
01890
01891 void Sheet::setData(const QString &data)
01892 {
01893 setText(currentRow(), currentColumn(), data);
01894 slotCellChanged(currentRow(), currentColumn());
01895 activateNextCell();
01896 }
01897
01898 QString Sheet::getData()
01899 {
01900 typeCellData *cellData=findCellData(currentRow(), currentColumn());
01901 if (cellData)
01902 return cellData->data;
01903 return "";
01904 }
01905
01906 void Sheet::lockClicks(bool lock)
01907 {
01908 clicksLocked=lock;
01909 }
01910
01911 void Sheet::paintCell(QPainter *p, int row, int col, const QRect & cr, bool selected)
01912 {
01913 if (selected && row==currentRow() && col==currentColumn()) selected=FALSE;
01914
01915 int sheetDataCurrent=sheetData.at();
01916 typeCellData *cellData=findCellData(row, col);
01917 if (sheetDataCurrent>=0) sheetData.at(sheetDataCurrent);
01918 if (!cellData) cellData=&defaultCellData;
01919 if (selected)
01920 p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().highlight());
01921 else
01922 {
01923 p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().base());
01924 p->fillRect(0, 0, cr.width(), cr.height(), cellData->background);
01925 }
01926
01927 QTableItem *cellItem=item(row, col);
01928 if (cellItem)
01929 {
01930 p->setPen(selected ? colorGroup().highlightedText() : cellData->fontColor);
01931 p->setFont(cellData->font);
01932 QString str=cellItem->text();
01933 p->drawText(2, 2, cr.width()-4, cr.height()-4, cellData->alignment, cellItem->text());
01934 }
01935
01936 int rx=cr.width()-1, ry=cr.height()-1;
01937 QPen pen(p->pen());
01938 p->setPen(cellData->borders.right);
01939 p->drawLine(rx, 0, rx, ry);
01940 p->setPen(cellData->borders.bottom);
01941 p->drawLine(0, ry, rx, ry);
01942 p->setPen(pen);
01943 }
01944
01945 void Sheet::viewportMousePressEvent(QMouseEvent *e)
01946 {
01947 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01948 if (clicksLocked)
01949 {
01950 if (selectionNo<0)
01951 {
01952 clearSelection();
01953 QTableSelection newSelection;
01954 newSelection.init(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01955 newSelection.expandTo(newSelection.anchorRow(), newSelection.anchorCol());
01956 selectionNo=addSelection(newSelection);
01957 }
01958 }
01959 else
01960 QTable::contentsMousePressEvent(&ce);
01961 }
01962
01963 void Sheet::viewportMouseMoveEvent(QMouseEvent *e)
01964 {
01965 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01966 if (clicksLocked)
01967 {
01968 if (selectionNo>=0)
01969 {
01970 QTableSelection oldSelection(selection(selectionNo));
01971 oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01972 if (!(oldSelection==selection(selectionNo)))
01973 {
01974 removeSelection(selectionNo);
01975 selectionNo=addSelection(oldSelection);
01976 }
01977 }
01978 }
01979 else
01980 QTable::contentsMouseMoveEvent(&ce);
01981 }
01982
01983 void Sheet::viewportMouseReleaseEvent(QMouseEvent *e)
01984 {
01985 QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01986 if (clicksLocked && selectionNo>=0)
01987 {
01988 QTableSelection oldSelection(selection(selectionNo));
01989 oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01990 removeSelection(selectionNo);
01991 selectionNo=-1;
01992 if (oldSelection.topRow()==oldSelection.bottomRow() && oldSelection.leftCol()==oldSelection.rightCol())
01993 emit cellClicked(findCellName(oldSelection.topRow(), oldSelection.leftCol()));
01994 else
01995 emit cellClicked(findCellName(oldSelection.topRow(), oldSelection.leftCol())+','+findCellName(oldSelection.bottomRow(), oldSelection.rightCol()));
01996 }
01997 else
01998 QTable::contentsMouseReleaseEvent(&ce);
01999 }
02000
02001 QString Sheet::findCellName(int row, int col)
02002 {
02003 return (getHeaderString(col+1)+QString::number(row+1));
02004 }
02005
02006 void Sheet::copySheetData(QList<typeCellData> *destSheetData)
02007 {
02008 typeCellData *tempCellData, *newCellData;
02009 destSheetData->clear();
02010
02011 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02012 {
02013 newCellData=new typeCellData;
02014 *newCellData=*tempCellData;
02015 destSheetData->append(newCellData);
02016 }
02017 }
02018
02019 void Sheet::setSheetData(QList<typeCellData> *srcSheetData)
02020 {
02021 typeCellData *tempCellData, *newCellData;
02022
02023 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02024 {
02025 clearCell(tempCellData->row, tempCellData->col);
02026 updateCell(tempCellData->row, tempCellData->col);
02027 }
02028 sheetData.clear();
02029
02030 for (tempCellData=srcSheetData->first(); tempCellData; tempCellData=srcSheetData->next())
02031 {
02032 newCellData=new typeCellData;
02033 *newCellData=*tempCellData;
02034 sheetData.append(newCellData);
02035 setText(newCellData->row, newCellData->col, dataParser(findCellName(newCellData->row, newCellData->col), newCellData->data));
02036 }
02037 emit sheetModified();
02038 }
02039
02040 void Sheet::setName(const QString &name)
02041 {
02042 sheetName=name;
02043 emit sheetModified();
02044 }
02045
02046 QString Sheet::getName()
02047 {
02048 return sheetName;
02049 }
02050
02051 void Sheet::setBrush(int row, int col, const QBrush &brush)
02052 {
02053 typeCellData *cellData=findCellData(row, col);
02054 if (!cellData) cellData=createCellData(row, col);
02055 if (cellData)
02056 {
02057 cellData->background=brush;
02058 emit sheetModified();
02059 }
02060 }
02061
02062 QBrush Sheet::getBrush(int row, int col)
02063 {
02064 typeCellData *cellData=findCellData(row, col);
02065 if (!cellData) cellData=&defaultCellData;
02066 return cellData->background;
02067 }
02068
02069 void Sheet::setTextAlign(int row, int col, Qt::AlignmentFlags flags)
02070 {
02071 typeCellData *cellData=findCellData(row, col);
02072 if (!cellData) cellData=createCellData(row, col);
02073 if (cellData)
02074 {
02075 cellData->alignment=flags;
02076 emit sheetModified();
02077 }
02078 }
02079
02080 Qt::AlignmentFlags Sheet::getAlignment(int row, int col)
02081 {
02082 typeCellData *cellData=findCellData(row, col);
02083 if (!cellData) cellData=&defaultCellData;
02084 return cellData->alignment;
02085 }
02086
02087 void Sheet::setTextFont(int row, int col, const QFont &font, const QColor &color)
02088 {
02089 typeCellData *cellData=findCellData(row, col);
02090 if (!cellData) cellData=createCellData(row, col);
02091 if (cellData)
02092 {
02093 cellData->font=font;
02094 cellData->fontColor=color;
02095 emit sheetModified();
02096 }
02097 }
02098
02099 QFont Sheet::getFont(int row, int col)
02100 {
02101 typeCellData *cellData=findCellData(row, col);
02102 if (!cellData) cellData=&defaultCellData;
02103 return cellData->font;
02104 }
02105
02106 QColor Sheet::getFontColor(int row, int col)
02107 {
02108 typeCellData *cellData=findCellData(row, col);
02109 if (!cellData) cellData=&defaultCellData;
02110 return cellData->fontColor;
02111 }
02112
02113 void Sheet::setPen(int row, int col, int vertical, const QPen &pen)
02114 {
02115 typeCellData *cellData=findCellData(row, col);
02116 if (!cellData) cellData=createCellData(row, col);
02117 if (cellData)
02118 {
02119 if (vertical)
02120 cellData->borders.right=pen;
02121 else
02122 cellData->borders.bottom=pen;
02123 emit sheetModified();
02124 }
02125 }
02126
02127 QPen Sheet::getPen(int row, int col, int vertical)
02128 {
02129 typeCellData *cellData=findCellData(row, col);
02130 if (!cellData) cellData=&defaultCellData;
02131 return (vertical ? cellData->borders.right : cellData->borders.bottom);
02132 }
02133
02134 void Sheet::getSelection(int *row1, int *col1, int *row2, int *col2)
02135 {
02136 int selectionNo=currentSelection();
02137 if (selectionNo>=0)
02138 {
02139 QTableSelection select(selection(selectionNo));
02140 *row1=select.topRow();
02141 *row2=select.bottomRow();
02142 *col1=select.leftCol();
02143 *col2=select.rightCol();
02144 }
02145 else
02146 {
02147 *row1=*row2=currentRow();
02148 *col1=*col2=currentColumn();
02149 }
02150 }
02151
02152 void Sheet::editClear()
02153 {
02154 int row1, row2, col1, col2;
02155 getSelection(&row1, &col1, &row2, &col2);
02156
02157 int row, col;
02158 for (row=row1; row<=row2; ++row)
02159 for (col=col1; col<=col2; ++col)
02160 {
02161 setText(row, col, "");
02162 slotCellChanged(row, col);
02163 }
02164 }
02165
02166 void Sheet::editCopy()
02167 {
02168 clipboardData.clear();
02169
02170 int row1, row2, col1, col2;
02171 getSelection(&row1, &col1, &row2, &col2);
02172
02173 typeCellData *cellData, *newCellData;
02174 int row, col;
02175 for (row=row1; row<=row2; ++row)
02176 for (col=col1; col<=col2; ++col)
02177 {
02178 cellData=findCellData(row, col);
02179 if (cellData)
02180 {
02181 newCellData=new typeCellData;
02182 *newCellData=*cellData;
02183 newCellData->row-=row1;
02184 newCellData->col-=col1;
02185 clipboardData.append(newCellData);
02186 }
02187 }
02188 }
02189
02190 void Sheet::editCut()
02191 {
02192 editCopy();
02193 editClear();
02194 }
02195
02196 void Sheet::editPaste(bool onlyContents)
02197 {
02198 int row1=currentRow(), col1=currentColumn();
02199 typeCellData *cellData, *tempCellData;
02200
02201 for (tempCellData=clipboardData.first(); tempCellData; tempCellData=clipboardData.next())
02202 {
02203 cellData=findCellData(tempCellData->row+row1, tempCellData->col+col1);
02204 if (!cellData) cellData=createCellData(tempCellData->row+row1, tempCellData->col+col1);
02205 if (cellData)
02206 {
02207 if (onlyContents)
02208 cellData->data=tempCellData->data;
02209 else
02210 {
02211 *cellData=*tempCellData;
02212 cellData->row+=row1;
02213 cellData->col+=col1;
02214 }
02215 setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
02216 emit sheetModified();
02217 }
02218 }
02219 }
02220
02221 void Sheet::insertRows(int no, bool allColumns)
02222 {
02223 setNumRows(numRows()+no);
02224
02225 typeCellData *tempCellData;
02226 int row=currentRow(), col=currentColumn();
02227
02228 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02229 if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
02230 {
02231 clearCell(tempCellData->row, tempCellData->col);
02232 tempCellData->row+=no;
02233 }
02234 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02235 if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
02236 {
02237 updateCell(tempCellData->row-no, tempCellData->col);
02238 setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02239 }
02240 emit sheetModified();
02241 }
02242
02243 void Sheet::insertColumns(int no, bool allRows)
02244 {
02245 int noCols=numCols();
02246 int newCols=noCols+no;
02247 setNumCols(newCols);
02248 for (int i=noCols; i<newCols; ++i)
02249 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
02250
02251 typeCellData *tempCellData;
02252 int col=currentColumn(), row=currentRow();
02253
02254 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02255 if (tempCellData->col>=col && (allRows || tempCellData->row==row))
02256 {
02257 clearCell(tempCellData->row, tempCellData->col);
02258 tempCellData->col+=no;
02259 }
02260 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02261 if (tempCellData->col>=col && (allRows || tempCellData->row==row))
02262 {
02263 updateCell(tempCellData->row, tempCellData->col-no);
02264 setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02265 }
02266 emit sheetModified();
02267 }
02268
02269 void Sheet::dataFindReplace(const QString &findStr, const QString &replaceStr, bool matchCase, bool allCells, bool entireCell, bool replace, bool replaceAll)
02270 {
02271 typeCellData *tempCellData;
02272 int row1, col1, row2, col2;
02273 getSelection(&row1, &col1, &row2, &col2);
02274 bool found=FALSE;
02275
02276 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02277 if (allCells || (tempCellData->row>=row1 && tempCellData->row<=row2 && tempCellData->col>=col1 && tempCellData->col<=col2))
02278 {
02279 QTableItem *cellItem=item(tempCellData->row, tempCellData->col);
02280 if (cellItem && (entireCell ? (matchCase ? cellItem->text()==findStr : cellItem->text().upper()==findStr.upper()) : cellItem->text().find(findStr, 0, matchCase)>=0))
02281 {
02282 if (!found)
02283 {
02284 found=TRUE;
02285 clearSelection();
02286 }
02287 setCurrentCell(tempCellData->row, tempCellData->col);
02288 if (replace)
02289 {
02290 tempCellData->data=cellItem->text().replace(QRegExp(findStr, matchCase), replaceStr);
02291 setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02292 }
02293 if (!replace || !replaceAll) break;
02294 }
02295 }
02296
02297 if (found)
02298 {
02299 if (replace)
02300 slotCellChanged(currentRow(), currentColumn());
02301 }
02302 else
02303 QMessageBox::warning(this, tr("Error"), tr("Search key not found!"));
02304 }
02305
02306
02307
02308
02309
02310 QString Sheet::getHeaderString(int section)
02311 {
02312 if (section<1) return "";
02313 return getHeaderString((section-1)/26)+QChar('A'+(section-1)%26);
02314 }
02315
02316 int Sheet::getHeaderColumn(const QString §ion)
02317 {
02318 if (section.isEmpty()) return 0;
02319 return (section[section.length()-1]-'A'+1)+getHeaderColumn(section.left(section.length()-1))*26;
02320 }
02321
02322
02323
02324
02325
02326 QChar Expression::chunk0(void)
02327 {
02328 if(chunk.length()>0) return(chunk[0]); else return('\0');
02329 };
02330
02331 Expression::Expression(QString expr1)
02332 {
02333 Body=expr1;
02334 SYMBOL="+-*/%^=()<>&|!,";
02335 MATHSYMBOL="+-*/%^=<>&|!,";
02336
02337
02338 ErrorFound=TRUE;
02339 n=0;chunk="";SymbGroup=NONE_TOKEN;InExpr=Body;
02340 ArgsOfFunc=0;
02341 CompiledBody.setAutoDelete(TRUE);
02342 CompiledBodyType.setAutoDelete(TRUE);
02343
02344 };
02345
02346 bool Expression::isSymbol(QChar ch)
02347 {
02348 int j = 0;
02349 while (j<=((int)SYMBOL.length()-1) && ch!=SYMBOL[j]) j++;
02350 if(j<((int)SYMBOL.length())) return true; else return false;
02351 };
02352
02353 bool Expression::isMathSymbol(QChar ch)
02354 {
02355 int j = 0;
02356 while (j<=((int)MATHSYMBOL.length()-1) && ch!=MATHSYMBOL[j]) j++;
02357 if(j<((int)MATHSYMBOL.length())) return true; else return false;
02358 };
02359
02360 void Expression::GetNext()
02361 {
02362 chunk="";
02363 if(n>=(int)InExpr.length()) return;
02364 while (InExpr[n]==' ') n++;
02365 if(InExpr[n]=='\"')
02366 {
02367 while ( (n<(int)InExpr.length()) && (InExpr[n+1]!='\"') )
02368 {
02369 printf("chunk=%s\r\n",chunk.latin1());
02370 chunk+=InExpr[n];
02371 n++;
02372 };
02373 chunk+=InExpr[n];
02374 printf("2\r\n");
02375 SymbGroup=STRING_TOKEN;
02376 }
02377 else if (isSymbol(InExpr[n]))
02378 {
02379 SymbGroup=SYMBOL_TOKEN;
02380 chunk+=InExpr[n];
02381 n++;
02382 if( (n<(int)InExpr.length()) &&
02383 isMathSymbol(InExpr[n-1]) &&
02384 isMathSymbol(InExpr[n]) )
02385 {
02386 SymbGroup=SYMBOL_TOKEN;
02387 chunk+=InExpr[n];
02388 n++;
02389 };
02390 }
02391 else if ((InExpr[n].isLetter())||(InExpr[n]=='#'))
02392 {
02393 while ( (n<(int)InExpr.length()) && !isSymbol(InExpr[n]) )
02394 {
02395 if (!(InExpr[n]==' ')) chunk+=InExpr[n];
02396 n++;
02397 };
02398 if (InExpr[n]=='(') SymbGroup=FUNCTION_TOKEN;
02399 else SymbGroup=VARIABLE_TOKEN;
02400 }
02401 else if((n<(int)InExpr.length()) &&
02402 ((InExpr[n].isDigit()) || (InExpr[n]=='.')))
02403 {
02404 while( n<(int)InExpr.length() )
02405 {
02406 if((InExpr[n].isDigit()) || InExpr[n]=='.')
02407 {
02408 chunk+=InExpr[n];
02409 SymbGroup=NUMBER_TOKEN;
02410 n++;
02411 }
02412 else if(InExpr[n]=='e')
02413 {
02414 if((n+1)<(int)InExpr.length())
02415 {
02416 if(InExpr[n+1]=='-' || InExpr[n+1]=='+' || InExpr[n+1].isDigit())
02417 {
02418 chunk+=InExpr[n];
02419 chunk+=InExpr[n+1];
02420 SymbGroup=NUMBER_TOKEN;
02421 n+=2;
02422 }
02423 }
02424 else
02425 {
02426 break;
02427 }
02428 }
02429 else
02430 {
02431 break;
02432 }
02433 }
02434 }
02435 }
02436 ;
02437
02438
02439 void Expression::First()
02440 {
02441 GetNext();
02442 if (!(chunk=="") && !ErrorFound) Third();
02443 else ErrorFound = true;
02444 };
02445
02446 void Expression::Third()
02447 {
02448 QChar sign, secS='\0';
02449 Fourth();
02450 sign = chunk0();
02451 if((int)chunk.length()>1) secS=chunk[1];
02452 while( sign == '+' || sign == '-'||
02453 sign == '<' || sign == '>'|| sign == '%'||
02454 sign == '&' || sign == '|' || sign == '!' || sign == '='
02455 )
02456 {
02457 GetNext();
02458 Fourth();
02459 QString name;
02460 if( sign == '+' ) name= "+" ;
02461 else if(sign=='-') name= "-" ;
02462 else if(sign=='>' && secS=='\0') name= ">" ;
02463 else if(sign=='<' && secS=='\0') name= "<" ;
02464 else if(sign=='=' && secS=='=') name= "==" ;
02465 else if(sign=='!' && secS=='=') name= "!=" ;
02466 else if(sign=='>' && secS=='=') name= ">=" ;
02467 else if(sign=='<' && secS=='=') name= "<=" ;
02468 else if(sign=='&' && secS=='&') name= "AND" ;
02469 else if(sign=='|' && secS=='|') name= "OR" ;
02470 else if(sign=='%') name= "MOD" ;
02471 CompiledBody.append(new QString(name));
02472 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8));
02473 sign = chunk0();
02474 }
02475 };
02476
02477 void Expression::Fourth()
02478 {
02479 QChar sign;
02480 Fifth();
02481 sign = chunk0();
02482 while( sign == '*' || sign == '/' )
02483 {
02484 GetNext();
02485 Fifth();
02486 QString name;
02487 if( sign == '*' ) name= "*" ;
02488 else name= "/" ;
02489 CompiledBody.append(new QString(name));
02490 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8));
02491 sign = chunk0();
02492 }
02493 };
02494
02495 void Expression::Fifth()
02496 {
02497 Sixth();
02498
02499 if( chunk0() == '^' )
02500 {
02501 GetNext();
02502 Fifth();
02503 CompiledBody.append(new QString("POWER"));
02504 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8));
02505 }
02506 };
02507
02508 void Expression::Sixth()
02509 {
02510 char sign;
02511 sign = ' ';
02512 if(SymbGroup== SYMBOL_TOKEN &&
02513 chunk0() == '+' || chunk0() == '-' | chunk0() == '!')
02514 {
02515 sign = chunk0();
02516 GetNext();
02517 }
02518 Seventh();
02519 if( sign == '-' )
02520 {
02521 CompiledBody.append(new QString("CHGSGN"));
02522 CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8));
02523 }
02524 if( sign == '!' )
02525 {
02526 CompiledBody.append(new QString("NOT"));
02527 CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8));
02528 }
02529 };
02530
02531
02532 void Expression::Seventh()
02533 {
02534 if( chunk0() == '(' && SymbGroup==SYMBOL_TOKEN)
02535 {
02536 GetNext();
02537 Third();
02538 if (chunk0() != ')') ErrorFound = true;
02539 GetNext();
02540 }
02541 else Eighth();
02542 };
02543
02544 void Expression::Eighth()
02545 {
02546 if ( SymbGroup== NUMBER_TOKEN )
02547 {
02548 CompiledBody.append(new QString(chunk));
02549 CompiledBodyType.append(new int(NUMBER_TOKEN));
02550 GetNext();
02551 }
02552 else if ( SymbGroup== VARIABLE_TOKEN )
02553 {
02554 CompiledBody.append(new QString(chunk));
02555 CompiledBodyType.append(new int(VARIABLE_TOKEN));
02556 GetNext();
02557 }
02558 else if (SymbGroup== STRING_TOKEN )
02559 {
02560 CompiledBody.append(new QString(chunk+QString("\"")));
02561 CompiledBodyType.append(new int(STRING_TOKEN));
02562 GetNext();
02563 }
02564 else Ninth();
02565 };
02566
02567 void Expression::Ninth()
02568 {
02569 if ( SymbGroup== FUNCTION_TOKEN )
02570 {
02571 QString TempFunk = chunk ;
02572 GetNext();
02573 if(chunk0() == '(' )
02574 {
02575 FuncDepth++;
02576 ArgsOfFunc.resize(FuncDepth+1);
02577 ArgsOfFunc[FuncDepth]=1;
02578
02579 GetNext();
02580 Third();
02581 while(chunk0()==',')
02582 {
02583
02584 ArgsOfFunc[FuncDepth]++;
02585 GetNext();
02586 Third();
02587 };
02588 if (chunk0() != ')') ErrorFound = true;
02589
02590 CompiledBody.append(new QString(TempFunk));
02591 if (TempFunk=="PI") ArgsOfFunc[FuncDepth]=0;
02592
02593 CompiledBodyType.append(new int(FUNCTION_TOKEN | (ArgsOfFunc[FuncDepth]<<8) ));
02594
02595 FuncDepth--;
02596 ArgsOfFunc.resize(FuncDepth+1);
02597 GetNext();
02598 }
02599 }
02600 else
02601 ErrorFound = true;
02602 };
02603
02604 bool Expression::Parse()
02605 {
02606 CompiledBody.clear();
02607 ErrorFound = false;
02608 n = 0;ArgsOfFunc.resize(0);FuncDepth=0;
02609 InExpr=Body;
02610 First();
02611 return(!ErrorFound);
02612 };
02613
02614