某些应用程序需要将报告模板存储在数据库中。 这简化了模板支持-所有报告都存储在一个地方,并允许区分对不同模板的访问权限。 我注意到该技术的唯一缺点-客户端应用程序中的代码略有复杂。
例如,我们需要创建名为“ reports”的Access数据库(mdb)和用于存储报告模板的表。 我将此表命名为“ reports_table”。 在我们的数据表中,三个表就足够了:
№ Field name Type Description
1 Id counter Auto-increment, index
2 ReportName text Name of report
3 ReportFile BLOB Binary data with template
您可以将模板存储在任何其他与我们的示例类似的数据库中。
去做这个:
- 打开设计师;
- 当用户在设计器中打开文件时,显示自定义表单以及来自我们数据库的模板列表,而不是标准对话框;
- 在自定义窗体中选择模板后,将其加载到设计器中;
- 将模板保存在用户在设计器中保存文件的数据库中。
首先在Visual Studio中创建一个新项目。 然后,您需要将“报表”对象从工具箱中拖放到空白表格中。 还要拖动“ EnvironmentSettings”对象(报告引擎的属性)。
您可以在“ environmentSettings1”对象中设置报告和设计器的许多设置。 您必须重写事件处理程序CustomOpenDialog,CustomOpenReport,CustomSaveDialog和CustomSaveReport。
事件处理程序CustomOpenDialog允许释放设计器中加载报告模板的任何算法-从数据库字段加载模板并将其加载到设计器中或设置e.Cancel = true;。 加载失败时。
该问题减少为显示与文件列表的对话框,您要从中选择一个文件列表,以从数据库中选择报告模板并在设计器中加载该模板。 当然,如果用户在此对话框中按“取消”按钮,则我们将e.Cancel = true设置为。 加载过程很清楚,但是保存代码需要一些细节。
用户可以选择两种保存文件的方法-只需单击“保存”,在这种情况下,报告应重写到旧位置,或者选择第二个选项“另存为...”,则用户应选择路径在本例中,报表模板的存储位置无法更改,您需要通过两种方式将模板保存在旧位置(数据库字段)-通过空函数捕获CustomSaveDialog事件,并在CustomSaveReport事件中将模板保存在数据库中。
现在,您需要向项目中添加一个新的数据源-reports.mdb。删除窗体上的按钮以启动报告设计器。
在Click事件处理程序中编写:
private void button1_Click(object sender, EventArgs e)
{
report1.Design();
}
创建用于模板选择的其他对话框形式:
分配对应于DialogResult的确定和取消按钮。
不要忘记将数据源绑定到DataGrid-选择记录的字段名称,并使索引字段不可见。
单击“确定”按钮时,需要保存所选索引:
public int reportID;
//...
private void OKBtn_Click(object sender, EventArgs e)
{
// save id of report for use in future
reportID = (int)dataGridView1.CurrentRow.Cells[0].Value;
}
我们返回第一个表格。
现在该处理打开和保存报告的事件了。
我们首先要加载:
// define variable for store of report ID
private int reportID;
// define array byte[] for store of template
private byte[] blob;
//....
private void environmentSettings1_CustomOpenDialog(object sender,
FastReport.Design.OpenSaveDialogEventArgs e)
{
using (ReportListForm reportListForm = new ReportListForm())
{
// show dialog for report selection
if (reportListForm.ShowDialog() == DialogResult.OK)
{
// get report ID
reportID = reportListForm.reportID;
// load report in array from BLOB
blob =
(byte[])this.reports_tableTableAdapter.GetDataByID(reportID).Rows[0]["ReportFile"];
// read file name of report for designers title
e.FileName =
(string)this.reports_tableTableAdapter.GetDataByID(reportID).Rows[0]["ReportName"];
}
else
// cancel loading
e.Cancel = true;
}
}
用于在设计器中加载模板的第二个处理程序CustomOpenReport应该如下所示:
private void environmentSettings1_CustomOpenReport(object sender,
FastReport.Design.OpenSaveReportEventArgs e)
{
using (MemoryStream stream = new MemoryStream())
{
// skip all garbage created by MS Access in begin of blob field - we seek the tag of XML
int start = 0;
for (int i = 0; i < blob.Length - 1; i++)
{
if (blob[i] == (byte)'<' && blob[i + 1] == (byte)'?')
{
start = i;
break;
}
}
// copy of blob content in stream
stream.Write(blob, start, blob.Length - start);
stream.Position = 0;
// load template in designer
e.Report.Load(stream);
}
}
我们使用mdb-database存储报告模板。
MS Access在BLOB字段的开头写入特殊标头。
我们需要跳过此标头,并找到xml文件的开始(报告模板存储在xml中)。
我们转到组织并使用设计器保存模板。 如上所述,我们需要用一个空函数覆盖事件处理程序CustomSaveDialog,以防止用户执行不必要的操作:
private void environmentSettings1_CustomSaveDialog(object sender,
FastReport.Design.OpenSaveDialogEventArgs e)
{
// empty
}
事件处理程序CustomSaveReport应该如下所示:
private void environmentSettings1_CustomSaveReport(object sender,
FastReport.Design.OpenSaveReportEventArgs e)
{
// create stream for store of template
using (MemoryStream stream = new MemoryStream())
{
// save template in stream
e.Report.Save(stream);
// copy stream in array
byte[] blob = stream.ToArray();
// save array in BLOB
this.reports_tableTableAdapter.UpdateReport(blob, reportID);
}
}
方法GetDataByID和UpdateReport在数据集设计器中创建-您可以在示例项目中看到它们。
编译并运行应用程序,然后按一个按钮以打开设计器:
- 单击菜单项“打开”:
- 选择任何报告模板,然后按OK。
您可以更改报告并保存模板,之后将新模板存储在数据库中。
该示例的完整源代码可在随附的zip存档中找到(包括带有报告的数据库)。
From: https://bytes.com/topic/net/insights/891986-how-store-fastreport-net-report-templates-database