views:

83

answers:

2

Hi all,

I am successfully writing to an Excel file, using javascript from my FireFox extension. I can get the formatting, and contents that I want, however I have run into a roadblock.

In order to add the formatting, I have to EOF the Workbook Globals Stream, and BOF the worksheet stream. When I do that Excel says the file is corrupt.

I am currently writing to the file these records, in this order:

BOF Record (0x05 [Workbook])
WINDOW1 Record
1904 Record
FONT Record (x7)
XF Record (x17)
BOUNDSHEET Record
EOF Record
BOF Record (0x10 [Worksheet])
LABEL Record
EOF Record

However when I open the file in Excel it says it is corrupt, when I open it in OpenOffice it loads the document just fine, when I open it with ExcelFile Workbook viewer to see the records, all looks fine.

Here is the code that I am writing at the beginning of the file:

    excelData[excelData.length] = pack("vvvvvv", 0x809, 0x08, 0x0500, 0x05, 0x096C, 0x07C9); // BOF Workbook

excelData[excelData.length] = pack("vvvvvvvvvvv", 0x003D, 0x0012, 0x0000, 0x0000, 0x25BC, 0x1572, 0x0038, 0x0000, 0x0000, 0x0001, 0x0258); // WINDOW1
excelData[excelData.length] = pack("vvv", 0x0022, 0x0002, 0x0000); // 1904

excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x0190, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 normal - index 0
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 1
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 2
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 3
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 5
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 6
excelData[excelData.length] = "Calibri";
excelData[excelData.length] = pack("vv", 0x0031, 0x0F+7);
excelData[excelData.length] = pack("vvvvvCCCCC", 0x00C8, 0x0001, 0x0000, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 7
excelData[excelData.length] = "Calibri";


excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0000, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0000, 0x0000, 0x0001, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0x0001, 0x0020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up? // User Defined





    var L = 0;
for (var i=0; i<excelData.length; i++) {
    L = Number(L)+Number(excelData[i].length);
}
L = L+27;

var data = pack("VvC", Number(L), 0x0000, 12); // BOUNDSHEET
data = data+"data sheet 1";
excelData[excelData.length] = pack("vv", 0x0085, data.length);
excelData[excelData.length] = data;


excelData[excelData.length] = pack("vv", 0x0A, 0x00); // EOF
excelData[excelData.length] = pack("vvvvvv", 0x809, 0x08, 0x0500, 0x10, 0x096C, 0x07C9); // BOF Worksheet

I truly suspect the problem lies in the BOUNDSHEET record. However I am not having any luck figuring this one out either. Any help would be appreciated!

-Alex

A: 

I suggest duplicating your Excel content using the Perl Excel Writer by John McNamara. Then compare the binary output of his sw and yours. You could also try to contact John for help.

I believe that the perl lib is considered the "standard" for open source Excel file creation. Many Excel writers in other languages are simply ports of John's work.

Also, can you say more about your FF extension for writing Excel files? It sounds great.

Larry K
Hi Larry, I have duplicated my work in a few of the available open source libraries out there, however there is always inconsistencies. The BOUNDSHEET record requires the length of the data up to the new BOF for the worksheet, which is different from file to file. I need to ensure my calculation for offset 4 of the BOUNDSHEET record is accurate.
Alex
+1  A: 

I am the author of the Spreadsheet::WriteExcel Perl module mentioned above.

If you send me one of the corrupt files I'll debug it for you and let you know what the issue is.

jmcnamara
After looking at the file it looks like the missing OLE doc information is causing the problem.
jmcnamara
The BOUNDSHEET offset calculation *is* correct.
jmcnamara