doit

公告

统计

置顶随笔

[置顶]用DbProviderFactory 实现通用数据库操作的封装

摘要: 用DbProviderFactory 实现通用数据库操作的封装阅读全文

posted @ 2010-08-08 08:27 doit 阅读(280) 评论(0) 编辑

2011年2月18日

Report报表学习系列五

今天写了一天的代码,关于报表的一些基本控件,回来不想再写了,直接COPY上,有详细的注释。主要内容有上一页,下一页,放大,缩小,导为EXCEL和PDF,打印。

这里再次感谢“蜡人张”,这里有很多功能是参考该大侠的博客后修改的,这里是他的文章链接:http://waxdoll.cnblogs.com/archive/2006/03/03/342435.html

 代友:

namespace POSReport.ReportForm
{
    public partial class FrmReportViewBase : Form
    {
      
     
        #region 构造函数

        public FrmReportViewBase()
        {
            InitializeComponent();
            //this.SetCtlDesc();
            //LanguageChange.ChangeDisplay(this);
        }

        #endregion


        #region 自定义报表按钮的操作

        #region 返回报表第一页
        /// <summary>
        /// 回到报表的第一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFirst_Click(object sender, EventArgs e)
        {
            this.rptViewMain.CurrentPage = 1;
        }
        #endregion

        #region 跳转到报表最后一页
        /// <summary>
        /// 跳转到报表最后一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLast_Click(object sender, EventArgs e)
        {
            this.rptViewMain.CurrentPage = this.rptViewMain.LocalReport.GetTotalPages();
        }
        #endregion

        #region 上一页
        /// <summary>
        /// 上一页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPre_Click(object sender, EventArgs e)
        {
            if (this.rptViewMain.CurrentPage > 1)
            {
                this.rptViewMain.CurrentPage--;
            }
        }
        #endregion

        #region 下一页
        private void btnNext_Click(object sender, EventArgs e)
        {
            if (this.rptViewMain.CurrentPage < this.rptViewMain.LocalReport.GetTotalPages())
            {
                this.rptViewMain.CurrentPage++;
            }
        }
        #endregion

        #region 放大
        /// <summary>
        ///放大
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEnlarge_Click(object sender, EventArgs e)
        {
            if (this.rptViewMain.ZoomPercent < maxPercent)
            {
                this.rptViewMain.ZoomPercent += addPercent;
            }
        }
        #endregion

        #region 缩小
        /// <summary>
        /// 缩小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReduce_Click(object sender, EventArgs e)
        {
            if (this.rptViewMain.ZoomPercent > minPercent)
            {
                this.rptViewMain.ZoomPercent -= addPercent;
            }
        }
        #endregion

        #region 关闭
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        #endregion

        #region 导出为Excel或PDF
        private void btnSaveDest_Click(object sender, EventArgs e)
        {
            try
            {
                Microsoft.Reporting.WinForms.Warning[] Warnings;
                string[] strStreamIds;
                string strMimeType;
                string strEncoding;
                string strFileNameExtension;

                //文件形式
                string fileType = "Excel";
                string fileName = "";
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.AddExtension = true;
                sfd.Filter = "excel|*.xls|PDF|*.PDF";

                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    if (string.IsNullOrEmpty(sfd.FileName))
                    {
                        return;
                    }
                    if (sfd.FilterIndex == 1)
                    {
                        fileType = "Excel";
                    }
                    else if (sfd.FilterIndex == 2)
                    {
                        fileType = "PDF";
                    }
                    else
                    {
                        fileType = "Excel";
                    }

                    fileName = sfd.FileName;
                    byte[] bytes = this.rptViewMain.LocalReport.Render(fileType, null, out strMimeType, out

strEncoding, out strFileNameExtension, out strStreamIds, out Warnings);
                    SaveFile(fileName, bytes);
                }
            }
            catch (Exception ex)
            {
                msgError.GetExcepiton(ex, MODULENAME, Common.CommonBase.MsgError.Title.Hint);
            }


        }
        #endregion

        #region 打印
        private void btnPrint_Click(object sender, EventArgs e)
        {
            try
            {
                Export(this.rptViewMain.LocalReport);
                currentPageIndex = 0;

                const string printerName = "Microsoft XPS Document Writer";

                if (streams == null || streams.Count == 0)
                    return;

                PrintDocument printDoc = new PrintDocument();
                printDoc.PrinterSettings.PrinterName = printerName;
                if (!printDoc.PrinterSettings.IsValid)
                {                  
                    return;
                }
                printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                printDoc.Print();

                //消毁streams
                if (streams != null)
                {

                    Foreach(Stream stream in streams)

               {
                    stream.Close();

               }
                }
            }
            catch (Exception ex)
            {
                msgError.GetExcepiton(ex, MODULENAME, MsgError.Title.Hint);
            }

        }
        #endregion

