00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "excel.h"
00022
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <vector>
00026 #include <string>
00027 #include <map>
00028 #include <stdio.h>
00029
00030 #include "pole.h"
00031 #include "swinder.h"
00032
00033
00034 namespace{
00035
00036 static inline unsigned long readU16( const void* p )
00037 {
00038 const unsigned char* ptr = (const unsigned char*) p;
00039 return ptr[0]+(ptr[1]<<8);
00040 }
00041
00042 static inline unsigned long readU32( const void* p )
00043 {
00044 const unsigned char* ptr = (const unsigned char*) p;
00045 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
00046 }
00047
00048 typedef double& data_64;
00049 inline void convert_64 (data_64 convert)
00050 {
00051 register unsigned char temp;
00052 register unsigned int u_int_temp;
00053 temp = ((unsigned char*)&convert)[0];
00054 ((unsigned char*)&convert)[0] = ((unsigned char*)&convert)[3];
00055 ((unsigned char*)&convert)[3] = temp;
00056 temp = ((unsigned char*)&convert)[1];
00057 ((unsigned char*)&convert)[1] = ((unsigned char*)&convert)[2];
00058 ((unsigned char*)&convert)[2] = temp;
00059 temp = ((unsigned char*)&convert)[4];
00060 ((unsigned char*)&convert)[4] = ((unsigned char*)&convert)[7];
00061 ((unsigned char*)&convert)[7] = temp;
00062 temp = ((unsigned char*)&convert)[5];
00063 ((unsigned char*)&convert)[5] = ((unsigned char*)&convert)[6];
00064 ((unsigned char*)&convert)[6] = temp;
00065
00066 u_int_temp = ((unsigned int *)&convert)[0];
00067 ((unsigned int *)&convert)[0] = ((unsigned int *)&convert)[1];
00068 ((unsigned int *)&convert)[1] = u_int_temp;
00069 }
00070
00071 inline bool isLittleEndian(void)
00072 {
00073 long i = 0x44332211;
00074 unsigned char* a = (unsigned char*) &i;
00075 return ( *a == 0x11 );
00076 }
00077
00078
00079
00080 static inline double readFloat64( const void*p )
00081 {
00082 const double* ptr = (const double*) p;
00083 double num = 0.0;
00084 num = *ptr;
00085
00086 if( !isLittleEndian() )
00087 convert_64( num );
00088
00089 return num;
00090 }
00091
00092
00093
00094 static inline void decodeRK( unsigned rkvalue, bool& isInteger,
00095 int& i, double& f )
00096 {
00097 double factor = (rkvalue & 0x01) ? 0.01 : 1;
00098 if( rkvalue & 0x02 )
00099 {
00100
00101 isInteger = true;
00102 i = (int)(factor * (*((int*) &rkvalue) >> 2) );
00103 }
00104 else
00105 {
00106
00107 isInteger = false;
00108 unsigned char* s = (unsigned char*) &rkvalue;
00109 unsigned char* r = (unsigned char*) &f;
00110 if( isLittleEndian() )
00111 {
00112 r[0] = r[1] = r[2] = r[3] = 0;
00113 r[4] = s[0] & 0xfc;
00114 r[5] = s[1]; r[6] = s[2]; r[7] = s[3];
00115 }
00116 else
00117 {
00118 r[0] = r[1] = r[2] = r[3] = 0;
00119 r[4] = s[0] & 0xfc;
00120 r[5] = s[1]; r[6] = s[2]; r[7] = s[3];
00121 }
00122 memcpy( &f, r, 8 );
00123 f *= factor;
00124 }
00125 }
00126
00127 }
00128
00129 namespace Swinder
00130 {
00131 std::ostream& operator<<( std::ostream& s, Swinder::UString ustring )
00132 {
00133 char* str = ustring.ascii();
00134 s << str;
00135 return s;
00136 }
00137
00138 }
00139
00140 using namespace Swinder;
00141
00142 static Value errorAsValue( int errorCode )
00143 {
00144 Value result( Value::Error );
00145
00146 switch( errorCode )
00147 {
00148 case 0x00: result = Value::errorNULL(); break;
00149 case 0x07: result = Value::errorDIV0(); break;
00150 case 0x0f: result = Value::errorVALUE(); break;
00151 case 0x17: result = Value::errorREF(); break;
00152 case 0x1d: result = Value::errorNAME(); break;
00153 case 0x24: result = Value::errorNUM(); break;
00154 case 0x2A: result = Value::errorNA(); break;
00155 default: break;
00156 };
00157
00158 return result;
00159 }
00160
00161
00162
00163
00164
00165
00166 class EString::Private
00167 {
00168 public:
00169 bool unicode;
00170 bool richText;
00171 UString str;
00172 unsigned size;
00173 };
00174
00175 EString::EString()
00176 {
00177 d = new EString::Private();
00178 d->unicode = false;
00179 d->richText = false;
00180 d->str = UString::null;
00181 d->size = 0;
00182 }
00183
00184 EString::EString( const EString& es )
00185 {
00186 d = new EString::Private();
00187 operator=( es );
00188 }
00189
00190 EString& EString::operator=( const EString& es )
00191 {
00192 d->unicode = es.d->unicode;
00193 d->richText = es.d->richText;
00194 d->size = es.d->size;
00195 d->str = es.d->str;
00196 return *this;
00197 }
00198
00199 EString::~EString()
00200 {
00201 delete d;
00202 }
00203
00204 bool EString::unicode() const
00205 {
00206 return d->unicode;
00207 }
00208
00209 void EString::setUnicode( bool u )
00210 {
00211 d->unicode = u;
00212 }
00213
00214 bool EString::richText() const
00215 {
00216 return d->richText;
00217 }
00218
00219 void EString::setRichText( bool r )
00220 {
00221 d->richText = r;
00222 }
00223
00224 UString EString::str() const
00225 {
00226 return d->str;
00227 }
00228
00229 void EString::setStr( const UString& str )
00230 {
00231 d->str = str;
00232 }
00233
00234 unsigned EString::size() const
00235 {
00236 return d->size;
00237 }
00238
00239 void EString::setSize( unsigned s )
00240 {
00241 d->size = s;
00242 }
00243
00244
00245 EString EString::fromUnicodeString( const void* p, bool longString, unsigned )
00246 {
00247 const unsigned char* data = (const unsigned char*) p;
00248 UString str = UString::null;
00249
00250 unsigned offset = longString ? 2 : 1;
00251 unsigned len = longString ? readU16( data ): data[0];
00252 unsigned char flag = data[ offset ];
00253 offset++;
00254
00255 bool unicode = flag & 0x01;
00256 bool richText = flag & 0x08;
00257 unsigned formatRuns = 0;
00258
00259 if( richText )
00260 {
00261 formatRuns = readU16( data + offset );
00262 offset += 2;
00263 }
00264
00265
00266 unsigned size = offset + len;
00267 if( unicode ) size += len;
00268 if( richText ) size += (formatRuns*4);
00269
00270 if( !unicode )
00271 {
00272 char* buffer = new char[ len+1 ];
00273 memcpy( buffer, data + offset, len );
00274 buffer[ len ] = 0;
00275 str = UString( buffer );
00276 delete[] buffer;
00277 }
00278 else
00279 {
00280 str = UString();
00281 for( unsigned k=0; k<len; k++ )
00282 {
00283 unsigned uchar = readU16( data + offset + k*2 );
00284 str.append( UString(UChar(uchar)) );
00285 }
00286 }
00287
00288 EString result;
00289 result.setUnicode( unicode );
00290 result.setRichText( richText );
00291 result.setSize( size );
00292 result.setStr( str );
00293
00294 return result;
00295 }
00296
00297
00298 EString EString::fromByteString( const void* p, bool longString,
00299 unsigned )
00300 {
00301 const unsigned char* data = (const unsigned char*) p;
00302 UString str = UString::null;
00303
00304 unsigned offset = longString ? 2 : 1;
00305 unsigned len = longString ? readU16( data ): data[0];
00306
00307 char* buffer = new char[ len+1 ];
00308 memcpy( buffer, data + offset, len );
00309 buffer[ len ] = 0;
00310 str = UString( buffer );
00311 delete[] buffer;
00312
00313 unsigned size = offset + len;
00314
00315 EString result;
00316 result.setUnicode( false );
00317 result.setRichText( false );
00318 result.setSize( size );
00319 result.setStr( str );
00320
00321 return result;
00322 }
00323
00324
00325
00326
00327 EString EString::fromSheetName( const void* p, unsigned datasize )
00328 {
00329 const unsigned char* data = (const unsigned char*) p;
00330 UString str = UString::null;
00331
00332 bool richText = false;
00333
00334
00335 unsigned len = data[0];
00336 unsigned flag = data[1];
00337 bool unicode = flag & 1;
00338
00339 if( len > datasize-2 ) len = datasize-2;
00340 if( len == 0 ) return EString();
00341
00342 unsigned offset = 2;
00343
00344 if( !unicode )
00345 {
00346 char* buffer = new char[ len+1 ];
00347 memcpy( buffer, data + offset, len );
00348 buffer[ len ] = 0;
00349 str = UString( buffer );
00350 delete[] buffer;
00351 }
00352 else
00353 {
00354 for( unsigned k=0; k<len; k++ )
00355 {
00356 unsigned uchar = readU16( data + offset + k*2 );
00357 str.append( UString(UChar(uchar)) );
00358 }
00359 }
00360
00361 EString result;
00362 result.setUnicode( unicode );
00363 result.setRichText( richText );
00364 result.setSize( datasize );
00365 result.setStr( str );
00366
00367 return result;
00368 }
00369
00370
00371
00372
00373
00374 class FormulaToken::Private
00375 {
00376 public:
00377 unsigned ver;
00378 unsigned id;
00379 std::vector<unsigned char> data;
00380 };
00381
00382 FormulaToken::FormulaToken()
00383 {
00384 d = new Private;
00385 d->ver = Excel97;
00386 d->id = Unused;
00387 }
00388
00389 FormulaToken::FormulaToken( unsigned t )
00390 {
00391 d = new Private;
00392 d->ver = Excel97;
00393 d->id = t;
00394 }
00395
00396 FormulaToken::FormulaToken( const FormulaToken& token )
00397 {
00398 d = new Private;
00399 d->ver = token.d->ver;
00400 d->id = token.id();
00401
00402 d->data.resize( token.d->data.size() );
00403 for( unsigned i = 0; i < d->data.size(); i++ )
00404 d->data[i] = token.d->data[i];
00405 }
00406
00407 FormulaToken::~FormulaToken()
00408 {
00409 delete d;
00410 }
00411
00412 unsigned FormulaToken::version() const
00413 {
00414 return d->ver;
00415 }
00416
00417 void FormulaToken::setVersion( unsigned v )
00418 {
00419 d->ver = v;
00420 }
00421
00422 unsigned FormulaToken::id() const
00423 {
00424 return d->id;
00425 }
00426
00427 const char* FormulaToken::idAsString() const
00428 {
00429 const char* s = 0;
00430
00431 switch( d->id )
00432 {
00433 case Matrix: s = "Matrix"; break;
00434 case Table: s = "Table"; break;
00435 case Add: s = "Add"; break;
00436 case Sub: s = "Sub"; break;
00437 case Mul: s = "Mul"; break;
00438 case Div: s = "Div"; break;
00439 case Power: s = "Power"; break;
00440 case Concat: s = "Concat"; break;
00441 case LT: s = "LT"; break;
00442 case LE: s = "LE"; break;
00443 case EQ: s = "EQ"; break;
00444 case GE: s = "GE"; break;
00445 case GT: s = "GT"; break;
00446 case NE: s = "NE"; break;
00447 case Intersect: s = "Intersect"; break;
00448 case List: s = "List"; break;
00449 case Range: s = "Range"; break;
00450 case UPlus: s = "UPlus"; break;
00451 case UMinus: s = "UMinus"; break;
00452 case Percent: s = "Percent"; break;
00453 case Paren: s = "Paren"; break;
00454 case String: s = "String"; break;
00455 case MissArg: s = "MissArg"; break;
00456 case ErrorCode: s = "ErrorCode"; break;
00457 case Bool: s = "Bool"; break;
00458 case Integer: s = "Integer"; break;
00459 case Array: s = "Array"; break;
00460 case Function: s = "Function"; break;
00461 case FunctionVar: s = "FunctionVar"; break;
00462 case Name: s = "Name"; break;
00463 case Ref: s = "Ref"; break;
00464 case RefErr: s = "RefErr"; break;
00465 case RefN: s = "RefN"; break;
00466 case Area: s = "Area"; break;
00467 case AreaErr: s = "AreaErr"; break;
00468 case AreaN: s = "AreaN"; break;
00469 case NameX: s = "NameX"; break;
00470 case Ref3d: s = "Ref3d"; break;
00471 case RefErr3d: s = "RefErr3d"; break;
00472 case Float: s = "Float"; break;
00473 case Area3d: s = "Area3d"; break;
00474 case AreaErr3d: s = "AreaErr3d"; break;
00475 default: s = "Unknown"; break;
00476 };
00477
00478 return s;
00479 }
00480
00481
00482 unsigned FormulaToken::size() const
00483 {
00484 unsigned s = 0;
00485
00486 switch( d->id )
00487 {
00488 case Add:
00489 case Sub:
00490 case Mul:
00491 case Div:
00492 case Power:
00493 case Concat:
00494 case LT:
00495 case LE:
00496 case EQ:
00497 case GE:
00498 case GT:
00499 case NE:
00500 case Intersect:
00501 case List:
00502 case Range:
00503 case UPlus:
00504 case UMinus:
00505 case Percent:
00506 case Paren:
00507 case MissArg:
00508 s = 0; break;
00509
00510 case Attr:
00511 s = 3; break;
00512
00513 case ErrorCode:
00514 case Bool:
00515 s = 1; break;
00516
00517 case Integer:
00518 s = 2; break;
00519
00520 case Array:
00521 s = 7; break;
00522
00523 case Function:
00524 s = 2;
00525 break;
00526
00527 case FunctionVar:
00528 s = 3;
00529 break;
00530
00531 case Matrix:
00532 case Table:
00533 s = (d->ver == Excel97) ? 4 : 3;
00534 break;
00535
00536 case Name:
00537 s = (d->ver == Excel97) ? 4 : 14;
00538 break;
00539
00540 case Ref:
00541 case RefErr:
00542 case RefN:
00543 s = (d->ver == Excel97) ? 4 : 3;
00544 break;
00545
00546 case Area:
00547 case AreaErr:
00548 case AreaN:
00549 s = (d->ver == Excel97) ? 8 : 6;
00550 break;
00551
00552 case NameX:
00553 s = (d->ver == Excel97) ? 6 : 24;
00554 break;
00555
00556 case Ref3d:
00557 case RefErr3d:
00558 s = (d->ver == Excel97) ? 6 : 27;
00559 break;
00560
00561 case Float:
00562 s = 8; break;
00563
00564 case Area3d:
00565 case AreaErr3d:
00566 s = (d->ver == Excel97) ? 10 : 20;
00567 break;
00568
00569 default:
00570
00571 break;
00572 };
00573
00574 return s;
00575 }
00576
00577 void FormulaToken::setData( unsigned size, const unsigned char* data )
00578 {
00579 d->data.resize( size );
00580 for( unsigned i = 0; i < size; i++ )
00581 d->data[i] = data[i];
00582 }
00583
00584 Value FormulaToken::value() const
00585 {
00586 Value result;
00587
00588 unsigned char* buf;
00589 buf = new unsigned char[d->data.size()];
00590 for( unsigned k=0; k<d->data.size(); k++ )
00591 buf[k] = d->data[k];
00592
00593
00594 switch( d->id )
00595 {
00596 case ErrorCode:
00597 result = errorAsValue( buf[0] );
00598 break;
00599
00600 case Bool:
00601 result = Value( buf[0]!=0 );
00602 break;
00603
00604 case Integer:
00605 result = Value( (int)readU16( buf ) );
00606 break;
00607
00608 case Float:
00609 result = Value( readFloat64( buf ) );
00610 break;
00611
00612 case String:
00613 {
00614 EString estr = (version()==Excel97) ?
00615 EString::fromUnicodeString( buf, false, d->data.size() ) :
00616 EString::fromByteString( buf, false, d->data.size() );
00617 result = Value( estr.str() );
00618 }
00619 break;
00620
00621 default: break;
00622 }
00623
00624 delete [] buf;
00625
00626 return result;
00627 }
00628
00629 unsigned FormulaToken::functionIndex() const
00630 {
00631
00632 unsigned index = 0;
00633 unsigned char buf[2];
00634
00635 if( d->id == Function )
00636 {
00637 buf[0] = d->data[0];
00638 buf[1] = d->data[1];
00639 index = readU16( buf );
00640 }
00641
00642 if( d->id == FunctionVar )
00643 {
00644 buf[0] = d->data[1];
00645 buf[1] = d->data[2];
00646 index = readU16( buf );
00647 }
00648
00649 return index;
00650 }
00651
00652 struct FunctionEntry
00653 {
00654 const char *name;
00655 int params;
00656 };
00657
00658 static const FunctionEntry FunctionEntries[] =
00659 {
00660 { "COUNT", 1 },
00661 { "IF", 0 },
00662 { "ISNV", 1 },
00663 { "ISERROR", 1 },
00664 { "SUM", 0 },
00665 { "AVERAGE", 0 },
00666 { "MIN", 0 },
00667 { "MAX", 0 },
00668 { "ROW", 0 },
00669 { "COLUMN", 0 },
00670 { "NOVALUE", 0 },
00671 { "NPV", 0 },
00672 { "STDEV", 0 },
00673 { "DOLLAR", 0 },
00674 { "FIXED", 0 },
00675 { "SIN", 1 },
00676 { "COS", 1 },
00677 { "TAN", 1 },
00678 { "ATAN", 1 },
00679 { "PI", 0 },
00680 { "SQRT", 1 },
00681 { "EXP", 1 },
00682 { "LN", 1 },
00683 { "LOG10", 1 },
00684 { "ABS", 1 },
00685 { "INT", 1 },
00686 { "SIGN", 1 },
00687 { "ROUND", 2 },
00688 { "LOOKUP", 0 },
00689 { "INDEX", 0 },
00690 { "REPT", 2 },
00691 { "MID", 3 },
00692 { "LEN", 1 },
00693 { "VALUE", 1 },
00694 { "TRUE", 0 },
00695 { "FALSE", 0 },
00696 { "AND", 0 },
00697 { "OR", 0 },
00698 { "NOT", 1 },
00699 { "MOD", 2 },
00700 { "DCOUNT", 3 },
00701 { "DSUM", 3 },
00702 { "DAVERAGE", 3 },
00703 { "DMIN", 3 },
00704 { "DMAX", 3 },
00705 { "DSTDEV", 3 },
00706 { "VAR", 0 },
00707 { "DVAR", 3 },
00708 { "TEXT", 2 },
00709 { "LINEST", 0 },
00710 { "TREND", 0 },
00711 { "LOGEST", 0 },
00712 { "GROWTH", 0 },
00713 { "GOTO", 0 },
00714 { "HALT", 0 },
00715 { "Unknown55", 0 },
00716 { "PV", 0 },
00717 { "FV", 0 },
00718 { "NPER", 0 },
00719 { "PMT", 0 },
00720 { "RATE", 0 },
00721 { "MIRR", 3 },
00722 { "IRR", 0 },
00723 { "RAND", 0 },
00724 { "MATCH", 0 },
00725 { "DATE", 3 },
00726 { "TIME", 3 },
00727 { "DAY", 1 },
00728 { "MONTH", 1 },
00729 { "YEAR", 1 },
00730 { "DAYOFWEEK", 0 },
00731 { "HOUR", 1 },
00732 { "MIN", 1 },
00733 { "SEC", 1 },
00734 { "NOW", 0 },
00735 { "AREAS", 1 },
00736 { "ROWS", 1 },
00737 { "COLUMNS", 1 },
00738 { "OFFSET", 0 },
00739 { "ABSREF", 2 },
00740 { "RELREF", 0 },
00741 { "ARGUMENT", 0 },
00742 { "SEARCH", 0 },
00743 { "TRANSPOSE", 1 },
00744 { "ERROR", 0 },
00745 { "STEP", 0 },
00746 { "TYPE", 1 },
00747 { "ECHO", 0 },
00748 { "SETNAME", 0 },
00749 { "CALLER", 0 },
00750 { "DEREF", 0 },
00751 { "WINDOWS", 0 },
00752 { "SERIES", 4 },
00753 { "DOCUMENTS", 0 },
00754 { "ACTIVECELL", 0 },
00755 { "SELECTION", 0 },
00756 { "RESULT", 0 },
00757 { "ATAN2", 2 },
00758 { "ASIN", 1 },
00759 { "ACOS", 1 },
00760 { "CHOOSE", 0 },
00761 { "HLOOKUP", 0 },
00762 { "VLOOKUP", 0 },
00763 { "LINKS", 0 },
00764 { "INPUT", 0 },
00765 { "ISREF", 1 },
00766 { "GETFORMULA", 0 },
00767 { "GETNAME", 0 },
00768 { "SETVALUE", 0 },
00769 { "LOG", 0 },
00770 { "EXEC", 0 },
00771 { "CHAR", 1 },
00772 { "LOWER", 1 },
00773 { "UPPER", 1 },
00774 { "PROPER", 1 },
00775 { "LEFT", 0 },
00776 { "RIGHT", 0 },
00777 { "EXACT", 2 },
00778 { "TRIM", 1 },
00779 { "REPLACE", 4 },
00780 { "SUBSTITUTE", 0 },
00781 { "CODE", 1 },
00782 { "NAMES", 0 },
00783 { "DIRECTORY", 0 },
00784 { "FIND", 0 },
00785 { "CELL", 0 },
00786 { "ISERR", 1 },
00787 { "ISTEXT", 1 },
00788 { "ISNUMBER", 1 },
00789 { "ISBLANK", 1 },
00790 { "T", 1 },
00791 { "N", 1 },
00792 { "FOPEN", 0 },
00793 { "FCLOSE", 0 },
00794 { "FSIZE", 0 },
00795 { "FREADLN", 0 },
00796 { "FREAD", 0 },
00797 { "FWRITELN", 0 },
00798 { "FWRITE", 0 },
00799 { "FPOS", 0 },
00800 { "DATEVALUE", 1 },
00801 { "TIMEVALUE", 1 },
00802 { "SLN", 3 },
00803 { "SYD", 4 },
00804 { "DDB", 0 },
00805 { "GETDEF", 0 },
00806 { "REFTEXT", 0 },
00807 { "TEXTREF", 0 },
00808 { "INDIRECT", 0 },
00809 { "REGISTER", 0 },
00810 { "CALL", 0 },
00811 { "ADDBAR", 0 },
00812 { "ADDMENU", 0 },
00813 { "ADDCOMMAND", 0 },
00814 { "ENABLECOMMAND", 0 },
00815 { "CHECKCOMMAND", 0 },
00816 { "RENAMECOMMAND", 0 },
00817 { "SHOWBAR", 0 },
00818 { "DELETEMENU", 0 },
00819 { "DELETECOMMAND", 0 },
00820 { "GETCHARTITEM", 0 },
00821 { "DIALOGBOX", 0 },
00822 { "CLEAN", 1 },
00823 { "MDETERM", 1 },
00824 { "MINVERSE", 1 },
00825 { "MMULT", 2 },
00826 { "FILES", 0 },
00827 { "IPMT", 0 },
00828 { "PPMT", 0 },
00829 { "COUNTA", 0 },
00830 { "CANCELKEY", 1 },
00831 { "Unknown171", 0 },
00832 { "Unknown172", 0 },
00833 { "Unknown173", 0 },
00834 { "Unknown174", 0 },
00835 { "INITIATE", 0 },
00836 { "REQUEST", 0 },
00837 { "POKE", 0 },
00838 { "EXECUTE", 0 },
00839 { "TERMINATE", 0 },
00840 { "RESTART", 0 },
00841 { "HELP", 0 },
00842 { "GETBAR", 0 },
00843 { "PRODUCT", 0 },
00844 { "FACT", 1 },
00845 { "GETCELL", 0 },
00846 { "GETWORKSPACE", 0 },
00847 { "GETWINDOW", 0 },
00848 { "GETDOCUMENT", 0 },
00849 { "DPRODUCT", 3 },
00850 { "ISNONTEXT", 1 },
00851 { "GETNOTE", 0 },
00852 { "NOTE", 0 },
00853 { "STDEVP", 0 },
00854 { "VARP", 0 },
00855 { "DSTDEVP", 3 },
00856 { "DVARP", 3 },
00857 { "TRUNC", 0 },
00858 { "ISLOGICAL", 1 },
00859 { "DCOUNTA", 3 },
00860 { "DELETEBAR", 0 },
00861 { "UNREGISTER", 0 },
00862 { "Unknown202", 0 },
00863 { "Unknown203", 0 },
00864 { "USDOLLAR", 0 },
00865 { "FINDB", 0 },
00866 { "SEARCHB", 0 },
00867 { "REPLACEB", 0 },
00868 { "LEFTB", 0 },
00869 { "RIGHTB", 0 },
00870 { "MIDB", 0 },
00871 { "LENB", 0 },
00872 { "ROUNDUP", 2 },
00873 { "ROUNDDOWN", 2 },
00874 { "ASC", 0 },
00875 { "DBCS", 0 },
00876 { "RANK", 0 },
00877 { "Unknown217", 0 },
00878 { "Unknown218", 0 },
00879 { "ADDRESS", 0 },
00880 { "GETDIFFDATE360", 0 },
00881 { "CURRENTDATE", 0 },
00882 { "VBD", 0 },
00883 { "Unknown223", 0 },
00884 { "Unknown224", 0 },
00885 { "Unknown225", 0 },
00886 { "Unknown226", 0 },
00887 { "MEDIAN", 0 },
00888 { "SUMPRODUCT", 0 },
00889 { "SINH", 1 },
00890 { "COSH", 1 },
00891 { "TANH", 1 },
00892 { "ASINH", 1 },
00893 { "ACOSH", 1 },
00894 { "ATANH", 1 },
00895 { "DGET", 3 },
00896 { "CREATEOBJECT", 0 },
00897 { "VOLATILE", 0 },
00898 { "LASTERROR", 0 },
00899 { "CUSTOMUNDO", 0 },
00900 { "CUSTOMREPEAT", 0 },
00901 { "FORMULACONVERT", 0 },
00902 { "GETLINKINFO", 0 },
00903 { "TEXTBOX", 0 },
00904 { "INFO", 1 },
00905 { "GROUP", 0 },
00906 { "GETOBJECT", 0 },
00907 { "DB", 0 },
00908 { "PAUSE", 0 },
00909 { "Unknown249", 0 },
00910 { "Unknown250", 0 },
00911 { "RESUME", 0 },
00912 { "FREQUENCY", 2 },
00913 { "ADDTOOLBAR", 0 },
00914 { "DELETETOOLBAR", 0 },
00915 { "Unknown255", 0 },
00916 { "RESETTOOLBAR", 0 },
00917 { "EVALUATE", 0 },
00918 { "GETTOOLBAR", 0 },
00919 { "GETTOOL", 0 },
00920 { "SPELLINGCHECK", 0 },
00921 { "ERRORTYPE", 1 },
00922 { "APPTITLE", 0 },
00923 { "WINDOWTITLE", 0 },
00924 { "SAVETOOLBAR", 0 },
00925 { "ENABLETOOL", 0 },
00926 { "PRESSTOOL", 0 },
00927 { "REGISTERID", 0 },
00928 { "GETWORKBOOK", 0 },
00929 { "AVEDEV", 0 },
00930 { "BETADIST", 0 },
00931 { "GAMMALN", 1 },
00932 { "BETAINV", 0 },
00933 { "BINOMDIST", 4 },
00934 { "CHIDIST", 2 },
00935 { "CHIINV", 2 },
00936 { "COMBIN", 2 },
00937 { "CONFIDENCE", 3 },
00938 { "CRITBINOM", 3 },
00939 { "EVEN", 1 },
00940 { "EXPONDIST", 3 },
00941 { "FDIST", 3 },
00942 { "FINV", 3 },
00943 { "FISHER", 1 },
00944 { "FISHERINV", 1 },
00945 { "FLOOR", 2 },
00946 { "GAMMADIST", 4 },
00947 { "GAMMAINV", 3 },
00948 { "CEIL", 2 },
00949 { "HYPGEOMDIST", 4 },
00950 { "LOGNORMDIST", 3 },
00951 { "LOGINV", 3 },
00952 { "NEGBINOMDIST", 3 },
00953 { "NORMDIST", 4 },
00954 { "NORMSDIST", 1 },
00955 { "NORMINV", 3 },
00956 { "NORMSINV", 1 },
00957 { "STANDARDIZE", 3 },
00958 { "ODD", 1 },
00959 { "PERMUT", 2 },
00960 { "POISSON", 3 },
00961 { "TDIST", 3 },
00962 { "WEIBULL", 4 },
00963 { "SUMXMY2", 2 },
00964 { "SUMX2MY2", 2 },
00965 { "SUMX2DY2", 2 },
00966 { "CHITEST", 2 },
00967 { "CORREL", 2 },
00968 { "COVAR", 2 },
00969 { "FORECAST", 3 },
00970 { "FTEST", 2 },
00971 { "INTERCEPT", 2 },
00972 { "PEARSON", 2 },
00973 { "RSQ", 2 },
00974 { "STEYX", 2 },
00975 { "SLOPE", 2 },
00976 { "TTEST", 4 },
00977 { "PROB", 0 },
00978 { "DEVSQ", 0 },
00979 { "GEOMEAN", 0 },
00980 { "HARMEAN", 0 },
00981 { "SUMSQ", 0 },
00982 { "KURT", 0 },
00983 { "SKEW", 0 },
00984 { "ZTEST", 0 },
00985 { "LARGE", 2 },
00986 { "SMALL", 2 },
00987 { "QUARTILE", 2 },
00988 { "PERCENTILE", 2 },
00989 { "PERCENTRANK", 0 },
00990 { "MODALVALUE", 0 },
00991 { "TRIMMEAN", 2 },
00992 { "TINV", 2 },
00993 { "Unknown333", 0 },
00994 { "MOVIECOMMAND", 0 },
00995 { "GETMOVIE", 0 },
00996 { "CONCATENATE", 0 },
00997 { "POWER", 2 },
00998 { "PIVOTADDDATA", 0 },
00999 { "GETPIVOTTABLE", 0 },
01000 { "GETPIVOTFIELD", 0 },
01001 { "GETPIVOTITEM", 0 },
01002 { "RADIANS", 1 },
01003 { "DEGREES", 1 },
01004 { "SUBTOTAL", 0 },
01005 { "SUMIF", 0 },
01006 { "COUNTIF", 2 },
01007 { "COUNTBLANK", 1 },
01008 { "SCENARIOGET", 0 },
01009 { "OPTIONSLISTSGET", 0 },
01010 { "ISPMT", 4 },
01011 { "DATEDIF", 3 },
01012 { "DATESTRING", 0 },
01013 { "NUMBERSTRING", 0 },
01014 { "ROMAN", 0 },
01015 { "OPENDIALOG", 0 },
01016 { "SAVEDIALOG", 0 },
01017 { "VIEWGET", 0 },
01018 { "GETPIVOTDATA", 2 },
01019 { "HYPERLINK", 1 },
01020 { "PHONETIC", 0 },
01021 { "AVERAGEA", 0 },
01022 { "MAXA", 0 },
01023 { "MINA", 0 },
01024 { "STDEVPA", 0 },
01025 { "VARPA", 0 },
01026 { "STDEVA", 0 },
01027 { "VARA", 0 },
01028 };
01029
01030 const char* FormulaToken::functionName() const
01031 {
01032 if( functionIndex() > 367 ) return 0;
01033 return FunctionEntries[ functionIndex() ].name;
01034 }
01035
01036 unsigned FormulaToken::functionParams() const
01037 {
01038 unsigned params = 0;
01039
01040 if( d->id == Function )
01041 {
01042 if( functionIndex() > 367 ) return 0;
01043 params = FunctionEntries[ functionIndex() ].params;
01044 }
01045
01046 if( d->id == FunctionVar )
01047 {
01048 params = (unsigned)d->data[0];
01049 params &= 0x7f;
01050 }
01051
01052 return params;
01053 }
01054
01055 unsigned FormulaToken::attr() const
01056 {
01057 unsigned attr = 0;
01058 if( d->id == Attr )
01059 {
01060 attr = (unsigned) d->data[0];
01061 }
01062 return attr;
01063 }
01064
01065 unsigned FormulaToken::nameIndex() const
01066 {
01067
01068 unsigned ni = 0;
01069 unsigned char buf[2];
01070
01071 if( d->id == NameX )
01072 if( d->ver == Excel97 )
01073 {
01074 buf[0] = d->data[2];
01075 buf[1] = d->data[3];
01076 ni = readU16( buf );
01077 }
01078
01079 if( d->id == NameX )
01080 if( d->ver == Excel95 )
01081 {
01082 buf[0] = d->data[10];
01083 buf[1] = d->data[11];
01084 ni = readU16( buf );
01085 }
01086
01087 return ni;
01088 }
01089
01090
01091 UString FormulaToken::area( unsigned row, unsigned col ) const
01092 {
01093
01094 unsigned char buf[2];
01095 int row1Ref, row2Ref, col1Ref, col2Ref;
01096 bool row1Relative, col1Relative;
01097 bool row2Relative, col2Relative;
01098
01099 if( version() == Excel97 )
01100 {
01101 buf[0] = d->data[0];
01102 buf[1] = d->data[1];
01103 row1Ref = readU16( buf );
01104
01105 buf[0] = d->data[2];
01106 buf[1] = d->data[3];
01107 row2Ref = readU16( buf );
01108
01109 buf[0] = d->data[4];
01110 buf[1] = d->data[5];
01111 col1Ref = readU16( buf );
01112
01113 buf[0] = d->data[6];
01114 buf[1] = d->data[7];
01115 col2Ref = readU16( buf );
01116
01117 row1Relative = col1Ref & 0x8000;
01118 col1Relative = col1Ref & 0x4000;
01119 col1Ref &= 0x3fff;
01120
01121 row2Relative = col2Ref & 0x8000;
01122 col2Relative = col2Ref & 0x4000;
01123 col2Ref &= 0x3fff;
01124 }
01125 else
01126 {
01127 buf[0] = d->data[0];
01128 buf[1] = d->data[1];
01129 row1Ref = readU16( buf );
01130
01131 buf[0] = d->data[2];
01132 buf[1] = d->data[3];
01133 row2Ref = readU16( buf );
01134
01135 buf[0] = d->data[4];
01136 buf[1] = 0;
01137 col1Ref = readU16( buf );
01138
01139 buf[0] = d->data[5];
01140 buf[1] = 0;
01141 col2Ref = readU16( buf );
01142
01143 row1Relative = row2Ref & 0x8000;
01144 col1Relative = row2Ref & 0x4000;
01145 row1Ref &= 0x3fff;
01146
01147 row2Relative = row2Ref & 0x8000;
01148 col2Relative = row2Ref & 0x4000;
01149 row2Ref &= 0x3fff;
01150 }
01151
01152 UString result;
01153 result.append( UString("[") );
01154
01155 if( !col1Relative )
01156 result.append( UString("$") );
01157 result.append( Cell::columnLabel( col1Ref ) );
01158 if( !row1Relative )
01159 result.append( UString("$") );
01160 result.append( UString::from( row1Ref+1 ) );
01161 result.append( UString(":") );
01162 if( !col2Relative )
01163 result.append( UString("$") );
01164 result.append( Cell::columnLabel( col2Ref ) );
01165 if( !row2Relative )
01166 result.append( UString("$") );
01167 result.append( UString::from( row2Ref+1 ) );
01168
01169 result.append( UString("]") );
01170
01171 return result;
01172 }
01173
01174 UString FormulaToken::ref( unsigned row, unsigned col ) const
01175 {
01176
01177
01178 unsigned char buf[2];
01179 int rowRef, colRef;
01180 bool rowRelative, colRelative;
01181
01182 if( version() == Excel97 )
01183 {
01184 buf[0] = d->data[0];
01185 buf[1] = d->data[1];
01186 rowRef = readU16( buf );
01187
01188 buf[0] = d->data[2];
01189 buf[1] = d->data[3];
01190 colRef = readU16( buf );
01191
01192 rowRelative = colRef & 0x8000;
01193 colRelative = colRef & 0x4000;
01194 colRef &= 0x3fff;
01195 }
01196 else
01197 {
01198 buf[0] = d->data[0];
01199 buf[1] = d->data[1];
01200 rowRef = readU16( buf );
01201
01202 buf[0] = d->data[2];
01203 buf[1] = 0;
01204 colRef = readU16( buf );
01205
01206 rowRelative = rowRef & 0x8000;
01207 colRelative = rowRef & 0x4000;
01208 rowRef &= 0x3fff;
01209 }
01210
01211 UString result;
01212
01213 result.append( UString("[") );
01214
01215 if( !colRelative )
01216 result.append( UString("$") );
01217 result.append( Cell::columnLabel( colRef ) );
01218 if( !rowRelative )
01219 result.append( UString("$") );
01220 result.append( UString::from( rowRef+1 ) );
01221
01222 result.append( UString("]") );
01223
01224 return result;
01225 }
01226
01227 std::ostream& Swinder::operator<<( std::ostream& s, Swinder::FormulaToken token )
01228 {
01229 s << std::setw(2) << std::hex << token.id() << std::dec;
01230
01231 s << " ";
01232
01233 switch( token.id() )
01234 {
01235 case FormulaToken::ErrorCode:
01236 case FormulaToken::Bool:
01237 case FormulaToken::Integer:
01238 case FormulaToken::Float:
01239 case FormulaToken::String:
01240 {
01241 Value v = token.value();
01242 s << v;
01243 }
01244 break;
01245
01246 case FormulaToken::Function:
01247 s << "Function " << token.functionName();
01248 break;
01249
01250 default:
01251 s << token.idAsString();
01252 break;
01253 }
01254
01255 return s;
01256 }
01257
01258
01259
01260
01261
01262 class CellInfo::Private
01263 {
01264 public:
01265 unsigned row;
01266 unsigned column;
01267 unsigned xfIndex;
01268 };
01269
01270 CellInfo::CellInfo()
01271 {
01272 info = new CellInfo::Private();
01273 info->row = 0;
01274 info->column = 0;
01275 info->xfIndex = 0;
01276 }
01277
01278 CellInfo::~CellInfo()
01279 {
01280 delete info;
01281 }
01282
01283 unsigned CellInfo::row() const
01284 {
01285 return info->row;
01286 }
01287
01288 void CellInfo::setRow( unsigned r )
01289 {
01290 info->row = r;
01291 }
01292
01293 unsigned CellInfo::column() const
01294 {
01295 return info->column;
01296 }
01297
01298 void CellInfo::setColumn( unsigned c )
01299 {
01300 info->column = c;
01301 }
01302
01303 unsigned CellInfo::xfIndex() const
01304 {
01305 return info->xfIndex;
01306 }
01307
01308 void CellInfo::setXfIndex( unsigned i )
01309 {
01310 info->xfIndex = i;
01311 }
01312
01313
01314
01315
01316
01317 class ColumnSpanInfo::Private
01318 {
01319 public:
01320 unsigned firstColumn;
01321 unsigned lastColumn;
01322 };
01323
01324 ColumnSpanInfo::ColumnSpanInfo()
01325 {
01326 spaninfo = new ColumnSpanInfo::Private();
01327 spaninfo->firstColumn = 0;
01328 spaninfo->lastColumn = 0;
01329 }
01330
01331 ColumnSpanInfo::~ColumnSpanInfo()
01332 {
01333 delete spaninfo;
01334 }
01335
01336 unsigned ColumnSpanInfo::firstColumn() const
01337 {
01338 return spaninfo->firstColumn;
01339 }
01340
01341 void ColumnSpanInfo::setFirstColumn( unsigned c )
01342 {
01343 spaninfo->firstColumn = c;
01344 }
01345
01346 unsigned ColumnSpanInfo::lastColumn() const
01347 {
01348 return spaninfo->lastColumn;
01349 }
01350
01351 void ColumnSpanInfo::setLastColumn( unsigned c )
01352 {
01353 spaninfo->lastColumn = c;
01354 }
01355
01356
01357
01358 const unsigned int Record::id = 0;
01359
01360 Record::Record()
01361 {
01362 stream_position = 0;
01363 ver = Excel97;
01364 }
01365
01366 Record::~Record()
01367 {
01368 }
01369
01370 Record* Record::create( unsigned type )
01371 {
01372 Record* record = 0;
01373
01374 if( type == BOFRecord::id )
01375 record = new BOFRecord();
01376
01377 else if( type == EOFRecord::id )
01378 record = new EOFRecord();
01379
01380 if( type == BackupRecord::id )
01381 record = new BackupRecord();
01382
01383 if( type == BlankRecord::id )
01384 record = new BlankRecord();
01385
01386 if( type == BoolErrRecord::id )
01387 record = new BoolErrRecord();
01388
01389 if( type == BottomMarginRecord::id )
01390 record = new BottomMarginRecord();
01391
01392 if( type == BoundSheetRecord::id )
01393 record = new BoundSheetRecord();
01394
01395 if( type == CalcModeRecord::id )
01396 record = new CalcModeRecord();
01397
01398 if( type == ColInfoRecord::id )
01399 record = new ColInfoRecord();
01400
01401 if( type == DateModeRecord::id )
01402 record = new DateModeRecord();
01403
01404 if( type == DimensionRecord::id )
01405 record = new DimensionRecord();
01406
01407 if( type == ExternNameRecord::id )
01408 record = new ExternNameRecord();
01409
01410 else if( type == FilepassRecord::id )
01411 record = new FilepassRecord();
01412
01413 else if( type == FontRecord::id )
01414 record = new FontRecord();
01415
01416 else if( type == FooterRecord::id )
01417 record = new FooterRecord();
01418
01419 else if( type == FormatRecord::id )
01420 record = new FormatRecord();
01421
01422 else if( type == FormulaRecord::id )
01423 record = new FormulaRecord();
01424
01425 else if( type == HeaderRecord::id )
01426 record = new HeaderRecord();
01427
01428 else if( type == LabelRecord::id )
01429 record = new LabelRecord();
01430
01431 else if( type == LabelSSTRecord::id )
01432 record = new LabelSSTRecord();
01433
01434 if( type == LeftMarginRecord::id )
01435 record = new LeftMarginRecord();
01436
01437 else if( type == MergedCellsRecord::id )
01438 record = new MergedCellsRecord();
01439
01440 else if( type == MulBlankRecord::id )
01441 record = new MulBlankRecord();
01442
01443 else if( type == MulRKRecord::id )
01444 record = new MulRKRecord();
01445
01446 if( type == NameRecord::id )
01447 record = new NameRecord();
01448
01449 else if( type == NumberRecord::id )
01450 record = new NumberRecord();
01451
01452 else if( type == PaletteRecord::id )
01453 record = new PaletteRecord();
01454
01455 if( type == RightMarginRecord::id )
01456 record = new RightMarginRecord();
01457
01458 else if( type == RKRecord::id )
01459 record = new RKRecord();
01460
01461 else if( type == RowRecord::id )
01462 record = new RowRecord();
01463
01464 else if( type == RStringRecord::id )
01465 record = new RStringRecord();
01466
01467 else if( type == SSTRecord::id )
01468 record = new SSTRecord();
01469
01470 else if( type == StringRecord::id )
01471 record = new StringRecord();
01472
01473 else if( type == XFRecord::id )
01474 record = new XFRecord();
01475
01476 else if( type == TopMarginRecord::id )
01477 record = new TopMarginRecord();
01478
01479 return record;
01480 }
01481
01482 void Record::setPosition( unsigned pos )
01483 {
01484 stream_position = pos;
01485 }
01486
01487 unsigned Record::position() const
01488 {
01489 return stream_position;
01490 }
01491
01492 void Record::setData( unsigned, const unsigned char* )
01493 {
01494 }
01495
01496 void Record::dump( std::ostream& ) const
01497 {
01498
01499 }
01500
01501
01502
01503 const unsigned int BackupRecord::id = 0x0040;
01504
01505 class BackupRecord::Private
01506 {
01507 public:
01508 bool backup;
01509 };
01510
01511 BackupRecord::BackupRecord():
01512 Record()
01513 {
01514 d = new BackupRecord::Private();
01515 d->backup = false;
01516 }
01517
01518 BackupRecord::~BackupRecord()
01519 {
01520 delete d;
01521 }
01522
01523 bool BackupRecord::backup() const
01524 {
01525 return d->backup;
01526 }
01527
01528 void BackupRecord::setBackup( bool b )
01529 {
01530 d->backup = b;
01531 }
01532
01533 void BackupRecord::setData( unsigned size, const unsigned char* data )
01534 {
01535 if( size < 2 ) return;
01536
01537 unsigned flag = readU16( data );
01538 d->backup = flag != 0;
01539 }
01540
01541 void BackupRecord::dump( std::ostream& out ) const
01542 {
01543 out << "BACKUP" << std::endl;
01544 out << " Backup on save : " << (backup() ? "Yes" : "No") << std::endl;
01545 }
01546
01547
01548
01549 const unsigned int BlankRecord::id = 0x0201;
01550
01551 BlankRecord::BlankRecord():
01552 Record(), CellInfo()
01553 {
01554 }
01555
01556 void BlankRecord::setData( unsigned size, const unsigned char* data )
01557 {
01558 if( size < 6 ) return;
01559
01560 setRow( readU16( data ) );
01561 setColumn( readU16( data+2 ) );
01562 setXfIndex( readU16( data+4 ) );
01563 }
01564
01565 void BlankRecord::dump( std::ostream& out ) const
01566 {
01567 out << "BLANK" << std::endl;
01568 out << " Row : " << row() << std::endl;
01569 out << " Column : " << column() << std::endl;
01570 out << " XF Index : " << xfIndex() << std::endl;
01571 }
01572
01573
01574
01575
01576 const unsigned int BOFRecord::id = 0x0809;
01577
01578
01579 class BOFRecord::Private
01580 {
01581 public:
01582 unsigned version;
01583 unsigned type;
01584 unsigned build;
01585 unsigned year;
01586 unsigned history;
01587 unsigned rversion;
01588 };
01589
01590
01591 BOFRecord::BOFRecord():
01592 Record()
01593 {
01594 d = new BOFRecord::Private();
01595 d->version = 0x600;
01596 d->type = 0;
01597 d->build = 0;
01598 d->year = 0;
01599 d->history = 0;
01600 d->rversion = 0;
01601 }
01602
01603
01604 BOFRecord::~BOFRecord()
01605 {
01606 delete d;
01607 }
01608
01609 void BOFRecord::setData( unsigned size, const unsigned char* data )
01610 {
01611 if( size < 4 ) return;
01612
01613 d->version = readU16( data );
01614 d->type = readU16( data+2 );
01615 if( size > 6 )
01616 {
01617 d->build = readU16( data+4 );
01618 d->year = readU16( data+6);
01619 if( size > 12 )
01620 {
01621 d->history = readU32( data+8 );
01622 d->rversion = readU32( data+12 );
01623 }
01624 }
01625 }
01626
01627 unsigned BOFRecord::version() const
01628 {
01629 unsigned ver = UnknownExcel;
01630 switch( d->version )
01631 {
01632 case 0x0500 : ver = Excel95; break;
01633 case 0x0600 : ver = Excel97; break;
01634 default: break;
01635 }
01636 return ver;
01637 }
01638
01639 const char* BOFRecord::versionAsString() const
01640 {
01641 const char *result = "Unknown";
01642 switch( version() )
01643 {
01644 case Excel95 : result = "Excel95"; break;
01645 case Excel97 : result = "Excel97"; break;
01646 default: break;
01647 }
01648 return result;
01649 }
01650
01651 unsigned BOFRecord::type() const
01652 {
01653 unsigned result = UnknownType;
01654 switch( d->type )
01655 {
01656 case 0x005 : result = Workbook; break;
01657 case 0x006 : result = VBModule; break;
01658 case 0x010 : result = Worksheet; break;
01659 case 0x020 : result = Chart; break;
01660 case 0x040 : result = MacroSheet; break;
01661 case 0x100 : result = Workspace; break;
01662 default: break;
01663 }
01664 return result;
01665 }
01666
01667 const char* BOFRecord::typeAsString() const
01668 {
01669 const char *result = "Unknown";
01670 switch( type() )
01671 {
01672 case Workbook : result = "Workbook"; break;
01673 case VBModule : result = "Visual Basic Module"; break;
01674 case Worksheet : result = "Worksheet"; break;
01675 case Chart : result = "Chart"; break;
01676 case MacroSheet : result = "Macro Sheet"; break;
01677 case Workspace : result = "Workspace File"; break;
01678 default: break;
01679 }
01680 return result;
01681 }
01682
01683 void BOFRecord::dump( std::ostream& out ) const
01684 {
01685 out << "BOF" << std::endl;
01686 out << " Version : 0x" << std::hex << d->version << " (" << versionAsString() << ")" << std::endl;
01687 out << " Type : 0x" << d->type << " (" << typeAsString() << ")" << std::endl;
01688 out << " Build : 0x" << d->build << std::endl;
01689 out << " Year : " << std::dec << d->year << std::endl;
01690 out << " History : 0x" << std::hex << d->history << std::endl;
01691 out << " RVersion : 0x" << d->rversion << std::endl;
01692 out << std::dec;
01693 }
01694
01695
01696
01697 const unsigned int BoolErrRecord::id = 0x0205;
01698
01699 class BoolErrRecord::Private
01700 {
01701 public:
01702 Value value;
01703 };
01704
01705 BoolErrRecord::BoolErrRecord():
01706 Record(), CellInfo()
01707 {
01708 d = new BoolErrRecord::Private();
01709 d->value = Value( false );
01710 }
01711
01712 BoolErrRecord::~BoolErrRecord()
01713 {
01714 delete d;
01715 }
01716
01717 void BoolErrRecord::setData( unsigned size, const unsigned char* data )
01718 {
01719 if( size != 8 ) return;
01720
01721 setRow( readU16( data ) );
01722 setColumn( readU16( data+2 ) );
01723 setXfIndex( readU16( data+4 ) );
01724
01725 switch( data[7] )
01726 {
01727 case 0 :
01728 d->value = Value( data[6] ? true : false );
01729 break;
01730 case 1 :
01731 d->value = errorAsValue( data[6] );
01732 break;
01733 default:
01734
01735 std::cerr << "Warning: bad BOOLERR record" << std::endl;
01736 break;
01737 }
01738 }
01739
01740 Value BoolErrRecord::value() const
01741 {
01742 return d->value;
01743 }
01744
01745 void BoolErrRecord::dump( std::ostream& out ) const
01746 {
01747 out << "BOOLERR" << std::endl;
01748 out << " Column : " << column() << std::endl;
01749 out << " Row : " << row() << std::endl;
01750 out << " XFIndex : " << xfIndex() << std::endl;
01751 out << " Value : " << value() << std::endl;
01752 }
01753
01754
01755
01756 const unsigned int BottomMarginRecord::id = 0x0029;
01757
01758 class BottomMarginRecord::Private
01759 {
01760 public:
01761 double bottomMargin;
01762 };
01763
01764 BottomMarginRecord::BottomMarginRecord():
01765 Record()
01766 {
01767 d = new BottomMarginRecord::Private();
01768 d->bottomMargin = 1.0;
01769 }
01770
01771 BottomMarginRecord::~BottomMarginRecord()
01772 {
01773 delete d;
01774 }
01775
01776 double BottomMarginRecord::bottomMargin() const
01777 {
01778 return d->bottomMargin;
01779 }
01780
01781 void BottomMarginRecord::setBottomMargin( double m )
01782 {
01783 d->bottomMargin = m;
01784 }
01785
01786 void BottomMarginRecord::setData( unsigned size, const unsigned char* data )
01787 {
01788 if( size < 8 ) return;
01789 setBottomMargin( readFloat64( data ) );
01790 }
01791
01792 void BottomMarginRecord::dump( std::ostream& out ) const
01793 {
01794 out << "BOTTOMMARGIN" << std::endl;
01795 out << " Bottom Margin : " << bottomMargin() << " inches" << std::endl;
01796 }
01797
01798
01799
01800
01801 const unsigned int BoundSheetRecord::id = 0x0085;
01802
01803
01804 class BoundSheetRecord::Private
01805 {
01806 public:
01807 unsigned type;
01808 unsigned visibility;
01809 UString name;
01810 unsigned bofPosition;
01811 };
01812
01813 BoundSheetRecord::BoundSheetRecord():
01814 Record()
01815 {
01816 d = new BoundSheetRecord::Private();
01817 d->type = 0;
01818 d->visibility = 0;
01819 d->name = "Sheet";
01820 }
01821
01822 void BoundSheetRecord::setType( unsigned t )
01823 {
01824 switch( t )
01825 {
01826 case Worksheet: d->type = 0; break;
01827 case Chart: d->type = 2; break;
01828 case VBModule: d->type = 6; break;
01829 default: d->type = 0; break;
01830 };
01831 }
01832
01833 unsigned BoundSheetRecord::type() const
01834 {
01835 unsigned t = Worksheet;
01836 switch( d->type )
01837 {
01838 case 0: t = Worksheet; break;
01839 case 2: t = Chart; break;
01840 case 6: t = VBModule; break;
01841 default: break;
01842 };
01843 return t;
01844 }
01845
01846 const char* BoundSheetRecord::typeAsString() const
01847 {
01848 const char *result = "Unknown";
01849 switch( type() )
01850 {
01851 case Worksheet: result = "Worksheet"; break;
01852 case Chart: result = "Chart"; break;
01853 case VBModule: result = "Visual Basic Module"; break;
01854 default: break;
01855 }
01856 return result;
01857 }
01858
01859 void BoundSheetRecord::setVisible( bool v )
01860 {
01861 d->visibility = v ? 0 : 1;
01862 }
01863
01864 bool BoundSheetRecord::visible() const
01865 {
01866 return d->visibility == 0;
01867 }
01868
01869 void BoundSheetRecord::setSheetName( const UString& n )
01870 {
01871 d->name = n;
01872 }
01873
01874 UString BoundSheetRecord::sheetName() const
01875 {
01876 return d->name;
01877 }
01878
01879 void BoundSheetRecord::setBofPosition( unsigned pos )
01880 {
01881 d->bofPosition = pos;
01882 }
01883
01884 unsigned BoundSheetRecord::bofPosition() const
01885 {
01886 return d->bofPosition;
01887 }
01888
01889 BoundSheetRecord::~BoundSheetRecord()
01890 {
01891 delete d;
01892 }
01893
01894 void BoundSheetRecord::setData( unsigned size, const unsigned char* data )
01895 {
01896 if( size < 6 ) return;
01897
01898 d->bofPosition = readU32( data );
01899 d->visibility = data[4];
01900 d->type = data[5];
01901
01902
01903
01904
01905
01906
01907
01908 UString name = ( version() >= Excel97 ) ?
01909 EString::fromSheetName( data+6, size-6 ).str() :
01910 EString::fromByteString( data+6, false, size-6 ).str();
01911 setSheetName( name );
01912 }
01913
01914 void BoundSheetRecord::dump( std::ostream& out ) const
01915 {
01916 out << "BOUNDSHEET" << std::endl;
01917 out << " Name : " << d->name << std::endl;
01918 out << " Type : " << d->type << " (" << typeAsString() << ")" << std::endl;
01919 out << " Visibility : " << d->visibility << " (";
01920 if( visible() ) out << "Visible"; else out << "Hidden"; out << ")" << std::endl;
01921 out << " BOF pos : " << d->bofPosition << std::endl;
01922 }
01923
01924
01925
01926 const unsigned int CalcModeRecord::id = 0x000d;
01927
01928 class CalcModeRecord::Private
01929 {
01930 public:
01931 bool autoCalc;
01932 };
01933
01934 CalcModeRecord::CalcModeRecord():
01935 Record()
01936 {
01937 d = new CalcModeRecord::Private();
01938 d->autoCalc = false;
01939 }
01940
01941 CalcModeRecord::~CalcModeRecord()
01942 {
01943 delete d;
01944 }
01945
01946 bool CalcModeRecord::autoCalc() const
01947 {
01948 return d->autoCalc;
01949 }
01950
01951 void CalcModeRecord::setAutoCalc( bool b )
01952 {
01953 d->autoCalc = b;
01954 }
01955
01956 void CalcModeRecord::setData( unsigned size, const unsigned char* data )
01957 {
01958 if( size < 2 ) return;
01959
01960 unsigned flag = readU16( data );
01961 d->autoCalc = flag != 0;
01962 }
01963
01964 void CalcModeRecord::dump( std::ostream& out ) const
01965 {
01966 out << "CALCMODE" << std::endl;
01967 out << " Auto Calc : " << (autoCalc() ? "Yes" : "No") << std::endl;
01968 }
01969
01970
01971
01972 const unsigned int ColInfoRecord::id = 0x007d;
01973
01974 class ColInfoRecord::Private
01975 {
01976 public:
01977 unsigned width;
01978 unsigned xfIndex;
01979 bool hidden;
01980 bool collapsed;
01981 unsigned outlineLevel;
01982 };
01983
01984 ColInfoRecord::ColInfoRecord():
01985 Record(), ColumnSpanInfo()
01986 {
01987 d = new ColInfoRecord::Private();
01988 d->width = 2340;
01989 d->xfIndex = 0;
01990 d->hidden = false;
01991 d->collapsed = false;
01992 d->outlineLevel = 0;
01993 }
01994
01995 ColInfoRecord::~ColInfoRecord()
01996 {
01997 delete d;
01998 }
01999
02000
02001 unsigned ColInfoRecord::width() const
02002 {
02003 return d->width;
02004 }
02005
02006 void ColInfoRecord::setWidth( unsigned w )
02007 {
02008 d->width = w;
02009 }
02010
02011 unsigned ColInfoRecord::xfIndex() const
02012 {
02013 return d->xfIndex;
02014 }
02015
02016 void ColInfoRecord::setXfIndex( unsigned i )
02017 {
02018 d->xfIndex = i;
02019 }
02020
02021 bool ColInfoRecord::hidden() const
02022 {
02023 return d->hidden;
02024 }
02025
02026 void ColInfoRecord::setHidden( bool h )
02027 {
02028 d->hidden = h;
02029 }
02030
02031 bool ColInfoRecord::collapsed() const
02032 {
02033 return d->collapsed;
02034 }
02035
02036 void ColInfoRecord::setCollapsed( bool c )
02037 {
02038 d->collapsed = c;
02039 }
02040
02041 unsigned ColInfoRecord::outlineLevel() const
02042 {
02043 return d->outlineLevel;
02044 }
02045
02046 void ColInfoRecord::setOutlineLevel( unsigned l )
02047 {
02048 d->outlineLevel = l;
02049 }
02050
02051 void ColInfoRecord::setData( unsigned size, const unsigned char* data )
02052 {
02053 if( size < 10 ) return;
02054
02055 setFirstColumn( readU16( data ) );
02056 setLastColumn( readU16( data+2 ) );
02057 setWidth( readU16( data+4 ) );
02058 setXfIndex( readU16( data+6 ) );
02059
02060 unsigned options = readU16( data+8 );
02061 setHidden ( options & 1 );
02062 setCollapsed ( options & 0x1000 );
02063 setOutlineLevel( ( options >> 8 ) & 7 );
02064 }
02065
02066 void ColInfoRecord::dump( std::ostream& out ) const
02067 {
02068 out << "COLINFO" << std::endl;
02069 out << " First Column : " << firstColumn() << std::endl;
02070 out << " Last Column : " << lastColumn() << std::endl;
02071 out << " Width : " << width() << std::endl;
02072 out << " XF Index : " << xfIndex() << std::endl;
02073 out << " Hidden : " << ( hidden() ? "Yes" : "No" ) << std::endl;
02074 out << " Collapsed : " << ( collapsed() ? "Yes" : "No" ) << std::endl;
02075 out << " Outline Level : " << outlineLevel() << std::endl;
02076 }
02077
02078
02079
02080 const unsigned int DateModeRecord::id = 0x0022;
02081
02082 class DateModeRecord::Private
02083 {
02084 public:
02085 bool base1904;
02086 };
02087
02088 DateModeRecord::DateModeRecord():
02089 Record()
02090 {
02091 d = new DateModeRecord::Private();
02092 d->base1904 = false;
02093 }
02094
02095 DateModeRecord::~DateModeRecord()
02096 {
02097 delete d;
02098 }
02099
02100 bool DateModeRecord::base1904() const
02101 {
02102 return d->base1904;
02103 }
02104
02105 void DateModeRecord::setBase1904( bool r )
02106 {
02107 d->base1904 = r;
02108 }
02109
02110 void DateModeRecord::setData( unsigned size, const unsigned char* data )
02111 {
02112 if( size < 2 ) return;
02113
02114 unsigned flag = readU16( data );
02115 d->base1904 = flag != 0;
02116 }
02117
02118 void DateModeRecord::dump( std::ostream& out ) const
02119 {
02120 out << "DATEMODE" << std::endl;
02121 out << " 1904 base : " << (base1904() ? "Yes" : "No") << std::endl;
02122 }
02123
02124
02125
02126
02127 const unsigned int DimensionRecord::id = 0x0200;
02128
02129 class DimensionRecord::Private
02130 {
02131 public:
02132 unsigned firstRow;
02133 unsigned lastRow;
02134 unsigned firstColumn;
02135 unsigned lastColumn;
02136 };
02137
02138 DimensionRecord::DimensionRecord():
02139 Record()
02140 {
02141 d = new DimensionRecord::Private;
02142 d->firstRow = 0;
02143 d->lastRow = 0;
02144 d->firstColumn = 0;
02145 d->lastColumn = 0;
02146 }
02147
02148 DimensionRecord::~DimensionRecord()
02149 {
02150 delete d;
02151 }
02152
02153 unsigned DimensionRecord::firstRow() const
02154 {
02155 return d->firstRow;
02156 }
02157
02158 void DimensionRecord::setFirstRow( unsigned r )
02159 {
02160 d->firstRow = r;
02161 }
02162
02163 unsigned DimensionRecord::lastRow() const
02164 {
02165 return d->lastRow;
02166 }
02167
02168 void DimensionRecord::setLastRow( unsigned r )
02169 {
02170 d->lastRow = r;
02171 }
02172
02173 unsigned DimensionRecord::firstColumn() const
02174 {
02175 return d->firstColumn;
02176 }
02177
02178 void DimensionRecord::setFirstColumn( unsigned r )
02179 {
02180 d->firstColumn = r;
02181 }
02182
02183 unsigned DimensionRecord::lastColumn() const
02184 {
02185 return d->lastColumn;
02186 }
02187
02188 void DimensionRecord::setLastColumn( unsigned r )
02189 {
02190 d->lastColumn = r;
02191 }
02192
02193 void DimensionRecord::setData( unsigned size, const unsigned char* data )
02194 {
02195 if( size < 14 ) return;
02196
02197 setFirstRow( readU32( data ) );
02198 setLastRow( readU32( data+4 ) - 1 );
02199 setFirstColumn( readU16( data + 8 ) );
02200 setLastColumn( readU16( data + 10 ) - 1 );
02201 }
02202
02203 void DimensionRecord::dump( std::ostream& out ) const
02204 {
02205 out << "DIMENSION" << std::endl;
02206 out << " First Row : " << firstRow() << std::endl;
02207 out << " Last Row : " << lastRow() << std::endl;
02208 out << " First Column : " << firstColumn() << std::endl;
02209 out << " Last Column : " << lastColumn() << std::endl;
02210 }
02211
02212
02213
02214 const unsigned int EOFRecord::id = 0x000a;
02215
02216 EOFRecord::EOFRecord():
02217 Record()
02218 {
02219 }
02220
02221 EOFRecord::~EOFRecord()
02222 {
02223 }
02224
02225 void EOFRecord::setData( unsigned, const unsigned char* )
02226 {
02227
02228 }
02229
02230 void EOFRecord::dump( std::ostream& out ) const
02231 {
02232 out << "EOF" << std::endl;
02233 }
02234
02235
02236
02237 const unsigned int ExternNameRecord::id = 0x0023;
02238
02239 class ExternNameRecord::Private
02240 {
02241 public:
02242 unsigned optionFlags;
02243 unsigned sheetIndex;
02244 UString externName;
02245 };
02246
02247
02248 ExternNameRecord::ExternNameRecord()
02249 {
02250 d = new Private;
02251 d->optionFlags = 0;
02252 d->sheetIndex = 0;
02253 }
02254
02255 ExternNameRecord::~ExternNameRecord()
02256 {
02257 delete d;
02258 }
02259
02260 void ExternNameRecord::setSheetIndex( unsigned sheetIndex )
02261 {
02262 d->sheetIndex = sheetIndex;
02263 }
02264
02265 unsigned ExternNameRecord::sheetIndex() const
02266 {
02267 return d->sheetIndex;
02268 }
02269
02270 void ExternNameRecord::setExternName( const UString& name )
02271 {
02272 d->externName = name;
02273 }
02274
02275 UString ExternNameRecord::externName() const
02276 {
02277 return d->externName;
02278 }
02279
02280 void ExternNameRecord::setData( unsigned size, const unsigned char* data )
02281 {
02282 if( size < 6 ) return;
02283
02284 if ( version() == Excel97 )
02285 {
02286 d->optionFlags = readU16( data );
02287 d->sheetIndex = readU16( data+2 );
02288 d->externName = EString::fromUnicodeString( data+6, false, size ).str();
02289 }
02290
02291 if ( version() == Excel95 )
02292 {
02293 d->optionFlags = 0;
02294 d->sheetIndex = 0;
02295 d->externName = EString::fromByteString( data+6, false, size ).str();
02296 }
02297 }
02298
02299 void ExternNameRecord::dump( std::ostream& out ) const
02300 {
02301 }
02302
02303
02304
02305 const unsigned int FilepassRecord::id = 0x002f;
02306
02307 FilepassRecord::FilepassRecord():
02308 Record()
02309 {
02310 }
02311
02312 FilepassRecord::~FilepassRecord()
02313 {
02314 }
02315
02316 void FilepassRecord::setData( unsigned, const unsigned char* )
02317 {
02318
02319 }
02320
02321 void FilepassRecord::dump( std::ostream& out ) const
02322 {
02323 out << "FILEPASS" << std::endl;
02324 }
02325
02326
02327
02328 const unsigned int FontRecord::id = 0x0031;
02329
02330 class FontRecord::Private
02331 {
02332 public:
02333 unsigned height;
02334 UString fontName;
02335 unsigned fontFamily;
02336 unsigned characterSet;
02337 unsigned colorIndex;
02338 unsigned boldness;
02339 bool italic;
02340 bool strikeout;
02341 unsigned escapement;
02342 unsigned underline;
02343 };
02344
02345 FontRecord::FontRecord(): Record()
02346 {
02347 d = new FontRecord::Private;
02348 d->height = 11;
02349 d->fontName = "Arial";
02350 d->fontFamily = 0;
02351 d->characterSet = 0;
02352 d->colorIndex = 0;
02353 d->boldness = 400;
02354 d->italic = false;
02355 d->strikeout = false;
02356 d->escapement = Normal;
02357 d->underline = None;
02358 }
02359
02360 FontRecord::~FontRecord()
02361 {
02362 delete d;
02363 }
02364
02365 FontRecord::FontRecord( const FontRecord& ef ): Record()
02366 {
02367 d = new FontRecord::Private;
02368 operator=( ef );
02369 }
02370
02371 FontRecord& FontRecord::operator=( const FontRecord& ef )
02372 {
02373 d->height = ef.height();
02374 d->fontName = ef.fontName();
02375 d->fontFamily = ef.fontFamily();
02376 d->characterSet = ef.characterSet();
02377 d->boldness = ef.boldness();
02378 d->italic = ef.italic();
02379 d->strikeout = ef.strikeout();
02380 d->escapement = ef.escapement();
02381 d->underline = ef.underline();
02382 d->colorIndex = ef.colorIndex();
02383 return *this;
02384 }
02385
02386 unsigned FontRecord::height() const
02387 {
02388 return d->height;
02389 }
02390
02391 void FontRecord::setHeight( unsigned h )
02392 {
02393 d->height = h;
02394 }
02395
02396 UString FontRecord::fontName() const
02397 {
02398 return d->fontName;
02399 }
02400
02401 void FontRecord::setFontName( const UString& fn )
02402 {
02403 d->fontName = fn;
02404 }
02405
02406 unsigned FontRecord::fontFamily() const
02407 {
02408 return d->fontFamily;
02409 }
02410
02411 void FontRecord::setFontFamily( unsigned f )
02412 {
02413 d->fontFamily = f;
02414 }
02415
02416 unsigned FontRecord::characterSet() const
02417 {
02418 return d->characterSet;
02419 }
02420
02421 void FontRecord::setCharacterSet( unsigned cs )
02422 {
02423 d->characterSet = cs;
02424 }
02425
02426 unsigned FontRecord::colorIndex() const
02427 {
02428 return d->colorIndex;
02429 }
02430
02431 void FontRecord::setColorIndex( unsigned ci )
02432 {
02433 d->colorIndex = ci;
02434 }
02435
02436 unsigned FontRecord::boldness() const
02437 {
02438 return d->boldness;
02439 }
02440
02441 void FontRecord::setBoldness( unsigned b )
02442 {
02443 d->boldness = b;
02444 }
02445
02446 bool FontRecord::italic() const
02447 {
02448 return d->italic;
02449 }
02450
02451 void FontRecord::setItalic( bool i )
02452 {
02453 d->italic = i;
02454 }
02455
02456 bool FontRecord::strikeout() const
02457 {
02458 return d->strikeout;
02459 }
02460
02461 void FontRecord::setStrikeout( bool s )
02462 {
02463 d->strikeout = s;
02464 }
02465
02466 unsigned FontRecord::escapement() const
02467 {
02468 return d->escapement;
02469 }
02470
02471 void FontRecord::setEscapement( unsigned s )
02472 {
02473 d->escapement = s;
02474 }
02475
02476 unsigned FontRecord::underline() const
02477 {
02478 return d->underline;
02479 }
02480
02481 void FontRecord::setUnderline( unsigned u )
02482 {
02483 d->underline = u;
02484 }
02485
02486
02487 void FontRecord::setData( unsigned size, const unsigned char* data )
02488 {
02489 if( size < 14 ) return;
02490
02491 setHeight( readU16( data ) );
02492 unsigned flag = readU16( data+2 );
02493 setItalic( flag & 2 );
02494 setStrikeout( flag & 8 );
02495 setStrikeout( flag & 8 );
02496
02497 setColorIndex( readU16( data+4 ) );
02498
02499 setBoldness( readU16( data+6 ) );
02500 setEscapement( readU16( data+8 ) );
02501 setUnderline( data[10] );
02502
02503 setFontFamily( data[11] );
02504 setCharacterSet( data[12] );
02505
02506 UString fn = ( version() >= Excel97 ) ?
02507 EString::fromSheetName( data+14, size-14 ).str() :
02508 EString::fromByteString( data+14, false, size-14 ).str();
02509 setFontName( fn );
02510 }
02511
02512
02513 void FontRecord::dump( std::ostream& out ) const
02514 {
02515 out << "FONT" << std::endl;
02516 out << " Height : " << height() << " twips" << std::endl;
02517 out << " Font Name : " << fontName() << std::endl;
02518 out << " Color Index : " << colorIndex() << std::endl;
02519 out << " Boldness : " << boldness() << std::endl;
02520 out << " Italic : " << (italic()?"Yes":"No") << std::endl;
02521 out << " Strikeout : " << (strikeout()?"Yes":"No") << std::endl;
02522 out << " Escapement : ";
02523 switch( escapement() )
02524 {
02525 case Normal: out << "Normal" << std::endl; break;
02526 case Subscript: out << "Subscript" << std::endl; break;
02527 case Superscript: out << "Superscript" << std::endl; break;
02528 default: out << "Unkown " << escapement() << std::endl; break;
02529 };
02530 }
02531
02532
02533
02534 const unsigned int FooterRecord::id = 0x0015;
02535
02536 class FooterRecord::Private
02537 {
02538 public:
02539 UString footer;
02540 };
02541
02542 FooterRecord::FooterRecord():
02543 Record()
02544 {
02545 d = new FooterRecord::Private();
02546 }
02547
02548 FooterRecord::~FooterRecord()
02549 {
02550 delete d;
02551 }
02552
02553 UString FooterRecord::footer() const
02554 {
02555 return d->footer;
02556 }
02557
02558 void FooterRecord::setFooter( const UString& footer )
02559 {
02560 d->footer = footer;
02561 }
02562
02563 void FooterRecord::setData( unsigned size, const unsigned char* data )
02564 {
02565 if( size < 2 ) return;
02566
02567 UString footer = ( version() >= Excel97 ) ?
02568 EString::fromUnicodeString( data, true, size ).str() :
02569 EString::fromByteString( data, false, size ).str();
02570 setFooter( footer );
02571 }
02572
02573 void FooterRecord::dump( std::ostream& out ) const
02574 {
02575 out << "FOOTER" << std::endl;
02576 out << " Footer : " << footer() << std::endl;
02577 }
02578
02579
02580
02581 const unsigned int FormatRecord::id = 0x041e;
02582
02583 class FormatRecord::Private
02584 {
02585 public:
02586 unsigned index;
02587 UString formatString;
02588 };
02589
02590 FormatRecord::FormatRecord():
02591 Record()
02592 {
02593 d = new FormatRecord::Private;
02594 d->index = 0;
02595 d->formatString = "General";
02596 }
02597
02598 FormatRecord::~FormatRecord()
02599 {
02600 delete d;
02601 }
02602
02603 FormatRecord::FormatRecord( const FormatRecord& fr ):
02604 Record()
02605 {
02606 d = new FormatRecord::Private;
02607 operator=( fr );
02608 }
02609
02610 FormatRecord& FormatRecord::operator=( const FormatRecord& fr )
02611 {
02612 d->index = fr.index();
02613 d->formatString = fr.formatString();
02614 return *this;
02615 }
02616
02617 unsigned FormatRecord::index() const
02618 {
02619 return d->index;
02620 }
02621
02622 void FormatRecord::setIndex( unsigned i )
02623 {
02624 d->index = i;
02625 }
02626
02627 UString FormatRecord::formatString() const
02628 {
02629 return d->formatString;
02630 }
02631
02632 void FormatRecord::setFormatString( const UString& fs )
02633 {
02634 d->formatString = fs;
02635 }
02636
02637 void FormatRecord::setData( unsigned size, const unsigned char* data )
02638 {
02639 if( size < 3 ) return;
02640
02641 setIndex( readU16( data ) );
02642
02643 UString fs = ( version() >= Excel97 ) ?
02644 EString::fromUnicodeString( data+2, true, size-2 ).str() :
02645 EString::fromByteString( data+2, false, size-2 ).str();
02646 setFormatString( fs );
02647 }
02648
02649 void FormatRecord::dump( std::ostream& out ) const
02650 {
02651 out << "FORMAT" << std::endl;
02652 out << " Index : " << index() << std::endl;
02653 out << " Format String : " << formatString() << std::endl;
02654 }
02655
02656
02657
02658
02659 const unsigned int FormulaRecord::id = 0x0006;
02660
02661 class FormulaRecord::Private
02662 {
02663 public:
02664 Value result;
02665 FormulaTokens tokens;
02666 };
02667
02668 FormulaRecord::FormulaRecord():
02669 Record()
02670 {
02671 d = new FormulaRecord::Private();
02672 }
02673
02674 FormulaRecord::~FormulaRecord()
02675 {
02676 delete d;
02677 }
02678
02679 Value FormulaRecord::result() const
02680 {
02681 return d->result;
02682 }
02683
02684 void FormulaRecord::setResult( const Value& r )
02685 {
02686 d->result = r;
02687 }
02688
02689 FormulaTokens FormulaRecord::tokens() const
02690 {
02691 return d->tokens;
02692 }
02693
02694 void FormulaRecord::setData( unsigned size, const unsigned char* data )
02695 {
02696 if( size < 20 ) return;
02697
02698 setRow( readU16( data ) );
02699 setColumn( readU16( data+2 ) );
02700 setXfIndex( readU16( data+4 ) );
02701
02702 if( readU16( data+12 ) != 0xffff )
02703 {
02704
02705 setResult( Value( readFloat64( data+6 ) ) );
02706 }
02707 else
02708 {
02709 switch( data[6] )
02710 {
02711 case 0:
02712 setResult( Value( Value::String ) );
02713 break;
02714 case 1:
02715 setResult( Value( data[8] ? true : false ) );
02716 break;
02717 case 2:
02718 setResult( errorAsValue( data[8] ) );
02719 break;
02720 case 3:
02721 setResult( Value::empty() );
02722 break;
02723 default:
02724 setResult( Value::empty() );
02725 break;
02726 };
02727 }
02728
02729 unsigned formula_len = readU16( data+20 );
02730
02731
02732 d->tokens.clear();
02733 for( unsigned j = 22; j < size; )
02734 {
02735 unsigned ptg = data[j++];
02736 ptg = ((ptg & 0x40) ? (ptg | 0x20) : ptg) & 0x3F;
02737 FormulaToken token( ptg );
02738 token.setVersion( version() );
02739
02740 if( token.id() == FormulaToken::String )
02741 {
02742
02743 EString estr = (version()==Excel97) ?
02744 EString::fromUnicodeString( data+j, false, formula_len ) :
02745 EString::fromByteString( data+j, false, formula_len );
02746 token.setData( estr.size(), data+j );
02747 j += estr.size();
02748 }
02749 else
02750 {
02751
02752 if( token.size() > 1 )
02753 {
02754 token.setData( token.size(), data+j );
02755 j += token.size();
02756 }
02757 }
02758
02759 d->tokens.push_back( token );
02760 }
02761 }
02762
02763 void FormulaRecord::dump( std::ostream& out ) const
02764 {
02765 out << "FORMULA" << std::endl;
02766 out << " Row : " << row() << std::endl;
02767 out << " Column : " << column() << std::endl;
02768 out << " XF Index : " << xfIndex() << std::endl;
02769 out << " Result : " << result() << std::endl;
02770
02771 FormulaTokens ts = tokens();
02772 out << " Tokens : " << ts.size() << std::endl;
02773 for( unsigned i = 0; i < ts.size(); i++ )
02774 out << " " << ts[i] << std::endl;
02775
02776 }
02777
02778
02779
02780 const unsigned int LabelRecord::id = 0x0204;
02781
02782 class LabelRecord::Private
02783 {
02784 public:
02785 UString label;
02786 };
02787
02788 LabelRecord::LabelRecord():
02789 Record(), CellInfo()
02790 {
02791 d = new LabelRecord::Private();
02792 d->label = UString::null;
02793 }
02794
02795 LabelRecord::~LabelRecord()
02796 {
02797 delete d;
02798 }
02799
02800 UString LabelRecord::label() const
02801 {
02802 return d->label;
02803 }
02804
02805 void LabelRecord::setLabel( const UString& l )
02806 {
02807 d->label = l;
02808 }
02809
02810 void LabelRecord::setData( unsigned size, const unsigned char* data )
02811 {
02812 if( size < 6 ) return;
02813
02814 setRow( readU16( data ) );
02815 setColumn( readU16( data+2 ) );
02816 setXfIndex( readU16( data+4 ) );
02817
02818 UString label = ( version() >= Excel97 ) ?
02819 EString::fromUnicodeString( data+6, true, size-6 ).str() :
02820 EString::fromByteString( data+6, true, size-6 ).str();
02821 setLabel( label );
02822 }
02823
02824 void LabelRecord::dump( std::ostream& out ) const
02825 {
02826 out << "LABEL" << std::endl;
02827 out << " Row : " << row() << std::endl;
02828 out << " Column : " << column() << std::endl;
02829 out << " XF Index : " << xfIndex() << std::endl;
02830 out << " Label : " << label() << std::endl;
02831 }
02832
02833
02834
02835 const unsigned int HeaderRecord::id = 0x0014;
02836
02837 class HeaderRecord::Private
02838 {
02839 public:
02840 UString header;
02841 };
02842
02843 HeaderRecord::HeaderRecord():
02844 Record()
02845 {
02846 d = new HeaderRecord::Private();
02847 }
02848
02849 HeaderRecord::~HeaderRecord()
02850 {
02851 delete d;
02852 }
02853
02854 UString HeaderRecord::header() const
02855 {
02856 return d->header;
02857 }
02858
02859 void HeaderRecord::setHeader( const UString& header )
02860 {
02861 d->header = header;
02862 }
02863
02864 void HeaderRecord::setData( unsigned size, const unsigned char* data )
02865 {
02866 if( size < 2 ) return;
02867
02868 UString header = ( version() >= Excel97 ) ?
02869 EString::fromUnicodeString( data, true, size ).str() :
02870 EString::fromByteString( data, false, size ).str();
02871 setHeader( header );
02872 }
02873
02874 void HeaderRecord::dump( std::ostream& out ) const
02875 {
02876 out << "HEADER" << std::endl;
02877 out << " Header: " << header() << std::endl;
02878 }
02879
02880
02881
02882 const unsigned int LabelSSTRecord::id = 0x00fd;
02883
02884 class LabelSSTRecord::Private
02885 {
02886 public:
02887 unsigned sstIndex;
02888 };
02889
02890 LabelSSTRecord::LabelSSTRecord():
02891 Record(), CellInfo()
02892 {
02893 d = new LabelSSTRecord::Private();
02894 d->sstIndex = 0;
02895 }
02896
02897 LabelSSTRecord::~LabelSSTRecord()
02898 {
02899 delete d;
02900 }
02901
02902 unsigned LabelSSTRecord::sstIndex() const
02903 {
02904 return d->sstIndex;
02905 }
02906
02907 void LabelSSTRecord::setData( unsigned size, const unsigned char* data )
02908 {
02909 if( size < 10 ) return;
02910
02911 setRow( readU16( data ) );
02912 setColumn( readU16( data+2 ) );
02913 setXfIndex( readU16( data+4 ) );
02914
02915 d->sstIndex = readU32( data+6 );
02916 }
02917
02918 void LabelSSTRecord::dump( std::ostream& out ) const
02919 {
02920 out << "LABELSST" << std::endl;
02921 out << " Row : " << row() << std::endl;
02922 out << " Column : " << column() << std::endl;
02923 out << " XF Index : " << xfIndex() << std::endl;
02924 out << " SST Index : " << d->sstIndex << std::endl;
02925 }
02926
02927
02928
02929 const unsigned int LeftMarginRecord::id = 0x0026;
02930
02931 class LeftMarginRecord::Private
02932 {
02933 public:
02934 double leftMargin;
02935 };
02936
02937 LeftMarginRecord::LeftMarginRecord():
02938 Record()
02939 {
02940 d = new LeftMarginRecord::Private();
02941 d->leftMargin = 1.0;
02942 }
02943
02944 LeftMarginRecord::~LeftMarginRecord()
02945 {
02946 delete d;
02947 }
02948
02949 double LeftMarginRecord::leftMargin() const
02950 {
02951 return d->leftMargin;
02952 }
02953
02954 void LeftMarginRecord::setLeftMargin( double m )
02955 {
02956 d->leftMargin = m;
02957 }
02958
02959 void LeftMarginRecord::setData( unsigned size, const unsigned char* data )
02960 {
02961 if( size < 8 ) return;
02962 setLeftMargin( readFloat64( data ) );
02963 }
02964
02965 void LeftMarginRecord::dump( std::ostream& out ) const
02966 {
02967 out << "LEFTMARGIN" << std::endl;
02968 out << " Left Margin : " << leftMargin() << " inches" << std::endl;
02969 }
02970
02971
02972
02973 const unsigned int MergedCellsRecord::id = 0x00e5;
02974
02975 class MergedInfo
02976 {
02977 public:
02978 unsigned firstRow, lastRow, firstColumn, lastColumn;
02979 };
02980
02981 class MergedCellsRecord::Private
02982 {
02983 public:
02984 std::vector<MergedInfo> mergedCells;
02985 };
02986
02987 MergedCellsRecord::MergedCellsRecord():
02988 Record()
02989 {
02990 d = new MergedCellsRecord::Private();
02991 }
02992
02993 MergedCellsRecord::~MergedCellsRecord()
02994 {
02995 delete d;
02996 }
02997
02998 unsigned MergedCellsRecord::count() const
02999 {
03000 return d->mergedCells.size();
03001 }
03002
03003 unsigned MergedCellsRecord::firstRow( unsigned i ) const
03004 {
03005 if( i >= d->mergedCells.size() ) return 0;
03006 MergedInfo info = d->mergedCells[ i ];
03007 return info.firstRow;
03008 }
03009
03010 unsigned MergedCellsRecord::lastRow( unsigned i ) const
03011 {
03012 if( i >= d->mergedCells.size() ) return 0;
03013 MergedInfo info = d->mergedCells[ i ];
03014 return info.lastRow;
03015 }
03016
03017 unsigned MergedCellsRecord::firstColumn( unsigned i ) const
03018 {
03019 if( i >= d->mergedCells.size() ) return 0;
03020 MergedInfo info = d->mergedCells[ i ];
03021 return info.firstColumn;
03022 }
03023
03024 unsigned MergedCellsRecord::lastColumn( unsigned i ) const
03025 {
03026 if( i >= d->mergedCells.size() ) return 0;
03027 MergedInfo info = d->mergedCells[ i ];
03028 return info.lastColumn;
03029 }
03030
03031 void MergedCellsRecord::setData( unsigned size, const unsigned char* data )
03032 {
03033 if( size < 2 ) return;
03034
03035 unsigned num = readU16( data );
03036
03037
03038 if( size < 2 + num*4 ) return;
03039
03040 unsigned p = 2;
03041 for( unsigned i = 0; i < num; i++ )
03042 {
03043 MergedInfo info;
03044 info.firstRow = readU16( data + p );
03045 info.lastRow = readU16( data + p + 2 );
03046 info.firstColumn = readU16( data + p + 4 );
03047 info.lastColumn = readU16( data + p + 6 );
03048 p += 8;
03049 d->mergedCells.push_back( info );
03050 }
03051 }
03052
03053 void MergedCellsRecord::dump( std::ostream& out ) const
03054 {
03055 out << "MERGEDCELLS" << std::endl;
03056 out << " Count : " << count() << std::endl;
03057 for( unsigned c = 0; c < count(); c++ )
03058 {
03059 out << " Merged Cell #" << c << " : ";
03060 out << "Column " << firstColumn(c) << "-" << lastColumn(c);
03061 out << " Row " << firstRow(c) << "-" << lastRow(c);
03062 out << std::endl;
03063 }
03064 }
03065
03066
03067
03068 const unsigned int MulBlankRecord::id = 0x00be;
03069
03070 class MulBlankRecord::Private
03071 {
03072 public:
03073 std::vector<unsigned> xfIndexes;
03074 };
03075
03076 MulBlankRecord::MulBlankRecord():
03077 Record(), CellInfo(), ColumnSpanInfo()
03078 {
03079 d = new MulBlankRecord::Private();
03080 }
03081
03082 MulBlankRecord::~MulBlankRecord()
03083 {
03084 delete d;
03085 }
03086
03087 void MulBlankRecord::setData( unsigned size, const unsigned char* data )
03088 {
03089 if( size < 6 ) return;
03090
03091 setRow( readU16( data ) );
03092
03093 setFirstColumn( readU16( data+2 ) );
03094 setLastColumn( readU16( data+size-2 ) );
03095
03096 d->xfIndexes.clear();
03097 for( unsigned i = 4; i < size-2; i+= 2 )
03098 d->xfIndexes.push_back( readU16( data+i ) );
03099
03100
03101 }
03102
03103 unsigned MulBlankRecord::xfIndex( unsigned i ) const
03104 {
03105 if( i >= d->xfIndexes.size() ) return 0;
03106 return d->xfIndexes[ i ];
03107 }
03108
03109 void MulBlankRecord::dump( std::ostream& out ) const
03110 {
03111 out << "MULBLANK" << std::endl;
03112 out << " Row : " << row() << std::endl;
03113 out << " First Column : " << firstColumn() << std::endl;
03114 out << " Last Column : " << lastColumn() << std::endl;
03115 }
03116
03117
03118
03119 const unsigned int MulRKRecord::id = 0x00bd;
03120
03121 class MulRKRecord::Private
03122 {
03123 public:
03124 std::vector<unsigned> xfIndexes;
03125 std::vector<bool> isIntegers;
03126 std::vector<int> intValues;
03127 std::vector<double> floatValues;
03128 std::vector<unsigned> rkValues;
03129 };
03130
03131 MulRKRecord::MulRKRecord():
03132 Record(), CellInfo(), ColumnSpanInfo()
03133 {
03134 d = new MulRKRecord::Private();
03135 }
03136
03137 MulRKRecord::~MulRKRecord()
03138 {
03139 delete d;
03140 }
03141
03142 unsigned MulRKRecord::xfIndex( unsigned i ) const
03143 {
03144 if( i >= d->xfIndexes.size() ) return 0;
03145 return d->xfIndexes[ i ];
03146 }
03147
03148 bool MulRKRecord::isInteger( unsigned i ) const
03149 {
03150 if( i >= d->isIntegers.size() ) return true;
03151 return d->isIntegers[ i ];
03152 }
03153
03154 int MulRKRecord::asInteger( unsigned i ) const
03155 {
03156 if( i >= d->intValues.size() ) return 0;
03157 return d->intValues[ i ];
03158 }
03159
03160 double MulRKRecord::asFloat( unsigned i ) const
03161 {
03162 if( i >= d->floatValues.size() ) return 0.0;
03163 return d->floatValues[ i ];
03164 }
03165
03166 unsigned MulRKRecord::encodedRK( unsigned i ) const
03167 {
03168 if( i >= d->rkValues.size() ) return 0;
03169 return d->rkValues[ i ];
03170 }
03171
03172 void MulRKRecord::setData( unsigned size, const unsigned char* data )
03173 {
03174 if( size < 6 ) return;
03175
03176 setRow( readU16( data ) );
03177
03178 setFirstColumn( readU16( data+2 ) );
03179 setLastColumn( readU16( data+size-2 ) );
03180
03181 d->xfIndexes.clear();
03182 d->isIntegers.clear();
03183 d->intValues.clear();
03184 d->floatValues.clear();
03185 for( unsigned i = 4; i < size-2; i+= 6 )
03186 {
03187 d->xfIndexes.push_back( readU16( data+i ) );
03188 unsigned rk = readU32( data+i+2 );
03189 d->rkValues.push_back( rk );
03190 bool isInteger = true; int iv = 0; double fv = 0.0;
03191 decodeRK( rk, isInteger, iv, fv );
03192
03193 d->isIntegers.push_back( isInteger );
03194 d->intValues.push_back( isInteger ? iv : (int)fv );
03195 d->floatValues.push_back( !isInteger ? fv : (double)iv );
03196 }
03197
03198
03199 }
03200
03201 void MulRKRecord::dump( std::ostream& out ) const
03202 {
03203 out << "MULRK" << std::endl;
03204 out << " Row : " << row() << std::endl;
03205 out << " First Column : " << firstColumn() << std::endl;
03206 out << " Last Column : " << lastColumn() << std::endl;
03207 for( unsigned c = firstColumn(); c <= lastColumn(); c++ )
03208 {
03209 out << " Column " << c << " : " << asFloat( c-firstColumn() );
03210 out << " Encoded: " << std::hex << encodedRK( c-firstColumn() );
03211 out << std::endl;
03212 }
03213 }
03214
03215
03216
03217 const unsigned int NameRecord::id = 0x0018;
03218
03219 class NameRecord::Private
03220 {
03221 public:
03222 unsigned optionFlags;
03223 UString definedName;
03224 };
03225
03226
03227 NameRecord::NameRecord()
03228 {
03229 d = new Private;
03230 d->optionFlags = 0;
03231 }
03232
03233 NameRecord::~NameRecord()
03234 {
03235 delete d;
03236 }
03237
03238 void NameRecord::setDefinedName( const UString& name )
03239 {
03240 d->definedName = name;
03241 }
03242
03243 UString NameRecord::definedName() const
03244 {
03245 return d->definedName;
03246 }
03247
03248 void NameRecord::setData( unsigned size, const unsigned char* data )
03249 {
03250 if( size < 14 ) return;
03251
03252 d->optionFlags = readU16( data );
03253 unsigned len = data[3];
03254
03255 if ( version() == Excel95 )
03256 {
03257 char* buffer = new char[ len+1 ];
03258 memcpy( buffer, data + 14, len );
03259 buffer[ len ] = 0;
03260 d->definedName = UString( buffer );
03261 delete[] buffer;
03262 }
03263
03264 if ( version() == Excel97 )
03265 {
03266 UString str = UString();
03267 for( unsigned k=0; k<len; k++ )
03268 {
03269 unsigned uchar = readU16( data + 14 + k*2 );
03270 str.append( UString(uchar) );
03271 }
03272 d->definedName = str;
03273 }
03274 }
03275
03276 void NameRecord::dump( std::ostream& out ) const
03277 {
03278 }
03279
03280
03281
03282 const unsigned int NumberRecord::id = 0x0203;
03283
03284 class NumberRecord::Private
03285 {
03286 public:
03287 double number;
03288 };
03289
03290 NumberRecord::NumberRecord():
03291 Record(), CellInfo()
03292 {
03293 d = new NumberRecord::Private();
03294 d->number = 0.0;
03295 }
03296
03297 NumberRecord::~NumberRecord()
03298 {
03299 delete d;
03300 }
03301
03302 double NumberRecord::number() const
03303 {
03304 return d->number;
03305 }
03306
03307 void NumberRecord::setNumber( double f )
03308 {
03309 d->number = f;
03310 }
03311
03312
03313 void NumberRecord::setData( unsigned size, const unsigned char* data )
03314 {
03315 if( size < 14 ) return;
03316
03317 setRow( readU16( data ) );
03318 setColumn( readU16( data+2 ) );
03319 setXfIndex( readU16( data+4 ) );
03320 setNumber( readFloat64( data+6 ) );
03321 }
03322
03323 void NumberRecord::dump( std::ostream& out ) const
03324 {
03325 out << "NUMBER" << std::endl;
03326 out << " Row : " << row() << std::endl;
03327 out << " Column : " << column() << std::endl;
03328 out << " XF Index : " << xfIndex() << std::endl;
03329 out << " Value : " << number() << std::endl;
03330 }
03331
03332
03333
03334 const unsigned int PaletteRecord::id = 0x0092;
03335
03336 class PaletteRecord::Private
03337 {
03338 public:
03339 std::vector<Color> colors;
03340 };
03341
03342 PaletteRecord::PaletteRecord():
03343 Record()
03344 {
03345 d = new PaletteRecord::Private();
03346 }
03347
03348 PaletteRecord::~PaletteRecord()
03349 {
03350 delete d;
03351 }
03352
03353 Color PaletteRecord::color( unsigned i ) const
03354 {
03355 return d->colors[ i ];
03356 }
03357
03358 unsigned PaletteRecord::count() const
03359 {
03360 return d->colors.size();
03361 }
03362
03363 void PaletteRecord::setData( unsigned size, const unsigned char* data )
03364 {
03365 if( size < 14 ) return;
03366
03367 unsigned num = readU16( data );
03368
03369 unsigned p = 2;
03370 for( unsigned i = 0; i < num; i++, p+=4 )
03371 {
03372 unsigned red = data[ p ];
03373 unsigned green = data[ p+1 ];
03374 unsigned blue = data[ p+2 ];
03375 d->colors.push_back( Color( red, green, blue ) );
03376 }
03377 }
03378
03379 void PaletteRecord::dump( std::ostream& out ) const
03380 {
03381 out << "PALETTE" << std::endl;
03382 out << " Count : " << count() << std::endl;
03383 for( unsigned i = 0; i < count(); i++ )
03384 {
03385 out << " Color #" << std::setw(2) << i << " : ";
03386 Color c = color( i );
03387 out << "R:" << std::setw(3) << c.red;
03388 out << " G:" << std::setw(3) << c.green;
03389 out << " B:" << std::setw(3) << c.blue << std::endl;
03390 }
03391 }
03392
03393
03394
03395 const unsigned int RightMarginRecord::id = 0x0027;
03396
03397 class RightMarginRecord::Private
03398 {
03399 public:
03400 double rightMargin;
03401 };
03402
03403 RightMarginRecord::RightMarginRecord():
03404 Record()
03405 {
03406 d = new RightMarginRecord::Private();
03407 d->rightMargin = 1.0;
03408 }
03409
03410 RightMarginRecord::~RightMarginRecord()
03411 {
03412 delete d;
03413 }
03414
03415 double RightMarginRecord::rightMargin() const
03416 {
03417 return d->rightMargin;
03418 }
03419
03420 void RightMarginRecord::setRightMargin( double m )
03421 {
03422 d->rightMargin = m;
03423 }
03424
03425 void RightMarginRecord::setData( unsigned size, const unsigned char* data )
03426 {
03427 if( size < 8 ) return;
03428 setRightMargin( readFloat64( data ) );
03429 }
03430
03431 void RightMarginRecord::dump( std::ostream& out ) const
03432 {
03433 out << "RIGHTMARGIN" << std::endl;
03434 out << " Right Margin : " << rightMargin() << " inches " << std::endl;
03435 }
03436
03437
03438
03439 const unsigned int RKRecord::id = 0x027e;
03440
03441 class RKRecord::Private
03442 {
03443 public:
03444 bool integer;
03445 unsigned rk;
03446 int i;
03447 double f;
03448 };
03449
03450 RKRecord::RKRecord():
03451 Record(), CellInfo()
03452 {
03453 d = new RKRecord::Private();
03454 d->integer = true;
03455 d->rk = 0;
03456 d->i = 0;
03457 d->f = 0.0;
03458 }
03459
03460 RKRecord::~RKRecord()
03461 {
03462 delete d;
03463 }
03464
03465 bool RKRecord::isInteger() const
03466 {
03467 return d->integer;
03468 }
03469
03470 bool RKRecord::isFloat() const
03471 {
03472 return !d->integer;
03473 }
03474
03475 int RKRecord::asInteger() const
03476 {
03477 if( d->integer )
03478 return d->i;
03479 else
03480 return (int)d->f;
03481 }
03482
03483 double RKRecord::asFloat() const
03484 {
03485 if( !d->integer )
03486 return d->f;
03487 else
03488 return (double)d->i;
03489 }
03490
03491 void RKRecord::setInteger( int i )
03492 {
03493 d->integer = true;
03494 d->i = i;
03495 d->f = (double)i;
03496 }
03497
03498 void RKRecord::setFloat( double f )
03499 {
03500 d->integer = false;
03501 d->i = (int)f;
03502 d->f = f;
03503 }
03504
03505 unsigned RKRecord::encodedRK() const
03506 {
03507 return d->rk;
03508 }
03509
03510
03511
03512 void RKRecord::setData( unsigned size, const unsigned char* data )
03513 {
03514 if( size < 10 ) return;
03515
03516 setRow( readU16( data ) );
03517 setColumn( readU16( data+2 ) );
03518 setXfIndex( readU16( data+4 ) );
03519
03520 int i = 0; double f = 0.0;
03521 d->rk = readU32( data+6 );
03522 decodeRK( d->rk, d->integer, i, f );
03523 if( d->integer ) setInteger( i );
03524 else setFloat( f );
03525 }
03526
03527 void RKRecord::dump( std::ostream& out ) const
03528 {
03529 out << "RK" << std::endl;
03530 out << " Row : " << row() << std::endl;
03531 out << " Column : " << column() << std::endl;
03532 out << " XF Index : " << xfIndex() << std::endl;
03533 out << " Value : " << asFloat() << std::endl;
03534 out << " Encoded RK : 0x" << std::hex << encodedRK() << std::endl;
03535 out << std::dec;
03536 }
03537
03538
03539
03540 const unsigned int RowRecord::id = 0x0208;
03541
03542 class RowRecord::Private
03543 {
03544 public:
03545 unsigned row;
03546 unsigned height;
03547 unsigned xfIndex;
03548 bool hidden;
03549 };
03550
03551 RowRecord::RowRecord():
03552 Record(), ColumnSpanInfo()
03553 {
03554 d = new RowRecord::Private();
03555 d->row = 0;
03556 d->height = 50;
03557 d->xfIndex = 0;
03558 d->hidden = false;
03559 }
03560
03561 RowRecord::~RowRecord()
03562 {
03563 delete d;
03564 }
03565
03566 unsigned RowRecord::row() const
03567 {
03568 return d->row;
03569 }
03570
03571 void RowRecord::setRow( unsigned r )
03572 {
03573 d->row = r;
03574 }
03575
03576 unsigned RowRecord::height() const
03577 {
03578 return d->height;
03579 }
03580
03581 void RowRecord::setHeight( unsigned h )
03582 {
03583 d->height = h;
03584 }
03585
03586 unsigned RowRecord::xfIndex() const
03587 {
03588 return d->xfIndex;
03589 }
03590
03591 void RowRecord::setXfIndex( unsigned i )
03592 {
03593 d->xfIndex = i;
03594 }
03595
03596 bool RowRecord::hidden() const
03597 {
03598 return d->hidden;
03599 }
03600
03601 void RowRecord::setHidden( bool h )
03602 {
03603 d->hidden = h;
03604 }
03605
03606 void RowRecord::setData( unsigned size, const unsigned char* data )
03607 {
03608 if( size < 16 ) return;
03609
03610 setRow( readU16( data ) );
03611 setFirstColumn( readU16( data+2 ) );
03612 setLastColumn( readU16( data+4 ) );
03613 setHeight( readU16( data+6 ) & 0x7fff );
03614 setXfIndex( readU16( data+14 ) & 0xfff );
03615
03616 unsigned options = readU16( data+12 );
03617 setHidden ( options & 0x20 );
03618 }
03619
03620 void RowRecord::dump( std::ostream& out ) const
03621 {
03622 out << "ROW" << std::endl;
03623 out << " Row : " << row() << std::endl;
03624 out << " First Column : " << firstColumn() << std::endl;
03625 out << " Last Column : " << lastColumn() << std::endl;
03626 out << " Height : " << height() << std::endl;
03627 out << " XF Index : " << xfIndex() << std::endl;
03628 out << " Hidden : " << ( hidden() ? "Yes" : "No" ) << std::endl;
03629 }
03630
03631
03632
03633 const unsigned int RStringRecord::id = 0x00d6;
03634
03635 class RStringRecord::Private
03636 {
03637 public:
03638 UString label;
03639 };
03640
03641 RStringRecord::RStringRecord():
03642 Record(), CellInfo()
03643 {
03644 d = new RStringRecord::Private();
03645 d->label = UString::null;
03646 }
03647
03648 RStringRecord::~RStringRecord()
03649 {
03650 delete d;
03651 }
03652
03653 UString RStringRecord::label() const
03654 {
03655 return d->label;
03656 }
03657
03658 void RStringRecord::setLabel( const UString& l )
03659 {
03660 d->label = l;
03661 }
03662
03663
03664 void RStringRecord::setData( unsigned size, const unsigned char* data )
03665 {
03666 if( size < 6 ) return;
03667
03668 setRow( readU16( data ) );
03669 setColumn( readU16( data+2 ) );
03670 setXfIndex( readU16( data+4 ) );
03671
03672
03673 UString label = ( version() >= Excel97 ) ?
03674 EString::fromUnicodeString( data+6, true, size-6 ).str() :
03675 EString::fromByteString( data+6, true, size-6 ).str();
03676 setLabel( label );
03677 }
03678
03679 void RStringRecord::dump( std::ostream& out ) const
03680 {
03681 out << "RSTRING" << std::endl;
03682 out << " Row : " << row() << std::endl;
03683 out << " Column : " << column() << std::endl;
03684 out << " XF Index : " << xfIndex() << std::endl;
03685 out << " Label : " << label() << std::endl;
03686 }
03687
03688
03689
03690 const unsigned int SSTRecord::id = 0x00fc;
03691
03692 class SSTRecord::Private
03693 {
03694 public:
03695 unsigned total;
03696 unsigned count;
03697 std::vector<UString> strings;
03698 };
03699
03700 SSTRecord::SSTRecord():
03701 Record()
03702 {
03703 d = new SSTRecord::Private();
03704 d->total = 0;
03705 d->count = 0;
03706 }
03707
03708 SSTRecord::~SSTRecord()
03709 {
03710 delete d;
03711 }
03712
03713 UString sstrecord_get_plain_string( const unsigned char* data, unsigned length )
03714 {
03715 char* buffer = new char[ length+1 ];
03716 memcpy( buffer, data, length );
03717 buffer[ length ] = 0;
03718 UString str = UString( buffer );
03719 delete[] buffer;
03720 return str;
03721 }
03722
03723 void SSTRecord::setData( unsigned size, const unsigned char* data )
03724 {
03725 if( size < 8 ) return;
03726
03727 d->total = readU32( data );
03728 d->count = readU32( data+4 );
03729
03730 unsigned offset = 8;
03731 d->strings.clear();
03732
03733 for( unsigned i = 0; i < d->count; i++ )
03734 {
03735
03736 if (offset >= size) {
03737 std::cerr << "Warning: reached end of SST record, but not all strings have been read!" << std::endl;
03738 break;
03739 }
03740
03741 EString es = EString::fromUnicodeString( data+offset, true, size - offset );
03742 d->strings.push_back( es.str() );
03743 offset += es.size();
03744 }
03745
03746
03747
03748 if( d->count < d->strings.size() )
03749 {
03750 std::cerr << "Warning: mismatch number of string in SST record!" << std::endl;
03751 d->count = d->strings.size();
03752 }
03753 }
03754
03755 unsigned SSTRecord::count() const
03756 {
03757 return d->count;
03758 }
03759
03760
03761 UString SSTRecord::stringAt( unsigned index ) const
03762 {
03763 if( index >= count()) return UString::null;
03764 return d->strings[ index ];
03765 }
03766
03767 void SSTRecord::dump( std::ostream& out ) const
03768 {
03769 out << "SST" << std::endl;
03770 out << " Occurences : " << d->total << std::endl;
03771 out << " Count : " << count() << std::endl;
03772 for( unsigned i = 0; i < count(); i++ )
03773 out << " String #" << std::setw(2) << i << " : " <<
03774 stringAt( i ) << std::endl;
03775 }
03776
03777
03778
03779 const unsigned int StringRecord::id = 0x0207;
03780
03781 class StringRecord::Private
03782 {
03783 public:
03784 UString string;
03785 };
03786
03787 StringRecord::StringRecord():
03788 Record()
03789 {
03790 d = new StringRecord::Private();
03791 }
03792
03793 StringRecord::~StringRecord()
03794 {
03795 delete d;
03796 }
03797
03798 void StringRecord::setData( unsigned size, const unsigned char* data )
03799 {
03800 if( size < 3 ) return;
03801
03802
03803
03804 EString es = EString::fromUnicodeString( data, true, size );
03805 d->string = es.str();
03806 }
03807
03808 UString StringRecord::ustring() const
03809 {
03810 return d->string;
03811 }
03812
03813 Value StringRecord::value() const
03814 {
03815 return Value( d->string );
03816 }
03817
03818 void StringRecord::dump( std::ostream& out ) const
03819 {
03820 out << "STRING" << std::endl;
03821 out << " String : " << ustring() << std::endl;
03822 }
03823
03824
03825
03826
03827 const unsigned int TopMarginRecord::id = 0x0028;
03828
03829 class TopMarginRecord::Private
03830 {
03831 public:
03832 double topMargin;
03833 };
03834
03835 TopMarginRecord::TopMarginRecord():
03836 Record()
03837 {
03838 d = new TopMarginRecord::Private();
03839 d->topMargin = 1.0;
03840 }
03841
03842 TopMarginRecord::~TopMarginRecord()
03843 {
03844 delete d;
03845 }
03846
03847 double TopMarginRecord::topMargin() const
03848 {
03849 return d->topMargin;
03850 }
03851
03852 void TopMarginRecord::setTopMargin( double m )
03853 {
03854 d->topMargin = m;
03855 }
03856
03857 void TopMarginRecord::setData( unsigned size, const unsigned char* data )
03858 {
03859 if( size < 8 ) return;
03860 setTopMargin( readFloat64( data ) );
03861 }
03862
03863 void TopMarginRecord::dump( std::ostream& out ) const
03864 {
03865 out << "TOPMARGIN" << std::endl;
03866 out << " Top Margin : " << topMargin() << " inches " << std::endl;
03867 }
03868
03869
03870
03871 const unsigned int XFRecord::id = 0x00e0;
03872
03873 class XFRecord::Private
03874 {
03875 public:
03876 unsigned fontIndex;
03877 unsigned formatIndex;
03878 bool locked;
03879 bool formulaHidden;
03880 unsigned parentStyle;
03881 unsigned horizontalAlignment;
03882 unsigned verticalAlignment;
03883 bool textWrap;
03884 unsigned rotationAngle;
03885 bool stackedLetters;
03886 unsigned indentLevel;
03887 bool shrinkContent;
03888 unsigned leftBorderStyle;
03889 unsigned leftBorderColor;
03890 unsigned rightBorderStyle;
03891 unsigned rightBorderColor;
03892 unsigned topBorderStyle;
03893 unsigned topBorderColor;
03894 unsigned bottomBorderStyle;
03895 unsigned bottomBorderColor;
03896 bool diagonalTopLeft;
03897 bool diagonalBottomLeft;
03898 unsigned diagonalStyle;
03899 unsigned diagonalColor;
03900 unsigned fillPattern;
03901 unsigned patternForeColor;
03902 unsigned patternBackColor;
03903 };
03904
03905 XFRecord::XFRecord(): Record()
03906 {
03907 d = new XFRecord::Private();
03908 d->fontIndex = 0;
03909 d->formatIndex = 0;
03910 d->locked = false;
03911 d->formulaHidden = false;
03912 d->parentStyle = 0;
03913 d->horizontalAlignment = Left;
03914 d->verticalAlignment = VCentered;
03915 d->textWrap = false;
03916 d->rotationAngle = 0;
03917 d->stackedLetters = 0;
03918 d->indentLevel = 0;
03919 d->shrinkContent = 0;
03920 d->leftBorderStyle = 0;
03921 d->leftBorderColor = 0;
03922 d->rightBorderStyle = 0;
03923 d->rightBorderColor = 0;
03924 d->topBorderStyle = 0;
03925 d->topBorderColor = 0;
03926 d->bottomBorderStyle = 0;
03927 d->bottomBorderColor = 0;
03928 d->diagonalTopLeft = false;
03929 d->diagonalBottomLeft = false;
03930 d->diagonalStyle = 0;
03931 d->diagonalColor = 0;
03932 d->fillPattern = 0;
03933 d->patternForeColor = 0;
03934 d->patternBackColor = 0;
03935 }
03936
03937 XFRecord::~XFRecord()
03938 {
03939 delete d;
03940 }
03941
03942 XFRecord::XFRecord( const XFRecord& xf ): Record()
03943 {
03944 d = new XFRecord::Private();
03945 operator=( xf );
03946 }
03947
03948 XFRecord& XFRecord::operator=( const XFRecord& xf )
03949 {
03950 d->fontIndex = xf.fontIndex();
03951 d->formatIndex = xf.formatIndex();
03952 d->locked = xf.locked();
03953 d->formulaHidden = xf.formulaHidden();
03954 d->parentStyle = xf.parentStyle();
03955 d->horizontalAlignment = xf.horizontalAlignment();
03956 d->verticalAlignment = xf.verticalAlignment();
03957 d->textWrap = xf.textWrap();
03958 d->rotationAngle = xf.rotationAngle();
03959 d->stackedLetters = xf.stackedLetters();
03960 d->indentLevel = xf.indentLevel();
03961 d->shrinkContent = xf.shrinkContent();
03962 d->leftBorderStyle = xf.leftBorderStyle();
03963 d->leftBorderColor = xf.leftBorderColor();
03964 d->rightBorderStyle = xf.rightBorderStyle();
03965 d->rightBorderColor = xf.rightBorderColor();
03966 d->topBorderStyle = xf.topBorderStyle();
03967 d->topBorderColor = xf.topBorderColor();
03968 d->bottomBorderStyle = xf.bottomBorderStyle();
03969 d->bottomBorderColor = xf.bottomBorderColor();
03970 d->diagonalTopLeft = xf.diagonalTopLeft();
03971 d->diagonalBottomLeft = xf.diagonalBottomLeft();
03972 d->diagonalStyle = xf.diagonalStyle();
03973 d->diagonalColor = xf.diagonalColor();
03974 d->fillPattern = xf.fillPattern();
03975 d->patternForeColor = xf.patternForeColor();
03976 d->patternBackColor = xf.patternBackColor();
03977 return *this;
03978 }
03979
03980 unsigned XFRecord::fontIndex() const
03981 {
03982 return d->fontIndex;
03983 }
03984
03985 void XFRecord::setFontIndex( unsigned fi )
03986 {
03987 d->fontIndex = fi;
03988 }
03989
03990 unsigned XFRecord::formatIndex() const
03991 {
03992 return d->formatIndex;
03993 }
03994
03995 void XFRecord::setFormatIndex( unsigned fi )
03996 {
03997 d->formatIndex = fi;
03998 }
03999
04000 bool XFRecord::locked() const
04001 {
04002 return d->locked;
04003 }
04004
04005 void XFRecord::setLocked( bool l )
04006 {
04007 d->locked = l;
04008 }
04009
04010 bool XFRecord::formulaHidden() const
04011 {
04012 return d->formulaHidden;
04013 }
04014
04015 void XFRecord::setFormulaHidden( bool f )
04016 {
04017 d->formulaHidden = f;
04018 }
04019
04020 unsigned XFRecord::parentStyle() const
04021 {
04022 return d->parentStyle;
04023 }
04024
04025 void XFRecord::setParentStyle( unsigned p )
04026 {
04027 d->parentStyle = p;
04028 }
04029
04030 unsigned XFRecord::horizontalAlignment() const
04031 {
04032 return d->horizontalAlignment;
04033 }
04034
04035 void XFRecord::setHorizontalAlignment( unsigned ha )
04036 {
04037 d->horizontalAlignment = ha;
04038 }
04039
04040 const char* XFRecord::horizontalAlignmentAsString() const
04041 {
04042 const char *result = "Unknown";
04043 switch( horizontalAlignment() )
04044 {
04045 case General: result = "General"; break;
04046 case Left: result = "Left"; break;
04047 case Centered: result = "Centered"; break;
04048 case Right: result = "Right"; break;
04049 case Justified: result = "Justified"; break;
04050 case Filled: result = "Filled"; break;
04051 default: break;
04052 }
04053 return result;
04054 }
04055
04056 unsigned XFRecord::verticalAlignment() const
04057 {
04058 return d->verticalAlignment;
04059 }
04060
04061 void XFRecord::setVerticalAlignment( unsigned va )
04062 {
04063 d->verticalAlignment = va;
04064 }
04065
04066 const char* XFRecord::verticalAlignmentAsString() const
04067 {
04068 const char *result = "Unknown";
04069 switch( verticalAlignment() )
04070 {
04071 case Top: result = "Top"; break;
04072 case VCentered: result = "Centered"; break;
04073 case Bottom: result = "Bottom"; break;
04074 case VJustified: result = "Justified"; break;
04075 case VDistributed: result = "Distributed"; break;
04076 default: break;
04077 }
04078 return result;
04079 }
04080
04081 bool XFRecord::textWrap() const
04082 {
04083 return d->textWrap;
04084 }
04085
04086 void XFRecord::setTextWrap( bool wrap )
04087 {
04088 d->textWrap = wrap;
04089 }
04090
04091 unsigned XFRecord::rotationAngle() const
04092 {
04093 return d->rotationAngle;
04094 }
04095
04096 void XFRecord::setRotationAngle( unsigned angle )
04097 {
04098 d->rotationAngle = angle;
04099 }
04100
04101 bool XFRecord::stackedLetters() const
04102 {
04103 return d->stackedLetters;
04104 }
04105
04106 void XFRecord::setStackedLetters( bool stacked )
04107 {
04108 d->stackedLetters = stacked;
04109 }
04110
04111 unsigned XFRecord::indentLevel() const
04112 {
04113 return d->indentLevel;
04114 }
04115
04116 void XFRecord::setIndentLevel( unsigned i )
04117 {
04118 d->indentLevel = i;
04119 }
04120
04121 bool XFRecord::shrinkContent() const
04122 {
04123 return d->shrinkContent;
04124 }
04125
04126 void XFRecord::setShrinkContent( bool s )
04127 {
04128 d->shrinkContent = s;
04129 }
04130
04131 unsigned XFRecord::leftBorderStyle() const
04132 {
04133 return d->leftBorderStyle;
04134 }
04135
04136 void XFRecord::setLeftBorderStyle( unsigned style )
04137 {
04138 d->leftBorderStyle = style;
04139 }
04140
04141 unsigned XFRecord::leftBorderColor() const
04142 {
04143 return d->leftBorderColor;
04144 }
04145
04146 void XFRecord::setLeftBorderColor( unsigned color )
04147 {
04148 d->leftBorderColor = color;
04149 }
04150
04151 unsigned XFRecord::rightBorderStyle() const
04152 {
04153 return d->rightBorderStyle;
04154 }
04155
04156 void XFRecord::setRightBorderStyle( unsigned style )
04157 {
04158 d->rightBorderStyle = style;
04159 }
04160
04161 unsigned XFRecord::rightBorderColor() const
04162 {
04163 return d->rightBorderColor;
04164 }
04165
04166 void XFRecord::setRightBorderColor( unsigned color )
04167 {
04168 d->rightBorderColor = color;
04169 }
04170
04171 unsigned XFRecord::topBorderStyle() const
04172 {
04173 return d->topBorderStyle;
04174 }
04175
04176 void XFRecord::setTopBorderStyle( unsigned style )
04177 {
04178 d->topBorderStyle = style;
04179 }
04180
04181 unsigned XFRecord::topBorderColor() const
04182 {
04183 return d->topBorderColor;
04184 }
04185
04186 void XFRecord::setTopBorderColor( unsigned color )
04187 {
04188 d->topBorderColor = color;
04189 }
04190
04191 unsigned XFRecord::bottomBorderStyle() const
04192 {
04193 return d->bottomBorderStyle;
04194 }
04195
04196 void XFRecord::setBottomBorderStyle( unsigned style )
04197 {
04198 d->bottomBorderStyle = style;
04199 }
04200
04201 unsigned XFRecord::bottomBorderColor() const
04202 {
04203 return d->bottomBorderColor;
04204 }
04205
04206 void XFRecord::setBottomBorderColor( unsigned color )
04207 {
04208 d->bottomBorderColor = color;
04209 }
04210
04211 bool XFRecord::diagonalTopLeft() const
04212 {
04213 return d->diagonalTopLeft;
04214 }
04215
04216 void XFRecord::setDiagonalTopLeft( bool dd )
04217 {
04218 d->diagonalTopLeft = dd;
04219 }
04220
04221 bool XFRecord::diagonalBottomLeft() const
04222 {
04223 return d->diagonalBottomLeft;
04224 }
04225
04226 void XFRecord::setDiagonalBottomLeft( bool dd )
04227 {
04228 d->diagonalBottomLeft = dd;
04229 }
04230
04231 unsigned XFRecord::diagonalStyle() const
04232 {
04233 return d->diagonalStyle;
04234 }
04235
04236 void XFRecord::setDiagonalStyle( unsigned style )
04237 {
04238 d->diagonalStyle = style;
04239 }
04240
04241 unsigned XFRecord::diagonalColor() const
04242 {
04243 return d->diagonalColor;
04244 }
04245
04246 void XFRecord::setDiagonalColor( unsigned color )
04247 {
04248 d->diagonalColor = color;
04249 }
04250
04251 unsigned XFRecord::fillPattern() const
04252 {
04253 return d->fillPattern;
04254 }
04255
04256 void XFRecord::setFillPattern( unsigned pattern )
04257 {
04258 d->fillPattern = pattern;
04259 }
04260
04261 unsigned XFRecord::patternForeColor() const
04262 {
04263 return d->patternForeColor;
04264 }
04265
04266 void XFRecord::setPatternForeColor( unsigned color )
04267 {
04268 d->patternForeColor = color;
04269 }
04270
04271 unsigned XFRecord::patternBackColor() const
04272 {
04273 return d->patternBackColor;
04274 }
04275
04276 void XFRecord::setPatternBackColor( unsigned color )
04277 {
04278 d->patternBackColor = color;
04279 }
04280
04281 void XFRecord::setData( unsigned size, const unsigned char* data )
04282 {
04283 unsigned recordSize = ( version() == Excel97 ) ? 20: 16;
04284 if( size < recordSize ) return;
04285
04286 setFontIndex( readU16( data ) );
04287 setFormatIndex( readU16( data+2 ) );
04288
04289 unsigned protection = readU16( data+4 ) & 7;
04290 setLocked( protection & 1 );
04291 setFormulaHidden( protection & 2 );
04292
04293 setParentStyle( readU16( data+4 ) >> 4 );
04294
04295 unsigned align = data[6];
04296 setHorizontalAlignment( align & 0x07 );
04297 setVerticalAlignment( align >> 4 );
04298 setTextWrap( align & 0x08 );
04299
04300 unsigned angle = data[7];
04301 setRotationAngle( ( angle != 255 ) ? ( angle & 0x7f ) : 0 );
04302 setStackedLetters( angle == 255 );
04303
04304 if( version() == Excel97 )
04305 {
04306 unsigned options = data[8];
04307 unsigned attributes = data[9];
04308
04309 setIndentLevel( options & 0x0f );
04310 setShrinkContent( options & 0x10 );
04311
04312 unsigned linestyle = readU16( data + 10 );
04313 unsigned color1 = readU16( data + 12 );
04314
04315 unsigned flag = readU16( data + 16 );
04316 unsigned fill = readU16( data + 18 );
04317
04318 setLeftBorderStyle( linestyle & 0xf );
04319 setRightBorderStyle( ( linestyle >> 4 ) & 0xf );
04320 setTopBorderStyle( ( linestyle >> 8 ) & 0xf );
04321 setBottomBorderStyle( ( linestyle >> 12 ) & 0xf );
04322
04323 setLeftBorderColor( color1 & 0x7f );
04324 setRightBorderColor( ( color1 >> 7 ) & 0x7f );
04325 setTopBorderColor( color1 & 0x7f );
04326 setBottomBorderColor( ( color1 >> 7 ) & 0x7f );
04327
04328 setDiagonalTopLeft( color1 & 0x40 );
04329 setDiagonalBottomLeft( color1 & 0x40 );
04330 setDiagonalStyle( ( flag >> 4 ) & 0x1e );
04331 setDiagonalColor( ( ( flag & 0x1f ) << 2 ) + ( ( color1 >> 14 ) & 3 ));
04332
04333 setFillPattern( ( flag >> 10 ) & 0x3f );
04334 setPatternForeColor( fill & 0x7f );
04335 setPatternBackColor( ( fill >> 7 ) & 0x7f );
04336 }
04337 else
04338 {
04339 unsigned data1 = readU32( data + 8 );
04340 unsigned data2 = readU32( data + 12 );
04341
04342 setPatternForeColor( data1 & 0x7f );
04343 setPatternBackColor( ( data1 >> 7 ) & 0x7f );
04344 setFillPattern( ( data1 >> 16 ) & 0x3f );
04345
04346 setBottomBorderStyle( ( data1 >> 22 ) & 0x07 );
04347 setBottomBorderColor( ( data1 >> 25 ) & 0x7f );
04348
04349 setTopBorderStyle( data2 & 0x07 );
04350 setLeftBorderStyle( ( data2 >> 3 ) & 0x07 );
04351 setRightBorderStyle( ( data2 >> 6 ) & 0x07 );
04352
04353 setTopBorderColor( ( data2 >> 9 ) & 0x7f );
04354 setLeftBorderColor( ( data2 >> 16 ) & 0x7f );
04355 setRightBorderColor( ( data2 >> 23 ) & 0x7f );
04356 }
04357 }
04358
04359 void XFRecord::dump( std::ostream& out ) const
04360 {
04361 out << "XF" << std::endl;
04362 out << " Parent Style : " << parentStyle() << std::endl;
04363 out << " Font Index : " << fontIndex() << std::endl;
04364 out << " Format Index : " << formatIndex() << std::endl;
04365 out << " Locked : " << (locked()?"Yes":"No") << std::endl;
04366 out << " Formula Visibility : " << (formulaHidden()?"Hidden":"Visible") << std::endl;
04367 out << " Horizontal Align : " << horizontalAlignmentAsString() << std::endl;
04368 out << " Vertical Align : " << verticalAlignmentAsString() << std::endl;
04369 out << " Text Wrap : " << ( textWrap() ? "yes" : "no" ) << std::endl;
04370 out << " Rotation : " << rotationAngle() << std::endl;
04371 out << " Stacked Letters : " << ( stackedLetters() ? "yes" : "no" ) << std::endl;
04372 out << " Indent Level : " << indentLevel() << std::endl;
04373 out << " Shrink To Fit : " << ( shrinkContent() ? "yes" : "no" ) << std::endl;
04374 out << " Left Border : Style " << leftBorderStyle();
04375 out << " Color: " << leftBorderColor() << std::endl;
04376 out << " Right Border : Style " << rightBorderStyle();
04377 out << " Color: " << rightBorderColor() << std::endl;
04378 out << " Top Border : Style " << topBorderStyle();
04379 out << " Color: " << topBorderColor() << std::endl;
04380 out << " Bottom Border : Style " << bottomBorderStyle();
04381 out << " Color: " << bottomBorderColor() << std::endl;
04382 out << " Diagonal Lines : " ;
04383 if ( diagonalTopLeft() ) out << "TopLeft ";
04384 if ( diagonalBottomLeft() ) out << "BottomLeft ";
04385 out << "Style " << diagonalStyle() << " Color: " << diagonalColor() << std::endl;
04386 out << " Fill Pattern : " << fillPattern() << std::endl;
04387 out << " Fill Color : Fore " << patternForeColor() << " Back: "
04388 << patternBackColor() << std::endl;
04389 }
04390
04391
04392
04393
04394
04395 class ExcelReader::Private
04396 {
04397 public:
04398
04399
04400 Workbook* workbook;
04401
04402
04403
04404 bool passwordProtected;
04405
04406
04407 Sheet* activeSheet;
04408
04409
04410 Cell* formulaCell;
04411
04412
04413 std::map<unsigned,Sheet*> bofMap;
04414
04415
04416 std::vector<UString> stringTable;
04417
04418
04419 std::map<unsigned,FormatRecord> formatTable;
04420 std::map<unsigned,UString> formatsTable;
04421
04422
04423 std::vector<FontRecord> fontTable;
04424
04425
04426 std::vector<XFRecord> xfTable;
04427
04428
04429 std::vector<Color> colorTable;
04430
04431
04432 std::map<unsigned,FormatFont> fontCache;
04433
04434
04435 std::vector<UString> nameTable;
04436 };
04437
04438 ExcelReader::ExcelReader()
04439 {
04440 d = new ExcelReader::Private();
04441
04442 d->workbook = 0;
04443 d->activeSheet = 0;
04444 d->formulaCell = 0;
04445
04446 d->passwordProtected = false;
04447
04448
04449 static const char *const default_palette[64-8] =
04450 {
04451 "#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff",
04452 "#00ffff", "#800000", "#008000", "#000080", "#808000", "#800080", "#008080",
04453 "#c0c0c0", "#808080", "#9999ff", "#993366", "#ffffcc", "#ccffff", "#660066",
04454 "#ff8080", "#0066cc", "#ccccff", "#000080", "#ff00ff", "#ffff00", "#00ffff",
04455 "#800080", "#800000", "#008080", "#0000ff", "#00ccff", "#ccffff", "#ccffcc",
04456 "#ffff99", "#99ccff", "#ff99cc", "#cc99ff", "#ffcc99", "#3366ff", "#33cccc",
04457 "#99cc00", "#ffcc00", "#ff9900", "#ff6600", "#666699", "#969696", "#003366",
04458 "#339966", "#003300", "#333300", "#993300", "#993366", "#333399", "#333333",
04459 };
04460 for( int i = 0; i < 64-8; i++ ) {
04461 d->colorTable.push_back(Color(default_palette[i]));
04462 }
04463 }
04464
04465 ExcelReader::~ExcelReader()
04466 {
04467 delete d;
04468 }
04469
04470 bool ExcelReader::load( Workbook* workbook, const char* filename )
04471 {
04472 POLE::Storage storage( filename );
04473 if( !storage.open() )
04474 {
04475 std::cerr << "Cannot open " << filename << std::endl;
04476 return false;
04477 }
04478
04479 unsigned version = Swinder::Excel97;
04480 POLE::Stream* stream;
04481 stream = new POLE::Stream( &storage, "/Workbook" );
04482 if( stream->fail() )
04483 {
04484 delete stream;
04485 stream = new POLE::Stream( &storage, "/Book" );
04486 version = Swinder::Excel95;
04487 }
04488
04489 if( stream->fail() )
04490 {
04491 std::cerr << filename << " is not Excel workbook" << std::endl;
04492 delete stream;
04493 return false;
04494 }
04495
04496 unsigned long stream_size = stream->size();
04497
04498 unsigned int buffer_size = 65536;
04499 unsigned char *buffer = (unsigned char *) malloc(buffer_size);
04500 unsigned char small_buffer[128];
04501
04502 workbook->clear();
04503 d->workbook = workbook;
04504
04505 d->passwordProtected = false;
04506
04507
04508
04509 while( stream->tell() < stream_size )
04510 {
04511
04512
04513
04514
04515 if(d->passwordProtected)
04516 {
04517 d->workbook->setPasswordProtected( true );
04518 break;
04519 }
04520
04521
04522 unsigned long pos = stream->tell();
04523 unsigned bytes_read = stream->read( buffer, 4 );
04524 if( bytes_read != 4 ) break;
04525
04526 unsigned long type = readU16( buffer );
04527 unsigned long size = readU16( buffer + 2 );
04528
04529
04530 if (size > buffer_size) {
04531 buffer = (unsigned char *) realloc(buffer, size);
04532 buffer_size = size;
04533 }
04534
04535
04536 bytes_read = stream->read( buffer, size );
04537 if( bytes_read != size ) break;
04538
04539
04540 unsigned long saved_pos;
04541
04542 unsigned long next_type;
04543 do {
04544 saved_pos = stream->tell();
04545
04546 bytes_read = stream->read( small_buffer, 4 );
04547 if (bytes_read != 4) break;
04548
04549 next_type = readU16( small_buffer );
04550 unsigned long next_size = readU16( small_buffer + 2 );
04551
04552 if (next_type == 0x3C) {
04553
04554
04555
04556 if ( (size + next_size) > buffer_size) {
04557 buffer = (unsigned char *) realloc(buffer, size + next_size);
04558 buffer_size = size + next_size;
04559 }
04560
04561
04562 bytes_read = stream->read( buffer + size, next_size );
04563 if (bytes_read != next_size) {
04564 std::cout << "ERROR!" << std::endl;
04565 break;
04566 }
04567
04568
04569 if (buffer[size] == 0) {
04570 memmove( buffer + size, buffer + size + 1, --next_size );
04571 }
04572
04573
04574 size += next_size;
04575 }
04576 } while (next_type == 0x3C);
04577
04578
04579 stream->seek( saved_pos );
04580
04581
04582 if( type == 0 ) continue;
04583
04584
04585 Record* record = Record::create( type );
04586
04587 if( record )
04588 {
04589
04590 record->setVersion( version );
04591 record->setData( size, buffer );
04592 record->setPosition( pos );
04593
04594 handleRecord( record );
04595
04596
04597 if ( record->rtti() == BOFRecord::id )
04598 {
04599 BOFRecord* bof = static_cast<BOFRecord*>(record);
04600 if( bof ) if( bof->type() == BOFRecord::Workbook )
04601 version = bof->version();
04602 }
04603
04604 #ifdef SWINDER_XLS2RAW
04605 std::cout << "Record 0x";
04606 std::cout << std::setfill('0') << std::setw(4) << std::hex << record->rtti();
04607 std::cout << " ";
04608 std::cout << std::dec;
04609 record->dump( std::cout );
04610 std::cout << std::endl;
04611 #endif
04612
04613 delete record;
04614 }
04615
04616 #ifdef SWINDER_XLS2RAW
04617 if( !record )
04618 {
04619 std::cout << "Record 0x";
04620 std::cout << std::setfill('0') << std::setw(4) << std::hex << type;
04621 std::cout << std::dec;
04622 std::cout << std::endl;
04623 std::cout << std::endl;
04624 }
04625 #endif
04626
04627 }
04628
04629 free(buffer);
04630
04631 delete stream;
04632
04633 storage.close();
04634
04635 return true;
04636 }
04637
04638 void ExcelReader::handleRecord( Record* record )
04639 {
04640 if( !record ) return;
04641
04642 unsigned type = record->rtti();
04643 switch( type )
04644 {
04645 case BottomMarginRecord::id:
04646 handleBottomMargin( static_cast<BottomMarginRecord*>( record ) ); break;
04647 case BoundSheetRecord::id:
04648 handleBoundSheet( static_cast<BoundSheetRecord*>( record ) ); break;
04649 case BOFRecord::id:
04650 handleBOF( static_cast<BOFRecord*>( record ) ); break;
04651 case BoolErrRecord::id:
04652 handleBoolErr( static_cast<BoolErrRecord*>( record ) ); break;
04653 case BlankRecord::id:
04654 handleBlank( static_cast<BlankRecord*>( record ) ); break;
04655 case CalcModeRecord::id:
04656 handleCalcMode( static_cast<CalcModeRecord*>( record ) ); break;
04657 case ColInfoRecord::id:
04658 handleColInfo( static_cast<ColInfoRecord*>( record ) ); break;
04659 case ExternNameRecord::id:
04660 handleExternName( static_cast<ExternNameRecord*>( record ) ); break;
04661 case FilepassRecord::id:
04662 handleFilepass( static_cast<FilepassRecord*>( record ) ); break;
04663 case FormatRecord::id:
04664 handleFormat( static_cast<FormatRecord*>( record ) ); break;
04665 case FormulaRecord::id:
04666 handleFormula( static_cast<FormulaRecord*>( record ) ); break;
04667 case FontRecord::id:
04668 handleFont( static_cast<FontRecord*>( record ) ); break;
04669 case FooterRecord::id:
04670 handleFooter( static_cast<FooterRecord*>( record ) ); break;
04671 case HeaderRecord::id:
04672 handleHeader( static_cast<HeaderRecord*>( record ) ); break;
04673 case LabelRecord::id:
04674 handleLabel( static_cast<LabelRecord*>( record ) ); break;
04675 case LabelSSTRecord::id:
04676 handleLabelSST( static_cast<LabelSSTRecord*>( record ) ); break;
04677 case LeftMarginRecord::id:
04678 handleLeftMargin( static_cast<LeftMarginRecord*>( record ) ); break;
04679 case MergedCellsRecord::id:
04680 handleMergedCells( static_cast<MergedCellsRecord*>( record ) ); break;
04681 case MulBlankRecord::id:
04682 handleMulBlank( static_cast<MulBlankRecord*>( record ) ); break;
04683 case MulRKRecord::id:
04684 handleMulRK( static_cast<MulRKRecord*>( record ) ); break;
04685 case NameRecord::id:
04686 handleName( static_cast<NameRecord*>( record ) ); break;
04687 case NumberRecord::id:
04688 handleNumber( static_cast<NumberRecord*>( record ) ); break;
04689 case PaletteRecord::id:
04690 handlePalette( static_cast<PaletteRecord*>( record ) ); break;
04691 case RightMarginRecord::id:
04692 handleRightMargin( static_cast<RightMarginRecord*>( record ) ); break;
04693 case RKRecord::id:
04694 handleRK( static_cast<RKRecord*>( record ) ); break;
04695 case RowRecord::id:
04696 handleRow( static_cast<RowRecord*>( record ) ); break;
04697 case RStringRecord::id:
04698 handleRString( static_cast<RStringRecord*>( record ) ); break;
04699 case SSTRecord::id:
04700 handleSST( static_cast<SSTRecord*>( record ) ); break;
04701 case StringRecord::id:
04702 handleString( static_cast<StringRecord*>( record ) ); break;
04703 case TopMarginRecord::id:
04704 handleTopMargin( static_cast<TopMarginRecord*>( record ) ); break;
04705 case XFRecord::id:
04706 handleXF( static_cast<XFRecord*>( record ) ); break;
04707 default:
04708 break;
04709 }
04710 }
04711
04712 void ExcelReader::handleBottomMargin( BottomMarginRecord* record )
04713 {
04714 if( !record ) return;
04715
04716 if( !d->activeSheet ) return;
04717
04718
04719 double margin = record->bottomMargin() * 72.0;
04720 d->activeSheet->setBottomMargin( margin );
04721 }
04722
04723
04724
04725 void ExcelReader::handleBoundSheet( BoundSheetRecord* record )
04726 {
04727 if( !record ) return;
04728
04729
04730 if( record->type() == BoundSheetRecord::Worksheet )
04731 {
04732
04733 Sheet* sheet = new Sheet( d->workbook );
04734 sheet->setName( record->sheetName() );
04735 sheet->setVisible( record->visible() );
04736
04737 d->workbook->appendSheet( sheet );
04738
04739
04740 unsigned bofPos = record->bofPosition();
04741 d->bofMap[ bofPos ] = sheet;
04742 }
04743 }
04744
04745 void ExcelReader::handleBOF( BOFRecord* record )
04746 {
04747 if( !record ) return;
04748
04749 if( record->type() == BOFRecord::Worksheet )
04750 {
04751
04752
04753 Sheet* sheet = d->bofMap[ record->position() ];
04754 if( sheet ) d->activeSheet = sheet;
04755 }
04756 }
04757
04758 void ExcelReader::handleBoolErr( BoolErrRecord* record )
04759 {
04760 if( !record ) return;
04761
04762 if( !d->activeSheet ) return;
04763
04764 unsigned column = record->column();
04765 unsigned row = record->row();
04766 unsigned xfIndex = record->xfIndex();
04767
04768 Cell* cell = d->activeSheet->cell( column, row, true );
04769 if( cell )
04770 {
04771 cell->setValue( record->value() );
04772 cell->setFormat( convertFormat( xfIndex ) );
04773 }
04774 }
04775
04776 void ExcelReader::handleBlank( BlankRecord* record )
04777 {
04778 if( !record ) return;
04779
04780 if( !d->activeSheet ) return;
04781
04782 unsigned column = record->column();
04783 unsigned row = record->row();
04784 unsigned xfIndex = record->xfIndex();
04785
04786 Cell* cell = d->activeSheet->cell( column, row, true );
04787 if( cell )
04788 {
04789 cell->setFormat( convertFormat( xfIndex ) );
04790 }
04791 }
04792
04793 void ExcelReader::handleCalcMode( CalcModeRecord* record )
04794 {
04795 if( !record ) return;
04796
04797 d->workbook->setAutoCalc( record->autoCalc() );
04798 }
04799
04800 void ExcelReader::handleColInfo( ColInfoRecord* record )
04801 {
04802 if( !record ) return;
04803
04804 if( !d->activeSheet ) return;
04805
04806 unsigned firstColumn = record->firstColumn();
04807 unsigned lastColumn = record->lastColumn();
04808 unsigned xfIndex = record->xfIndex();
04809 unsigned width = record->width();
04810 bool hidden = record->hidden();
04811
04812 for( unsigned i = firstColumn; i <= lastColumn; i++ )
04813 {
04814 Column* column = d->activeSheet->column( i, true );
04815 if( column )
04816 {
04817 column->setWidth( width / 120 );
04818 column->setFormat( convertFormat( xfIndex ) );
04819 column->setVisible( !hidden );
04820 }
04821 }
04822 }
04823
04824 void ExcelReader::handleDateMode( DateModeRecord* record )
04825 {
04826 if( !record ) return;
04827
04828
04829 std::cerr << "WARNING: Workbook uses unsupported 1904 Date System " << std::endl;
04830 }
04831
04832 void ExcelReader::handleDimension( DimensionRecord* record )
04833 {
04834 if( !record ) return;
04835
04836
04837
04838 }
04839
04840 void ExcelReader::handleLabel( LabelRecord* record )
04841 {
04842 if( !record ) return;
04843
04844 if( !d->activeSheet ) return;
04845
04846 unsigned column = record->column();
04847 unsigned row = record->row();
04848 unsigned xfIndex = record->xfIndex();
04849 UString label = record->label();
04850
04851 Cell* cell = d->activeSheet->cell( column, row, true );
04852 if( cell )
04853 {
04854 cell->setValue( Value( label ) );
04855 cell->setFormat( convertFormat( xfIndex ) );
04856 }
04857 }
04858
04859 void ExcelReader::handleLeftMargin( LeftMarginRecord* record )
04860 {
04861 if( !record ) return;
04862
04863 if( !d->activeSheet ) return;
04864
04865
04866 double margin = record->leftMargin() * 72.0;
04867 d->activeSheet->setLeftMargin( margin );
04868 }
04869
04870 void ExcelReader::handleFormat( FormatRecord* record )
04871 {
04872 if( !record ) return;
04873
04874 d->formatTable[ record->index() ] = *record;
04875 d->formatsTable[ record->index() ] = record->formatString();
04876 }
04877
04878 void ExcelReader::handleFormula( FormulaRecord* record )
04879 {
04880 if( !record ) return;
04881
04882 if( !d->activeSheet ) return;
04883
04884 unsigned column = record->column();
04885 unsigned row = record->row();
04886 unsigned xfIndex = record->xfIndex();
04887 Value value = record->result();
04888
04889 UString formula = decodeFormula( row, column, record->tokens() );
04890
04891 Cell* cell = d->activeSheet->cell( column, row, true );
04892 if( cell )
04893 {
04894 cell->setValue( value );
04895 if( !formula.isEmpty() )
04896 cell->setFormula( formula );
04897 cell->setFormat( convertFormat( xfIndex ) );
04898
04899
04900 if( value.isString() )
04901 d->formulaCell = cell;
04902 }
04903 }
04904
04905 void ExcelReader::handleExternName( ExternNameRecord* record )
04906 {
04907 if( !record ) return;
04908
04909 d->nameTable.push_back( record->externName() );
04910 }
04911
04912 void ExcelReader::handleFilepass( FilepassRecord* record )
04913 {
04914 if( !record ) return;
04915
04916 d->passwordProtected = true;
04917 }
04918
04919 void ExcelReader::handleFont( FontRecord* record )
04920 {
04921 if( !record ) return;
04922
04923 d->fontTable.push_back( *record );
04924
04925
04926 if( d->fontTable.size() == 4 )
04927 d->fontTable.push_back( FontRecord() );
04928 }
04929
04930 void ExcelReader::handleFooter( FooterRecord* record )
04931 {
04932 if( !record ) return;
04933
04934 if( !d->activeSheet ) return;
04935
04936 UString footer = record->footer();
04937 UString left, center, right;
04938 int pos = -1, len = 0;
04939
04940
04941 pos = footer.find( UString("&L") );
04942 if( pos >= 0 )
04943 {
04944 pos += 2;
04945 len = footer.find( UString("&C") ) - pos;
04946 if( len > 0 )
04947 {
04948 left = footer.substr( pos, len );
04949 footer = footer.substr( pos+len, footer.length() );
04950 }
04951 }
04952
04953
04954 pos = footer.find( UString("&C") );
04955 if( pos >= 0 )
04956 {
04957 pos += 2;
04958 len = footer.find( UString("&R") ) - pos;
04959 if( len > 0 )
04960 {
04961 center = footer.substr( pos, len );
04962 footer = footer.substr( pos+len, footer.length() );
04963 }
04964 }
04965
04966
04967 pos = footer.find( UString("&R") );
04968 if( pos >= 0 )
04969 {
04970 pos += 2;
04971 right = footer.substr( pos, footer.length() - pos );
04972 }
04973
04974 d->activeSheet->setLeftFooter( left );
04975 d->activeSheet->setCenterFooter( center );
04976 d->activeSheet->setRightFooter( right );
04977 }
04978
04979 void ExcelReader::handleHeader( HeaderRecord* record )
04980 {
04981 if( !record ) return;
04982
04983 if( !d->activeSheet ) return;
04984
04985 UString header = record->header();
04986 UString left, center, right;
04987 int pos = -1, len = 0;
04988
04989
04990 pos = header.find( UString("&L") );
04991 if( pos >= 0 )
04992 {
04993 pos += 2;
04994 len = header.find( UString("&C") ) - pos;
04995 if( len > 0 )
04996 {
04997 left = header.substr( pos, len );
04998 header = header.substr( pos+len, header.length() );
04999 }
05000 }
05001
05002
05003 pos = header.find( UString("&C") );
05004 if( pos >= 0 )
05005 {
05006 pos += 2;
05007 len = header.find( UString("&R") ) - pos;
05008 if( len > 0 )
05009 {
05010 center = header.substr( pos, len );
05011 header = header.substr( pos+len, header.length() );
05012 }
05013 }
05014
05015
05016 pos = header.find( UString("&R") );
05017 if( pos >= 0 )
05018 {
05019 pos += 2;
05020 right = header.substr( pos, header.length() - pos );
05021 }
05022
05023 d->activeSheet->setLeftHeader( left );
05024 d->activeSheet->setCenterHeader( center );
05025 d->activeSheet->setRightHeader( right );
05026 }
05027
05028 void ExcelReader::handleLabelSST( LabelSSTRecord* record )
05029 {
05030 if( !record ) return;
05031
05032 if( !d->activeSheet ) return;
05033
05034 unsigned column = record->column();
05035 unsigned row = record->row();
05036 unsigned index = record->sstIndex();
05037 unsigned xfIndex = record->xfIndex();
05038
05039 UString str;
05040 if( index < d->stringTable.size() )
05041 str = d->stringTable[ index ];
05042
05043 Cell* cell = d->activeSheet->cell( column, row, true );
05044 if( cell )
05045 {
05046 cell->setValue( Value( str ) );
05047 cell->setFormat( convertFormat( xfIndex) );
05048 }
05049 }
05050
05051 void ExcelReader::handleMergedCells( MergedCellsRecord* record )
05052 {
05053 if( !record ) return;
05054
05055 if( !d->activeSheet ) return;
05056
05057 for( unsigned i = 0; i < record->count(); i++ )
05058 {
05059 unsigned firstRow = record->firstRow( i );
05060 unsigned lastRow = record->lastRow( i );
05061 unsigned firstColumn = record->firstColumn( i );
05062 unsigned lastColumn = record->lastColumn( i );
05063
05064 Cell* cell = d->activeSheet->cell( firstColumn, firstRow, true );
05065 if( cell )
05066 {
05067 cell->setColumnSpan( lastColumn - firstColumn + 1 );
05068 cell->setRowSpan( lastRow - firstRow + 1 );
05069 }
05070 }
05071 }
05072
05073 void ExcelReader::handleMulBlank( MulBlankRecord* record )
05074 {
05075 if( !record ) return;
05076
05077 if( !d->activeSheet ) return;
05078
05079 unsigned firstColumn = record->firstColumn();
05080 unsigned lastColumn = record->lastColumn();
05081 unsigned row = record->row();
05082
05083 for( unsigned column = firstColumn; column <= lastColumn; column++ )
05084 {
05085 Cell* cell = d->activeSheet->cell( column, row, true );
05086 if( cell )
05087 {
05088 cell->setFormat( convertFormat( record->xfIndex( column - firstColumn ) ) );
05089 }
05090 }
05091 }
05092
05093 void ExcelReader::handleMulRK( MulRKRecord* record )
05094 {
05095 if( !record ) return;
05096
05097 if( !d->activeSheet ) return;
05098
05099 unsigned firstColumn = record->firstColumn();
05100 unsigned lastColumn = record->lastColumn();
05101 unsigned row = record->row();
05102
05103 for( unsigned column = firstColumn; column <= lastColumn; column++ )
05104 {
05105 Cell* cell = d->activeSheet->cell( column, row, true );
05106 if( cell )
05107 {
05108 unsigned i = column - firstColumn;
05109 Value value;
05110 if( record->isInteger( i ) )
05111 value.setValue( record->asInteger( i ) );
05112 else
05113 value.setValue( record->asFloat( i ) );
05114 cell->setValue( value );
05115 cell->setFormat( convertFormat( record->xfIndex( column-firstColumn ) ) );
05116 }
05117 }
05118 }
05119
05120 void ExcelReader::handleName( NameRecord* record )
05121 {
05122 if( !record ) return;
05123
05124 d->nameTable.push_back( record->definedName() );
05125 }
05126
05127 void ExcelReader::handleNumber( NumberRecord* record )
05128 {
05129 if( !record ) return;
05130
05131 if( !d->activeSheet ) return;
05132
05133 unsigned column = record->column();
05134 unsigned row = record->row();
05135 unsigned xfIndex = record->xfIndex();
05136 double number = record->number();
05137
05138 Cell* cell = d->activeSheet->cell( column, row, true );
05139 if( cell )
05140 {
05141 cell->setValue( Value( number ) );
05142 cell->setFormat( convertFormat( xfIndex) );
05143 }
05144 }
05145
05146 void ExcelReader::handlePalette( PaletteRecord* record )
05147 {
05148 if( !record ) return;
05149
05150 d->colorTable.clear();
05151 for( unsigned i = 0; i < record->count(); i++ )
05152 d->colorTable.push_back( record->color( i ) );
05153 }
05154
05155 void ExcelReader::handleRightMargin( RightMarginRecord* record )
05156 {
05157 if( !record ) return;
05158
05159 if( !d->activeSheet ) return;
05160
05161
05162 double margin = record->rightMargin() * 72.0;
05163 d->activeSheet->setRightMargin( margin );
05164 }
05165
05166 void ExcelReader::handleRK( RKRecord* record )
05167 {
05168 if( !record ) return;
05169
05170 if( !d->activeSheet ) return;
05171
05172 unsigned column = record->column();
05173 unsigned row = record->row();
05174 unsigned xfIndex = record->xfIndex();
05175
05176 Value value;
05177 if( record->isInteger() )
05178 value.setValue( record->asInteger() );
05179 else
05180 value.setValue( record->asFloat() );
05181
05182 Cell* cell = d->activeSheet->cell( column, row, true );
05183 if( cell )
05184 {
05185 cell->setValue( value );
05186 cell->setFormat( convertFormat( xfIndex) );
05187 }
05188 }
05189
05190 void ExcelReader::handleRow( RowRecord* record )
05191 {
05192 if( !record ) return;
05193
05194 if( !d->activeSheet ) return;
05195
05196 unsigned index = record->row();
05197 unsigned xfIndex = record->xfIndex();
05198 unsigned height = record->height();
05199 bool hidden = record->hidden();
05200
05201 Row* row = d->activeSheet->row( index, true );
05202 if( row )
05203 {
05204 row->setHeight( height / 20.0 );
05205 row->setFormat( convertFormat( xfIndex ) );
05206 row->setVisible( !hidden );
05207 }
05208 }
05209
05210 void ExcelReader::handleRString( RStringRecord* record )
05211 {
05212 if( !record ) return;
05213
05214 if( !d->activeSheet ) return;
05215
05216 unsigned column = record->column();
05217 unsigned row = record->row();
05218 unsigned xfIndex = record->xfIndex();
05219 UString label = record->label();
05220
05221 Cell* cell = d->activeSheet->cell( column, row, true );
05222 if( cell )
05223 {
05224 cell->setValue( Value( label ) );
05225 cell->setFormat( convertFormat( xfIndex) );
05226 }
05227 }
05228
05229 void ExcelReader::handleSST( SSTRecord* record )
05230 {
05231 if( !record ) return;
05232
05233 d->stringTable.clear();
05234 for( unsigned i = 0; i < record->count();i++ )
05235 {
05236 UString str = record->stringAt( i );
05237 d->stringTable.push_back( str );
05238 }
05239 }
05240
05241 void ExcelReader::handleString( StringRecord* record )
05242 {
05243 if( !record ) return;
05244
05245 if( !d->activeSheet ) return;
05246 if( !d->formulaCell ) return;
05247
05248 d->formulaCell->setValue( record->value() );
05249
05250 d->formulaCell = 0;
05251 }
05252
05253 void ExcelReader::handleTopMargin( TopMarginRecord* record )
05254 {
05255 if( !record ) return;
05256
05257 if( !d->activeSheet ) return;
05258
05259
05260
05261 double margin = record->topMargin() * 72.0;
05262 d->activeSheet->setTopMargin( margin );
05263 }
05264
05265 FormatFont ExcelReader::convertFont( unsigned fontIndex )
05266 {
05267
05268 FormatFont font = d->fontCache[ fontIndex ];
05269 if( font.isNull() && ( fontIndex < d->fontTable.size() ))
05270 {
05271 FontRecord fr = d->fontTable[ fontIndex ];
05272 font.setFontSize( fr.height() / 20.0 );
05273 font.setFontFamily( fr.fontName() );
05274 font.setColor( convertColor( fr.colorIndex() ) );
05275 font.setBold( fr.boldness() > 500 );
05276 font.setItalic( fr.italic() );
05277 font.setStrikeout( fr.strikeout() );
05278 font.setSubscript( fr.escapement() == FontRecord::Subscript );
05279 font.setSuperscript( fr.escapement() == FontRecord::Superscript );
05280 font.setUnderline( fr.underline() != FontRecord::None );
05281
05282
05283 d->fontCache[ fontIndex ] = font;
05284 }
05285
05286 return font;
05287 }
05288
05289 Color ExcelReader::convertColor( unsigned colorIndex )
05290 {
05291 if( ( colorIndex >= 8 ) && ( colorIndex < 0x40 ) )
05292 if( colorIndex-8 < d->colorTable.size() )
05293 return d->colorTable[ colorIndex-8 ];
05294
05295
05296
05297
05298
05299 if( colorIndex == 0x40 ) return Color( 0, 0, 0 );
05300 if( colorIndex == 0x41 ) return Color( 255, 255, 255 );
05301 if( colorIndex == 0x7fff ) return Color( 0, 0, 0 );
05302
05303
05304 Color color;
05305
05306
05307
05308 switch( colorIndex )
05309 {
05310 case 0: color = Color( 0, 0, 0 ); break;
05311 case 1: color = Color( 255, 255, 255 ); break;
05312 case 2: color = Color( 255, 0, 0 ); break;
05313 case 3: color = Color( 0, 255, 0 ); break;
05314 case 4: color = Color( 0, 0, 255 ); break;
05315 case 5: color = Color( 255, 255, 0 ); break;
05316 case 6: color = Color( 255, 0, 255 ); break;
05317 case 7: color = Color( 0, 255, 255 ); break;
05318 default: break;
05319 }
05320
05321 return color;
05322 }
05323
05324
05325 static Pen convertBorderStyle( unsigned style )
05326 {
05327 Pen pen;
05328 switch( style )
05329 {
05330 case XFRecord::NoLine:
05331 pen.width = 0;
05332 pen.style = Pen::NoLine;
05333 break;
05334 case XFRecord::Thin:
05335 pen.width = 1;
05336 pen.style = Pen::SolidLine;
05337 break;
05338 case XFRecord::Medium:
05339 pen.width = 3;
05340 pen.style = Pen::SolidLine;
05341 break;
05342 case XFRecord::Dashed:
05343 pen.width = 1;
05344 pen.style = Pen::DashLine;
05345 break;
05346 case XFRecord::Dotted:
05347 pen.width = 1;
05348 pen.style = Pen::DotLine;
05349 break;
05350 case XFRecord::Thick:
05351 pen.width = 4;
05352 pen.style = Pen::SolidLine;
05353 break;
05354 case XFRecord::Double:
05355
05356 pen.width = 4;
05357 pen.style = Pen::SolidLine;
05358 break;
05359 case XFRecord::Hair:
05360
05361 pen.width = 1;
05362 pen.style = Pen::DotLine;
05363 break;
05364 case XFRecord::MediumDashed:
05365 pen.width = 3;
05366 pen.style = Pen::DashLine;
05367 break;
05368 case XFRecord::ThinDashDotted:
05369 pen.width = 1;
05370 pen.style = Pen::DashDotLine;
05371 break;
05372 case XFRecord::MediumDashDotted:
05373 pen.width = 3;
05374 pen.style = Pen::DashDotLine;
05375 break;
05376 case XFRecord::ThinDashDotDotted:
05377 pen.width = 1;
05378 pen.style = Pen::DashDotDotLine;
05379 break;
05380 case XFRecord::MediumDashDotDotted:
05381 pen.width = 3;
05382 pen.style = Pen::DashDotDotLine;
05383 break;
05384 case XFRecord::SlantedMediumDashDotted:
05385
05386 pen.width = 3;
05387 pen.style = Pen::DashDotLine;
05388 break;
05389 default:
05390
05391 pen.width = 1;
05392 pen.style = Pen::SolidLine;
05393 break;
05394 };
05395
05396 return pen;
05397 }
05398
05399 unsigned convertPatternStyle( unsigned pattern )
05400 {
05401 switch ( pattern )
05402 {
05403 case 0x00: return FormatBackground::EmptyPattern;
05404 case 0x01: return FormatBackground::SolidPattern;
05405 case 0x02: return FormatBackground::Dense4Pattern;
05406 case 0x03: return FormatBackground::Dense3Pattern;
05407 case 0x04: return FormatBackground::Dense5Pattern;
05408 case 0x05: return FormatBackground::HorPattern;
05409 case 0x06: return FormatBackground::VerPattern;
05410 case 0x07: return FormatBackground::FDiagPattern;
05411 case 0x08: return FormatBackground::BDiagPattern;
05412 case 0x09: return FormatBackground::Dense1Pattern;
05413 case 0x0A: return FormatBackground::Dense2Pattern;
05414 case 0x0B: return FormatBackground::HorPattern;
05415 case 0x0C: return FormatBackground::VerPattern;
05416 case 0x0D: return FormatBackground::FDiagPattern;
05417 case 0x0E: return FormatBackground::BDiagPattern;
05418 case 0x0F: return FormatBackground::CrossPattern;
05419 case 0x10: return FormatBackground::DiagCrossPattern;
05420 case 0x11: return FormatBackground::Dense6Pattern;
05421 case 0x12: return FormatBackground::Dense7Pattern;
05422 default: return FormatBackground::SolidPattern;
05423 }
05424 }
05425
05426
05427 Format ExcelReader::convertFormat( unsigned xfIndex )
05428 {
05429 Format format;
05430
05431 if( xfIndex >= d->xfTable.size() ) return format;
05432
05433 XFRecord xf = d->xfTable[ xfIndex ];
05434
05435 UString valueFormat = d->formatsTable[xf.formatIndex()];
05436 if( valueFormat.isEmpty() )
05437 switch( xf.formatIndex() )
05438 {
05439 case 0: valueFormat = "General"; break;
05440 case 1: valueFormat = "0"; break;
05441 case 2: valueFormat = "0.00"; break;
05442 case 3: valueFormat = "#,##0"; break;
05443 case 4: valueFormat = "#,##0.00"; break;
05444 case 5: valueFormat = "\"$\"#,##0_);(\"S\"#,##0)"; break;
05445 case 6: valueFormat = "\"$\"#,##0_);[Red](\"S\"#,##0)"; break;
05446 case 7: valueFormat = "\"$\"#,##0.00_);(\"S\"#,##0.00)"; break;
05447 case 8: valueFormat = "\"$\"#,##0.00_);[Red](\"S\"#,##0.00)"; break;
05448 case 9: valueFormat = "0%"; break;
05449 case 10: valueFormat = "0.00%"; break;
05450 case 11: valueFormat = "0.00E+00"; break;
05451 case 12: valueFormat = "#?/?"; break;
05452 case 13: valueFormat = "#\?\?/\?\?"; break;
05453 case 14: valueFormat = "M/D/YY"; break;
05454 case 15: valueFormat = "D-MMM-YY"; break;
05455 case 16: valueFormat = "D-MMM"; break;
05456 case 17: valueFormat = "MMM-YY"; break;
05457 case 18: valueFormat = "h:mm AM/PM"; break;
05458 case 19: valueFormat = "h:mm:ss AM/PM"; break;
05459 case 20: valueFormat = "h:mm"; break;
05460 case 21: valueFormat = "h:mm:ss"; break;
05461 case 22: valueFormat = "M/D/YY h:mm"; break;
05462 case 37: valueFormat = "_(#,##0_);(#,##0)"; break;
05463 case 38: valueFormat = "_(#,##0_);[Red](#,##0)"; break;
05464 case 39: valueFormat = "_(#,##0.00_);(#,##0)"; break;
05465 case 40: valueFormat = "_(#,##0.00_);[Red](#,##0)"; break;
05466 case 41: valueFormat = "_(\"$\"*#,##0_);_(\"$\"*#,##0_);_(\"$\"*\"-\");(@_)"; break;
05467 case 42: valueFormat = "_(*#,##0_);(*(#,##0);_(*\"-\");_(@_)"; break;
05468 case 43: valueFormat = "_(\"$\"*#,##0.00_);_(\"$\"*#,##0.00_);_(\"$\"*\"-\");(@_)"; break;
05469 case 44: valueFormat = "_(\"$\"*#,##0.00_);_(\"$\"*#,##0.00_);_(\"$\"*\"-\");(@_)"; break;
05470 case 45: valueFormat = "mm:ss"; break;
05471 case 46: valueFormat = "[h]:mm:ss"; break;
05472 case 47: valueFormat = "mm:ss.0"; break;
05473 case 48: valueFormat = "##0.0E+0"; break;
05474 case 49: valueFormat = "@"; break;
05475 default: valueFormat = "General"; break;
05476 };
05477 format.setValueFormat( valueFormat );
05478
05479 format.setFont( convertFont( xf.fontIndex() ) );
05480
05481 FormatAlignment alignment;
05482 switch( xf.horizontalAlignment() )
05483 {
05484 case XFRecord::Left:
05485 alignment.setAlignX( Format::Left ); break;
05486 case XFRecord::Right:
05487 alignment.setAlignX( Format::Right ); break;
05488 case XFRecord::Centered:
05489 alignment.setAlignX( Format::Center ); break;
05490 default: break;
05491
05492 };
05493 switch( xf.verticalAlignment() )
05494 {
05495 case XFRecord::Top:
05496 alignment.setAlignY( Format::Top ); break;
05497 case XFRecord::VCentered:
05498 alignment.setAlignY( Format::Middle ); break;
05499 case XFRecord::Bottom:
05500 alignment.setAlignY( Format::Bottom ); break;
05501 default: break;
05502
05503 }
05504 alignment.setWrap( xf.textWrap() );
05505 format.setAlignment( alignment );
05506
05507 FormatBorders borders;
05508
05509 Pen pen;
05510 pen = convertBorderStyle( xf.leftBorderStyle() );
05511 pen.color = convertColor( xf.leftBorderColor() );
05512 borders.setLeftBorder( pen );
05513
05514 pen = convertBorderStyle( xf.rightBorderStyle() );
05515 pen.color = convertColor( xf.rightBorderColor() );
05516 borders.setRightBorder( pen );
05517
05518 pen = convertBorderStyle( xf.topBorderStyle() );
05519 pen.color = convertColor( xf.topBorderColor() );
05520 borders.setTopBorder( pen );
05521
05522 pen = convertBorderStyle( xf.bottomBorderStyle() );
05523 pen.color = convertColor( xf.bottomBorderColor() );
05524 borders.setBottomBorder( pen );
05525
05526 format.setBorders( borders );
05527
05528 FormatBackground background;
05529 background.setForegroundColor( convertColor( xf.patternForeColor() ) );
05530 background.setBackgroundColor( convertColor( xf.patternBackColor() ) );
05531 background.setPattern( convertPatternStyle( xf.fillPattern() ) );
05532 format.setBackground( background );
05533
05534 return format;
05535 }
05536
05537 void ExcelReader::handleXF( XFRecord* record )
05538 {
05539 if( !record ) return;
05540
05541 d->xfTable.push_back( *record );
05542 }
05543
05544 typedef std::vector<UString> UStringStack;
05545
05546 void mergeTokens( UStringStack* stack, int count, UString mergeString )
05547 {
05548 if( !stack ) return;
05549 if( !stack->size() ) return;
05550
05551 UString s1, s2;
05552
05553 while(count)
05554 {
05555 count--;
05556
05557 UString last = (*stack)[ stack->size()-1 ];
05558 UString tmp = last;
05559 tmp.append( s1 );
05560 s1 = tmp;
05561
05562 if( count )
05563 {
05564 tmp = mergeString;
05565 tmp.append( s1 );
05566 s1 = tmp;
05567 }
05568
05569 stack->resize( stack->size()-1 );
05570 }
05571
05572 stack->push_back( s1 );
05573 }
05574
05575 #ifdef SWINDER_XLS2RAW
05576 void dumpStack( std::vector<UString> stack )
05577 {
05578 std::cout << std::endl;
05579 std::cout << "Stack now is: " ;
05580 if( !stack.size() )
05581 std::cout << "(empty)" ;
05582
05583 for( unsigned i = 0; i < stack.size(); i++ )
05584 std::cout << " " << i << ": " << stack[i].ascii() << std::endl;
05585 std::cout << std::endl;
05586 }
05587 #endif
05588
05589 UString ExcelReader::decodeFormula( unsigned row, unsigned col, const FormulaTokens& tokens )
05590 {
05591 UStringStack stack;
05592
05593 for( unsigned c=0; c < tokens.size(); c++ )
05594 {
05595 FormulaToken token = tokens[c];
05596
05597 #ifdef SWINDER_XLS2RAW
05598 std::cout << "Token " << c << ": ";
05599 std::cout << token.id() << " ";
05600 std::cout << token.idAsString() << std::endl;
05601 #endif
05602
05603 switch( token.id() )
05604 {
05605 case FormulaToken::Add:
05606 mergeTokens( &stack, 2, UString("+") );
05607 break;
05608
05609 case FormulaToken::Sub:
05610 mergeTokens( &stack, 2, UString("-") );
05611 break;
05612
05613 case FormulaToken::Mul:
05614 mergeTokens( &stack, 2, UString("*") );
05615 break;
05616
05617 case FormulaToken::Div:
05618 mergeTokens( &stack, 2, UString("/") );
05619 break;
05620
05621 case FormulaToken::Power:
05622 mergeTokens( &stack, 2, UString("^") );
05623 break;
05624
05625 case FormulaToken::Concat:
05626 mergeTokens( &stack, 2, UString("&") );
05627 break;
05628
05629 case FormulaToken::LT:
05630 mergeTokens( &stack, 2, UString("<") );
05631 break;
05632
05633 case FormulaToken::LE:
05634 mergeTokens( &stack, 2, UString("<=") );
05635 break;
05636
05637 case FormulaToken::EQ:
05638 mergeTokens( &stack, 2, UString("=") );
05639 break;
05640
05641 case FormulaToken::GE:
05642 mergeTokens( &stack, 2, UString(">=") );
05643 break;
05644
05645 case FormulaToken::GT:
05646 mergeTokens( &stack, 2, UString(">") );
05647 break;
05648
05649 case FormulaToken::NE:
05650 mergeTokens( &stack, 2, UString("<>") );
05651 break;
05652
05653 case FormulaToken::Intersect:
05654 mergeTokens( &stack, 2, UString(" ") );
05655 break;
05656
05657 case FormulaToken::List:
05658 mergeTokens( &stack, 2, UString(";") );
05659 break;
05660
05661 case FormulaToken::Range:
05662 mergeTokens( &stack, 2, UString(";") );
05663 break;
05664
05665 case FormulaToken::UPlus:
05666 {
05667 UString str( "+" );
05668 str.append( stack[ stack.size()-1 ] );
05669 stack[ stack.size()-1 ] = str;
05670 }
05671 break;
05672
05673 case FormulaToken::UMinus:
05674 {
05675 UString str( "-" );
05676 str.append( stack[ stack.size()-1 ] );
05677 stack[ stack.size()-1 ] = str;
05678 }
05679 break;
05680
05681 case FormulaToken::Percent:
05682 stack[ stack.size()-1 ].append( UString("%") );
05683 break;
05684
05685 case FormulaToken::Paren:
05686 {
05687 UString str( "(" );
05688 str.append( stack[ stack.size()-1 ] );
05689 str.append( UString(")") );
05690 stack[ stack.size()-1 ] = str;
05691 }
05692 break;
05693
05694 case FormulaToken::MissArg:
05695
05696 stack.push_back( UString(" ") );
05697 break;
05698
05699 case FormulaToken::String:
05700 {
05701 UString str( '\"' );
05702 str.append( token.value().asString() );
05703 str.append( UString( '\"' ) );
05704 stack.push_back( str );
05705 }
05706 break;
05707
05708 case FormulaToken::Bool:
05709 if( token.value().asBoolean() )
05710 stack.push_back( UString( "TRUE" ) );
05711 else
05712 stack.push_back( UString( "FALSE" ) );
05713 break;
05714
05715 case FormulaToken::Integer:
05716 stack.push_back( UString::from( token.value().asInteger() ) );
05717 break;
05718
05719 case FormulaToken::Float:
05720 stack.push_back( UString::from( token.value().asFloat() ) );
05721 break;
05722
05723 case FormulaToken::Array:
05724
05725 break;
05726
05727 case FormulaToken::Ref:
05728 stack.push_back( token.ref( row, col ) );
05729 break;
05730
05731 case FormulaToken::Area:
05732 stack.push_back( token.area( row, col ) );
05733 break;
05734
05735 case FormulaToken::Function:
05736 {
05737 mergeTokens( &stack, token.functionParams(), UString(";") );
05738 if( stack.size() )
05739 {
05740 UString str( token.functionName() ? token.functionName() : "??" );
05741 str.append( UString("(") );
05742 str.append( stack[ stack.size()-1 ] );
05743 str.append( UString(")") );
05744 stack[ stack.size()-1 ] = str;
05745 }
05746 }
05747 break;
05748
05749 case FormulaToken::FunctionVar:
05750 if( token.functionIndex() != 255 )
05751 {
05752 mergeTokens( &stack, token.functionParams(), UString(";") );
05753 if( stack.size() )
05754 {
05755 UString str;
05756 if( token.functionIndex() != 255 )
05757 str = token.functionName() ? token.functionName() : "??";
05758 str.append( UString("(") );
05759 str.append( stack[ stack.size()-1 ] );
05760 str.append( UString(")") );
05761 stack[ stack.size()-1 ] = str;
05762 }
05763 }
05764 else
05765 {
05766 unsigned count = token.functionParams()-1;
05767 mergeTokens( &stack, count, UString(";") );
05768 if( stack.size() )
05769 {
05770 UString str;
05771 str.append( UString("(") );
05772 str.append( stack[ stack.size()-1 ] );
05773 str.append( UString(")") );
05774 stack[ stack.size()-1 ] = str;
05775 }
05776 }
05777 break;
05778
05779 case FormulaToken::Attr:
05780 if( token.attr() & 0x10 )
05781 {
05782 mergeTokens( &stack, 1, UString(";") );
05783 if( stack.size() )
05784 {
05785 UString str( "SUM" );
05786 str.append( UString("(") );
05787 str.append( stack[ stack.size()-1 ] );
05788 str.append( UString(")") );
05789 stack[ stack.size()-1 ] = str;
05790 }
05791 }
05792 break;
05793
05794 case FormulaToken::NameX:
05795 if( token.nameIndex() > 0 )
05796 if( token.nameIndex() <= d->nameTable.size() )
05797 stack.push_back( d->nameTable[ token.nameIndex()-1 ] );
05798 break;
05799
05800 case FormulaToken::NatFormula:
05801 case FormulaToken::Sheet:
05802 case FormulaToken::EndSheet:
05803 case FormulaToken::ErrorCode:
05804 case FormulaToken::Name:
05805 case FormulaToken::MemArea:
05806 case FormulaToken::MemErr:
05807 case FormulaToken::MemNoMem:
05808 case FormulaToken::MemFunc:
05809 case FormulaToken::RefErr:
05810 case FormulaToken::AreaErr:
05811 case FormulaToken::RefN:
05812 case FormulaToken::AreaN:
05813 case FormulaToken::MemAreaN:
05814 case FormulaToken::MemNoMemN:
05815 case FormulaToken::Ref3d:
05816 case FormulaToken::Area3d:
05817 case FormulaToken::RefErr3d:
05818 case FormulaToken::AreaErr3d:
05819 default:
05820
05821 stack.push_back( UString("Unknown") );
05822 break;
05823 };
05824
05825 #ifdef SWINDER_XLS2RAW
05826 dumpStack( stack );
05827 #endif
05828
05829 }
05830
05831 UString result;
05832 for( unsigned i = 0; i < stack.size(); i++ )
05833 result.append( stack[i] );
05834
05835 #ifdef SWINDER_XLS2RAW
05836 std::cout << "FORMULA Result: " << result << std::endl;
05837 #endif
05838 return result;
05839 }
05840
05841
05842 #ifdef SWINDER_XLS2RAW
05843
05844 #include <iostream>
05845
05846 int main( int argc, char ** argv )
05847 {
05848 if( argc < 2 )
05849 {
05850 std::cout << "Usage: xls2raw filename" << std::endl;
05851 return 0;
05852 }
05853
05854 char* filename = argv[1];
05855 std::cout << "Checking " << filename << std::endl;
05856
05857 Workbook* workbook = new Workbook();
05858 ExcelReader* reader = new ExcelReader();
05859 reader->load( workbook, filename );
05860 delete reader;
05861 delete workbook;
05862
05863 return 0;
05864 }
05865
05866 #endif // XLS2RAW