Dùng hàm Select() để lọc dữ liệu từ DataTable trong C#

Hôm nay Góc kinh Nghiệm sẽ trình bày cách dùng hàm Select() của đối tượng DataTable để lọc ra dữ liệu mong muốn. Ví dụ bên dưới sẽ dùng hàm Select() của lớp System.Data.DataTable để lọc ra tất các nhân viên có giới tính là “Nam”.

Góc Kinh Nghiệm giả sử chúng ta đã có các đối tượng sau:

  • Form chính tên FormSelectData
  • Đối tượng DataGridView tên grvData
  • Đối tượng Button tên btnSelect và sự kiện khi click chuột lên nút btnSelect là btnSelect_Click()
  • Đối tượng DataTable tên data dùng để chứa thông tin nhân viên, đối tượng data có 3 cột: mã nhân viên, tên nhân viên, giới tính

Cách thực hiện như sau:

  • Bước 1: Khởi tạo 3 nhân viên & hiển thị 3 nhân viên đó lên grvData
  • Bước 2: Khi nhấn nút “Lọc dữ liệu”, chương trình sẽ gọi sự kiện btnSelect_Click(), và sự kiện btnSelect_Click() sẽ gọi hàm SelectData().
  • Bước 3: Khi gọi hàm SelectData() ở bước 2, chuỗi điều kiện lọc được tạo ra như sau:
// Lọc ra các nhân viên nam
string filterExpression = "";
filterExpression = "GioiTinh ='Nam'";

Sau đó dùng hàm Select để lọc ra dữ liệu:

DataRow[] rows = pData.Select(filterExpression);

Dữ liệu sau khi lọc sẽ trả về một mãng các dòng đối tượng là DataRow

  • Bước 4: Cuối cùng là hiển thị dữ liệu đã được lọc ra lên đối tượng grvData

Dưới đây là đoạn code mình họa:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MyProject
{
   public partial class FormSelectData : Form
   {
      public FormSelectData()
      {
         InitializeComponent();
      }

      private void FormSelectData_Load(object sender, EventArgs e)
      {
         // Bước 1
         // Tạo ra 3 nhân viên cho đối tượng DataGridView tên grvData
         // Tạo đối tượng DataTable tên data
         DataTable data = new DataTable();

         // Đối tượng data có 3 cột: Mã nhân viên, tên nhân viên và giới tính
         data.Columns.Add("MaNhanVien", typeof(string));
         data.Columns.Add("TenNhanVien", typeof(string));
         data.Columns.Add("GioiTinh", typeof(string));

         // Khởi tạo 3 nhân viên cho đối tượng data
         // Nhân viên 1
         DataRow empployee1 = data.NewRow();
         empployee1["MaNhanVien"] = "NV01";
         empployee1["TenNhanVien"] = "Nguyễn Khánh Hưng";
         empployee1["GioiTinh"] = "Nam";
         data.Rows.Add(empployee1);

         // Nhân viên 2
         DataRow empployee2 = data.NewRow();
         empployee2["MaNhanVien"] = "NV02";
         empployee2["TenNhanVien"] = "Đoàn Thanh Thúy";
         empployee2["GioiTinh"] = "Nữ";
         data.Rows.Add(empployee2);

         // Nhân viên 3
         DataRow empployee3 = data.NewRow();
         empployee3["MaNhanVien"] = "NV03";
         empployee3["TenNhanVien"] = "Trần Xuân Vũ";
         empployee3["GioiTinh"] = "Nam";
         data.Rows.Add(empployee3);

         // Hiển thị dữ liệu lên DataGridVidew
         grvData.DataSource = data;
      }

      private void btnSelect_Click(object sender, EventArgs e)
      {
         // Bước 2
         SelectData((DataTable)grvData.DataSource);
      }

      private void SelectData(DataTable pData)
      {
         // Bước 3
         // Lọc ra các nhân viên nam
         string filterExpression = "";
         filterExpression = "GioiTinh ='Nam'";
         DataRow[] rows = pData.Select(filterExpression);

         // Bước 4
         // Hiển thị dữ liệu đã được lọc ra
         pData = ((DataTable)grvData.DataSource).Clone();
         for (int i = 0; i < rows.Length; i++)
         {
            DataRow row = pData.NewRow();
            row[0] = rows[i].ItemArray[0].ToString();
            row[1] = rows[i].ItemArray[1].ToString();
            row[2] = rows[i].ItemArray[2].ToString();
            pData.Rows.Add(row);
         }
         grvData.DataSource = pData;
      }
   }
}