        #endregion

        #region 报表事件

        private void rptViewMain_Load(object sender, EventArgs e)
        {
            // 设置自定义报表按钮是否为可用
            SetControlVisble();
            //设置报表的缩放模式
            this.rptViewMain.ZoomMode = ZoomMode.Percent;
        }

        #region 报表的显示页号改变事件
        private void rptViewMain_PageNavigation(object sender, PageNavigationEventArgs e)
        {
            // 设置自定义报表按钮是否为可用
            SetControlVisble();
        }
        #endregion

        #region 报表显示的百分比改变事件
        private void rptViewMain_ZoomChange(object sender, ZoomChangeEventArgs e)
        {
            if (this.rptViewMain.ZoomPercent >= maxPercent)
            {
                this.btnEnlarge.Enabled = false;
            }
            else
            {
                this.btnEnlarge.Enabled = true;
            }

            if (this.rptViewMain.ZoomPercent <= minPercent)
            {
                this.btnReduce.Enabled = false;
            }
            else
            {
                this.btnReduce.Enabled = true;
            }
        }
        #endregion

        #endregion

        #region 方法

        #region 设置自定义报表按钮是否为可用
        /// <summary>
        /// 设置自定义报表按钮是否为可用
        /// </summary>.
        private void SetControlVisble()
        {
            if (this.rptViewMain.LocalReport.GetTotalPages() <= 1)
            {
                this.btnFirst.Enabled = false;
                this.btnLast.Enabled = false;
                this.btnNext.Enabled = false;
                this.btnPre.Enabled = false;
                return;
            }

            if (this.rptViewMain.CurrentPage >= this.rptViewMain.LocalReport.GetTotalPages() - 1)
            {
                this.btnNext.Enabled = false;
                this.btnLast.Enabled = false;
            }
            else
            {
                this.btnLast.Enabled = true;
                this.btnNext.Enabled = true;
            }

            if (this.rptViewMain.CurrentPage <= 0)
            {
                this.btnFirst.Enabled = false;
                this.btnPre.Enabled = false;
            }
            else
            {
                this.btnPre.Enabled = true;
                this.btnFirst.Enabled = true;
            }
        }
        #endregion

        #region 保存
        protected void SaveFile(string fileName, byte[] bytes)
        {
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Create))
                {
                    fs.Write(bytes, 0, bytes.Length);
                }
            }
            catch (IOException ex)
            {
                return;
            }
        }
        #endregion

        #region 创建文件流
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool

willSeek)
        {
            stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
            streams.Add(stream);
            name = string.Empty;
            fileNameExtension = string.Empty;
            return stream;

        }
        #endregion

        #region 将本地报表导出为文件流
        private void Export(LocalReport report)
        {
            string deviceInfo =
              "<DeviceInfo>" +
              "  <OutputFormat>EMF</OutputFormat>" +
              "  <PageWidth>8.5in</PageWidth>" +
              "  <PageHeight>11in</PageHeight>" +
              "  <MarginTop>0.25in</MarginTop>" +
              "  <MarginLeft>0.25in</MarginLeft>" +
              "  <MarginRight>0.25in</MarginRight>" +
              "  <MarginBottom>0.25in</MarginBottom>" +
              "</DeviceInfo>";
            Warning[] warnings;
            streams = new List<Stream>();
            report.Render("Image", deviceInfo, CreateStream, out warnings);

            foreach (Stream stream in streams)
            {
                stream.Position = 0;
            }
        }


        #endregion

        #region Page打印方法
        private void PrintPage(object sender, PrintPageEventArgs e)
        {
            Metafile pageImage = new Metafile(streams[currentPageIndex]);
            e.Graphics.DrawImage(pageImage, e.PageBounds);

            currentPageIndex++;
            e.HasMorePages = (currentPageIndex < streams.Count);
        }
        #endregion
        #endregion

        #region 私有成员
        //报表显示的百分比的增量因子
        private const int addPercent = 25;
        //报表显示的最大百分比
        private const int maxPercent = 200;
        private const int minPercent = 25;


        private MsgError msgError = MsgError.getInstance();//实例化错误异常提示类
        private const string MODULENAME = "FrmReportViewBase"; //模块名称

        //当前页的索引
        private int currentPageIndex;
        //打印需要的文件流序列
        private IList<Stream> streams;

        #endregion

    }
}

