delphi 将FastReport报表存入access数据库
转载自:http://t.zoukankan.com/hnxxcxg-p-2940801.html
以下代碼在D7+ACCESS+FastReport 3.15版中測試通過.
1.將FastReport存入數據庫中:
在窗體的"Insert"按鈕的OnClick事件中插入下面代碼:
(Insert_rep: TADOQuery.設置SQL語句:select * from reportdata.
注:ReportData為放置數據庫的表,其中有字段ID(標志),REPORT(報表內容))
procedure TForm1.Button4Click(Sender: TObject);
var
template : TStream;
begin
template := TMemoryStream.Create;
template.Position := 0;
frxReport1.SaveToStream(template);
Insert_rep.Insert;
try
Insert_rep.Active := true;
Insert_rep.Edit;
Insert_rep.DisableControls;
Insert_rep.FieldByName('rptname').AsString := ExtractFileName(OpenDialog1.FileName);//報表名稱,作為報表數據的標志
(Insert_rep.FieldByName('rptdata') as TBlobField).LoadFromStream(template);
Insert_rep.FieldByName('uptime').AsDateTime := now;
Insert_rep.Append;
ShowMessage('Insert OK!');
finally
Insert_rep.EnableControls;
template.Free;
end;
end;
2.將報表從數據庫中讀取出來:
在Button的OnClick事件中添加下面代碼:
(qr_report: ADOQuery)
procedure TForm1.Button4Click(Sender: TObject);
var
template : TStream;
begin
try
g_filename := ...;//報表名稱
qr_report.Close;
qr_report.SQL.Clear;
qr_report.SQL.Add('select * from reportdata where id =:id');
qr_report.Parameters.ParamByName('id').Value := g_filename;
qr_report.Open;
try
template := qr_report.CreateBlobStream(qr_report.FieldByName('report'), bmRead);
template.Position := 0;
frxReport1.LoadFromStream(template);
finally
template.Free;
end;
end;
end;
3修改報表,并寫入數據庫.
在frxDesigner1控件的OnSaveReport事件中,加入下面代碼:
(設計報表后,單擊報表中的 "save" 圖標,觸發該事件)
function TForm1.frxDesigner1SaveReport(Report: TfrxReport;
SaveAs: Boolean): Boolean;
var template : TStream;
begin
template := TMemoryStream.Create;
template.Position := 0;
frxReport1.SaveToStream(template);
qr_report.Edit;
try
qr_report.DisableControls;
(qr_report.FieldByName('Report') as TBlobField).LoadFromStream(template);
qr_report.Post;
finally
qr_report.EnableControls;
template.Free;
end;
end
2023-01-27 16:48追加
上面的代码收藏了许久,现在才有机会实践,上面用的是ADO的方法,而我实际中用的是FireDAC,以下代码经过实测可用,仅供参考
数据库设计:

功能设计:

