// Created by Yap Chun Wei // Version 1.0 (20 April 2006) // Version 1.1 (22 April 2006) // - Fixed bugs with compound files not being able to write files more than 65535 bytes. // - Fixed bugs with reading and writing to Excel files containing many strings. // Version 1.2 (30 April 2006) // - Added operator<< to pass BasicExcelCell to an output stream. // - Added Print() to BasicExcelWorksheet to print the worksheet to an output stream. // - Change BasicExcelCell Get functions to const functions. // - Rename BasicExcelWorksheet functions RenameWorkSheet() to Rename(). // Version 1.3 (10 May 2006) // - Fixed bugs with reading from Excel files containing Asian characters. // Version 1.4 (13 May 2006) // - Fixed bugs with reading and writing to Excel files containing many strings. // Version 1.5 (15 May 2006) // - Remove code for ExtSST because it was causing problems with reading and writing to Excel files containing many strings. // Version 1.6 (16 May 2006) // - Optimized code for reading and writing. // Version 1.7 (22 May 2006) // - Fixed code to remove some warnings. // - Fixed bug with BasicExcelWorksheet::Cell. // - Fixed bug with BasicExcel::UpdateWorksheets(). // Version 1.8 (23 May 2006) // - Fixed bug with reading Excel files containing many unicode strings. // - Fixed code to remove some warnings. // - Fixed variable code_ duplication in BoolErr. // - Minor changes to BasicExcelCell:Set functions. // Version 1.9 (24 May 2006) // - Changed name_ in Style from SmallString to LargeString. // - Fixed bug in BasicExcelCell::GetString and BasicExcelCell::GetWString. // - Minor changes to functions in BasicExcel and BasicExcelWorksheet which checks for unicode. // - Minor change to SmallString::Read. // Version 1.10 (30 May 2006) // - Fixed bug with reading Excel files containing many strings. // - Remove memory leaks. // Version 1.11 (2 June 2006) // - Fixed bug with reading and writing Excel files containing many unicode and ANSI strings. // Version 1.12 (6 June 2006) // - Fixed bug with reading and writing Excel files containing many unicode and ANSI strings. // Version 1.13 (1 August 2006) // - Changed BasicExcelCell::Get() so that it will get a stored double as an integer or vice versa if necessary. // - Changed BasicExcelCell::Get() so that it will not cause any errors if a string is empty. // - Changed BasicExcelCell::SetString() and BasicExcelCell::SetWString() so that it will not save an empty string. // Version 1.14 (6 August 2006) // - Fixed bug with reading Excel files that contain a null string. // Version 2.0 (September 2009, Martin Fuchs) // - extended to maintain font and format information when reading and writing Excel sheets // - XLSFormatManager, ExcelFont and CellFormat to edit fonts and formats // Version 2.1 (04.10.2009, Martin Fuchs) // - fixed memory leak in XLSFormatManager::get_font_idx() // - define macros and constants for cell and font properties // Version 2.2 (07.11.2009, Martin Fuchs) // - fixed VS2008 problem when reading sheets with formula fields // - added BasicExcel::Close() // - added CellFormat::get/set_text_props() and get/set_borderlines() // Version 2.3 (05.01.2009, Ami Castonguay/Martin Fuchs) // - fixed reference counting of Formula data structs // - support for shared formulas // - support for merged cells // - save formatting even if cell is empty // - flush fstream instead of closing it followed by open to prevent races in conjunction with virus scanners // - enable reading of XLS files exported by MacOS Numbers.app #ifndef BASICEXCEL_HPP #define BASICEXCEL_HPP //MF #if defined(_MSC_VER) && _MSC_VER<=1200 // VC++ 6.0 #pragma warning(disable: 4786) #define LONGINT __int64 #define LONGINT_CONST(x) x #define COMPOUNDFILE #else // newer Microsoft compilers #define LONGINT long long #define COMPOUNDFILE CompoundFile:: #define LONGINT_CONST(x) x##LL #endif #if _MSC_VER>=1400 // VS 2005 #define _CRT_SECURE_NO_WARNINGS //MF #define _SCL_SECURE_NO_WARNINGS //MF #endif #ifdef __GNUC__ #define FMT_SIZE_T "%zu" #define FMT_SSIZE_T "%zd" #define FMT_PTRDIFF_T "%zd" #elif _MSC_VER>=1400 // VS 2005 #define FMT_SIZE_T "%Iu" #define FMT_SSIZE_T "%Id" #define FMT_PTRDIFF_T "%Id" #else #define FMT_SIZE_T "%u" #define FMT_SSIZE_T "%d" #define FMT_PTRDIFF_T "%d" #endif #include #include #include #include #include #include #include #include #include //MF using namespace std; // get facet from locale for GCC #ifndef _USE #define _USE(loc, fac) use_facet(loc) #endif #include //MF #define UTF16 #ifdef UTF16 #define SIZEOFWCHAR_T 2 #else #define SIZEOFWCHAR_T sizeof(wchar_t) #endif namespace YCompoundFiles { class Block // PURPOSE: In charge of handling blocks of data from a file { public: Block(); // File handling functions bool Create(const wchar_t* filename); bool Open(const wchar_t* filename, ios_base::openmode mode=ios_base::in | ios_base::out); bool Close(); bool IsOpen(); // Block handling functions bool Read(size_t index, char* block); bool Write(size_t index, const char* block); bool Swap(size_t index1, size_t index2); bool Move(size_t from, size_t to); bool Insert(size_t index, const char* block); bool Erase(size_t index); bool Erase(vector& indices); // Misc functions size_t GetBlockSize() const {return blockSize_;} void SetBlockSize(size_t size) { blockSize_ = size; indexEnd_ = fileSize_/blockSize_ + (fileSize_ % blockSize_ ? 1 : 0); } protected: vector filename_; ios_base::openmode mode_; fstream file_; size_t blockSize_; size_t indexEnd_; size_t fileSize_; }; struct LittleEndian { #if defined(_MSC_VER) && _MSC_VER<=1200 // VC++ 6.0 #define READWRITE(Type) \ static void Read(const char* buffer, Type& retVal, int pos=0, int bytes=0) \ { \ retVal = Type(0); \ if (bytes == 0) bytes = sizeof(Type); \ for (size_t i=0; i>= 8; \ } \ } \ static void WriteString(char* buffer, Type* str, int pos=0, int bytes=0) \ { \ for (size_t i=0; i& buffer, Type& retVal, int pos=0, int bytes=0) \ { \ retVal = Type(0); \ if (bytes == 0) bytes = sizeof(Type); \ for (size_t i=0; i& buffer, Type* str, int pos=0, int bytes=0) \ { \ for (size_t i=0; i& buffer, Type val, int pos=0, int bytes=0) \ { \ if (bytes == 0) bytes = sizeof(Type); \ for (size_t i=0; i>= 8; \ } \ } \ static void WriteString(vector& buffer, Type* str, int pos=0, int bytes=0) \ { \ for (size_t i=0; i>= 8; } } static void WriteString(char* buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i& buffer, wchar_t& retVal, int pos=0, int bytes=0) { retVal = wchar_t(0); if (bytes == 0) bytes = SIZEOFWCHAR_T; for (int i=0; i& buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i& buffer, wchar_t val, int pos=0, int bytes=0) { if (bytes == 0) bytes = SIZEOFWCHAR_T; for (int i=0; i>= 8; } } static void WriteString(vector& buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i static void Read(const char* buffer, Type& retVal, int pos=0, int bytes=0) { retVal = Type(0); if (bytes == 0) bytes = sizeof(Type); for (int i=0; i static void ReadString(const char* buffer, Type* str, int pos=0, int bytes=0) { for (int i=0; i static void Write(char* buffer, Type val, int pos=0, int bytes=0) { if (bytes == 0) bytes = sizeof(Type); for (int i=0; i>= 8; } } template static void WriteString(char* buffer, Type* str, int pos=0, int bytes=0) { for (int i=0; i static void Read(const vector& buffer, Type& retVal, int pos=0, int bytes=0) { retVal = Type(0); if (bytes == 0) bytes = sizeof(Type); for (int i=0; i static void ReadString(const vector& buffer, Type* str, int pos=0, int bytes=0) { for (int i=0; i static void Write(vector& buffer, Type val, int pos=0, int bytes=0) { if (bytes == 0) bytes = sizeof(Type); for (int i=0; i>= 8; } } template static void WriteString(vector& buffer, Type* str, int pos=0, int bytes=0) { for (int i=0; i>= 8; } } static void WriteString(char* buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i& buffer, wchar_t& retVal, int pos=0, int bytes=0) { retVal = wchar_t(0); if (bytes == 0) bytes = SIZEOFWCHAR_T; for (int i=0; i& buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i& buffer, wchar_t val, int pos=0, int bytes=0) { if (bytes == 0) bytes = SIZEOFWCHAR_T; for (int i=0; i>= 8; } } static void WriteString(vector& buffer, wchar_t* str, int pos=0, int bytes=0) { for (int i=0; i& path); int RemoveDirectory(const wchar_t* path); int DelTree(const wchar_t* path); int DirectoryList(vector >& list, const wchar_t* path=0); // File functions int MakeFile(const wchar_t* path); int RemoveFile(const wchar_t* path); int FileSize(const wchar_t* path, size_t& size); int ReadFile(const wchar_t* path, char* data); int ReadFile(const wchar_t* path, vector&data); int WriteFile(const wchar_t* path, const char* data, size_t size); int WriteFile(const wchar_t* path, const vector&data, size_t size); // ANSI char functions bool Create(const char* filename); bool Open(const char* filename, ios_base::openmode mode=ios_base::in | ios_base::out); int ChangeDirectory(const char* path); int MakeDirectory(const char* path); int PresentWorkingDirectory(char* path); int PresentWorkingDirectory(vector& path); int RemoveDirectory(const char* path); int DelTree(const char* path); int MakeFile(const char* path); int RemoveFile(const char* path); int FileSize(const char* path, size_t& size); int ReadFile(const char* path, char* data); int ReadFile(const char* path, vector& data); int WriteFile(const char* path, char* data, size_t size); int WriteFile(const char* path, vector& data, size_t size); // Protected functions and data members protected: // General functions and data members void IncreaseLocationReferences(vector indices); void DecreaseLocationReferences(vector indices); void SplitPath(const wchar_t* path, wchar_t*& parentpath, wchar_t*& propertyname); vector block_; Block file_; // Header related functions and data members bool LoadHeader(); void SaveHeader(); class Header { public: Header(); void Write(char* block); void Read(char* block); LONGINT fileType_; // Magic number identifying this as a compound file system (0x0000) int uk1_; // Unknown constant (0x0008) int uk2_; // Unknown constant (0x000C) int uk3_; // Unknown constant (0x0010) int uk4_; // Unknown constant (0x0014) short uk5_; // Unknown constant (revision?) (0x0018) short uk6_; // Unknown constant (version?) (0x001A) short uk7_; // Unknown constant (0x001C) short log2BigBlockSize_; // Log, base 2, of the big block size (0x001E) int log2SmallBlockSize_; // Log, base 2, of the small block size (0x0020) int uk8_; // Unknown constant (0x0024) int uk9_; // Unknown constant (0x0028) size_t BATCount_; // Number of elements in the BAT array (0x002C) size_t propertiesStart_; // Block index of the first block of the property table (0x0030) int uk10_; // Unknown constant (0x0034) int uk11_; // Unknown constant (0x0038) size_t SBATStart_; // Block index of first big block containing the small block allocation table (SBAT) (0x003C) size_t SBATCount_; // Number of big blocks holding the SBAT (0x0040) size_t XBATStart_; // Block index of the first block in the Extended Block Allocation Table (XBAT) (0x0044) size_t XBATCount_; // Number of elements in the Extended Block Allocation Table (to be added to the BAT) (0x0048) size_t BATArray_[109]; // Array of block indices constituting the Block Allocation Table (BAT) (0x004C, 0x0050, 0x0054 ... 0x01FC) size_t bigBlockSize_; size_t smallBlockSize_; private: void Initialize(); }; Header header_; // BAT related functions and data members void LoadBAT(); void SaveBAT(); size_t DataSize(size_t startIndex, bool isBig); size_t ReadData(size_t startIndex, char* data, bool isBig); size_t WriteData(const char* data, size_t size, int startIndex, bool isBig); void GetBlockIndices(size_t startIndex, vector& indices, bool isBig); size_t GetFreeBlockIndex(bool isBig); void ExpandBATArray(bool isBig); void LinkBlocks(size_t from, size_t to, bool isBig); void FreeBlocks(vector& indices, bool isBig); vector blocksIndices_; vector sblocksIndices_; // Properties related functions and data members class Property { public: Property(); void Write(char* block); void Read(char* block); friend bool operator==(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) { return (!wcscmp(lhs.name_, rhs.name_)); } friend bool operator< (const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) { size_t maxLen1 = wcslen(lhs.name_); size_t maxLen2 = wcslen(rhs.name_); if (maxLen1 < maxLen2) return true; else if (maxLen1 > maxLen2) return false; else { int result = wcscmp(lhs.name_, rhs.name_); if (result <= 0) return true; else return false; } } friend bool operator!=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(lhs == rhs);} friend bool operator> (const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return (rhs < lhs);} friend bool operator<=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(rhs < lhs);} friend bool operator>=(const COMPOUNDFILE Property& lhs, const COMPOUNDFILE Property& rhs) {return !(lhs < rhs);} wchar_t name_[32]; // A unicode null-terminated uncompressed 16bit string (lblocke the high bytes) containing the name of the property. (0x00, 0x02, 0x04, ... 0x3E) short nameSize_; // Number of characters in the NAME field (0x40) unsigned char propertyType_; // Property type (directory, file, or root) Byte 1 (directory), 2 (file), or 5 (root entry) (0x42) unsigned char nodeColor_; // Node color (0x43) size_t previousProp_; // Previous property index (0x44) size_t nextProp_; // Next property index (0x48) size_t childProp_; // First child property index (0x4c) int uk1_; int uk2_; int uk3_; int uk4_; int uk5_; int seconds1_; // Seconds component of the created timestamp? (0x64) int days1_; // Days component of the created timestamp? (0x68) int seconds2_; // Seconds component of the modified timestamp? (0x6C) int days2_; // Days component of the modified timestamp? (0x70) size_t startBlock_; // Starting block of the file, used as the first block in the file and the pointer to the next block from the BAT (0x74) int size_; // Actual size of the file this property points to. (used to truncate the blocks to the real size). (0x78) }; class PropertyTree { public: PropertyTree(); ~PropertyTree(); PropertyTree* parent_; Property* self_; size_t index_; vector children_; }; void LoadProperties(); void SaveProperties(); int MakeProperty(const wchar_t* path, Property* property); PropertyTree* FindProperty(size_t index); PropertyTree* FindProperty(const wchar_t* path); PropertyTree* FindProperty(PropertyTree* parentTree, wchar_t* name); void InsertPropertyTree(PropertyTree* parentTree, Property* property, size_t index); void DeletePropertyTree(PropertyTree* tree); void UpdateChildrenIndices(PropertyTree* parentTree); void IncreasePropertyReferences(PropertyTree* parentTree, size_t index); void DecreasePropertyReferences(PropertyTree* parentTree, size_t index); PropertyTree* propertyTrees_; PropertyTree* currentDirectory_; vector properties_; vector previousDirectories_; }; } // YCompoundFiles namespace end // reference counting to implement smart pointers namespace RefCount { // reference counter for SmartPtr managed objects struct RefCnt { // On construction the reference counter is initialized with an usage count of 0. RefCnt() : _ref_cnt(0) { } int _ref_cnt; }; // reference counting smart pointer template struct SmartPtr { // default constructor SmartPtr() : _ptr(NULL) { } // The initialized SmartPtr constructor increments the reference counter in struct RefCnt. SmartPtr(T* p) : _ptr(p) { if (p) ++_ptr->_ref_cnt; } // The copy constructor increments the reference counter. SmartPtr(const SmartPtr& other) : _ptr(other._ptr) { if (_ptr) ++_ptr->_ref_cnt; } // The destructor decreases the reference counter and // frees the managed memory as the counter reaches zero. ~SmartPtr() { if (_ptr) { if (!--_ptr->_ref_cnt) delete _ptr; } } // The assignment operator increments the reference counter. SmartPtr& operator=(T* p) { if (_ptr) { if (!--_ptr->_ref_cnt) delete _ptr; _ptr = NULL; } if (p) { _ptr = p; ++_ptr->_ref_cnt; } return *this; } // operator bool() to check for non-empty smart pointers operator bool() const {return _ptr != NULL;} // operator!() to check for empty smart pointers bool operator!() const {return !_ptr;} // operator->() to access the managed objects T* operator->() {return _ptr;} const T* operator->() const {return _ptr;} // Derefence pointed memory T& operator*() {return *_ptr;} const T& operator*() const {return *_ptr;} private: T* _ptr; }; } // namespace RefCount //MF namespace ExcelFormat { struct CellFormat; } namespace YExcel { using namespace YCompoundFiles; struct CODE { enum { FORMULA=0x0006, //Token array and the result of a formula cell. YEOF=0x000A, //End of a record block with leading BOF record. CALCCOUNT=0x000C, //Maximum number of times the forumlas should be iteratively calculated CALCMODE=0x000D, //Calculate formulas manually, automatically, or automatically except for multiple table operations PRECISION=0x000E, //Whether formulas use the real cell values for calculation or the values displayed on the screen. REFMODE=0x000F, //Method used to show cell addresses in formulas. DELTA=0x0010, //Maximum change of the result to exit an iteration. ITERATION=0x0011, //Whether iterations are allowed while calculating recursive formulas. PROTECT=0x0012, //Whether worksheet or a workbook is protected against modification. PASSWORD=0x0013, //16-bit hash value, calculated from the worksheet or workbook protection password. HEADER=0x0014, //Page header string for the current worksheet. FOOTER=0x0015, //Page footer string for the current worksheet. EXTERNSHEET=0x0017, //List with indexes to SUPBOOK records NAME=0x0018, //Name and token array of an internal defined name. WINDOWPROTECT=0x0019, //Whether the window configuration of the document is protected. SELECTION=0x001D, //Addresses of all selected cell ranges and position of the active cell for a pane in the current sheet. DATEMODE=0x0022, //Base date for displaying date values. EXTERNNAME=0x0023, //Name of an external defined name, name of an add-in function, a DDE item or an OLE object storage identifier. LEFTMARGIN=0x0026, //Left page margin of the current worksheet. RIGHTMARGIN=0x0027, //Right page margin of the current worksheet. TOPMARGIN=0x0028, //Top page margin of the current worksheet. BOTTOMMARGIN=0x0029, //Bottom page margin of current worksheet PRINTHEADERS=0x002A, //Whether row and column headers (the areas with row numbers and column letters) will be printed. PRINTGRIDLINES=0x002B, //Whether sheet grid lines will be printed. FILEPASS=0x002F, //Information about the read/write password of the file. FONT=0x0031, //Information about a used font, including character formatting. TABLE=0x0036, //Information about a multiple operation table in the sheet. CONTINUE=0x003C, //Continue from previous record WINDOW1=0x003D, //General settings for the workbook global settings. BACKUP=0x0040, //Make backup of file while saving? PANE=0x0041, //Position of window panes. CODEPAGE=0x0042, //Text encoding used to encode byte strings DCONREF=0x0051, DEFCOLWIDTH=0x0055, //Default column width for columns that do not have a specific width set XCT=0x0059, //Number of immediately following CRN records. CRN=0x005A, //Contents of an external cell or cell range. FILESHARING=0x005B, //Information about write protection, for instance the write protection password. WRITEACCESS=0x005C, //Name of the user that has saved the file. UNCALCED=0x005E, //Formulas have not been recalculated before the document was saved. SAVERECALC=0x005F, //"Recalculate before save" option OBJECTPROTECT=0x0063, //Whether objects of the current sheet are protected. COLINFO=0x007D, //Width for a given range of columns GUTS=0x0080, //Layout of outline symbols. WSBOOL=0x0081, //16-bit value with boolean options for the current sheet. GRIDSET=0x0082, //Whether option to print sheet grid lines has ever been changed. HCENTER=0x0083, //Sheet is centred horizontally when printed. VCENTER=0x0084, //Whether sheet is centred vertically when printed. BOUNDSHEET=0x0085, //Sheet inside of the workbook WRITEPROT=0x0086, //Whether file is write protected. COUNTRY=0x008C, //User interface language of the Excel version that has saved the file, system regional settings at the time the file was saved. HIDEOBJ=0x008D, //Whether and how to show objects in the workbook. SORT=0x0090, //Last settings from the "Sort" dialogue for each sheet. PALETTE=0x0092, //Definition of all user-defined colours available for cell and object formatting. SETUP=0x00A1, //Page format settings of the current sheet. SHRFMLA=0x00BC, //Token array of a shared formula. MULRK=0x00BD, //Cell range containing RK value cells. All cells are located in the same row. MULBLANK=0x00BE, //Cell range of empty cells. All cells are located in the same row. DBCELL=0x00D7, //Relative offsets to calculate stream position of the first cell record for each row. BOOKBOOL=0x00DA, //Save values linked from external workbooks records and XCT records? SCENPROTECT=0x00DD, //Whether scenarios of the current sheet are protected. XF=0x00E0, //Formatting information for cells, rows, columns or styles. MERGEDCELLS=0x00E5, //All merged cell ranges of the current sheet. SST=0x00FC, //List of all strings used anywhere in the workbook. LABELSST=0x00FD, //Cell that contains a string. EXTSST=0x00FF, //Create a hash table with stream offsets to the SST record to optimise string search operations. LABELRANGES=0x015F, //Addresses of all row and column label ranges in the current sheet. USESELFS=0x0160, //Whether formulas in the workbook can use "natural language formulas". DSF=0x0161, //Whether file contains an addition BIFF5/BIFF7 workbook stream. SUPBOOK=0x01AE, //URL of an external document and a list of sheet names inside this document. CONDFMT=0x01B0, //List of cell range addresses for all cells with equal conditional formatting. CF=0x01B1, //Condition and the formatting attributes applied to the cells specified in the CONDFMT record, if the condition is met DVAL=0x01B2, //List header of the data validity table in the current sheet. HLINK=0x01B8, //One cell address or a cell range where all cells contain the same hyperlink. DV=0x01BE, //Data validity settings and a list of cell ranges which contain these settings. DIMENSIONS=0x0200, //Range address of the used area in the current sheet. BLANK=0x0201, //Empty cell, contains cell address and formatting information NUMBER=0x0203, //Cell that contains a floating-point value. BOOLERR=0x0205, //Error value cell STRING=0x0207, //Result of a string formula. ROW=0x0208, //Properties of a single row in the sheet. INDEX=0x020B, //Range of used rows and stream positions of several records of the current sheet. ARRAY=0x0221, //Token array of an array formula WINDOW2=0x023E, //Additional settings for the window of a specific worksheet. RK=0x027E, //Cell that contains an RK value (encoded integer or floating point value). STYLE=0x0293, //Name of a user-defined cell style or specific options for a built-in cell style. FORMAT=0x041E, //Number format. SHRFMLA1=0x04BC, //Token array of a shared formula (added). QUICKTIP=0x0800, //Cell range and text for a tool tip. BOF=0x0809, //Beginning of file SHEETLAYOUT=0x0862, //Colour of the tab below the sheet containing the sheet name. SHEETPROTECTION=0x0867, //Additional options for sheet protection. RANGEPROTECTION=0x0868 //Information about special protected ranges in a protected sheet. }; }; class Record { public: Record(); virtual ~Record(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); short code_; vector data_; size_t dataSize_; size_t recordSize_; vector continueIndices_; }; struct BOF : public Record { BOF(); virtual size_t Read(const char* data); virtual size_t Write(char* data); short version_; short type_; short buildIdentifier_; short buildYear_; int fileHistoryFlags_; int lowestExcelVersion_; }; struct YEOF : public Record { YEOF(); }; // String with 1 byte length field struct SmallString { SmallString(); ~SmallString(); SmallString(const SmallString& s); SmallString& operator=(const SmallString& s); const SmallString& operator=(const char* str); const SmallString& operator=(const wchar_t* str); void Reset(); size_t Read(const char* data); size_t Write(char* data); size_t DataSize(); size_t RecordSize(); size_t StringSize(); wchar_t* wname_; char* name_; char unicode_; }; // String with 2 byte length field struct LargeString { LargeString(); ~LargeString(); LargeString(const LargeString& s); LargeString& operator=(const LargeString& s); const LargeString& operator=(const char* str); const LargeString& operator=(const wchar_t* str); void Reset(); size_t Read(const char* data); size_t ContinueRead(const char* data, size_t size); size_t Write(char* data); size_t DataSize(); size_t RecordSize(); size_t StringSize(); vector wname_; vector name_; char unicode_; short richtext_; int phonetic_; }; //MF string conversion functions // Courtesy of Tom Widmer (VC++ MVP) inline std::string narrow_string(const std::wstring& str) { std::string ret; ret.resize(str.length()); typedef std::ctype CT; CT const& ct = std::_USE(std::locale(), CT); ct.narrow(&str[0], &*str.begin()+str.size(), '?', &ret[0]); return ret; } inline std::string narrow_string(const vector& wstr) { return narrow_string(wstring(&*wstr.begin(), wstr.size())); } inline std::wstring widen_string(const std::string& str) { std::wstring ret; ret.resize(str.length()); typedef std::ctype CT; CT const& ct = std::_USE(std::locale(), CT); ct.widen(&str[0], &*str.begin()+str.size(), &ret[0]); return ret; } inline std::wstring widen_string(const vector& wstr) { return widen_string(string(&*wstr.begin(), wstr.size())); } inline string stringFromSmallString(const SmallString& ss) { if (ss.unicode_) return narrow_string(ss.wname_); else return ss.name_; } inline string stringFromLargeString(const LargeString& ls) { if (ls.unicode_) return narrow_string(ls.wname_); else return string(&*ls.name_.begin(), ls.name_.size()); } inline wstring wstringFromSmallString(const SmallString& ss) { if (ss.unicode_) return ss.wname_; else return widen_string(ss.name_); } inline wstring wstringFromLargeString(const LargeString& ls) { if (ls.unicode_) return wstring(&*ls.wname_.begin(), ls.wname_.size()); else return widen_string(ls.name_); } class Workbook { public: Workbook(); public: struct FileProtection; struct CodePage; struct DSF; struct TabID; struct FnGroupCount; struct WorkbookProtection; struct Window1 : public Record { Window1(); virtual size_t Read(const char* data); virtual size_t Write(char* data); short horizontalPos_; short verticalPos_; short width_; short height_; short options_; short activeWorksheetIndex_; short firstVisibleTabIndex_; short selectedWorksheetNo_; short worksheetTabBarWidth_; }; struct Backup; struct HideObj; struct DateMode; struct Precision; struct RefreshAll; struct BookBool; struct Font : public Record { Font(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); short height_; short options_; short colourIndex_; short weight_; short escapementType_; char underlineType_; char family_; char characterSet_; char unused_; SmallString name_; }; struct Format : public Record { //MF Format(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); short index_; LargeString fmtstring_; }; struct XF : public Record { XF(); virtual size_t Read(const char* data); virtual size_t Write(char* data); short fontRecordIndex_; short formatRecordIndex_; short protectionType_; char alignment_; char rotation_; char textProperties_; char usedAttributes_; int borderLines_; int colour1_; short colour2_; }; struct Style : public Record { Style(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); short XFRecordIndex_; char identifier_; char level_; LargeString name_; }; struct Palette; struct UseSelfs; struct BoundSheet : public Record { BoundSheet(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); int BOFpos_; char visibility_; char type_; SmallString name_; }; struct Country; struct LinkTable; struct SharedStringTable : public Record { SharedStringTable(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); int stringsTotal_; size_t uniqueStringsTotal_; vector strings_; }; struct ExtSST : public Record { ExtSST(); virtual size_t Read(const char* data); virtual size_t Write(char* data); virtual size_t DataSize(); virtual size_t RecordSize(); short stringsTotal_; vector streamPos_; vector firstStringPos_; vector unused_; }; size_t Read(const char* data); size_t Write(char* data); size_t DataSize(); size_t RecordSize(); BOF bof_; Window1 window1_; vector fonts_; vector XFs_; vector