posted @ 2011-02-18 18:29 doit 阅读(166) 评论(0) 编辑

2011年2月10日

Report报表学习系列四

因为过春节的缘故,第四篇多等了一年。

上一篇写到表参数设置和建立子表,分组,本篇将学习使用钻取报表。其实只要会使用参数和建立子报表,钻取报表是很简单的事情了。

首先简单地说一下这里的钻取报表的目的:当点击相应的学生后面的查看按钮后,能跳转到另一张报表,显示该学生所在班级的所有学生信息。

一 在文件夹Report中添加报表文件StudentDetail.rdlc,拖放一张表。报表-选择数据源为RptDataSet_Student,报表-建立参数ClassID,选中表,右键-属性-筛选器,设置(=Fields!ClassID.Value)=(=Fields!Sname.Value),确定。

二 在rptStudent.rdlc的表的最右侧插入列,列标题为"查看所在班级",详细内容为"查看",如下图1.1

 
图1.1
右击“查看”所有在的单元格,右键选择属性-导航-跳至表设为rptStudentDetail,然后点参数,设置参数名为刚才上面在StudentDetail里面的ClassID,值为=Fields!ClassID.Value,颜色设为红色.
三 为报表添加钻取报表处理事件。
  private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            e.DataSources .Add (
                new ReportDataSource("RptDataSet_Student", studentDataSource.GetStudentData())
                );
        }
四 把委派事件添加到本地报表
在窗体的LOAD事件里面添加如下代码
  this.rptViewMain.Drillthrough += new DrillthroughEventHandler(LocalReport_DrillthroughEventHandler);
整个代码如下:

public FrmRptMain()
        {
            InitializeComponent();
        }

        private ClassDataSource dataSource = new ClassDataSource();
        private StudentDataSource studentDataSource = new StudentDataSource();

        private void FrmRptMain_Load(object sender, EventArgs e)
        {
            this.rptViewMain.LocalReport.SubreportProcessing +=
                 new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);

            this.rptViewMain.Drillthrough += new DrillthroughEventHandler(LocalReport_DrillthroughEventHandler);

            this.rptViewMain.LocalReport.ReportEmbeddedResource = "ReportingAPP.Report.rptClass.rdlc";
            this.rptViewMain.LocalReport.DataSources.Add(
                new ReportDataSource("RptDataSet_Class", dataSource.GetClassData())
                );

            this.rptViewMain.RefreshReport();
        }

        private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            e.DataSources.Add(
                new ReportDataSource("RptDataSet_Student", studentDataSource.GetStudentData())
                );
        }

        private void LocalReport_DrillthroughEventHandler(object sender, DrillthroughEventArgs e)
        {
            LocalReport rpt = e.Report as LocalReport;
            if (rpt != null)
            {
                rpt.DataSources.Add(new ReportDataSource("RptDataSet_Student", studentDataSource.GetStudentData()));
            }
        }

五 调试运行

主界面如下:

当点击查看后,结果如下图
六 总结
钻取报表的处理过程和子报表差不多,这里只说最基础的入门知识,更深的东西希望读者自己摸索,这里简单的总结一下过程。
1)建立需要跳转的目标报表,选择相应的数据源和建立相应的参数,设置筛选条件。
2)在主报表中设置链接的字段,设置链接的路径和参数。
3)编写本地报表的钻取事件(为子目标报表提供数据源)
4)添加本地报表的钻取事件。
过完年刚刚回来,第一天上班,还没什么状态,先到这里,Happy new year!

posted @ 2011-02-10 21:37 doit 阅读(455) 评论(1) 编辑

2011年1月24日

Report报表学习系列三

昨天写了用C#做最基本的报表,并手动配置数据源,这篇主要讲报表参数设置和建立子表,分组。

一 建立报表参数    

    打开昨天的项目,在Report文件夹中新建报表rptStudent .rdlc,拖入一张表,点击报表-报表参数--参数--添加,参数名称Cno,确定

二 为子报表添加数据集

    依然是报表--数据源--把RptDataSet_Student添加到报表,确定.

三 设计子报表

    添加分组,如图1

