zoukankan      html  css  js  c++  java
  • C#集成FastReport.Net并将模板保存到数据库

    本着开发与实施分离的思想,设计一个通用的报表设计窗体显得尤为重要(下图为图一):

    要求与优点:

      I、报表设计窗体支持所有单据调用,一种单据支持多个打印模板。

      II、报表模板存储在数据库中。一是支持客户端设计及保存模板,二是一次修改所有客户端生效。

      III、点击保存是将模板保存在数据库中,点击另存为可将模板保存为文件。这样可以实现模板的复制。

      IV、预览与打印。已设计好的模板不需要每次都进入设计界面,直接预览或打印即可。

    开发环境:

    VS2017+SQL SERVER 2014+FastReport.Net(2017.1.16)

    由于篇幅较多,本次主要分享设计按钮的功能。闲话少说!

    1、数据表设计。

    CREATE TABLE [dbo].[AT_REPORT](
        [FORMID] [varchar](20) NOT NULL,
        [RPT_NO] [varchar](20) NOT NULL,
        [RPT_NAME] [varchar](50) NULL,
        [FILEDATA] [varbinary](max) NULL,
     CONSTRAINT [PK_AT_REPORT] PRIMARY KEY CLUSTERED 
    (
        [FORMID] ASC,
        [RPT_NO] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    2、新增FastReportDesign窗体(图一):

      1.1引用FastReport库文件。

      

      1.2代码引用。

    using System.Data.SqlClient;
    using FastReport;
    using FastReport.Utils;
    using FastReport.Design;

    2、定义属性及变量:

    说明:FormID是单据ID,即哪种单据调用报表设计窗体则给此属性赋值。RptNo、RptName在点击图一报表种类时赋值。

    public string FormID { get; set; } = "PRDT"; //单据ID
    private string RptNo, RptName; //报表编号、名称
    private DataTable RptTable; //数据表
    private DataRow RptRow; //数据行(报表数据源)
    private bool isSaveAs = false; //另存为

    3、双击设计按钮:

    说明:tvwRight是图一右边Treeview的名称。

    //设计
            private void btnDes_Click(object sender, EventArgs e)
            {
                if (tvwRight.SelectedNode != null)
                {
                    if (!string.IsNullOrEmpty(FormID) && !string.IsNullOrEmpty(RptNo))
                    {
                        InitializeReport("DESIGN");
                    }
                    else
                    {
                        MessageBox.Show("报表获取失败。", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                {
                    MessageBox.Show("请先选择报表。", "信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }

    4、初始化方法:

    注:mymeans.GetDataSet是自己写的类方法,主要是将SQL生成DataSet。

    //初始化报表
            private void InitializeReport(string RptMode)
            {
                DataSet Ds = mymeans.GetDataSet("SELECT RPT_NO,RPT_NAME,FILEDATA FROM AT_REPORT WHERE FORMID='" + FormID + "' AND RPT_NO='" + RptNo + "'", "REPORT");
                RptTable = Ds.Tables[0];
                RptRow = RptTable.Rows[0];
                RegisterDesignerEvents();
                DesignReport(RptMode);
            }

    5、注册事件:

    说明:FastReport设计器菜单保存及另存为功能,都是将设计模板保存成文件。由于我们需要将设计模板保存到数据库,所以需要屏蔽掉系统原有的功能自己写。另外需要说明的是,保存按钮不会弹出对话框,所以当点击另存为时,才会触发OpenSaveDialogEventHandler。(可参考FastReport自带范例CustomOpenSaveDialogs)

    
    
    //菜单事件注册
            private void RegisterDesignerEvents()
            {
                Config.DesignerSettings.CustomSaveDialog += new OpenSaveDialogEventHandler(DesignerSettings_CustomSaveDialog);
                Config.DesignerSettings.CustomSaveReport += new OpenSaveReportEventHandler(DesignerSettings_CustomSaveReport);
            }
    
    

     6、设计模板加载:

    //设计报表
            private void DesignReport(string RptMode)
            {
                using (Report TargetReport = new Report())
                {
                    TargetReport.FileName = RptName;
                    if (RptRow["FILEDATA"].ToString().Length > 0)
                    {
                        byte[] ReportBytes = (byte[])RptRow["FILEDATA"];
                        using (MemoryStream Stream = new MemoryStream(ReportBytes))
                        {
                            TargetReport.Load(Stream);
                        }
                    }
                    //操作方式:DESIGN-设计;PREVIEW-预览;PRINT-打印
                    if (RptMode == "DESIGN")
                    {
                        TargetReport.Design();
                    }
                    else if (RptMode == "PREVIEW")
                    {
                        TargetReport.Prepare();
                        TargetReport.ShowPrepared();
                    }
                    else if (RptMode == "PRINT")
                    {
                        TargetReport.Print();
                    }
                }
            }

    7、另存为对话框:

    说明:isSaveAs为true时,表明点击的是另存为按钮。

    //保存菜单:对话框
            private void DesignerSettings_CustomSaveDialog(object sender, OpenSaveDialogEventArgs e)
            {
                isSaveAs = true;
            }

    8、保存委托函数:

    //保存菜单:委托函数
            private void DesignerSettings_CustomSaveReport(object sender, OpenSaveReportEventArgs e)
            {
                SaveReport(e.Report);
            }

     9、报表模板保存:

    说明:mymeans.ConOpen()是自己写的类方法,主要是连接数据库。

    
    
    //保存报表
            private void SaveReport(Report TargetReport)
            {
                try
                {
                    using (MemoryStream msStream = new MemoryStream())
                    {
                        //解决困扰多时的多次保存问题。
                        Config.DesignerSettings.CustomSaveDialog -= new OpenSaveDialogEventHandler(DesignerSettings_CustomSaveDialog);
                        Config.DesignerSettings.CustomSaveReport -= new OpenSaveReportEventHandler(DesignerSettings_CustomSaveReport);
                        //保存
                        TargetReport.Save(msStream);
                        RptRow["FILEDATA"] = msStream.ToArray();
                        if (FrameClass.MyMeans.Con == null || FrameClass.MyMeans.Con.State != ConnectionState.Open)
                        {
                            mymeans.ConOpen();
                        }
                        SqlCommand Cmd = FrameClass.MyMeans.Con.CreateCommand();
                        Cmd.CommandText = "UPDATE AT_REPORT SET FILEDATA=@FILEDATA WHERE FORMID=@FORMID AND RPT_NO=@RPT_NO";
                        Cmd.Parameters.AddWithValue("@FILEDATA", msStream.ToArray());
                        Cmd.Parameters.AddWithValue("@FORMID", FormID);
                        Cmd.Parameters.AddWithValue("@RPT_NO", RptNo);
                        Cmd.ExecuteNonQuery();
                        //另存为
                        if (isSaveAs == true)
                        {
                            SaveFileDialog saveFileDialog = new SaveFileDialog();
                            //设置文件类型
                            saveFileDialog.Filter = "报表文件(*.frx)|*.frx";
                            //设置默认文件类型显示顺序  
                            saveFileDialog.FilterIndex = 1;
                            //是否自动在文件名中添加扩展名
                            saveFileDialog.AddExtension = true;
                            //是否记忆上次打开的目录
                            saveFileDialog.RestoreDirectory = true;
                            //设置默认文件名
                            saveFileDialog.FileName = RptName;
                            //按下确定选择的按钮  
                            if (saveFileDialog.ShowDialog() == DialogResult.OK)
                            {
                                //获得文件路径 
                                string localFilePath = saveFileDialog.FileName.ToString();
                                //文件保存
                                FileStream fsStream = new FileStream(localFilePath, FileMode.Create);
                                msStream.WriteTo(fsStream);
                                //资源释放      
                                fsStream.Close();
                                fsStream = null;
                            }
                            //赋初始值
                            isSaveAs = false;
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }

    好了,主要的功能就分享到此,希望对大家有一些帮助。

  • 相关阅读:
    Cookie天使还是恶魔?
    Nhibernate学习起步之manytoone篇
    共享终结者ShareKiller
    基于弹性碰撞原理的抖动式窗口
    Nhibernate分析之华山论剑篇
    Nhibernate学习之manytomany篇
    JavaScript常用字符串函数
    让全中国人蒙羞的搜索爬虫
    近期项目的一些代码总结
    Nhibernate学习之性能改善1
  • 原文地址:https://www.cnblogs.com/atomy/p/7986996.html
Copyright © 2011-2022 走看看