添加一个窗体(类)方法:
public procedure StartReport(flg: Boolean); //准备报表 ,true为打印,false为预览
以下是它的具体内容:
//准备报表 procedure T报废记录.StartReport(flg: Boolean); var IDList: string; n, i: integer; template: TStream; begin inherited; //检查权限 if UserInfo.frm报废记录 < 3 then begin Application.MessageBox('您当前的权限不足,无法进行打印操作!', '权限不足', MB_OK + MB_ICONSTOP); exit; end; with TV报废记录 do begin n := Controller.SelectedRowCount; //检查是否选中记录 if n = 0 then begin Application.MessageBox('请先选择目标记录,然后再进行打印操作!', '无效的操作', MB_OK + MB_ICONSTOP); exit; end; //获取用户选择的数据列表 => 1,2,3, 注意后面会多出一个逗号,后面要处理掉 for i := 0 to n - 1 do begin Controller.SelectedRows[i].Focused := true; IDList := IDList + DM.FDQ报废记录.FieldByName('ID').AsString + ','; end; end; SetLength(IDList, IDList.Length - 1); //删除最后的逗号 //下载数据库中的报表模板 with DM.FD公共查询 do begin try Close; SQL.text := 'select * from 报表存储 where UserID =' + userinfo.UserID.ToString + ' and ModuleName=' + 'Frm报废记录'.QuotedString; Open(); if recordcount > 0 then //如果用户有自定义报表,则下载,否则调用内置报表格式 begin try template := CreateBlobStream(FieldByName('ReportData'), bmRead);//下载模板 template.Position := 0; frxReport1.LoadFromStream(template);//套用模板 finally template.Free; end; end; finally //empty end; end; with dm.FDQReport报废记录 do //初始化查询,为报表提供数据,这里大家自由发挥吧 begin close; sql.Text := ' SELECT 报废记录.recordID, 报废记录.报废单号, 报废记录.日期, 报废记录.物料代码, 报废记录.名称规格,' + ' round(报废记录.数量,2)*1 as 数量, 报废记录.用途, 报废记录.报废原因, 报废记录.审核, 供应商列表.供应商名称 AS 供应商,' + ' 仓库列表.仓库名称 AS 仓库, 单位列表.单位, 用户名.UserName AS 申请人 ' + ' FROM 供应商列表 INNER JOIN (用户名 INNER JOIN (单位列表 INNER JOIN (仓库列表 INNER JOIN 报废记录 ON ' + ' 仓库列表.仓库ID = 报废记录.仓库ID) ON 单位列表.单位ID = 报废记录.单位) ON 用户名.UserID = 报废记录.申请人) ON' + ' 供应商列表.供应商ID = 报废记录.供应商 WHERE 审核=0 and 报废记录.recordID In (' + IDList + ')'; Open(); DisableControls; //断开与数据集的联系,否则会出现逐行扫描的现象 ,这是FDQUERY的方法 if flg then begin frxReport1.PrepareReport(); //准备报表 frxReport1.Print; //调出打印机界面 end else frxReport1.ShowReport(); EnableControls; //恢复与数据集的联系 ,这是FDQUERY的方法 first; // 使数据集跳到第一行 ,这是FDQUERY的方法 end; end;
然后打印报表和预览报表,都是调用上面的公共方法,只是参数有区别 true为打印,false为预览
procedure T报废记录.dxBarLargeButton3Click(Sender: TObject); //打印报表 begin Self.StartReport(True); end; procedure T报废记录.dxBarLargeButton4Click(Sender: TObject); //预览报表 begin Self.StartReport(false); end;
然后是设置报表,这没什么好讲的,就一句代码
procedure T报废记录.dxBarLargeButton5Click(Sender: TObject); //报表设计 begin frxReport1.DesignReport(); end;
重点是要用到它的保存事件OnSaveReport
//修改报表 function T报废记录.frxDesigner1SaveReport(Report: TfrxReport;SaveAs: Boolean): Boolean; var template: TStream; begin template := TMemoryStream.Create; template.Position := 0; frxReport1.SaveToStream(template); with DM.FD公共查询 do begin close; SQL.Text := 'select * from 报表存储 where userID=' + UserInfo.UserID.ToString + ' and ModuleName=' + 'frm报废记录'.QuotedString; open(); if recordcount = 0 then //如果不存在则新增 begin close; SQL.Text := 'insert into 报表存储 (UserID,ModuleName) values(' + Userinfo.UserID.ToString + ',' + 'Frm报废记录'.QuotedString + ')'; ExecSQL; //重新选定用户数据 close; SQL.Text := 'select * from 报表存储 where userID=' + UserInfo.UserID.ToString + ' and ModuleName=' + 'frm报废记录'.QuotedString; open(); end; Edit; try DisableControls; //断开联系 (FieldByName('ReportData') as TBlobField).LoadFromStream(template); Post;//上传报表 finally EnableControls; //恢复联系 template.Free; end; end; end;
以下是chatGPT的回复
--- Q: 请用delphi写出把fastreport报表提交到数据库的方法,要带注释 A: 方法一: //使用FastReport的DataSet属性 DataSet := MyDataSet; DataSet.Open; DataSet.Append; DataSet.FieldByName('FieldName').AsString := 'Value'; DataSet.Post; ---

浙公网安备 33010602011771号