Tạo báo cáo dùng control ReportViewer với C#



Giới thiệu

Trong các ứng dụng với cơ sở dữ liệu (CSDL), việc đưa ra các báo cáo là việc làm cần cần thiết để giúp các nhà quản lý, người sử dụng đưa ra các thống kê và in ấn khi cần, ví dụ như báo cáo doanh thu theo tuần, theo quý, hoặc báo cáo sinh viên trong một lớp, sinh viên đỗ, trượt, v.v.

Với .NET bạn có thể tạo báo cáo cho các ứng dụng với CSDL một cách dễ dàng, trong bài trước tôi đã giới thiệu bài viết tạo báo cáo sử dụng Crystal Report (CR). Crystal Report đã là một component từ khi Visual Studio ra đời năm 2012.Trong các phiên bản từ VS2008 trở về trước, bạn có thể thêm nó vào thanh Toolbox để phát triển ứng dụng của mình. CR được cung cấp bởi SAP. Từ phiên bản VS2010, SAP chưa có sản phẩm tích hợp CRvới VS2010, bạn muốn sử dụng CR cho phát triển ứng dụng của bạn, bạn chỉ có thể sử dụng bản beta của họ. Bạn có thể download và về cài đặt. Bạn có thể tham khảo thêm tại đây.

Trong bài viết này tôi giới thiệu cách sử dụng control ReportViewer, được tích hợp sẵn trong các phiên bản Visual Studio.


Chuẩn bị

  • Cơ sở dữ liệu và báo cáo chúng ta định xây dựng. Trong ví dụ này chúng ta sử dụng lại CSDL Quản lý bán hàng bài trước, cấu trúc bảng như sau: tblMatHang( MaSP nchar(5), TenSP nvarchar(30), NgaySX Date, NgayHH Date, DonVi nvarchar(10), DonGia Float , GhiChu nvarchar(200))
  • Yêu cầu: tạo báo cáo các sản phẩm có ngày sản xuất lớn hơn một ngày nào đó do người sử dụng nhập vào trên giao diện.

Các bước tạo báo cáo

  1. Tạo mới Project sử dụng template, ngôn ngữ C# và tạo CSDL giống như bài trước hoặc download mã nguồn bài trước rồi phát triển thêm phần báo cáo
  2. Kích chuột phải vào tên Project trong cửa sổ Solution Explorer > Add > New Item …, một cửa sổ hiện ra bạn chọn kiểu Windows Form, đặt tên phần Name: frmBaoCao
  3. Mở Form frmBaoCao, rồi tìm tới control ReportViewer trên ToolBox. Nếu bạn không nhìn thấy ToolBox, bạn có thể vào menu View > ToolBox. Rồi kéo control ReportViewer vào frmBaoCao

