Click here to Skip to main content
Click here to Skip to main content

Saving Excel 2.1 Workbook

By , 12 Sep 2002
 

Sample Image

Introduction

Recently I worked on a project that required exporting some reports containing various file statistics. The goal was having one format that would look good immediately and one easy accessible format for the user to import and build custom reports. For the first export type, plain HTML was used. But for importing, HTML is not really easy to use, so Excel file creation seemed a good choice.

Requirements

Since the Excel exported file is just for the user to have easy access to data, only a small part of the Excel file format features were needed. Also, there was no guarantee that Excel would even be installed on the computer where the reports are generated and since a port to Linux was imminent, it would be nice for the class to be platform independent. The goal was to be able to write something as this:

CMiniExcel miniexcel;

miniexcel(0,0) = "FileName";
miniexcel(0,1) = "Size (MB)";

miniexcel(1,0) = "c:\\bigfile.txt";
miniexcel(1,1) = 123.45;

miniexcel.SaveAs("Report.xls")

There are no real memory constraints, since Excel cannot handle over ~65K rows anyway. (Actually we also needed a single big report with more that 65K rows, and we had to save it as a "Comma separated values" file). So the whole excel worksheet could be kept in memory.

Excel file format

After a little bit of searching on the net, I decided on the Excel 2.1 Workbook format (description of the format found here). Even though this format is old, it can be imported by Excel or by other programs and it seemed suitable for our simple needs.

From the documentation of the Excel 2.1 format it turns out that an excel document is stored using a format called Binary File Format (BIFF). This format is a sequence of BIFF records, each record containing a certain property/value of the workgroup. Each BIFF record starts with a 2 byte number containing it's type and another 2 bytes for the size of the record. After this header, record-specific data will follow:

XX XX

 XX XX

 ....

Type  Length  Specific Data

From the several record types needed, only a few were really important for simple excel exporting. BOF and EOF records were unavoidable and also text strings (LABEL record) and numbers (NUMBER record) needed to be saved.

Implementation

First of all, to take care of the platform independence and also to make life easier when saving the BIFF records, I implemented a writer class (CLittleEndianWriter) that should be able to write 1 byte, 2 byte and 4 byte values in little endian byte order. Also, it needed to be able to save double values in IEEE format, since this is the format used to store real numbers (excel has a BIFF record fr storing a 16 bit unsigned integer, but it is not enough):

class LittleEndianWriter{
  ...
public:
  ...
  void Write1 (char v);
  void Write2 (int v);
  void Write4 (long v);
  void WriteFloatIEEE (float v);
  void WriteDoubleIEEE (double v); 
};

After this, it also seems pretty clear that since every single record is saved in a biff file format, it would be nice have a abstract BIFFRecord class and that every single record should be derived from it.

class BIFFRecord{
  ...

  /* Write a BIFF header for the opcode nRecno of length nRecLen */
  void Write (LittleEndianWriter *pWriter, int nRecNo, int nRecLen);

public:

  /* We should be able to write every type of BIFF records */
  virtual void Write (LittleEndianWriter *pWriter) = 0; 
}; 

This being done, implementing excel file saving is only adding the required BIFF records. I added in this demo project BOF, EOF, NUMBER and LABEL (others should be easy to add). We also need a generic container class, so that Excel file creation is easy. The container class is needed because BIFF records have to be in a specific order in the XLS file and it's nice if the container class does this for us:

class CMiniExcel{
  ...
public:
  ... 
  /* Access the columns in the excel document */
  ExcelCell &operator() (unsigned row, unsigned column);

  /* Write into a file. */
  void Write (FILE *dest);
};

Note that the operator () returns an ExcelCell. This is just a simple container for either numbers or strings and it makes like a lot easier when coding by not having to worry about cell types in the Excel Workbook.

Final notes

This is by no means a complete project. The saving is basic and error checking is almost none existing. Adding other BIFF records to the generic format should be pretty easy and if somebody finds it useful, I might add a few more into this demo source code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Andrei Litvin
Web Developer
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberchang 210 May '13 - 17:23 
Good Job.
QuestionBOLD and COLORmemberallegroaallegroa28 Oct '11 - 4:01 
Hi Andrei,
 
thanks for your code it was been very usefull for my application.
 
