From 3cca3e840ba20deee7dc24d8e3b4c1e1cd3c17bc Mon Sep 17 00:00:00 2001 From: smh Date: Tue, 1 Nov 2011 06:16:21 +0000 Subject: [PATCH] Export to Excel. Special classes to export data in native XLS 95-2003 format. --- src/Qtx/QtxXlsBiff.cxx | 661 ++++++++++++++++++++++++++++++++++ src/Qtx/QtxXlsBiff.h | 604 +++++++++++++++++++++++++++++++ src/Qtx/QtxXlsBorderTool.cxx | 669 +++++++++++++++++++++++++++++++++++ src/Qtx/QtxXlsBorderTool.h | 253 +++++++++++++ src/Qtx/QtxXlsWriter.cxx | 485 +++++++++++++++++++++++++ src/Qtx/QtxXlsWriter.h | 188 ++++++++++ 6 files changed, 2860 insertions(+) create mode 100755 src/Qtx/QtxXlsBiff.cxx create mode 100755 src/Qtx/QtxXlsBiff.h create mode 100755 src/Qtx/QtxXlsBorderTool.cxx create mode 100755 src/Qtx/QtxXlsBorderTool.h create mode 100755 src/Qtx/QtxXlsWriter.cxx create mode 100755 src/Qtx/QtxXlsWriter.h diff --git a/src/Qtx/QtxXlsBiff.cxx b/src/Qtx/QtxXlsBiff.cxx new file mode 100755 index 000000000..c7ee11981 --- /dev/null +++ b/src/Qtx/QtxXlsBiff.cxx @@ -0,0 +1,661 @@ +// Name : QtxXlsBiff.cpp +// Purpose: Implementation of QtxXlsBiff class. +// +// History: +// 17/10/11 - Oleg Agashin - Creation of the file + +#include + +/** + * + */ +QtxXlsBiff::QtxXlsBiff() +: myDefaultFontName("Arial"), + myDefaultFontSize(10), + mySheetName("Sheet1"), + myLabelsNum(0) +{ + clear(); +} + +/** + * Check that high bytes of string chars + * equal to 0 and can be skipped + */ +bool QtxXlsBiff::canBePacked( const QString& theStr ) +{ + QString::const_iterator anIt = theStr.begin(); + while( (anIt++) != theStr.end() ) + { + if ( (anIt->unicode() & 0xFF00) > 0 ) + return false; + } + return true; +} + +/** + * + */ +void QtxXlsBiff::SetSheetName( const QString& theName ) +{ + if( !theName.isEmpty() ) + mySheetName = theName; +} + +/** + * Clear all structures + */ +void QtxXlsBiff::clear() +{ + cleanBuffers(); + + myFontTable.clear(); + myFontNames.clear(); + addDefaultFonts(); + + myStyleTable.clear(); + addDefaultStyles(); + + mySSTTable.clear(); + myLabelsNum = 0; + + myMergedCells.clear(); + + myBlankCells.clear(); +} + +/** + * + */ +void QtxXlsBiff::cleanBuffers() +{ + myWbDataBuf.clear(); + myShDataBuf.clear(); +} + +/** + * BOF record + */ +void QtxXlsBiff::createBOF() +{ + BIFF8_BOF aBOF; + + //BOF for workbook + aBOF.biffRecord.biffNum = _BOF; + aBOF.biffRecord.length = SIZEOF(BIFF8_BOF); + aBOF.verOfBIFF = BIFF_ver; + aBOF.typeOfData = WorkbookGlobals; + aBOF.buildID = 0x0DBB; + aBOF.buildYear = 0x07CC; + aBOF.historyFlags = 0x41; + aBOF.lowestVer = 0x6; + myWbDataBuf.append( BYTE_ARRAY(aBOF.buf, sizeof(BIFF8_BOF)) ); + + //BOF for worksheet + aBOF.typeOfData = Sheet; + myShDataBuf.prepend( BYTE_ARRAY(aBOF.buf, sizeof(BIFF8_BOF)) ); +} + +/** + * WINDOW1 record + */ +void QtxXlsBiff::createWindow1() +{ + BIFF8_WINDOW1 aWND; + + aWND.biffRecord.biffNum = WINDOW1; + aWND.biffRecord.length = SIZEOF(BIFF8_WINDOW1); + aWND.xWnd = 0; + aWND.yWnd = 0; + aWND.dxWnd = 0x25BC; + aWND.dyWnd = 0x1572; + aWND.optionFlags = None; + aWND.fDspHScroll = 1; + aWND.fDspVScroll = 1; + aWND.fDisplayWbTabs = 1; + aWND.iSelWbTab = 0; + aWND.iFirstDispWbTab = 0; + aWND.selTabNum = 1; + aWND.wTabRatio = 0x0258; + + myWbDataBuf.append( BYTE_ARRAY(aWND.buf, sizeof(BIFF8_WINDOW1)) ); +} + +/** + * Date1904 record + */ +void QtxXlsBiff::createDate1904() +{ + BIFF8_DATE1904 aDate; + aDate.biffRecord.biffNum = DATE1904; + aDate.biffRecord.length = SIZEOF(BIFF8_DATE1904); + aDate.f1904 = None; + myWbDataBuf.append( BYTE_ARRAY(aDate.buf, sizeof(BIFF8_DATE1904)) ); +} + +/** + * Adds user-defined font into the font table + */ +int QtxXlsBiff::addFont( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold, + const XlsWORD theFontColor, + const XlsWORD theFontStyle, + const XlsWORD theSuperSubscriptType, + const XlsWORD theUnderlineType ) + +{ + BIFF8_FONT aFont = formatFontRecord( theFontName, + theFontSize, + theIsBold, + theFontColor, + theFontStyle, + theSuperSubscriptType, + theUnderlineType ); + + myFontTable.append( aFont ); + myFontNames.append( theFontName ); + + return myFontTable.size() - 1; +} + +/** + * + */ +QtxXlsBiff::BIFF8_FONT QtxXlsBiff::formatFontRecord( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold, + const XlsWORD theFontColor, + const XlsWORD theFontStyle, + const XlsWORD theSuperSubscriptType, + const XlsWORD theUnderlineType ) + +{ + BIFF8_FONT aFont; + aFont.biffRecord.biffNum = FONT; + //Beacause unicode + aFont.biffRecord.length = SIZEOF(BIFF8_FONT) + theFontName.length(); + aFont.height = theFontSize * 20; + aFont.fontAttr = theFontStyle; + aFont.color = theFontColor; + aFont.boldStyle = theIsBold ? BoldText : NormalText; + aFont.superSubStyle = theSuperSubscriptType; + aFont.underlineStyle = theUnderlineType; + aFont.fontFamily = None; + aFont.charSet = ANSI_Latin; + aFont.reserved = None; + aFont.fontNameLen = theFontName.length(); + aFont.unicodeStrFlags = Compressed; + + if ( !canBePacked( theFontName ) ) + { + aFont.unicodeStrFlags = Uncompressed; + aFont.biffRecord.length += theFontName.length(); + } + + return aFont; +} + +/** + * + */ +void QtxXlsBiff::addDefaultFonts() +{ + BIFF8_FONT aFont = formatFontRecord( myDefaultFontName, myDefaultFontSize ); + //MS Excel requires five font records at least + for( int i = 0; i < 5; i++ ) + { + myFontTable.append( aFont ); + myFontNames.append( myDefaultFontName ); + + } +} + +/** + * Packs all font records into font table + */ +void QtxXlsBiff::createFontTable() +{ + QByteArray aUnicodeByteName; + int aCount = myFontTable.size(); + + for( int i = 0; i < aCount; i++ ) + { + if ( myFontTable[i].unicodeStrFlags == Compressed ) + { + aUnicodeByteName.append( myFontNames[i] ); + } + else + { + aUnicodeByteName = unicodeToByteArray( myFontNames[i] ); + } + + myWbDataBuf.append( BYTE_ARRAY(myFontTable[i].buf, sizeof(BIFF8_FONT)) ); + myWbDataBuf.append( aUnicodeByteName ); + + aUnicodeByteName.clear(); + } +} + +/** + * Adds user-defined cell format into the format table + */ +int QtxXlsBiff::addCellStyle( const XlsWORD theFontID, + const XlsWORD theFormatID, + const XlsWORD theAlign, + const XlsWORD theVAlign, + const QtxXlsBiff::Border* theBorders, + const bool theIsWrapped, + const bool theIsMerged, + const XlsWORD theRotation, + const XlsBYTE theForegrountColorID, + const XlsBYTE theBackgrountColorID/*, + const XlsWORD theParentStyleID*/ ) +{ + BIFF8_XF aXF; + for( int i = 2; i < 24; i++ ) + aXF.buf[i] = 0; + + //Create default style formats + aXF.biffRecord.biffNum = XF; + aXF.biffRecord.length = SIZEOF(BIFF8_XF); + aXF.fontID = theFontID > 3 ? theFontID + 1 : theFontID; + aXF.formatID = theFormatID; + + aXF.fStyle = Cell; + aXF.ixfParent = NoParentStyle/*theParentStyleID*/; + + aXF.align = theAlign; + aXF.valign = theVAlign; + aXF.fWrap = theIsWrapped; + aXF.rotation = theRotation; + aXF.mergeCell = theIsMerged; + + + aXF.foregroundColor = theForegrountColorID; + aXF.backgroundColor = theBackgrountColorID; + + if( theBorders ) + { + aXF.left = theBorders->leftBorderStyle; + aXF.right = theBorders->rightBorderStyle; + aXF.top = theBorders->topBorderStyle; + aXF.bottom = theBorders->bottomBorderStyle; + + aXF.colorLeft = theBorders->leftBorderColor; + aXF.colorRight = theBorders->rightBorderColor; + aXF.colorTop = theBorders->topBorderColor; + aXF.colorBottom = theBorders->bottomBorderColor; + + aXF.diagBdrStyle = theBorders->diagonalBorderStyle; + aXF.diagonalType = theBorders->diagonalType; + aXF.colorDiagonal = theBorders->diagonalColor; + } + + myStyleTable.append( aXF ); + + return myStyleTable.size() - 1; +} + +/** + * + */ +void QtxXlsBiff::addDefaultStyles() +{ + BIFF8_XF aXF; + for( int i = 2; i < 24; i++ ) + aXF.buf[i] = 0; + + //Create default style formats + aXF.biffRecord.biffNum = XF; + aXF.biffRecord.length = SIZEOF(BIFF8_XF); + aXF.fStyle = Style; + aXF.ixfParent = NoParentStyle; + aXF.align = AlignGeneral; + aXF.valign = VAlignCenter; + aXF.foregroundColor = DefaultForegroundColor; + aXF.backgroundColor = DefaultBackgroundColor; + + //Table contains 15 style format records at least + for( int i = 0; i < 15; i++ ) + myStyleTable.append( aXF ); + + //Create default cell formats, + aXF.paramFlags = Cell; + myStyleTable.append( aXF ); +} + +/** + * Packs all cell format records into cell format table + */ +void QtxXlsBiff::createFormatTable() +{ + // Write additional format records here + QVector::iterator anIt = myStyleTable.begin(); + while( anIt != myStyleTable.end() ) + { + myWbDataBuf.append( BYTE_ARRAY((*anIt).buf, sizeof(BIFF8_XF)) ); + ++anIt; + } +} + +/** + * STYLE record + */ +void QtxXlsBiff::createStyleInfoTable() +{ + //Each style in an Excel workbook, whether built-in + //or user-defined, requires a style record + BIFF8_STYLE aStyle; + aStyle.biffRecord.biffNum = STYLE; + aStyle.biffRecord.length = SIZEOF(BIFF8_STYLE); + aStyle.iXF = None; + aStyle.ixfe = 0; + aStyle.fBuiltIn = 1; + aStyle.builtInStyle = Normal; + aStyle.level = 0xFF; + myWbDataBuf.append( BYTE_ARRAY(aStyle.buf, sizeof(BIFF8_STYLE)) ); +} + +/** + * Stores unicode value of string into byte array + * ( QString converts unicode char into ASCII char ) + */ +QByteArray QtxXlsBiff::unicodeToByteArray( const QString& theStr ) +{ + QByteArray aUnicodeByteName; + xlsWORDExcange anExchanger; + + for( int i = 0; i < theStr.length(); i++ ) + { + anExchanger.value = theStr[i].unicode(); + aUnicodeByteName.append( anExchanger.buf[0] ); + aUnicodeByteName.append( anExchanger.buf[1] ); + } + + return aUnicodeByteName; +} + +/** + * BOUNDSHEET record contains information about worksheet + */ +void QtxXlsBiff::createBoundsheet( const int theSSTLength ) +{ + BIFF8_BOUNDSHEET aBoundsheet; + aBoundsheet.biffRecord.biffNum = BOUNDSHEET; + aBoundsheet.biffRecord.length = SIZEOF(BIFF8_BOUNDSHEET) + mySheetName.length(); + + aBoundsheet.hiddenSate = Visible; + aBoundsheet.reserved = None; + aBoundsheet.sheetType = WorksheetType; + + aBoundsheet.sheetNameLen = mySheetName.length(); + aBoundsheet.unicodeStrFlags = Compressed; + + QByteArray aUnicodeByteName; + if ( canBePacked( mySheetName ) ) + { + aUnicodeByteName.append( mySheetName ); + } + else + { + aBoundsheet.unicodeStrFlags = Uncompressed; + aBoundsheet.biffRecord.length += mySheetName.length(); + + aUnicodeByteName = unicodeToByteArray(mySheetName); + } + + aBoundsheet.streamStartPos = myWbDataBuf.length() + + sizeof(BIFF8_BOUNDSHEET) + + aUnicodeByteName.length() + + sizeof(BIFF8_SST) + + theSSTLength + + sizeof(BIFF8_RECORD); //EOF + + myWbDataBuf.append( BYTE_ARRAY(aBoundsheet.buf, sizeof(BIFF8_BOUNDSHEET)) ); + myWbDataBuf.append( aUnicodeByteName ); +} + +/** + * SST record contains Shared String Table + */ +void QtxXlsBiff::createSSTTable( const QByteArray& theStringTable ) +{ + BIFF8_SST aSST; + aSST.biffRecord.biffNum = SST; + aSST.biffRecord.length = SIZEOF(BIFF8_SST) + theStringTable.size(); + aSST.totalNum = myLabelsNum; + aSST.uniqueNum = mySSTTable.size(); + + myWbDataBuf.append( BYTE_ARRAY(aSST.buf, sizeof(BIFF8_SST)) ); + myWbDataBuf.append( theStringTable ); +} + +/** + * + */ +void QtxXlsBiff::createMergeCellsRecord() +{ + if ( myMergedCells.isEmpty() ) + return; + + QVector::iterator anIt = myMergedCells.begin(); + + QByteArray aMergedCellsBuf; + BIFF8_RECORD aRec; + aRec.biffNum = MERGECELLS; + aRec.length = sizeof(XlsWORD) + sizeof(BIFF8_REF) * myMergedCells.size(); + aMergedCellsBuf.append( DWORD_BYTE_ARRAY(aRec.buf) ); + + xlsWORDExcange aCount; + aCount.value = myMergedCells.size(); + aMergedCellsBuf.append( BYTE_ARRAY(aCount.buf, sizeof(XlsWORD)) ); + + while( anIt != myMergedCells.end() ) + { + aMergedCellsBuf.append( BYTE_ARRAY(anIt->buf, sizeof(BIFF8_REF)) ); + ++anIt; + } + + myShDataBuf.append( aMergedCellsBuf ); +} + +/** + * Returns byte array with workbook and worksheet data + * prepared for writing + */ +QByteArray QtxXlsBiff::getBiffData() +{ + createBOF(); + createWindow1(); + createDate1904(); + + createFontTable(); + createFormatTable(); + createStyleInfoTable(); + + //SST len determination + QByteArray aUnicodeByteName; + QStringList::const_iterator anIt = mySSTTable.begin(); + while( anIt != mySSTTable.end() ) + { + xlsWORDExcange anExchanger; + anExchanger.value = anIt->length(); + aUnicodeByteName.append( anExchanger.buf[0] ); + aUnicodeByteName.append( anExchanger.buf[1] ); + + if ( canBePacked( *anIt ) ) + { + aUnicodeByteName.append( Compressed ); + aUnicodeByteName.append( *anIt ); + } + else + { + aUnicodeByteName.append( Uncompressed ); + aUnicodeByteName.append( unicodeToByteArray( *anIt ) ); + } + + ++anIt; + } + + createBoundsheet( aUnicodeByteName.size() ); + createSSTTable( aUnicodeByteName ); + + xlsDWORDExcange anExchanger; + anExchanger.value = _EOF; + + QByteArray aEOF( TO_PCHAR(anExchanger.buf), sizeof(XlsDWORD) ); + + QByteArray aDataBuffer( myWbDataBuf ); + aDataBuffer.append( aEOF ); + + createMergeCellsRecord(); + + aDataBuffer.append( myShDataBuf ); + aDataBuffer.append( aEOF ); + + cleanBuffers(); + + return aDataBuffer; +} + +/** + * Adds number value + */ +void QtxXlsBiff::addData( const double theNumber, + const XlsWORD theRow, + const XlsWORD theCol, + const XlsWORD theStyleID ) +{ + BIFF8_NUMBER aNumber; + aNumber.biffRecord.biffNum = NUMBER; + aNumber.biffRecord.length = SIZEOF(BIFF8_NUMBER); + + aNumber.row = theRow; + aNumber.col = theCol; + aNumber.iXF = theStyleID; //first cell format record having id = 15 + aNumber.num = theNumber; + + myShDataBuf.append( BYTE_ARRAY(aNumber.buf, sizeof(BIFF8_NUMBER)) ); +} + +/** + * Adds string or blank value + */ +void QtxXlsBiff::addData( const QString& theString, + const XlsWORD theRow, + const XlsWORD theCol, + const XlsWORD theStyleID ) +{ + if ( theString.isEmpty() ) + { + BIFF8_BLANK aBlank; + aBlank.biffRecord.biffNum = BLANK; + aBlank.biffRecord.length = SIZEOF(BIFF8_BLANK); + aBlank.row = theRow; + aBlank.col = theCol; + aBlank.iXF = theStyleID; + + myShDataBuf.append( BYTE_ARRAY(aBlank.buf, sizeof(BIFF8_BLANK)) ); + return; + } + + int anIndex = mySSTTable.indexOf( theString ); + + BIFF8_LABELSST aLabel; + aLabel.biffRecord.biffNum = LABELSST; + aLabel.biffRecord.length = SIZEOF(BIFF8_LABELSST); + aLabel.row = theRow; + aLabel.col = theCol; + aLabel.iXF = theStyleID; //first cell format record having id = 15 + + if ( anIndex < 0 ) + { + mySSTTable.append( theString ); + aLabel.iSST = mySSTTable.size() - 1; + } + else + { + aLabel.iSST = anIndex; + } + + ++myLabelsNum; + myShDataBuf.append( BYTE_ARRAY(aLabel.buf, sizeof(BIFF8_LABELSST)) ); +} + +/** + * + */ +void QtxXlsBiff::mergeCells( const XlsWORD theFirstRow, const XlsWORD theLastRow, + const XlsWORD theFirstCol, const XlsWORD theLastCol ) +{ + BIFF8_REF aRef; + aRef.rowFirst = theFirstRow; + aRef.rowLast = theLastRow; + aRef.colFirst = theFirstCol; + aRef.colLast = theLastCol; + + myMergedCells.append( aRef ); +} + +/** + * + */ +void QtxXlsBiff::setColWidth( const XlsWORD theWidth, const XlsWORD theFrom, + const XlsWORD theTo, const XlsWORD theStyleID ) +{ + BIFF8_COLINFO aColinfo; + aColinfo.biffRecord.biffNum = COLINFO; + aColinfo.biffRecord.length = SIZEOF(BIFF8_COLINFO); + aColinfo.colFirst = theFrom; + aColinfo.colLast = theTo; + aColinfo.colDx = 256 * theWidth; + aColinfo.iXF = theStyleID; + aColinfo.options = None; + aColinfo.reserved = None; + + myShDataBuf.append( BYTE_ARRAY(aColinfo.buf, sizeof(BIFF8_COLINFO)) ); +} + +/** + * + */ +void QtxXlsBiff::getFontParams( const XlsWORD theStyleID, QString& theFontName, + int& theFontSize, bool& theIsBold ) +{ + if ( myStyleTable.size() < theStyleID ) + { + theFontName = ""; + theFontSize = -1; + theIsBold = false; + return; + } + + int aFontId = myStyleTable[theStyleID].fontID; + if ( aFontId < MinFontNum + 1 ) + { + theFontName = myDefaultFontName; + theFontSize = myDefaultFontSize; + theIsBold = false; + return; + } + + --aFontId; + + theFontName = myFontNames[aFontId]; + theFontSize = myFontTable[aFontId].height / 20; + theIsBold = myFontTable[aFontId].boldStyle == BoldText; +} + +/** + * + */ +void QtxXlsBiff::cleanBorderStruct( QtxXlsBiff::Border& theBorder ) +{ + Border aBorder = { None, None, None, + None, None, None, + None, None, None, + None, None }; + + theBorder = aBorder; +} diff --git a/src/Qtx/QtxXlsBiff.h b/src/Qtx/QtxXlsBiff.h new file mode 100755 index 000000000..15c57fef7 --- /dev/null +++ b/src/Qtx/QtxXlsBiff.h @@ -0,0 +1,604 @@ +// Name : QtxXlsBiff.h +// Purpose: QtxXlsBiff is a class for storing main data to high-level *.XLS structures. +// +// History: +// 17/10/11 - Oleg Agashin - Creation of the file + +#ifndef QTXXLSBIFF_HEADER +#define QTXXLSBIFF_HEADER + +#include +#include +#include + +//Own types +typedef unsigned char XlsBYTE; +typedef unsigned short XlsWORD; +typedef unsigned int XlsDWORD; + +#define TO_PCHAR(x) reinterpret_cast(x) +#define BYTE_ARRAY(x,y) QByteArray(TO_PCHAR(x), (y)) +#define DWORD_BYTE_ARRAY(x) BYTE_ARRAY((x), sizeof(XlsDWORD)) + +union xlsWORDExcange +{ + XlsBYTE buf[sizeof(XlsWORD)]; + XlsWORD value; +}; + +union xlsDWORDExcange +{ + XlsBYTE buf[sizeof(XlsDWORD)]; + XlsDWORD value; +}; + + +#pragma pack(push,1) + +#define SIZEOF(x) (sizeof(x) - sizeof(BIFF8_RECORD)) + +/** + * Class for creating data model + * + * Format of *.XLS data model: + * +----------------------------+ + * | BOF | + * +----------------------------+ + * | Workbook Globals | + * +----------------------------+ + * | EOF | + * +----------------------------+ + * +----------------------------+ + * | BOF | + * +----------------------------+ + * | Sheet stream | + * | getBiffBeforeData | + * | #Data | + * | getBiffAfterData | + * +----------------------------+ + * | EOF | + * +----------------------------+ + */ +class QtxXlsBiff +{ + //-------------- BIFF structure types ------------------------ + + union BIFF8_RECORD + { + XlsBYTE buf[4]; + struct + { + XlsWORD biffNum; + XlsWORD length; + }; + }; + + union BIFF8_BOF + { + XlsBYTE buf[20]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD verOfBIFF; + XlsWORD typeOfData; + XlsWORD buildID; + XlsWORD buildYear; + XlsDWORD historyFlags; + XlsDWORD lowestVer; + }; + }; + + union BIFF8_DATE1904 + { + XlsBYTE buf[6]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD f1904; + }; + }; + + union BIFF8_XF + { + XlsBYTE buf[24]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD fontID; + XlsWORD formatID; + union + { + XlsWORD paramFlags; + struct + { + XlsWORD fLocked : 1; + XlsWORD fHidden : 1; + XlsWORD fStyle : 1; + XlsWORD f123Prefix : 1; + XlsWORD ixfParent : 12; + }; + }; + union + { + XlsWORD formatAlign; + struct + { + XlsWORD align : 3; + XlsWORD fWrap : 1; + XlsWORD valign : 3; + XlsWORD fJustLast : 1; + XlsWORD rotation : 8; + }; + }; + union + { + XlsWORD formatView; + struct + { + XlsWORD indent : 4; + XlsWORD shrinkToFit : 1; + XlsWORD mergeCell : 1; + XlsWORD readOrder : 2; + XlsWORD reserved1 : 2; + XlsWORD attrNum : 1; + XlsWORD attrFnt : 1; + XlsWORD attrAlign : 1; + XlsWORD attrBdr : 1; + XlsWORD attrPat : 1; + XlsWORD attrProt : 1; + }; + }; + union + { + XlsWORD formatBorder; + struct + { + XlsWORD left : 4; + XlsWORD right : 4; + XlsWORD top : 4; + XlsWORD bottom : 4; + }; + }; + union + { + XlsWORD formatLRBdrColor; + struct + { + XlsWORD colorLeft : 7; + XlsWORD colorRight : 7; + XlsWORD diagonalType : 2; + }; + }; + union + { + XlsDWORD formatTBBdrColor; + struct + { + XlsDWORD colorTop : 7; + XlsDWORD colorBottom : 7; + XlsDWORD colorDiagonal : 7; + XlsDWORD diagBdrStyle : 4; + XlsDWORD hasXFExt : 1; + XlsDWORD fillPattern : 6; + }; + }; + union + { + XlsWORD formatBGColor; + struct + { + XlsWORD foregroundColor : 7; + XlsWORD backgroundColor : 7; + XlsWORD sxButton : 1; + XlsWORD reserved2 : 1; + }; + }; + }; + }; + + union BIFF8_FONT + { + //XlsBYTE buf[19]; + XlsBYTE buf[20]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD height; + union + { + XlsWORD fontAttr; + struct + { + XlsWORD reserved1 : 1; + XlsWORD fItalic : 1; + XlsWORD reserved2 : 1; + XlsWORD fStrikeout : 1; + XlsWORD fOutline : 1; + XlsWORD fShadow : 1; + XlsWORD reserved3 : 2; + XlsWORD unused : 8; + }; + }; + XlsWORD color; + XlsWORD boldStyle; + XlsWORD superSubStyle; + XlsBYTE underlineStyle; + XlsBYTE fontFamily; + XlsBYTE charSet; + XlsBYTE reserved; //zero + XlsBYTE fontNameLen; + XlsBYTE unicodeStrFlags; + //+ font name + }; + }; + + union BIFF8_BOUNDSHEET + { + XlsBYTE buf[12]; + struct + { + BIFF8_RECORD biffRecord; + XlsDWORD streamStartPos; + union + { + XlsWORD sheetAttr; + struct + { + XlsWORD hiddenSate : 2; + XlsWORD reserved : 6; + XlsWORD sheetType : 8; + }; + }; + XlsBYTE sheetNameLen; + XlsBYTE unicodeStrFlags; + //+ sheet name + }; + }; + + union BIFF8_STYLE + { + XlsBYTE buf[8]; + struct + { + BIFF8_RECORD biffRecord; + union + { + XlsWORD iXF; + struct + { + XlsWORD ixfe : 12; + XlsWORD unused : 3; + XlsWORD fBuiltIn : 1; + }; + }; + XlsBYTE builtInStyle; + XlsBYTE level; + }; + }; + + union BIFF8_SST + { + XlsBYTE buf[12]; + struct + { + BIFF8_RECORD biffRecord; + XlsDWORD totalNum; + XlsDWORD uniqueNum; + }; + }; + + union BIFF8_ROW + { + XlsBYTE buf[20]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD rowNum; + XlsWORD firstCol; + XlsWORD lastCol; + XlsWORD rowHeight; + XlsWORD irwMac; + XlsWORD reserved; + union + { + XlsWORD optionFlags; + struct + { + XlsWORD fOutlineLevel: 3; + XlsWORD reserved1 : 1; + XlsWORD fCollapsed : 1; + XlsWORD fDyZero : 1; + XlsWORD fUnsynced : 1; + XlsWORD fGhostDirty : 1; + XlsWORD reserved2 : 8; + }; + }; + XlsWORD iXF; + }; + }; + + union BIFF8_WINDOW1 + { + XlsBYTE buf[22]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD xWnd; + XlsWORD yWnd; + XlsWORD dxWnd; + XlsWORD dyWnd; + union + { + XlsWORD optionFlags; + struct + { + XlsWORD fHidden : 1; + XlsWORD fIconic : 1; + XlsWORD reserved1 : 1; + XlsWORD fDspHScroll : 1; + XlsWORD fDspVScroll : 1; + XlsWORD fDisplayWbTabs : 1; + XlsWORD fNoAFDateGroup : 1; + XlsWORD reserved2 : 1; + XlsWORD reserved3 : 8; + }; + }; + XlsWORD iSelWbTab; + XlsWORD iFirstDispWbTab; + XlsWORD selTabNum; + XlsWORD wTabRatio; + }; + }; + + union BIFF8_COLINFO + { + XlsBYTE buf[16]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD colFirst; + XlsWORD colLast; + XlsWORD colDx; + XlsWORD iXF; + XlsWORD options; + XlsWORD reserved; + }; + }; + + union BIFF8_REF + { + XlsBYTE buf[8]; + struct + { + XlsWORD rowFirst; + XlsWORD rowLast; + XlsWORD colFirst; + XlsWORD colLast; + }; + }; + + //------------------- Excel data types ------------------- + union BIFF8_NUMBER + { + XlsBYTE buf[18]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD row; + XlsWORD col; + XlsWORD iXF; + double num; + }; + }; + + union BIFF8_BLANK + { + XlsBYTE buf[10]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD row; + XlsWORD col; + XlsWORD iXF; + }; + }; + + union BIFF8_LABELSST + { + XlsBYTE buf[14]; + struct + { + BIFF8_RECORD biffRecord; + XlsWORD row; + XlsWORD col; + XlsWORD iXF; + XlsDWORD iSST; + }; + }; + //-------------- end of Excel data types ----------------- + + enum TypeOfData { WorkbookGlobals = 0x5, VB = 0x6, + Sheet = 0x10, Chart = 0x20, + MacroSheet = 0x40, + Workspace = 0x100 }; + + enum TypeOfXF { Cell = 0, Style }; + + enum ReadingOrder { Context = 0, LeftToRight, RightToLeft }; + + enum OtherFormatConstants { NoTransKeys = 0, DefaultParentStyle = 0, NoParentStyle = 0xFFF }; + + enum SheetHiddenState { Visible = 0, Hidden, VeryHidden }; + + enum SheetType { WorksheetType = 0, MacroType, ChartType, VBType = 6}; + + enum BuiltInSyles { Normal = 0, RowLevel_n, ColLevel_n, Comma, + Currency, Percent, Comma_0, Currency_0 }; + + enum Constants { MinFontNum = 5, MinXFNum = 15 }; + + enum StringFlags { Compressed = 0, Uncompressed }; + + enum FormatNumbers { _BOF = 0x0809, + _EOF = 0x000A, + WINDOW1 = 0x003d, + DATE1904 = 0x0022, + FONT = 0x0031, + BOUNDSHEET = 0x0085, + NUMBER = 0x0203, + BLANK = 0x0201, + LABELSST = 0x00FD, + XF = 0x00E0, + SST = 0x00FC, + ROW = 0x0208, + MERGECELLS = 0x00E5, + COLINFO = 0x007D, + STYLE = 0x0293, + BIFF_ver = 0x0600 }; + //-------------- end of BIFF structure types ----------------- +public: + enum Align { AlignGeneral = 0, AlignLeft, AlignCenter, AlignRight, + AlignFill, AlignJustify, AlignCenterAcrossSelection }; + + enum VAlign { VAlignTop = 0, VAlignCenter, VAlignBottom, VAlignJustify }; + + enum LineStyles { None = 0, Thin, Medium, Dashed, + Dotted, Thick, Double, Hair, + MediumDashed, DashDot, MediumDashDot, + DashDotDot, MediumDashDotDot, + SlantedDashDot, + DiagDown = 1, DiagUp = 2, DiagBoth = 3}; + + enum FontStyle { Italic = 0x2, Strikeout = 0x8, Outline = 0x10, + Shadow = 0x20, Superscript = 1, Subscript = 2 }; + + enum FontWeight { NormalText = 0x190, BoldText = 0x2BC }; + + enum FontUnderlineType { SingleUnderline = 1, DoubleUnderline, + SingleAccountingUnderline = 0x21, DoubleAccountingUnderline = 0x22 }; + + enum InternalFormat { General = 0, Integer }; //0x31 total - see XF reference + + enum DefaultGroundColors { DefaultForegroundColor = 0x40, DefaultBackgroundColor }; + + enum DefaultFontColor { Black = 0x7FFF }; + + enum Font { DefaultFont = 0 }; + + enum Style { DefaultStyle = 15 }; + + enum CharSet { ANSI_Latin = 0, SystemDefault, Symbol }; + + struct Border + { + LineStyles leftBorderStyle; + LineStyles rightBorderStyle; + LineStyles topBorderStyle; + LineStyles bottomBorderStyle; + + LineStyles diagonalType; + LineStyles diagonalBorderStyle; + + XlsBYTE leftBorderColor; + XlsBYTE rightBorderColor; + XlsBYTE topBorderColor; + XlsBYTE bottomBorderColor; + XlsBYTE diagonalColor; + }; + +public: + QtxXlsBiff(); + +public: + QByteArray getBiffData(); + void clear(); + + static void cleanBorderStruct( Border& theBorder ); + + void SetSheetName( const QString& theName ); + + void setColWidth( const XlsWORD theWidth, const XlsWORD theFrom, + const XlsWORD theTo,const XlsWORD theStyleID ); + + void getFontParams( const XlsWORD theStyleID, QString& theFontName, + int& theFontSize, bool& theIsBold ); + + void addData( const double theNumber, + const XlsWORD theRow, + const XlsWORD theCol, + const XlsWORD theStyleID = 0 ); + + void addData( const QString& theString, + const XlsWORD theRow, + const XlsWORD theCol, + const XlsWORD theStyleID = 0 ); + + int addFont( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold = false, + const XlsWORD theFontColor = Black, + const XlsWORD theFontStyle = None, + const XlsWORD theSuperSubscriptType = None, + const XlsWORD theUnderlineType = None ); + + int addCellStyle( const XlsWORD theFontID, + const XlsWORD theFormatID, + const XlsWORD theAlign, + const XlsWORD theVAlign, + const Border* theBorders = 0, + const bool theIsWrapped = false, + const bool theIsMerged = false, + const XlsWORD theRotation = None, + const XlsBYTE theForegrountColorID = DefaultForegroundColor, + const XlsBYTE theBackgrountColorID = DefaultBackgroundColor ); + + void mergeCells( const XlsWORD theFirstRow, const XlsWORD theLastRow, + const XlsWORD theFirstCol, const XlsWORD theLastCol ); + +private: + bool canBePacked( const QString& theStr ); + QByteArray unicodeToByteArray( const QString& theStr ); + void cleanBuffers(); + void addDefaultFonts(); + void addDefaultStyles(); + + void createBOF(); + void createWindow1(); + void createDate1904(); + void createFontTable(); + void createFormatTable(); + void createStyleInfoTable(); + void createBoundsheet( const int theSSTLength ); + void createSSTTable( const QByteArray& theStringTable ); + void createMergeCellsRecord(); + + BIFF8_FONT formatFontRecord( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold = false, + const XlsWORD theFontColor = Black, + const XlsWORD theFontStyle = None, + const XlsWORD theSuperSubscriptType = None, + const XlsWORD theUnderlineType = None ); +private: + QString myDefaultFontName; + int myDefaultFontSize; + + QString mySheetName; + + QByteArray myWbDataBuf; + QByteArray myShDataBuf; + + QVector myFontTable; + QStringList myFontNames; + + QVector myStyleTable; + QVector myMergedCells; + + QStringList mySSTTable; + XlsDWORD myLabelsNum; + + QVector myBlankCells; +}; + +#pragma pack(pop) +#endif diff --git a/src/Qtx/QtxXlsBorderTool.cxx b/src/Qtx/QtxXlsBorderTool.cxx new file mode 100755 index 000000000..16b9b620b --- /dev/null +++ b/src/Qtx/QtxXlsBorderTool.cxx @@ -0,0 +1,669 @@ +// Name : QtxXlsBorderTool.cpp +// Purpose: Implementation of QtxXlsBorderTool class. +// +// History: +// 20/10/11 - Oleg Agashin - Creation of the file + +#include +#include + + +/** + * + */ +int QtxXlsBorderTool::LeftTopThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightTopThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftBottomThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightBottomThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftTopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightTopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + + + +/** + * + */ +int QtxXlsBorderTool::LeftThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::TopThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::BottomThick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::TopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::BottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::Thick( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::Thin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + + + +/** + * + */ +int QtxXlsBorderTool::LeftTopThickRightBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightTopThickLeftBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftBottomThickRightTopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightBottomThickLeftTopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftTopRightThickBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftBottomRightThickTopThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftRightThickTopBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::TopThickLeftBottomRightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftThickTopBottomRightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::BottomThickTopLeftRightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightThickTopLeftBottomThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thin; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thin; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::LeftTopBottomThickRightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thick; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::RightTopBottomThickLeftThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thick; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} + +/** + * + */ +int QtxXlsBorderTool::TopBottomThickLeftRightThin( QtxXlsWriter& theWriter, const XlsWORD theFontID, + const XlsBYTE theColor, const XlsWORD theFormatID, + const XlsWORD theAlign, const XlsWORD theVAlign ) +{ + QtxXlsBiff::Border aBorder; + QtxXlsBiff::cleanBorderStruct( aBorder ); + + aBorder.topBorderStyle = QtxXlsBiff::Thick; + aBorder.topBorderColor = theColor; + aBorder.leftBorderStyle = QtxXlsBiff::Thin; + aBorder.leftBorderColor = theColor; + aBorder.bottomBorderStyle = QtxXlsBiff::Thick; + aBorder.bottomBorderColor = theColor; + aBorder.rightBorderStyle = QtxXlsBiff::Thin; + aBorder.rightBorderColor = theColor; + + return theWriter.addCellStyle( theFontID, theFormatID, + theAlign, theVAlign, &aBorder ); +} diff --git a/src/Qtx/QtxXlsBorderTool.h b/src/Qtx/QtxXlsBorderTool.h new file mode 100755 index 000000000..6afeaa057 --- /dev/null +++ b/src/Qtx/QtxXlsBorderTool.h @@ -0,0 +1,253 @@ +// Name : QtxXlsBorderTool.h +// Purpose: QtxXlsBorderTool is a class for easy creation of cell border styles. +// +// History: +// 20/10/11 - Oleg Agashin - Creation of the file + +#ifndef QTXXLSBORDERTOOL_H_ +#define QTXXLSBORDERTOOL_H_ + +#include + +class QtxXlsWriter; + +class QtxXlsBorderTool +{ +public: +// Corner styles + //Thick + static int LeftTopThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightTopThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftBottomThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightBottomThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + // Thin + static int LeftTopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightTopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + +// Side styles + //Thick + static int LeftThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int TopThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int BottomThick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + //For whole cell border + static int Thick( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + + //Thin + static int LeftThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int TopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int BottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + //For whole cell border + static int Thin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + +// Combine styles + static int LeftTopThickRightBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightTopThickLeftBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftBottomThickRightTopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightBottomThickLeftTopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftTopRightThickBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftBottomRightThickTopThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftRightThickTopBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int TopThickLeftBottomRightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftThickTopBottomRightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int BottomThickTopLeftRightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightThickTopLeftBottomThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int LeftTopBottomThickRightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int RightTopBottomThickLeftThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); + + static int TopBottomThickLeftRightThin( QtxXlsWriter& theWriter, + const XlsWORD theFontID, + const XlsBYTE theColor = QtxXlsBiff::DefaultForegroundColor, + const XlsWORD theFormatID = QtxXlsBiff::General, + const XlsWORD theAlign = QtxXlsBiff::AlignGeneral, + const XlsWORD theVAlign = QtxXlsBiff::VAlignCenter ); +}; + +#endif /* QTXXLSBORDERTOOL_H_ */ diff --git a/src/Qtx/QtxXlsWriter.cxx b/src/Qtx/QtxXlsWriter.cxx new file mode 100755 index 000000000..34aebf547 --- /dev/null +++ b/src/Qtx/QtxXlsWriter.cxx @@ -0,0 +1,485 @@ +// Name : QtxXlsWriter.cpp +// Purpose: Implementation of QtxXlsWriter class. +// +// History: +// 11/10/11 - Oleg Agashin - Creation of the file + +#include + +#include + + +/** + * + */ +QtxXlsWriter::QtxXlsWriter( const QString& theFileName ) +: myFileName(theFileName), myWorkbookName("Workbook"), + myDataSecNum(Dummy), myMSATSecNum(Dummy), + mySATSecNum(Dummy), myFreeSector(Dummy) +{ +} + +/** + * + */ +QtxXlsWriter::~QtxXlsWriter() +{ +} + +/** + * Clear all structures + */ +void QtxXlsWriter::clear() +{ + myData.clear(); + myDataSecNum = Dummy; + myMSATSecNum = Dummy; + mySATSecNum = Dummy; + myFreeSector = Dummy; +} + +/** + * Forms header of xls file + */ +QByteArray QtxXlsWriter::formatHeader( const QByteArray& theDataBuffer ) +{ + //Data aligned to SectorSize boundary + XlsDWORD aDataLen = theDataBuffer.length(); + + mySATSecNum = Dummy; + XlsDWORD aTotalSSATSecNum = Dummy; + myMSATSecNum = Dummy; + + //Are there some data in buffer? + //if ( aDataLen ) + // + //rem: BOF & EOF data are always there and aDataLen >= SectorSize, + // nothing to check + + myDataSecNum = aDataLen / SectorSize; //Total data sectors + + //If data length below a lower boundary + if ( aDataLen < MinStreamSize ) + { + //format SSAT + aTotalSSATSecNum = 1; + } + else + { + //format SAT + mySATSecNum = getSectorsNum( myDataSecNum, totalSecIDinSATSector); + + //check to add additional MSAT + if ( mySATSecNum > MinSATSecInMSAT ) + { + //format MSAT + myMSATSecNum = getSectorsNum( mySATSecNum - MinSATSecInMSAT, totalSecIDinMSATSector ); + } + } + + + XlsHeader aHeader = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}; + + for( XlsWORD i = 8; i < 76; i++ ) + aHeader.buf[i] = Dummy; + + aHeader.formatRev = 0x003E; + aHeader.formatVer = 0x0003; + aHeader.byteOrder = 0xFFFE; + + aHeader.sectorSize = 9; + aHeader.shortSectorSize = 6; + + aHeader.minStreamSize = MinStreamSize; + + aHeader.totalSATSecs = mySATSecNum; + aHeader.totalSSATSecs = aTotalSSATSecNum; + aHeader.totalMSATSecs = myMSATSecNum; + + myFreeSector = myDataSecNum; + + fillFirstSectorID( myMSATSecNum, aHeader.firstMSATSecID, myFreeSector ); + fillFirstSectorID( aTotalSSATSecNum, aHeader.firstSSATSecID, myFreeSector ); + aHeader.firstDirSecID = myFreeSector++; + + XlsWORD anIndex = 76; + + XlsWORD aBound = mySATSecNum; + if ( myMSATSecNum ) + { + aBound = MinSATSecInMSAT; + } + + for( XlsWORD i = 0; i < aBound; i++) + { + *(reinterpret_cast(&aHeader.buf[anIndex])) = myFreeSector++; + + anIndex += SizeOfDWORD; + } + + //If we have a reminder + for(; anIndex < SectorSize; anIndex++) + aHeader.buf[anIndex] = Free_SecID; + + return BYTE_ARRAY( aHeader.buf, SectorSize ); +} + +/** + * Calculates first sector ID for some structure block + */ +void QtxXlsWriter::fillFirstSectorID( const XlsDWORD theTotalSecNum, + XlsDWORD& theFirstSectorID, + XlsDWORD& theFreeSector ) +{ + if ( theTotalSecNum ) + { + theFirstSectorID = theFreeSector; + theFreeSector += theTotalSecNum; + } + else + theFirstSectorID = EndOfChain_SecID; +} + +/** + * Update directory structure by default values + */ +void QtxXlsWriter::clearDirStructure( DirEntityStructure& theStruct ) +{ + for( XlsWORD i = 0; i < DirEntrySize; i++ ) + theStruct.buf[i] = Dummy; + + theStruct.leftChildDirID = Free_SecID; + theStruct.rightChildDirID = Free_SecID; + theStruct.rootDirID = Free_SecID; +} + +/** + * Adds user-defined font + */ +int QtxXlsWriter::addFont( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold, + const XlsWORD theFontColor, + const XlsWORD theFontStyle, + const XlsWORD theSuperSubscriptType, + const XlsWORD theUnderlineType ) +{ + return myData.addFont( theFontName, theFontSize, theIsBold, + theFontColor, theFontStyle, + theSuperSubscriptType, + theUnderlineType ); +} + +/** + * Adds user-defined format + */ +int QtxXlsWriter::addCellStyle( const XlsWORD theFontID, + const XlsWORD theFormatID, + const XlsWORD theAlign, + const XlsWORD theVAlign, + const QtxXlsBiff::Border* theBorders, + const bool theIsWrapped, + const bool theIsMerged, + const XlsWORD theRotation, + const XlsBYTE theForegrountColorID, + const XlsBYTE theBackgrountColorID/*, + const XlsWORD theParentStyleID*/ ) +{ + return myData.addCellStyle( theFontID, theFormatID, theAlign, + theVAlign, theBorders, theIsWrapped, theIsMerged, + theRotation, theForegrountColorID, theBackgrountColorID ); +} + +/** + * + */ +void QtxXlsWriter::SetWorkbookName( const QString& theName ) +{ + if( !theName.isEmpty() ) + myWorkbookName = theName; +} + +/** + * + */ +void QtxXlsWriter::SetSheetName( const QString& theName ) +{ + myData.SetSheetName( theName ); +} + +/** + * + */ +void QtxXlsWriter::SetFileName( const QString& theName ) +{ + if( !theName.isEmpty() ) + myFileName = theName; +} + +/** + * Stores the file + */ +bool QtxXlsWriter::upload() +{ + QFile aFile( myFileName ); + if ( !aFile.open( QFile::WriteOnly ) ) + return false; + + QByteArray aDataBuffer( myData.getBiffData() ); + fillData( aDataBuffer ); + + //counting data sectors + + QByteArray aByteArray = formatHeader( aDataBuffer ); + aFile.write( aByteArray ); + + aFile.write( aDataBuffer ); + + aByteArray = formatMSAT(); + aFile.write( aByteArray ); + + aByteArray = formatDirectoryEntry( aDataBuffer.length() ); + aFile.write( aByteArray ); + + aByteArray = formatSAT(); + aFile.write( aByteArray ); + + aFile.close(); + + return true; +} + +/** + * + */ +void QtxXlsWriter::fillData( QByteArray& theDataBuffer ) +{ + alignData( theDataBuffer, Dummy ); + + //Workaround of short-stream containers + while( theDataBuffer.length() < MinStreamSize ) + theDataBuffer.append( Dummy ); +} + +/** + * Aligns data to SectorSize boundary + * by inserting Dummy data + */ +void QtxXlsWriter::alignData( QByteArray& theBuffer, + XlsDWORD theFiller, + QtxXlsWriter::AlignType theAlignType ) +{ + int aPackLen = SectorSize - (theBuffer.length() % SectorSize); + if ( aPackLen != SectorSize ) + { + for( int i = 0; i < aPackLen; ) + { + switch ( theAlignType ) + { + case Byte: + theBuffer.append( theFiller ); + i++; + break; + + case Dword: + xlsDWORDExcange anExchanger; + + anExchanger.value = theFiller; + theBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + i += SizeOfDWORD; + break; + } + } + } +} + +/** + * Returns exact number of sectors that can storing all data + */ +XlsDWORD QtxXlsWriter::getSectorsNum( const XlsDWORD theDividend, const XlsDWORD theDivisor ) +{ + XlsDWORD aSecNum = theDividend / theDivisor; + if ( theDividend % theDivisor ) + ++aSecNum; + return aSecNum; +} + +/** + * Fills the SAT sectors by reference data sectors IDs + */ +QByteArray QtxXlsWriter::formatSAT() +{ + QByteArray aBuffer; + xlsDWORDExcange anExchanger; + XlsDWORD aPenultimate = myDataSecNum - 1; + + //Fill data chain + for( XlsDWORD anIndex = 0; anIndex < myDataSecNum; anIndex++) + { + if ( anIndex == aPenultimate ) + anExchanger.value = EndOfChain_SecID; + else + anExchanger.value = anIndex + 1; + + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + } + + //Fill MSAT used sectors + for( XlsDWORD anIndex = 0; anIndex < myMSATSecNum; anIndex++) + { + anExchanger.value = MSAT_SecID; + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + } + + //Fill SSAT + + //Fill Dir - only one sector + anExchanger.value = EndOfChain_SecID; + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + + //Fill SAT used sectors + for( XlsDWORD anIndex = 0; anIndex < mySATSecNum; anIndex++) + { + anExchanger.value = SAT_SecID; + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + } + + alignData( aBuffer, Free_SecID, Dword ); + + return aBuffer; +} + +/** + * Fills the MSAT sectors by reference SAT sectors IDs + */ +QByteArray QtxXlsWriter::formatMSAT() +{ + QByteArray aBuffer; + + if ( !myMSATSecNum ) + { + return aBuffer; + } + + xlsDWORDExcange anExchanger; + XlsDWORD aRemSATSectors = mySATSecNum - MinSATSecInMSAT; + XlsDWORD aNextMSATSec = myDataSecNum + 1; + + for( XlsDWORD anIndex = 1; anIndex <= aRemSATSectors; anIndex++) + { + if ( !( anIndex % totalSecIDinSATSector ) ) + { + anExchanger.value = aNextMSATSec++; + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + } + + anExchanger.value = myFreeSector++; + aBuffer.append( DWORD_BYTE_ARRAY(anExchanger.buf) ); + } + + alignData( aBuffer, Free_SecID, Dword ); + + return aBuffer; +} + +/** + * Fills entry point for workbook + */ +QByteArray QtxXlsWriter::formatDirectoryEntry( const XlsDWORD theDataLen ) +{ + QString aName; + QByteArray aBuffer; + DirEntityStructure anEntity; + + clearDirStructure( anEntity ); + + aName = "Root Entry"; + + XlsDWORD aStrLen = aName.length(); + for ( XlsDWORD i = 0; i < aStrLen ; i++ ) + anEntity.entryNameUnicode[i] = aName[i].unicode(); + + anEntity.nameLenInBytes = (aStrLen + 1) << 1; + anEntity.entityType = Root; + anEntity.nodeColour = Black; //Red; + anEntity.rootDirID = 1; //only one stream, this points to next dir entry + anEntity.firstSecID = EndOfChain_SecID; + anEntity.totalStreamSize = Dummy; + + anEntity.UID[0] = 0x00020820; + anEntity.UID[1] = 0x00000000; + anEntity.UID[2] = 0x000000C0; + anEntity.UID[3] = 0x46000000; + + //Add root entry to buffer + aBuffer.append( BYTE_ARRAY(anEntity.buf, DirEntrySize) ); + + + clearDirStructure( anEntity ); + + aStrLen = myWorkbookName.length(); + if ( aStrLen > MaxDirNameLen ) + { + myWorkbookName.truncate( MaxDirNameLen ); + aStrLen = MaxDirNameLen; + } + + for ( XlsDWORD i = 0; i < aStrLen ; i++ ) + anEntity.entryNameUnicode[i] = myWorkbookName[i].unicode(); + + anEntity.nameLenInBytes = (aStrLen + 1) << 1; + anEntity.entityType = UserStream; + anEntity.nodeColour = Black; + anEntity.firstSecID = 0; + anEntity.totalStreamSize = theDataLen; + + //Add root entry to buffer + aBuffer.append( BYTE_ARRAY(anEntity.buf, DirEntrySize) ); + + alignData( aBuffer, Dummy ); + + return aBuffer; +} + +/** + * Adds string value + */ +void QtxXlsWriter::addData( const QString& theData, const XlsWORD theRow, + const XlsWORD theCol, const XlsWORD theStyleID ) +{ + bool aIsDouble = false; + double aDouble = theData.toDouble( &aIsDouble ); + if ( aIsDouble ) + myData.addData( aDouble, theRow, theCol, theStyleID ); + else + myData.addData( theData, theRow, theCol, theStyleID ); + +} + +/** + * Adds double value + */ +void QtxXlsWriter::addData( const double theData, const XlsWORD theRow, + const XlsWORD theCol, const XlsWORD theStyleID ) +{ + myData.addData( theData, theRow, theCol, theStyleID ); +} + +/** + * + */ +void QtxXlsWriter::setColWidth( const XlsWORD theMaxLen, const XlsWORD theFromCol, + const XlsWORD theToCol, const XlsWORD theStyleID ) +{ + myData.setColWidth( theMaxLen + 1, theFromCol, + theToCol, theStyleID ); +} + +/** + * + */ +void QtxXlsWriter::mergeCells( const XlsWORD theFirstRow, const XlsWORD theLastRow, + const XlsWORD theFirstCol, const XlsWORD theLastCol ) +{ + myData.mergeCells( theFirstRow, theLastRow, theFirstCol, theLastCol ); +} diff --git a/src/Qtx/QtxXlsWriter.h b/src/Qtx/QtxXlsWriter.h new file mode 100755 index 000000000..6f6387559 --- /dev/null +++ b/src/Qtx/QtxXlsWriter.h @@ -0,0 +1,188 @@ +// Name : QtxXlsWriter.h +// Purpose: QtxXlsWriter is a class for storing data to *.XLS file. +// General behaviour - creating a low-level storage format +// for *.XLS file. +// +// History: +// 11/10/11 - Oleg Agashin - Creation of the file + +#ifndef QTXXLSWRITER_HEADER +#define QTXXLSWRITER_HEADER + +#include + +#include +#include + + +#pragma pack(push,1) +/* + * Class for exporting data to *.XLS file + * Uses only one data stream + * + * *.XLS file structure: + * +------------------------+ + * | Header | + * +------------------------+ + * | DATA | + * +------------------------+ + * | MSAT or Nothing if | + * | number of SAT sectors | + * | lower than 109 | + * +------------------------+ + * | SSAT or Nothing if | + * | length of data stream | + * | greater than minimum | + * | value | + * +------------------------+ + * | Directory Entry | + * | Structure | + * +------------------------+ + * | SAT or Nothing if | + * | length of data stream | + * | lower than minimum | + * | value | + * +------------------------+ + */ +class QtxXlsWriter +{ + //-------------- File structure types ------------------------ + enum SectorType { Free_SecID = -1, EndOfChain_SecID = -2, + SAT_SecID = -3, MSAT_SecID = -4, + Dummy = 0}; + + enum EntryType { Empty = 0, UserStorage, UserStream, + LockBytes, Property, Root}; + + enum NodeColour { Red = 0, Black }; + + enum Constants { SectorSize = 512, MinStreamSize = 4096, + DirEntrySize = 128, MinSATSecInMSAT = 109, + MaxDirNameLen = 32, + SizeOfDWORD = sizeof(XlsDWORD), + totalSecIDinSATSector = SectorSize/SizeOfDWORD, + totalSecIDinMSATSector = totalSecIDinSATSector-1 }; + + enum AlignType { Byte, Dword }; + + //Xls header structure + union XlsHeader + { + XlsBYTE buf[SectorSize]; + struct + { + XlsBYTE fileID[8]; + XlsBYTE UID[16]; + XlsWORD formatRev; + XlsWORD formatVer; + XlsWORD byteOrder; + XlsWORD sectorSize; + XlsWORD shortSectorSize; + XlsBYTE notUsed10[10]; + XlsDWORD totalSATSecs; + XlsDWORD firstDirSecID; + XlsDWORD notUsed; + XlsDWORD minStreamSize; + XlsDWORD firstSSATSecID; + XlsDWORD totalSSATSecs; + XlsDWORD firstMSATSecID; + XlsDWORD totalMSATSecs; + XlsBYTE MSAT[436]; + }; + }; + + //Directiry entity structure + union DirEntityStructure + { + XlsBYTE buf[DirEntrySize]; + struct + { + XlsWORD entryNameUnicode[32]; + XlsWORD nameLenInBytes; + XlsBYTE entityType; + XlsBYTE nodeColour; + XlsDWORD leftChildDirID; + XlsDWORD rightChildDirID; + XlsDWORD rootDirID; + XlsDWORD UID[4]; + XlsDWORD userFlags; + XlsDWORD timeStampCreation[2]; + XlsDWORD timeStampModification[2]; + XlsDWORD firstSecID; + XlsDWORD totalStreamSize; + XlsDWORD notUsed; + }; + }; + //-------------- end of File structure types ----------------- + +public: + QtxXlsWriter( const QString& ); + virtual ~QtxXlsWriter(); + +public: + void addData( const QString& theData, const XlsWORD theRow, + const XlsWORD theCol, const XlsWORD theStyleID ); + void addData( const double theData, const XlsWORD theRow, + const XlsWORD theCol, const XlsWORD theStyleID ); + + bool upload(); + void clear(); + + void SetWorkbookName( const QString& theName ); + void SetSheetName( const QString& theName ); + void SetFileName( const QString& theName ); + + void setColWidth( const XlsWORD theMaxLen, const XlsWORD theFromCol, + const XlsWORD theToCol, const XlsWORD theStyleID ); + + void mergeCells( const XlsWORD theFirstRow, const XlsWORD theLastRow, + const XlsWORD theFirstCol, const XlsWORD theLastCol ); + + int addFont( const QString& theFontName, + const XlsWORD theFontSize, + const bool theIsBold = false, + const XlsWORD theFontColor = QtxXlsBiff::Black, + const XlsWORD theFontStyle = QtxXlsBiff::None, + const XlsWORD theSuperSubscriptType = QtxXlsBiff::None, + const XlsWORD theUnderlineType = QtxXlsBiff::None ); + + int addCellStyle( const XlsWORD theFontID, + const XlsWORD theFormatID, + const XlsWORD theAlign, + const XlsWORD theVAlign, + const QtxXlsBiff::Border* theBorders = 0, + const bool theIsWrapped = false, + const bool theIsMerged = false, + const XlsWORD theRotation = QtxXlsBiff::None, + const XlsBYTE theForegrountColorID = QtxXlsBiff::DefaultForegroundColor, + const XlsBYTE theBackgrountColorID = QtxXlsBiff::DefaultBackgroundColor ); + +private: + QByteArray formatHeader( const QByteArray& theDataBuffer ); + QByteArray formatSAT(); + QByteArray formatMSAT(); + QByteArray formatDirectoryEntry( const XlsDWORD theDataLen ); + + void clearDirStructure( DirEntityStructure& theStruct ); + void alignData( QByteArray& theBuffer, XlsDWORD theFiller, AlignType theAlignType = Byte); + void fillData( QByteArray& ); + XlsDWORD getSectorsNum( const XlsDWORD theDividend, const XlsDWORD theDivisor ); + void fillFirstSectorID( const XlsDWORD theTotalSecNum, + XlsDWORD& theFirstSectorID, + XlsDWORD& theFreeSector ); + +private: + QString myFileName; + QString myWorkbookName; + + QtxXlsBiff myData; + + XlsDWORD myDataSecNum; + XlsDWORD myMSATSecNum; + XlsDWORD mySATSecNum; + + XlsDWORD myFreeSector; +}; + +#pragma pack(pop) +#endif -- 2.39.2