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