Kết quả khi chạy chương trình:

Sau đó nhấn nút “Lọc dữ liệu” -> sẽ được kết quả bên dưới:

Mở rộng:

Ngoài ra, bạn có thể sử dụng các điều kiện lọc tương tự như SQL để làm điều kiện lọc. Như thế sẽ làm cho việc lọc dữ liệu của bạn thêm phong phú. Góc Kinh Nghiệm đưa ra một vài điều kiện lọc mở rộng bên dưới để bạn có thể tham khảo:

  • “GioiTinh=’Nam’ AND MaNhanVien=’NV01’” -> kết quả trả về là chỉ có một nhân viên tên “Nguyễn Khánh Hưng”;
  • “MaNhanVien in (‘NV01’,’NV02’)” -> Kết quả trả về là 2 nhân viên tên “Nguyễn Khánh Hưng” & “Đoàn Thanh Thúy”
  • “MaNhanVien in (‘NV01’,’NV02’) AND GioiTinh=’Nữ’” -> Kết quả trả về là 1 nhân viên tên “Đoàn Thanh Thúy”

Góc Kinh Nghiệm lưu ý một số điểm sau:

  • Điều kiện lọc tương tự như SQL, nếu bạn biết SQL thì đây là một lợi thế rất lớn cho bạn
  • Đối với kiểu dữ liệu chữ sẽ có cặp dấu nháy đơn bao bọc ví dụ ‘NV01’
  • Đối với dữ liệu sô ví dụ như tuổi thì không có dấu nháy đơn bao bọc.

Góc Kinh Nghiệm chúc các bạn thành công!  :lol:

 