It's not clear how I can made a cell with attributes BOLD or COLOR; I've tried many and many times without results.
 
Can you help me?
Thanks
Ale
QuestionHow to save Date and Timememberabhirajundefined22 Feb '10 - 22:58 
Hi Andrei,
 
I want to save date and time in my excel file. How to do using your miniexcel?
News[ANN] Libexcel library for writing xls-filesmemberchipmunk20 Jul '08 - 5:16 
http://libexcel.com
GeneralRe: [ANN] Libexcel library for writing xls-filesmemberMember 843316529 Nov '11 - 7:38 
it´s not free... WTF | :WTF:
GeneralMore than one time writememberSimon Potzkai25 Jun '08 - 21:11 
Hi,
i want to write into the fiel more then one time.
For example:
I write some strings into the File.
And via one for loop, i will write at the end of file with miniexcel.write(f).
 
But this doesn't work.
Has anybody an idea?
 
Greets
GeneralSystem Hang(quite urgent)....membermk200627 Jun '07 - 21:43 
Hi Andrei ,
 
Thanks for your information and thid file.
 
but i used your concept in my project , but my system hanging after i run 10 min..
just the normal error(system.exe encounterd a problem)comes out..
 
afterthat if restart , then it works fine..
 
i couldn't findout where id the problem exactly..
 
the following code u sed your function.. i just stored the listview result into excel worksheet..
please have a look at code, and reply me what is the mistake i made?? i already include your headerand .cpp file..i used to store in .csv file..
 
please why system hang some times..??
 
void CResultList::saveTest()
{
 
int m = 0 ;
CTime time= CTime::GetCurrentTime();
CString s = time.Format( "%H, %M, %d, %Y" );
CString filename;
char newline = '\n';
 
filename = "C:\\Data\\MODEL"+ m_modelName + s + ".csv";

FILE *fp = fopen(filename, "wb");
 
if(fp != NULL)
{
CMiniExcel miniexcel;
miniexcel(0,0) = "No";
miniexcel(0,1) ="Name";
miniexcel(0,2) ="Description";
miniexcel(0,3) ="Low";
miniexcel(0,4) ="High";
miniexcel(0,5) ="Reading";
miniexcel(0,6) ="Result";
 
for (int i = 0; i < m_totalRows; i++)
{
 
m = i + 1;

miniexcel(m,0)= GetListCtrl().GetItemText(i, 2);
miniexcel(m,1) =GetListCtrl().GetItemText(i, 3);
miniexcel(m,2) = GetListCtrl().GetItemText(i, 4);
miniexcel(m,3)= GetListCtrl().GetItemText(i, 5);
miniexcel(m,4) = GetListCtrl().GetItemText(i, 6);
miniexcel(m,5) = GetListCtrl().GetItemText(i, 7);
miniexcel(m,6) = GetListCtrl().GetItemText(i, 8);

}

miniexcel.Write(fp);
 
}
fclose(fp);
 
}
 

waiting for your valubale reply..
 
with regards,
mk..

QuestionHow write a formulate ?memberCG2i0325 May '07 - 23:15 
Hi,
Thank for your library !
How write a formulate with your library ?
For example : "=B1+B2"
 
Thank !
General.csv file ??? [modified]membermkmut25 Apr '07 - 20:26 
Hi,
first of all i like congrtas to you for your great works done here..

using this one how to make .csv file instaed of excel file???
 
i want to write in to .csv file instaed if excel file??
 
how to i do??
 
waiting for your valable reply...
 
with regards,
Mk..
 

 
-- modified at 2:41 Thursday 26th April, 2007
GeneralRe: .csv file ???membermkmut25 Apr '07 - 20:38 
Sorry.. not.cav file...
.csv file..
sorry for spcelling mistake..
 
how to make it .csv file??
 
with regards,
Mk..
QuestionHow should I save a picture into this?membersuvendu Laha6 Dec '06 - 11:48 
Could you please suggest me how to store a picture into xls file format?
 

 
suvendu
Generalproblem in strdup (); functionmemberGlamar22 Nov '06 - 19:37 
I have tried the given example but there are 3 error in strdup();
 
Also this function is not defined anywhere in the given file.
 
Please give the solution for this function error.
 
