unit ReportClass;
interface
uses CommonForm, SysUtils, Classes, Forms, Dialogs, DB, Controls, Grids, ComCtrls,
FR_DBSet, FR_Class, Printers, FR_Utils, FR_Pars, DBGrids, IniFiles, Variants,
TypInfo;
type
TReport = class
private
FDatasetArray: array of TDataset;
FRDataset: array of TfrDBDataset;
FrmCommon: TfrmCommon; //设置窗体
FReport: TfrReport; //报表对象
FPage: TfrPage; //页面对象
FVariants: TfrVariables; //报表的数据字典变量
FVariantList: TStrings; //变量列表
FGridFields: TStrings; //表格的字段=标签
FGridWidths: TStrings; //表格的字段=宽度
FGridRowHeight: integer; //表格行高
FGrid: TCustomGrid; //表格名称
FTitleMemo: TfrMemoView; //标题头文本框
FTitleDate: TfrmemoView; //标题日期文本框
FPrintReportDate: Boolean; //是否打印页头日期
FOrientation: Boolean; //报表打印方向
FPrintPageNumber: Boolean; //是否打印页码
FHeaderFields: TStrings; //页头字段列表
FDetailFields: TStrings; //明细字段列表
FFooterFields: Tstrings; //页脚字段列表
INIFile: TINIFile;
FFileName: string; //报表的文件名
FDetailSourceType: string; //报表数据源类型('TDBGrid'或'TDataset')
FReportName: string; //在INI文件中小节的报表的名称
procedure ShowData;
function GetVariant: TStrings;
procedure SetVariants(const Value: TStrings);
protected
function GetReportTitle: string;
procedure SetReportTitle(value: string);
function GetOrientation: Boolean;
procedure SetOrientation(value: Boolean);
function GetPrintReportDate: Boolean;
procedure SetPrintReportDate(value: Boolean);
function GetPrintPageNumber: Boolean;
procedure SetPrintPageNumber(value: Boolean);
function GetHeaderFields: TStrings;
procedure SetHeaderFields(const Value: TStrings);
function GetFooterFields: TStrings;
procedure SetFooterFields(const Value: TStrings);
function GetDetailFields: TStrings;
procedure SetDetailFields(const Value: TStrings);
function GetFileName: string;
procedure SetFileName(const Value: string);
function GetGrid: TCustomGrid;
procedure SetGrid(const Grid: TCustomGrid);
public
constructor Create;
destructor Destroy; override;
procedure Preview; overload;
procedure Preview(FileName: string); overload;
procedure Design; overload;
procedure Design(FileName: string); overload;
procedure SetMemoView(MemoView: TfrMemoView; //设置文本框属性
Alignment: integer; //Alignment:文本对齐方式,frtaCenter表示居中对齐
FrameTyp: word); //FrameTyp:边框样式,0:无边框;15:有边框
function FindBandView(BandType: TfrBandType): TfrBandView; //根据BandView类型返回TfrBandview
function FindMemoView(Text: string; var CompNo: integer): TfrMemoView; //根据MemoView的文本返回TfrMemoView和序号
function ShowFieldListForm: Boolean;
procedure SaveFieldList(ReportName: string); //存储字段列表到报表配置文件中
procedure LoadFieldList(ReportName: string); //从配置文件中调用字段列表
procedure SetDataset(Datasets: array of TDataset);
published
property Title: string read GetReportTitle write SetReportTitle; //报表标题
property PrintPageNumber: Boolean read GetPrintPageNumber write SetPrintpageNumber default false; //是否打印报表页码
property PrintReportDate: Boolean read GetPrintReportDate write SetPrintReportDate default true; //是否打印报表日期
property Orientation: Boolean read GetOrientation write SetOrientation default true; //页面默认为纵向
property HeaderFields: TStrings read GetHeaderFields write SetHeaderFields; //页头上要打印的字段列表
property DetailFields: TStrings read GetDetailFields write SetDetailFields; //明细字体列表
property FooterFields: TStrings read GetFooterFields write SetFooterFields; //页脚上要打印的字段列表
property FileName: string read GetFileName write SetFileName;
property DetailSourceType: string read FDetailSourceType write FDetailSourceType; //明细数据源是'TDBGrid'还是'TDataset'
property Grid: TCustomGrid read GetGrid write SetGrid;
property Variants: TStrings read GetVariant write SetVariants; //报表数据字典中的变量
end;
implementation
{ TReport }
constructor TReport.Create;
var
band: TfrBandView;
AppPath: string;
begin
inherited;
FHeaderFields := TStringList.Create; //标题字段列表
FDetailFields := TStringList.Create; //明细字段列表
FFooterFields := TStringList.Create; //页脚字段列表
FGridFields := TStringList.Create; //表格字段列表
FGridWidths := TStringList.Create; //表格字段宽度列表
FPrintReportDate := true; //默认打印报表日期
FOrientation := true;
FReport := TfrReport.Create(nil); //建立报表
//建立页面
FReport.Pages.Clear;
FReport.Pages.Add;
FPage := FReport.Pages[0];
FVariants := TfrVariables.Create;
FVariantList := TStringList.Create;
Band := TfrBandView.Create; //建立标题条
Band.SetBounds(tbbLeft, tbbTop, tbbWidth, tbbHeight); //条位置
Band.BandType := btReportTitle; //条类型
FPage.Objects.Add(Band);
FTitleMemo := TfrMemoView.Create; //建立标题文本
FTitleMemo.SetBounds(tmbLeft, tmbTop, tmbWidth, tmbHeight);
FTitleMemo.BandAlign := baCenter; //文本框居中
FTitleMemo.Prop['Alignment'] := frtaCenter or frtaMiddle; //文本的对齐方式(垂直居中)
FTitleMemo.Prop['Font.Style'] := 2;
FTitleMemo.prop['Font.Name'] := mvFontName;
FTitleMemo.Prop['Font.Size'] := 14;
FPage.Objects.Add(FTitleMemo);
FPrintReportDate := true;
SetPrintReportDate(FPrintReportDate);
frmCommon := TfrmCommon.Create(nil);
AppPath := ExtractFilePath(Application.ExeName) + 'Reports/';
if not DirectoryExists(AppPath) then CreateDir(AppPath);
INIFile := TIniFile.Create(AppPath + 'Reports.ini');
end;
destructor TReport.Destroy;
begin
FreeAndNil(INIFile);
FreeAndNil(FHeaderFields);
FreeAndNil(FFooterFields);
FreeAndNil(FDetailFields);
FreeAndNil(FGridWidths);
FreeAndNil(FGridFields);
FreeAndNil(frmCommon);
FreeAndNil(FVariantList);
FreeAndNil(FVariants);
FreeAndNil(FReport);
FDatasetArray := nil;
inherited;
end;
function TReport.GetReportTitle: string;
begin
result := FTitleMemo.Memo.Text
end;
procedure TReport.SetReportTitle(value: string);
begin
FTitleMemo.Memo.Text := value;
frmCommon.ReportTitle := value;
end;
function TReport.GetOrientation: Boolean;
begin
result := FOrientation;
end;
procedure TReport.SetOrientation(value: Boolean);
begin
FOrientation := value;
if FOrientation then
Fpage.ChangePaper(Fpage.pgSize, Fpage.pgWidth, Fpage.pgHeight, Fpage.pgBin, poPortrait) //页面横向
else
Fpage.ChangePaper(Fpage.pgSize, Fpage.pgWidth, Fpage.pgHeight, Fpage.pgBin, poLandscape); //页面纵向
FTitleDate.SetBounds(FPage.Prop['Width'] - 70, tdbTop, tdbWidth, tdbHeight);
end;
procedure TReport.Preview;
begin
ShowData;
if FReport.PrepareReport then
FReport.ShowPreparedReport;
end;
procedure TReport.Preview(FileName: string);
var
s: string;
begin
s := FileName;
if s = '' then s := FFileName;
if s = '' then exit;
FReport.LoadFromFile(s);
if FReport.PrepareReport then
FReport.ShowPreparedReport;
end;
procedure TReport.Design(FileName: string);
var
s: string;
begin
s := FileName;
if s = '' then s := FFileName;
if s = '' then exit;
FReport.LoadFromFile(s);
if FReport.PrepareReport then
FReport.DesignReport;
end;
procedure TReport.Design;
begin
ShowData;
if FReport.PrepareReport then
FReport.DesignReport;
end;
function TReport.GetPrintReportDate: Boolean;
begin
result := FPrintReportDate;
end;
procedure TReport.SetPrintReportDate(value: Boolean);
var
Blank: integer;
begin
FPrintReportDate := value;
if FPrintReportDate then
begin
FTitleDate := tfrMemoView.Create;
if FOrientation then //如果是纵向打印
Blank := 1480
else
Blank := 1200;
FTitleDate.SetBounds(FPage.pgWidth - Blank, tdbTop, tdbWidth, tdbHeight);
FTitleDate.Memo.Add('[Date]');
FPage.Objects.Add(FTitleDate);
end;
end;
function TReport.GetPrintPageNumber: Boolean;
begin
result := FPrintPageNumber;
end;
procedure TReport.SetPrintPageNumber(value: Boolean);
const
PageNumber = '[PAGE#]/[TOTALPAGES]';
var
mv: TfrMemoView;
Band: TfrBandView;
CompNo: integer;
begin
FPrintPageNumber := value;
Band := FindBandView(btPageFooter);
if band = nil then //如果没有FooterBand,那么新建一个
begin
Band := TfrBandView.Create;
Band.BandType := btPageFooter;
band.SetBounds(fbbLeft, fbbTop, fbbWidth, fbbHeight);
FPage.Objects.Add(Band);
end;
if FPrintPageNumber then //如果打印页码
begin
FReport.DoublePass := true; //报表只有显示两次才能显示页码
mv := TfrMemoView.Create;
mv.Memo.Text := PageNumber;
mv.SetBounds(0, fbbTop, 100, mvHeight);
mv.BandAlign := baCenter;
mv.Prop['Alignment'] := frtaMiddle or frtaCenter;
mv.prop['Font.Name'] := mvFontName;
mv.Prop['Font.Size'] := mvFontSize;
FPage.Objects.Add(mv);
end
else //如果不打印页码,那么删除已存在的页码文本框
begin
mv := FindMemoView(PageNumber, CompNo);
if mv <> nil then
begin
FPage.Delete(CompNo);
mv.Free;
end;
end;
end;
function TReport.FindBandView(BandType: TfrBandType): TfrBandView;
var
v: TfrBandView;
i: integer;
begin
result := nil;
for i:=0 to FPage.Objects.Count-1 do //查找是否有FooterBand
begin
v := FPage.objects[i];
if (v.ClassNameIs('TfrBandView') and (TfrBandView(v).BandType = BandType)) then
begin
result := v;
exit;
end;
end;
end;
function TReport.FindMemoView(Text: string; var CompNo: integer): TfrMemoView;
var
i: integer;
v: TfrMemoView;
begin
result := nil;
for i:=0 to FPage.Objects.Count-1 do
begin
v := FPage.Objects[i];
if (v.ClassNameIs('TfrMemoView') and (TfrMemoView(v).Memo.Text = Text)) then
begin
CompNo := i;
result := v;
exit;
end;
end;
end;
procedure TReport.SetMemoView(MemoView: TfrMemoView; Alignment: integer; FrameTyp: word);
begin
if MemoView = nil then exit;
MemoView.Prop['Alignment'] := frtaMiddle or Alignment; //文本对齐方式(默认为垂直居中)
MemoView.prop['Font.Name'] := mvFontName; //字体名称
MemoView.Prop['Font.Size'] := mvFontSize; //字体尺寸
if frmCommon.MemoFrameTyp then
MemoView.FrameTyp := FrameTyp; //边框
end;
////////////////////////////////////给打印字段列表赋值/////////////////////////////
function TReport.GetHeaderFields: TStrings;
begin
result := FHeaderFields;
end;
procedure TReport.SetHeaderFields(const Value: TStrings);
begin
FHeaderFields.Assign(value);
end;
function TReport.GetFooterFields: TStrings;
begin
result := FFooterFields;
end;
procedure TReport.SetFooterFields(const Value: TStrings);
begin
FFooterFields.Assign(value);
end;
/////////////////////////////////////////////////////////////////////////////////
function TReport.ShowFieldListForm: Boolean;
begin
frmCommon.HeaderFields := HeaderFields;
frmCommon.DetailFields := DetailFields;
frmCommon.FooterFields := FooterFields;
frmCommon.ShowModal; //显示报表设置窗体
result := frmCommon.FormCloseMode;
if not frmCommon.FormCloseMode then exit; //如果窗体是Cancel方式关闭的
FTitleMemo.Memo.Text := frmCommon.ReportTitle; //返回报表标题
//获得打印字段列表
HeaderFields := frmCommon.HeaderFields;
DetailFields := frmCommon.DetailFields;
FooterFields := frmCommon.FooterFields;
if frmCommon.SavePrintFields and (FReportName <> '') then //如果保存打印字段列表
SaveFieldList(FReportName);
end;
procedure TReport.ShowData;
function AnalyseText(str: string): string;
var
n: integer;
begin
result := '';
n := AnsiPos('.', str);
if n = 0 then exit;
insert('"', str, n+1);
result := str + '"';
end;
function GetDisLabelWidth(FieldName: string): integer; //根据字段名得到字段标签的长度
var
n, i, j: integer;
s: string;
begin
result := 0;
s := Fieldname;
n := AnsiPos('.', s);
if n > 0 then //如果字段名带有表名前缀
begin
Delete(s, 1, n);
end;
if s = '' then exit;
for i:=0 to High(FDatasetArray) do //这个函数没考虑到前缀对应的问题,以后有空改吧
begin
for j:=0 to FDatasetArray[i].FieldCount-1 do
begin
if FDatasetArray[i].Fields[j].FieldName = s then
begin
result := FDatasetArray[i].Fields[j].DisplayWidth * 5; //宽度增加5倍
exit;
end;
end;
end;
end;
var
iCol, iLeft, i, w, h: integer;
mv: TfrMemoView;
Band: TfrBandView;
begin
if FHeaderFields.Count > 0 then
begin
iLeft := tmbLeft; //其它字段的位置在打印日期之下
iCol := 1; //第一行
for i:=0 to FHeaderFields.Count-1 do
begin
if (i mod 3 = 0) and (i > 0) then //一行只显示三列字段
begin
inc(iCol, 1);
iLeft := tmbLeft;
end;
mv := TfrMemoView.Create;
SetMemoView(mv, frtaLeft, 0);
mv.SetBounds(iLeft, tdbTop + (tdbHeight + 4) * iCol, 200, mvHeight); //4是上下Memo行之间的间隔
mv.Memo.Text := HeaderFields.ValueFromIndex[i] + ':['
+ FDatasetArray[0].Owner.Name + '.' + AnalyseText(HeaderFields.Names[i]) + ']';
FPage.Objects.Add(mv);
inc(iLeft, 200);
end;
end
else //否则不打印页头上的字段列表
begin
band := FindBandView(btReportTitle);
Band.SetBounds(tbbLeft, tbbTop, tbbWidth, 60); //缩小条高度
end;
///////////////////////////////// 明细 ///////////////////////////////////////////
if frmCommon.UseGridRowHeight then
h := frmCommon.GridRowHeight
else
h := frmCommon.MemoHeight; //得到文本框高度
//页头
Band := TfrBandView.Create;
Band.SetBounds(0, PageBandTop, 0, h);
Band.BandType := btPageHeader;
Band.Prop['OnFirstPage'] := true;
FPage.Objects.Add(Band);
Band := TfrBandView.Create; //主数据条
Band.SetBounds(0, PageBandTop + DataBandHeight * 2, 0, h);
Band.BandType := btMasterData;
Band.DataSet := 'frmCommon.' + frmCommon.DetailDatasetName; //明细数据条需要一个数据源
FPage.Objects.Add(Band);
w := 0;
for i:=0 to FDetailFields.Count-1 do //求出明细文本框居中时的左起点
begin
if frmCommon.UseGridWidth then //如果使用表格的字段列表的宽度
w := w + StrToInt(FGridWidths.ValueFromIndex[i])
else
w := w + GetDisLabelWidth(FDetailFields.Names[i]); //得到数据字段的显示长度
end;
iLeft := (FPage.Prop['Width'] - w) div 2;
if iLeft < 32 then iLeft := 32;
for i:=0 to FDetailFields.Count -1 do
begin
mv := TfrMemoView.Create; //标签
SetMemoView(mv, frtaCenter, 15);
if frmCommon.UseGridWidth then //如果使用表格的字段列表的宽度
w := StrToInt(FGridWidths.ValueFromIndex[i])
else
w := GetDisLabelWidth(FDetailFields.Names[i]); //得到数据字段的显示长度
mv.SetBounds(iLeft, PageBandTop, w, h);
mv.Memo.Add(DetailFields.ValueFromIndex[i]);
FPage.Objects.Add(mv);
mv := TfrMemoView.Create; //记录
mv.SetBounds(iLeft, PageBandTop + DataBandHeight * 2, w, h);
if frmCommon.MemoFrameTyp then //文本框是否有边框
SetMemoView(mv, frtaLeft, 15) //设置文本框属性
else
SetMemoView(mv, frtaLeft, 0);
mv.Memo.Text := '[' + FDatasetArray[0].Owner.Name + '.'
+ AnalyseText(DetailFields.Names[i]) + ']';
FPage.Objects.Add(mv);
inc(iLeft, w);
end;
if iLeft > FPage.Prop['width'] then //如果文本框超过了页面的长度,
begin
SetOrientation(false); //那么页面自动转为横向打印
FTitleDate.SetBounds(FPage.Prop['width'] - tdbWidth - 70, tdbTop, tdbWidth, tdbHeight);
end;
////////////////////////////////// 页脚 ////////////////////////////////////////////////
if FFooterFields.Count > 0 then
begin
Band := FindBandView(btReportSummary);
if band = nil then //如果没有FooterBand,那么新建一个
begin
Band := TfrBandView.Create;
Band.BandType := btReportSummary;
band.SetBounds(rfbLeft, rfbTop, rfbWidth, rfbHeight);
FPage.Objects.Add(Band);
end;
iLeft := tmbLeft; //其它字段的位置在打印日期之下
iCol := 0;
for i:=0 to FFooterFields.Count-1 do
begin
if (i mod 3 = 0) and (i > 0) then //一行只显示三列字段
begin
inc(iCol, 1);
iLeft := tmbLeft;
end;
mv := TfrMemoView.Create;
SetMemoView(mv, frtaLeft, 0);
mv.SetBounds(iLeft, rfbTop + (tdbHeight + 4) * iCol, 200, mvHeight);
mv.Memo.Text := FFooterFields.ValueFromIndex[i] + ':['
+ FDatasetArray[0].Owner.Name + '.' + AnalyseText(FFooterFields.Names[i]) + ']';
FPage.Objects.Add(mv);
inc(iLeft, 200);
end;
end
else //否则不打印页脚上的字段列表
begin
end;
end;
function TReport.GetFileName: string;
begin
result := FFileName;
end;
procedure TReport.SetFileName(const Value: string);
begin
FFileName := value;
FReport.LoadFromFile(FFileName);
end;
procedure TReport.SaveFieldList(ReportName: string);
var
i: integer;
s: string;
begin
if ReportName = '' then exit;
s := '';
for i:=0 to HeaderFields.Count-1 do
s := s + HeaderFields.Strings[i] + ',';
delete(s, length(s), 1); //删除最后一个','号
INIFile.WriteString(ReportName, 'Title', s);
s := '';
for i:=0 to DetailFields.Count-1 do
s := s + DetailFields.Strings[i] + ',' ;
delete(s, length(s), 1);
INIFile.WriteString(ReportName, 'Detail', s);
s := '';
for i:=0 to FooterFields.Count-1 do
s := s + FooterFields.Strings[i] + ',' ;
delete(s, length(s), 1);
INIFile.WriteString(ReportName, 'Footer', s);
end;
//从配置文件中得到要打印的字段,然后加入Listview中
procedure TReport.LoadFieldList(ReportName: string);
var
s: string;
begin
FReportName := ReportName;
HeaderFields.CommaText := INIFile.ReadString(ReportName, 'Title', '');
//注意:当调用了LoadFieldList之后,再执行SetGrid,那么DetailFields的字段列表会被FGridFields的字段列表覆盖
DetailFields.CommaText := IniFile.ReadString(ReportName, 'Detail', '');
FooterFields.CommaText := INIFile.ReadString(ReportName, 'Footer', '');
if Detailfields.Count > 0 then
begin
s := DetailFields.Names[DetailFields.Count-1]; ;//最后一个字段的前缀就是明细数据条的数据源
frmCommon.DetailDatasetName := Copy(s, 1, AnsiPos('.', s)-1);
end;
end;
function TReport.GetDetailFields: TStrings;
begin
result := FDetailFields;
end;
procedure TReport.SetDetailFields(const Value: TStrings);
begin
FDetailFields.Assign(value);
end;
procedure TReport.SetDataset(Datasets: array of TDataset);
var
i, j, iLen: integer;
Dataset: TDataset;
TvFields: TTreeView;
MainNode: TTreeNode;
b: Boolean;
begin
for i:=0 to high(Datasets) do //把数据集逐一赋给FDatasetArray
begin
b := false;
for j:=0 to high(FDatasetArray) do //先判断数组中是否已存在要加入的数据集
begin
b := false;
if FDatasetArray[j].Name = Datasets[i].Name then
begin
b := true;
break;
end;
end;
if not b then
begin
iLen := high(FDatasetArray) + 2; //得到数组的上标(动态数组作为参数,其下标总是从0开始),长度加2才是数量
SetLength(FDatasetArray, iLen);
SetLength(FRDataset, iLen);
dec(iLen);
FDatasetArray[iLen] := Datasets[i]; //数量减去1才是维数
FRDataset[iLen] := TfrDBDataset.Create(frmCommon);
FRDataset[iLen].DataSet := FDatasetArray[iLen];
frDataset[iLen].Name := FDatasetArray[iLen].Name;
end;
end;
tvFields := TTreeView.Create(nil); //因为打算用一个树形结构来表示所有字段,为便于赋值,干脆把整棵树赋值给frmCommon(有时间改为Stream比较好)
try
tvFields.Parent := frmCommon;
for i:=0 to high(FDatasetArray) do
begin
Dataset := FDatasetArray[i];
MainNode := tvFields.Items.Add(nil, Dataset.Name);
for j:=0 to Dataset.FieldCount-1 do
tvFields.Items.AddChild(MainNode, Dataset.Fields[j].FieldName
+ '[' + Dataset.Fields[j].DisplayLabel + ']');
end;
frmCommon.tvFields.Items.Assign(tvFields.Items); //把树赋给frmCommon
finally
tvFields.Free;
end;
end;
function TReport.GetGrid: TCustomGrid;
begin
result := FGrid;
end;
procedure TReport.SetGrid(const Grid: TCustomGrid);
var
PropInfo:PPropInfo;
DBGrid: TDBGrid;
i: integer;
Dataset: TDataset;
begin
FGrid := Grid;
if not assigned(Grid) then exit;
PropInfo := GetPropInfo(Grid,'DataSource'); //查找Grid是否有DataSource属性
if PropInfo <> nil then //如果有
begin
DBGrid := TDBGrid.Create(nil);
try
//得到表格数据源的数据集的名称
//为了不引用EhLib.pas也能得到TDBGridEh.Datasource.Dataset.Name,所以使用了RTTI
//这样的好处不仅在TDBGridEh中体现,以后使用了别的DBGrid,只要它有DataSource,也能得到其数据集的名称
SetObjectProp(DBGrid, 'DataSource', GetObjectProp(Grid, 'DataSource'));
if not assigned(DBGrid.DataSource) then exit;
Dataset := DBGrid.DataSource.DataSet;
if Dataset = nil then exit;
SetDataset(DataSet);
PropInfo := GetPropInfo(Grid, 'Columns'); //查找Grid是否有Columns属性
if PropInfo <> nil then
begin
SetObjectProp(DBGrid, 'Columns', GetObjectProp(Grid, 'Columns'));
if not assigned(DBGrid.Columns) then exit;
for i:=0 to DBGrid.Columns.Count-1 do
begin
if DBGrid.Columns[i].Visible then //只挑选可视的字段
begin
FGridFields.Add(Dataset.Name + '.' + Dataset.Fields[i].FieldName + '=' + DBGrid.Columns[i].DisplayName);
FGridWidths.Add(Dataset.Name + '.' + Dataset.Fields[i].FieldName + '=' + IntToStr(DBGRid.Columns[i].Width));
end;
end;
end;
PropInfo := GetPropInfo(Grid, 'RowHeight'); //查找Grid是否有RowHeight属性
if PropInfo <> nil then
begin
FGridRowHeight := GetPropValue(Grid, 'RowHeight', false);
frmCommon.GridRowHeight := FGridRowHeight;
end;
//把DetailFields的字段列表清空,并把Grid的字段加入DetailFields中
//这样处理有个问题:当调用了LoadFieldList后,DetailFields从FGridFields中得到的字段列表会被配置文件中的字段列表覆盖
DetailFields.Clear;
for i:=0 to FGridFields.Count-1 do
DetailFields.Add(FGridFields.Strings[i]);
finally
FreeAndNil(DBGrid);
end;
end;
end;
function TReport.GetVariant: TStrings;
begin
result := FVariantList;
end;
procedure TReport.SetVariants(const Value: TStrings);
var
i: integer;
begin
//注意:如果要传字符串变量,那么格式为'Name=''Value''';如果要传数值变量,那么格式为'Name=1'
FvariantList.Assign(value);
FReport.Dictionary.Variables[' VariantList'] := ''; //变量root
for i:=0 to FVariantList.Count-1 do //把变量列表加入数据字典
FReport.Dictionary.Variables[value.Names[i]] := value.ValueFromIndex[i];
end;
end.