图1
分组依据为ClassID,包括组头和组尾。如图2
图2
作如下设置
其中的=Count(Fields!Sno.Value) 可以右击单元格,表达式--常见函数--聚合,选择Count(),再在Count()的括号中选择字段,双击Sno。
这里顺便讲一下分组,其实分组就像SQL里面的聚合函数,通过一定的分组依据,把数据划分成相同性质的若干小组,就像这里用班号,把学生数据划分为若干个班级。
然后选择中表格,右键,选择属性的筛选器,设置(=Fields!ClassID.Value)=(=Parameters!.Cid.value)
四 在主报表中的设置.
   打开主报表rptClass,从工具箱里面拖一张子表放入组尾(最好把尾组的一行单元格合并),重命名为subRptStudent
  设置子报表subRptStudent控件的ReportName为rptStudent,右键--属性--参数--Cid值为=Fields!SystemKey.Value,如图
 
五编写Student的数据访问类
    首先,在DataSource文件中添加Studnet的数据处理类StudentDataSource.类的内容如下,它为报表提供数据源实例。
public class StudentDataSource
    {
        public DataTable GetStudentData()
        {
            DataTable dt = new DataTable();
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ReportingAPP.Properties.Settings.RptDBConnectionString"].ToString());
            StringBuilder cmdText = new StringBuilder();
            cmdText.Append("SELECT [SystemKey] ,[Sno],[Sname],[ClassID] FROM [Student]");
            try
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand(cmdText.ToString(), conn);
                dt.Load(cmd.ExecuteReader());
            }
            catch (Exception ex)
            {
            }
            finally
            {
                conn.Close();
            }
            return dt;
        }
    }
然后在主窗体中添加
六  为子报表添加子报表的本地处理事件的委托方法。
在主窗体中添加如下方法
        private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            e.DataSources .Add (
                new ReportDataSource("RptDataSet_Student", studentDataSource.GetStudentData())
                );       
       }
七 为主报表添加添加子报表的本地处理事件
    在主窗体的Load事件中,添加如下语句
 private void FrmRptMain_Load(object sender, EventArgs e)
        {
            this.rptViewMain.LocalReport.SubreportProcessing +=
                 new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);//如果没有这个会报子报表无法显示的错误
            this.rptViewMain.LocalReport.ReportEmbeddedResource = "ReportingAPP.Report.rptClass.rdlc";
            this.rptViewMain.LocalReport.DataSources.Add(
                new  ReportDataSource("RptDataSet_Class",dataSource.GetClassData ())
                );
            this.rptViewMain.RefreshReport();
        }
好吧,现在我是迫不及待的按F5了。。。。。。并没有显示学生名字。。。rptStudent中的表要把设置DataSetName为RptDataSet_Student,输出数据选择为是。
现在可以了。运行结果如下
现在来简单的总结一下子报表的处理
1)报立子报表的RDLC文件,建立参数,选择数据集,写好筛选器的条件,为报表里的表选择好DataSetName,输出数据设置为是,并按所需设置子报表格式和内容
2)在主报表中添加子报表控件,选择子报表控件的ReportName为刚建立好的RDLC子报表,设置参数。
3)为子报表写数据源提供数据实例(编写相关的DataSource类)
4)编写本地报表的委托处理方法
  private void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
        {
            e.DataSources .Add (
                new ReportDataSource("RptDataSet_Student", studentDataSource.GetStudentData())
                );       
       }
5)添加子报表的本地处理事件 this.rptViewMain.LocalReport.SubreportProcessing +=
                 new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
好像有点累,今天就到这里吧,明天写钻取报表。

posted @ 2011-01-24 21:01 doit 阅读(286) 评论(6) 编辑

2011年1月23日

Report报表学习系列二

前面讲了用报表向导创建报表项目,今天用C#代码做与前面相同功能的基本报表。

一 创建三个文件夹 DataSet(存放数据集),DataSource(提供数据源),Report(存放报表文件)

二 创建数据集.

    在DataSet中新建数据集RptDataSet.xsd,VS--视图--服务器资源管理器--选择前面创建的两张表--拖入数据集中(删除ClassTableAdapter和StudentTableAdapter,因为不删除的话系统会调用里面的FILL方法自动填充数据集。)注,这里的数据集不是必须从服务器资源管理器拖,也可以直接写,这里是为了方便数据的绑定,下面会讲到。

 三在DataSet中新建ClassDataSource.cs,代码如下

 public class ClassDataSource
    {
        public DataTable GetClassData()
        {
            DataTable dt = new DataTable();
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ReportingAPP.Properties.Settings.RptDBConnectionString"].ToString());//注意添加ConfigurationManager的引用和自己配置连接字符串
            StringBuilder cmdText = new StringBuilder();
            cmdText.Append("SELECT [SystemKey],[Cno] ,[CName] FROM [RptDB].[dbo].[Class]");
            try
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand(cmdText.ToString(), conn);
                dt.Load(cmd.ExecuteReader());
            }
            catch (Exception ex)
            {

            }
            finally
            {
                conn.Close();
            }

            return dt;

        }

}