Kéo control ReportViewer vào Form
Nếu bạn không tìm thấy control ReportViewer thì xem cách cài đặt trong Visual Studio

  1. Thiết kế Form báo cáo như sau:
    Giao diện form báo cáo

    Phần giao diện Loại control Các thuộc tính
    Cửa sổ chính Form Name = frmBaoCao
    Text = Báo cáo sản phẩm
    (1) GroupBox Text = Điều kiện cho báo cáo
    Dock = Top
    Label Text = Ngày sản xuất lớn hơn
    DateTimePicker Name = dtpNgaySX
    Format = Short
    Button Name = btnBaoCao
    Text = &Tạo báo cáo
    (2) GroupBox Text = Hiển thị cho báo cáo
    Dock = Fill
    ReportViewer Name = rpvBaoCao
    Dock = Hiển thị báo cáo

    Sau khi bạn đã thêm ReportViewer vào Form, bạn sẽ nhìn thấy ở góc trên bên phải có một biểu tượng mũi tên màu đen, bạn kích chuột vào đó nó sẽ bật ra cửa sổ có tên ReportViewer Tasks để cho phép bạn lựa chọn một báo cáo mà bạn đã thiết kế.

    • Nếu bạn muốn hiển thị một báo cáo đã được lưu trữ ở một máy chủ bạn có thể chọn <Server Report> trong mục Choose Report, sau đó điền vào hai thuộc tính Report Server UrlReport Path. Report Server Url là địa chỉ trỏ tới report server, Report Path là đường dẫn đầy đủ mà report trả về.
    • Nếu bạn muốn hiển thị một báo cáo ở local, bạn có thể kích vào tuỳ chọn Design a new report để bắt đầu thiết kế report của bạn hoặc chọn một report đã tồn tại trong Project. Trong bài này chúng ta sẽ tập trung phần thiết kế báo cáo ở local.
  2. Thiết kế tạo mẫu báo cáo, đây là bước chúng ta sẽ thiết kế báo cáo hiển thị những nội dung thông tin gì ở phần thân báo cáo(Body), tiêu đề báo cáo (Header Report), phần đuôi của báo cáo (Footer Report).
    • Kích chuột phải vào tên Project ở cửa sổ Solution Explorer > Add > New Item … trong cửa sổ hiển ra bên trái chọn Reporting, sau đó bên phải chọn Report hoặc Report Wizard, đặt tên cho báo cáo ở phần Name = rptSanPham.rdlc xem hình dưới.Chọn kiểu báo cáo
    • Kích đúp vào rptSanPham.rdlc trong Solution Explorer. Bạn sẽ thấy bên góc bên trái có một cửa sổ Report Data, bạn kích vào New > DataSet… để chọn dữ liệu cho thiết kế báo cáo.Thiết kế DataSet cho Report
    • Các cửa sổ hiển thị lên, bạn chọn nguồn dữ liệu, các bảng sẽ dùng cho thiết kế báo cáo …Chọn nguồn dữ liệu
    • Sau khi chọn song nguồn dữ liêu, trong trường hợp này ta chỉ chọn bảng tblMatHangCấu hình DataSet cho Report
    • Kích chuột phải vào vùng cửa sổ làm việc của rptSanPham.rdlc, rồi chọn các đối tượng hiển thị trong phần thân báo cáo báo cáo như Table, Matrix, Chart, Image … Ngoài ra bạn cũng có thể thêm phần Page HeaderPage Footer để tạo tiêu đề và cho báo cáoChọn các đối tượng cho báo cáo
    • Giả sử phần thân báo cáo tôi sử dụng một Table để hiển thị dữ liệu dưới dạng bảng. Bên cửa sổ trái của Report Data bạn kéo các cột MaSP, TenSP, NgaySX, … vào phần Data và sau đó bạn có thể chỉnh sửa lại phần Header cho có dấu tiếng việt. Sau thiết kế tôi có kết quả như sau:Kết quả thiết kế báo cáo
    • Sau khi hoàn thành việc thiết kế báo cáo, bạn chọn vào file rptSanPham.rdlc trong cửa sổ Solution Explorer, rồi chọn vào cửa sổ Properties và thay đổi thuộc tính Copy to Output Directory = Copy if newerThay đổi copy to report
    • Quay lại Form frmBaoCao kích vào nút Tạo báo cáo để viết sự kiện Click cho nút này.

Phần code lập trình


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using Microsoft.Reporting.WinForms;

namespace QLBanHang
{
    public partial class frmBaoCao : Form
    {
        public frmBaoCao()
        {
            InitializeComponent();
        }

