00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <math.h>
00025 #include <float.h>
00026
00027 #include <kdebug.h>
00028
00029 #include <koscript_parser.h>
00030 #include <koscript_util.h>
00031 #include <koscript_func.h>
00032 #include <koscript_synext.h>
00033
00034 #include "kspread_doc.h"
00035 #include "kspread_functions.h"
00036 #include "kspread_interpreter.h"
00037 #include "kspread_sheet.h"
00038 #include "kspread_util.h"
00039 #include "kspread_value.h"
00040
00041
00042 bool kspreadfunc_address( KSContext & context );
00043 bool kspreadfunc_areas( KSContext & context );
00044 bool kspreadfunc_choose( KSContext & context );
00045 bool kspreadfunc_column( KSContext & context );
00046 bool kspreadfunc_columns( KSContext & context );
00047 bool kspreadfunc_indirect( KSContext & context );
00048 bool kspreadfunc_lookup( KSContext & context );
00049 bool kspreadfunc_row( KSContext & context );
00050 bool kspreadfunc_rows( KSContext & context );
00051
00052
00053 void KSpreadRegisterReferenceFunctions()
00054 {
00055 KSpreadFunctionRepository * repo = KSpreadFunctionRepository::self();
00056 repo->registerFunction( "ADDRESS", kspreadfunc_address );
00057 repo->registerFunction( "AREAS", kspreadfunc_areas );
00058 repo->registerFunction( "CHOOSE", kspreadfunc_choose );
00059 repo->registerFunction( "COLUMN", kspreadfunc_column );
00060 repo->registerFunction( "COLUMNS", kspreadfunc_columns );
00061 repo->registerFunction( "INDIRECT", kspreadfunc_indirect );
00062 repo->registerFunction( "LOOKUP", kspreadfunc_lookup );
00063 repo->registerFunction( "ROW", kspreadfunc_row );
00064 repo->registerFunction( "ROWS", kspreadfunc_rows );
00065 }
00066
00067
00068 bool kspreadfunc_address( KSContext & context )
00069 {
00070 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00071 bool r1c1 = false;
00072 QString sheetName;
00073 int absNum = 1;
00074
00075 if ( !KSUtil::checkArgumentsCount( context, 5, "ADDRESS", false ) )
00076 {
00077 if ( !KSUtil::checkArgumentsCount( context, 4, "ADDRESS", false ) )
00078 {
00079 r1c1 = false;
00080
00081 if ( !KSUtil::checkArgumentsCount( context, 3, "ADDRESS", false ) )
00082 {
00083 absNum = 1;
00084
00085 if ( !KSUtil::checkArgumentsCount( context, 2, "ADDRESS", true ) )
00086 return false;
00087 }
00088 else
00089 {
00090 if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00091 return false;
00092
00093 absNum = args[2]->intValue();
00094 }
00095 }
00096 else
00097 {
00098 if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00099 return false;
00100
00101 if ( !KSUtil::checkType( context, args[3], KSValue::BoolType, true ) )
00102 return false;
00103
00104 absNum = args[2]->intValue();
00105 r1c1 = !args[3]->boolValue();
00106 }
00107 }
00108 else
00109 {
00110 if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00111 return false;
00112
00113 if ( !KSUtil::checkType( context, args[3], KSValue::BoolType, true ) )
00114 return false;
00115
00116 if ( !KSUtil::checkType( context, args[4], KSValue::StringType, true ) )
00117 return false;
00118
00119 absNum = args[2]->intValue();
00120 r1c1 = !args[3]->boolValue();
00121 sheetName = args[4]->stringValue();
00122 }
00123
00124 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00125 return false;
00126 if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00127 return false;
00128
00129 QString result;
00130 int row = args[0]->intValue();
00131 int col = args[1]->intValue();
00132
00133 if ( !sheetName.isEmpty() )
00134 {
00135 result += sheetName;
00136 result += "!";
00137 }
00138
00139 if ( r1c1 )
00140 {
00141
00142 bool abs = false;
00143 if ( absNum == 1 || absNum == 2 )
00144 abs = true;
00145
00146 result += 'R';
00147 if ( !abs )
00148 result += '[';
00149 result += QString::number( row );
00150
00151 if ( !abs )
00152 result += ']';
00153
00154
00155 abs = false;
00156 if ( absNum == 1 || absNum == 3 )
00157 abs = true;
00158
00159 result += 'C';
00160 if ( !abs )
00161 result += '[';
00162 result += QString::number( col );
00163
00164 if ( !abs )
00165 result += ']';
00166 }
00167 else
00168 {
00169 bool abs = false;
00170 if ( absNum == 1 || absNum == 3 )
00171 abs = true;
00172
00173 if ( abs )
00174 result += '$';
00175
00176 result += KSpreadCell::columnName( col );
00177
00178 abs = false;
00179 if ( absNum == 1 || absNum == 2 )
00180 abs = true;
00181
00182 if ( abs )
00183 result += '$';
00184
00185 result += QString::number( row );
00186 }
00187
00188 context.setValue( new KSValue( result ) );
00189
00190 return true;
00191 }
00192
00193 bool checkRef( QString const & ref )
00194 {
00195 KSpreadRange r( ref );
00196 if ( !r.isValid() )
00197 {
00198 KSpreadPoint p( ref );
00199 if ( !p.isValid() )
00200 return false;
00201 }
00202 return true;
00203 }
00204
00205
00206 bool kspreadfunc_areas( KSContext & context )
00207 {
00208 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00209 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00210
00211 if ( extra.count() > 0 )
00212 {
00213 context.setValue( new KSValue( (int) extra.count() ) );
00214 return true;
00215 }
00216
00217 if ( !KSUtil::checkArgumentsCount( context, 1, "AREAS", true ) )
00218 return false;
00219
00220 QString s = args[0]->stringValue();
00221 if ( s[0] != '(' || s[s.length() - 1] != ')' )
00222 return false;
00223
00224 int l = s.length();
00225
00226 int num = 0;
00227 QString ref;
00228 for ( int i = 1; i < l; ++i )
00229 {
00230 if ( s[i] == ',' || s[i] == ')' )
00231 {
00232 if ( !checkRef( ref ) )
00233 return false;
00234 else
00235 {
00236 ++num;
00237 ref = "";
00238 }
00239 }
00240 else
00241 ref += s[i];
00242 }
00243
00244 context.setValue( new KSValue( num ) );
00245 return true;
00246 }
00247
00248
00249 bool kspreadfunc_choose( KSContext & context )
00250 {
00251 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00252
00253 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00254 QValueList<KSValue::Ptr>::Iterator end = args.end();
00255
00256 int index = -1;
00257 int count = 0;
00258
00259 for( ; it != end; ++it )
00260 {
00261 if ( index == -1 )
00262 {
00263 if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00264 return false;
00265
00266 index = args[0]->intValue();
00267
00268 if ( index < 1 )
00269 return false;
00270 }
00271 else
00272 {
00273 if ( KSUtil::checkType( context, *it, KSValue::ListType, true ) )
00274 {
00275 QValueList<KSValue::Ptr> list( (*it)->listValue() );
00276
00277 QValueList<KSValue::Ptr>::Iterator listIter = list.begin();
00278 QValueList<KSValue::Ptr>::Iterator listEnd = list.end();
00279
00280 if ( KSUtil::checkType( context, *listIter, KSValue::ListType, true ) )
00281 {
00282 list = (*listIter)->listValue();
00283
00284 listIter = list.begin();
00285 listEnd = list.end();
00286 }
00287
00288 while ( listIter != listEnd )
00289 {
00290 if ( count == index )
00291 {
00292 if ( KSUtil::checkType( context, *listIter, KSValue::StringType, true ) )
00293 context.setValue( new KSValue( (*listIter)->stringValue() ) );
00294 else if ( KSUtil::checkType( context, *listIter, KSValue::DoubleType, true ) )
00295 context.setValue( new KSValue( (*listIter)->doubleValue() ) );
00296 else if ( KSUtil::checkType( context, *listIter, KSValue::BoolType, true ) )
00297 context.setValue( new KSValue( (*listIter)->boolValue() ) );
00298 else if ( KSUtil::checkType( context, *listIter, KSValue::IntType, true ) )
00299 context.setValue( new KSValue( (*listIter)->intValue() ) );
00300 else if ( KSUtil::checkType( context, *listIter, KSValue::DateType, true ) )
00301 context.setValue( new KSValue( (*listIter)->dateValue() ) );
00302 else if ( KSUtil::checkType( context, *listIter, KSValue::TimeType, true ) )
00303 context.setValue( new KSValue( (*listIter)->timeValue() ) );
00304 else
00305 {
00306 kdDebug() << "Unkown type" << endl;
00307 return false;
00308 }
00309
00310 return true;
00311 }
00312 ++count;
00313 ++listIter;
00314 }
00315 }
00316 else if ( count == index )
00317 {
00318 if ( KSUtil::checkType( context, *it, KSValue::StringType, true ) )
00319 context.setValue( new KSValue( (*it)->stringValue() ) );
00320 else if ( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00321 context.setValue( new KSValue( (*it)->doubleValue() ) );
00322 else if ( KSUtil::checkType( context, *it, KSValue::BoolType, true ) )
00323 context.setValue( new KSValue( (*it)->boolValue() ) );
00324 else if ( KSUtil::checkType( context, *it, KSValue::IntType, true ) )
00325 context.setValue( new KSValue( (*it)->intValue() ) );
00326 else if ( KSUtil::checkType( context, *it, KSValue::DateType, true ) )
00327 context.setValue( new KSValue( (*it)->dateValue() ) );
00328 else if ( KSUtil::checkType( context, *it, KSValue::TimeType, true ) )
00329 context.setValue( new KSValue( (*it)->timeValue() ) );
00330 else
00331 return false;
00332 return true;
00333 }
00334 }
00335 ++count;
00336 }
00337
00338 return false;
00339 }
00340
00341
00342 bool kspreadfunc_column( KSContext & context )
00343 {
00344 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00345
00346 KSpreadCell * cell = ((KSpreadInterpreter *) context.interpreter() )->cell();
00347
00348 if ( !KSUtil::checkArgumentsCount( context, 1, "COLUMN", false ) )
00349 {
00350 if ( cell )
00351 {
00352 context.setValue( new KSValue( (int) cell->column() ) );
00353 return true;
00354 }
00355 else
00356 return false;
00357 }
00358 else
00359 {
00360 if ( extra.count() > 0 )
00361 {
00362 QString s( extra[0]->stringValue() );
00363
00364 KSpreadRange ra( s );
00365 if ( ra.range.left() <= 0 || ra.range.right() <= 0 )
00366 {
00367 KSpreadPoint p( s );
00368 if ( p.pos.x() <= 0 || p.pos.y() <= 0 )
00369 return false;
00370
00371 context.setValue( new KSValue( p.pos.x() ) );
00372 return true;
00373 }
00374 else
00375 {
00376 context.setValue( new KSValue( ra.range.left() ) );
00377 return true;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 }
00397 }
00398
00399 return false;
00400 }
00401
00402
00403 bool kspreadfunc_columns( KSContext & context )
00404 {
00405 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00406 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00407
00408 if ( !KSUtil::checkArgumentsCount( context, 1, "COLUMNS", true ) )
00409 return false;
00410
00411 if ( extra.count() > 0 )
00412 {
00413 QString s( extra[0]->stringValue() );
00414
00415 KSpreadRange r( s );
00416 if ( r.range.left() <= 0 || r.range.right() <= 0 )
00417 {
00418 KSpreadPoint p( s );
00419 if ( p.pos.x() <= 0 || p.pos.y() <= 0 )
00420 return false;
00421
00422 context.setValue( new KSValue( (int) 1 ) );
00423 return true;
00424 }
00425
00426 context.setValue( new KSValue( r.range.width() ) );
00427 return true;
00428 }
00429 return false;
00430 if ( args.count() > 0 )
00431 {
00432 if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00433 return false;
00434
00435 QString s( args[0]->stringValue() );
00436
00437 int l = s.length();
00438 int n = s.find( '[' );
00439 if ( n == -1 )
00440 return false;
00441 int n2 = s.find( '[', n + 1 );
00442 if ( n2 != -1 )
00443 n = n2;
00444 int count = 0;
00445 for ( int i = n; i < l; ++i )
00446 {
00447 if ( s[i] == ',' )
00448 ++count;
00449 else if ( s[i] == ']' )
00450 {
00451 ++count;
00452 break;
00453 }
00454 }
00455
00456 context.setValue( new KSValue( count ) );
00457 return true;
00458 }
00459
00460 return false;
00461 }
00462
00463
00464
00465 bool kspreadfunc_indirect( KSContext & context )
00466 {
00467 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00468 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00469
00470 if ( !KSUtil::checkArgumentsCount( context, 1, "INDIRECT", true ) )
00471 return false;
00472
00473 bool r1c1 = false;
00474 if ( !KSUtil::checkArgumentsCount( context, 2, "INDIRECT", false ) )
00475 r1c1 = false;
00476 else
00477 {
00478 if ( !KSUtil::checkType( context, args[1], KSValue::BoolType, true ) )
00479 return false;
00480
00481 r1c1 = !args[1]->boolValue();
00482 }
00483
00484 QString ref;
00485
00486 if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00487 {
00488 if ( !KSUtil::checkType( context, extra[0], KSValue::StringType, true ) )
00489 return false;
00490 ref = extra[0]->stringValue();
00491 }
00492 else
00493 ref = args[0]->stringValue();
00494
00495 if ( ref.isEmpty() )
00496 return false;
00497
00498 if ( r1c1 )
00499 {
00500
00501 ref = ref;
00502 }
00503
00504 KSpreadMap * map = ((KSpreadInterpreter *) context.interpreter() )->document()->map();
00505 KSpreadSheet * sheet = ((KSpreadInterpreter *) context.interpreter() )->sheet();
00506
00507 KSpreadPoint p( ref, map, sheet );
00508
00509 if ( !p.isValid() )
00510 return false;
00511
00512 KSpreadCell * cell = p.cell();
00513 if ( cell )
00514 {
00515 if ( cell->value().isString() )
00516 context.setValue( new KSValue( cell->value().asString() ) );
00517 else if ( cell->value().isNumber() )
00518 context.setValue( new KSValue( cell->value().asFloat() ) );
00519 else if ( cell->value().isBoolean() )
00520 context.setValue( new KSValue( cell->value().asBoolean() ) );
00521 else if ( cell->isDate() )
00522 context.setValue( new KSValue( cell->value().asDate() ) );
00523 else if ( cell->isTime() )
00524 context.setValue( new KSValue( cell->value().asTime() ) );
00525 else if ( cell->value().isEmpty() || cell->isEmpty() || cell->isDefault() )
00526 context.setValue( new KSValue( (int) 0 ) );
00527 else
00528 context.setValue( new KSValue( cell->strOutText() ) );
00529
00530 return true;
00531 }
00532
00533 return false;
00534 }
00535
00536 static bool isEqualLess( KSContext & context, KSpreadValue::Type type, KSValue::Ptr const & value,
00537 double dValue, QString const & sValue, bool bValue )
00538 {
00539 if ( ( type == KSpreadValue::Float )
00540 && ( KSUtil::checkType( context, value, KSValue::DoubleType, true ) ) )
00541 {
00542 if ( dValue <= value->doubleValue() )
00543 return true;
00544
00545 return false;
00546 }
00547
00548 else if ( type == KSpreadValue::Integer || type == KSpreadValue::Float )
00549 return true;
00550
00551 else if ( ( type == KSpreadValue::String )
00552 && ( KSUtil::checkType( context, value, KSValue::StringType, true ) ) )
00553 {
00554 if ( sValue.lower() <= value->stringValue().lower() )
00555 return true;
00556
00557 return false;
00558 }
00559
00560 else if ( type == KSpreadValue::String )
00561 return true;
00562
00563 else if ( ( type == KSpreadValue::Boolean )
00564 && ( KSUtil::checkType( context, value, KSValue::BoolType, true ) ) )
00565 {
00566 if ( (int) bValue <= (int) value->boolValue() )
00567 return true;
00568 }
00569
00570 return false;
00571 }
00572
00573 bool kspreadfunc_lookup( KSContext & context )
00574 {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00598
00599 if ( !KSUtil::checkArgumentsCount( context, 3, "LOOKUP", true ) )
00600 return false;
00601
00602 KSpreadValue::Type type;
00603
00604 if ( KSUtil::checkType( context, args[0], KSValue::BoolType, true ) )
00605 type = KSpreadValue::Boolean;
00606 else if ( KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00607 type = KSpreadValue::Float;
00608 else
00609 return false;
00610
00611 int index = -1;
00612
00613 double dValue = 0.0;
00614 QString sValue;
00615 bool bValue = false;
00616
00617 if ( type == KSpreadValue::Float || type == KSpreadValue::Integer )
00618 dValue = args[0]->doubleValue();
00619 if ( type == KSpreadValue::String )
00620 sValue = args[0]->stringValue();
00621 if ( type == KSpreadValue::Boolean )
00622 bValue = args[0]->boolValue();
00623
00624
00625 if ( !KSUtil::checkType( context, args[1], KSValue::ListType, true ) )
00626 {
00627 if ( KSUtil::checkType( context, args[2], KSValue::ListType, true ) )
00628 return false;
00629
00630 if ( ( type == KSpreadValue::Float || type == KSpreadValue::Integer )
00631 && ( KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) ) )
00632 {
00633 if ( dValue <= args[1]->doubleValue() )
00634 {
00635 context.setValue( new KSValue( args[2] ) );
00636 return true;
00637 }
00638 return false;
00639 }
00640 else
00641 if ( type == KSpreadValue::Float || type == KSpreadValue::Integer )
00642 {
00643 context.setValue( new KSValue( args[2] ) );
00644 return true;
00645 }
00646 else if ( ( type == KSpreadValue::String )
00647 && ( KSUtil::checkType( context, args[1], KSValue::StringType, true ) ) )
00648 {
00649 if ( sValue.lower() <= args[1]->stringValue().lower() )
00650 {
00651 context.setValue( new KSValue( args[2] ) );
00652 return true;
00653 }
00654 return false;
00655 }
00656 else if ( type == KSpreadValue::String )
00657 {
00658 context.setValue( new KSValue( args[2] ) );
00659 return true;
00660 }
00661 else if ( ( type == KSpreadValue::Boolean )
00662 && ( KSUtil::checkType( context, args[1], KSValue::BoolType, true ) ) )
00663 {
00664 if ( bValue <= args[1]->boolValue() )
00665 {
00666 context.setValue( new KSValue( args[2] ) );
00667 return true;
00668 }
00669 }
00670
00671 return false;
00672 }
00673
00674 QValueList<KSValue::Ptr> lookup( args[1]->listValue() );
00675 QValueList<KSValue::Ptr> & result = args[2]->listValue();
00676
00677 if ( lookup.count() != result.count() )
00678 return false;
00679
00680 index = -1;
00681 int l = lookup.count();
00682 for ( int i = 0; i < l; ++i )
00683 {
00684 if ( KSUtil::checkType( context, lookup[i], KSValue::DoubleType, true ) )
00685 kdDebug() << "Double" << endl;
00686 if ( KSUtil::checkType( context, lookup[i], KSValue::ListType, true ) )
00687 kdDebug() << "List" << endl;
00688 if ( KSUtil::checkType( context, lookup[i], KSValue::IntType, true ) )
00689 kdDebug() << "Int" << endl;
00690 if ( KSUtil::checkType( context, lookup[i], KSValue::StringType, true ) )
00691 kdDebug() << "String" << endl;
00692 kdDebug() << "index: " << index << ", " << dValue << endl;
00693 if ( !isEqualLess( context, type, lookup[i], dValue, sValue, bValue ) )
00694 {
00695 if ( index < 0 )
00696 return false;
00697 context.setValue( new KSValue( result[index] ) );
00698 return true;
00699 }
00700
00701 ++index;
00702 }
00703
00704 return false;
00705 }
00706
00707
00708 bool kspreadfunc_row( KSContext & context )
00709 {
00710 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00711
00712 KSpreadCell * cell = ((KSpreadInterpreter *) context.interpreter() )->cell();
00713
00714 if ( !KSUtil::checkArgumentsCount( context, 1, "ROW", false ) )
00715 {
00716 if ( cell )
00717 {
00718 context.setValue( new KSValue( (int) cell->row() ) );
00719 return true;
00720 }
00721 else
00722 return false;
00723 }
00724 else
00725 {
00726 if ( extra.count() > 0 )
00727 {
00728 QString s( extra[0]->stringValue() );
00729
00730 KSpreadRange r( s );
00731 if ( r.range.left() <= 0 || r.range.right() <= 0 )
00732 {
00733 KSpreadPoint p( s );
00734 if ( p.pos.y() <= 0 || p.pos.x() <= 0 )
00735 return false;
00736
00737 context.setValue( new KSValue( p.pos.y() ) );
00738 return true;
00739 }
00740 else
00741 {
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 context.setValue( new KSValue( r.range.top() ) );
00754 return true;
00755 }
00756
00757 }
00758 }
00759
00760 return false;
00761 }
00762
00763
00764 bool kspreadfunc_rows( KSContext & context )
00765 {
00766 QValueList<KSValue::Ptr> & args = context.value()->listValue();
00767 QValueList<KSValue::Ptr> & extra = context.extraData()->listValue();
00768
00769 if ( !KSUtil::checkArgumentsCount( context, 1, "ROWS", true ) )
00770 return false;
00771
00772 if ( extra.count() > 0 )
00773 {
00774 QString s( extra[0]->stringValue() );
00775 KSpreadRange r( s );
00776 if ( r.range.left() <= 0 || r.range.right() <= 0 )
00777 {
00778 KSpreadPoint p( s );
00779 if ( p.pos.y() <= 0 || p.pos.x() <= 0 )
00780 return false;
00781
00782 context.setValue( new KSValue( (int) 1 ) );
00783 return true;
00784 }
00785
00786 context.setValue( new KSValue( r.range.height() ) );
00787 return true;
00788 }
00789 else if ( args.count() > 0 )
00790 {
00791 if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00792 return false;
00793
00794 QString s( args[0]->stringValue() );
00795 int l = s.length();
00796 int n = s.find( '[' );
00797 if ( n == -1 )
00798 return false;
00799 int n2 = s.find( '[', n + 1 );
00800 if ( n2 != -1 )
00801 n = n2;
00802 int count = 0;
00803 for ( int i = n; i < l; ++i )
00804 {
00805 if ( s[i] == '[' )
00806 ++count;
00807 }
00808
00809 context.setValue( new KSValue( count ) );
00810 return true;
00811 }
00812
00813 return false;
00814 }
00815