四 在Report文件夹中添加报表文件rptClass.rdlc

在报表里面拖一张表,选择VS上文工具栏的数据源(选中表后才能看得见报表工具,和报表有关的资源大多放在这里,比如参数,数据源,图片),选择RptDataSet_Class添加到报表.

然后用如下的设计

 
 
五 在主窗体上拖一个MicrosoftReportView控件重命名为rptViewMain
    在窗体的LOAD事件里面添加如下的语句
 private ClassDataSource dataSource = new ClassDataSource();
      this.rptViewMain.LocalReport.ReportEmbeddedResource = "ReportingAPP.Report.rptClass.rdlc";//指定报表路径
this.rptViewMain.LocalReport.DataSources.Add(
                new  ReportDataSource("RptDataSet_Class",dataSource.GetClassData ())
                );//为报表添加数据源,这里ReportDataSource的第一个参数同报表文件里面的数据源同名.
            this.rptViewMain.RefreshReport(); //呈现报表数据
F5
这样,一个最基本的报表就呈现出来了。
下一篇将讲报表参数和子报表。

posted @ 2011-01-23 18:59 doit 阅读(1876) 评论(5) 编辑

2011年1月22日

Report报表学习系列一 (开篇)

最近公司要用到Report报表,为什么要用Report报表,原因很简单,客户要求用免费的。因此专门去学习了一下,看了园子里面很多大牛的随笔,谢园子里面无私的朋友,把自己的学习经验和大家分享,这里特别感谢“蜡人张”。

好吧,就这么开始,我是第一次写随笔,因为还到明年才毕业,经验比较少,觉压力很大,写随笔也主要是学习而已,比较适合像我这样按步部就班的初学者。

下面用的方法是用报表向导直接在界面上操作的。

一 建数据库(比较懒的朋友可以直接复制下面的SQL)

CREATE DATABASE RptDB
GO
USE RptDB
GO
CREATE TABLE Class
(
SystemKey UNIQUEIDENTIFIER DEFAULT(NEWID())  PRIMARY KEY ,
Cno   NVARCHAR(20) NOT NULL,
CName NVARCHAR(50) NOT NULL
)
GO
CREATE TABLE Student
(
SystemKey UNIQUEIDENTIFIER DEFAULT(NEWID())  PRIMARY KEY ,
Sno NVARCHAR(20) NOT NULL,
Sname NVARCHAR(50) NOT NULL,
ClassID UNIQUEIDENTIFIER
)
ALTER TABLE Student ADD CONSTRAINT FK_Stu_Class FOREIGN KEY(ClassID)
REFERENCES Class(SystemKey)

插入数据若干。

二 新建报表就用程序 ReportingAPP

窗体上拖放MicrosoftReportView,点击其右上角的三角符号,选择设计新报表。

依次选择数据库--新建连接--连接到刚才新建的数据库RptDB。

数据源选择表Class--下一步--表格式--详细信息选择CName--完成--重命名报表--完成

再选择窗体上的reportView控件,点右上角的三角符号,选择刚刚设计好的报表,F5,就可以看到下面的结果了。

到此,一个最基本的报表就可以呈现出来了。

现在观察主窗体,发现上面多了三个控件,

Load事件里面也多了以下语句

   1)  this.ClassTableAdapter.Fill(this.RptDBDataSet.Class);//填充数据集
   2)  this.rptViewMain.RefreshReport();   //这个是报表最见的方法之一,其作用是呈现当前报表内容

先到这里,下一篇介绍一用C#语句而非向导形式做最基本的报表。

posted @ 2011-01-22 23:05 doit 阅读(301) 评论(0) 编辑

2010年11月2日

IBATIS.net 中remapResults属性的运用

摘要: 昨天开始学IBARIS框架了,今天老师上课的时候老师说-里面的remapResults属性没用,可能是XML架构出了问题。我仔细研究了一下,同是也参考了别人的例子(http://www.360doc.com/content/07/1207/15/7147_876919.shtml),总结如下:remapResults绝对是有用的,而且很灵活。1:SELECT $colunm$ FROM table...阅读全文

posted @ 2010-11-02 10:59 doit 阅读(236) 评论(0) 编辑

2010年8月8日

用DbProviderFactory 实现通用数据库操作的封装

摘要: 用DbProviderFactory 实现通用数据库操作的封装阅读全文

posted @ 2010-08-08 08:27 doit 阅读(280) 评论(0) 编辑