        private void btnBaoCao_Click(object sender, EventArgs e)
        {
            //Khai báo câu lệnh SQL
            String sql = "Select * from tblMatHang Where NgaySX >='" + dtpNgaySX.Value.ToString() + "'" ;
            SqlConnection con = new SqlConnection();
            //Truyền vào chuỗi kết nối tới cơ sở dữ liệu
            //Gọi Application.StartupPath để lấy đường dẫn tới thư mục chứa file chạy chương trình 
            con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=" + Application.StartupPath + @"\QLBanHang.mdf;Integrated Security=True;User Instance=True";
            SqlDataAdapter adp = new SqlDataAdapter(sql, con);
            DataSet ds = new DataSet();
            adp.Fill(ds);

            //Khai báo chế độ xử lý báo cáo, trong trường hợp này lấy báo cáo ở local
            rpvBaoCao.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
            //Đường dẫn báo cáo
            rpvBaoCao.LocalReport.ReportPath = "rptSanPham.rdlc";
            //Nếu có dữ liệu
            if (ds.Tables[0].Rows.Count > 0)
            {
                //Tạo nguồn dữ liệu cho báo cáo
                ReportDataSource rds = new ReportDataSource();
                rds.Name = "tblMatHang";
                rds.Value = ds.Tables[0];
                //Xóa dữ liệu của báo cáo cũ trong trường hợp người dùng thực hiện câu truy vấn khác
                rpvBaoCao.LocalReport.DataSources.Clear();
                //Add dữ liệu vào báo cáo
                rpvBaoCao.LocalReport.DataSources.Add(rds);
                //Refresh lại báo cáo
                rpvBaoCao.RefreshReport();
            }
        }
    }
}

Download mã nguồn phần báo cáo tại đây.


Chú ý: Trong một Project có nhiều Form, bạn muốn form nào chạy đầy tiên thì bạn có thể kích và file Program.cs và thay đổi tên Form muốn chạy trước ở phần Application.Run(…)

Có thể bạn sẽ thích…