26 comments

  1. cho mình hỏi,mún truy vấn trực tiếp từ 1 datatable trong 1 dataset dc ko,chẳng hạn mình có 1 datatable gồm mã sản phẩm,số lượng bán,số lượng khuyến mãi,thành tiền.sau khi mình add dữ liệu vào datatable để hiển thị ra datagirdview,sẽ có 1 số dòng trong datagridview bị trùng mã sản phẩm.mình mún select distnict masp ,sum các cột mà có mã sản phẩm trùng nhau để đưa vào Database.bạn có thể hướng dẫn mình đôi chút ko.thanks bạn

    1. Hàm Select() ở đây giống như một điều kiện where trong SQL, nên không dùng được select distnict masp ,sum

      Nếu như bạn dùng Linq, RIA serivce thì bạn mới có thể giải quyết vấn đề của bạn nêu ra được. Bạn cho mình hỏi, bạn đang sử dụng Visual Studio mấy vậy?

    1. uhm, chính xác là bạn đang dùng Linq. Linq hỗ trợ rất mạnh và đa dạng, và cho phép thao tác giống như sql, nhưng khác về cú pháp.

  2. bạn ơi,vd mình mún add từng row vào 1 datatable để hiển thị trên datagridview,dữ liệu của từng rows mình lấy từ textbox or combobox.cứ mỗi lần bấm button add thì sẽ cập nhật từng row vào datatable.datatable sẽ tự động cập nhật từng row và thể hiện từng rows đó trên datagridview.minh code như thế này nhưng mỗi lần bấm button add thì datagirdview chi hiển thị dc 1 dòng thui,ko hiển thì dc nhìu dòng,

    public void xuli()
    {
    string ma = textBox1.Text;
    DataSet ds = new DataSet();
    DataTable dt = new DataTable();
    dt = ds.Tables.Add(“table”);
    dt.Columns.Add(“MaSanPham”, typeof(string));
    DataRow dr;
    dr = dt.NewRow();
    dr[“MaSanPham”] = ma;
    dt.Rows.Add(dr);

    dataGridView1.DataSource = ds;
    dataGridView1.DataMember = “table”;
    }

    private void button1_Click(object sender, EventArgs e)
    {
    xuli();
    }

    1. Bạn phải chép các dòng code bên dưới ra khỏi hàm xuli():
      DataSet ds = new DataSet();
      DataTable dt = new DataTable();
      dt = ds.Tables.Add(“table”);
      dt.Columns.Add(“MaSanPham”, typeof(string));

      Vì mỗi lần bạn gọi sự kiện button1_Click(), như code bạn gửi, nó sẽ khởi tạo lại đối tượng DataSet & DataTable, nên bạn chỉ thấy được dữ liệu 1 row sau cùng mà thôi.

      Tốt nhất bạn khai báo ở sự kiện form_load, để 2 đối tượng trên chỉ tạo ra một lần đầu tiên thôi. Đặc biệt không để trong sự kiện button1_Click()

  3. bạn ơi mình có 1 datagridview mình mún kiểm tra mỗi lần nhập vào datagridview từ textbox thì nó sẽ kiểm tra dữ liệu đó đã tồn tại chưa.but mà nó chỉ kiểm tra dc đúng dòng đầu tiên thui,bạn xem dùm mình nhé

    public void kiemtradulieu()
    {
    if (dataGridView2.Rows.Count-1 == 0)
    {
    dataGridView2.Rows.Add(textBox1.Text);
    }
    else
    {
    string ma = textBox1.Text;
    int count = 0;
    for (int i = 0; i < dataGridView1.Rows.Count ; i++)
    {
    count += i;
    string macu = dataGridView2.Rows[count].Cells[0].Value.ToString();
    if (string.Equals(ma, macu) == false)
    {
    dataGridView2.Rows.Add(ma);
    }
    else
    MessageBox.Show("đã trùng");
    }

    }

    }

    }

    1. Do biến count của bạn làm bỏ xót một số row. Giả sử biến i có giá trị từ 1 đến 4, Góc Kinh Nghiệm sẽ chạy bằng tay cho bạn như sau:

      i =0; count = 0;
      i = 1; count = count + i = 1 + 0 = 1;
      i = 2; count = count + i = 1 + 2 = 3;
      i = 3; count = count + i = 3 + 3 = 6;
      i = 4; count = count + i = 6 + 4 = 10;
      …..

      Bạn thấy đấy Góc Kinh Nghiệm chỉ chạy từ i từ 1 đến 4 thôi vòng lặp for của bạn đã bỏ qua các row có index 2,4,5,8,9. Chưa kể nếu biết count < dataGridView1.Rows.Count - 1 => chương trình của bạn xuất hiện exception (lỗi)

  4. nhưng mình sửa trong vòng lặp count = i vẫn ko kiểm tra dc tất cả các row,chỉ kiểm tra dc 1 vòng đầu tiên thui,hix.vậy bạn có thể chỉ mình sữa lại đoạn code đó ko,hay dùng cách nào tiện nhất để làm việc này,thanks

  5. Cho mình hỏi cái này tí

    Trên 1 form có 2 cái DataGrid ( Phieu Xuất & Chi Tiết Phiếu Xuất) nếu nhấp vào phiếu xuất với mã 001 thì ở dưới Chi tiết Phiếu xuất hiện toàn bộ mã 001. Giúp mình nhé các bác

    1. Bạn có thể làm theo nhiều cách khác nhau:
      Cách 1: Load hết dữ liệu 2 grid, đối với grid C.Tiết P.Xuất thì bạn dùng một table nguồn, sau đó mỗi lần list lên item trên Phiếu Xuất bạn chỉ cần select table nguồn theo mã phiếu xuất.
      Cách 2: Mỗi lần bạn click lên item P.Xuất thì xuống database query dữ liệu về
      … (còn một số cách nữa)

      Mỗi cách có ưu/ nhược điểm riêng, tùy bạn chọn cách nào mà thôi.

  6. bạn ơi mình có 1 datagridview mình mún kiểm tra mỗi lần nhập vào datagridview từ textbox thì nó sẽ kiểm tra dữ liệu đó đã tồn tại chưa.but mà nó chỉ kiểm tra dc đúng dòng đầu tiên thui,bạn xem dùm mình nhé

    public void kiemtradulieu()
    {
    if (dataGridView2.Rows.Count-1 == 0)
    {
    dataGridView2.Rows.Add(textBox1.Text);
    }
    else
    {
    string ma = textBox1.Text;
    int count = 0;
    for (int i = 0; i < dataGridView1.Rows.Count ; i++)
    {
    count += i;
    string macu = dataGridView2.Rows[count].Cells[0].Value.ToString();
    if (string.Equals(ma, macu) == false)
    {
    dataGridView2.Rows.Add(ma);
    }
    else
    MessageBox.Show("đã trùng");
    }

    }

    }
    }
    ================================================
    cai nay cua ban co the sua nhu sau
    bool kiemtra(string [] mang1,string []mang2)
    {
    if(mang1==mang2)
    return false;
    else
    return true;
    }

    void nhap()
    {
    string []mang1="",[]mang2="";
    mang1[0]=txttextbox1.text;
    for(int i=0;i<DataGridview.Rowns.Count-1;++i)
    {
    mang2[i]=DataGridview[0,i].Value.ToString();
    }
    for(int i=0;i<mang2.Lenght;++i)
    {
    if(Kiemtra(mang1[0],mang2[i])==false)
    {
    MessageBox.Show("Trung Ma","Thong Bao");
    }
    else
    {
    dataGridView.Rows.Add(mang1[0]);
    }
    }
    }

    ============================
    Ban tham Khao nha !
    Co gi sai thi thong Cam vi Minh Viet Truc Tiep Trong Comment Chua Test Thu nen ko Biet Co Dung ko nua.

  7. Chào các bạn. Mình cũng đang mắc cái này. Nhưng mình muốn lọc dữ liệu theo Tháng. Mình dùng lệnh like để truy vấn tháng. Nhưng gặp cái lỗi là chẳng hạn tìm dữ liệu tháng 7 thì cả ngày 7/6/2011,7/5/2011…..
    cũng hiện ra. xem hộ code cho mình nhé. Thanhk :
    public void rfmtm()
    {
    try
    {
    textBox9.Text = textBox5.Text + “/”;
    textBox10.Text = “/” + textBox7.Text;
    DataTable tblDoUong = new DataTable(“matd”);
    Dataconn();
    OleDbCommand command = new OleDbCommand();
    command.Connection = con;
    command.CommandText = “select MaHD,TongTien from matd where tg like (‘%” + textBox9.Text + “%’)AND(‘%” + textBox10.Text + “%’)”;
    OleDbDataAdapter adapter = new OleDbDataAdapter(command);
    adapter.Fill(tblDoUong);
    dataGridView1.DataSource = tblDoUong;

    }
    catch (Exception tb)
    {
    MessageBox.Show(“Không Tìm thấy!”);
    MessageBox.Show(“” + tb.Message);
    }

    1. bạn dùng hàm month trong biểu thức điều kiện của where như sau

      where month(tg) = 7 (với 7 là tháng bạn nhập từ textbox)

  8. Chào bạn!! cách của bạn rất hay!!
    Bâyh mình có 1 trường hợp thế này.
    Là mình ko muốn lọc dự liệu đó. Mình có 1 cái textbox, khi mình nhập cái mã NV đó vào thì mình muốn còn trỏ trong cái datagridview đó né sẽ tự nhảy đến vị trí của cái mã mình đã nhập vào đó!! Trường hợp Datagirdview đó có rất nhiều dòng!!! Mình sẽ làm ntn??

    1. tìm giá trị của textbox tương ứng với giá trị trên datagridview, rồi trả về số index, cuối cùng dùng datagirdview.Rows[index].Selected = true;

  9. Chào các bạn, mình k biết cách giá trị của một bảng trong database để hiển thị lên một textbox, bạn nào biết chỉ mình với, thanks

  10. minh muon thong ke so lan xuat hien 1 san pham 1 cot trong datagridview, roi xuat ra label, ai biet chi minh voi

  11. ban ơi giải thích cụ thể hộ mình từng dòng code này với với’
    for (int i = 0; i < rows.Length; i++)
    {
    DataRow row = pData.NewRow();
    row[0] = rows[i].ItemArray[0].ToString();
    row[1] = rows[i].ItemArray[1].ToString();
    row[2] = rows[i].ItemArray[2].ToString();
    pData.Rows.Add(row);
    }

  12. chào bạn mình có yêu cầu này mong được giúp đỡ.mình muốn dữ lại nhưng nhân viên đã bị lọc đi qua một datadridview khác thì làm sao ạ
    -cụ thể là nếu bạn lọc giới tính nam thì
    +datagridview thứ nhất sẽ dữ lại những người giới tính nam
    +còn datagirdview hai sẽ hiện những người nữ

  13. bạn ơi cho mình hỏi lọc dl như vậy nhưng bạn có thể chuyển code sang vb.net được ko? mình ko xài được c#

Leave a Reply

Your email address will not be published. Required fields are marked *