38static inline unsigned long readU16(
const void* p )
40 const unsigned char* ptr = (
const unsigned char*) p;
41 return ptr[0]+(ptr[1]<<8);
44static inline int readI16(
const void* p )
46 const unsigned char* ptr = (
const unsigned char*) p;
47 unsigned int v = ptr[0]+(ptr[1]<<8);
48 if(v > 32768) v -= 65536;
52static inline unsigned long readU32(
const void* p )
54 const unsigned char* ptr = (
const unsigned char*) p;
55 return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
58typedef double& data_64;
59inline void convert_64 (data_64 convert)
62 unsigned int u_int_temp;
63 temp = ((
unsigned char*)&convert)[0];
64 ((
unsigned char*)&convert)[0] = ((
unsigned char*)&convert)[3];
65 ((
unsigned char*)&convert)[3] = temp;
66 temp = ((
unsigned char*)&convert)[1];
67 ((
unsigned char*)&convert)[1] = ((
unsigned char*)&convert)[2];
68 ((
unsigned char*)&convert)[2] = temp;
69 temp = ((
unsigned char*)&convert)[4];
70 ((
unsigned char*)&convert)[4] = ((
unsigned char*)&convert)[7];
71 ((
unsigned char*)&convert)[7] = temp;
72 temp = ((
unsigned char*)&convert)[5];
73 ((
unsigned char*)&convert)[5] = ((
unsigned char*)&convert)[6];
74 ((
unsigned char*)&convert)[6] = temp;
76 u_int_temp = ((
unsigned int *)&convert)[0];
77 ((
unsigned int *)&convert)[0] = ((
unsigned int *)&convert)[1];
78 ((
unsigned int *)&convert)[1] = u_int_temp;
81inline bool isLittleEndian(
void)
84 unsigned char* a = (
unsigned char*) &i;
85 return ( *a == 0x11 );
90static inline double readFloat64(
const void*p )
92 const double* ptr = (
const double*) p;
96 if( !isLittleEndian() )
104static inline void decodeRK(
unsigned rkvalue,
bool& isInteger,
105 int& intResult,
double& floatResult )
107 bool div100 = rkvalue & 0x01;
108 isInteger = rkvalue & 0x02;
113 intResult = *((
int*) &rkvalue) >> 2;
119 floatResult = (double)intResult / 100.0;
125 unsigned char* s = (
unsigned char*) &rkvalue;
126 unsigned char* r = (
unsigned char*) &floatResult;
127 if( isLittleEndian() )
129 r[0] = r[1] = r[2] = r[3] = 0;
131 r[5] = s[1]; r[6] = s[2]; r[7] = s[3];
135 r[0] = r[1] = r[2] = r[3] = 0;
137 r[5] = s[1]; r[6] = s[2]; r[7] = s[3];
139 memcpy( &floatResult, r, 8 );
150std::ostream& operator<<( std::ostream& s, Swinder::UString ustring )
152 char* str = ustring.
ascii();
159using namespace Swinder;
161static Value errorAsValue(
int errorCode )
163 Value result( Value::Error );
185class EString::Private
196 d =
new EString::Private();
203EString::EString(
const EString& es )
205 d =
new EString::Private();
209EString& EString::operator=(
const EString& es )
211 d->unicode = es.d->unicode;
212 d->richText = es.d->richText;
213 d->size = es.d->size;
223bool EString::unicode()
const
228void EString::setUnicode(
bool u )
233bool EString::richText()
const
238void EString::setRichText(
bool r )
248void EString::setStr(
const UString& str )
253unsigned EString::size()
const
258void EString::setSize(
unsigned s )
264EString EString::fromUnicodeString(
const void* p,
bool longString,
unsigned )
266 const unsigned char* data = (
const unsigned char*) p;
269 unsigned offset = longString ? 2 : 1;
270 unsigned len = longString ? readU16( data ): data[0];
271 unsigned char flag = data[ offset ];
274 bool unicode = flag & 0x01;
275 bool richText = flag & 0x08;
276 unsigned formatRuns = 0;
280 formatRuns = readU16( data + offset );
285 unsigned size = offset + len;
286 if( unicode ) size += len;
287 if( richText ) size += (formatRuns*4);
291 char* buffer =
new char[ len+1 ];
292 memcpy( buffer, data + offset, len );
294 str = UString( buffer );
301 for(
unsigned k=0; k<len; k++ )
302 str.append( readU16( data + offset + k*2 ) );
306 result.setUnicode( unicode );
307 result.setRichText( richText );
308 result.setSize( size );
309 result.setStr( str );
315EString EString::fromByteString(
const void* p,
bool longString,
318 const unsigned char* data = (
const unsigned char*) p;
321 unsigned offset = longString ? 2 : 1;
322 unsigned len = longString ? readU16( data ): data[0];
324 char* buffer =
new char[ len+1 ];
325 memcpy( buffer, data + offset, len );
327 str = UString( buffer );
330 unsigned size = offset + len;
333 result.setUnicode(
false );
334 result.setRichText(
false );
335 result.setSize( size );
336 result.setStr( str );
344EString EString::fromSheetName(
const void* p,
unsigned datasize )
346 const unsigned char* data = (
const unsigned char*) p;
349 bool richText =
false;
352 unsigned len = data[0];
353 unsigned flag = data[1];
354 bool unicode = flag & 1;
356 if( len > datasize-2 ) len = datasize-2;
357 if( len == 0 )
return EString();
363 char* buffer =
new char[ len+1 ];
364 memcpy( buffer, data + offset, len );
366 str = UString( buffer );
371 for(
unsigned k=0; k<len; k++ )
373 unsigned uch = readU16( data + offset + k*2 );
374 str.append( UChar(uch) );
379 result.setUnicode( unicode );
380 result.setRichText( richText );
381 result.setSize( datasize );
382 result.setStr( str );
391class FormulaToken::Private
396 std::vector<unsigned char> data;
399FormulaToken::FormulaToken()
406FormulaToken::FormulaToken(
unsigned t )
413FormulaToken::FormulaToken(
const FormulaToken& token )
416 d->ver = token.d->ver;
419 d->data.resize( token.d->data.size() );
420 for(
unsigned i = 0; i < d->data.size(); i++ )
421 d->data[i] = token.d->data[i];
424FormulaToken::~FormulaToken()
429unsigned FormulaToken::version()
const
434void FormulaToken::setVersion(
unsigned v )
439unsigned FormulaToken::id()
const
444const char* FormulaToken::idAsString()
const
450 case Matrix: s =
"Matrix";
break;
451 case Table: s =
"Table";
break;
452 case Add: s =
"Add";
break;
453 case Sub: s =
"Sub";
break;
454 case Mul: s =
"Mul";
break;
455 case Div: s =
"Div";
break;
456 case Power: s =
"Power";
break;
457 case Concat: s =
"Concat";
break;
458 case LT: s =
"LT";
break;
459 case LE: s =
"LE";
break;
460 case EQ: s =
"EQ";
break;
461 case GE: s =
"GE";
break;
462 case GT: s =
"GT";
break;
463 case NE: s =
"NE";
break;
464 case Intersect: s =
"Intersect";
break;
465 case List: s =
"List";
break;
466 case Range: s =
"Range";
break;
467 case UPlus: s =
"UPlus";
break;
468 case UMinus: s =
"UMinus";
break;
469 case Percent: s =
"Percent";
break;
470 case Paren: s =
"Paren";
break;
471 case String: s =
"String";
break;
472 case MissArg: s =
"MissArg";
break;
473 case ErrorCode: s =
"ErrorCode";
break;
474 case Bool: s =
"Bool";
break;
475 case Integer: s =
"Integer";
break;
476 case Array: s =
"Array";
break;
477 case Function: s =
"Function";
break;
478 case FunctionVar: s =
"FunctionVar";
break;
479 case Name: s =
"Name";
break;
480 case Ref: s =
"Ref";
break;
481 case RefErr: s =
"RefErr";
break;
482 case RefN: s =
"RefN";
break;
483 case Area: s =
"Area";
break;
484 case AreaErr: s =
"AreaErr";
break;
485 case AreaN: s =
"AreaN";
break;
486 case NameX: s =
"NameX";
break;
487 case Ref3d: s =
"Ref3d";
break;
488 case RefErr3d: s =
"RefErr3d";
break;
489 case Float: s =
"Float";
break;
490 case Area3d: s =
"Area3d";
break;
491 case AreaErr3d: s =
"AreaErr3d";
break;
492 default: s =
"Unknown";
break;
499unsigned FormulaToken::size()
const
550 s = (d->ver == Excel97) ? 4 : 3;
554 s = (d->ver == Excel97) ? 4 : 14;
560 s = (d->ver == Excel97) ? 4 : 3;
566 s = (d->ver == Excel97) ? 8 : 6;
570 s = (d->ver == Excel97) ? 6 : 24;
575 s = (d->ver == Excel97) ? 6 : 17;
583 s = (d->ver == Excel97) ? 10 : 20;
594void FormulaToken::setData(
unsigned size,
const unsigned char* data )
596 d->data.resize( size );
597 for(
unsigned i = 0; i < size; i++ )
598 d->data[i] = data[i];
601Value FormulaToken::value()
const
604 if(d->data.size() == 0)
610 buf =
new unsigned char[d->data.size()];
611 for(
unsigned k=0; k<d->data.size(); k++ )
618 result = errorAsValue( buf[0] );
622 result = Value( buf[0]!=0 );
626 result = Value( (
int)readU16( buf ) );
630 result = Value( readFloat64( buf ) );
635 EString estr = (version()==Excel97) ?
636 EString::fromUnicodeString( buf,
false, d->data.size() ) :
637 EString::fromByteString( buf,
false, d->data.size() );
638 result = Value( estr.str() );
650unsigned FormulaToken::functionIndex()
const
654 unsigned char buf[2];
656 if( d->id == Function )
660 index = readU16( buf );
663 if( d->id == FunctionVar )
667 index = readU16( buf );
679static const FunctionEntry FunctionEntries[] =
835 {
"ENABLECOMMAND", 0 },
836 {
"CHECKCOMMAND", 0 },
837 {
"RENAMECOMMAND", 0 },
840 {
"DELETECOMMAND", 0 },
841 {
"GETCHARTITEM", 0 },
867 {
"GETWORKSPACE", 0 },
869 {
"GETDOCUMENT", 0 },
901 {
"GETDIFFDATE360", 0 },
902 {
"CURRENTDATE", 0 },
917 {
"CREATEOBJECT", 0 },
921 {
"CUSTOMREPEAT", 0 },
922 {
"FORMULACONVERT", 0 },
923 {
"GETLINKINFO", 0 },
935 {
"DELETETOOLBAR", 0 },
937 {
"RESETTOOLBAR", 0 },
941 {
"SPELLINGCHECK", 0 },
944 {
"WINDOWTITLE", 0 },
945 {
"SAVETOOLBAR", 0 },
949 {
"GETWORKBOOK", 0 },
970 {
"HYPGEOMDIST", 4 },
971 {
"LOGNORMDIST", 3 },
973 {
"NEGBINOMDIST", 3 },
978 {
"STANDARDIZE", 3 },
1009 {
"PERCENTILE", 2 },
1010 {
"PERCENTRANK", 0 },
1011 {
"MODALVALUE", 0 },
1014 {
"Unknown333", 0 },
1015 {
"MOVIECOMMAND", 0 },
1017 {
"CONCATENATE", 0 },
1019 {
"PIVOTADDDATA", 0 },
1020 {
"GETPIVOTTABLE", 0 },
1021 {
"GETPIVOTFIELD", 0 },
1022 {
"GETPIVOTITEM", 0 },
1028 {
"COUNTBLANK", 1 },
1029 {
"SCENARIOGET", 0 },
1030 {
"OPTIONSLISTSGET", 0 },
1033 {
"DATESTRING", 0 },
1034 {
"NUMBERSTRING", 0 },
1036 {
"OPENDIALOG", 0 },
1037 {
"SAVEDIALOG", 0 },
1039 {
"GETPIVOTDATA", 2 },
1051const char* FormulaToken::functionName()
const
1053 if( functionIndex() > 367 )
return 0;
1054 return FunctionEntries[ functionIndex() ].name;
1057unsigned FormulaToken::functionParams()
const
1059 unsigned params = 0;
1061 if( d->id == Function )
1063 if( functionIndex() > 367 )
return 0;
1064 params = FunctionEntries[ functionIndex() ].params;
1067 if( d->id == FunctionVar )
1069 params = (unsigned)d->data[0];
1076unsigned FormulaToken::attr()
const
1081 attr = (unsigned) d->data[0];
1086unsigned FormulaToken::nameIndex()
const
1090 unsigned char buf[2];
1092 if( d->id == NameX )
1093 if( d->ver == Excel97 )
1095 buf[0] = d->data[2];
1096 buf[1] = d->data[3];
1097 ni = readU16( buf );
1100 if( d->id == NameX )
1101 if( d->ver == Excel95 )
1103 buf[0] = d->data[10];
1104 buf[1] = d->data[11];
1105 ni = readU16( buf );
1112UString FormulaToken::area(
unsigned row,
unsigned col )
const
1121 if((
id() == Area3d))
1122 minsize = (version() == Excel97) ? 10 : 20;
1123 else if(
id() == Area)
1124 minsize = (version() == Excel97) ? 8 : 6;
1125 if(d->data.size() < minsize)
1128 unsigned char buf[2];
1129 int row1Ref, row2Ref, col1Ref, col2Ref;
1130 bool row1Relative, col1Relative;
1131 bool row2Relative, col2Relative;
1133 if( version() == Excel97 )
1135 int ofs = (id() == Area) ? 0 : 2;
1137 buf[0] = d->data[ofs];
1138 buf[1] = d->data[ofs+1];
1139 row1Ref = readU16( buf );
1141 buf[0] = d->data[ofs+2];
1142 buf[1] = d->data[ofs+3];
1143 row2Ref = readU16( buf );
1145 buf[0] = d->data[ofs+4];
1146 buf[1] = d->data[ofs+5];
1147 col1Ref = readU16( buf );
1149 buf[0] = d->data[ofs+6];
1150 buf[1] = d->data[ofs+7];
1151 col2Ref = readU16( buf );
1153 row1Relative = col1Ref & 0x8000;
1154 col1Relative = col1Ref & 0x4000;
1157 row2Relative = col2Ref & 0x8000;
1158 col2Relative = col2Ref & 0x4000;
1163 int ofs = (id() == Area) ? 0 : 14;
1165 buf[0] = d->data[ofs];
1166 buf[1] = d->data[ofs+1];
1167 row1Ref = readU16( buf );
1169 buf[0] = d->data[ofs+2];
1170 buf[1] = d->data[ofs+3];
1171 row2Ref = readU16( buf );
1173 buf[0] = d->data[ofs+4];
1175 col1Ref = readU16( buf );
1177 buf[0] = d->data[ofs+5];
1179 col2Ref = readU16( buf );
1181 row1Relative = row2Ref & 0x8000;
1182 col1Relative = row2Ref & 0x4000;
1185 row2Relative = row2Ref & 0x8000;
1186 col2Relative = row2Ref & 0x4000;
1199 result.
append( Cell::columnLabel( col1Ref ) );
1206 result.
append( Cell::columnLabel( col2Ref ) );
1214UString FormulaToken::ref(
unsigned row,
unsigned col )
const
1223 unsigned char buf[2];
1225 bool rowRelative, colRelative;
1227 if( version() == Excel97 )
1229 int ofs = (id() == Ref) ? 0 : 2;
1230 buf[0] = d->data[ofs];
1231 buf[1] = d->data[ofs+1];
1232 rowRef = readU16( buf );
1234 buf[0] = d->data[ofs+2];
1235 buf[1] = d->data[ofs+3];
1236 colRef = readU16( buf );
1238 rowRelative = colRef & 0x8000;
1239 colRelative = colRef & 0x4000;
1244 int ofs = (id() == Ref) ? 0 : 14;
1245 buf[0] = d->data[ofs];
1246 buf[1] = d->data[ofs+1];
1247 rowRef = readU16( buf );
1249 buf[0] = d->data[ofs+2];
1251 colRef = readU16( buf );
1253 rowRelative = rowRef & 0x8000;
1254 colRelative = rowRef & 0x4000;
1267 result.
append( Cell::columnLabel( colRef ) );
1276unsigned FormulaToken::externSheetRef()
const
1278 if(version() >= Excel97)
1280 unsigned char buf[2];
1281 buf[0] = d->data[0];
1282 buf[1] = d->data[1];
1283 return readU16(buf);
1287 unsigned char buf[2];
1288 buf[0] = d->data[0];
1289 buf[1] = d->data[1];
1290 int index = readI16(buf);
1296 unsigned ref = -index - 1;
1305unsigned FormulaToken::refRow()
const
1308 unsigned char buf[2];
1310 buf[0] = d->
data[0];
1311 buf[1] = d->data[1];
1312 unsigned ref = readU16(buf);
1318unsigned FormulaToken::refColumn()
const
1321 unsigned char buf[2];
1323 buf[0] = d->data[2];
1324 buf[1] = d->data[3];
1325 unsigned ref = readU16(buf);
1331std::ostream& Swinder::operator<<( std::ostream& s, Swinder::FormulaToken token )
1333 s << std::setw(2) << std::hex << token.id() << std::dec;
1337 switch( token.id() )
1339 case FormulaToken::ErrorCode:
1340 case FormulaToken::Bool:
1341 case FormulaToken::Integer:
1342 case FormulaToken::Float:
1343 case FormulaToken::String:
1345 Value v = token.value();
1350 case FormulaToken::Function:
1351 s <<
"Function " << token.functionName();
1355 s << token.idAsString();
1366class CellInfo::Private
1376 info =
new CellInfo::Private();
1399 return info->column;
1409 return info->xfIndex;
1421class ColumnSpanInfo::Private
1430 spaninfo =
new ColumnSpanInfo::Private();
1431 spaninfo->firstColumn = 0;
1432 spaninfo->lastColumn = 0;
1442 return spaninfo->firstColumn;
1447 spaninfo->firstColumn = c;
1452 return spaninfo->lastColumn;
1457 spaninfo->lastColumn = c;
1466 stream_position = 0;
1481 else if( type == EOFRecord::id )
1484 if( type == BackupRecord::id )
1487 if( type == BlankRecord::id )
1493 if( type == BottomMarginRecord::id )
1496 if( type == BoundSheetRecord::id )
1499 if( type == CalcModeRecord::id )
1502 if( type == ColInfoRecord::id )
1505 if( type == DateModeRecord::id )
1508 if( type == DimensionRecord::id )
1511 if( type == ExternNameRecord::id )
1512 record =
new ExternNameRecord();
1514 if( type == ExternSheetRecord::id )
1515 record =
new ExternSheetRecord();
1517 else if( type == FilepassRecord::id )
1518 record =
new FilepassRecord();
1520 else if( type == FontRecord::id )
1523 else if( type == FooterRecord::id )
1526 else if( type == FormatRecord::id )
1529 else if( type == FormulaRecord::id )
1532 else if( type == FormulaRecord::idOld )
1535 else if( type == HeaderRecord::id )
1538 else if( type == LabelRecord::id )
1541 else if( type == LabelSSTRecord::id )
1544 if( type == LeftMarginRecord::id )
1547 else if( type == MergedCellsRecord::id )
1550 else if( type == MulBlankRecord::id )
1553 else if( type == MulRKRecord::id )
1556 if( type == NameRecord::id )
1557 record =
new NameRecord();
1559 else if( type == NumberRecord::id )
1562 else if( type == PaletteRecord::id )
1565 if( type == RightMarginRecord::id )
1568 else if( type == RKRecord::id )
1571 else if( type == RowRecord::id )
1574 else if( type == RStringRecord::id )
1577 else if( type == SSTRecord::id )
1580 else if( type == StringRecord::id )
1583 else if( type == SupbookRecord::id )
1586 else if( type == XFRecord::id )
1589 else if( type == TopMarginRecord::id )
1597 stream_position = pos;
1602 return stream_position;
1616const unsigned int BackupRecord::id = 0x0040;
1618class BackupRecord::Private
1627 d =
new BackupRecord::Private();
1648 if( size < 2 )
return;
1650 unsigned flag = readU16( data );
1651 d->backup = flag != 0;
1656 out <<
"BACKUP" << std::endl;
1657 out <<
" Backup on save : " << (
backup() ?
"Yes" :
"No") << std::endl;
1662const unsigned int BlankRecord::id = 0x0201;
1671 if( size < 6 )
return;
1673 setRow( readU16( data ) );
1680 out <<
"BLANK" << std::endl;
1681 out <<
" Row : " <<
row() << std::endl;
1682 out <<
" Column : " <<
column() << std::endl;
1683 out <<
" XF Index : " <<
xfIndex() << std::endl;
1692class BOFRecord::Private
1707 d =
new BOFRecord::Private();
1724 if( size < 4 )
return;
1726 d->version = readU16( data );
1727 d->type = readU16( data+2 );
1730 d->build = readU16( data+4 );
1731 d->year = readU16( data+6);
1734 d->history = readU32( data+8 );
1735 d->rversion = readU32( data+12 );
1742 unsigned ver = UnknownExcel;
1743 switch( d->version )
1745 case 0x0500 : ver = Excel95;
break;
1746 case 0x0600 : ver = Excel97;
break;
1754 const char *result =
"Unknown";
1757 case Excel95 : result =
"Excel95";
break;
1758 case Excel97 : result =
"Excel97";
break;
1766 unsigned result = UnknownType;
1769 case 0x005 : result = Workbook;
break;
1770 case 0x006 : result = VBModule;
break;
1771 case 0x010 : result = Worksheet;
break;
1772 case 0x020 : result = Chart;
break;
1773 case 0x040 : result = MacroSheet;
break;
1774 case 0x100 : result = Workspace;
break;
1782 const char *result =
"Unknown";
1785 case Workbook : result =
"Workbook";
break;
1786 case VBModule : result =
"Visual Basic Module";
break;
1787 case Worksheet : result =
"Worksheet";
break;
1788 case Chart : result =
"Chart";
break;
1789 case MacroSheet : result =
"Macro Sheet";
break;
1790 case Workspace : result =
"Workspace File";
break;
1798 out <<
"BOF" << std::endl;
1799 out <<
" Version : 0x" << std::hex << d->version <<
" (" <<
versionAsString() <<
")" << std::endl;
1800 out <<
" Type : 0x" << d->type <<
" (" <<
typeAsString() <<
")" << std::endl;
1801 out <<
" Build : 0x" << d->build << std::endl;
1802 out <<
" Year : " << std::dec << d->year << std::endl;
1803 out <<
" History : 0x" << std::hex << d->history << std::endl;
1804 out <<
" RVersion : 0x" << d->rversion << std::endl;
1812class BoolErrRecord::Private
1821 d =
new BoolErrRecord::Private();
1822 d->value =
Value(
false );
1832 if( size != 8 )
return;
1834 setRow( readU16( data ) );
1841 d->value =
Value( data[6] ?
true :
false );
1844 d->value = errorAsValue( data[6] );
1848 std::cerr <<
"Warning: bad BOOLERR record" << std::endl;
1860 out <<
"BOOLERR" << std::endl;
1861 out <<
" Column : " <<
column() << std::endl;
1862 out <<
" Row : " <<
row() << std::endl;
1863 out <<
" XFIndex : " <<
xfIndex() << std::endl;
1864 out <<
" Value : " <<
value() << std::endl;
1869const unsigned int BottomMarginRecord::id = 0x0029;
1871class BottomMarginRecord::Private
1880 d =
new BottomMarginRecord::Private();
1881 d->bottomMargin = 1.0;
1891 return d->bottomMargin;
1896 d->bottomMargin = m;
1901 if( size < 8 )
return;
1907 out <<
"BOTTOMMARGIN" << std::endl;
1908 out <<
" Bottom Margin : " <<
bottomMargin() <<
" inches" << std::endl;
1914const unsigned int BoundSheetRecord::id = 0x0085;
1917class BoundSheetRecord::Private
1921 unsigned visibility;
1929 d =
new BoundSheetRecord::Private();
1939 case Worksheet: d->type = 0;
break;
1940 case Chart: d->type = 2;
break;
1941 case VBModule: d->type = 6;
break;
1942 default: d->type = 0;
break;
1948 unsigned t = Worksheet;
1951 case 0: t = Worksheet;
break;
1952 case 2: t = Chart;
break;
1953 case 6: t = VBModule;
break;
1961 const char *result =
"Unknown";
1964 case Worksheet: result =
"Worksheet";
break;
1965 case Chart: result =
"Chart";
break;
1966 case VBModule: result =
"Visual Basic Module";
break;
1974 d->visibility = v ? 0 : 1;
1979 return d->visibility == 0;
1994 d->bofPosition = pos;
1999 return d->bofPosition;
2009 if( size < 6 )
return;
2011 d->bofPosition = readU32( data );
2012 d->visibility = data[4];
2022 EString::fromSheetName( data+6, size-6 ).str() :
2023 EString::fromByteString( data+6,
false, size-6 ).str();
2029 out <<
"BOUNDSHEET" << std::endl;
2030 out <<
" Name : " << d->name << std::endl;
2031 out <<
" Type : " << d->type <<
" (" <<
typeAsString() <<
")" << std::endl;
2032 out <<
" Visibility : " << d->visibility <<
" (";
2033 if(
visible() ) out <<
"Visible";
else out <<
"Hidden"; out <<
")" << std::endl;
2034 out <<
" BOF pos : " << d->bofPosition << std::endl;
2039const unsigned int CalcModeRecord::id = 0x000d;
2041class CalcModeRecord::Private
2050 d =
new CalcModeRecord::Private();
2051 d->autoCalc =
false;
2071 if( size < 2 )
return;
2073 unsigned flag = readU16( data );
2074 d->autoCalc = flag != 0;
2079 out <<
"CALCMODE" << std::endl;
2080 out <<
" Auto Calc : " << (
autoCalc() ?
"Yes" :
"No") << std::endl;
2085const unsigned int ColInfoRecord::id = 0x007d;
2087class ColInfoRecord::Private
2100 d =
new ColInfoRecord::Private();
2104 d->collapsed =
false;
2105 d->outlineLevel = 0;
2146 return d->collapsed;
2156 return d->outlineLevel;
2161 d->outlineLevel = l;
2166 if( size < 10 )
return;
2173 unsigned options = readU16( data+8 );
2181 out <<
"COLINFO" << std::endl;
2182 out <<
" First Column : " <<
firstColumn() << std::endl;
2183 out <<
" Last Column : " <<
lastColumn() << std::endl;
2184 out <<
" Width : " <<
width() << std::endl;
2185 out <<
" XF Index : " <<
xfIndex() << std::endl;
2186 out <<
" Hidden : " << (
hidden() ?
"Yes" :
"No" ) << std::endl;
2187 out <<
" Collapsed : " << (
collapsed() ?
"Yes" :
"No" ) << std::endl;
2188 out <<
" Outline Level : " <<
outlineLevel() << std::endl;
2193const unsigned int DateModeRecord::id = 0x0022;
2195class DateModeRecord::Private
2204 d =
new DateModeRecord::Private();
2205 d->base1904 =
false;
2225 if( size < 2 )
return;
2227 unsigned flag = readU16( data );
2228 d->base1904 = flag != 0;
2233 out <<
"DATEMODE" << std::endl;
2234 out <<
" 1904 base : " << (
base1904() ?
"Yes" :
"No") << std::endl;
2240const unsigned int DimensionRecord::id = 0x0200;
2242class DimensionRecord::Private
2254 d =
new DimensionRecord::Private;
2288 return d->firstColumn;
2298 return d->lastColumn;
2308 if( size < 14 )
return;
2318 out <<
"DIMENSION" << std::endl;
2319 out <<
" First Row : " <<
firstRow() << std::endl;
2320 out <<
" Last Row : " <<
lastRow() << std::endl;
2321 out <<
" First Column : " <<
firstColumn() << std::endl;
2322 out <<
" Last Column : " <<
lastColumn() << std::endl;
2327const unsigned int EOFRecord::id = 0x000a;
2345 out <<
"EOF" << std::endl;
2350const unsigned int ExternNameRecord::id = 0x0023;
2352class ExternNameRecord::Private
2355 unsigned optionFlags;
2356 unsigned sheetIndex;
2361ExternNameRecord::ExternNameRecord()
2368ExternNameRecord::~ExternNameRecord()
2373void ExternNameRecord::setSheetIndex(
unsigned sheetIndex )
2375 d->sheetIndex = sheetIndex;
2378unsigned ExternNameRecord::sheetIndex()
const
2380 return d->sheetIndex;
2383void ExternNameRecord::setExternName(
const UString& name )
2385 d->externName = name;
2388UString ExternNameRecord::externName()
const
2390 return d->externName;
2393void ExternNameRecord::setData(
unsigned size,
const unsigned char* data )
2395 if( size < 6 )
return;
2397 if ( version() == Excel97 )
2399 d->optionFlags = readU16( data );
2400 d->sheetIndex = readU16( data+2 );
2401 d->externName = EString::fromUnicodeString( data+6,
false, size ).str();
2404 if ( version() == Excel95 )
2408 d->externName = EString::fromByteString( data+6,
false, size ).str();
2412void ExternNameRecord::dump( std::ostream& out )
const
2418const unsigned int ExternSheetRecord::id = 0x0017;
2420class ExternSheetRecord::Private
2429 std::vector<ExternSheetRef> refs;
2433ExternSheetRecord::ExternSheetRecord()
2438ExternSheetRecord::~ExternSheetRecord()
2443unsigned ExternSheetRecord::count()
const
2445 return d->refs.size();
2448unsigned ExternSheetRecord::refIndex(
unsigned i)
const
2450 if(i >= d->refs.size())
return 0;
2451 return d->refs[i].index;
2454unsigned ExternSheetRecord::firstSheet(
unsigned i)
const
2456 if(i >= d->refs.size())
return 0;
2457 return d->refs[i].first;
2460unsigned ExternSheetRecord::lastSheet(
unsigned i)
const
2462 if(i >= d->refs.size())
return 0;
2463 return d->refs[i].last;
2466UString ExternSheetRecord::refName()
const
2471void ExternSheetRecord::setData(
unsigned size,
const unsigned char* data )
2477 if(size < 2)
return;
2479 if(version() >= Excel97)
2482 unsigned c = readU16(data);
2485 for(
unsigned i = 0; i < c; i++, ofs+=6)
2488 if(ofs + 6 > size)
break;
2490 ExternSheetRecord::Private::ExternSheetRef ref;
2491 ref.index = readU16(data+ofs);
2492 ref.first = readU16(data+ofs+2);
2493 ref.last = readU16(data+ofs+4);
2495 d->refs.push_back(ref);
2500 unsigned char dtype = data[1];
2501 unsigned dlen = (unsigned) data[0];
2507 for(
int i = 0; i < dlen; i++)
2509 if(i + 2 > size)
break;
2510 char ch = data[i + 2];
2519void ExternSheetRecord::dump( std::ostream& out )
const
2521 out <<
"EXTERNSHEET" << std::endl;
2526const unsigned int FilepassRecord::id = 0x002f;
2528FilepassRecord::FilepassRecord():
2533FilepassRecord::~FilepassRecord()
2537void FilepassRecord::setData(
unsigned,
const unsigned char* )
2542void FilepassRecord::dump( std::ostream& out )
const
2544 out <<
"FILEPASS" << std::endl;
2549const unsigned int FontRecord::id = 0x0031;
2551class FontRecord::Private
2556 unsigned fontFamily;
2557 unsigned characterSet;
2558 unsigned colorIndex;
2562 unsigned escapement;
2568 d =
new FontRecord::Private;
2570 d->fontName =
"Arial";
2572 d->characterSet = 0;
2576 d->strikeout =
false;
2577 d->escapement = Normal;
2578 d->underline = None;
2588 d =
new FontRecord::Private;
2594 d->height = ef.height();
2596 d->fontFamily = ef.fontFamily();
2597 d->characterSet = ef.characterSet();
2607unsigned FontRecord::height()
const
2612void FontRecord::setHeight(
unsigned h )
2627unsigned FontRecord::fontFamily()
const
2629 return d->fontFamily;
2632void FontRecord::setFontFamily(
unsigned f )
2637unsigned FontRecord::characterSet()
const
2639 return d->characterSet;
2642void FontRecord::setCharacterSet(
unsigned cs )
2644 d->characterSet = cs;
2649 return d->colorIndex;
2679 return d->strikeout;
2689 return d->escapement;
2699 return d->underline;
2710 if( size < 14 )
return;
2712 setHeight( readU16( data ) );
2713 unsigned flag = readU16( data+2 );
2724 setFontFamily( data[11] );
2725 setCharacterSet( data[12] );
2727 UString fn = ( version() >= Excel97 ) ?
2728 EString::fromSheetName( data+14, size-14 ).str() :
2729 EString::fromByteString( data+14,
false, size-14 ).str();
2736 out <<
"FONT" << std::endl;
2737 out <<
" Height : " << height() <<
" twips" << std::endl;
2738 out <<
" Font Name : " <<
fontName() << std::endl;
2739 out <<
" Color Index : " <<
colorIndex() << std::endl;
2740 out <<
" Boldness : " <<
boldness() << std::endl;
2741 out <<
" Italic : " << (
italic()?
"Yes":
"No") << std::endl;
2742 out <<
" Strikeout : " << (
strikeout()?
"Yes":
"No") << std::endl;
2743 out <<
" Escapement : ";
2746 case Normal: out <<
"Normal" << std::endl;
break;
2747 case Subscript: out <<
"Subscript" << std::endl;
break;
2748 case Superscript: out <<
"Superscript" << std::endl;
break;
2749 default: out <<
"Unkown " <<
escapement() << std::endl;
break;
2755const unsigned int FooterRecord::id = 0x0015;
2757class FooterRecord::Private
2766 d =
new FooterRecord::Private();
2786 if( size < 2 )
return;
2789 EString::fromUnicodeString( data,
true, size ).str() :
2790 EString::fromByteString( data,
false, size ).str();
2796 out <<
"FOOTER" << std::endl;
2797 out <<
" Footer : " <<
footer() << std::endl;
2802const unsigned int FormatRecord::id = 0x041e;
2804class FormatRecord::Private
2814 d =
new FormatRecord::Private;
2826 d =
new FormatRecord::Private;
2849 return d->formatString;
2854 d->formatString = fs;
2859 if( size < 3 )
return;
2863 UString fs = ( version() >= Excel97 ) ?
2864 EString::fromUnicodeString( data+2,
true, size-2 ).str() :
2865 EString::fromByteString( data+2,
false, size-2 ).str();
2871 out <<
"FORMAT" << std::endl;
2872 out <<
" Index : " <<
index() << std::endl;
2873 out <<
" Format String : " <<
formatString() << std::endl;
2879const unsigned int FormulaRecord::id = 0x0006;
2880const unsigned int FormulaRecord::idOld = 0x0206;
2882class FormulaRecord::Private
2886 FormulaTokens tokens;
2892 d =
new FormulaRecord::Private();
2910FormulaTokens FormulaRecord::tokens()
const
2917 int formula_ofs = 20;
2920 if( size < formula_ofs )
return;
2922 setRow( readU16( data ) );
2926 if( readU16( data+12 ) != 0xffff )
2953 unsigned formula_len = readU16( data+formula_ofs );
2957 for(
unsigned j = formula_ofs+2; j < size; )
2959 unsigned ptg = data[j++];
2960 ptg = ((ptg & 0x40) ? (ptg | 0x20) : ptg) & 0x3F;
2961 FormulaToken token( ptg );
2962 token.setVersion( version() );
2964 if( token.id() == FormulaToken::String )
2967 EString estr = (version()==Excel97) ?
2968 EString::fromUnicodeString( data+j,
false, formula_len ) :
2969 EString::fromByteString( data+j,
false, formula_len );
2970 token.setData( estr.size(), data+j );
2976 if( token.size() > 1 )
2978 token.setData( token.size(), data+j );
2983 d->tokens.push_back( token );
2989 out <<
"FORMULA" << std::endl;
2990 out <<
" Row : " <<
row() << std::endl;
2991 out <<
" Column : " <<
column() << std::endl;
2992 out <<
" XF Index : " <<
xfIndex() << std::endl;
2993 out <<
" Result : " <<
result() << std::endl;
2995 FormulaTokens ts = tokens();
2996 out <<
" Tokens : " << ts.size() << std::endl;
2997 for(
unsigned i = 0; i < ts.size(); i++ )
2998 out <<
" " << ts[i] << std::endl;
3004const unsigned int LabelRecord::id = 0x0204;
3006class LabelRecord::Private
3015 d =
new LabelRecord::Private();
3036 if( size < 6 )
return;
3038 setRow( readU16( data ) );
3043 EString::fromUnicodeString( data+6,
true, size-6 ).str() :
3044 EString::fromByteString( data+6,
true, size-6 ).str();
3050 out <<
"LABEL" << std::endl;
3051 out <<
" Row : " <<
row() << std::endl;
3052 out <<
" Column : " <<
column() << std::endl;
3053 out <<
" XF Index : " <<
xfIndex() << std::endl;
3054 out <<
" Label : " <<
label() << std::endl;
3059const unsigned int HeaderRecord::id = 0x0014;
3061class HeaderRecord::Private
3070 d =
new HeaderRecord::Private();
3090 if( size < 2 )
return;
3093 EString::fromUnicodeString( data,
true, size ).str() :
3094 EString::fromByteString( data,
false, size ).str();
3100 out <<
"HEADER" << std::endl;
3101 out <<
" Header: " <<
header() << std::endl;
3106const unsigned int LabelSSTRecord::id = 0x00fd;
3108class LabelSSTRecord::Private
3117 d =
new LabelSSTRecord::Private();
3133 if( size < 10 )
return;
3135 setRow( readU16( data ) );
3139 d->sstIndex = readU32( data+6 );
3144 out <<
"LABELSST" << std::endl;
3145 out <<
" Row : " <<
row() << std::endl;
3146 out <<
" Column : " <<
column() << std::endl;
3147 out <<
" XF Index : " <<
xfIndex() << std::endl;
3148 out <<
" SST Index : " << d->sstIndex << std::endl;
3153const unsigned int LeftMarginRecord::id = 0x0026;
3155class LeftMarginRecord::Private
3164 d =
new LeftMarginRecord::Private();
3165 d->leftMargin = 1.0;
3175 return d->leftMargin;
3185 if( size < 8 )
return;
3191 out <<
"LEFTMARGIN" << std::endl;
3192 out <<
" Left Margin : " <<
leftMargin() <<
" inches" << std::endl;
3197const unsigned int MergedCellsRecord::id = 0x00e5;
3202 unsigned firstRow, lastRow, firstColumn, lastColumn;
3205class MergedCellsRecord::Private
3208 std::vector<MergedInfo> mergedCells;
3214 d =
new MergedCellsRecord::Private();
3224 return d->mergedCells.size();
3229 if( i >= d->mergedCells.size() )
return 0;
3230 MergedInfo info = d->mergedCells[ i ];
3231 return info.firstRow;
3236 if( i >= d->mergedCells.size() )
return 0;
3237 MergedInfo info = d->mergedCells[ i ];
3238 return info.lastRow;
3243 if( i >= d->mergedCells.size() )
return 0;
3244 MergedInfo info = d->mergedCells[ i ];
3245 return info.firstColumn;
3250 if( i >= d->mergedCells.size() )
return 0;
3251 MergedInfo info = d->mergedCells[ i ];
3252 return info.lastColumn;
3257 if( size < 2 )
return;
3259 unsigned num = readU16( data );
3262 if( size < 2 + num*4 )
return;
3265 for(
unsigned i = 0; i < num; i++ )
3268 info.firstRow = readU16( data + p );
3269 info.lastRow = readU16( data + p + 2 );
3270 info.firstColumn = readU16( data + p + 4 );
3271 info.lastColumn = readU16( data + p + 6 );
3273 d->mergedCells.push_back( info );
3279 out <<
"MERGEDCELLS" << std::endl;
3280 out <<
" Count : " <<
count() << std::endl;
3281 for(
unsigned c = 0; c <
count(); c++ )
3283 out <<
" Merged Cell #" << c <<
" : ";
3292const unsigned int MulBlankRecord::id = 0x00be;
3294class MulBlankRecord::Private
3297 std::vector<unsigned> xfIndexes;
3303 d =
new MulBlankRecord::Private();
3313 if( size < 6 )
return;
3315 setRow( readU16( data ) );
3320 d->xfIndexes.clear();
3321 for(
unsigned i = 4; i < size-2; i+= 2 )
3322 d->xfIndexes.push_back( readU16( data+i ) );
3329 if( i >= d->xfIndexes.size() )
return 0;
3330 return d->xfIndexes[ i ];
3335 out <<
"MULBLANK" << std::endl;
3336 out <<
" Row : " <<
row() << std::endl;
3337 out <<
" First Column : " <<
firstColumn() << std::endl;
3338 out <<
" Last Column : " <<
lastColumn() << std::endl;
3343const unsigned int MulRKRecord::id = 0x00bd;
3345class MulRKRecord::Private
3348 std::vector<unsigned> xfIndexes;
3349 std::vector<bool> isIntegers;
3350 std::vector<int> intValues;
3351 std::vector<double> floatValues;
3352 std::vector<unsigned> rkValues;
3358 d =
new MulRKRecord::Private();
3368 if( i >= d->xfIndexes.size() )
return 0;
3369 return d->xfIndexes[ i ];
3374 if( i >= d->isIntegers.size() )
return true;
3375 return d->isIntegers[ i ];
3380 if( i >= d->intValues.size() )
return 0;
3381 return d->intValues[ i ];
3386 if( i >= d->floatValues.size() )
return 0.0;
3387 return d->floatValues[ i ];
3390unsigned MulRKRecord::encodedRK(
unsigned i )
const
3392 if( i >= d->rkValues.size() )
return 0;
3393 return d->rkValues[ i ];
3398 if( size < 6 )
return;
3400 setRow( readU16( data ) );
3405 d->xfIndexes.clear();
3406 d->isIntegers.clear();
3407 d->intValues.clear();
3408 d->floatValues.clear();
3409 for(
unsigned i = 4; i < size-2; i+= 6 )
3411 d->xfIndexes.push_back( readU16( data+i ) );
3412 unsigned rk = readU32( data+i+2 );
3413 d->rkValues.push_back( rk );
3414 bool isInteger =
true;
int iv = 0;
double fv = 0.0;
3418 d->intValues.push_back(
isInteger ? iv : (
int)fv );
3419 d->floatValues.push_back( !
isInteger ? fv : (
double)iv );
3427 out <<
"MULRK" << std::endl;
3428 out <<
" Row : " <<
row() << std::endl;
3429 out <<
" First Column : " <<
firstColumn() << std::endl;
3430 out <<
" Last Column : " <<
lastColumn() << std::endl;
3434 out <<
" Encoded: " << std::hex << encodedRK( c-
firstColumn() );
3441const unsigned int NameRecord::id = 0x0018;
3443class NameRecord::Private
3446 unsigned optionFlags;
3451NameRecord::NameRecord()
3457NameRecord::~NameRecord()
3462void NameRecord::setDefinedName(
const UString& name )
3464 d->definedName = name;
3467UString NameRecord::definedName()
const
3469 return d->definedName;
3472void NameRecord::setData(
unsigned size,
const unsigned char* data )
3474 if( size < 14 )
return;
3476 d->optionFlags = readU16( data );
3477 unsigned len = data[3];
3479 if ( version() == Excel95 )
3481 char* buffer =
new char[ len+1 ];
3482 memcpy( buffer, data + 14, len );
3484 d->definedName = UString( buffer );
3488 if ( version() == Excel97 )
3490 UString str = UString();
3491 for(
unsigned k=0; k<len; k++ )
3493 unsigned uch = readU16( data + 14 + k*2 );
3494 str.
append( UChar(uch) );
3496 d->definedName = str;
3500void NameRecord::dump( std::ostream& out )
const
3506const unsigned int NumberRecord::id = 0x0203;
3508class NumberRecord::Private
3517 d =
new NumberRecord::Private();
3539 if( size < 14 )
return;
3541 setRow( readU16( data ) );
3549 out <<
"NUMBER" << std::endl;
3550 out <<
" Row : " <<
row() << std::endl;
3551 out <<
" Column : " <<
column() << std::endl;
3552 out <<
" XF Index : " <<
xfIndex() << std::endl;
3553 out <<
" Value : " <<
number() << std::endl;
3558const unsigned int PaletteRecord::id = 0x0092;
3560class PaletteRecord::Private
3563 std::vector<Color> colors;
3569 d =
new PaletteRecord::Private();
3579 return d->colors[ i ];
3584 return d->colors.size();
3589 if( size < 14 )
return;
3591 unsigned num = readU16( data );
3594 for(
unsigned i = 0; i < num; i++, p+=4 )
3596 unsigned red = data[ p ];
3597 unsigned green = data[ p+1 ];
3598 unsigned blue = data[ p+2 ];
3599 d->colors.push_back(
Color( red, green, blue ) );
3605 out <<
"PALETTE" << std::endl;
3606 out <<
" Count : " <<
count() << std::endl;
3607 for(
unsigned i = 0; i <
count(); i++ )
3609 out <<
" Color #" << std::setw(2) << i <<
" : ";
3611 out <<
"R:" << std::setw(3) << c.red;
3612 out <<
" G:" << std::setw(3) << c.green;
3613 out <<
" B:" << std::setw(3) << c.blue << std::endl;
3619const unsigned int RightMarginRecord::id = 0x0027;
3621class RightMarginRecord::Private
3630 d =
new RightMarginRecord::Private();
3631 d->rightMargin = 1.0;
3641 return d->rightMargin;
3651 if( size < 8 )
return;
3657 out <<
"RIGHTMARGIN" << std::endl;
3658 out <<
" Right Margin : " <<
rightMargin() <<
" inches " << std::endl;
3663const unsigned int RKRecord::id = 0x027e;
3665class RKRecord::Private
3677 d =
new RKRecord::Private();
3712 return (
double)d->i;
3729unsigned RKRecord::encodedRK()
const
3738 if( size < 10 )
return;
3740 setRow( readU16( data ) );
3744 int i = 0;
double f = 0.0;
3745 d->rk = readU32( data+6 );
3746 decodeRK( d->rk, d->integer, i, f );
3753 out <<
"RK" << std::endl;
3754 out <<
" Row : " <<
row() << std::endl;
3755 out <<
" Column : " <<
column() << std::endl;
3756 out <<
" XF Index : " <<
xfIndex() << std::endl;
3757 out <<
" Value : " <<
asFloat() << std::endl;
3758 out <<
" Encoded RK : 0x" << std::hex << encodedRK() << std::endl;
3764const unsigned int RowRecord::id = 0x0208;
3766class RowRecord::Private
3778 d =
new RowRecord::Private();
3832 if( size < 16 )
return;
3834 setRow( readU16( data ) );
3837 setHeight( readU16( data+6 ) & 0x7fff );
3840 unsigned options = readU16( data+12 );
3846 out <<
"ROW" << std::endl;
3847 out <<
" Row : " <<
row() << std::endl;
3848 out <<
" First Column : " <<
firstColumn() << std::endl;
3849 out <<
" Last Column : " <<
lastColumn() << std::endl;
3850 out <<
" Height : " <<
height() << std::endl;
3851 out <<
" XF Index : " <<
xfIndex() << std::endl;
3852 out <<
" Hidden : " << (
hidden() ?
"Yes" :
"No" ) << std::endl;
3857const unsigned int RStringRecord::id = 0x00d6;
3859class RStringRecord::Private
3868 d =
new RStringRecord::Private();
3890 if( size < 6 )
return;
3892 setRow( readU16( data ) );
3898 EString::fromUnicodeString( data+6,
true, size-6 ).str() :
3899 EString::fromByteString( data+6,
true, size-6 ).str();
3905 out <<
"RSTRING" << std::endl;
3906 out <<
" Row : " <<
row() << std::endl;
3907 out <<
" Column : " <<
column() << std::endl;
3908 out <<
" XF Index : " <<
xfIndex() << std::endl;
3909 out <<
" Label : " <<
label() << std::endl;
3914const unsigned int SSTRecord::id = 0x00fc;
3916class SSTRecord::Private
3921 std::vector<UString> strings;
3927 d =
new SSTRecord::Private();
3937UString sstrecord_get_plain_string(
const unsigned char* data,
unsigned length )
3939 char* buffer =
new char[ length+1 ];
3940 memcpy( buffer, data, length );
3941 buffer[ length ] = 0;
3949 if( size < 8 )
return;
3951 d->total = readU32( data );
3952 d->count = readU32( data+4 );
3954 unsigned offset = 8;
3957 for(
unsigned i = 0; i < d->count; i++ )
3960 if (offset >= size) {
3961 std::cerr <<
"Warning: reached end of SST record, but not all strings have been read!" << std::endl;
3965 EString es = EString::fromUnicodeString( data+offset,
true, size - offset );
3966 d->strings.push_back( es.str() );
3967 offset += es.size();
3971 while( d->strings.size() < d->count )
3972 d->strings.push_back(
UString() );
3976 if( d->count < d->strings.size() )
3978 std::cerr <<
"Warning: mismatch number of string in SST record!" << std::endl;
3979 d->count = d->strings.size();
3992 return d->strings[ index ];
3997 out <<
"SST" << std::endl;
3998 out <<
" Occurences : " << d->total << std::endl;
3999 out <<
" Count : " <<
count() << std::endl;
4000 for(
unsigned i = 0; i <
count(); i++ )
4001 out <<
" String #" << std::setw(2) << i <<
" : " <<
4007const unsigned int StringRecord::id = 0x0207;
4009class StringRecord::Private
4018 d =
new StringRecord::Private();
4028 if( size < 3 )
return;
4032 EString es = EString::fromUnicodeString( data,
true, size );
4033 d->string = es.str();
4043 return Value( d->string );
4048 out <<
"STRING" << std::endl;
4049 out <<
" String : " <<
ustring() << std::endl;
4054const unsigned int SupbookRecord::id = 0x01ae;
4056class SupbookRecord::Private
4059 SupbookRecord::ReferenceType type;
4065 d->type = UnknownRef;
4087 if( version() >= Excel97 )
4092 unsigned id1 = readU16(data);
4093 unsigned id2 = readU16(data+2);
4094 if((id1 == 1) && (id2 == 0x3a01))
4098 if((id1 > 0) && (id2 == 0x0401))
4106 unsigned id1 = readU16(data);
4119 out <<
"SUPBOOK" << std::endl;
4125const unsigned int TopMarginRecord::id = 0x0028;
4127class TopMarginRecord::Private
4136 d =
new TopMarginRecord::Private();
4147 return d->topMargin;
4157 if( size < 8 )
return;
4163 out <<
"TOPMARGIN" << std::endl;
4164 out <<
" Top Margin : " <<
topMargin() <<
" inches " << std::endl;
4169const unsigned int XFRecord::id = 0x00e0;
4171class XFRecord::Private
4205 d =
new XFRecord::Private();
4209 d->formulaHidden =
false;
4211 d->horizontalAlignment = Left;
4212 d->verticalAlignment = VCentered;
4213 d->textWrap =
false;
4214 d->rotationAngle = 0;
4215 d->stackedLetters = 0;
4217 d->shrinkContent = 0;
4218 d->leftBorderStyle = 0;
4219 d->leftBorderColor = 0;
4220 d->rightBorderStyle = 0;
4221 d->rightBorderColor = 0;
4222 d->topBorderStyle = 0;
4223 d->topBorderColor = 0;
4224 d->bottomBorderStyle = 0;
4225 d->bottomBorderColor = 0;
4226 d->diagonalTopLeft =
false;
4227 d->diagonalBottomLeft =
false;
4228 d->diagonalStyle = 0;
4229 d->diagonalColor = 0;
4231 d->patternForeColor = 0;
4232 d->patternBackColor = 0;
4242 d =
new XFRecord::Private();
4280 return d->fontIndex;
4290 return d->formatIndex;
4295 d->formatIndex = fi;
4310 return d->formulaHidden;
4315 d->formulaHidden = f;
4320 return d->parentStyle;
4330 return d->horizontalAlignment;
4335 d->horizontalAlignment = ha;
4340 const char *result =
"Unknown";
4343 case General: result =
"General";
break;
4344 case Left: result =
"Left";
break;
4345 case Centered: result =
"Centered";
break;
4346 case Right: result =
"Right";
break;
4347 case Justified: result =
"Justified";
break;
4348 case Filled: result =
"Filled";
break;
4356 return d->verticalAlignment;
4361 d->verticalAlignment = va;
4366 const char *result =
"Unknown";
4369 case Top: result =
"Top";
break;
4370 case VCentered: result =
"Centered";
break;
4371 case Bottom: result =
"Bottom";
break;
4372 case VJustified: result =
"Justified";
break;
4373 case VDistributed: result =
"Distributed";
break;
4391 return d->rotationAngle;
4396 d->rotationAngle = angle;
4401 return d->stackedLetters;
4406 d->stackedLetters = stacked;
4411 return d->indentLevel;
4421 return d->shrinkContent;
4426 d->shrinkContent = s;
4431 return d->leftBorderStyle;
4436 d->leftBorderStyle = style;
4441 return d->leftBorderColor;
4446 d->leftBorderColor = color;
4451 return d->rightBorderStyle;
4456 d->rightBorderStyle = style;
4461 return d->rightBorderColor;
4466 d->rightBorderColor = color;
4471 return d->topBorderStyle;
4476 d->topBorderStyle = style;
4481 return d->topBorderColor;
4486 d->topBorderColor = color;
4491 return d->bottomBorderStyle;
4496 d->bottomBorderStyle = style;
4501 return d->bottomBorderColor;
4506 d->bottomBorderColor = color;
4511 return d->diagonalTopLeft;
4516 d->diagonalTopLeft = dd;
4521 return d->diagonalBottomLeft;
4526 d->diagonalBottomLeft = dd;
4531 return d->diagonalStyle;
4536 d->diagonalStyle = style;
4541 return d->diagonalColor;
4546 d->diagonalColor = color;
4551 return d->fillPattern;
4556 d->fillPattern = pattern;
4561 return d->patternForeColor;
4566 d->patternForeColor = color;
4571 return d->patternBackColor;
4576 d->patternBackColor = color;
4581 unsigned recordSize = ( version() == Excel97 ) ? 20: 16;
4582 if( size < recordSize )
return;
4587 unsigned protection = readU16( data+4 ) & 7;
4593 unsigned align = data[6];
4598 unsigned angle = data[7];
4602 if( version() == Excel97 )
4604 unsigned options = data[8];
4605 unsigned attributes = data[9];
4610 unsigned linestyle = readU16( data + 10 );
4611 unsigned color1 = readU16( data + 12 );
4613 unsigned flag = readU16( data + 16 );
4614 unsigned fill = readU16( data + 18 );
4637 unsigned data1 = readU32( data + 8 );
4638 unsigned data2 = readU32( data + 12 );
4659 out <<
"XF" << std::endl;
4660 out <<
" Parent Style : " <<
parentStyle() << std::endl;
4661 out <<
" Font Index : " <<
fontIndex() << std::endl;
4662 out <<
" Format Index : " <<
formatIndex() << std::endl;
4663 out <<
" Locked : " << (
locked()?
"Yes":
"No") << std::endl;
4664 out <<
" Formula Visibility : " << (
formulaHidden()?
"Hidden":
"Visible") << std::endl;
4667 out <<
" Text Wrap : " << (
textWrap() ?
"yes" :
"no" ) << std::endl;
4669 out <<
" Stacked Letters : " << (
stackedLetters() ?
"yes" :
"no" ) << std::endl;
4670 out <<
" Indent Level : " <<
indentLevel() << std::endl;
4671 out <<
" Shrink To Fit : " << (
shrinkContent() ?
"yes" :
"no" ) << std::endl;
4680 out <<
" Diagonal Lines : " ;
4684 out <<
" Fill Pattern : " <<
fillPattern() << std::endl;
4693struct ExcelReaderExternalWorkbook
4701class ExcelReader::Private
4710 bool passwordProtected;
4719 std::map<unsigned,Sheet*> bofMap;
4722 std::vector<UString> stringTable;
4725 std::map<unsigned,FormatRecord> formatTable;
4726 std::map<unsigned,UString> formatsTable;
4729 std::vector<FontRecord> fontTable;
4732 std::vector<XFRecord> xfTable;
4735 std::vector<Color> colorTable;
4738 std::map<unsigned,FormatFont> fontCache;
4741 std::vector<UString> nameTable;
4744 std::vector<ExcelReaderExternalWorkbook> externalWorkbooks;
4747 std::vector<UString> sheetRefs;
4753ExcelReader::ExcelReader()
4755 d =
new ExcelReader::Private();
4761 d->passwordProtected =
false;
4763 d->mergedTokens.reserve(1024);
4767 static const char *
const default_palette[64-8] =
4769 "#000000",
"#ffffff",
"#ff0000",
"#00ff00",
"#0000ff",
"#ffff00",
"#ff00ff",
4770 "#00ffff",
"#800000",
"#008000",
"#000080",
"#808000",
"#800080",
"#008080",
4771 "#c0c0c0",
"#808080",
"#9999ff",
"#993366",
"#ffffcc",
"#ccffff",
"#660066",
4772 "#ff8080",
"#0066cc",
"#ccccff",
"#000080",
"#ff00ff",
"#ffff00",
"#00ffff",
4773 "#800080",
"#800000",
"#008080",
"#0000ff",
"#00ccff",
"#ccffff",
"#ccffcc",
4774 "#ffff99",
"#99ccff",
"#ff99cc",
"#cc99ff",
"#ffcc99",
"#3366ff",
"#33cccc",
4775 "#99cc00",
"#ffcc00",
"#ff9900",
"#ff6600",
"#666699",
"#969696",
"#003366",
4776 "#339966",
"#003300",
"#333300",
"#993300",
"#993366",
"#333399",
"#333333",
4778 for(
int i = 0; i < 64-8; i++ ) {
4779 d->colorTable.push_back(Color(default_palette[i]));
4783 for(
int format = 0; format < 50; format++)
4785 UString valueFormat;
4789 case 1: valueFormat =
"0";
break;
4790 case 2: valueFormat =
"0.00";
break;
4791 case 3: valueFormat =
"#,##0";
break;
4792 case 4: valueFormat =
"#,##0.00";
break;
4793 case 5: valueFormat =
"\"$\"#,##0_);(\"S\"#,##0)";
break;
4794 case 6: valueFormat =
"\"$\"#,##0_);[Red](\"S\"#,##0)";
break;
4795 case 7: valueFormat =
"\"$\"#,##0.00_);(\"S\"#,##0.00)";
break;
4796 case 8: valueFormat =
"\"$\"#,##0.00_);[Red](\"S\"#,##0.00)";
break;
4797 case 9: valueFormat =
"0%";
break;
4798 case 10: valueFormat =
"0.00%";
break;
4799 case 11: valueFormat =
"0.00E+00";
break;
4800 case 12: valueFormat =
"#?/?";
break;
4801 case 13: valueFormat =
"#\?\?/\?\?";
break;
4802 case 14: valueFormat =
"M/D/YY";
break;
4803 case 15: valueFormat =
"D-MMM-YY";
break;
4804 case 16: valueFormat =
"D-MMM";
break;
4805 case 17: valueFormat =
"MMM-YY";
break;
4806 case 18: valueFormat =
"h:mm AM/PM";
break;
4807 case 19: valueFormat =
"h:mm:ss AM/PM";
break;
4808 case 20: valueFormat =
"h:mm";
break;
4809 case 21: valueFormat =
"h:mm:ss";
break;
4810 case 22: valueFormat =
"M/D/YY h:mm";
break;
4811 case 37: valueFormat =
"_(#,##0_);(#,##0)";
break;
4812 case 38: valueFormat =
"_(#,##0_);[Red](#,##0)";
break;
4813 case 39: valueFormat =
"_(#,##0.00_);(#,##0)";
break;
4814 case 40: valueFormat =
"_(#,##0.00_);[Red](#,##0)";
break;
4815 case 41: valueFormat =
"_(\"$\"*#,##0_);_(\"$\"*#,##0_);_(\"$\"*\"-\");(@_)";
break;
4816 case 42: valueFormat =
"_(*#,##0_);(*(#,##0);_(*\"-\");_(@_)";
break;
4817 case 43: valueFormat =
"_(\"$\"*#,##0.00_);_(\"$\"*#,##0.00_);_(\"$\"*\"-\");(@_)";
break;
4818 case 44: valueFormat =
"_(\"$\"*#,##0.00_);_(\"$\"*#,##0.00_);_(\"$\"*\"-\");(@_)";
break;
4819 case 45: valueFormat =
"mm:ss";
break;
4820 case 46: valueFormat =
"[h]:mm:ss";
break;
4821 case 47: valueFormat =
"mm:ss.0";
break;
4822 case 48: valueFormat =
"##0.0E+0";
break;
4823 case 49: valueFormat =
"@";
break;
4825 d->formatsTable[format] = valueFormat;
4829ExcelReader::~ExcelReader()
4836static Pen convertBorderStyle(
unsigned style )
4841 case XFRecord::NoLine:
4843 pen.style = Pen::NoLine;
4845 case XFRecord::Thin:
4847 pen.style = Pen::SolidLine;
4849 case XFRecord::Medium:
4851 pen.style = Pen::SolidLine;
4853 case XFRecord::Dashed:
4855 pen.style = Pen::DashLine;
4857 case XFRecord::Dotted:
4859 pen.style = Pen::DotLine;
4861 case XFRecord::Thick:
4863 pen.style = Pen::SolidLine;
4865 case XFRecord::Double:
4868 pen.style = Pen::SolidLine;
4870 case XFRecord::Hair:
4873 pen.style = Pen::DotLine;
4875 case XFRecord::MediumDashed:
4877 pen.style = Pen::DashLine;
4879 case XFRecord::ThinDashDotted:
4881 pen.style = Pen::DashDotLine;
4883 case XFRecord::MediumDashDotted:
4885 pen.style = Pen::DashDotLine;
4887 case XFRecord::ThinDashDotDotted:
4889 pen.style = Pen::DashDotDotLine;
4891 case XFRecord::MediumDashDotDotted:
4893 pen.style = Pen::DashDotDotLine;
4895 case XFRecord::SlantedMediumDashDotted:
4898 pen.style = Pen::DashDotLine;
4903 pen.style = Pen::SolidLine;
4910unsigned convertPatternStyle(
unsigned pattern )
4914 case 0x00:
return FormatBackground::EmptyPattern;
4915 case 0x01:
return FormatBackground::SolidPattern;
4916 case 0x02:
return FormatBackground::Dense4Pattern;
4917 case 0x03:
return FormatBackground::Dense3Pattern;
4918 case 0x04:
return FormatBackground::Dense5Pattern;
4919 case 0x05:
return FormatBackground::HorPattern;
4920 case 0x06:
return FormatBackground::VerPattern;
4921 case 0x07:
return FormatBackground::FDiagPattern;
4922 case 0x08:
return FormatBackground::BDiagPattern;
4923 case 0x09:
return FormatBackground::Dense1Pattern;
4924 case 0x0A:
return FormatBackground::Dense2Pattern;
4925 case 0x0B:
return FormatBackground::HorPattern;
4926 case 0x0C:
return FormatBackground::VerPattern;
4927 case 0x0D:
return FormatBackground::FDiagPattern;
4928 case 0x0E:
return FormatBackground::BDiagPattern;
4929 case 0x0F:
return FormatBackground::CrossPattern;
4930 case 0x10:
return FormatBackground::DiagCrossPattern;
4931 case 0x11:
return FormatBackground::Dense6Pattern;
4932 case 0x12:
return FormatBackground::Dense7Pattern;
4933 default:
return FormatBackground::SolidPattern;
4938bool ExcelReader::load( Workbook* workbook,
const char* filename )
4940 POLE::Storage storage( filename );
4941 if( !storage.open() )
4947 unsigned version = Swinder::Excel97;
4948 POLE::Stream* stream;
4949 stream =
new POLE::Stream( &storage,
"/Workbook" );
4950 if( stream->fail() )
4953 stream =
new POLE::Stream( &storage,
"/Book" );
4954 version = Swinder::Excel95;
4957 if( stream->fail() )
4964 unsigned long stream_size = stream->size();
4966 unsigned int buffer_size = 65536;
4967 unsigned char *buffer = (
unsigned char *) malloc(buffer_size);
4968 unsigned char small_buffer[128];
4971 d->workbook = workbook;
4973 d->passwordProtected =
false;
4977 while( stream->tell() < stream_size )
4983 if(d->passwordProtected)
4985 d->workbook->setPasswordProtected(
true );
4990 unsigned long pos = stream->tell();
4991 unsigned bytes_read = stream->read( buffer, 4 );
4992 if( bytes_read != 4 )
break;
4994 unsigned long type = readU16( buffer );
4995 unsigned long size = readU16( buffer + 2 );
4998 if (size > buffer_size) {
4999 buffer = (
unsigned char *) realloc(buffer, size);
5004 bytes_read = stream->read( buffer, size );
5005 if( bytes_read != size )
break;
5008 unsigned long saved_pos;
5010 unsigned long next_type;
5012 saved_pos = stream->tell();
5014 bytes_read = stream->read( small_buffer, 4 );
5015 if (bytes_read != 4)
break;
5017 next_type = readU16( small_buffer );
5018 unsigned long next_size = readU16( small_buffer + 2 );
5020 if (next_type == 0x3C) {
5024 if ( (size + next_size) > buffer_size) {
5025 buffer = (
unsigned char *) realloc(buffer, size + next_size);
5026 buffer_size = size + next_size;
5030 bytes_read = stream->read( buffer + size, next_size );
5031 if (bytes_read != next_size) {
5032 std::cout <<
"ERROR!" << std::endl;
5037 if (buffer[size] == 0) {
5038 memmove( buffer + size, buffer + size + 1, --next_size );
5044 }
while (next_type == 0x3C);
5047 stream->seek( saved_pos );
5050 if( type == 0 )
continue;
5058 record->setVersion( version );
5059 record->
setData( size, buffer );
5062 handleRecord( record );
5067 BOFRecord* bof =
static_cast<BOFRecord*
>(record);
5068 if( bof )
if( bof->
type() == BOFRecord::Workbook )
5072#ifdef SWINDER_XLS2RAW
5073 std::cout <<
"Record 0x";
5074 std::cout << std::setfill(
'0') << std::setw(4) << std::hex << record->rtti();
5076 std::cout << std::dec;
5077 std::cout <<
"(Pos: " << record->
position() <<
") ";
5078 record->
dump( std::cout );
5079 std::cout << std::endl;
5085#ifdef SWINDER_XLS2RAW
5088 std::cout <<
"Record 0x";
5089 std::cout << std::setfill(
'0') << std::setw(4) << std::hex << type;
5090 std::cout << std::dec;
5091 std::cout <<
"(Pos: " << pos <<
") ";
5092 std::cout << std::endl;
5093 std::cout << std::endl;
5106 for(
int i = 0; i < d->xfTable.size(); i++ )
5109 const XFRecord& xf = d->xfTable[i];
5111 UString valueFormat = d->formatsTable[xf.
formatIndex()];
5116 FormatAlignment alignment;
5119 case XFRecord::Left:
5120 alignment.setAlignX( Format::Left );
break;
5121 case XFRecord::Right:
5122 alignment.setAlignX( Format::Right );
break;
5123 case XFRecord::Centered:
5124 alignment.setAlignX( Format::Center );
break;
5131 alignment.setAlignY( Format::Top );
break;
5132 case XFRecord::VCentered:
5133 alignment.setAlignY( Format::Middle );
break;
5134 case XFRecord::Bottom:
5135 alignment.setAlignY( Format::Bottom );
break;
5139 alignment.setWrap( xf.
textWrap() );
5142 FormatBorders borders;
5163 FormatBackground background;
5169 d->workbook->setFormat( i, format );
5176void ExcelReader::handleRecord(
Record* record )
5178 if( !record )
return;
5180 unsigned type = record->rtti();
5184 handleBottomMargin(
static_cast<BottomMarginRecord*
>( record ) );
break;
5186 handleBoundSheet(
static_cast<BoundSheetRecord*
>( record ) );
break;
5188 handleBOF(
static_cast<BOFRecord*
>( record ) );
break;
5190 handleBoolErr(
static_cast<BoolErrRecord*
>( record ) );
break;
5192 handleBlank(
static_cast<BlankRecord*
>( record ) );
break;
5194 handleCalcMode(
static_cast<CalcModeRecord*
>( record ) );
break;
5196 handleColInfo(
static_cast<ColInfoRecord*
>( record ) );
break;
5198 handleExternName(
static_cast<ExternNameRecord*
>( record ) );
break;
5200 handleExternSheet(
static_cast<ExternSheetRecord*
>( record ) );
break;
5202 handleFilepass(
static_cast<FilepassRecord*
>( record ) );
break;
5204 handleFormat(
static_cast<FormatRecord*
>( record ) );
break;
5206 handleFormula(
static_cast<FormulaRecord*
>( record ) );
break;
5208 handleFont(
static_cast<FontRecord*
>( record ) );
break;
5210 handleFooter(
static_cast<FooterRecord*
>( record ) );
break;
5212 handleHeader(
static_cast<HeaderRecord*
>( record ) );
break;
5214 handleLabel(
static_cast<LabelRecord*
>( record ) );
break;
5216 handleLabelSST(
static_cast<LabelSSTRecord*
>( record ) );
break;
5218 handleLeftMargin(
static_cast<LeftMarginRecord*
>( record ) );
break;
5220 handleMergedCells(
static_cast<MergedCellsRecord*
>( record ) );
break;
5222 handleMulBlank(
static_cast<MulBlankRecord*
>( record ) );
break;
5224 handleMulRK(
static_cast<MulRKRecord*
>( record ) );
break;
5226 handleName(
static_cast<NameRecord*
>( record ) );
break;
5228 handleNumber(
static_cast<NumberRecord*
>( record ) );
break;
5230 handlePalette(
static_cast<PaletteRecord*
>( record ) );
break;
5232 handleRightMargin(
static_cast<RightMarginRecord*
>( record ) );
break;
5234 handleRK(
static_cast<RKRecord*
>( record ) );
break;
5236 handleRow(
static_cast<RowRecord*
>( record ) );
break;
5238 handleRString(
static_cast<RStringRecord*
>( record ) );
break;
5240 handleSST(
static_cast<SSTRecord*
>( record ) );
break;
5242 handleString(
static_cast<StringRecord*
>( record ) );
break;
5244 handleSupbook(
static_cast<SupbookRecord*
>( record ) );
break;
5246 handleTopMargin(
static_cast<TopMarginRecord*
>( record ) );
break;
5248 handleXF(
static_cast<XFRecord*
>( record ) );
break;
5256 if( !record )
return;
5258 if( !d->activeSheet )
return;
5262 d->activeSheet->setBottomMargin( margin );
5269 if( !record )
return;
5272 if( record->
type() == BoundSheetRecord::Worksheet )
5275 Sheet* sheet =
new Sheet( d->workbook );
5277 sheet->setVisible( record->
visible() );
5279 d->workbook->appendSheet( sheet );
5283 d->bofMap[ bofPos ] = sheet;
5287void ExcelReader::handleBOF(
BOFRecord* record )
5289 if( !record )
return;
5291 if( record->
type() == BOFRecord::Worksheet )
5295 Sheet* sheet = d->bofMap[ record->
position() ];
5296 if( sheet ) d->activeSheet = sheet;
5302 if( !record )
return;
5304 if( !d->activeSheet )
return;
5306 unsigned column = record->
column();
5307 unsigned row = record->
row();
5308 unsigned xfIndex = record->
xfIndex();
5310 Cell* cell = d->activeSheet->cell( column, row,
true );
5313 cell->setValue( record->
value() );
5314 cell->setFormatIndex( xfIndex );
5318void ExcelReader::handleBlank(
BlankRecord* record )
5320 if( !record )
return;
5322 if( !d->activeSheet )
return;
5324 unsigned column = record->
column();
5325 unsigned row = record->
row();
5326 unsigned xfIndex = record->
xfIndex();
5328 Cell* cell = d->activeSheet->cell( column, row,
true );
5331 cell->setFormatIndex( xfIndex );
5337 if( !record )
return;
5339 d->workbook->setAutoCalc( record->
autoCalc() );
5344 if( !record )
return;
5346 if( !d->activeSheet )
return;
5350 unsigned xfIndex = record->
xfIndex();
5351 unsigned width = record->
width();
5352 bool hidden = record->
hidden();
5354 for(
unsigned i = firstColumn; i <= lastColumn; i++ )
5356 Column* column = d->activeSheet->column( i,
true );
5359 column->setWidth( width / 120 );
5360 column->setFormatIndex( xfIndex );
5361 column->setVisible( !hidden );
5368 if( !record )
return;
5371 std::cerr <<
"WARNING: Workbook uses unsupported 1904 Date System " << std::endl;
5376 if( !record )
return;
5382void ExcelReader::handleLabel(
LabelRecord* record )
5384 if( !record )
return;
5386 if( !d->activeSheet )
return;
5388 unsigned column = record->
column();
5389 unsigned row = record->
row();
5390 unsigned xfIndex = record->
xfIndex();
5391 UString label = record->
label();
5393 Cell* cell = d->activeSheet->cell( column, row,
true );
5396 cell->setValue( Value( label ) );
5397 cell->setFormatIndex( xfIndex );
5403 if( !record )
return;
5405 if( !d->activeSheet )
return;
5409 d->activeSheet->setLeftMargin( margin );
5414 if( !record )
return;
5416 d->formatTable[ record->
index() ] = *record;
5422 if( !record )
return;
5424 if( !d->activeSheet )
return;
5426 unsigned column = record->
column();
5427 unsigned row = record->
row();
5428 unsigned xfIndex = record->
xfIndex();
5429 Value value = record->
result();
5433 UString formula = decodeFormula( row, column, record->tokens(),
true );
5436 UString formula = decodeFormula( row, column, record->tokens(),
true );
5439 Cell* cell = d->activeSheet->cell( column, row,
true );
5442 cell->setValue( value );
5444 cell->setFormula( formula );
5445 cell->setFormatIndex( xfIndex );
5449 d->formulaCell = cell;
5453void ExcelReader::handleExternName( ExternNameRecord* record )
5455 if( !record )
return;
5457 d->nameTable.push_back( record->externName() );
5460void ExcelReader::handleExternSheet( ExternSheetRecord* record )
5462 if( !record )
return;
5464 if(record->version() >= Excel97)
5465 for(
unsigned i = 0; i < record->count(); i++)
5467 UString decodedRef(
"#REF");
5469 unsigned index = record->refIndex(i);
5470 unsigned first = record->firstSheet(i);
5471 unsigned last = record->lastSheet(i);
5473 if(index < d->externalWorkbooks.size())
5476 if(d->externalWorkbooks[index].internal)
5477 if(first < d->workbook->sheetCount())
5478 decodedRef = d->workbook->sheet(first)->name();
5481 if(d->externalWorkbooks[index].addin)
5482 decodedRef = UString(
"#");
5485 d->sheetRefs.push_back(decodedRef);
5489 UString ref = record->refName();
5490 d->sheetRefs.push_back(ref);
5494void ExcelReader::handleFilepass( FilepassRecord* record )
5496 if( !record )
return;
5498 d->passwordProtected =
true;
5501void ExcelReader::handleFont(
FontRecord* record )
5503 if( !record )
return;
5505 d->fontTable.push_back( *record );
5508 if( d->fontTable.size() == 4 )
5509 d->fontTable.push_back( FontRecord() );
5514 if( !record )
return;
5516 if( !d->activeSheet )
return;
5518 UString footer = record->
footer();
5519 UString left, center, right;
5520 int pos = -1, len = 0;
5523 pos = footer.
find( UString(
"&L") );
5527 len = footer.
find( UString(
"&C") ) - pos;
5530 left = footer.
substr( pos, len );
5536 pos = footer.
find( UString(
"&C") );
5540 len = footer.
find( UString(
"&R") ) - pos;
5543 center = footer.
substr( pos, len );
5549 pos = footer.
find( UString(
"&R") );
5556 d->activeSheet->setLeftFooter( left );
5557 d->activeSheet->setCenterFooter( center );
5558 d->activeSheet->setRightFooter( right );
5563 if( !record )
return;
5565 if( !d->activeSheet )
return;
5567 UString header = record->
header();
5568 UString left, center, right;
5569 int pos = -1, len = 0;
5572 pos = header.
find( UString(
"&L") );
5576 len = header.
find( UString(
"&C") ) - pos;
5579 left = header.
substr( pos, len );
5585 pos = header.
find( UString(
"&C") );
5589 len = header.
find( UString(
"&R") ) - pos;
5592 center = header.
substr( pos, len );
5598 pos = header.
find( UString(
"&R") );
5605 d->activeSheet->setLeftHeader( left );
5606 d->activeSheet->setCenterHeader( center );
5607 d->activeSheet->setRightHeader( right );
5612 if( !record )
return;
5614 if( !d->activeSheet )
return;
5616 unsigned column = record->
column();
5617 unsigned row = record->
row();
5618 unsigned index = record->
sstIndex();
5619 unsigned xfIndex = record->
xfIndex();
5622 if( index < d->stringTable.size() )
5623 str = d->stringTable[ index ];
5625 Cell* cell = d->activeSheet->cell( column, row,
true );
5628 cell->setValue( Value( str ) );
5629 cell->setFormatIndex( xfIndex );
5635 if( !record )
return;
5637 if( !d->activeSheet )
return;
5639 for(
unsigned i = 0; i < record->
count(); i++ )
5641 unsigned firstRow = record->
firstRow( i );
5642 unsigned lastRow = record->
lastRow( i );
5644 unsigned lastColumn = record->
lastColumn( i );
5646 Cell* cell = d->activeSheet->cell( firstColumn, firstRow,
true );
5649 cell->setColumnSpan( lastColumn - firstColumn + 1 );
5650 cell->setRowSpan( lastRow - firstRow + 1 );
5657 if( !record )
return;
5659 if( !d->activeSheet )
return;
5663 unsigned row = record->
row();
5665 for(
unsigned column = firstColumn; column <= lastColumn; column++ )
5667 Cell* cell = d->activeSheet->cell( column, row,
true );
5670 cell->setFormatIndex( record->
xfIndex( column - firstColumn ) );
5675void ExcelReader::handleMulRK(
MulRKRecord* record )
5677 if( !record )
return;
5679 if( !d->activeSheet )
return;
5683 unsigned row = record->
row();
5685 for(
unsigned column = firstColumn; column <= lastColumn; column++ )
5687 Cell* cell = d->activeSheet->cell( column, row,
true );
5690 unsigned i = column - firstColumn;
5693 value.setValue( record->
asInteger( i ) );
5695 value.setValue( record->
asFloat( i ) );
5696 cell->setValue( value );
5697 cell->setFormatIndex( record->
xfIndex( column-firstColumn ) );
5702void ExcelReader::handleName( NameRecord* record )
5704 if( !record )
return;
5706 d->nameTable.push_back( record->definedName() );
5711 if( !record )
return;
5713 if( !d->activeSheet )
return;
5715 unsigned column = record->
column();
5716 unsigned row = record->
row();
5717 unsigned xfIndex = record->
xfIndex();
5718 double number = record->
number();
5720 Cell* cell = d->activeSheet->cell( column, row,
true );
5723 cell->setValue( Value( number ) );
5724 cell->setFormatIndex( xfIndex );
5730 if( !record )
return;
5732 d->colorTable.clear();
5733 for(
unsigned i = 0; i < record->
count(); i++ )
5734 d->colorTable.push_back( record->
color( i ) );
5739 if( !record )
return;
5741 if( !d->activeSheet )
return;
5745 d->activeSheet->setRightMargin( margin );
5748void ExcelReader::handleRK(
RKRecord* record )
5750 if( !record )
return;
5752 if( !d->activeSheet )
return;
5754 unsigned column = record->
column();
5755 unsigned row = record->
row();
5756 unsigned xfIndex = record->
xfIndex();
5762 value.setValue( record->
asFloat() );
5764 Cell* cell = d->activeSheet->cell( column, row,
true );
5767 cell->setValue( value );
5768 cell->setFormatIndex( xfIndex );
5772void ExcelReader::handleRow(
RowRecord* record )
5774 if( !record )
return;
5776 if( !d->activeSheet )
return;
5778 unsigned index = record->
row();
5779 unsigned xfIndex = record->
xfIndex();
5780 unsigned height = record->
height();
5781 bool hidden = record->
hidden();
5783 Row* row = d->activeSheet->row( index,
true );
5786 row->setHeight( height / 20.0 );
5787 row->setFormatIndex( xfIndex );
5788 row->setVisible( !hidden );
5794 if( !record )
return;
5796 if( !d->activeSheet )
return;
5798 unsigned column = record->
column();
5799 unsigned row = record->
row();
5800 unsigned xfIndex = record->
xfIndex();
5801 UString label = record->
label();
5803 Cell* cell = d->activeSheet->cell( column, row,
true );
5806 cell->setValue( Value( label ) );
5807 cell->setFormatIndex( xfIndex );
5811void ExcelReader::handleSST(
SSTRecord* record )
5813 if( !record )
return;
5815 d->stringTable.clear();
5816 for(
unsigned i = 0; i < record->
count();i++ )
5818 UString str = record->
stringAt( i );
5819 d->stringTable.push_back( str );
5825 if( !record )
return;
5827 if( !d->activeSheet )
return;
5828 if( !d->formulaCell )
return;
5830 d->formulaCell->setValue( record->
value() );
5837 if( !record )
return;
5839 ExcelReaderExternalWorkbook ext;
5840 ext.addin = record->
referenceType() == SupbookRecord::AddInRef;
5841 ext.internal = record->
referenceType() == SupbookRecord::InternalRef;
5842 ext.external = record->
referenceType() == SupbookRecord::ExternalRef;
5843 ext.objectLink = record->
referenceType() == SupbookRecord::ObjectLink;
5844 d->externalWorkbooks.push_back(ext);
5849 if( !record )
return;
5851 if( !d->activeSheet )
return;
5855 double margin = record->
topMargin() * 72.0;
5856 d->activeSheet->setTopMargin( margin );
5859FormatFont ExcelReader::convertFont(
unsigned fontIndex )
5862 FormatFont font = d->fontCache[ fontIndex ];
5863 if( font.
isNull() && ( fontIndex < d->fontTable.size() ))
5865 FontRecord fr = d->fontTable[ fontIndex ];
5877 d->fontCache[ fontIndex ] = font;
5883Color ExcelReader::convertColor(
unsigned colorIndex )
5885 if( ( colorIndex >= 8 ) && ( colorIndex < 0x40 ) )
5886 if( colorIndex-8 < d->colorTable.size() )
5887 return d->colorTable[ colorIndex-8 ];
5893 if( colorIndex == 0x40 )
return Color( 0, 0, 0 );
5894 if( colorIndex == 0x41 )
return Color( 255, 255, 255 );
5895 if( colorIndex == 0x7fff )
return Color( 0, 0, 0 );
5902 switch( colorIndex )
5904 case 0: color = Color( 0, 0, 0 );
break;
5905 case 1: color = Color( 255, 255, 255 );
break;
5906 case 2: color = Color( 255, 0, 0 );
break;
5907 case 3: color = Color( 0, 255, 0 );
break;
5908 case 4: color = Color( 0, 0, 255 );
break;
5909 case 5: color = Color( 255, 255, 0 );
break;
5910 case 6: color = Color( 255, 0, 255 );
break;
5911 case 7: color = Color( 0, 255, 255 );
break;
5919Format ExcelReader::convertFormat(
unsigned xfIndex )
5923 if( xfIndex >= d->xfTable.size() )
return format;
5925 XFRecord xf = d->xfTable[ xfIndex ];
5927 UString valueFormat = d->formatsTable[xf.
formatIndex()];
5932 FormatAlignment alignment;
5935 case XFRecord::Left:
5936 alignment.setAlignX( Format::Left );
break;
5937 case XFRecord::Right:
5938 alignment.setAlignX( Format::Right );
break;
5939 case XFRecord::Centered:
5940 alignment.setAlignX( Format::Center );
break;
5947 alignment.setAlignY( Format::Top );
break;
5948 case XFRecord::VCentered:
5949 alignment.setAlignY( Format::Middle );
break;
5950 case XFRecord::Bottom:
5951 alignment.setAlignY( Format::Bottom );
break;
5955 alignment.setWrap( xf.
textWrap() );
5958 FormatBorders borders;
5979 FormatBackground background;
5988void ExcelReader::handleXF(
XFRecord* record )
5990 if( !record )
return;
5992 d->xfTable.push_back( *record );
5996void ExcelReader::mergeTokens( UStringStack* stack,
int count,
const char* mergeString )
5998 if( !stack )
return;
5999 if( !stack->size() )
return;
6000 if( count < 1 )
return;
6002 d->mergedTokens.truncate(0);
6008 if(stack->size() == 0)
break;
6010 d->mergedTokens.prepend((*stack)[ stack->size()-1 ]);
6012 d->mergedTokens.prepend(mergeString);
6013 stack->resize( stack->size()-1 );
6016 stack->push_back( d->mergedTokens );
6019void ExcelReader::mergeTokens( UStringStack* stack,
int count,
const char mergeChar )
6021 if( !stack )
return;
6022 if( !stack->size() )
return;
6023 if( count < 1 )
return;
6025 d->mergedTokens.truncate(0);
6031 if(stack->size() == 0)
break;
6033 d->mergedTokens.prepend((*stack)[ stack->size()-1 ]);
6035 d->mergedTokens.prepend(mergeChar);
6036 stack->resize( stack->size()-1 );
6039 stack->push_back( d->mergedTokens );
6042#ifdef SWINDER_XLS2RAW
6043void dumpStack( std::vector<UString> stack )
6045 std::cout << std::endl;
6046 std::cout <<
"Stack now is: " ;
6048 std::cout <<
"(empty)" ;
6050 for(
unsigned i = 0; i < stack.size(); i++ )
6051 std::cout <<
" " << i <<
": " << stack[i].ascii() << std::endl;
6052 std::cout << std::endl;
6056UString ExcelReader::decodeFormula(
unsigned row,
unsigned col,
6057 const FormulaTokens& tokens,
bool openDocumentFormat )
6061 char argumentSeparator =
',';
6062 if( openDocumentFormat )
6063 argumentSeparator =
';';
6065 for(
unsigned c=0; c < tokens.size(); c++ )
6067 FormulaToken token = tokens[c];
6069#ifdef SWINDER_XLS2RAW
6070 std::cout <<
"Token " << c <<
": ";
6071 std::cout << token.id() <<
" ";
6072 std::cout << token.idAsString() << std::endl;
6075 switch( token.id() )
6077 case FormulaToken::Add:
6078 mergeTokens( &stack, 2,
'+' );
6081 case FormulaToken::Sub:
6082 mergeTokens( &stack, 2,
'-' );
6085 case FormulaToken::Mul:
6086 mergeTokens( &stack, 2,
'*' );
6089 case FormulaToken::Div:
6090 mergeTokens( &stack, 2,
'/' );
6093 case FormulaToken::Power:
6094 mergeTokens( &stack, 2,
'^' );
6097 case FormulaToken::Concat:
6098 mergeTokens( &stack, 2,
'&' );
6101 case FormulaToken::LT:
6102 mergeTokens( &stack, 2,
'<' );
6105 case FormulaToken::LE:
6106 mergeTokens( &stack, 2,
"<=" );
6109 case FormulaToken::EQ:
6110 mergeTokens( &stack, 2,
'=' );
6113 case FormulaToken::GE:
6114 mergeTokens( &stack, 2,
">=" );
6117 case FormulaToken::GT:
6118 mergeTokens( &stack, 2,
'>' );
6121 case FormulaToken::NE:
6122 mergeTokens( &stack, 2,
"<>" );
6125 case FormulaToken::Intersect:
6126 mergeTokens( &stack, 2,
' ' );
6129 case FormulaToken::List:
6130 mergeTokens( &stack, 2,
';' );
6133 case FormulaToken::Range:
6134 mergeTokens( &stack, 2,
';' );
6137 case FormulaToken::UPlus:
6138 if(stack.size() > 1)
6139 stack[ stack.size()-1 ].prepend(
'+');
6142 case FormulaToken::UMinus:
6143 if(stack.size() > 1)
6144 stack[ stack.size()-1 ].prepend(
'-');
6147 case FormulaToken::Percent:
6148 stack[ stack.size()-1 ].append(
'%');
6151 case FormulaToken::Paren:
6153 UString str(stack[ stack.size()-1 ]);
6156 stack[ stack.size()-1 ] = str;
6160 case FormulaToken::MissArg:
6162 stack.push_back( UString(
" ") );
6165 case FormulaToken::String:
6167 UString str(token.value().
asString());
6170 stack.push_back( str );
6174 case FormulaToken::Bool:
6176 stack.push_back( UString(
"TRUE" ) );
6178 stack.push_back( UString(
"FALSE" ) );
6181 case FormulaToken::Integer:
6185 case FormulaToken::Float:
6189 case FormulaToken::Array:
6193 case FormulaToken::Ref:
6195 UString refName(token.ref( row, col ));
6196 if( openDocumentFormat )
6198 refName.prepend(
'[');
6199 refName.append(
']');
6201 stack.push_back( refName );
6205 case FormulaToken::Ref3d:
6207 UString refName(
"#REF");
6208 refName.reserve(32);
6210 unsigned sheetIndex = token.externSheetRef();
6211 if(sheetIndex < d->sheetRefs.size())
6213 UString cellName = token.ref(row, col);
6214 UString sheetName = d->sheetRefs[sheetIndex];
6217 if( openDocumentFormat )
6219 refName = UString(
"[");
6220 refName.append( sheetName );
6222 refName.append(UString(
"."));
6223 refName.append( cellName );
6224 refName.append(UString(
"]"));
6228 refName = sheetName;
6230 refName.
append(UString(
"."));
6231 refName.
append(UString(
"!"));
6232 refName.
append(cellName);
6236 stack.push_back( refName );
6240 case FormulaToken::Area:
6242 UString areaName( token.area( row, col ) );
6243 if( openDocumentFormat )
6245 areaName.prepend(
'[');
6246 areaName.append(
']');
6248 stack.push_back( areaName);
6252 case FormulaToken::Area3d:
6254 UString areaName(
"#REF");
6255 areaName.reserve(32);
6257 unsigned sheetIndex = token.externSheetRef();
6258 if(sheetIndex < d->sheetRefs.size())
6260 UString rangeName = token.area(row, col);
6261 UString sheetName = d->sheetRefs[sheetIndex];
6264 if( openDocumentFormat )
6266 areaName = UString(
"[");
6267 areaName.append( sheetName );
6269 areaName.append(
'.');
6270 areaName.append( rangeName );
6271 areaName.append(
']');
6275 areaName = sheetName;
6278 areaName.append(
'.');
6279 areaName.append(
'!');
6281 areaName.
append(rangeName);
6284 stack.push_back( areaName);
6288 case FormulaToken::Function:
6290 mergeTokens( &stack, token.functionParams(), argumentSeparator );
6293 UString str( token.functionName() ? token.functionName() :
"??" );
6296 str.
append( stack[ stack.size()-1 ] );
6298 stack[ stack.size()-1 ] = str;
6303 case FormulaToken::FunctionVar:
6304 if( token.functionIndex() != 255 )
6306 mergeTokens( &stack, token.functionParams(), argumentSeparator );
6310 if( token.functionIndex() != 255 )
6311 str = token.functionName() ? token.functionName() :
"??";
6314 str.
append( stack[ stack.size()-1 ] );
6316 stack[ stack.size()-1 ] = str;
6321 unsigned count = token.functionParams()-1;
6322 mergeTokens( &stack, count, argumentSeparator );
6327 str.
append( stack[ stack.size()-1 ] );
6329 stack[ stack.size()-1 ] = str;
6334 case FormulaToken::Attr:
6335 if( token.attr() & 0x10 )
6337 mergeTokens( &stack, 1, argumentSeparator );
6340 UString str(
"SUM" );
6342 str.
append( stack[ stack.size()-1 ] );
6344 stack[ stack.size()-1 ] = str;
6349 case FormulaToken::NameX:
6350 if( token.nameIndex() > 0 )
6351 if( token.nameIndex() <= d->nameTable.size() )
6352 stack.push_back( d->nameTable[ token.nameIndex()-1 ] );
6355 case FormulaToken::Matrix:
6357 int row = token.refRow();
6358 int col = token.refColumn();
6363 case FormulaToken::NatFormula:
6364 case FormulaToken::Sheet:
6365 case FormulaToken::EndSheet:
6366 case FormulaToken::ErrorCode:
6367 case FormulaToken::Name:
6368 case FormulaToken::MemArea:
6369 case FormulaToken::MemErr:
6370 case FormulaToken::MemNoMem:
6371 case FormulaToken::MemFunc:
6372 case FormulaToken::RefErr:
6373 case FormulaToken::AreaErr:
6374 case FormulaToken::RefN:
6375 case FormulaToken::AreaN:
6376 case FormulaToken::MemAreaN:
6377 case FormulaToken::MemNoMemN:
6378 case FormulaToken::RefErr3d:
6379 case FormulaToken::AreaErr3d:
6382 stack.push_back( UString(
"UnknownToken") );
6387#ifdef SWINDER_XLS2RAW
6394 for(
unsigned i = 0; i < stack.size(); i++ )
6395 result.
append( stack[i] );
6397#ifdef SWINDER_XLS2RAW
6398 std::cout <<
"FORMULA Result: " << result << std::endl;
6404#ifdef SWINDER_XLS2RAW
6408int main(
int argc,
char ** argv )
6412 std::cout <<
"Usage: xls2raw filename" << std::endl;
6416 char* filename = argv[1];
6417 std::cout <<
"Checking " << filename << std::endl;
6419 Workbook* workbook =
new Workbook();
6420 ExcelReader* reader =
new ExcelReader();
6421 reader->load( workbook, filename );
Beginning of file/set of records.
static const unsigned int id
Static ID of the BOF record.
const char * typeAsString() const
Returns BOF type as string, something like "Worksheet".
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual ~BOFRecord()
Destroys the record.
unsigned type() const
Returns type of the BOF record, like Workbook, Chart, and so on.
BOFRecord()
Creates a new BOF record.
const char * versionAsString() const
Returns the version as string, something like "Excel97".
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned version() const
Returns the version, like Excel95, Excel97, and so on.
BackupRecord()
Creates a new Backup record.
~BackupRecord()
Destroy the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
bool backup() const
Returns true if a backup is made when saving the file.
void setBackup(bool r)
If r is true, a backup will be made when saving the file.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
BlankRecord()
Creates a new Blank record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
Boolean value or error code.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
BoolErrRecord()
Creates a new BoolErr record.
static const unsigned int id
Static ID of the BoolErr record.
Value value() const
Returns value of the cell, could be either boolean or error.
virtual ~BoolErrRecord()
Destroys the BoolErr record.
~BottomMarginRecord()
Destroy the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
double bottomMargin() const
Gets the bottom margin (in inches).
void setBottomMargin(double m)
Sets the new bottom margin (in inches).
BottomMarginRecord()
Creates a new BottomMargin record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned type() const
Returns the type of the BoundSheet.
void setBofPosition(unsigned pos)
Sets the position of the BOF record associated with this BoundSheet.
void setSheetName(const UString &name)
Sets the name of the sheet.
bool visible() const
Returns true if the sheet is visible.
virtual const char * name()
Returns the name of the record.
virtual ~BoundSheetRecord()
Destroys the BoundSheet record.
UString sheetName() const
Returns the name of the sheet.
BoundSheetRecord()
Creates a new BoundSheet record.
const char * typeAsString() const
Returns the type of the BoundSheet as string.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
void setVisible(bool visible)
Sets the visibility of the sheet.
void setType(unsigned type)
Sets the type of the BoundSheet.
unsigned bofPosition() const
Returns the position of the BOF record associated with this BoundSheet.
Automatic recalculation mode.
~CalcModeRecord()
Destroy the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
void setAutoCalc(bool r)
If r is true, formulas calculation will be performed automatically.
bool autoCalc() const
Returns true if formulas calculation is performed automatically.
CalcModeRecord()
Creates a new CalcMode record.
virtual void setXfIndex(unsigned i)
Sets the XF index for formatting of the cell.
virtual void setColumn(unsigned c)
Sets the column associated with the cell information.
virtual unsigned xfIndex() const
Returns the XF index for formatting of the cell.
virtual void setRow(unsigned r)
Sets the row associated with the cell information.
virtual unsigned row() const
Returns the row associated with the cell information.
virtual unsigned column() const
Returns the column associated with the cell information.
CellInfo()
Creates a new cell information.
virtual ~CellInfo()
Destroys the cell information.
Columns width and format.
unsigned outlineLevel() const
Returns the outline level of the columns.
unsigned xfIndex() const
Returns the XF index for the formatting of the column(s).
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual ~ColInfoRecord()
Destroys the record.
void setOutlineLevel(unsigned l)
Sets the outline level of the columns.
ColInfoRecord()
Creates a new ColInfo record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
void setXfIndex(unsigned i)
Sets the XF index for the formatting of the column(s).
void setHidden(bool h)
Sets whether columns should be hidden or visible.
bool collapsed() const
Returns true if the columns should be collapsed.
bool hidden() const
Returns true if the columns should be hidden, i.e not visible.
void setWidth(unsigned w)
Sets the width of the column(s), specified in 1/256 of a character width.
unsigned width() const
Returns the width of the column(s), specified in 1/256 of a character width.
void setCollapsed(bool c)
Sets whether columns should be collapsed or not.
Provides color based on RGB values.
virtual unsigned lastColumn() const
Returns the last column associated with the span information.
virtual void setLastColumn(unsigned c)
Sets the last column associated with the span information.
virtual unsigned firstColumn() const
Returns the first column associated with the span information.
virtual ~ColumnSpanInfo()
Destroys the column span information.
ColumnSpanInfo()
Creates a new column span information.
virtual void setFirstColumn(unsigned c)
Sets the first column associated with the span information.
~DateModeRecord()
Destroy the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
DateModeRecord()
Creates a new DateMode record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
bool base1904() const
Returns true if the reference date is 1st of January, 1904 or false if the reference date is 31st of ...
void setBase1904(bool r)
If r is true, sets the reference date to 1st of January, 1904.
void setFirstColumn(unsigned r)
Sets index to the first used column.
void setFirstRow(unsigned r)
Sets index to the first used row.
DimensionRecord()
Creates a new Dimension record.
unsigned firstColumn() const
Returns index to the first used column.
unsigned lastColumn() const
Returns index to the last used column.
void setLastColumn(unsigned r)
Sets index to the last used column.
unsigned lastRow() const
Returns index to the last used row.
unsigned firstRow() const
Returns index to the first used row.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
void setLastRow(unsigned r)
Sets index to the last used row.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
~DimensionRecord()
Destroys the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual ~EOFRecord()
Destroy the record.
EOFRecord()
Creates a new EOF record.
bool italic() const
Returns true if italic has been set.
void setColorIndex(unsigned c)
Sets the index of the color of the font.
void setEscapement(unsigned s)
Sets the superscript or subscript.
FontRecord & operator=(const FontRecord &fr)
Assigns from another Font record.
virtual ~FontRecord()
Destroy the record.
void setItalic(bool i)
If i is true, italic is set on; otherwise italic is set off.
UString fontName() const
Returns the name of font, e.g "Arial".
bool strikeout() const
Returns true if strikeout has been set.
void setFontName(const UString &fn)
Sets the name of the font.
void setBoldness(unsigned b)
Sets the boldness of the font.
void setStrikeout(bool s)
If s is true, strikeout is set on; otherwise strikeout is set off.
void setUnderline(unsigned u)
Sets the underline style of the font.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
FontRecord()
Creates a new Font record.
unsigned underline() const
Returns the underline style of the font.
unsigned escapement() const
Returns Font::Superscript if superscript is set, or Font::Subscript if subscript is set,...
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned colorIndex() const
Returns index of the color of the font.
unsigned boldness() const
Returns the boldness of the font.
Class LabelRecord represents a cell that contains a string.
void setLabel(const UString &l)
Sets the label string.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
LabelRecord()
Creates a new Label record.
UString label() const
Returns the label string.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
virtual ~LabelRecord()
Destroys the record.
Class LabelSSTRecord represents a cell that contains a string.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned sstIndex() const
Returns the SST index.
virtual ~LabelSSTRecord()
Destroys the record.
LabelSSTRecord()
Creates a new LabelSST record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
Class LeftMarginRecord holds information about left margin.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
~LeftMarginRecord()
Destroy the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
double leftMargin() const
Gets the left margin (in inches).
void setLeftMargin(double m)
Sets the new left margin (in inches).
LeftMarginRecord()
Creates a new LeftMargin record.
Class MergedCellsRecord represents MergedCells record, which contains a list of all merged cells in t...
unsigned firstColumn(unsigned i) const
Returns the index to first column in the i-th position in the list.
virtual ~MergedCellsRecord()
Destroys the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned count() const
Returns the total number of merged cells in the list.
unsigned firstRow(unsigned i) const
Returns the index to first row in the i-th position in the list.
unsigned lastColumn(unsigned i) const
Returns the index to last column in the i-th position in the list.
unsigned lastRow(unsigned i) const
Returns the index to last row in the i-th position in the list.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
MergedCellsRecord()
Creates a new MergedCells record.
Class MulBlankRecord represents a cell range containing blank cells.
unsigned xfIndex(unsigned i) const
Returns XF index of ith column.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
MulBlankRecord()
Creates a new MulBlank record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual ~MulBlankRecord()
Destroys the record.
Class MulRKRecord represents a cell range containing RK value cells.
MulRKRecord()
Creates a new MulRK record.
virtual ~MulRKRecord()
Destroys the record.
double asFloat(unsigned i) const
Returns the floating-point value specified by the record.
bool isInteger(unsigned i) const
Returns true if the record holds an integer value.
int asInteger(unsigned i) const
Returns the integer value specified by the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
unsigned xfIndex(unsigned i) const
Returns XF index of ith column.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
Class NumberRecord represents a cell that contains a floating point value.
double number() const
Returns the floating-point value specified by the record.
void setNumber(double f)
Sets the floating-point value specified by the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
NumberRecord()
Creates a new Number record.
virtual ~NumberRecord()
Destroys the record.
Class PaletteRecord lists colors.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
unsigned count() const
Returns the number of colors in the palette.
PaletteRecord()
Creates a new Palette record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
~PaletteRecord()
Destroy the record.
Color color(unsigned i) const
Gets the n-th color.
Class RKRecord represents a cell that contains an RK value, i.e encoded integer or floating-point val...
bool isInteger() const
Returns true if the record holds an integer value.
bool isFloat() const
Returns true if the record holds a floating-point value.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
RKRecord()
Creates a new RK record.
virtual ~RKRecord()
Destroys the record.
void setFloat(double f)
Sets the floating-point value to be specified by the record.
void setInteger(int i)
Sets the integer value to be specified by the record.
int asInteger() const
Returns the integer value specified by the record.
double asFloat() const
Returns the floating-point value specified by the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
Class RStringRecord represents a cell that contains rich-text string.
UString label() const
Returns the label string.
void setLabel(const UString &l)
Sets the label string.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
RStringRecord()
Creates a new Label record.
virtual ~RStringRecord()
Destroys the record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
Class Record represents a base class for all other type record, hence do not use this class in real l...
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
static const unsigned int id
Static ID of the record.
unsigned position() const
Gets the position of this record in the OLE stream.
static Record * create(unsigned type)
Record factory, create a new record of specified type.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
void setPosition(unsigned pos)
Sets the position of the record in the OLE stream.
virtual ~Record()
Destroys the record.
Record()
Creates a new generic record.
Class RightMarginRecord holds information about right margin.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
double rightMargin() const
Gets the right margin (in inches).
void setRightMargin(double m)
Sets the new right margin (in inches).
RightMarginRecord()
Creates a new RightMargin record.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
~RightMarginRecord()
Destroy the record.
Class RowRecord represents Row record, which provides information (such as row height and formatting)...
unsigned row() const
Returns the index of the row.
virtual ~RowRecord()
Destroys the record.
void setRow(unsigned r)
Sets the index of the row.
unsigned height() const
Returns the height of the row, specified in twips (1/20 pt).
void setXfIndex(unsigned i)
Sets the XF index for the formatting of the cells.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
bool hidden() const
Returns true if the row should be hidden, i.e not visible.
void setHeight(unsigned h)
Sets the height of the row, specified in twips (1/20 pt).
RowRecord()
Creates a new Row record.
void setHidden(bool h)
Sets whether row should be hidden or visible.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
unsigned xfIndex() const
Returns the XF index for the formatting of the cells.
Class SSTRecord represents SST record, which holds the shared string table of the workbook.
SSTRecord()
Creates a new SST record.
virtual ~SSTRecord()
Destroys the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
unsigned count() const
Returns the number of available string in this string table.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
UString stringAt(unsigned index) const
Returns the string at specified index.
Class String represents a string record, which holds the value of calculation if a formula returns a ...
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
UString ustring() const
Returns the string (in Unicode).
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
StringRecord()
Creates a new string record.
virtual ~StringRecord()
Destroys the record.
Value value() const
Returns the string as a value.
Class SupbookRecord stores references to external workbook.
ReferenceType referenceType() const
Returns the type of the reference.
SupbookRecord()
Creates a new Supbook record.
void setReferenceType(ReferenceType type)
Sets the type of the reference.
~SupbookRecord()
Destroy the record.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
Class TopMarginRecord holds information about top margin.
void setTopMargin(double m)
Sets the new top margin (in inches).
double topMargin() const
Gets the top margin (in inches).
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
TopMarginRecord()
Creates a new TopMargin record.
~TopMarginRecord()
Destroy the record.
UString & prepend(const UString &)
Prepend another string.
int find(const UString &f, int pos=0) const
static UString number(int i)
Constructs a string from an int.
char * ascii() const
Convert the Unicode string to plain ASCII chars chopping of any higher bytes.
static UString null
Static instance of a null string.
UString substr(int pos=0, int len=-1) const
const UChar * data() const
void reserve(int r)
Reserves room for the string, useful to speed up append().
UString & append(const UString &)
Append another string.
Provides a wrapper for cell value.
static const Value & empty()
Returns constant reference to empty value.
static const Value & errorDIV0()
Returns constant reference to DIV/0!
static const Value & errorNULL()
Returns constant reference to NULL!
static const Value & errorNAME()
Returns constant reference to NAME?
static const Value & errorNUM()
Returns constant reference to NUM!
static const Value & errorREF()
Returns constant reference to REF!
double asFloat() const
Returns the floating-point value of this value.
UString asString() const
Returns the string value of this value.
bool isString() const
Returns true if the type of this value is string.
static const Value & errorVALUE()
Returns constant reference to VALUE!
bool asBoolean() const
Returns the boolean value of this value.
static const Value & errorNA()
Returns constant reference to N/A error.
int asInteger() const
Returns the integer value of this value.
Class XFRecord holds information of XF (eXtended Format) which specifies many kind of properties of a...
unsigned indentLevel() const
Returns indent level.
void setPatternForeColor(unsigned color)
Sets the fill foreground color.
bool formulaHidden() const
Returns true if the formula of the cells using this format should be hidden from user.
void setRotationAngle(unsigned angle)
Sets the rotation angle of the text.
virtual void dump(std::ostream &out) const
Dumps record information to output stream.
unsigned topBorderColor() const
Returns the color for top border.
unsigned horizontalAlignment() const
Gets the horizontal alignment, e.g Left.
unsigned leftBorderStyle() const
Returns the line style for left border.
void setTopBorderColor(unsigned color)
Sets the color for top border.
XFRecord & operator=(const XFRecord &xf)
Assigns from another XF record.
void setLeftBorderColor(unsigned color)
Sets the color for left border.
const char * horizontalAlignmentAsString() const
Returns human-readable string representation of the horizontal alignment.
void setFormatIndex(unsigned fi)
Sets the index of the number format for use in this XFormat.
void setPatternBackColor(unsigned color)
Sets the fill background color.
unsigned parentStyle() const
Returns the index of the parent stlye of this format.
unsigned fontIndex() const
Gets the index of the font for use in this XFormat.
unsigned rightBorderStyle() const
Returns the line style for right border.
void setShrinkContent(bool s)
Sets whether content should be shrunk to fit into cell.
bool textWrap() const
Returns true if text is wrapped at right border.
void setLocked(bool l)
Sets whether the cells using this format should be locked or not.
void setTextWrap(bool wrap)
Sets whether text should be wrapped at right border.
void setFormulaHidden(bool f)
Sets whether the formula of the cells using this format should be hidden or should be visible.
unsigned patternBackColor() const
Returns the fill background color.
void setVerticalAlignment(unsigned va)
Sets the vertical alignment, e.g Top.
unsigned rightBorderColor() const
Returns the color for right border.
void setStackedLetters(bool stacked)
Sets whether the letters for text should be stacked top-to-bottom.
void setDiagonalTopLeft(bool d)
Sets whether there should be a diagonal line from top left to right bottom.
unsigned patternForeColor() const
Returns the fill foreground color.
unsigned verticalAlignment() const
Gets the vertical alignment, e.g Bottom.
bool stackedLetters() const
Returns true if the letters for text are not rotated, but instead stacked top-to-bottom.
~XFRecord()
Destroy the record.
void setParentStyle(unsigned ps)
Sets the index of the parent stlye of this format.
unsigned bottomBorderStyle() const
Returns the line style for bottom border.
bool diagonalBottomLeft() const
Returns true if there is a diagonal line from bottom left to right top.
void setRightBorderStyle(unsigned style)
Sets the line style for right border.
unsigned diagonalColor() const
Returns the color for diagonal line.
unsigned diagonalStyle() const
Returns the diagonal line style.
const char * verticalAlignmentAsString() const
Returns human-readable string representation of the vertical alignment.
void setLeftBorderStyle(unsigned style)
Sets the line style for left border.
void setBottomBorderStyle(unsigned style)
Sets the line style for bottom border.
unsigned bottomBorderColor() const
Returns the color for bottom border.
void setDiagonalColor(unsigned color)
Sets the color for diagonal line.
unsigned fillPattern() const
Returns fill pattern.
void setFontIndex(unsigned fi)
Sets the index of the font for use in this XFormat.
void setIndentLevel(unsigned i)
Sets indent level.
unsigned leftBorderColor() const
Returns the color for left border.
unsigned formatIndex() const
Gets the index of the number format for use in this XFormat.
void setDiagonalStyle(unsigned style)
Sets the line style for diagonal line.
void setRightBorderColor(unsigned color)
Sets the color for right border.
unsigned topBorderStyle() const
Returns the line style for top border.
XFRecord()
Creates a new XF record.
unsigned rotationAngle() const
Returns the rotation angle of the text.
virtual void setData(unsigned size, const unsigned char *data)
Sets the data for this record.
bool shrinkContent() const
Returns true if content should be shrunk to fit into cell.
void setFillPattern(unsigned pattern)
Sets fill pattern.
void setBottomBorderColor(unsigned color)
Sets the color for bottom border.
void setHorizontalAlignment(unsigned ha)
Sets the horizontal alignment, e.g Left.
void setTopBorderStyle(unsigned style)
Sets the line style for top border.
void setDiagonalBottomLeft(bool d)
Sets whether there should be a diagonal line from bottom left to right top.
bool locked() const
Returns true if the cells using this format should be locked.
bool diagonalTopLeft() const
Returns true if there is a diagonal line from top left to right bottom.