68 phản hồi

  1. Nguyễn Trí Nhân viết:

    Xin code quản lý bán hàng. Cám ơn thầy nhiều.

    • Phan Tiến viết:

      Hi Em,
      Mục tiêu của bài quản lý bán hàng để bạn nghiên cứu một bài toán thực tế, và viết chương trình theo hướng dẫn để các bạn làm quen. Trong quá trình làm có thể các em sẽ gặp các lỗi và sẽ tự sửa nó hoặc đặt câu hỏi mình sẽ gợi ý. Mình không cho các bạn code vì sợ các bạn sẽ chẳng chịu làm gì cả, rồi cũng chẳng biết gì.

  2. Cao Kỳ viết:

    chào thầy. sao e làm nó load lên ko được ạ. cảm ơn thầy

    • Phan Tiến viết:

      Trong cái hình thứ 4 từ trên xuống có phần chú ý đặt tên là tblMatHang, em có thể đặt tên gì cũng được, nhưng khi viết trong code phần ReportDataSource phải truyền đúng tên bảng mà em đã đặt tên.

  3. Hải Nguyễn viết:

    Chào thầy
    Thầy cho em hỏi là để làm một cái report hóa đơn bán hàng có kích thước bằng với lại khổ giấy cuộn như cái hóa đơn mua hàng ở siêu thị thì mình làm như thế nào ạ

    • Phan Tiến viết:

      – Em thiết kế dữ liêụ tương ứng với khổ giấy em muốn in ví dụ như A5, A4, A3 …
      – Sau đó em có thể dùng đoạn code sau để thiết lập mặc định khổ giây in ra

      System.Drawing.Printing.PageSettings pg=new System.Drawing.Printing.PageSettings();
      pg.Margins.Top = 0;
      pg.Margins.Bottom = 0;
      pg.Margins.Left = 0;
      pg.Margins.Right = 0;
      System.Drawing.Printing.PaperSize size = new PaperSize();
      size.RawKind = (int)PaperKind.A5;
      pg.PaperSize = size;
      reportViewer1.SetPageSettings(pg);
      this.reportViewer1.RefreshReport();

      • Hải Nguyễn viết:

        Chào thầy,
        Dạ thầy cho em hỏi là khổ giấy mình thường dùng để in hóa đơn tính tiền như ở siêu thị là khổ giấy gì và làm sao để chiều dài của khổ giấy vừa đủ với dữ liệu mình cần in mà không bị phân trang ạ

        • Phan Tiến viết:

          Nhưng máy in hoá đơn ở siêu thị thường dùng khổ giấy K80 tức chiều rộng của hóa đơn in ra có kích thước 80mm. Ngoài khổ này còn các máy in mini ở các quán cafe có thể dùng khổ giấy nhỏ hơn là K57 (57mm) em nhé.

  4. Hà Thủ viết:

    Cho hỏi tạo title và summary trong reportview C# 2010 bằng cách nào ?. Cám ơn.

  5. Tuấn viết:

    Thưa thầy, đã là quản lý bán hàng nhưng em chưa thấy phần bán hàng sẽ code và hoạt động ra sao ? .Mong thầy chỉ giúp.

    • Phan Tiến viết:

      Đây chỉ là một phần nhỏ trong một chương trình quản lý. Em cần lắp ghép vào để tạo thành một chương tình hoàn chỉnh. Về quản lý bán hàng em sẽ cần phải quản lý quá trình nhập xuất hàng ngày để lưu vào phần mềm đi kèm với hoá đơn tương ứng. Việc lập trình phần mềm quản lý bán hàng cũng nhưng các mô hình quản lý khác đều có một cách thức tương tự nhau thôi em.

  6. Trương Việt viết:

    bạn cho mình hỏi mình dùng report viewer theo dạng list, làm sao để mình hiển thị trong 1 tờ giấy A4 sẽ hiển thị được 4 list, 2 list ở trên và 2 list ở dưới rồi mới nhảy sang trang khác, hiện tại mình chỉ làm được list nhảy theo hàng dọc chứ không chạy theo hàng ngang được, bạn giúp mình nhé, cảm ơn bạn

  7. Phong Vũ viết:

    Thầy ơi cho em hỏi..e muốn đổ dữ liệu vào biểu mẩu word thì phải làm thế nào ah.

  8. Nam viết:

    Em chào thầy, mong thầy hồi đáp giúp em !
    Em tới bước chọn nguồn dữ liệu (phần 5 ) thì ko kết nối đến database được, mong thầy giúp em với, em sắp đến deadline rồi ạ.
    Mong thầy hồi âm sớm , em cảm ơn thầy ! Em chúc thầy sức khỏe .

  9. Nam viết:

    em chạy dc rồi tự nhưng khúc cuối bên frmMain lại ra lỗi như này,
    Error 1 ‘QLNS.frmMain’ does not contain a definition for ‘rptBaoCao’ and no extension method ‘rptBaoCao’ accepting a first argument of type ‘QLNS.frmMain’ could be found (are you missing a using directive or an assembly reference?) C:\Users\Sumary\Downloads\Compressed\QLNS\QLNS\QLNS\Form1.cs 46 18 QLNS

    em ko chụp ảnh dc ạ, thầy có thể cho em facebook được ko ạ

  10. Nam viết:

    code của em bị lỗi ở dòng : adp.Fill(ds);
    và đây là 2 thông báo của nó :
    The user instance login flag is not supported on this version of SQL Server. The connection will be closed.
    sqlException was unhandled
    Thầy xem giúp em với ạ

  11. Phương viết:

    e chào thầy. khi e thêm mới dữ liệu. thì trong report lại k có dữ liệu đó. làm cách nào để load dl lên đc ak. e cảm ơn

    • Phan Tiến viết:

      Trước hết em cần kiểm tra xem chương trình của khi biên dịch hoặc khi chạy có báo lỗi gì không? Nếu báo lỗi thì em xem lỗi đó để sửa.

      Như trường hợp em đang nói, mình nghĩ chắc report em chạy được rồi, nhưng khi em thêm mới thì không thấy nó lên report.
      => Vấn đề ở đây mặc định của Visual Studio khi chạy => copy Database vào thư mục chạy của ứng dụng (thư mục Bin của Debug) nên khi em thêm mới nó sẽ thêm vào Database trong Debug\Bin.
      Khi em chạy lại chương trình nó lại copy lại Database trong Project của em đè vào Databse trong Debug\Bin nên dữ liệu em thêm mới sẽ không có.
      Cách khác phục:
      – Trong cửa sổ Solution Explorer em chọn vào Database của em đang làm
      – Rồi ở cửa sổ Propert, tìm thuộc tính Copy to Output => Copy if newer

  12. Đăng Tài viết:

    thầy ơi,sao reportviewer của em không có design a new report vậy Thầy.

  13. Nguyễn DUy Khả viết:

    Dear Thầy,

    Thầy cho em hỏi 1 vẫn đề liên quan đế CSDL ạ
    Nếu e chỉ sử dụng 2 file Database *.mdf và file Log *.ldf, khi copy 2 file này sang máy không có cài đặt sẵn SQL server thì chương trình có kết nối được với CSDL không ạ

  14. Đại Phúc viết:

    Dear Thầy,
    Thầy cho em hỏi trong csdl của em có cột TinhTrang kiểu int có 2 giá trị 0 và 1 làm sao để khi báo cáo 0 thì nó là “Chưa Trả” còn 1 thì “Đã Trả”

  15. Long Sơn viết:

    Cho em hỏi giờ em muốn nạp datasource từ trong code em có tạo sẵn 1 lớp xử lý lấy dữ liệu lên theo điều kiện rồi, giờ em muốn nạp vào report thì làm sao ạ, em làm cách này thì toàn hiện full data không có điều kiện không ạ. Em cảm ơn

  16. Long Sơn viết:

    Cho em hỏi em muốn add data vào report theo 1 dataset mà em đã xây dựng 1 lớp để lấy dữ liệu đã lọc theo điều kiện thì làm sao ạ, em làm cách này thì toàn lấy full data từ database lên không ạ. em cảm ơn

  17. than viết:

    thầy ơi muốn xuất ra mẫu file word định sẵn thì làm sao. thank thầy ạ

    • Phan Tiến viết:

      Em muốn xuất thẳng ra word thì có 1 số phương án:
      1. Sử dụng thư viện của MS Office để xuất trực tiếp ra Word=> https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interop/how-to-access-office-onterop-objects
      2. Xuất trực tiếp từ lưới DataGrid

      protected void ExportToWord()
      {
      //Lấy dữ liệu từ cơ sở dữ liệu
      string strQuery = "select CustomerID, ContactName, City, PostalCode" +
      " from customers";
      SqlCommand cmd = new SqlCommand(strQuery);
      DataTable dt = GetData(cmd);
      //Tạo một GridView để hiển thị dữ liệu
      GridView GridView1 = new GridView();
      GridView1.AllowPaging = false;
      GridView1.DataSource = dt;
      GridView1.DataBind();

      Response.Clear();
      Response.Buffer = true;
      Response.AddHeader("content-disposition",
      "attachment;filename=DataTable.doc");
      Response.Charset = "";
      Response.ContentType = "application/vnd.ms-word ";
      StringWriter sw = new StringWriter();
      HtmlTextWriter hw = new HtmlTextWriter(sw);
      GridView1.RenderControl(hw);
      Response.Output.Write(sw.ToString());
      Response.Flush();
      Response.End();
      }

      3. Từ công cụ CrystalReport cũng có khả năng xuất ra Word.

  18. Vũ Văn Trưởng viết:

    Thầy cho e hỏi chút. e có 1 word template trong đó có các field1,2,3……ở dạng văn bản chứ k phải dạng table. giờ e muốn xuất dữ liệu từ datagridview hoặc database thì làm như thế nào ạ. e làm theo code trên của thầy k dc ạ. Cảm ơn thầy.

  19. Than Chí viết:

    Thầy ơi xin giúp em với
    ví dụ em có file word với những thông tin để trống (giống trộn thư) lúc này trong form cũng có những thông tin tương ứng như vậy, em muốn khi click vào nút in thì những thông tin trên form sẽ tự động điền tương ứng vào các chỗ định sẵn trong word như mẫu này được không ạ

    Họ tên
    Năm sinh
    Địa chỉ
    SĐT

    thank thầy nhiều ạ

  20. Than viết:

    Thầy ơi, công cụ CrystalReport xuất ra Word theo khổ a4 thì có cần phải chỉnh sửa không, hay nó hỗ trợ xuất đúng định dạng lúc mình thiết kế report

    • Phan Tiến viết:

      Khi em thiết kế báo cáo, em sẽ chọn khổ của báo cáo là A4, A3 để thiết kế. Nhưng khi xuất có thể dữ liệu nó sẽ ra không đúng (ví dụ như bị xuống dòng hoặc dòng dài quá), lúc này em vẫn cần phải định dạng lại cho chuẩn trên phần mềm Word.

  21. Phương Nam viết:

    Chào bạn!
    Mình muốn viết phần report hiện lên kiểu thẻ học sinh, sinh viên. Giống như mình thiết kế thẻ học sinh trên word để in thành thẻ hs. Như vậy cần phải làm như thế nào, rất mong bạn hướng dẫn

  22. Ánh viết:

    Thầy ơi thầy có thể cho em xin câu lệnh sql đưa ra bái cáo xuất nhập tồn của tất cả hàng trong thời gian từ ngày đến ngày được k ạ

  23. Ngọc viết:

    Thầy ơi của e ko có report review, phải làm sao để có ạ? e dùng vs 2015

  24. hòa viết:

    Thầy ơi, cho em hỏi vd em muốn số lượng trong hàng hóa tự động cập nhập khi mua hàng và bán hàng thì làm thế nào ạ? em có bảng chi tiết HĐN và chi tiết HĐB ạ

  25. Ly viết:

    Thưa thầy nếu em cần làm báo cáo hàng hóa không bán được trong 1 tháng thì sử dụng câu lệnh nào ạ? Em cảm ơn thầy nhiều ạ

  26. Trần Huyền viết:

    Chào thầy
    Em muốn thực hiện 1 cái report hiển thị dữ liệu về kết quả thực hiện NCKH của 1 các nhân. Bao gồm dữ liệu về đề tài, sáng kiến, giáo trình, bài báo mà cá nhân đấy đã thực hiện. Report sẽ hiện thị lần lượt như sau
    I. Đề tài (Thông tin về các đề tài mà cá nhân đã thực hiện)
    II. Sáng kiến
    III. Bài báo
    IV. Giáo trình
    Em mới chỉ mới biết cách hiển thị report cho từng trường hợp riêng rẽ. Còn trường hợp tổng hợp trên 1 report như thế này thì chưa biết thiết kế như thế nào trên CrystalReport.
    Thầy có thể hướng dẫn em với không ạ! Em cảm ơn thầy nhiều!

  27. Dương viết:

    em muốn làm báo cáo file báo cáo trong ngày hôm đó đã bán được những gì thì làm sao ạ

  28. Dương viết:

    em muốn báo cáo theo tháng thì làn như thế nào thưa thầy

  29. Tăng Thành Trung viết:

    //Gọi Application.StartupPath để lấy đường dẫn tới thư mục chứa file chạy chương trình
    con.ConnectionString = @”Data Source=.\SQLEXPRESS;AttachDbFilename=” + Application.StartupPath + @”\QLBanHang.mdf;Integrated Security=True;User Instance=True”;

    Thầy ơi cho em hỏi câu lệnh + Application.StartupPath + @”\QLBanHang.mdf; (QLBanHang.mdf) là phải có file QLBanHang.mdf mới chạy được phải không thầy

  30. Phạm Nhi viết:

    cho em hỏi ngoài crystal report, ReportViewer,còn có những loại report nào mà Visual hỗ trợ ạ?

  31. bui lam viết:

    thầy cho em hỏi là lỗi này với ạ
    error CS0234: The type or namespace name ‘WinForms’ does not exist in the namespace ‘Microsoft.Reporting’ (are you missing an assembly reference?)
    e đã cài hết rồi mà vẫn báo lỗi

  32. Khắc Huynh viết:

    Thầy ơi em muốn chọn một hóa đơn nào từ bảng hóa đơn bán hàng sang report viewer thì làm như thế nào ạ.

  33. huynhvanquy viết:

    thưa thầy! phần toolbox của e hk có ReportViewer thì kiếm chỗ nào thầy :<

Để lại một bình luận