views:

50

answers:

1

Hi all,

I'm using the FireFox API to write to a binary file from my JavaScript based FireFox extension.

So far I am fully able to write the information to the file in BIFF5 format, and re-size the columns successfully.

The problem I'm running into is no matter what I try, I can not seem to get the XF index (ixfe) in the LABEL record to point to the XF record. (That or my XF record is faulty)

Basically I'm trying to change the font weight in a few cells to bold.

I know I can use for statements to clean this code up a bit, but while I'm troubleshooting I'm doing it one record at a time so I can easily see whats going on.

This is what I'm writing for the BOF:

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

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, 0x7FFF, 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, 0x7FFF, 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, 0x7FFF, 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, 0x7FFF, 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, 0x7FFF, 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, 0x7FFF, 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, 0x7FFF, 0x02BC, 0x0000, 0x0200, 0x00, 0x01, 0x00, 7); // calibri 10 bold - index 7
excelData[excelData.length] = "Calibri";


excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0xFFF5, 0x2020, 0x20C0, 0x8140, 0x15B3, 0x2040); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0x00,   0x2020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up?
excelData[excelData.length] = pack("vvvvvvvvvv", 0x00E0, 0x0010, 0x0006, 0x0000, 0x00,   0x2020, 0x20C0, 0x0000, 0x0000, 0x0000); //XF Messed up? // User Defined

This is what I'm writing for the LABEL:

    excelData[excelData.length] = pack("vvvvvv", 0x0204, Number(L)+8, Row, Col, 0x11, L);
excelData[excelData.length] = Value; // Cell Value

So if I'm not mistaken, 0x11 in the LABEL, is pointing to ixfe 17 which is the 16th XF record.

The XF record is pointing to ifnt (font index) of 0x0006 which is ifnt 6, or the 6th FONT record thanks to index 4 being unused.

What is happening is that the cells are still just using the default font (ifnt 0) regardless of what I have changed the ixfe in the LABEL record, or the ifnt in the XF record to.

I have read every ounce of documentation I could find, as well as tried to reverse engineer a few of the libraries that are out there for PHP.

At this point, any guidance would be greatly appreciated because I am completely out of ideas.

Thanks alot, folks!

EDIT

I have learned alot in the past couple hours, thanks for your help. I will be posting a new question for the new problem I'm facing regarding the Workbook Stream.

New question for anyone whom may track this down and have similar issues: http://stackoverflow.com/questions/3714051/biff5-excel-workbook-stream-problems-corrupt-file

+1  A: 

For bold, the Font record needs a value of 0x02BC at offset 6. For future reference, in case you want to add further font styling subsequently, italic requires a bitmask of 0x0002 at offset 2, while strikethrough requires a bitmask of 0x0008 at offset 2. Offset 4 points to the colour index, if you want to change font colour, while offset 8 identifies superscript/subscript, and offset 10 identifies underline type. Offsets 11, 12 and 14 identify the font family, character set and size of the font name, followed by the font name itself.

You can find full details of all the options at http://msdn.microsoft.com/en-us/library/cc313154(v=office.12).aspx

EDIT

Looking at your XF record, you're writing it as a BIFF5 record rather than the later version BIFF8. The link that I referenced with the worked example is actually a BIFF8 example.

BIFF8 would be:- header = pack("vv", 0x00E0, 0x0014); data = pack("vvvCCCCVVv", fontIndex, numberFormatIndex, 0xFFF5, alignment, rotation, identation+shrinkToFit+textDirection, attributes, border1, border2, fg_and_bg_colours);

BIFF5 is:- header = pack("vv", 0x00E0, 0x0010); data = pack("vvvvvvvv", fontIndex, numberFormatIndex, 0xFFF5, alignment, fg_and_bg_colours, fillPattern, border1, border2);

I'll confess that I'm more used to working with the BIFF8 format; but reading through the details of the format for BIFF5, I can't see any obvious problems with the xf that you're writing. I do know that in PHPExcel we explicitly write the 16 Font records for the pre-defineds before writing the new user-defined font records, and then always set the XF records pointing to the user-defined fonts.

Mark Baker
Hi Mark, Thanks for your response! If you look at the code I supplied you'll see that although the first FONT record has a normal font weight (0x0190), the following FONT records are in fact using 0x02BC in offset 6. The LABEL points to the XF record which points to one of the FONT records using the 0x02BC byte. In other words, LABEL -> XF -> FONT, and the FONT record it points to is already in fact bold. Yet it still is not changing the font to bold. What am I missing?
Alex
Rereading the specification document, Font records 0-15 are reserved for Normal style, Row outline levels 1-7, Column outline levels 1-7, and the Default cell format. User-defined font records should be index 16 and up.
Mark Baker
According to the Excel Binary File Format Specifications PDF from Microsoft's website, Offset 8, in the LABEL record is an index to the XF record. Offset 4 in the XF record is an index to the FONT record, so if this is the case, I'm not understanding why it doesn't work as I've implemented it. Regardless, I have tried adding 16 (the total required XF records) to the FONT index number, as you suggested, and it still does not work. From my understanding, the XF index and FONT index are two different values. The LABEL record should point to the XF record, which in turn points to the FONT record.
Alex
The principle you're outlining Cell -> XF -> Font is quite correct... the problem is probably somewhere in the detail of the values you're writing to the XF record, as you believe. there's a worked example at this url http://msdn.microsoft.com/en-us/library/dd943793(v=office.12).aspx that might help.
Mark Baker
Ok, I have made a few changes to my XFs, and I'm fairly certain they are correct. I am also fairly certain all my indexes are correct. Am I missing some records that are required to make this functionality work? currently I am using the following records: BOF (0x10 - Worksheet), WINDOW1, 1904, FONT(x7), XF(x17), LABEL, and EOF. Everytime I try to add STYLE, EXTERNSHEET or BOUNDSHEET it corrupts the Excel file, so these are the only records I have currently. Am I missing a necessary record to make XF/FONT work properly?
Alex
I'd assumed your code was extracts from the write rather than the whole script. XF and Font records appear in the General workbook stream, while each worksheet is written in its own stream, so you have a BOF at the beginning of the file, an EOF after the style XF and font records, followed by the individual worksheet streams
Mark Baker
Thanks Mark, you're right. I updated my original post. Once I did that I could see in a different editor that the styling was being applied correctly, however now Excel kicks it back as "file is corrupt" I can only assume there is a problem with my BOUNDSHEET record, or I am missing records.. Now my current output is BOF (0x05), WINDOW1, 1904, FONT(x7), XF(x17), BOUNDSHEET, EOF, BOF (0x10), LABELs, EOF
Alex