Diffstat (limited to 'noncore/apps/opie-sheet/Excel.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/apps/opie-sheet/Excel.cpp | 1664 |
1 files changed, 1664 insertions, 0 deletions
diff --git a/noncore/apps/opie-sheet/Excel.cpp b/noncore/apps/opie-sheet/Excel.cpp new file mode 100644 index 0000000..225c3e1 --- a/dev/null +++ b/noncore/apps/opie-sheet/Excel.cpp | |||
@@ -0,0 +1,1664 @@ | |||
1 | |||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <math.h> | ||
6 | #include <time.h> | ||
7 | #include <sys/types.h> | ||
8 | #include <strings.h> | ||
9 | #include <qstring.h> | ||
10 | #include <qlist.h> | ||
11 | #include <qarray.h> | ||
12 | #include "Excel.h" | ||
13 | |||
14 | static xfrecord formatter[] = { | ||
15 | { 0xe , DATEFORMAT, "%m/%d/%y"}, | ||
16 | { 0xf , DATEFORMAT, "%d-%b-%y"}, | ||
17 | { 0x10, DATEFORMAT, "%d-%b"}, | ||
18 | { 0x11, DATEFORMAT, "%b-%y"}, | ||
19 | { 0x12, DATEFORMAT, "%I:%M %p"}, | ||
20 | { 0x13, DATEFORMAT, "%I:%M:%S %p"}, | ||
21 | { 0x14, DATEFORMAT, "%H:%M"}, | ||
22 | { 0x15, DATEFORMAT, "%H:%M:%S"}, | ||
23 | { 0x16, DATEFORMAT, "%m/%d/%y %H:%M"}, | ||
24 | { 0x2d, DATEFORMAT, "%M:%S"}, | ||
25 | { 0x2e, DATEFORMAT, "%H:%M:%S"}, | ||
26 | { 0x2f, DATEFORMAT, "%M:%S"}, | ||
27 | { 0xa5, DATEFORMAT, "%m/%d/%y %I:%M %p"}, | ||
28 | { 0x1 , NUMBERFORMAT, "%.0f"}, | ||
29 | { 0x2 , NUMBERFORMAT, "%.2f"}, | ||
30 | { 0x3 , NUMBERFORMAT, "#,##%.0f"}, | ||
31 | { 0x4 , NUMBERFORMAT, "#,##%.2f"}, | ||
32 | { 0x5 , NUMBERFORMAT, "$#,##%.0f"}, | ||
33 | { 0x6 , NUMBERFORMAT, "$#,##%.0f"}, | ||
34 | { 0x7 , NUMBERFORMAT, "$#,##%.2f"}, | ||
35 | { 0x8 , NUMBERFORMAT, "$#,##%.2f"}, | ||
36 | { 0x9 , NUMBERFORMAT, "%.0f%%"}, | ||
37 | { 0xa , NUMBERFORMAT, "%.2f%%"}, | ||
38 | { 0xb , NUMBERFORMAT, "%e"}, | ||
39 | { 0x25, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, | ||
40 | { 0x26, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, | ||
41 | { 0x27, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, | ||
42 | { 0x28, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, | ||
43 | { 0x29, NUMBERFORMAT, "#,##%.0f;(#,##0)"}, | ||
44 | { 0x2a, NUMBERFORMAT, "$#,##%.0f;($#,##0)"}, | ||
45 | { 0x2b, NUMBERFORMAT, "#,##%.2f;(#,##0.00)"}, | ||
46 | { 0x2c, NUMBERFORMAT, "$#,##%.2f;($#,##0.00)"}, | ||
47 | { 0x30, NUMBERFORMAT, "##0.0E0"}, | ||
48 | { 0, 0, ""} | ||
49 | }; | ||
50 | |||
51 | |||
52 | |||
53 | int ExcelBook::Integer2Byte(int b1, int b2) | ||
54 | { | ||
55 | int i1 = b1 & 0xff; | ||
56 | int i2 = b2 & 0xff; | ||
57 | int val = i2 << 8 | i1; | ||
58 | return val; | ||
59 | }; | ||
60 | |||
61 | int ExcelBook::Integer4Byte(int b1,int b2,int b3,int b4) | ||
62 | { | ||
63 | int i1 = Integer2Byte(b1, b2); | ||
64 | int i2 = Integer2Byte(b3, b4); | ||
65 | int val = i2 << 16 | i1; | ||
66 | return val; | ||
67 | }; | ||
68 | |||
69 | int ExcelBook::Integer2ByteFile(FILE *f) { | ||
70 | int i1, i2; | ||
71 | i1 = fgetc(f); | ||
72 | i2 = fgetc(f); | ||
73 | return Integer2Byte(i1,i2); | ||
74 | }; | ||
75 | |||
76 | float ExcelBook::Float4Byte(int b1, int b2, int b3, int b4) | ||
77 | { | ||
78 | int i; | ||
79 | float f; | ||
80 | unsigned char *ieee; | ||
81 | ieee = (unsigned char *) &f; | ||
82 | for (i = 0; i < 4; i++) ieee[i] = 0; | ||
83 | ieee[0] = ((int)b4) & 0xff; | ||
84 | ieee[1] = ((int)b3) & 0xff; | ||
85 | ieee[2] = ((int)b2) & 0xff; | ||
86 | ieee[3] = ((int)b1) & 0xff; | ||
87 | return f; | ||
88 | }; | ||
89 | |||
90 | double ExcelBook::Double4Byte(int b1, int b2, int b3, int b4) | ||
91 | { | ||
92 | long int rk; | ||
93 | double value; | ||
94 | |||
95 | rk=Integer4Byte(b1,b2,b3,b4); | ||
96 | //printf("Double4Bytes:%d,%d,%d,%d\r\n",b1,b2,b3,b4); | ||
97 | if ( (rk & 0x02) != 0) | ||
98 | { | ||
99 | long int intval = rk >> 2; //drops the 2 bits | ||
100 | printf("Double4Byte:intval=%d, rk=%d, rk>>2=%d\r\n",intval,rk,rk>>2); | ||
101 | value = (double) intval; | ||
102 | printf("Double4Byte: VALUEINT=%f\r\n",value); | ||
103 | if ( (rk & 0x01) != 0) | ||
104 | { | ||
105 | value /= 100.0; | ||
106 | }; | ||
107 | return value; | ||
108 | }else | ||
109 | { | ||
110 | |||
111 | union { double d; unsigned long int b[2]; } dbl_byte; | ||
112 | unsigned long int valbits = (rk & 0xfffffffc); | ||
113 | #if defined(__arm__) && !defined(__vfp__) | ||
114 | dbl_byte.b[0]=valbits; | ||
115 | dbl_byte.b[1]=0; | ||
116 | #else | ||
117 | dbl_byte.b[0]=0; | ||
118 | dbl_byte.b[1]=valbits; | ||
119 | #endif | ||
120 | printf("dbl_byte.b[0]=%d,dbl_byte.b[1]=%d\r\n",dbl_byte.b[0],dbl_byte.b[1]); | ||
121 | value=dbl_byte.d; | ||
122 | printf("Double4Byte: VALUE=%f\r\n",value); | ||
123 | |||
124 | if ( (rk & 0x01) != 0) | ||
125 | { | ||
126 | value /= 100.0; | ||
127 | }; | ||
128 | return value; | ||
129 | }; | ||
130 | }; | ||
131 | |||
132 | void ExcelBook::DetectEndian(void) | ||
133 | { | ||
134 | int end; | ||
135 | long i = 0x44332211; | ||
136 | unsigned char* a = (unsigned char*) &i; | ||
137 | end = (*a != 0x11); | ||
138 | if (end == 1) { | ||
139 | endian = BIG_ENDIAN; | ||
140 | printf("BIGENDIAN!\r\n"); | ||
141 | } else { | ||
142 | endian = LITTLE_ENDIAN; | ||
143 | printf("LITTLEENDIAN!\r\n"); | ||
144 | } | ||
145 | }; | ||
146 | |||
147 | double ExcelBook::Double8Byte(int b1, int b2, int b3, int b4, int b5, int b6, int b7, int b8) | ||
148 | { | ||
149 | int i; | ||
150 | double d; | ||
151 | unsigned char *ieee; | ||
152 | ieee = (unsigned char *)&d; | ||
153 | for (i = 0; i < 8; i++) ieee[i] = 0; | ||
154 | if (endian == BIG_ENDIAN) { | ||
155 | ieee[0] = ((int)b8) & 0xff;ieee[1] = ((int)b7) & 0xff; | ||
156 | ieee[2] = ((int)b6) & 0xff;ieee[3] = ((int)b5) & 0xff; | ||
157 | ieee[4] = ((int)b4) & 0xff;ieee[5] = ((int)b3) & 0xff; | ||
158 | ieee[6] = ((int)b2) & 0xff;ieee[7] = ((int)b1) & 0xff; | ||
159 | } else { | ||
160 | ieee[0] = ((int)b1) & 0xff;ieee[1] = ((int)b2) & 0xff; | ||
161 | ieee[2] = ((int)b3) & 0xff;ieee[3] = ((int)b4) & 0xff; | ||
162 | ieee[4] = ((int)b5) & 0xff;ieee[5] = ((int)b6) & 0xff; | ||
163 | ieee[6] = ((int)b7) & 0xff;ieee[7] = ((int)b8) & 0xff; | ||
164 | } | ||
165 | return d; | ||
166 | }; | ||
167 | |||
168 | bool ExcelBook::OpenFile(char *Filename) | ||
169 | { | ||
170 | printf("Opening excel file!\r\n"); | ||
171 | File= fopen(Filename, "r"); | ||
172 | Position=0; // first byte index in file | ||
173 | XFRecords.resize(0); | ||
174 | SharedStrings.resize(0); | ||
175 | Names.resize(0); | ||
176 | Sheets.resize(0); | ||
177 | if(File==NULL) return false; | ||
178 | printf("Opened excel file!\r\n"); | ||
179 | return true; | ||
180 | }; | ||
181 | |||
182 | bool ExcelBook::CloseFile(void) | ||
183 | { | ||
184 | int w1; | ||
185 | for(w1=0;w1<(int)XFRecords.count();w1++) | ||
186 | { | ||
187 | if(XFRecords[w1]!=NULL) {delete XFRecords[w1];XFRecords[w1]=NULL;}; | ||
188 | }; | ||
189 | for(w1=0;w1<(int)SharedStrings.count();w1++) | ||
190 | { | ||
191 | if(SharedStrings[w1]!=NULL) {delete SharedStrings[w1];SharedStrings[w1]=NULL;}; | ||
192 | }; | ||
193 | for(w1=0;w1<(int)Names.count();w1++) | ||
194 | { | ||
195 | if(Names[w1]!=NULL) {delete Names[w1];Names[w1]=NULL;}; | ||
196 | }; | ||
197 | for(w1=0;w1<(int)Sheets.count();w1++) | ||
198 | { | ||
199 | if(Sheets[w1]!=NULL) {delete Sheets[w1];Sheets[w1]=NULL;}; | ||
200 | }; | ||
201 | XFRecords.resize(0); | ||
202 | SharedStrings.resize(0); | ||
203 | Names.resize(0); | ||
204 | Sheets.resize(0); | ||
205 | fclose(File); | ||
206 | printf("closed excel file!\r\n"); | ||
207 | if(File==NULL) return true; | ||
208 | return false; | ||
209 | }; | ||
210 | |||
211 | void ExcelBook::SeekPosition(int pos) | ||
212 | { | ||
213 | if(!feof(File)) | ||
214 | { | ||
215 | Position=pos; | ||
216 | //printf("SeekPosition:Pos:%d\r\n",Position); | ||
217 | fseek(File,pos,SEEK_SET); | ||
218 | }; | ||
219 | }; | ||
220 | |||
221 | void ExcelBook::SeekSkip(int pos) | ||
222 | { | ||
223 | if(!feof(File)) | ||
224 | { | ||
225 | Position=Position+pos; | ||
226 | //printf("SeekSkip:Pos:%d\r\n",Position); | ||
227 | fseek(File, Position, SEEK_SET); | ||
228 | }; | ||
229 | }; | ||
230 | |||
231 | int ExcelBook::FileEOF(void) | ||
232 | { | ||
233 | if(File!=NULL) return(feof(File)); else return 0; | ||
234 | //EOF is defined in stdlib as -1 | ||
235 | }; | ||
236 | |||
237 | int ExcelBook::Get2Bytes(void) | ||
238 | { | ||
239 | int i1,i2; | ||
240 | i1=0; i2=0; | ||
241 | if (!feof(File)) | ||
242 | { | ||
243 | i1=fgetc(File); | ||
244 | Position++; | ||
245 | }; | ||
246 | if (!feof(File)) | ||
247 | { | ||
248 | i2=fgetc(File); | ||
249 | Position++; | ||
250 | }; | ||
251 | return Integer2Byte(i1,i2); | ||
252 | }; | ||
253 | |||
254 | char* ExcelBook::Read(int pos, int length) | ||
255 | { | ||
256 | int i; | ||
257 | char *data; | ||
258 | data= new char[length]; | ||
259 | SeekPosition(pos); | ||
260 | for(i=0; i<length; i++) | ||
261 | { | ||
262 | if(!feof(File)) data[i]=fgetc(File); | ||
263 | }; | ||
264 | Position= Position+length; | ||
265 | return data; | ||
266 | }; | ||
267 | |||
268 | QString ExcelBook::ReadUnicodeChar(int pos, int length) | ||
269 | { | ||
270 | int i; | ||
271 | QString data; | ||
272 | int i1=' ',i2=' ',ii; | ||
273 | SeekPosition(pos); | ||
274 | for(i=0; i<length; i++) | ||
275 | { | ||
276 | if(!feof(File)) i1=fgetc(File); | ||
277 | if(!feof(File)) i2=fgetc(File); | ||
278 | ii=Integer2Byte(i1,i2); | ||
279 | data.append(ii); | ||
280 | Position+=2; | ||
281 | }; | ||
282 | return data; | ||
283 | }; | ||
284 | |||
285 | QString* ExcelBook::GetString(int num) | ||
286 | { | ||
287 | if(num>=0 && num<(int)SharedStrings.count()) | ||
288 | { | ||
289 | return SharedStrings[num]; | ||
290 | }; | ||
291 | return new QString(""); | ||
292 | }; | ||
293 | |||
294 | int ExcelBook::SeekBOF(void) | ||
295 | { | ||
296 | int opcode,version,streamtype,length,ret=0; | ||
297 | char *data; | ||
298 | while(!feof(File)) | ||
299 | { | ||
300 | opcode=Get2Bytes(); | ||
301 | if(opcode==XL_BOF) | ||
302 | { | ||
303 | length=Get2Bytes(); | ||
304 | data=Read(Position,length); | ||
305 | version=Integer2Byte(data[0], data[1]); | ||
306 | streamtype=Integer2Byte(data[2], data[3]); | ||
307 | printf("SEEKBOF:opcode=XLBOF, %d ,version %d\r\n",Position,version); | ||
308 | delete data; data=NULL; | ||
309 | if (version==BIFF8) ret=8; | ||
310 | else if(version==BIFF7) ret=7; | ||
311 | printf("SEEKBOF:versionBIFF%d\r\n",ret); | ||
312 | if(streamtype==WBKGLOBAL) return ret *2; | ||
313 | else if(streamtype==WRKSHEET) return ret *1; | ||
314 | return 1; | ||
315 | }; | ||
316 | }; | ||
317 | return 0; | ||
318 | }; | ||
319 | |||
320 | ExcelBREC* ExcelBook::GetBREC(void) | ||
321 | { | ||
322 | ExcelBREC* rec; | ||
323 | rec= new ExcelBREC; | ||
324 | if(FileEOF()) return NULL; | ||
325 | rec->data=NULL; | ||
326 | rec->code=Get2Bytes(); | ||
327 | rec->length=Get2Bytes(); | ||
328 | rec->position=Position; | ||
329 | SeekSkip(rec->length); | ||
330 | return rec; | ||
331 | }; | ||
332 | |||
333 | ExcelBREC* ExcelBook::PeekBREC(void) | ||
334 | { | ||
335 | int oldpos; | ||
336 | ExcelBREC* NextRec; | ||
337 | oldpos=Position; | ||
338 | NextRec=GetBREC(); | ||
339 | SeekPosition(oldpos); | ||
340 | return NextRec; | ||
341 | }; | ||
342 | |||
343 | char* ExcelBook::GetDataOfBREC(ExcelBREC* record) | ||
344 | { | ||
345 | if(record->data==NULL) | ||
346 | { | ||
347 | ConvertCharToArray(record,Read(record->position,record->length),record->length); | ||
348 | }; | ||
349 | return record->data;//new? | ||
350 | }; | ||
351 | |||
352 | void ExcelBook::ConvertCharToArray(ExcelBREC* record, char* chars, int length) | ||
353 | { | ||
354 | record->data=new char[length]; | ||
355 | for(int w1=0;w1<=length-1;w1++) | ||
356 | record->data[w1]=chars[w1]; | ||
357 | }; | ||
358 | |||
359 | |||
360 | bool ExcelSheet::InitCells() | ||
361 | { | ||
362 | int r; | ||
363 | Cells.resize(rows * cols + cols+1); | ||
364 | if(Cells.count()==0) return false; | ||
365 | for(r=0;r < Cells.count();r++) | ||
366 | { | ||
367 | Cells[r]=NULL; | ||
368 | }; | ||
369 | return true; | ||
370 | }; | ||
371 | |||
372 | void ExcelSheet::Set(int row, int col, ExcelCell* cell) | ||
373 | { | ||
374 | if(cell!=NULL&&(row*cols+col)<Cells.count()) | ||
375 | { | ||
376 | Cells[row*cols+col]=cell; | ||
377 | }; | ||
378 | }; | ||
379 | |||
380 | ExcelCell* ExcelSheet::Get(int row, int col) | ||
381 | { | ||
382 | ExcelCell* cell; | ||
383 | cell=Cells[row*cols+col]; | ||
384 | if(cell==NULL) return NULL; | ||
385 | return cell; | ||
386 | }; | ||
387 | |||
388 | int ExcelBook::SheetHandleRecord(ExcelSheet* sheet, ExcelBREC* record) | ||
389 | { | ||
390 | char* data=NULL; | ||
391 | switch (record->code) | ||
392 | { | ||
393 | case XL_DIMENSION: | ||
394 | data = GetDataOfBREC(record); | ||
395 | if (record->length == 10) | ||
396 | { | ||
397 | sheet->rows = Integer2Byte(data[2], data[3]); | ||
398 | sheet->cols = Integer2Byte(data[6], data[7]); | ||
399 | } else | ||
400 | { | ||
401 | sheet->rows = Integer4Byte(data[4], data[5], data[6], data[7]); | ||
402 | sheet->cols = Integer2Byte(data[10], data[11]); | ||
403 | } | ||
404 | sheet->InitCells(); | ||
405 | break; | ||
406 | |||
407 | case XL_LABELSST: | ||
408 | HandleLabelSST(sheet, record); | ||
409 | break; | ||
410 | |||
411 | case XL_RK: | ||
412 | case XL_RK2: | ||
413 | HandleRK(sheet, record); | ||
414 | break; | ||
415 | |||
416 | case XL_MULRK: | ||
417 | HandleMulrk(sheet, record); | ||
418 | break; | ||
419 | |||
420 | case XL_ROW: | ||
421 | break; | ||
422 | |||
423 | case XL_NUMBER: | ||
424 | HandleNumber(sheet, record); | ||
425 | break; | ||
426 | |||
427 | case XL_BOOLERR: | ||
428 | break; | ||
429 | |||
430 | case XL_CONTINUE: | ||
431 | break; | ||
432 | |||
433 | case XL_FORMULA: | ||
434 | case XL_FORMULA2: | ||
435 | HandleFormula(sheet, record); | ||
436 | break; | ||
437 | |||
438 | case XL_LABEL: | ||
439 | break; | ||
440 | |||
441 | case XL_NAME: | ||
442 | HandleName(sheet, record); | ||
443 | break; | ||
444 | |||
445 | case XL_BOF: | ||
446 | break; | ||
447 | case XL_EOF: | ||
448 | return 0; | ||
449 | default: | ||
450 | break; | ||
451 | }; | ||
452 | return 1; | ||
453 | }; | ||
454 | |||
455 | int ExcelBook::ReadSheet(ExcelSheet* sheet) | ||
456 | { | ||
457 | ExcelBREC* record; | ||
458 | int oldpos; | ||
459 | oldpos = Position; | ||
460 | SeekPosition(sheet->position); | ||
461 | record = GetBREC(); | ||
462 | while (record!=NULL) | ||
463 | { | ||
464 | if (!SheetHandleRecord(sheet, record)) break; | ||
465 | record=GetBREC(); | ||
466 | }; | ||
467 | SeekPosition(oldpos); | ||
468 | return 1; | ||
469 | }; | ||
470 | |||
471 | ExcelSheet* ExcelBook::GetSheet(void) | ||
472 | { | ||
473 | ExcelSheet* sh=NULL; | ||
474 | int type; | ||
475 | type=SeekBOF(); | ||
476 | Version=type; | ||
477 | sh=new ExcelSheet; | ||
478 | if(type) | ||
479 | { | ||
480 | sh->type=type; | ||
481 | sh->position=Position; | ||
482 | sh->name=QString(""); | ||
483 | }; | ||
484 | if(type==8||type==7) | ||
485 | { | ||
486 | ReadSheet(sh); | ||
487 | }; | ||
488 | return sh; | ||
489 | }; | ||
490 | |||
491 | void ExcelBook::ParseSheets(void) | ||
492 | { | ||
493 | int BOFs; | ||
494 | ExcelBREC* r; | ||
495 | BOFs=1; | ||
496 | r=GetBREC(); | ||
497 | while(BOFs) | ||
498 | { | ||
499 | r=GetBREC(); | ||
500 | switch(r->code) | ||
501 | { | ||
502 | case XL_SST: | ||
503 | HandleSST(r); | ||
504 | break; | ||
505 | |||
506 | case XL_TXO: | ||
507 | break; | ||
508 | case XL_NAME: | ||
509 | break; | ||
510 | case XL_ROW: | ||
511 | break; | ||
512 | |||
513 | case XL_FORMAT: | ||
514 | HandleFormat(r); | ||
515 | break; | ||
516 | |||
517 | case XL_XF: | ||
518 | HandleXF(r); | ||
519 | break; | ||
520 | |||
521 | case XL_BOUNDSHEET: | ||
522 | HandleBoundSheet(r); | ||
523 | break; | ||
524 | |||
525 | case XL_EXTSST: | ||
526 | break; | ||
527 | case XL_CONTINUE: | ||
528 | break; | ||
529 | |||
530 | case XL_EOF: | ||
531 | BOFs--; | ||
532 | break; | ||
533 | |||
534 | default: | ||
535 | break; | ||
536 | }; | ||
537 | }; | ||
538 | }; | ||
539 | |||
540 | void ExcelBook::GetSheets(void) | ||
541 | { | ||
542 | ExcelSheet* sheet; | ||
543 | Sheets.resize(0); | ||
544 | sheet=GetSheet(); | ||
545 | while (sheet->Cells.count()!= 0 ) | ||
546 | { | ||
547 | Sheets.resize(Sheets.count()+1); | ||
548 | Sheets[Sheets.count()-1]=sheet; | ||
549 | sheet->name=*Names[Sheets.count()-1]; | ||
550 | sheet=GetSheet(); | ||
551 | }; | ||
552 | }; | ||
553 | |||
554 | bool ExcelBook::ParseBook(char *file) | ||
555 | { | ||
556 | dateformat=QString(""); | ||
557 | DetectEndian(); | ||
558 | OpenFile(file); | ||
559 | SeekBOF(); | ||
560 | ParseSheets(); | ||
561 | GetSheets(); | ||
562 | return true; | ||
563 | }; | ||
564 | |||
565 | QString ExcelBook::GetASCII(char* inbytes, int pos, int chars) | ||
566 | { | ||
567 | int i; | ||
568 | QString outstr=""; | ||
569 | for (i = 0; i < chars; i++) | ||
570 | { | ||
571 | outstr.append(inbytes[i+pos]); | ||
572 | }; | ||
573 | return outstr; | ||
574 | }; | ||
575 | |||
576 | QString ExcelBook::GetUnicode(char * inbytes, int pos, int chars) | ||
577 | { | ||
578 | QString outstr=""; | ||
579 | int i; | ||
580 | int rc; | ||
581 | for (i=0; i<chars*2; i++) | ||
582 | { | ||
583 | rc=Integer2Byte(inbytes[i+pos],inbytes[i+pos+1]); | ||
584 | outstr.append(QChar(rc)); | ||
585 | i++; | ||
586 | }; | ||
587 | return outstr; | ||
588 | }; | ||
589 | |||
590 | |||
591 | void ExcelBook::HandleBoundSheet(ExcelBREC* rec) | ||
592 | { | ||
593 | char* data; | ||
594 | int type; | ||
595 | int visibility; | ||
596 | int length; | ||
597 | int pos; | ||
598 | QString name; | ||
599 | pos = 8; | ||
600 | data = GetDataOfBREC(rec); | ||
601 | type = data[4]; | ||
602 | visibility = data[5]; | ||
603 | length = data[6]; | ||
604 | if(data[7]==0) | ||
605 | { | ||
606 | //ascii | ||
607 | name=GetASCII(data,pos,length); | ||
608 | }else | ||
609 | { | ||
610 | name=GetUnicode(data,pos,length); | ||
611 | }; | ||
612 | Names.resize(Names.count()+1); | ||
613 | Names[Names.count()-1]=new QString(name); | ||
614 | }; | ||
615 | |||
616 | void ExcelBook::HandleName(ExcelSheet* sheet, ExcelBREC* rec) | ||
617 | { | ||
618 | char* data; | ||
619 | QString name; | ||
620 | int length; | ||
621 | int pos; | ||
622 | pos = 15; | ||
623 | data = GetDataOfBREC(rec); | ||
624 | length = data[3]; | ||
625 | name = GetASCII(data,pos,length); | ||
626 | |||
627 | |||
628 | }; | ||
629 | |||
630 | ExcelFormat* ExcelBook::GetFormatting(int xf) | ||
631 | { | ||
632 | int i; | ||
633 | ExcelFormat* rec; | ||
634 | rec=new ExcelFormat(); | ||
635 | for (i = 0; formatter[i].code != 0; i++) | ||
636 | { | ||
637 | if (xf == formatter[i].code) break; | ||
638 | }; | ||
639 | if (formatter[i].format ==NULL) return NULL; | ||
640 | rec->code = xf; | ||
641 | rec->type = formatter[i].type; | ||
642 | rec->format = formatter[i].format; | ||
643 | return rec; | ||
644 | }; | ||
645 | |||
646 | void ExcelBook::HandleSetOfSST(ExcelBREC* rec/*, SSTList* cont*/, char* bytes) | ||
647 | { | ||
648 | QString str=QString(""); | ||
649 | char* data; | ||
650 | int chars, pos, options, i; | ||
651 | int richstring, fareaststring, runlength=0; | ||
652 | int richruns=0,fareastsize=0; | ||
653 | int totalstrings; | ||
654 | int uniquestrings; | ||
655 | data = GetDataOfBREC(rec); | ||
656 | totalstrings = Integer4Byte(data[0], data[1], data[2], data[3]); | ||
657 | uniquestrings = Integer4Byte(data[4], data[5], data[6], data[7]); | ||
658 | pos = 8; | ||
659 | for (i = 0; i < uniquestrings; i++) | ||
660 | { | ||
661 | richruns=0; fareastsize=0; | ||
662 | chars = Integer2Byte(data[pos], data[pos+1]); | ||
663 | pos += 2; | ||
664 | options = data[pos]; | ||
665 | pos++; | ||
666 | fareaststring = ((options & 0x04) != 0); | ||
667 | richstring = ((options & 0x08) != 0); | ||
668 | if(richstring) | ||
669 | { | ||
670 | richruns= Integer2Byte(data[pos],data[pos+1]); | ||
671 | pos+=2; | ||
672 | }; | ||
673 | if(fareaststring) | ||
674 | { | ||
675 | fareastsize=Integer4Byte(data[pos], data[pos+1], data[pos+2], data[pos+3]); | ||
676 | pos+=4; | ||
677 | }; | ||
678 | |||
679 | if ((options & 0x01) == 0) //8 bit chars | ||
680 | { | ||
681 | /* ascii */ | ||
682 | str = GetASCII(bytes,pos,chars); | ||
683 | pos=pos+chars; | ||
684 | if(str[0]=='=') str[0]=' '; | ||
685 | }else //16 bit chars | ||
686 | { | ||
687 | /* unicode */ | ||
688 | str = GetUnicode(bytes,pos,chars); | ||
689 | pos=pos+chars*2; | ||
690 | }; | ||
691 | // HERE TO PUT richformat handling | ||
692 | if (richstring) | ||
693 | { | ||
694 | pos += 4 * richruns; | ||
695 | }; | ||
696 | if (fareaststring) | ||
697 | { | ||
698 | pos += fareastsize; | ||
699 | }; | ||
700 | //printf("String=%s, length=%d first=0x%x\r\n",str.ascii(),str.length(),str[0].unicode()); | ||
701 | SharedStrings.resize(SharedStrings.count()+1); | ||
702 | SharedStrings[SharedStrings.count()-1]=new QString(str); | ||
703 | } | ||
704 | }; | ||
705 | |||
706 | |||
707 | char* ExcelBook::MergeBytesFromSSTs(ExcelBREC* rec,SSTList* cont) | ||
708 | { | ||
709 | int i, pos; | ||
710 | int length; | ||
711 | |||
712 | char* data; | ||
713 | char* bytes; | ||
714 | length = rec->length; | ||
715 | for (i = 0; i < (int) cont->rec.count(); i++) | ||
716 | { | ||
717 | length += cont->rec[i]->length; | ||
718 | } | ||
719 | bytes = GetDataOfBREC(rec); | ||
720 | pos = rec->length; | ||
721 | for (i = 0; i < (int) cont->rec.count(); i++) | ||
722 | { | ||
723 | data = GetDataOfBREC(cont->rec[i]); | ||
724 | *bytes += pos; | ||
725 | bytes = data; | ||
726 | pos += cont->rec[i]->length; | ||
727 | } | ||
728 | return bytes; | ||
729 | }; | ||
730 | |||
731 | |||
732 | void ExcelBook::HandleSST(ExcelBREC* rec) | ||
733 | { | ||
734 | char* bytes; | ||
735 | SSTList* cont; | ||
736 | cont= new SSTList; | ||
737 | ExcelBREC* nr; | ||
738 | nr = PeekBREC(); | ||
739 | while (nr->code == XL_CONTINUE) | ||
740 | { | ||
741 | cont->rec.resize(cont->rec.count()+1); | ||
742 | cont->rec[cont->rec.count()-1]=GetBREC(); | ||
743 | nr = PeekBREC(); | ||
744 | } | ||
745 | bytes = MergeBytesFromSSTs(rec,cont); | ||
746 | HandleSetOfSST(rec, bytes); | ||
747 | for(int w1=0;w1<(int)cont->rec.count();w1++) | ||
748 | { | ||
749 | if(cont->rec[w1]!=NULL) {delete cont->rec[w1];cont->rec[w1]=NULL;}; | ||
750 | }; | ||
751 | cont->rec.resize(0); | ||
752 | }; | ||
753 | |||
754 | void ExcelBook::HandleLabelSST(ExcelSheet* sheet, ExcelBREC* rec) | ||
755 | { | ||
756 | int index, row, col; | ||
757 | char* data; | ||
758 | data = GetDataOfBREC(rec); | ||
759 | index = Integer4Byte(data[6], data[7], data[8], data[9]); | ||
760 | row = Integer2Byte(data[0], data[1]); | ||
761 | col = Integer2Byte(data[2], data[3]); | ||
762 | sheet->Set(row,col, CellLabel(row, col, *GetString(index))); | ||
763 | }; | ||
764 | |||
765 | ExcelCell* ExcelBook::CellLabel(int row, int col, QString str) | ||
766 | { | ||
767 | ExcelCell* c; | ||
768 | c= new ExcelCell; | ||
769 | c->row = row; | ||
770 | c->col = col; | ||
771 | c->type = CELL_LABEL; | ||
772 | c->valuec = str; | ||
773 | return c; | ||
774 | }; | ||
775 | |||
776 | ExcelCell* ExcelBook::CellNumber(int row, int col, int index, double d) | ||
777 | { | ||
778 | ExcelCell* c; | ||
779 | c=new ExcelCell; | ||
780 | c->row = row; | ||
781 | c->col = col; | ||
782 | c->xfindex = index; | ||
783 | c->type = CELL_NUMBER; | ||
784 | c->valued = d; | ||
785 | return c; | ||
786 | }; | ||
787 | |||
788 | QString* ExcelBook::CellDataString(ExcelSheet* sh, int row, int col) | ||
789 | { | ||
790 | time_t date; | ||
791 | struct tm *tmptr; | ||
792 | ExcelCell* c; | ||
793 | char str[128]; | ||
794 | QString format; | ||
795 | int precision; | ||
796 | int utcOffsetDays = 25569; | ||
797 | int sInADay = 24 * 60 * 60; | ||
798 | c = sh->Get(row,col); | ||
799 | if (c == NULL) return new QString(""); | ||
800 | switch (c->type) | ||
801 | { | ||
802 | case CELL_LABEL: | ||
803 | return new QString(c->valuec); | ||
804 | case CELL_NUMBER: | ||
805 | if (XFRecords[c->xfindex]->type == DATEFORMAT) | ||
806 | { | ||
807 | |||
808 | format = XFRecords[c->xfindex]->format; | ||
809 | date = (time_t) ((c->valued - utcOffsetDays) * sInADay); | ||
810 | tmptr = gmtime(&date); | ||
811 | if (dateformat) | ||
812 | { | ||
813 | strftime(str,1024,dateformat.ascii(),tmptr); | ||
814 | } else | ||
815 | { | ||
816 | strftime(str,1024,format.ascii(),tmptr); | ||
817 | }; | ||
818 | } else | ||
819 | if (XFRecords[c->xfindex]->type == NUMBERFORMAT) | ||
820 | { | ||
821 | format = XFRecords[c->xfindex]->format; | ||
822 | //sprintf(str,format.ascii(),c->valued); | ||
823 | // the real format is ignored... | ||
824 | // because there is more work to be done in the field | ||
825 | precision = CellGetPrecision(c->valued); | ||
826 | sprintf(str,"%.*f",precision,c->valued); | ||
827 | }else | ||
828 | { | ||
829 | precision = CellGetPrecision(c->valued); | ||
830 | sprintf(str,"%.*f",precision,c->valued); | ||
831 | }; | ||
832 | break; | ||
833 | case CELL_DATE: | ||
834 | break; | ||
835 | case CELL_BOOLEAN: | ||
836 | break; | ||
837 | case CELL_ERROR: | ||
838 | break; | ||
839 | } | ||
840 | return new QString(str); | ||
841 | }; | ||
842 | |||
843 | int ExcelBook::CellGetPrecision(double d) | ||
844 | { | ||
845 | double t; | ||
846 | int i,x; | ||
847 | int count; | ||
848 | if (d < 0) d *= -1; | ||
849 | i = (int)d; | ||
850 | t = d - (double)i; | ||
851 | if (t <= 0) | ||
852 | { | ||
853 | return 0; | ||
854 | }; | ||
855 | count = 0; | ||
856 | for (x = 6; x > 1; x--) | ||
857 | { | ||
858 | i = (int)d; | ||
859 | t = d - (double)i; | ||
860 | t *= pow(10,x - 2); | ||
861 | i = (int)t; | ||
862 | t = t - (double)i; | ||
863 | t *= 10; | ||
864 | i = (int)t; | ||
865 | if (i > 0) break; | ||
866 | count++; | ||
867 | }; | ||
868 | return (5 - count); | ||
869 | }; | ||
870 | |||
871 | |||
872 | void ExcelBook::CellSetDateFormat(char *d) | ||
873 | { | ||
874 | dateformat = QString(d); | ||
875 | }; | ||
876 | |||
877 | void ExcelBook::HandleMulrk(ExcelSheet* sheet, ExcelBREC* record) | ||
878 | { | ||
879 | struct mulrk mulrk; | ||
880 | char* data; | ||
881 | ExcelCell* cell; | ||
882 | int len; | ||
883 | int i; | ||
884 | len = record->length; | ||
885 | data = GetDataOfBREC(record); | ||
886 | mulrk.row = Integer2Byte(data[0],data[1]); | ||
887 | mulrk.first = Integer2Byte(data[2],data[3]); | ||
888 | mulrk.last = Integer2Byte(data[len - 2],data[len - 1]); | ||
889 | mulrk.numrks = mulrk.last - mulrk.first + 1; | ||
890 | MulrkRead(&mulrk, data); | ||
891 | for (i = 0; i < mulrk.numrks; i++) | ||
892 | { | ||
893 | cell = CellNumber(mulrk.row, mulrk.first + i, mulrk.xfindices[i], mulrk.rkdbls[i]); | ||
894 | sheet->Set(mulrk.row,mulrk.first+ i, cell); | ||
895 | //printf("handleMULRK:row=%d,col=%d,val=%f\r\n",mulrk.row,mulrk.first+i,mulrk.rkdbls[i]); | ||
896 | } | ||
897 | //delete(mulrk.xfindices); | ||
898 | //delete(mulrk.rkdbls); | ||
899 | }; | ||
900 | |||
901 | void ExcelBook::MulrkRead(struct mulrk *mulrk, char* data) | ||
902 | { | ||
903 | double d; | ||
904 | int i; | ||
905 | int pos; | ||
906 | pos = 4; | ||
907 | mulrk->xfindices.resize(mulrk->numrks); | ||
908 | mulrk->rkdbls.resize(mulrk->numrks); | ||
909 | for (i = 0; i < mulrk->numrks; i++) | ||
910 | { | ||
911 | mulrk->xfindices[i] = Integer2Byte(data[pos], data[pos+1]); | ||
912 | d=Double4Byte(data[pos+2], data[pos+3], data[pos+4], data[pos+5]); | ||
913 | //printf("double:%f\r\n",d); | ||
914 | mulrk->rkdbls[i] = d; | ||
915 | pos += 6; | ||
916 | } | ||
917 | }; | ||
918 | |||
919 | |||
920 | void ExcelBook::HandleNumber(ExcelSheet* sheet, ExcelBREC* record) | ||
921 | { | ||
922 | int xfindex, row, col; | ||
923 | char* data; | ||
924 | double d; | ||
925 | data = GetDataOfBREC(record); | ||
926 | row = Integer2Byte(data[0], data[1]); | ||
927 | col = Integer2Byte(data[2], data[3]); | ||
928 | xfindex = Integer2Byte(data[4], data[5]); | ||
929 | #if defined(__arm__) && !defined(__vfp__) | ||
930 | d=Double8Byte(data[10], data[11], data[12], data[13],data[6], data[7], data[8], data[9]); | ||
931 | #else | ||
932 | d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]); | ||
933 | #endif | ||
934 | //even if ARM is little endian... doubles are been placed as bigendian words. | ||
935 | //thanks pb_ for that. :) | ||
936 | sheet->Set(row,col, CellNumber(row,col,xfindex,d)); | ||
937 | //printf("handleNumber:row=%d,col=%d,val=%f\r\n",row,col,d); | ||
938 | }; | ||
939 | |||
940 | ExcelFormat::ExcelFormat() | ||
941 | { | ||
942 | code=0;type=0;format=""; | ||
943 | }; | ||
944 | |||
945 | ExcelFormat::ExcelFormat(int c,int t, QString s) | ||
946 | { | ||
947 | code=c;type=t;format=s; | ||
948 | }; | ||
949 | |||
950 | |||
951 | void ExcelBook::HandleFormat(ExcelBREC* rec) | ||
952 | { | ||
953 | ExcelFormat* xfrec; | ||
954 | char* data; | ||
955 | int format; | ||
956 | data = GetDataOfBREC(rec); | ||
957 | format = Integer2Byte(data[2],data[3]); | ||
958 | xfrec = GetFormatting(format); | ||
959 | /*int idx; | ||
960 | idx=XFRecords.count()-1; | ||
961 | XFRecords[idx]->code=xfrec->code; | ||
962 | XFRecords[idx]->type=xfrec->type; | ||
963 | XFRecords[idx]->format="manos"; | ||
964 | //XFRecords[XFRecords.count()-1]=xfrec; | ||
965 | printf("6\r\n");*/ | ||
966 | }; | ||
967 | |||
968 | void ExcelBook::HandleXF(ExcelBREC* rec) | ||
969 | { | ||
970 | ExcelFormat* xfrec; | ||
971 | char* data; | ||
972 | int format; | ||
973 | data = GetDataOfBREC(rec); | ||
974 | format = Integer2Byte(data[2],data[3]); | ||
975 | xfrec = GetFormatting(format); | ||
976 | XFRecords.resize(XFRecords.count()+1); | ||
977 | XFRecords[XFRecords.count()-1]=xfrec; | ||
978 | }; | ||
979 | |||
980 | |||
981 | |||
982 | void ExcelBook::HandleRK(ExcelSheet* sheet, ExcelBREC* record) | ||
983 | { | ||
984 | int xfindex, row, col; | ||
985 | char* data; | ||
986 | double d; | ||
987 | data = GetDataOfBREC(record); | ||
988 | row = Integer2Byte(data[0], data[1]); | ||
989 | col = Integer2Byte(data[2], data[3]); | ||
990 | xfindex = Integer2Byte(data[4], data[5]); | ||
991 | d=Double4Byte(data[6], data[7], data[8], data[9]); | ||
992 | sheet->Set(row,col,CellNumber(row,col,xfindex,d)); | ||
993 | //printf("handleRK:row=%d,col=%d,val=%f\r\n",row,col,d); | ||
994 | }; | ||
995 | |||
996 | |||
997 | void ExcelBook::HandleFormula(ExcelSheet* sheet, ExcelBREC* record) | ||
998 | { | ||
999 | int xfindex, row, col; | ||
1000 | char* data; | ||
1001 | double d; | ||
1002 | data = GetDataOfBREC(record); | ||
1003 | row = Integer2Byte(data[0], data[1]); | ||
1004 | col = Integer2Byte(data[2], data[3]); | ||
1005 | if (data[6] == 0 && data[12] == -1 && data[13] == -1) | ||
1006 | { | ||
1007 | // string | ||
1008 | } else | ||
1009 | if (data[6] == 1 && data[12] == -1 && data[13] == -1) | ||
1010 | { | ||
1011 | // boolean | ||
1012 | } else | ||
1013 | if ( data[6] == 2 && data[12] == -1 && data[13] == -1) | ||
1014 | { | ||
1015 | // error | ||
1016 | } | ||
1017 | else | ||
1018 | { | ||
1019 | // number | ||
1020 | xfindex = Integer2Byte(data[4], data[5]); | ||
1021 | d=Double8Byte(data[6], data[7], data[8], data[9],data[10], data[11], data[12], data[13]); | ||
1022 | QString s1; | ||
1023 | int sz; | ||
1024 | sz=Integer2Byte(data[20],data[21]);// size of the formula | ||
1025 | char* formuladata; | ||
1026 | formuladata=new char[sz]; | ||
1027 | for(int w1=0;w1<sz;w1++) | ||
1028 | { | ||
1029 | formuladata[w1]=data[22+w1]; | ||
1030 | }; | ||
1031 | //22 is the first 0 idx of formula data | ||
1032 | s1="="+GetFormula(row,col,sheet,formuladata,sz); | ||
1033 | //printf("GetFormula:Formula=%s\r\n",s1.ascii()); | ||
1034 | sheet->Set(row,col,CellLabel(row,col,s1)); | ||
1035 | } | ||
1036 | }; | ||
1037 | |||
1038 | |||
1039 | QString ExcelBook::GetFormula(int row, int col, ExcelSheet* sheet, char* data, int sz) | ||
1040 | { | ||
1041 | int length=sz; | ||
1042 | printf("{FormulaParser}\r\n"); | ||
1043 | printf("row=%d, col=%d, length=%d\r\n",row,col,length); | ||
1044 | int idx=0; | ||
1045 | int w1,w2,w3,w4; | ||
1046 | double d1; | ||
1047 | int token; | ||
1048 | QString s1; | ||
1049 | QList <QString> operands; | ||
1050 | operands.setAutoDelete(TRUE); | ||
1051 | QString formula; | ||
1052 | operands.clear(); | ||
1053 | while( idx<length ) | ||
1054 | { | ||
1055 | token= data[idx]; idx++; | ||
1056 | switch(token) | ||
1057 | { | ||
1058 | case 0x1E: //prtInt | ||
1059 | w1=Integer2Byte(data[idx],data[idx+1]); | ||
1060 | idx=idx+2; | ||
1061 | operands.prepend(new QString(QString::number(w1))); | ||
1062 | printf(" token:ptgInt,num=%d\r\n",w1); | ||
1063 | break; | ||
1064 | case 0x1F: //ptgNumber | ||
1065 | #if defined(__arm__) && !defined(__vfp__) | ||
1066 | d1=Double8Byte(data[idx+4],data[idx+5],data[idx+6],data[idx+7] | ||
1067 | ,data[idx],data[idx+1],data[idx+2],data[idx+3]); | ||
1068 | #else | ||
1069 | d1=Double8Byte(data[idx],data[idx+1],data[idx+2],data[idx+3] | ||
1070 | ,data[idx+4],data[idx+5],data[idx+6],data[idx+7]); | ||
1071 | #endif | ||
1072 | idx=idx+8; | ||
1073 | operands.prepend(new QString(QString::number(d1))); | ||
1074 | printf(" token:ptgNumber,num=%f\r\n",d1); | ||
1075 | break; | ||
1076 | case 0x17: //ptgStr | ||
1077 | if(Version==8) | ||
1078 | { | ||
1079 | //unicode string | ||
1080 | //w1=Integer2Byte(data[idx],data[idx+1]);idx+=2; | ||
1081 | w1=data[idx];idx++; | ||
1082 | printf("len=%d\r\n",w1); | ||
1083 | int richruns=0; int fareastsize=0; | ||
1084 | int richstring,fareaststring; | ||
1085 | int options = data[idx];idx++; | ||
1086 | fareaststring = ((options & 0x04) != 0); | ||
1087 | richstring = ((options & 0x08) != 0); | ||
1088 | if(richstring) | ||
1089 | { | ||
1090 | //containts rich string formatting. | ||
1091 | printf("STRING:richstring\r\n"); | ||
1092 | richruns= Integer2Byte(data[idx],data[idx+1]); | ||
1093 | printf("richruns:%d\r\n",richruns); | ||
1094 | idx+=2; | ||
1095 | }; | ||
1096 | if(fareaststring) | ||
1097 | { | ||
1098 | //contains far east formatting | ||
1099 | printf("STRING:fareast!\r\n"); | ||
1100 | fareastsize=Integer4Byte(data[idx], data[idx+1], | ||
1101 | data[idx+2], data[idx+3]); | ||
1102 | printf("fareastsize=%d",fareastsize); | ||
1103 | idx+=4; | ||
1104 | }; | ||
1105 | if ((options & 0x01) == 0) //8 bit chars | ||
1106 | { | ||
1107 | /* ascii */ | ||
1108 | s1 = GetASCII(data,idx,w1); | ||
1109 | idx=idx+w1; | ||
1110 | printf("STRING:ASCII=%s\r\n",s1.ascii()); | ||
1111 | }else //16 bit chars | ||
1112 | { | ||
1113 | /* unicode */ | ||
1114 | s1 = GetUnicode(data,idx,w1); | ||
1115 | idx=idx+w1*2; | ||
1116 | printf("STRING:unicode=%s\r\n",s1.ascii()); | ||
1117 | }; | ||
1118 | // HERE TO PUT richformat handling | ||
1119 | if (richstring) | ||
1120 | { | ||
1121 | idx += 4 * richruns; | ||
1122 | }; | ||
1123 | if (fareaststring) | ||
1124 | { | ||
1125 | idx += fareastsize; | ||
1126 | }; | ||
1127 | s1=QString("""")+s1+QString(""""); | ||
1128 | operands.prepend(new QString(s1)); | ||
1129 | }else | ||
1130 | { | ||
1131 | w1=data[idx];idx++; | ||
1132 | s1=GetASCII(data,idx,w1); | ||
1133 | s1=QString("""")+s1+QString(""""); | ||
1134 | idx=idx+w1; | ||
1135 | operands.prepend(new QString(s1)); | ||
1136 | }; | ||
1137 | printf(" token:ptgStr,num=%d\r\n",w1); | ||
1138 | break; | ||
1139 | case 0x25: | ||
1140 | case 0x45: | ||
1141 | case 0x65: // ptgArea | ||
1142 | if(Version==8) | ||
1143 | { | ||
1144 | w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row1 | ||
1145 | w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row2 | ||
1146 | w3=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col1 | ||
1147 | w4=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col2 | ||
1148 | }else | ||
1149 | { | ||
1150 | w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row1 | ||
1151 | w2=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row2 | ||
1152 | w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col1 | ||
1153 | w4=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col2 | ||
1154 | }; | ||
1155 | //ignores relative or absolute refs | ||
1156 | s1=FindCellName(w1,w3)+":"+FindCellName(w2,w4); | ||
1157 | printf(" token:ptgArea,ref=%s\r\n",s1.ascii()); | ||
1158 | operands.prepend(new QString(s1)); | ||
1159 | break; | ||
1160 | case 0x24: | ||
1161 | case 0x44: | ||
1162 | case 0x64://ptgRef | ||
1163 | if(Version==8) | ||
1164 | { | ||
1165 | w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//row | ||
1166 | w2=Integer2Byte(data[idx],data[idx+1]) & 0x00FF;idx=idx+2;//col | ||
1167 | }else | ||
1168 | { | ||
1169 | w1=Integer2Byte(data[idx],data[idx+1]) & 0x3FFF;idx=idx+2;//row | ||
1170 | w2=Integer2Byte(data[idx],data[idx+1]);idx=idx+2;//col | ||
1171 | }; | ||
1172 | s1=FindCellName(w1,w2); | ||
1173 | printf("token:ptgRef,ref=%s\r\n",s1.ascii()); | ||
1174 | operands.prepend(new QString(s1)); | ||
1175 | break; | ||
1176 | case 0x1D: // ptgBool | ||
1177 | w1=data[idx];idx++; | ||
1178 | printf("token:ptgBool,val=%d\r\n",w1); | ||
1179 | operands.prepend(new QString(QString::number(w1))); | ||
1180 | break; | ||
1181 | case 0x16://ptg MissArg | ||
1182 | printf("token:ptgMissArg, val=' '\r\n"); | ||
1183 | operands.prepend(new QString("0")); | ||
1184 | break; | ||
1185 | case 0x12://ptgUplus== | ||
1186 | printf("token:ptgUplus\r\n"); | ||
1187 | s1=QString("+")+operands.first()->ascii(); | ||
1188 | operands.removeFirst(); | ||
1189 | operands.prepend(new QString(s1)); | ||
1190 | break; | ||
1191 | case 0x13://ptgUminus | ||
1192 | printf("token:ptgUminus\r\n"); | ||
1193 | s1=QString("-")+operands.first()->ascii(); | ||
1194 | operands.removeFirst(); | ||
1195 | operands.prepend(new QString(s1)); | ||
1196 | break; | ||
1197 | case 0x03://ptgAdd | ||
1198 | printf("token:ptgAdd\r\n"); | ||
1199 | operands.first(); | ||
1200 | s1=operands.next()->ascii() | ||
1201 | +QString("+")+operands.first()->ascii(); | ||
1202 | operands.removeFirst();operands.removeFirst(); | ||
1203 | operands.prepend(new QString(s1)); | ||
1204 | break; | ||
1205 | case 0x04://ptgSub | ||
1206 | printf("token:ptgSub\r\n"); | ||
1207 | operands.first(); | ||
1208 | s1=operands.next()->ascii() | ||
1209 | +QString("-")+operands.first()->ascii(); | ||
1210 | operands.removeFirst();operands.removeFirst(); | ||
1211 | operands.prepend(new QString(s1)); | ||
1212 | break; | ||
1213 | case 0x05://ptgMul | ||
1214 | printf("token:ptgMul\r\n"); | ||
1215 | operands.first(); | ||
1216 | s1=operands.next()->ascii() | ||
1217 | +QString("*")+operands.first()->ascii(); | ||
1218 | operands.removeFirst();operands.removeFirst(); | ||
1219 | operands.prepend(new QString(s1)); | ||
1220 | break; | ||
1221 | case 0x06://ptgDiv | ||
1222 | printf("token:ptgDiv\r\n"); | ||
1223 | operands.first(); | ||
1224 | s1=operands.next()->ascii() | ||
1225 | +QString("/")+operands.first()->ascii(); | ||
1226 | operands.removeFirst();operands.removeFirst(); | ||
1227 | operands.prepend(new QString(s1)); | ||
1228 | break; | ||
1229 | case 0x07://ptgPOWER | ||
1230 | printf("token:ptgPow\r\n"); | ||
1231 | operands.first(); | ||
1232 | s1=QString("POWER(")+operands.next()->ascii() | ||
1233 | +QString(",")+operands.first()->ascii()+QString(")"); | ||
1234 | operands.removeFirst();operands.removeFirst(); | ||
1235 | operands.prepend(new QString(s1)); | ||
1236 | break; | ||
1237 | case 0x08://ptgConcat | ||
1238 | printf("token:ptgConcat\r\n"); | ||
1239 | operands.first(); | ||
1240 | s1=QString("CONCATENATE(")+operands.next()->ascii() | ||
1241 | +QString(",")+operands.first()->ascii()+QString(")"); | ||
1242 | operands.removeFirst();operands.removeFirst(); | ||
1243 | operands.prepend(new QString(s1)); | ||
1244 | break; | ||
1245 | case 0x15://ptgParenthesis | ||
1246 | printf("token:ptgParenthesis\r\n"); | ||
1247 | s1=QString("(")+operands.first()->ascii()+QString(")"); | ||
1248 | operands.removeFirst(); | ||
1249 | operands.prepend(new QString(s1)); | ||
1250 | break; | ||
1251 | case 0x14://ptgPercent | ||
1252 | printf("token:ptgPercent\r\n"); | ||
1253 | s1=operands.first()->ascii()+QString("*0.01"); | ||
1254 | operands.removeFirst(); | ||
1255 | operands.prepend(new QString(s1)); | ||
1256 | break; | ||
1257 | case 0x9://ptgLessThan | ||
1258 | printf("token:ptgLESS\r\n"); | ||
1259 | operands.first(); | ||
1260 | s1=operands.next()->ascii() | ||
1261 | +QString("<")+operands.first()->ascii(); | ||
1262 | operands.removeFirst();operands.removeFirst(); | ||
1263 | operands.prepend(new QString(s1)); | ||
1264 | break; | ||
1265 | case 0xa://ptgLessEqual | ||
1266 | printf("token:ptgLESS_EQUAL\r\n"); | ||
1267 | operands.first(); | ||
1268 | s1=operands.next()->ascii() | ||
1269 | +QString("<=")+operands.first()->ascii(); | ||
1270 | operands.removeFirst();operands.removeFirst(); | ||
1271 | operands.prepend(new QString(s1)); | ||
1272 | break; | ||
1273 | case 0xb://ptgEQUAL | ||
1274 | printf("token:ptgEQUAL\r\n"); | ||
1275 | operands.first(); | ||
1276 | s1=operands.next()->ascii() | ||
1277 | +QString("==")+operands.first()->ascii(); | ||
1278 | operands.removeFirst();operands.removeFirst(); | ||
1279 | operands.prepend(new QString(s1)); | ||
1280 | break; | ||
1281 | case 0xc://ptgGREATER_EQUAL | ||
1282 | printf("token:ptgGREAT_EQUAL\r\n"); | ||
1283 | operands.first(); | ||
1284 | s1=operands.next()->ascii() | ||
1285 | +QString(">=")+operands.first()->ascii(); | ||
1286 | operands.removeFirst();operands.removeFirst(); | ||
1287 | operands.prepend(new QString(s1)); | ||
1288 | break; | ||
1289 | case 0xd://ptgGREAT_THAN | ||
1290 | printf("token:ptgGREAT_THAN\r\n"); | ||
1291 | operands.first(); | ||
1292 | s1=operands.next()->ascii() | ||
1293 | +QString(">")+operands.first()->ascii(); | ||
1294 | operands.removeFirst();operands.removeFirst(); | ||
1295 | operands.prepend(new QString(s1)); | ||
1296 | break; | ||
1297 | case 0xe://ptgNOT_EQUAL | ||
1298 | printf("token:ptgNOTequal\r\n"); | ||
1299 | operands.first(); | ||
1300 | s1=operands.next()->ascii() | ||
1301 | +QString("!=")+operands.first()->ascii(); | ||
1302 | operands.removeFirst();operands.removeFirst(); | ||
1303 | operands.prepend(new QString(s1)); | ||
1304 | break; | ||
1305 | case 0x19://attribute can be Sum,If,Choose | ||
1306 | w3=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; | ||
1307 | idx++; | ||
1308 | printf("token:ATTRIBUTE:0x%x\r\n",w3); | ||
1309 | for(w4=idx;w4<length;w4++) | ||
1310 | printf("0x%x, ",data[w4]); | ||
1311 | if(w3&0x01)//choose | ||
1312 | { | ||
1313 | printf("token:CHOOSE\r\n"); | ||
1314 | } | ||
1315 | else if(w3&0x02)//if | ||
1316 | { | ||
1317 | printf("token:IF\r\n"); | ||
1318 | } | ||
1319 | else if(w3&0x10)//sum | ||
1320 | { | ||
1321 | printf("token:SUM\r\n"); | ||
1322 | }; | ||
1323 | |||
1324 | break; | ||
1325 | |||
1326 | |||
1327 | case 0x21: | ||
1328 | case 0x22: | ||
1329 | case 0x42: | ||
1330 | case 0x62: | ||
1331 | case 0x41: | ||
1332 | case 0x61://ptgFunction | ||
1333 | printf("token:ptgFunction\r\n"); | ||
1334 | if(token==0x22||token==0x42||token==0x62) | ||
1335 | { | ||
1336 | w2=(int)data[idx];idx++; | ||
1337 | w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; | ||
1338 | }else | ||
1339 | { | ||
1340 | w1=Integer2Byte(data[idx],data[idx+1]);idx=idx+2; | ||
1341 | }; | ||
1342 | switch(w1) | ||
1343 | { | ||
1344 | case 0xf://SIN | ||
1345 | s1=QString("SIN(")+operands.first()->ascii()+QString(")"); | ||
1346 | operands.removeFirst(); | ||
1347 | operands.prepend(new QString(s1)); | ||
1348 | break; | ||
1349 | case 0x10://COS | ||
1350 | s1=QString("COS(")+operands.first()->ascii()+QString(")"); | ||
1351 | operands.removeFirst(); | ||
1352 | operands.prepend(new QString(s1)); | ||
1353 | break; | ||
1354 | case 0x11://tan | ||
1355 | s1=QString("TAN(")+operands.first()->ascii()+QString(")"); | ||
1356 | operands.removeFirst(); | ||
1357 | operands.prepend(new QString(s1)); | ||
1358 | break; | ||
1359 | case 0x62://asin | ||
1360 | s1=QString("ASIN(")+operands.first()->ascii()+QString(")"); | ||
1361 | operands.removeFirst(); | ||
1362 | operands.prepend(new QString(s1)); | ||
1363 | break; | ||
1364 | case 0x63://ACOS | ||
1365 | s1=QString("ACOS(")+operands.first()->ascii()+QString(")"); | ||
1366 | operands.removeFirst(); | ||
1367 | operands.prepend(new QString(s1)); | ||
1368 | break; | ||
1369 | case 0x12://ATAN | ||
1370 | s1=QString("ATAN(")+operands.first()->ascii()+QString(")"); | ||
1371 | operands.removeFirst(); | ||
1372 | operands.prepend(new QString(s1)); | ||
1373 | break; | ||
1374 | case 0xe5://SINH | ||
1375 | s1=QString("SINH(")+operands.first()->ascii()+QString(")"); | ||
1376 | operands.removeFirst(); | ||
1377 | operands.prepend(new QString(s1)); | ||
1378 | break; | ||
1379 | case 0xe6://COSH | ||
1380 | s1=QString("COSH(")+operands.first()->ascii()+QString(")"); | ||
1381 | operands.removeFirst(); | ||
1382 | operands.prepend(new QString(s1)); | ||
1383 | break; | ||
1384 | case 0xe7://TANH | ||
1385 | s1=QString("TANH(")+operands.first()->ascii()+QString(")"); | ||
1386 | operands.removeFirst(); | ||
1387 | operands.prepend(new QString(s1)); | ||
1388 | break; | ||
1389 | case 0xe8://ASINH | ||
1390 | s1=QString("ASINH(")+operands.first()->ascii()+QString(")"); | ||
1391 | operands.removeFirst(); | ||
1392 | operands.prepend(new QString(s1)); | ||
1393 | break; | ||
1394 | case 0xe9://ACOSH | ||
1395 | s1=QString("ACOSH(")+operands.first()->ascii()+QString(")"); | ||
1396 | operands.removeFirst(); | ||
1397 | operands.prepend(new QString(s1)); | ||
1398 | break; | ||
1399 | case 0xea://ATANH | ||
1400 | s1=QString("ATANH(")+operands.first()->ascii()+QString(")"); | ||
1401 | operands.removeFirst(); | ||
1402 | operands.prepend(new QString(s1)); | ||
1403 | break; | ||
1404 | case 0x13://pi | ||
1405 | s1="PI()"; | ||
1406 | operands.prepend(new QString(s1)); | ||
1407 | break; | ||
1408 | case 0x14://sqrt | ||
1409 | s1=QString("SQRT(")+operands.first()->ascii()+QString(")"); | ||
1410 | operands.removeFirst(); | ||
1411 | operands.prepend(new QString(s1)); | ||
1412 | break; | ||
1413 | case 0x15://exp | ||
1414 | s1=QString("EXP(")+operands.first()->ascii()+QString(")"); | ||
1415 | operands.removeFirst(); | ||
1416 | operands.prepend(new QString(s1)); | ||
1417 | break; | ||
1418 | case 0x16://LN | ||
1419 | s1=QString("LN(")+operands.first()->ascii()+QString(")"); | ||
1420 | operands.removeFirst(); | ||
1421 | operands.prepend(new QString(s1)); | ||
1422 | break; | ||
1423 | case 0x17://LOG10 | ||
1424 | s1=QString("LOG10(")+operands.first()->ascii()+QString(")"); | ||
1425 | operands.removeFirst(); | ||
1426 | operands.prepend(new QString(s1)); | ||
1427 | break; | ||
1428 | case 0x18://ABS | ||
1429 | s1=QString("ABS(")+operands.first()->ascii()+QString(")"); | ||
1430 | operands.removeFirst(); | ||
1431 | operands.prepend(new QString(s1)); | ||
1432 | break; | ||
1433 | case 0x19://int | ||
1434 | s1=QString("INT(")+operands.first()->ascii()+QString(")"); | ||
1435 | operands.removeFirst(); | ||
1436 | operands.prepend(new QString(s1)); | ||
1437 | break; | ||
1438 | case 0x1a://sign | ||
1439 | s1=QString("SIGN(")+operands.first()->ascii()+QString(")"); | ||
1440 | operands.removeFirst(); | ||
1441 | operands.prepend(new QString(s1)); | ||
1442 | break; | ||
1443 | case 0x1b://round | ||
1444 | operands.first(); | ||
1445 | s1=QString("ROUND(")+operands.next()->ascii() | ||
1446 | +QString(",")+operands.first()->ascii() | ||
1447 | +QString(")"); | ||
1448 | operands.removeFirst();operands.removeFirst(); | ||
1449 | operands.prepend(new QString(s1)); | ||
1450 | break; | ||
1451 | case 0x1d://index | ||
1452 | operands.first(); | ||
1453 | s1=QString("INDEX(")+operands.next()->ascii() | ||
1454 | +QString(",") | ||
1455 | +operands.first()->ascii()+QString(")"); | ||
1456 | operands.removeFirst(); | ||
1457 | operands.removeFirst(); | ||
1458 | operands.prepend(new QString(s1)); | ||
1459 | break; | ||
1460 | case 0x1: // if ATTRIBUTE | ||
1461 | operands.first();operands.next(); | ||
1462 | s1=QString("IF(")+operands.next()->ascii()+QString(","); | ||
1463 | operands.first(); | ||
1464 | s1=s1+operands.next()->ascii()+QString(","); | ||
1465 | s1=s1+operands.first()->ascii()+QString(")"); | ||
1466 | operands.removeFirst(); | ||
1467 | operands.removeFirst(); | ||
1468 | operands.removeFirst(); | ||
1469 | operands.prepend(new QString(s1)); | ||
1470 | break; | ||
1471 | case 0x81://isblank | ||
1472 | s1=QString("ISBLANK(")+operands.first()->ascii() | ||
1473 | +QString(")"); | ||
1474 | operands.removeFirst(); | ||
1475 | operands.prepend(new QString(s1)); | ||
1476 | break; | ||
1477 | case 0x80://isnumber | ||
1478 | s1=QString("ISNUMBER(")+operands.first()->ascii() | ||
1479 | +QString(")"); | ||
1480 | operands.removeFirst(); | ||
1481 | operands.prepend(new QString(s1)); | ||
1482 | break; | ||
1483 | case 0x120://ceiling | ||
1484 | operands.first(); | ||
1485 | s1=QString("CEILING(")+operands.next()->ascii() | ||
1486 | +QString(",")+operands.first()->ascii() | ||
1487 | +QString(")"); | ||
1488 | operands.removeFirst();operands.removeFirst(); | ||
1489 | operands.prepend(new QString(s1)); | ||
1490 | break; | ||
1491 | case 0x11d://floor | ||
1492 | operands.first(); | ||
1493 | s1=QString("FLOOR(")+operands.next()->ascii() | ||
1494 | +QString(",")+operands.first()->ascii() | ||
1495 | +QString(")"); | ||
1496 | operands.removeFirst();operands.removeFirst(); | ||
1497 | operands.prepend(new QString(s1)); | ||
1498 | break; | ||
1499 | case 0x157://degrees | ||
1500 | s1=QString("DEGREES(")+operands.first()->ascii() | ||
1501 | +QString(")"); | ||
1502 | operands.removeFirst(); | ||
1503 | operands.prepend(new QString(s1)); | ||
1504 | break; | ||
1505 | case 0x156://radians | ||
1506 | s1=QString("RADIANS(")+operands.first()->ascii() | ||
1507 | +QString(")"); | ||
1508 | operands.removeFirst(); | ||
1509 | operands.prepend(new QString(s1)); | ||
1510 | break; | ||
1511 | case 0xb8://fact | ||
1512 | s1=QString("FACT(")+operands.first()->ascii() | ||
1513 | +QString(")"); | ||
1514 | operands.removeFirst(); | ||
1515 | operands.prepend(new QString(s1)); | ||
1516 | break; | ||
1517 | case 0x27://MOD | ||
1518 | operands.first(); | ||
1519 | s1=QString("MOD(")+operands.next()->ascii() | ||
1520 | +QString(",")+operands.first()->ascii() | ||
1521 | +QString(")"); | ||
1522 | operands.removeFirst();operands.removeFirst(); | ||
1523 | operands.prepend(new QString(s1)); | ||
1524 | break; | ||
1525 | case 0x151://power | ||
1526 | operands.first(); | ||
1527 | s1=QString("POWER(")+operands.next()->ascii() | ||
1528 | +QString(",")+operands.first()->ascii() | ||
1529 | +QString(")"); | ||
1530 | operands.removeFirst();operands.removeFirst(); | ||
1531 | operands.prepend(new QString(s1)); | ||
1532 | break; | ||
1533 | case 0x3f://rand() | ||
1534 | s1="RAND()"; | ||
1535 | operands.prepend(new QString(s1)); | ||
1536 | break; | ||
1537 | case 0x4://sum | ||
1538 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1539 | s1=QString("SUM(")+operands.first()->ascii() | ||
1540 | +QString(")"); | ||
1541 | operands.removeFirst(); | ||
1542 | operands.prepend(new QString(s1)); | ||
1543 | break; | ||
1544 | case 0x6://min | ||
1545 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1546 | s1=QString("MIN(")+operands.first()->ascii() | ||
1547 | +QString(")"); | ||
1548 | operands.removeFirst(); | ||
1549 | operands.prepend(new QString(s1)); | ||
1550 | break; | ||
1551 | case 0x7://max | ||
1552 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1553 | s1=QString("MAX(")+operands.first()->ascii() | ||
1554 | +QString(")"); | ||
1555 | operands.removeFirst(); | ||
1556 | operands.prepend(new QString(s1)); | ||
1557 | break; | ||
1558 | case 0x5://average | ||
1559 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1560 | s1=QString("AVERAGE(")+operands.first()->ascii() | ||
1561 | +QString(")"); | ||
1562 | operands.removeFirst(); | ||
1563 | operands.prepend(new QString(s1)); | ||
1564 | break; | ||
1565 | case 0x2e://var | ||
1566 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1567 | s1=QString("VAR(")+operands.first()->ascii() | ||
1568 | +QString(")"); | ||
1569 | operands.removeFirst(); | ||
1570 | operands.prepend(new QString(s1)); | ||
1571 | break; | ||
1572 | case 0xc2://varp | ||
1573 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1574 | s1=QString("VARP(")+operands.first()->ascii() | ||
1575 | +QString(")"); | ||
1576 | operands.removeFirst(); | ||
1577 | operands.prepend(new QString(s1)); | ||
1578 | break; | ||
1579 | case 0xc://stdev | ||
1580 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1581 | s1=QString("STDEV(")+operands.first()->ascii() | ||
1582 | +QString(")"); | ||
1583 | operands.removeFirst(); | ||
1584 | operands.prepend(new QString(s1)); | ||
1585 | break; | ||
1586 | case 0xc1://stdevp | ||
1587 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1588 | s1=QString("STDEVP(")+operands.first()->ascii() | ||
1589 | +QString(")"); | ||
1590 | operands.removeFirst(); | ||
1591 | operands.prepend(new QString(s1)); | ||
1592 | break; | ||
1593 | case 0x143://skew | ||
1594 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1595 | s1=QString("SKEW(")+operands.first()->ascii() | ||
1596 | +QString(")"); | ||
1597 | operands.removeFirst(); | ||
1598 | operands.prepend(new QString(s1)); | ||
1599 | break; | ||
1600 | case 0x142://kurt | ||
1601 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1602 | s1=QString("KURT(")+operands.first()->ascii() | ||
1603 | +QString(")"); | ||
1604 | operands.removeFirst(); | ||
1605 | operands.prepend(new QString(s1)); | ||
1606 | break; | ||
1607 | case 0x0://count | ||
1608 | for(w4=1;w4<w2;w4++) operands.removeFirst(); | ||
1609 | s1=QString("COUNT(")+operands.first()->ascii() | ||
1610 | +QString(")"); | ||
1611 | operands.removeFirst(); | ||
1612 | operands.prepend(new QString(s1)); | ||
1613 | break; | ||
1614 | |||
1615 | default: | ||
1616 | printf("token:FUNCTION_UNKNOWN=0x%x\r\n",w1); | ||
1617 | return QString("FUNC_UNKNOWN"); | ||
1618 | break; | ||
1619 | |||
1620 | }; | ||
1621 | |||
1622 | break; | ||
1623 | |||
1624 | default: | ||
1625 | printf("tokenUNKNOWN=0x%x\r\n",token); | ||
1626 | return QString("TOKEN_UKNOWN"); | ||
1627 | //it is dangerous to go to idx++ and not return | ||
1628 | // because the result is unexpected. | ||
1629 | // but there is a possibility the the parser will give the correct | ||
1630 | // answer, because there are some tokens in excel formulas that can be //ignored. | ||
1631 | idx++; | ||
1632 | break; | ||
1633 | }; | ||
1634 | |||
1635 | }; | ||
1636 | |||
1637 | |||
1638 | |||
1639 | printf("{////FormulaParser}\r\n"); | ||
1640 | printf("GetFormula:::::::r=%d,c=%d,,,%s\r\n",row,col,s1.ascii()); | ||
1641 | printf("\r\n"); | ||
1642 | s1=operands.first()->ascii(); | ||
1643 | operands.clear(); | ||
1644 | return QString(s1); | ||
1645 | }; | ||
1646 | |||
1647 | QString ExcelBook::FindCellName(int row, int col) | ||
1648 | { | ||
1649 | row++;col++; | ||
1650 | QString s1=""; | ||
1651 | int i1=col % 26; | ||
1652 | int i2=col / 26; | ||
1653 | if (i2!=0) s1=(char)(i2+65); //65 =A | ||
1654 | s1=s1+(char)(i1+65-1); | ||
1655 | return (s1+QString::number(row)); | ||
1656 | }; | ||
1657 | |||
1658 | |||
1659 | |||
1660 | |||
1661 | |||
1662 | |||
1663 | |||
1664 | |||