I put command at this 3 error place. but runtime memory exception rised.

GeneralRe: problem in strdup (); functionmemberGlamar26 Nov '06 - 19:40 
i have try to implement strdup() function like this

somewhere in vector implementation area have problem.
 
Still problem.
 
static char *strdup(const char *s)
{
int len = strlen(s) + 1;
r = (char*)malloc(len);
memcpy(r,s,len);
return r;
}
 
give a solution.
GeneralThank you very much Andrey!memberLac_equinu25 Jul '06 - 14:27 
I want to send for you very big respect! Your are very good programmer though I have some errors while embedding your code in MFC project(I had C1010 error...) but any way I'm using your code with big glad!Big Grin | :-D

GeneralMerger Cellmembermbcvamsidhar6 Jun '06 - 5:28 
Hi,
Is it possible to merge cells from your files?
 
VD
 
Thanks and Rgds,
VamsiDhar.MBC
SoftwareEngineer.
QuestionHow to run it in VC environmentmemberthomsy23 May '06 - 20:25 
Actually i am facing a problem when i run the code in VC++ 6.0,its telling Winmain 16.Can u help me in this?

AnswerRe: How to run it in VC environmentmemberemranallan22 Sep '06 - 22:05 
It is in Project-> Settings->C/C++->Category->Precompiled headers->not using precompiled headers.
 
with best regards
AnswerRe: How to run it in VC environmentmemberdavemaster9924 Nov '06 - 7:05 
Hi
 
Chage your project properties to "console mode" not win32, thats all....
 
good luck
QuestionHow to Run In Visual C++6?memberChhoto Bou15 May '06 - 9:27 
Hi.
 
Thanks for support. Can u plz feedback to me that how i can run this code under visual C++6?
 
Bye.

AnswerRe: How to Run In Visual C++6?memberAndrei Litvin6 Jul '06 - 13:23 
There are likely a few issues that can arise with VC6 (did not test it, but this would be my best guess):
 
Precompiled header errors, in which case you either add a "#include " in every ".cpp" file or you disable precompiled headers for the mini-excel files.
 
WinMain definitions, in which case your project file is likely not configured to use "main(int, char **)" as the main function, so you will have to rename it.
 
I hope this helps in some way,
Andrei
GeneralRe: How to Run In Visual C++6?memberemranallan24 Sep '06 - 1:04 
if still get error
 
go to --Project-> Settings->C/C++->Category->Precompiled headers->not using precompiled headers.
 
with best regards Cool | :cool:

QuestionHow to process merged cell?memberwangqinyincoder27 Mar '06 - 16:34 
Hello:
Big Grin | :-D
1) Is it has Process "merged cell"( see follow ) Record in Excel 2.1
   Like this:
      A               B            C            D      ...
   ----------------------------------------
1 |   merged cell   |            |            |   ...
   ----------------------------------------
2 |            |            |            |            |   ...
   ----------------------------------------
3      .            .            .            .         ...
.      .            .            .            .         ...
.      .            .            .            .         ...
.      .            .            .            .         ...
 
2) What is mean the "Cell is hidden" bit in "rgbAttr" field ? Is it related to other Record or Bit of other Record?
   Please help me!
GeneralStringsize.memberPeter Hendrix27 Mar '06 - 2:09 
Hi,
 
Great class.
I noticed that the length of string values is limited to 256 characters.
I have tried extending this value however I cannot get it to work.
 
Could anybody help me on this any help would be greatly appreciated.
 
Regards,
Peter Hendrix.
GeneralRe: Stringsize.memberAndrei Litvin6 Jul '06 - 13:29 
In the BIFF format that this version of Excel uses, the string length is held in 1 byte, so you cannot really have strings longer than 256 characters (or at least I am not sure how you could manage to do that).
GeneralTried to compile you code, gives memory exception errormembermawani3112 Jan '06 - 23:22 
hi,
i tried to compile you code in (Microsoft development environment 2003 version 7.1.3008)
but it is giving me memory exception.
 
it is really helpfull.
i need to create the excel file for report generation.
 
will be thankful to you if you give some more details.
 
thanks in advance
mawani311@rediffmail.com

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 13 Sep 2002
Article Copyright 2002 by Andrei Litvin
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid