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