{*******************************************************************} { } { Developer Express Visual Component Library } { ExpressQuantumGrid export routines } { } { Copyright (c) 1998-2009 Developer Express Inc. } { ALL RIGHTS RESERVED } { } { The entire contents of this file is protected by U.S. and } { International Copyright Laws. Unauthorized reproduction, } { reverse-engineering, and distribution of all or any portion of } { the code contained in this file is strictly prohibited and may } { result in severe civil and criminal penalties and will be } { prosecuted to the maximum extent possible under the law. } { } { RESTRICTIONS } { } { THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES } { (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE } { SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS } { LICENSED TO DISTRIBUTE THE EXPRESSGRID AND ALL ACCOMPANYING VCL } { CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. } { } { THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED } { FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE } { COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE } { AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT } { AND PERMISSION FROM DEVELOPER EXPRESS INC. } { } { CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON } { ADDITIONAL RESTRICTIONS. } { } {*******************************************************************} unit dxGrExpt; interface {$I dxTLVer.inc} uses Classes, dxDBCtrl, dxDBGrid, dxTL, Graphics{$IFDEF DELPHI6}, Variants{$ENDIF}; type { TdxDBGridExport } TdxDBGridExportWrapper = class(TdxDBGrid); TdxDBGridExport = class private FFileName: string; FGrid: TdxDBGridExportWrapper; FSaveAll: Boolean; protected TotalCount: Integer; Stream: TStream; procedure DoBeginWriting; virtual; procedure DoEndWriting; virtual; procedure DoWriteHeader; virtual; procedure DoWriteFooter; virtual; procedure DoWriteRecord(Node: TdxTreeListNode); virtual; public procedure Execute; virtual; procedure SaveToStream(Stream: TStream); virtual; property FileName: string read FFileName write FFileName; property Grid: TdxDBGridExportWrapper read FGrid write FGrid; property SaveAll: Boolean read FSaveAll write FSaveAll; end; { TdxDBGridExportExcel } TdxDBGridExportExcel = class(TdxDBGridExport) protected VisColIndexes: array [0..255] of Integer; VisColCount: Integer; procedure DoBeginWriting; override; procedure DoEndWriting; override; procedure DoWriteHeader; override; procedure DoWriteFooter; override; procedure DoWriteRecord(Node: TdxTreeListNode); override; end; { TdxDBGridExportHTML } TdxDBGridExportHTML = class(TdxDBGridExport) private procedure GetFontStyle(AFont: TFont; var SBegin, SEnd: string); function GetHTMLAlignment(AAlignment: TAlignment): String; procedure Write(const S: string); procedure WriteLn(S: string); protected procedure DoBeginWriting; override; procedure DoEndWriting; override; procedure DoWriteHeader; override; procedure DoWriteFooter; override; procedure DoWriteRecord(Node: TdxTreeListNode); override; end; { TdxDBGridExportText } TdxDBGridExportText = class(TdxDBGridExport) private FSeparator: string; FBeginString, FEndString: string; procedure WriteLn(S: string); protected procedure DoWriteHeader; override; procedure DoWriteRecord(Node: TdxTreeListNode); override; public property Separator: string read FSeparator write FSeparator; property BeginString: string read FBeginString write FBeginString; property EndString: string read FEndString write FEndString; end; { TdxDBGridExportXML } TdxDBGridExportXML = class(TdxDBGridExport) private FGroupCount: Integer; FIndentCharCount: Integer; procedure BeginRows; procedure ChangeIndent(AValue: Integer); procedure CloseGroup; procedure CloseGroups; procedure EndRows; function GetIndentStr: string; function GetNodeValue(ANode: TdxTreeListNode; AColumn: TdxDBGridColumn): string; procedure WriteBands; procedure WriteColumns; procedure WriteDTD; procedure WriteGroup(Node: TdxTreeListNode); procedure WriteRow(Node: TdxTreeListNode); procedure WriteXSL; protected procedure DoBeginWriting; override; procedure DoEndWriting; override; procedure DoWriteHeader; override; procedure DoWriteFooter; override; procedure DoWriteRecord(Node: TdxTreeListNode); override; procedure Write(const S: string); procedure WriteLn(S: string); end; procedure SaveToHTML(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean); procedure SaveToXLS(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean); procedure SaveToText(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean; const ASeparator, ABeginString, AEndString: string); procedure SaveToXML(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean); implementation uses Windows, SysUtils, DB, Forms, dxGrDate; // Excel format const XLSBOF: array[0..4] of Word = ($409, 6, 0, $10, 0); XLSGUTS: array[0..5] of Word = ($80, 8, 0, 0, 0, 0); XLSPalette: array[0..2] of Word = ($92, 0, 0); XLSDimension: array [0..6] of Word = ($200, $0A, 0, $FFFF, 0, $FF, 0); XLSEOF: array[0..1] of Word = ($0A, 0); XLSFONTH: array[0..9] of Byte = ($31, 2, 0, 0, 0, 0, 0, 0, 8, 0); XLSFONTG: array[0..9] of Byte = ($31, 2, 0, 0, 0, 0, 0, 0, 10, 0); XLSFONT: array[0..9] of Byte = ($31, 2, 0, 0, 0, 0, 0, 0, 0, 0); XLSXF1: array[0..15] of Byte = ($43, 4, $0C, 0, 0, 0, $F5, $FF, $20, 0, 0, $CE, 0, 0, 0, 0); XLSXF2: array[0..15] of Byte = ($43, 4, $0C, 0, 1, 0, $F5, $FF, $20, $F4, 0, $CE, 0, 0, 0, 0); XLSXF3: array[0..15] of Byte = ($43, 4, $0C, 0, 2, 0, $F5, $FF, $20, $F4, 0, $CE, 0, 0, 0, 0); XLSXF4: array[0..15] of Byte = ($43, 4, $0C, 0, 0, 0, $F5, $FF, $20, $F4, 0, $CE, 0, 0, 0, 0); XLSXF5: array[0..15] of Byte = ($43, 4, $0C, 0, 0, 0, 1, 0, $20, 0, 0, $CE, 0, 0, 0, 0); XLSXF6: array[0..15] of Byte = ($43, 4, $0C, 0, 1, $21, $F5, $FF, $20, $F8, 0, $CE, 0, 0, 0, 0); XLSXF7: array[0..15] of Byte = ($43, 4, $0C, 0, 1, $1F, $F5, $FF, $20, $F8, 0, $CE, 0, 0, 0, 0); XLSXF8: array[0..15] of Byte = ($43, 4, $0C, 0, 1, $20, $F5, $FF, $20, $F8, 0, $CE, 0, 0, 0, 0); XLSXF9: array[0..15] of Byte = ($43, 4, $0C, 0, 1, $1E, $F5, $FF, $20, $F8, 0, $CE, 0, 0, 0, 0); XLSXF10: array[0..15] of Byte = ($43, 4, $0C, 0, 1, $0D, $F5, $FF, $20, $F8, 0, $CE, 0, 0, 0, 0); XLSXF: array[0..15] of Byte = ($43, 4, $0C, 0, 5, 0, 1, 0, $21, $78, $41, 3, 0, 0, 0, 0); XLSXFB: array[0..15] of Byte = ($43, 4, $0C, 0, 8, 0, 1, 0, $22, $78, $41, 2, $71, $71, $71, 0); XLSXFH: array[0..15] of Byte = ($43, 4, $0C, 0, 6, 0, 1, 0, $22, $78, $41, 2, $71, $71, $71, $71); XLSXFG: array[0..15] of Byte = ($43, 4, $0C, 0, 7, 0, 1, 0, $21, $78, $C1, 2, 0, 0, 0, 0); XLSXFF: array[0..15] of Byte = ($43, 4, $0C, 0, 5, 0, 1, 0, $22, $78, $C1, 2, $B9, $B9, $B9, $B9); XLSXFF1: array[0..15] of Byte = ($43, 4, $0C, 0, 5, 0, 1, 0, $22, $78, $C1, 2, $B9, 0, $B9, 0); XLSXFRF: array[0..15] of Byte = ($43, 4, $0C, 0, 9, 0, 1, 0, $21, $78, $C1, 2, $B9, $B9, $B9, $B9); XLSXFRF1: array[0..15] of Byte = ($43, 4, $0C, 0, 9, 0, 1, 0, $21, $78, $C1, 2, $B9, 0, $B9, 0); XLSCOL: array[0..7] of Word = ($7D, $0C, 0, 0, 0, $F, 0, 0); XLSSFONT: array[0..15] of Byte = ($31, 2, $0C, 0, $C8, 0, 0, 0, $FF, $7F, 5, $41, $72, $69, $61, $6C); XLSLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0); XLSBlank: array[0..4] of Word = ($201, 6, 0, 0, $17); XLSBlankF: array[0..4] of Word = ($201, 6, 0, 0, $19); XLSBlankRF: array[0..4] of Word = ($201, 6, 0, 0, $1C); // XLSBlankH: array[0..4] of Word = ($201, 6, 0, 0, $16); // XLSBlankB: array[0..4] of Word = ($201, 6, 0, 0, $1A); XLSNumber: array[0..4] of Word = ($203, 14, 0, 0, 0); XLSRK: array[0..4] of Word = ($27E, 10, 0, 0, 0); XLSFormula: array[0..15] of Word =($406, $1D, 0, 0, $18, 0, 0, 0, 0, 3, $0B, $25, 0, 0, 0, 0); function CompareByPointer(Item1, Item2: Pointer): Integer; begin Result := {DWORD}Integer(Item1) - {DWORD}Integer(Item2); end; function CompareByAbsoluteIndex(Item1, Item2: Pointer): Integer; var Node1, Node2: TdxTreeListNode; begin Node1 := TdxTreeListNode(Item1); Node2 := TdxTreeListNode(Item2); if Node1.HasAsParent(Node2) then begin Result := 1; Exit; end; if Node2.HasAsParent(Node1) then begin Result := -1; Exit; end; while Node1.Level > Node2.Level do Node1 := Node1.Parent; while Node2.Level > Node1.Level do Node2 := Node2.Parent; while Node1.Parent <> Node2.Parent do begin Node1 := Node1.Parent; Node2 := Node2.Parent; end; Result := (Node1.Index - Node2.Index); end; // XML routines // Date in a subset of ISO 8601 format, with optional time and no optional zone. // Fractional seconds can be as precise as nanoseconds. // For example, "1988-04-07T18:39:09". function ConvertDateToXmlStr(const V: Variant): string; const DTFormat: array [Boolean] of string = ('yyyy-mm-dd', 'yyyy-mm-dd"T"hh:nn:ss'); var D: TDateTime; begin D := TDateTime(V); if D = NullDate then Result := '' else if DateOf(D) = 0 then Result := FormatDateTime('hh:nn:ss', V) else Result := FormatDateTime(DTFormat[TimeOf(V) <> 0], V); end; function CharToUTF8(const AChar: Char): string; var WS: WideString; begin WS := AChar; SetLength(Result, 2); WideCharToMultiByte(CP_UTF8, 0, PWideChar(WS), 1, @Result[1], 2, nil, nil); end; function ConvertTextToXml(const AText: string): string; const NormalAlpha = ['0'..'9', ':', ';', '*', '+', ',', '-', '.', '/', '!', ' ', 'A'..'Z', 'a'..'z', '_']; var I: Integer; begin Result := ''; for I := 1 to Length(AText) do if AText[I] in NormalAlpha then Result := Result + AText[I] else Result := Result + CharToUTF8(AText[I]); // Result := Result + Format('&#%d;', [Ord(AText[I])]); end; function ConvertFileNameToXml(const AText: string): string; const NormalAlpha = ['0'..'9', '-', '.', 'A'..'Z', 'a'..'z', '_']; var I: Integer; begin Result := AText; for I := 1 to Length(Result) do if not (Result[I] in NormalAlpha) then Result[I] := '_'; end; function GetColumnIdentifier(AColumn: TdxTreeListColumn): string; begin if AColumn.Name = '' then Result := 'Column' + IntToStr(AColumn.Index) else Result := AColumn.Name; end; procedure SaveToHTML(AGrid: TdxDBGrid; const AFileName : String; ASaveAll: Boolean); begin with TdxDBGridExportHTML.Create do try FileName := AFileName; Grid := TdxDBGridExportWrapper(AGrid); SaveAll := ASaveAll; Execute; finally Free; end; end; procedure SaveToXLS(AGrid: TdxDBGrid; const AFileName : String; ASaveAll: Boolean); begin with TdxDBGridExportExcel.Create do try FileName := AFileName; Grid := TdxDBGridExportWrapper(AGrid); SaveAll := ASaveAll; Execute; finally Free; end; end; procedure SaveToText(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean; const ASeparator, ABeginString, AEndString: string); begin with TdxDBGridExportText.Create do try Separator := ASeparator; BeginString := ABeginString; EndString := AEndString; FileName := AFileName; Grid := TdxDBGridExportWrapper(AGrid); SaveAll := ASaveAll; Execute; finally Free; end; end; procedure SaveToXML(AGrid: TdxDBGrid; const AFileName: string; ASaveAll: Boolean); begin with TdxDBGridExportXML.Create do try FileName := AFileName; Grid := TdxDBGridExportWrapper(AGrid); SaveAll := ASaveAll; Execute; finally Free; end; end; { TdxDBGridExport } procedure TdxDBGridExport.Execute; begin Stream := TFileStream.Create(FileName, fmCreate); try SaveToStream(Stream); finally Stream.Free; Stream := nil; end; end; procedure TdxDBGridExport.SaveToStream(Stream: TStream); var FlagAll: Boolean; DataSet: TDataSet; Current: TBookmarkStr; i: Integer; FList: TList; Node: TdxTreeListNode; OldTopIndex: Integer; FlagDataSet: Boolean; procedure LoadList(Node: TdxTreeListNode); var i: Integer; begin FList.Add(Node); if Node.HasChildren then for i := 0 to Node.Count - 1 do LoadList(Node[i]); end; procedure LoadParent(Node: TdxTreeListNode); begin if (Node <> nil) and (FList.IndexOf(Node) = -1 ) then begin FList.Add(Node); LoadParent(Node.Parent); end; end; procedure LoadSelNodeList(Node: TdxTreeListNode); var i: Integer; begin FList.Add(Node); LoadParent(Node.Parent); if Node.HasChildren then for i := 0 to Node.Count - 1 do LoadList(Node[i]); end; procedure LoadNodes(List: TList); var i: Integer; begin List.Clear; with Grid do if FlagAll then for i := 0 to Count - 1 do LoadList(Items[i]) else begin for i := 0 to SelectedCount - 1 do LoadSelNodeList(SelectedNodes[i]); // sort by pointer and kill equal nodes List.Sort(CompareByPointer); for i := List.Count - 1 downto 1 do if List[i] = List[i - 1] then List.Delete(i); // sort by absolute order List.Sort(CompareByAbsoluteIndex); end; end; begin if Assigned(FGrid) and Assigned(FGrid.DataSource) and Assigned(FGrid.DataSource.DataSet) then with FGrid do begin FlagAll := FSaveAll or (SelectedCount = 0); FlagDataSet := IsGridMode or (IsPartialLoad and FlagAll); DataSet := DataSource.DataSet; if FlagDataSet then begin DataSet.DisableControls; Current := DataSet.Bookmark; OldTopIndex := TopIndex; end else OldTopIndex := -1; DoBeginWriting; try TotalCount := 0; // write header DoWriteHeader; if FlagDataSet{IsGridMode or (IsPartialLoad and FlagAll)} then begin if FlagAll then begin DataSet.First; while not DataSet.EOF do begin // processing record DoWriteRecord(nil); Inc(TotalCount); DataSet.Next; end; end else for i := 0 to SelectedCount - 1 do begin DataSet.Bookmark := SelectedRows[i]; // processing record DoWriteRecord(nil); Inc(TotalCount); end; end else begin FList := TList.Create; try LoadNodes(FList); for i := 0 to FList.Count - 1 do begin Node := TdxTreeListNode(FList[i]); // processing record DoWriteRecord(Node); Inc(TotalCount); end; finally FList.Free; end; end; DoWriteFooter; finally DoEndWriting; if FlagDataSet then begin DataSet.Bookmark := Current; DataSet.EnableControls; TopIndex := OldTopIndex; end; end; end; end; procedure TdxDBGridExport.DoBeginWriting; begin end; procedure TdxDBGridExport.DoEndWriting; begin end; procedure TdxDBGridExport.DoWriteHeader; begin end; procedure TdxDBGridExport.DoWriteFooter; begin end; procedure TdxDBGridExport.DoWriteRecord(Node: TdxTreeListNode); begin end; {TdxDBGridExportExcel} procedure TdxDBGridExportExcel.DoBeginWriting; var C: LongInt; S: string; B: Byte; i, j, k: Integer; begin with Grid do begin VisColCount := 0; for i := 0 to GetBandCount - 1 do for j := 0 to GetHeaderRowCount(i) - 1 do for k := 0 to GetHeaderColCount(i, j) - 1 do if IsHeaderVisible(GetHeaderAbsoluteIndex(i,j,k)) then begin VisColIndexes[VisColCount] := GetHeaderAbsoluteIndex(i,j,k); Inc(VisColCount); end; Stream.WriteBuffer(XLSBOF, SizeOf(XLSBOF)); Stream.WriteBuffer(XLSGUTS, SizeOf(XLSGUTS)); // XLS Palette XLSPalette[1] := 54; XLSPalette[2] := 13; Stream.WriteBuffer(XLSPalette, SizeOf(XLSPalette)); if HeaderFont.Color = clNone then C := 0 else C := ColorToRGB(HeaderFont.Color); Stream.WriteBuffer(C, SizeOf(C)); if HeaderColor = clNone then C := 0 else C := ColorToRGB(HeaderColor); Stream.WriteBuffer(C, SizeOf(C)); if GroupNodeTextColor = clNone then C := 0 else C := ColorToRGB(GroupNodeTextColor); Stream.WriteBuffer(C, SizeOf(C)); if GroupNodeColor = clNone then C := 0 else C := ColorToRGB(GroupNodeColor); Stream.WriteBuffer(C, SizeOf(C)); if Font.Color = clNone then C := 0 else C := ColorToRGB(Font.Color); Stream.WriteBuffer(C, SizeOf(C)); if Color = clNone then C := 0 else C := ColorToRGB(Color); Stream.WriteBuffer(C, SizeOf(C)); C := ColorToRGB(clWindowFrame); Stream.WriteBuffer(C, SizeOf(C)); C := ColorToRGB(clWindow); Stream.WriteBuffer(C, SizeOf(C)); if BandFont.Color = clNone then C := 0 else C := ColorToRGB(BandFont.Color); Stream.WriteBuffer(C, SizeOf(C)); if BandColor = clNone then C := 0 else C := ColorToRGB(BandColor); Stream.WriteBuffer(C, SizeOf(C)); if RowFooterTextColor = clNone then C := 0 else C := ColorToRGB(RowFooterTextColor); Stream.WriteBuffer(C, SizeOf(C)); if RowFooterColor = clNone then C := 0 else C := ColorToRGB(RowFooterColor); Stream.WriteBuffer(C, SizeOf(C)); if GridLineColor = clNone then C := 0 else C := ColorToRGB(GridLineColor); Stream.WriteBuffer(C, SizeOf(C)); // XLS Font Stream.WriteBuffer(XLSSFont, SizeOf(XLSSFont)); Stream.WriteBuffer(XLSSFont, SizeOf(XLSSFont)); Stream.WriteBuffer(XLSSFont, SizeOf(XLSSFont)); Stream.WriteBuffer(XLSSFont, SizeOf(XLSSFont)); // Grid Font S := Font.Name; B := Length(S); XLSFont[2] := B + 7; XLSFont[4] := Font.Size*20 mod 256; XLSFont[5] := Font.Size*20 div 256; XLSFont[6] := 0; if (fsBold in Font.Style) then XLSFont[6] := XLSFont[6] + 1; if (fsItalic in Font.Style) then XLSFont[6] := XLSFont[6] + 2; if (fsUnderline in Font.Style) then XLSFont[6] := XLSFont[6] + 4; if (fsStrikeOut in Font.Style) then XLSFont[6] := XLSFont[6] + 8; XLSFont[8] := 12; Stream.WriteBuffer(XLSFont, SizeOf(XLSFont)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); // Header Font S := HeaderFont.Name; B := Length(S); XLSFontH[2] := B + 7; XLSFontH[4] := HeaderFont.Size*20 mod 256; XLSFontH[5] := HeaderFont.Size*20 div 256; XLSFontH[6] := 0; if (fsBold in HeaderFont.Style) then XLSFontH[6] := XLSFontH[6] + 1; if (fsItalic in HeaderFont.Style) then XLSFontH[6] := XLSFontH[6] + 2; if (fsUnderline in HeaderFont.Style) then XLSFontH[6] := XLSFontH[6] + 4; if (fsStrikeOut in HeaderFont.Style) then XLSFontH[6] := XLSFontH[6] + 8; Stream.WriteBuffer(XLSFontH, SizeOf(XLSFontH)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); // Group Font S := Font.Name; B := Length(S); XLSFontG[2] := B + 7; XLSFontG[4] := Font.Size*20 mod 256; XLSFontG[5] := Font.Size*20 div 256; XLSFontG[6] := 0; if (fsBold in Font.Style) then XLSFontG[6] := XLSFontG[6] + 1; if (fsItalic in Font.Style) then XLSFontG[6] := XLSFontG[6] + 2; if (fsUnderline in Font.Style) then XLSFontG[6] := XLSFontG[6] + 4; if (fsStrikeOut in Font.Style) then XLSFontG[6] := XLSFontG[6] + 8; Stream.WriteBuffer(XLSFontG, SizeOf(XLSFontG)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); // Band Font S := BandFont.Name; B := Length(S); XLSFont[2] := B + 7; XLSFont[4] := BandFont.Size*20 mod 256; XLSFont[5] := BandFont.Size*20 div 256; XLSFont[6] := 0; if (fsBold in BandFont.Style) then XLSFont[6] := XLSFont[6] + 1; if (fsItalic in BandFont.Style) then XLSFont[6] := XLSFont[6] + 2; if (fsUnderline in BandFont.Style) then XLSFont[6] := XLSFont[6] + 4; if (fsStrikeOut in BandFont.Style) then XLSFont[6] := XLSFont[6] + 8; XLSFont[8] := 16; Stream.WriteBuffer(XLSFont, SizeOf(XLSFont)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); // Footer Font S := Font.Name; B := Length(S); XLSFont[2] := B + 7; XLSFont[4] := Font.Size*20 mod 256; XLSFont[5] := Font.Size*20 div 256; XLSFont[6] := 0; if (fsBold in Font.Style) then XLSFont[6] := XLSFont[6] + 1; if (fsItalic in Font.Style) then XLSFont[6] := XLSFont[6] + 2; if (fsUnderline in Font.Style) then XLSFont[6] := XLSFont[6] + 4; if (fsStrikeOut in Font.Style) then XLSFont[6] := XLSFont[6] + 8; XLSFont[8] := 18; Stream.WriteBuffer(XLSFont, SizeOf(XLSFont)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); // Columns Fonts for i := 0 to VisColCount - 1 do begin S := GetColumnFont(VisColIndexes[i]).Name; B := Length(S); XLSFont[2] := B + 7; XLSFont[4] := GetColumnFont(VisColIndexes[i]).Size*20 mod 256; XLSFont[5] := GetColumnFont(VisColIndexes[i]).Size*20 div 256; XLSFont[6] := 0; if (fsBold in GetColumnFont(VisColIndexes[i]).Style) then XLSFont[6] := XLSFont[6] + 1; if (fsItalic in GetColumnFont(VisColIndexes[i]).Style) then XLSFont[6] := XLSFont[6] + 2; if (fsUnderline in GetColumnFont(VisColIndexes[i]).Style) then XLSFont[6] := XLSFont[6] + 4; if (fsStrikeOut in GetColumnFont(VisColIndexes[i]).Style) then XLSFont[6] := XLSFont[6] + 8; XLSFont[8] := 12; Stream.WriteBuffer(XLSFont, SizeOf(XLSFont)); Stream.WriteBuffer(B, SizeOf(B)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end; // Grid Stream.WriteBuffer(XLSXF1, SizeOf(XLSXF1)); Stream.WriteBuffer(XLSXF2, SizeOf(XLSXF2)); Stream.WriteBuffer(XLSXF2, SizeOf(XLSXF2)); Stream.WriteBuffer(XLSXF3, SizeOf(XLSXF3)); Stream.WriteBuffer(XLSXF3, SizeOf(XLSXF3)); for i := 0 to 9 do Stream.WriteBuffer(XLSXF4, SizeOf(XLSXF4)); Stream.WriteBuffer(XLSXF5, SizeOf(XLSXF5)); Stream.WriteBuffer(XLSXF6, SizeOf(XLSXF6)); Stream.WriteBuffer(XLSXF7, SizeOf(XLSXF7)); Stream.WriteBuffer(XLSXF8, SizeOf(XLSXF8)); Stream.WriteBuffer(XLSXF9, SizeOf(XLSXF9)); Stream.WriteBuffer(XLSXF10, SizeOf(XLSXF10)); if ShowGrid then begin XLSXF[12] := $A1; XLSXF[13] := $A1; XLSXF[14] := $A1; XLSXF[15] := $A1; end; Stream.WriteBuffer(XLSXF, SizeOf(XLSXF)); Stream.WriteBuffer(XLSXFH, SizeOf(XLSXFH)); Stream.WriteBuffer(XLSXFG, SizeOf(XLSXFG)); Stream.WriteBuffer(XLSXFF, SizeOf(XLSXFF)); Stream.WriteBuffer(XLSXFF1, SizeOf(XLSXFF1)); Stream.WriteBuffer(XLSXFB, SizeOf(XLSXFB)); Stream.WriteBuffer(XLSXFRF, SizeOf(XLSXFRF)); Stream.WriteBuffer(XLSXFRF1, SizeOf(XLSXFRF1)); for i := 0 to VisColCount - 1 do begin XLSXF[4] := i + 10; case Columns[VisColIndexes[i]].Alignment of taLeftJustify : XLSXF[8] := $21; taRightJustify : XLSXF[8] := $23; taCenter : XLSXF[8] := $22; end; // XLSXF[11] := i*2 + 21; //// Stream.WriteBuffer(XLSXF, SizeOf(XLSXF)); end; // Group Columns for i := 0 to GroupColumnCount - 1 do begin XLSCOL[2] := i; XLSCOL[3] := i; XLSCOL[4] := 400; Stream.WriteBuffer(XLSCOL, SizeOf(XLSCOL)); end; // VsibleColumns for i := 0 to VisColCount - 1 do begin XLSCOL[2] := i + GroupColumnCount; XLSCOL[3] := i + GroupColumnCount; XLSCOL[4] := 36 * GetHeaderBoundsWidth(VisColIndexes[i]); Stream.WriteBuffer(XLSCOL, SizeOf(XLSCOL)); end; Stream.WriteBuffer(XLSDimension, SizeOf(XLSDimension)); end; end; procedure TdxDBGridExportExcel.DoWriteHeader; var i, j, k: Integer; S: string; begin with Grid do begin // Draw Bands if ShowBands then begin for i := 0 to GroupColumnCount - 1 do begin XLSBlank[2] := TotalCount; XLSBlank[3] := i; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end; for j := 0 to VisColCount - 1 do begin XLSBlank[2] := TotalCount; XLSBlank[3] := j + GroupColumnCount; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end; k := 0; for i := 0 to GetBandCount - 1 do begin S := GetBandText(i); XLSLAbel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := k + GroupColumnCount; XLSLabel[4] := $1A; XLSLabel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); for j := 0 to GetHeaderRowCount(i) - 1 do k := k + GetHeaderColCount(i,j); end; Inc(TotalCount); end; // Draw Heders if ShowHeader then begin for i := 0 to GroupColumnCount - 1 do begin XLSBlank[2] := TotalCount; XLSBlank[3] := i; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end; for i := 0 to VisColCount - 1 do begin // S := GetHeaderText(VisColIndexes[i]); S := Columns[VisColIndexes[i]].Caption; if Columns[VisColIndexes[i]].DisableCaption then S := ''; XLSLAbel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := i + GroupColumnCount; XLSLabel[4] := $16; XLSLabel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end; Inc(TotalCount); end; end; end; procedure TdxDBGridExportExcel.DoWriteRecord(Node: TdxTreeListNode); var C: LongInt; F: Double; i, j: Integer; S: string; V: Variant; begin with Grid do begin if (GroupColumnCount > 0) and (Node <> nil) then begin for i := 0 to GroupColumnCount - 1 do if i = Node.Level then begin S := Node.Strings[GroupColumns[Node.Level].Index]; XLSLAbel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := i; XLSLabel[4] := $17; XLSLAbel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end else begin XLSBlank[2] := TotalCount; XLSBlank[3] := i; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end; end; for i := 0 to VisColCount - 1 do begin if (Node <> nil) and Node.HasChildren then begin XLSBlank[2] := TotalCount; XLSBlank[3] := GroupColumnCount + i; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end else if (Columns[VisColIndexes[i]].FieldName = '') or not Assigned(Columns[VisColIndexes[i]].Field ) then begin XLSLAbel[1] := 8; XLSLabel[2] := TotalCount; XLSLabel[3] := i; XLSLabel[4] := $1D + i; XLSLAbel[5] := 0; Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); end else begin with Columns[VisColIndexes[i]].Field do begin if Node <> nil then V := Node.Values[Columns[VisColIndexes[i]].Index] else V := Value; // Convert Value if Columns[VisColIndexes[i]].ConvertExportValue(V, False) then case VarType(V) of varSmallint, varInteger: begin if VarIsNull(V) then C := 0 else C := V; C := C shl 2 + 2; XLSRK[2] := TotalCount; XLSRK[3] := GroupColumnCount + i; XLSRK[4] := $1D + i; Stream.WriteBuffer(XLSRK, SizeOf(XLSRK)); Stream.WriteBuffer(C, SizeOf(C)); end; varSingle, varDouble, varCurrency: begin if VarIsNull(V) then F := 0.0 else F := V; XLSNumber[2] := TotalCount; XLSNumber[3] := GroupColumnCount + i; XLSNumber[4] := $1D + i; Stream.WriteBuffer(XLSNumber, SizeOf(XLSNumber)); Stream.WriteBuffer(F, SizeOf(F)); end; else {String} begin if VarIsNull(V) then S := '' else S := V; if DataType = ftMemo then S := Copy(S, 0, 255); XLSLAbel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := GroupColumnCount + i; XLSLabel[4] := $1D + i; XLSLAbel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end; end else {old} begin case DataType of ftSmallint, ftInteger, ftWord, ftAutoInc, ftBytes: begin if Node = nil then C := AsInteger else begin V := TdxDBGridNode(Node).VariantValues[Columns[VisColIndexes[i]].Index]; if V = Null then C := 0 else C := V; end; C := C shl 2 + 2; XLSRK[2] := TotalCount; XLSRK[3] := GroupColumnCount + i; XLSRK[4] := $1D + i; Stream.WriteBuffer(XLSRK, SizeOf(XLSRK)); Stream.WriteBuffer(C, SizeOf(C)); end; ftFloat, ftCurrency, ftBCD: begin if Node = nil then F := AsFloat else begin V := TdxDBGridNode(Node).VariantValues[Columns[VisColIndexes[i]].Index]; if V = Null then F := 0.0 else F := V; end; XLSNumber[2] := TotalCount; XLSNumber[3] := GroupColumnCount + i; XLSNumber[4] := $1D + i; Stream.WriteBuffer(XLSNumber, SizeOf(XLSNumber)); Stream.WriteBuffer(F, SizeOf(F)); end; else begin if Node = nil then S := DisplayText else S := TdxDBGridNode(Node).Strings[Columns[VisColIndexes[i]].Index]; if DataType = ftMemo then S := Copy(S, 0, 255); XLSLAbel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := GroupColumnCount + i; XLSLabel[4] := $1D + i; XLSLAbel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end; end; end; end; end; end; for j := 0 to GetRowFooterCount(Node) - 1 do begin Inc(TotalCount); for i := 0 to GetNodeFooterLevel(Node,j) do begin XLSBlank[2] := TotalCount; XLSBlank[3] := i; Stream.WriteBuffer(XLSBlank, SizeOf(XLSBlank)); end; for i := 0 to VisColCount - 1 do if not IsExistRowFooterCell(Node,VisColIndexes[i],j) then begin XLSBlankRF[2] := TotalCount; XLSBlankRF[3] := GroupColumnCount + i; Stream.WriteBuffer(XLSBlankRF, SizeOf(XLSBlankRF)); end else begin S := GetFooterCellText(Node,VisColIndexes[i],j); XLSLabel[1] := Length(S) + 8; XLSLabel[2] := TotalCount; XLSLabel[3] := GroupColumnCount + i; if (i = 0) and (GroupColumnCount - GetNodeFooterLevel(Node,j) - 1 > 0) then XLSLabel[3] := GetNodeFooterLevel(Node,j) + 1 ; XLSLabel[4] := $1B; XLSLabel[5] := Length(S); Stream.WriteBuffer(XLSLabel, SizeOf(XLSLabel)); Stream.WriteBuffer(Pointer(S)^, Length(S)); end; for i := 1 to GroupColumnCount - GetNodeFooterLevel(Node,j) - 1 do begin XLSBlankRF[2] := TotalCount; XLSBlankRF[3] := GroupColumnCount - i + 1; Stream.WriteBuffer(XLSBlankRF, SizeOf(XLSBlankRF)); end; end; end; end; procedure TdxDBGridExportExcel.DoWriteFooter; function FindSummaryCol(const FieldName: string; var Column: TdxDBTreeListColumn): Integer; var i: Integer; begin Result := -1; for i := 0 to VisColCount - 1 do if AnsiCompareText(Grid.Columns[VisColIndexes[i]].FieldName, FieldName) = 0 then begin Result := i; Exit; end; end; var i, ColIndx: Integer; Col: TdxDBTreeListColumn; b: Byte; begin with Grid do if ShowSummaryFooter then begin for i := 0 to GroupColumnCount - 1 do begin XLSBlankF[2] := TotalCount; XLSBlankF[3] := i; Stream.WriteBuffer(XLSBlankF, SizeOf(XLSBlankF)); end; for i := 0 to VisColCount - 1 do begin with TdxDBGridColumn(Columns[VisColIndexes[i]]) do begin case SummaryFooterType of cstAvg: XLSFormula[15] := $501; cstCount: XLSFormula[15] := $A901; cstMax: XLSFormula[15] := $701; cstMin: XLSFormula[15] := $601; cstSum: XLSFormula[15] := $10; end; ColIndx := FindSummaryCol(SummaryFooterField, Col); if (SummaryFooterType = cstCount) then ColIndx := i; if (SummaryFooterType = cstNone) or (ColIndx = -1) then begin XLSBlankF[2] := TotalCount; XLSBlankF[3] := GroupColumnCount + i; Stream.WriteBuffer(XLSBlankF, SizeOf(XLSBlankF)); end else begin XLSFormula[2] := TotalCount; XLSFormula[3] := GroupColumnCount + i; XLSFormula[11] := $25; if ShowBands then XLSFormula[11] := XLSFormula[11] + $100; if ShowHeader then XLSFormula[11] := XLSFormula[11] + $100; XLSFormula[12] := ((TotalCount - 1) shl 8) + $C0; XLSFormula[13] := ((GroupColumnCount + ColIndx) shl 8) + (((TotalCount - 1) shr 8) or $C0); if SummaryFooterType = cstSum then XLSFormula[14] := $1900 + GroupColumnCount + ColIndx else XLSFormula[14] := $4200 + GroupColumnCount + ColIndx; Stream.WriteBuffer(XLSFormula, SizeOf(XLSFormula)); b := 0; Stream.WriteBuffer(b, SizeOf(b)); end; end; end; end; end; procedure TdxDBGridExportExcel.DoEndWriting; begin Stream.WriteBuffer(XLSEOF, SizeOf(XLSEOF)); end; {TdxDBGridExportHTML} procedure TdxDBGridExportHTML.GetFontStyle(AFont: TFont; var SBegin, SEnd: string); begin SBegin := ''; if (fsBold in AFont.Style) then SBegin := SBegin + ''; if (fsItalic in AFont.Style) then SBegin := SBegin + ''; if (fsUnderline in AFont.Style) then SBegin := SBegin + ''; if (fsStrikeOut in AFont.Style) then SBegin := SBegin + ''; SEnd := ''; if (fsStrikeOut in AFont.Style) then SEnd := SEnd + ''; if (fsUnderline in AFont.Style) then SEnd := SEnd + ''; if (fsItalic in AFont.Style) then SEnd := SEnd + ''; if (fsBold in AFont.Style) then SEnd := SEnd + ''; end; function TdxDBGridExportHTML.GetHTMLAlignment(AAlignment: TAlignment): String; begin case AAlignment of taLeftJustify: Result := 'LEFT'; taCenter: Result := 'CENTER'; taRightJustify: Result := 'RIGHT'; end; end; procedure TdxDBGridExportHTML.Write(const S: string); begin Stream.WriteBuffer(Pointer(S)^, Length(S)); end; procedure TdxDBGridExportHTML.WriteLn(S: string); begin S := S + #13#10; Stream.WriteBuffer(Pointer(S)^, Length(S)); end; procedure TdxDBGridExportHTML.DoBeginWriting; var S, St: string; begin // HTML Header WriteLn(''); WriteLn(''); WriteLn(''); Write(''); Write(Grid.Name); Writeln(' '); Writeln(''); Writeln(' '); Writeln(''); // Table if Grid.BorderStyle = bsSingle then Writeln('
'); S := ''; Writeln(S); end; procedure TdxDBGridExportHTML.DoWriteHeader; var S, St, St1: string; i, j, k, AI: Integer; begin with Grid do begin // Draw Bands if ShowBands then begin S := ''; Write(S); GetFontStyle(BandFont, St, St1); if GroupColumnCount > 0 then begin S := ''; Write(S); end; for i := 0 to GetBandCount - 1 do begin k := 0; for j := 0 to GetHeaderRowCount(i) - 1 do k := k + GetHeaderColCount(i,j); S := ''; Write(S); end; Writeln(''); end; // Draw Headers if ShowHeader then begin S := ''; Write(S); if GroupColumnCount > 0 then begin S := ''; Write(S); end; GetFontStyle(HeaderFont, St, St1); for i := 0 to GetBandCount - 1 do for j := 0 to GetHeaderRowCount(i) - 1 do for k := 0 to GetHeaderColCount(i, j) - 1 do begin AI := GetHeaderAbsoluteIndex(i,j,k); if IsHeaderVisible(AI) then begin S := ''; Write(S); end; end; Writeln(''); end; end; end; procedure TdxDBGridExportHTML.DoEndWriting; begin Writeln('
'; if GetBandText(i) = '' then S := S + ' ' else S := S + St + GetBandText(i) + St1; S := S + '
'; if (Columns[AI].Caption = '') or Columns[AI].DisableCaption then S := S + ' ' else S := S + St + Columns[AI].Caption{GetHeaderText(AI)} + St1; S := S + '
'); if Grid.BorderStyle = bsSingle then Writeln('
'); Writeln(''); Writeln(''); end; procedure TdxDBGridExportHTML.DoWriteFooter; var S, S1, St, St1: string; i, j, k, AI: Integer; begin with Grid do if ShowSummaryFooter and not IsGridMode then begin S := ''; Write(S); GetFontStyle(Font, St, St1); if GroupColumnCount > 0 then begin S := ''; Write(S); end; for i := 0 to GetBandCount - 1 do for j := 0 to GetHeaderRowCount(i) - 1 do for k := 0 to GetHeaderColCount(i, j) - 1 do begin AI := GetHeaderAbsoluteIndex(i,j,k); if IsHeaderVisible(AI) then with Columns[AI] do begin S := ''; GetFontStyle(Font, St, St1); S1 := Columns[AI].SummaryFooterText; if S1 = '' then S1 := S1 else S := S + St + S1 + St1; S := S + ''; Write(S); end; end; Writeln(''); end; end; procedure TdxDBGridExportHTML.DoWriteRecord(Node: TdxTreeListNode); var S, S1, St, St1: string; i, j, k, AI, FI: Integer; V: Variant; begin with Grid do begin // group ident if (Node <> nil) and (Node.HasChildren) then begin S := ''; Write(S); GetFontStyle(Font, St, St1); for i := 0 to Node.Level - 1 do begin Write(''; Write(S); end; end else begin Write(''); for i := 0 to GroupColumnCount - 1 do begin Write(''; Write(S); end; end; if (Node <> nil) and (Node.HasChildren) then begin GetFontStyle(Font, St, St1); S := ''; S1 := Node.Strings[GroupColumns[Node.Level].Index]; if S1 = '' then S := S + ' ' else S := S + St + S1 + St1; S := S + ''; Write(S); end else begin for i := 0 to GetBandCount - 1 do for j := 0 to GetHeaderRowCount(i) - 1 do for k := 0 to GetHeaderColCount(i, j) - 1 do begin AI := GetHeaderAbsoluteIndex(i,j,k); if IsHeaderVisible(AI) then with Columns[AI] do begin S := ''; S := S + ''; GetFontStyle(Font, St, St1); // Value if Node <> nil then V := Node.Values[AI] else if Field <> nil then V := Field.Value else V := ''; // Convert Value if ConvertExportValue(V, True) then begin if VarIsNull(V) then S1 := '' else S1 := V end else begin if Node = nil then if Field <> nil then S1 := Field.DisplayText else S1 := '' else S1 := Node.Strings[AI]; end; // // S1 := '' + S1 + ''; // if S1 = '' then S := S + ' ' else S := S + St + S1 + St1; S := S + ''; Write(S); end; end; end; Writeln(''); for FI := 0 to GetRowFooterCount(Node) - 1 do with Grid do begin S := ''; Write(S); for i := 0 to GetNodeFooterLevel(Node,FI) do begin Write(''; Write(S); end; GetFontStyle(Font, St, St1); for i := 0 to GetBandCount - 1 do for j := 0 to GetHeaderRowCount(i) - 1 do for k := 0 to GetHeaderColCount(i, j) - 1 do begin AI := GetHeaderAbsoluteIndex(i,j,k); if IsHeaderVisible(AI) then begin S := ''; S1 := GetFooterCellText(Node,AI,FI); if (S1 = '') or (not IsExistRowFooterCell(Node,AI,FI)) then S1 := ' ' else S := S + St + S1 + St1; S := S + ''; Write(S); end; end; Writeln(''); end; end; end; { TdxDBGridExportText } procedure TdxDBGridExportText.DoWriteHeader; var I, C: Integer; S: string; begin with Grid do begin S := ''; C := GetVisibleHeaderCount; for I := 0 to C - 1 do begin if not Columns[GetFocusedAbsoluteIndex(I)].DisableCaption then S := S + Columns[GetFocusedAbsoluteIndex(I)].Caption; if I <> (C - 1) then S := S + Separator; end; Writeln(S); Writeln(''); end; end; procedure TdxDBGridExportText.DoWriteRecord(Node: TdxTreeListNode); var I, C, AbsoluteIndex: Integer; S, S1: string; V: Variant; begin with Grid do begin S := ''; if Assigned(Node) and IsRowGroup(Node) then S := Node.Strings[0] else begin C := GetVisibleHeaderCount; for I := 0 to C - 1 do begin AbsoluteIndex := GetFocusedAbsoluteIndex(I); with Columns[AbsoluteIndex] do begin if Node <> nil then V := Node.Values[AbsoluteIndex] else if Field <> nil then V := Field.Value else V := ''; // Convert Value if ConvertExportValue(V, False) then begin if VarIsNull(V) then S1 := '' else S1 := V end else begin if Node = nil then if Field <> nil then S1 := Field.DisplayText else S1 := '' else S1 := Node.Strings[AbsoluteIndex]; end; end; S := S + BeginString + S1 + EndString; if I <> (C - 1) then S := S + Separator; end; end; Writeln(S); end; end; procedure TdxDBGridExportText.WriteLn(S: string); begin S := S + #13#10; Stream.WriteBuffer(Pointer(S)^, Length(S)); end; { TdxDBGridExportXSL } type TdxDBGridExportXSL = class private FFileName: string; FGrid: TdxDBGridExportWrapper; FStream: TStream; protected procedure WriteContent; procedure WriteLn(S: string); public procedure Execute; property FileName: string read FFileName write FFileName; property Grid: TdxDBGridExportWrapper read FGrid write FGrid; end; procedure TdxDBGridExportXSL.Execute; begin FStream := TFileStream.Create(FileName, fmCreate); try WriteContent; finally FStream.Free; FStream := nil; end; end; procedure TdxDBGridExportXSL.WriteContent; const StartIndent = ' '; procedure WriteRows(AGroupIndex: Integer); var I, J, K: Integer; AIndex: Integer; Indent: string; AColumn: TdxDBGridColumn; begin Indent := StartIndent; if AGroupIndex <> -1 then begin for I := 0 to AGroupIndex - 1 do Indent := Indent + ' '; end; WriteLn(Format(Indent + '', [Grid.Font.Size, Grid.Font.Name])); // Header WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); // Rows if AGroupIndex = -1 then WriteLn(Indent + ' ') else WriteLn(Indent + ' '); WriteLn(Indent + ' '); for I := 0 to Grid.GetBandCount - 1 do for J := 0 to Grid.GetHeaderRowCount(I) - 1 do for K := 0 to Grid.GetHeaderColCount(I, J) - 1 do begin AIndex := Grid.GetHeaderAbsoluteIndex(I, J, K); if Grid.IsHeaderVisible(AIndex) then begin AColumn := TdxDBGridColumn(Grid.Columns[AIndex]); WriteLn(Indent + ' '); end; end; WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + '
'); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + '
'); WriteLn(Format(Indent + ' ', [GetColumnIdentifier(AColumn)])); WriteLn(Format(Indent + '  ', [GetColumnIdentifier(AColumn)])); WriteLn(Indent + '
'); end; procedure BeginGroup(AGroupIndex: Integer); var I: Integer; Indent: string; S: string; begin Indent := StartIndent; for I := 0 to AGroupIndex - 1 do Indent := Indent + ' '; S := ''; if AGroupIndex = 0 then S := '/GRID/GROUP' else S := 'GROUP'; WriteLn(Format(Indent + '', [S])); WriteLn(Format(Indent + ' ', [Grid.Font.Size, Grid.Font.Name])); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + ' '); WriteLn(Indent + '
 '); // width="1000" WriteLn(Indent + '  '); WriteLn(Indent + '
 '); // width="1000" end; procedure EndGroup(AGroupIndex: Integer); var I: Integer; Indent: string; begin Indent := StartIndent; for I := 0 to AGroupIndex - 1 do Indent := Indent + ' '; WriteLn(Indent + '
'); WriteLn(Indent + '
'); end; procedure WriteSubGroups(AGroupIndex: Integer); begin if AGroupIndex = Grid.GroupColumnCount then WriteRows(AGroupIndex) else begin BeginGroup(AGroupIndex); WriteSubGroups(AGroupIndex + 1); EndGroup(AGroupIndex); end; end; begin WriteLn(''); WriteLn(''); WriteLn(' '); WriteLn(' '); WriteLn(' '); if Grid.GroupColumnCount = 0 then WriteRows(-1) else WriteSubGroups(0); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(''); end; procedure TdxDBGridExportXSL.WriteLn(S: string); begin S := S + #13#10; FStream.WriteBuffer(Pointer(S)^, Length(S)); end; { TdxDBGridExportXML } procedure TdxDBGridExportXML.DoBeginWriting; begin FIndentCharCount := 0; WriteLn(''); WriteXSL; WriteDTD; WriteLn(''); end; procedure TdxDBGridExportXML.DoEndWriting; begin WriteLn(''); end; procedure TdxDBGridExportXML.DoWriteHeader; begin WriteBands; WriteColumns; BeginRows; end; procedure TdxDBGridExportXML.DoWriteFooter; begin EndRows; end; procedure TdxDBGridExportXML.DoWriteRecord(Node: TdxTreeListNode); begin if (Node <> nil) and (Node.Count > 0) then WriteGroup(Node) else WriteRow(Node); end; procedure TdxDBGridExportXML.Write(const S: string); begin Stream.WriteBuffer(Pointer(S)^, Length(S)); end; procedure TdxDBGridExportXML.WriteLn(S: string); begin S := S + #13#10; Stream.WriteBuffer(Pointer(S)^, Length(S)); end; procedure TdxDBGridExportXML.BeginRows; begin if Grid.GroupColumnCount = 0 then begin ChangeIndent(1); WriteLn(GetIndentStr + ''); end; end; procedure TdxDBGridExportXML.ChangeIndent(AValue: Integer); begin Inc(FIndentCharCount, AValue); end; procedure TdxDBGridExportXML.CloseGroups; begin while FGroupCount > 0 do CloseGroup; end; procedure TdxDBGridExportXML.CloseGroup; begin WriteLn(GetIndentStr + ''); Dec(FGroupCount); ChangeIndent(-1); end; procedure TdxDBGridExportXML.EndRows; begin if Grid.GroupColumnCount = 0 then begin WriteLn(GetIndentStr + ''); ChangeIndent(-1); end else CloseGroups; end; function TdxDBGridExportXML.GetNodeValue(ANode: TdxTreeListNode; AColumn: TdxDBGridColumn): string; const DateTimeFields = [ftDate, ftTime, ftDateTime]; SimpleFields = [ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftAutoInc]; var ATextFlag: Boolean; V: Variant; begin if ANode <> nil then V := ANode.Values[AColumn.Index] else if AColumn.Field <> nil then V := AColumn.Field.Value else V := ''; ATextFlag := False; if AColumn.ConvertExportValue(V, False{!}) then begin if VarIsNull(V) then Result := '' else begin if VarType(V) = varDate then Result := ConvertDateToXmlStr(V) else begin Result := V; ATextFlag := (VarType(V) = varString) and (Result <> ''); end; end; end else begin if ANode = nil then begin if Assigned(AColumn.Field) then begin if (AColumn.Field.DataType in SimpleFields) and not Assigned(AColumn.Field.OnGetText) then begin if AColumn.Field.DataType in DateTimeFields then Result := ConvertDateToXmlStr(AColumn.Field.AsDateTime{Value}) else Result := AColumn.Field.AsString; end else begin Result := AColumn.Field.DisplayText; ATextFlag := Result <> ''; end; end else Result := ''; end else begin V := ANode.Values[AColumn.Index]; if VarType(V) = varDate then Result := ConvertDateToXmlStr(V) else begin Result := ANode.Strings[AColumn.Index]; ATextFlag := (VarType(V) = varString) and (Result <> ''); end; end; end; if not ATextFlag then ATextFlag := True; // TODO: if ATextFlag then Result := ConvertTextToXml(Result); //Format('', [Result]); end; function TdxDBGridExportXML.GetIndentStr: string; var I: Integer; begin SetLength(Result, FIndentCharCount * 2); for I := 1 to Length(Result) do Result[I] := ' '; end; procedure TdxDBGridExportXML.WriteBands; var I: Integer; begin with Grid do begin ChangeIndent(1); WriteLn(GetIndentStr + ''); ChangeIndent(1); for I := 0 to GetBandCount - 1 do begin WriteLn(Format(GetIndentStr + '', [I, ConvertTextToXml(GetBandText(I))])); end; ChangeIndent(-1); WriteLn(GetIndentStr + ''); ChangeIndent(-1); end; end; procedure TdxDBGridExportXML.WriteColumns; var I, J, K: Integer; AIndex: Integer; AColumn: TdxTreeListColumn; S: string; begin with Grid do begin ChangeIndent(1); WriteLn(GetIndentStr + ''); ChangeIndent(1); for I := 0 to GetBandCount - 1 do for J := 0 to GetHeaderRowCount(I) - 1 do for K := 0 to GetHeaderColCount(I, J) - 1 do begin AIndex := GetHeaderAbsoluteIndex(I, J, K); if IsHeaderVisible(AIndex) then begin AColumn := Columns[AIndex]; if AColumn.DisableCaption then S := '' else S := AColumn.Caption; WriteLn(Format(GetIndentStr + '', [GetColumnIdentifier(AColumn), ConvertTextToXml(S), AIndex, I, J, K, AColumn.Width])); end; end; ChangeIndent(-1); WriteLn(GetIndentStr + ''); ChangeIndent(-1); end; end; procedure TdxDBGridExportXML.WriteDTD; var I: Integer; begin WriteLn('') else if Grid.GroupColumnCount > 0 then WriteLn(', GROUP*)>') else WriteLn(', ROWS*)>'); WriteLn(' '); // Bands WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); // Columns WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); WriteLn(' '); // Group WriteLn(' '); WriteLn(' '); // Rows WriteLn(' '); // Row WriteLn(' '); for I := 0 to Grid.ColumnCount - 1 do if Grid.IsHeaderVisible(I) then WriteLn(Format(' ', [GetColumnIdentifier(Grid.Columns[I])])); // Common WriteLn(']>'); end; procedure TdxDBGridExportXML.WriteXSL; var S, SFileName: string; begin with TdxDBGridExportXSL.Create do try S := ExtractFilePath(Self.FileName); SFileName := ExtractFileName(Self.FileName); SFileName := ConvertFileNameToXml(ChangeFileExt(SFileName, '.xsl')); FileName := S + SFileName; Grid := Self.Grid; Execute; finally Free; end; WriteLn(Format('', [SFileName])); end; procedure TdxDBGridExportXML.WriteGroup(Node: TdxTreeListNode); var AColumn: TdxTreeListColumn; AGroupText: string; begin while Node.Level < FGroupCount do CloseGroup; ChangeIndent(1); AColumn := Grid.GroupColumns[Node.Level]; AGroupText := ConvertTextToXml(Node.Strings[AColumn.Index]); WriteLn(Format(GetIndentStr + '', [AGroupText])); Inc(FGroupCount); end; procedure TdxDBGridExportXML.WriteRow(Node: TdxTreeListNode); var I, J, K: Integer; AIndex: Integer; AColumn: TdxDBGridColumn; begin ChangeIndent(1); Write(GetIndentStr + ''); ChangeIndent(-1); end; end.