Componentes.Terceros.DevExp.../internal/x.36/1/ExpressVerticalGrid/Sources/cxExportVGLink.pas
2008-09-04 11:31:51 +00:00

1305 lines
41 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressVerticalGrid }
{ }
{ Copyright (c) 1998-2008 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 EXPRESSVERTICALGRID 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 cxExportVGLink;
{$I cxVer.inc}
interface
uses
cxVGrid;
procedure cxExportVGToHTML(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'html');
procedure cxExportVGToXML(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'xml');
procedure cxExportVGToExcel(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
AUseNativeFormat: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'xls');
procedure cxExportVGToText(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
const ASeparator: string = ''; const ABeginString: string = '';
const AEndString: string = ''; ARecordPerBand: Integer = 8;
const AFileExt: string = 'txt');
procedure cxExportVGToFile(AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExportType: Integer;
AExpand, AUseNativeFormat: Boolean; const ASeparators: array of string;
ARecordPerBand: Integer; const AFileExt: string);
implementation
uses
Windows, Types,
Graphics, cxGeometry,
{$IFDEF DELPHI6}
Variants,
{$ENDIF}
cxEdit, cxCalendar, cxCurrencyEdit, cxSpinEdit, cxCalc, cxTimeEdit,
SysUtils, Classes, cxClasses, cxGraphics, cxStyles, cxInplaceContainer,
cxDataUtils, cxExport, cxXLSExport, cxHtmlXmlTxtExport, cxVGridViewInfo,
cxVGridConsts, cxVGridUtils;
type
TcxVerticalGridAccess = class(TcxCustomVerticalGrid);
TcxControllerAccess = class(TcxvgController);
TcxScrollerAccess = class(TcxvgScroller);
TcxViewInfoAccess = class(TcxvgCustomViewInfo);
TcxStylesAccess = class(TcxVerticalGridStyles);
TcxPropertiesAccess = class(TcxCustomEditProperties);
TcxRowHeaderAccess = class(TcxCustomRowHeaderInfo);
TcxCustomEditorRowAccess = class(TcxCustomEditorRow);
TcxCustomEditorRowPropertiesAccess = class(TcxCustomEditorRowProperties);
TcxCustomMultiEditorRowAccess = class(TcxCustomMultiEditorRow);
TcxCustomRowAccess = class(TcxCustomRow);
TcxVerticalGridExportHelper = class;
TcxColumnsMap = class;
TcxRowIndentData = record
StyleIndex: Integer;
IsCategory: Boolean;
Column: Integer;
Width: Integer;
end;
PcxRowIndentData = ^TcxRowIndentData;
{ TcxRowIndentsInfo }
TcxRowIndentsInfo = class
private
FGridLineColor: TColor;
FGridLines: TcxvgGridLines;
FHeaderColumnsMap: TcxColumnsMap;
FHeaderInfo: TcxRowHeaderAccess;
FIsCategory: Boolean;
FList: TList;
FPaintStyle: TcxvgPaintStyle;
FProvider: IcxExportProvider;
FRow: TcxCustomRow;
function GetCount: Integer;
function GetIndent(Index: Integer): TcxRowIndentData;
protected
procedure AddFirstIndent;
procedure AddParentIndents;
procedure Calculate(AHeaderColumnsMap: TcxColumnsMap; AProvider: IcxExportProvider);
property Row: TcxCustomRow read FRow;
property GridLineColor: TColor read FGridLineColor;
property GridLines: TcxvgGridLines read FGridLines;
property HeaderColumnsMap: TcxColumnsMap read FHeaderColumnsMap;
property HeaderInfo: TcxRowHeaderAccess read FHeaderInfo;
property IsCategory: Boolean read FIsCategory;
property PaintStyle: TcxvgPaintStyle read FPaintStyle;
property Provider: IcxExportProvider read FProvider;
public
constructor Create(ARow: TcxCustomRow);
destructor Destroy; override;
property Count: Integer read GetCount;
property Indents[Index: Integer]: TcxRowIndentData read GetIndent;
end;
{ TcxColumnsMap }
TElementInfo = record
Pos: Integer;
ColumnStart: Integer;
ColumnEnd: Integer;
Width: Integer;
IsLevel: Boolean;
case Boolean of
False: (
Row: TcxCustomRow;
CellIndex: Integer
);
True: (
Level: Integer
);
end;
PElementInfo = ^TElementInfo;
TcxColumnsMap = class
private
FElements: TList;
FColumnWidths: array of Integer;
protected
NeedWidth: Integer;
MaxColumnIndex: Integer;
public
constructor Create;
destructor Destroy; override;
procedure AddRowCell(APos: Integer; ARow: TcxCustomRow; ACellIndex, AWidth: Integer);
procedure AddLevel(ALevel, APos, AWidth: Integer);
procedure Build;
procedure CheckNeedWidth(APos: Integer);
function FindColumnForPos(APos: Integer): Integer;
procedure GetColumnInfoFromRowCell(ARow: TcxCustomRow; ACellIndex: Integer;
var AStart, AEnd: Integer);
procedure GetColumnInfoFromLevel(ALevel: Integer; var AStart, AEnd: Integer);
function GetColumnWidth(AIndex: Integer): Integer;
end;
{ TcxRowsIndents }
TcxRowsIndents = class(TList)
private
function GetIndent(Index: Integer): TcxRowIndentsInfo;
public
procedure Clear; override;
property Indents[Index: Integer]: TcxRowIndentsInfo read GetIndent; default;
end;
{ TcxRowCellsInfo }
TRowCaptionCellInfo = record
Caption: string;
Column: Integer;
Width: Integer;
StyleIndex: Integer;
end;
PRowCaptionCellInfo = ^TRowCaptionCellInfo;
TcxRowCellsInfo = class(TList)
private
function GetItem(Index: Integer): TRowCaptionCellInfo;
public
function AddCaption(AColumn: Integer; AWidth: Integer; AStyleIndex: Integer; const ACaption: string): Integer; overload;
procedure Clear; override;
property Items[Index: Integer]: TRowCaptionCellInfo read GetItem; default;
end;
{ TcxRowsCaptions }
TcxRowsCaptions = class(TList)
private
function GetCaption(Index: Integer): TcxRowCellsInfo;
public
function AddCaption: TcxRowCellsInfo;
procedure Clear; override;
property Captions[Index: Integer]: TcxRowCellsInfo read GetCaption;
end;
{ TcxVerticalGridMapInfo }
TcxVerticalGridMapsInfo = class
private
FBandCount: Integer;
FFirstValuesColumn: Integer;
FGridLineColor: TColor;
FGridLines: TcxvgGridLines;
FHeaderColumnsMap: TcxColumnsMap;
FIsEmpty: Boolean;
FLastBandRecords: Integer;
FLevelIndents: array of Integer;
FMaxHeaderWidth: Integer;
FMaxLevel: Integer;
FMaxValueWidth: Integer;
FMinHeaderWidth: Integer;
FMinValueWidth: Integer;
FOwner: TcxVerticalGridExportHelper;
FPaintStyle: TcxvgPaintStyle;
FRecordCount: Integer;
FRecordsPerBand: Integer;
FRowCount: Integer;
FRows: TList;
FRowsCaptions: TcxRowsCaptions;
FRowsIndents: TcxRowsIndents;
FSize: TSize;
FValueColumnsMap: TcxColumnsMap;
FVerticalGrid: TcxVerticalGridAccess;
FViewInfo: TcxViewInfoAccess;
function GetLevelIndent(Index: Integer): Integer;
function GetProvider: IcxExportProvider;
function GetRow(Index: Integer): TcxCustomRow;
protected
TotalWidth: Integer;
Position: Integer;
procedure AddMultiEditorRowCells(ARow: TcxCustomRow);
procedure AddMapRightSide(AMap: TcxColumnsMap; ARight, AMinCellWidth: Integer; ACalcIndent: Boolean);
procedure AlignCategories;
procedure CalculateHeader;
procedure CalculateRowsCaptions;
procedure CalculateRowsIndents;
procedure CalculateSize;
procedure CalculateValuesMap;
procedure DoCalculate; virtual;
procedure DoWrite; virtual;
function GetDisplayText(ARecordIndex: Integer; ARow: TcxCustomEditorRowProperties): string;
function GetDisplayValue(ARecordIndex: Integer; ARow: TcxCustomEditorRowProperties): Variant;
function GetMultiEditorRowProperties(ARow: TcxCustomRow): TcxMultiEditorRowProperties;
function IsIncludeRow(ARow: TcxCustomRow): Boolean; virtual;
function IsNativeFormatProperties(AProperties: TcxCustomEditProperties): Boolean;
procedure SetCellStyle(ACol, ARow, W, AStyleIndex: Integer); overload;
procedure SetCellStyle(ACol, ARow, W: Integer; const AStyle: TcxCacheCellStyle); overload;
procedure WriteColumnWidths;
procedure WriteHeaders(ARowIndex: Integer); virtual;
procedure WriteRecord(ACol, ARowIndex, ARecordIndex: Integer); virtual;
procedure WriteRowCaptions(ARowIndex: Integer; ACaptions: TcxRowCellsInfo);
procedure WriteRowHeader(ARowIndex: Integer; AIndents: TcxRowIndentsInfo; ACaptions: TcxRowCellsInfo);
procedure WriteValue(ACol, ARow, ARecordIndex: Integer;
AProperties: TcxCustomEditorRowProperties);
procedure WriteValues;
property FirstValuesColumn: Integer read FFirstValuesColumn;
property GridLineColor: TColor read FGridLineColor;
property GridLines: TcxvgGridLines read FGridLines;
property HeaderColumnsMap: TcxColumnsMap read FHeaderColumnsMap;
property IsEmpty: Boolean read FIsEmpty;
property LastBandRecords: Integer read FLastBandRecords;
property LevelIndents[Index: Integer]: Integer read GetLevelIndent;
property MaxHeaderWidth: Integer read FMaxHeaderWidth;
property MaxValueWidth: Integer read FMaxValueWidth;
property MinHeaderWidth: Integer read FMinHeaderWidth;
property MinValueWidth: Integer read FMinHeaderWidth;
property Owner: TcxVerticalGridExportHelper read FOwner;
property PaintStyle: TcxvgPaintStyle read FPaintStyle;
property Provider: IcxExportProvider read GetProvider;
property RecordCount: Integer read FRecordCount;
property RecordsPerBand: Integer read FRecordsPerBand;
property ValueColumnsMap: TcxColumnsMap read FValueColumnsMap;
property ViewInfo: TcxViewInfoAccess read FViewInfo;
public
constructor Create(AOwner: TcxVerticalGridExportHelper); virtual;
destructor Destroy; override;
property MaxLevel: Integer read FMaxLevel;
property RowCount: Integer read FRowCount;
property Rows[Index: Integer]: TcxCustomRow read GetRow;
property RowsCaptions: TcxRowsCaptions read FRowsCaptions;
property RowsIndents: TcxRowsIndents read FRowsIndents;
property Size: TSize read FSize;
property VerticalGrid: TcxVerticalGridAccess read FVerticalGrid;
end;
TcxVerticalGridMapsInfoClass = class of TcxVerticalGridMapsInfo;
{ TcxVerticalGridExportHelper }
TcxVerticalGridExportHelper = class
private
FProvider: IcxExportProvider;
FRecordsPerBand: Integer;
FExpand: Boolean;
FIsNativeFormat: Boolean;
FVerticalGrid: TcxVerticalGridAccess;
protected
MapsInfo: TcxVerticalGridMapsInfo;
procedure DoCalculateTableMap; virtual;
procedure DoWriteCells; virtual;
function GetMapsInfoClass: TcxVerticalGridMapsInfoClass; virtual;
public
constructor Create(AVerticalGrid: TcxCustomVerticalGrid;
AExportType: Integer; const AFileName: string); virtual;
destructor Destroy; override;
property RecordsPerBand: Integer read FRecordsPerBand write FRecordsPerBand;
property Expand: Boolean read FExpand write FExpand;
property IsNativeFormat: Boolean read FIsNativeFormat;
property Provider: IcxExportProvider read FProvider;
property VerticalGrid: TcxVerticalGridAccess read FVerticalGrid;
end;
const
cxInvalidIndex = -1;
cxIndentFontName = 'Tahoma';
cxCellBorders: array[Boolean] of TcxBorders = ([], cxBordersAll);
cxIndentStyle: TcxCacheCellStyle =
( AlignText: catCenter;
FontStyle: [];
FontColor: 0;
FontSize: 12;
FontCharset: 0;
BrushStyle: cbsSolid);
// todo: need move to cxExport for Delphi 4
AlignToCxAlign: array[TAlignment] of TcxAlignText =
(catLeft, catRight, catCenter);
cxUsedBorder: TcxCellBorders = (IsDefault: False; Width: 1);
cxEmptyBorder: TcxCellBorders = (IsDefault: True; Width: 0);
function cxSetBorder(var ABorder: TcxCellBorders; NeedSet: Boolean; Color: Integer): Boolean;
begin
Result := NeedSet;
if NeedSet then
begin
ABorder := cxUsedBorder;
ABorder.Color := Color;
end
else
ABorder := cxEmptyBorder;
end;
procedure cxCheckBorders(var AStyle: TcxCacheCellStyle;
const ABorders: TcxBorders; AColor: TColor; AGridLines: TcxvgGridLines);
begin
cxSetBorder(AStyle.Borders[0],
(bLeft in ABorders) and (AGridLines in [vglVertical, vglBoth]), AColor);
cxSetBorder(AStyle.Borders[1],
(bTop in ABorders) and (AGridLines in [vglHorizontal, vglBoth]), AColor);
cxSetBorder(AStyle.Borders[2],
(bRight in ABorders) and (AGridLines in [vglVertical, vglBoth]), AColor);
cxSetBorder(AStyle.Borders[3],
(bBottom in ABorders) and (AGridLines in [vglHorizontal, vglBoth]), AColor);
end;
procedure cxViewParamsToCacheStyle(
AViewParams: TcxViewParams; var ACacheStyle: TcxCacheCellStyle);
begin
ACacheStyle := DefaultCellStyle;
with ACacheStyle do
begin
StrPCopy(FontName, AViewParams.Font.Name);
FontStyle := TcxFontStyles(AViewParams.Font.Style);
FontColor := ColorToRgb(AViewParams.TextColor);
FontSize := AViewParams.Font.Size;
FontCharset := AViewParams.Font.Charset;
BrushStyle := cbsSolid;
BrushBkColor := ColorToRgb(AViewParams.Color);
BrushFgColor := BrushBkColor;
end;
end;
function GetHeaderViewParams(ARow: TcxCustomRow): TcxViewParams;
begin
with TcxRowHeaderAccess(ARow.ViewInfo.HeaderInfo) do
begin
CalcViewParams(False);
Result := IndentViewParams;
end;
end;
{ TcxRowIndentsInfo }
constructor TcxRowIndentsInfo.Create(ARow: TcxCustomRow);
begin
FRow := ARow;
FList := TList.Create;
end;
destructor TcxRowIndentsInfo.Destroy;
var
I: Integer;
begin
FProvider := nil;
for I := 0 to FList.Count - 1 do
Dispose(PcxRowIndentData(FList[I]));
FList.Free;
inherited Destroy;
end;
procedure TcxRowIndentsInfo.AddFirstIndent;
var
AEnd: Integer;
Info: PcxRowIndentData;
AStyle: TcxCacheCellStyle;
ABorders: TcxBorders;
begin
New(Info);
FIsCategory := FRow is TcxCategoryRow;
Info.IsCategory := IsCategory;
HeaderColumnsMap.GetColumnInfoFromLevel(FRow.Level, Info.Column, AEnd);
Info.Width := AEnd - Info.Column;
cxViewParamsToCacheStyle(GetHeaderViewParams(FRow), AStyle);
AStyle.AlignText := catCenter;
ABorders := [bTop, bBottom];
if FRow.IsRootLevel then Include(ABorders, bLeft);
if (PaintStyle = psDotNet) and IsCategory then
begin
Include(ABorders, bLeft);
if FRow.HasVisibleChildren then
Exclude(ABorders, bBottom);
end;
cxCheckBorders(AStyle, ABorders, GridLineColor, GridLines);
Info.StyleIndex := Provider.RegisterStyle(AStyle);
FList.Add(Info);
end;
procedure TcxRowIndentsInfo.AddParentIndents;
var
AEnd: Integer;
Info: PcxRowIndentData;
ABorders: TcxBorders;
ANeedBottom, ALastRow: Boolean;
AParent: TcxCustomRow;
AStyle: TcxCacheCellStyle;
begin
if FRow.IsRootLevel then Exit;
AParent := Row;
ALastRow := Row.VerticalGrid.LastVisibleRow = Row;
ANeedBottom := True;
repeat
AParent := AParent.Parent;
New(Info);
Info.IsCategory := AParent is TcxCategoryRow;
HeaderColumnsMap.GetColumnInfoFromLevel(AParent.Level, Info.Column, AEnd);
Info.Width := AEnd - Info.Column;
cxViewParamsToCacheStyle(GetHeaderViewParams(AParent), AStyle);
if PaintStyle = psDelphi then
begin
ABorders := [bTop, bBottom];
if AParent.IsRootLevel then Include(ABorders, bLeft);
end
else
begin
if Info.IsCategory then
begin
ANeedBottom := False;
ABorders := [bLeft, bRight];
if AParent.GetLastVisibleChild = FRow then
Include(ABorders, bBottom);
end
else
if (not IsCategory and ANeedBottom) or ALastRow then
ABorders := [bBottom]
else
ABorders := [];
end;
cxCheckBorders(AStyle, ABorders, GridLineColor, GridLines);
Info.StyleIndex := Provider.RegisterStyle(AStyle);
FList.Add(Info);
until AParent.IsRootLevel;
end;
procedure TcxRowIndentsInfo.Calculate(AHeaderColumnsMap: TcxColumnsMap;
AProvider: IcxExportProvider);
begin
FHeaderColumnsMap := AHeaderColumnsMap;
FHeaderInfo := TcxRowHeaderAccess(FRow.ViewInfo.HeaderInfo);
with FRow.VerticalGrid.OptionsView do
begin
FGridLines := GridLines;
FPaintStyle := PaintStyle;
FGridLineColor := GridLineColor;
end;
FProvider := AProvider;
AddFirstIndent;
AddParentIndents;
end;
function TcxRowIndentsInfo.GetCount: Integer;
begin
Result := FList.Count;
end;
function TcxRowIndentsInfo.GetIndent(Index: Integer): TcxRowIndentData;
begin
Result := PcxRowIndentData(FList[Index])^;
end;
{ TcxRowsIndents }
procedure TcxRowsIndents.Clear;
var
I: Integer;
begin
for I := 0 to Count - 1 do
TObject(Items[I]).Free;
inherited Clear;
end;
function TcxRowsIndents.GetIndent(Index: Integer): TcxRowIndentsInfo;
begin
Result := List^[Index];
end;
{ TcxRowCellsInfo }
function TcxRowCellsInfo.AddCaption(AColumn, AWidth,
AStyleIndex: Integer; const ACaption: string): Integer;
var
C: PRowCaptionCellInfo;
begin
New(C);
with C^ do
begin
Caption := ACaption;
Column := AColumn;
StyleIndex := AStyleIndex;
Width := AWidth;
end;
Result := Add(C);
end;
procedure TcxRowCellsInfo.Clear;
var
I: Integer;
begin
for I := 0 to Count - 1 do
Dispose(PRowCaptionCellInfo(inherited Items[I]));
inherited Clear;
end;
function TcxRowCellsInfo.GetItem(Index: Integer): TRowCaptionCellInfo;
begin
Result := TRowCaptionCellInfo(inherited Items[Index]^);
end;
{ TcxRowsCaptions }
function TcxRowsCaptions.AddCaption: TcxRowCellsInfo;
begin
Result := TcxRowCellsInfo.Create;
Add(Result);
end;
procedure TcxRowsCaptions.Clear;
var
I: Integer;
begin
for I := 0 to Count - 1 do
TObject(Items[I]).Free;
inherited Clear;
end;
function TcxRowsCaptions.GetCaption(Index: Integer): TcxRowCellsInfo;
begin
Result := List^[Index];
end;
{ TcxColumnsMap }
constructor TcxColumnsMap.Create;
begin
FElements := TList.Create;
NeedWidth := 0;
end;
destructor TcxColumnsMap.Destroy;
var
I: Integer;
begin
for I := 0 to FElements.Count - 1 do
Dispose(PElementInfo(FElements.List^[I]));
FElements.Free;
FColumnWidths := nil;
inherited Destroy;
end;
procedure TcxColumnsMap.AddRowCell(APos: Integer; ARow: TcxCustomRow;
ACellIndex, AWidth: Integer);
var
E: PElementInfo;
begin
New(E);
E.Pos := APos;
E.Width := AWidth;
E.IsLevel := False;
E.Row := ARow;
E.CellIndex := ACellIndex;
FElements.Add(E);
if AWidth > 0 then
begin
New(E);
E.Pos := APos + AWidth;
E.Width := 0;
E.IsLevel := False;
E.Row := ARow;
E.CellIndex := ACellIndex;
FElements.Add(E);
end;
end;
procedure TcxColumnsMap.AddLevel(ALevel, APos, AWidth: Integer);
var
E: PElementInfo;
begin
New(E);
E.Pos := APos;
E.Width := AWidth;
E.IsLevel := True;
E.Level := ALevel;
FElements.Add(E);
if AWidth > 0 then
begin
New(E);
E.Pos := APos + AWidth;
E.Width := 0;
E.IsLevel := True;
E.Level := ALevel;
FElements.Add(E);
end;
end;
function ComparePos(Item1, Item2: Pointer): Integer;
begin
Result := PElementInfo(Item1).Pos - PElementInfo(Item2).Pos;
end;
procedure TcxColumnsMap.Build;
var
I, AColumn, APos: Integer;
begin
FElements.Sort(ComparePos);
AColumn := 0;
APos := 0;
for I := 0 to FElements.Count - 1 do
with PElementInfo(FElements.List^[I])^ do
begin
if Pos > APos then
begin
SetLength(FColumnWidths, Succ(AColumn));
FColumnWidths[AColumn] := Pos - APos;
APos := Pos;
Inc(AColumn);
end;
ColumnStart := AColumn;
end;
for I := 0 to FElements.Count - 1 do
with PElementInfo(FElements.List^[I])^ do
if Width > 0 then ColumnEnd := FindColumnForPos(Pos + Width);
MaxColumnIndex := AColumn - 1;
end;
procedure TcxColumnsMap.CheckNeedWidth(APos: Integer);
begin
NeedWidth := Max(NeedWidth, APos);
end;
function TcxColumnsMap.FindColumnForPos(APos: Integer): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to FElements.Count - 1 do
with PElementInfo(FElements.List^[I])^ do
if APos = Pos then
begin
Result := ColumnStart;
break;
end;
end;
procedure TcxColumnsMap.GetColumnInfoFromRowCell(ARow: TcxCustomRow;
ACellIndex: Integer; var AStart, AEnd: Integer);
var
I: Integer;
begin
for I := 0 to FElements.Count - 1 do
with PElementInfo(FElements.List^[I])^ do
if not IsLevel and (Row = ARow) and (CellIndex = ACellIndex) then
begin
AStart := ColumnStart;
AEnd := ColumnEnd;
break;
end;
end;
procedure TcxColumnsMap.GetColumnInfoFromLevel(ALevel: Integer;
var AStart, AEnd: Integer);
var
I: Integer;
begin
for I := 0 to FElements.Count - 1 do
with PElementInfo(FElements.List^[I])^ do
if IsLevel and (Level = ALevel) then
begin
AStart := ColumnStart;
AEnd := ColumnEnd;
break;
end;
end;
function TcxColumnsMap.GetColumnWidth(AIndex: Integer): Integer;
begin
Result := FColumnWidths[AIndex];
end;
{ TcxVerticalGridMapsInfo }
constructor TcxVerticalGridMapsInfo.Create(
AOwner: TcxVerticalGridExportHelper);
begin
FOwner := AOwner;
FVerticalGrid := FOwner.VerticalGrid;
FViewInfo := TcxViewInfoAccess(FVerticalGrid.ViewInfo);
FRows := TList.Create;
FRowsCaptions := TcxRowsCaptions.Create;
FRowsIndents := TcxRowsIndents.Create;
FHeaderColumnsMap := TcxColumnsMap.Create;
FValueColumnsMap := TcxColumnsMap.Create;
with FVerticalGrid.OptionsView do
begin
FGridLineColor := GridLineColor;
FGridLines := GridLines;
FPaintStyle := PaintStyle;
end;
end;
destructor TcxVerticalGridMapsInfo.Destroy;
begin
FLevelIndents := nil;
FRows.Free;
FHeaderColumnsMap.Free;
FValueColumnsMap.Free;
FRowsCaptions.Free;
FRowsIndents.Free;
inherited Destroy;
end;
procedure TcxVerticalGridMapsInfo.AddMultiEditorRowCells(ARow: TcxCustomRow);
var
I, APosHeaderCell, AWidthHeaderCell, APosValueCell, AWidthValueCell: Integer;
begin
with GetMultiEditorRowProperties(ARow) do
begin
if Editors.Count < 2 then Exit;
APosHeaderCell := Succ(ARow.Level) * ViewInfo.RowIndentWidth;
APosValueCell := 0;
for I := 0 to Editors.Count - 1 do
begin
AWidthHeaderCell := Max(Editors[I].Width, FMinHeaderWidth);
AWidthValueCell := Max(Editors[I].Width, FMinValueWidth);
HeaderColumnsMap.CheckNeedWidth(APosHeaderCell + AWidthHeaderCell);
ValueColumnsMap.CheckNeedWidth(APosValueCell + AWidthValueCell);
if I = Editors.Count - 1 then break;
HeaderColumnsMap.AddRowCell(APosHeaderCell, ARow, I, AWidthHeaderCell);
Inc(APosHeaderCell, AWidthHeaderCell);
ValueColumnsMap.AddRowCell(APosValueCell, ARow, I, AWidthValueCell);
Inc(APosValueCell, AWidthValueCell);
end;
end;
end;
procedure TcxVerticalGridMapsInfo.AddMapRightSide(AMap: TcxColumnsMap;
ARight, AMinCellWidth: Integer; ACalcIndent: Boolean);
var
I, J, AWidth, APos: Integer;
ARow: TcxCustomRow;
begin
for I := 0 to RowCount - 1 do
begin
ARow := Rows[I];
APos := cxSetValue(ACalcIndent, (ARow.Level + 1) * ViewInfo.RowIndentWidth, 0);
if ARow is TcxCustomEditorRow then
AMap.AddRowCell(APos, ARow, 0, ARight - APos)
else
if ARow is TcxCustomMultiEditorRow then
with GetMultiEditorRowProperties(ARow) do
begin
if Editors.Count = 0 then continue;
for J := 0 to Editors.Count - 1 do
begin
AWidth := Max(Editors[J].Width, AMinCellWidth);
if J = Editors.Count - 1 then
AMap.AddRowCell(APos, ARow, J, ARight - APos);
Inc(APos, AWidth);
end;
end;
end;
end;
procedure TcxVerticalGridMapsInfo.AlignCategories;
var
I: Integer;
AProperties: TcxCaptionRowProperties;
ARow: TcxCustomRow;
AStart, AEnd: Integer;
AStyle: TcxCacheCellStyle;
AViewParams: TcxViewParams;
begin
for I := 0 to RowCount - 1 do
begin
ARow := Rows[I];
if ARow is TcxCategoryRow then
begin
AProperties := TcxCategoryRow(ARow).Properties;
HeaderColumnsMap.GetColumnInfoFromLevel(ARow.Level, AStart, AEnd);
AViewParams := VerticalGrid.Styles.GetCategoryParams(ARow);
cxViewParamsToCacheStyle(AViewParams, AStyle);
AStyle.AlignText := AlignToCxAlign[AProperties.HeaderAlignmentHorz];
cxCheckBorders(AStyle, [bTop, bBottom, bRight], GridLineColor, GridLines);
RowsCaptions.Captions[I].AddCaption(AEnd, Size.cx - AEnd,
Provider.RegisterStyle(AStyle), AProperties.Caption);
end;
end;
end;
procedure TcxVerticalGridMapsInfo.CalculateHeader;
var
I, AWidth: Integer;
ARow: TcxCustomRow;
begin
FMinHeaderWidth := VerticalGrid.OptionsView.RowHeaderMinWidth;
FMaxLevel := 0;
for I := 0 to VerticalGrid.Rows.Count - 1 do
begin
ARow := VerticalGrid.Rows[I];
if IsIncludeRow(ARow) then
begin
FRows.Add(ARow);
if ARow is TcxCustomMultiEditorRow then
AddMultiEditorRowCells(ARow);
FMaxLevel := Max(FMaxLevel, ARow.Level);
end;
end;
FRowCount := FRows.Count;
AWidth := ViewInfo.RowIndentWidth;
for I := 0 to FMaxLevel do
HeaderColumnsMap.AddLevel(I, I * AWidth, AWidth);
FMaxHeaderWidth := Max(HeaderColumnsMap.NeedWidth,
VerticalGrid.OptionsView.RowHeaderWidth);
HeaderColumnsMap.AddLevel(-1, 0, MaxHeaderWidth);
AddMapRightSide(HeaderColumnsMap, MaxHeaderWidth, MinHeaderWidth, True);
HeaderColumnsMap.Build;
CalculateRowsIndents;
CalculateRowsCaptions;
end;
procedure TcxVerticalGridMapsInfo.CalculateRowsCaptions;
var
I, J: Integer;
AViewParams: TcxViewParams;
ARow: TcxCustomRow;
ACaptions: TcxRowCellsInfo;
procedure AddCaption(AProperties: TcxCaptionRowProperties; ACellIndex: Integer);
var
AStart, AEnd: Integer;
AStyle: TcxCacheCellStyle;
begin
HeaderColumnsMap.GetColumnInfoFromRowCell(ARow, ACellIndex, AStart, AEnd);
cxViewParamsToCacheStyle(AViewParams, AStyle);
AStyle.AlignText := AlignToCxAlign[AProperties.HeaderAlignmentHorz];
cxCheckBorders(AStyle, [bTop, bBottom, bRight], GridLineColor, GridLines);
ACaptions.AddCaption(AStart, AEnd - AStart, Provider.RegisterStyle(AStyle), AProperties.Caption);
end;
begin
for I := 0 to RowCount - 1 do
begin
ARow := Rows[I];
ACaptions := RowsCaptions.AddCaption;
AViewParams := VerticalGrid.Styles.GetHeaderParams(ARow);
if ARow is TcxCustomEditorRow then
AddCaption(TcxCustomEditorRowAccess(ARow).Properties, 0)
else
if ARow is TcxCustomMultiEditorRow then
with GetMultiEditorRowProperties(ARow) do
for J := 0 to Editors.Count - 1 do
AddCaption(Editors[J], J);
end;
end;
procedure TcxVerticalGridMapsInfo.CalculateRowsIndents;
var
I: Integer;
AIndents: TcxRowIndentsInfo;
begin
for I := 0 to RowCount - 1 do
begin
AIndents := TcxRowIndentsInfo.Create(Rows[I]);
AIndents.Calculate(HeaderColumnsMap, Provider);
RowsIndents.Add(AIndents);
end;
end;
procedure TcxVerticalGridMapsInfo.CalculateSize;
begin
CalculateHeader;
CalculateValuesMap;
FRecordCount := VerticalGrid.RecordCount;
FIsEmpty := FRecordCount = 0;
if FIsEmpty then Inc(FRecordCount);
FRecordsPerBand := Max(Owner.RecordsPerBand, 1);
FBandCount := FRecordCount div FRecordsPerBand;
FLastBandRecords := FRecordCount - FBandCount * FRecordsPerBand;
if FLastBandRecords > 0 then
Inc(FBandCount)
else
FLastBandRecords := FRecordsPerBand;
FSize := cxSize(FirstValuesColumn + (ValueColumnsMap.MaxColumnIndex + 1) *
cxSetValue(FBandCount = 1, FLastBandRecords, RecordsPerBand),
(RowCount + 1) * FBandCount - 1);
end;
procedure TcxVerticalGridMapsInfo.CalculateValuesMap;
begin
FFirstValuesColumn := HeaderColumnsMap.MaxColumnIndex + 1;
FMinValueWidth := VerticalGrid.OptionsView.ValueMinWidth;
FMaxValueWidth := Max(ValueColumnsMap.NeedWidth,
VerticalGrid.OptionsView.ValueWidth);
ValueColumnsMap.AddLevel(-1, 0, MaxValueWidth);
AddMapRightSide(ValueColumnsMap, MaxValueWidth, MinValueWidth, False);
ValueColumnsMap.Build;
end;
procedure TcxVerticalGridMapsInfo.DoCalculate;
begin
CalculateSize;
AlignCategories;
end;
procedure TcxVerticalGridMapsInfo.DoWrite;
begin
Provider.SetRange(Size.cx, Size.cy, False);
WriteColumnWidths;
WriteValues;
end;
function TcxVerticalGridMapsInfo.GetDisplayText(ARecordIndex: Integer;
ARow: TcxCustomEditorRowProperties): string;
begin
with ARow.DisplayEditProperties[ARecordIndex] do
begin
if GetEditValueSource(False) = evsValue then
Result := GetDisplayText(ARow.Values[ARecordIndex], True)
else
Result := ARow.DisplayTexts[ARecordIndex];
end;
end;
function TcxVerticalGridMapsInfo.GetDisplayValue(ARecordIndex: Integer;
ARow: TcxCustomEditorRowProperties): Variant;
var
AProperties: TcxCustomEditProperties;
begin
AProperties := ARow.DisplayEditProperties[ARecordIndex];
if IsNativeFormatProperties(AProperties) then
Result := ARow.Values[ARecordIndex]
else
Result := AProperties.GetDisplayText(ARow.Values[ARecordIndex], True);
end;
function TcxVerticalGridMapsInfo.GetMultiEditorRowProperties(
ARow: TcxCustomRow): TcxMultiEditorRowProperties;
begin
Result := TcxMultiEditorRowProperties(
TcxCustomMultiEditorRowAccess(ARow).FProperties);
end;
function TcxVerticalGridMapsInfo.IsIncludeRow(ARow: TcxCustomRow): Boolean;
begin
Result := VerticalGrid.IsRowVisible(ARow);
end;
function TcxVerticalGridMapsInfo.IsNativeFormatProperties(
AProperties: TcxCustomEditProperties): Boolean;
begin
Result := (AProperties is TcxDateEditProperties) or (AProperties is TcxCurrencyEditProperties) or
(AProperties is TcxSpinEditProperties) or (AProperties is TcxCalcEditProperties) or
(AProperties is TcxTimeEditProperties);
end;
procedure TcxVerticalGridMapsInfo.SetCellStyle(ACol, ARow, W, AStyleIndex: Integer);
begin
with Provider do
SetCellStyleEx(ACol, ARow, 1, W, AStyleIndex);
end;
procedure TcxVerticalGridMapsInfo.SetCellStyle(ACol, ARow, W: Integer;
const AStyle: TcxCacheCellStyle);
begin
with Provider do
SetCellStyleEx(ACol, ARow, 1, W, RegisterStyle(AStyle));
end;
procedure TcxVerticalGridMapsInfo.WriteColumnWidths;
var
I, J, AWidth, ACount: Integer;
begin
for I := 0 to HeaderColumnsMap.MaxColumnIndex do
begin
AWidth := HeaderColumnsMap.GetColumnWidth(I);
Provider.SetColumnWidth(I, AWidth);
end;
ACount := cxSetValue(RecordCount > FRecordsPerBand, FRecordsPerBand,
FLastBandRecords);
for J := 0 to ACount - 1 do
for I := 0 to ValueColumnsMap.MaxColumnIndex do
begin
AWidth := ValueColumnsMap.GetColumnWidth(I);
Provider.SetColumnWidth(FirstValuesColumn +
J * (ValueColumnsMap.MaxColumnIndex + 1) + I, AWidth);
end;
end;
procedure TcxVerticalGridMapsInfo.WriteHeaders(ARowIndex: Integer);
var
I: Integer;
begin
for I := 0 to RowCount - 1 do
WriteRowHeader(ARowIndex + I, RowsIndents[I], RowsCaptions[I]);
end;
procedure TcxVerticalGridMapsInfo.WriteRecord(
ACol, ARowIndex, ARecordIndex: Integer);
var
I, J: Integer;
ARow: TcxCustomRow;
procedure WriteCell(ARowIndex: Integer;
AProperties: TcxCustomEditorRowProperties; ACellIndex: Integer);
var
AStart, AEnd: Integer;
AViewParams: TcxViewParams;
AStyle: TcxCacheCellStyle;
begin
ValueColumnsMap.GetColumnInfoFromRowCell(ARow, ACellIndex, AStart, AEnd);
AViewParams := VerticalGrid.Styles.GetContentParams(AProperties, False, ARecordIndex);
cxViewParamsToCacheStyle(AViewParams, AStyle);
AStyle.AlignText := AlignToCxAlign[TcxPropertiesAccess(AProperties.DisplayEditProperties[ARecordIndex]).Alignment.Horz];
cxCheckBorders(AStyle, cxBordersAll, GridLineColor, GridLines);
SetCellStyle(ACol + AStart, ARowIndex, AEnd - AStart, AStyle);
WriteValue(ACol + AStart, ARowIndex, ARecordIndex, AProperties);
end;
begin
for I := 0 to RowCount - 1 do
begin
ARow := Rows[I];
if ARow is TcxCustomEditorRow then
WriteCell(ARowIndex + I, TcxCustomEditorRowAccess(ARow).Properties, 0)
else
if ARow is TcxCustomMultiEditorRow then
with GetMultiEditorRowProperties(ARow) do
for J := 0 to Editors.Count - 1 do
WriteCell(ARowIndex + I, Editors[J], J)
end;
end;
procedure TcxVerticalGridMapsInfo.WriteRowCaptions(ARowIndex: Integer;
ACaptions: TcxRowCellsInfo);
var
I: Integer;
begin
with Provider do
for I := 0 to ACaptions.Count - 1 do
with ACaptions[I] do
begin
SetCellStyleEx(Column, ARowIndex, 1, Width, StyleIndex);
SetCellDataString(Column, ARowIndex, Caption);
end;
end;
procedure TcxVerticalGridMapsInfo.WriteRowHeader(ARowIndex: Integer;
AIndents: TcxRowIndentsInfo; ACaptions: TcxRowCellsInfo);
const
PlusMinus: array[Boolean] of Char = ('+', '-');
var
I: Integer;
begin
for I := 0 to AIndents.Count - 1 do
with AIndents.Indents[I] do
begin
if (I = 0) and AIndents.Row.HasVisibleChildren then
Provider.SetCellDataString(Column, ARowIndex, PlusMinus[AIndents.Row.Expanded]);
SetCellStyle(Column, ARowIndex, Width, StyleIndex);
end;
WriteRowCaptions(ARowIndex, ACaptions);
end;
procedure TcxVerticalGridMapsInfo.WriteValue(ACol, ARow, ARecordIndex: Integer;
AProperties: TcxCustomEditorRowProperties);
begin
if IsEmpty then
Provider.SetCellDataString(ACol, ARow, '')
else
begin
if Owner.IsNativeFormat then
Provider.SetCellValue(ACol, ARow, GetDisplayValue(ARecordIndex, AProperties))
else
Provider.SetCellDataString(ACol, ARow, GetDisplayText(ARecordIndex, AProperties));
end;
end;
procedure TcxVerticalGridMapsInfo.WriteValues;
var
I, J, ARow, ACol, ARecord: Integer;
begin
ARow := 0;
ARecord := 0;
for I := 0 to FBandCount - 1 do
begin
ACol := HeaderColumnsMap.MaxColumnIndex + 1;
WriteHeaders(ARow);
for J := 0 to FRecordsPerBand - 1 do
begin
WriteRecord(ACol + J * (ValueColumnsMap.MaxColumnIndex + 1), ARow, ARecord);
Inc(ARecord);
if ARecord = RecordCount then Exit;
end;
Inc(ARow, RowCount + 1);
Provider.SetRowHeight(ARow - 1, 8);
end;
end;
function TcxVerticalGridMapsInfo.GetLevelIndent(Index: Integer): Integer;
begin
Result := FLevelIndents[Index];
end;
function TcxVerticalGridMapsInfo.GetProvider: IcxExportProvider;
begin
Result := FOwner.Provider;
end;
function TcxVerticalGridMapsInfo.GetRow(Index: Integer): TcxCustomRow;
begin
Result := TcxCustomRow(FRows.List^[Index]);
end;
{ TcxVerticalGridExportHelper }
constructor TcxVerticalGridExportHelper.Create(
AVerticalGrid: TcxCustomVerticalGrid; AExportType: Integer;
const AFileName: string);
function DefaultStyle: TcxCacheCellStyle;
var
I: Integer;
begin
cxViewParamsToCacheStyle(VerticalGrid.Styles.GetBackgroundParams, Result);
for I := 0 to 3 do
begin
Result.Borders[I].IsDefault := True;
Result.Borders[I].Width := 0;
end;
end;
begin
FVerticalGrid := TcxVerticalGridAccess(AVerticalGrid);
TcxExport.Provider(AExportType, AFileName).GetInterface(IcxExportProvider, FProvider);
FProvider.SetDefaultStyle(DefaultStyle);
MapsInfo := GetMapsInfoClass.Create(Self);
end;
destructor TcxVerticalGridExportHelper.Destroy;
begin
try
MapsInfo.Free;
FProvider := nil;
finally
inherited Destroy;
end;
end;
procedure TcxVerticalGridExportHelper.DoCalculateTableMap;
begin
MapsInfo.DoCalculate;
end;
procedure TcxVerticalGridExportHelper.DoWriteCells;
begin
MapsInfo.DoWrite;
Provider.Commit;
end;
function TcxVerticalGridExportHelper.GetMapsInfoClass: TcxVerticalGridMapsInfoClass;
begin
Result := TcxVerticalGridMapsInfo;
end;
// external procedures definition
{$IFNDEF DELPHI6}
type
IInterface = IUnknown;
{$ENDIF}
function cxSupports(const Instance: IInterface; const IID: TGUID; out Intf): Boolean;
begin
Result := (Instance <> nil) and (Instance.QueryInterface(IID, Intf) = 0);
end;
procedure cxExportVGToFile(AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExportType: Integer;
AExpand, AUseNativeFormat: Boolean; const ASeparators: array of string;
ARecordPerBand: Integer; const AFileExt: string);
var
I: Integer;
AIntf: IcxExportWithSeparators;
begin
if AFileExt <> '' then
AFileName := ChangeFileExt(AFileName, '.' + AFileExt);
if not AVerticalGrid.Visible then
cxVerticalGridError(cxSvgExportNotVisibleControl);
with TcxVerticalGridExportHelper.Create(AVerticalGrid, AExportType, AFileName) do
try
FExpand := AExpand;
if AExpand then AVerticalGrid.FullExpand;
AVerticalGrid.FocusedRow := nil;
FRecordsPerBand := Max(ARecordPerBand, 1);
FIsNativeFormat := AUseNativeFormat;
if cxSupports(Provider, IcxExportWithSeparators, AIntf) and (Length(ASeparators) > 0) then
begin
for I := Low(ASeparators) to High(ASeparators) do
AIntf.AddSeparator(ASeparators[I]);
end;
DoCalculateTableMap;
DoWriteCells;
finally
Free;
end;
end;
procedure cxExportVGToHTML(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'html');
begin
cxExportVGToFile(AFileName, AVerticalGrid, cxExportToHtml, AExpand, False, [],
ARecordPerBand, AFileExt);
end;
procedure cxExportVGToXML(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'xml');
begin
cxExportVGToFile(AFileName, AVerticalGrid, cxExportToXML, AExpand, False, [],
ARecordPerBand, AFileExt);
end;
procedure cxExportVGToExcel(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
AUseNativeFormat: Boolean = True;
ARecordPerBand: Integer = 8; const AFileExt: string = 'xls');
begin
cxExportVGToFile(AFileName, AVerticalGrid, cxExportToExcel, AExpand,
AUseNativeFormat, [], ARecordPerBand, AFileExt);
end;
procedure cxExportVGToText(const AFileName: string;
AVerticalGrid: TcxCustomVerticalGrid; AExpand: Boolean = True;
const ASeparator: string = ''; const ABeginString: string = '';
const AEndString: string = ''; ARecordPerBand: Integer = 8;
const AFileExt: string = 'txt');
begin
cxExportVGToFile(AFileName, AVerticalGrid, cxExportToText, AExpand, False,
[ASeparator, ABeginString, AEndString], ARecordPerBand, AFileExt);
end;
initialization
Move(cxIndentFontName[1], cxIndentStyle.FontName[0], Length(cxIndentFontName));
cxExportInit(TcxGetResourceStringProc(@cxGetResourceString), @ColorToRGB, True );
end.