Xây dựng chương trình quản lý bán hàng bằng C#


Nội dung

Giới thiệu

Với sự ra đời của .Net và Visual Studio của Microsoft, việc xây dựng một chương trình quản lý với cơ sở dữ liệu đã đơn giản hơn rất nhiều. Bài này hướng dẫn bạn cách tạo ứng dụng quản lý bán hàng lưu niệm sử dụng ngôn ngữ lập trình C# và hệ quản trị cơ sở dữ liệu SQL Server.

1. Yêu cầu

Xây dựng chương trình quản lý cửa hàng Bán hàng lưu niệm sư dụng ngôn ngữ C# và hệ quản trị cơ sở dữ liệu SQL Server. Hệ thống có các chức năng cơ bản như quản lý mặt hàng, quản lý khách hàng, quản lý hoá đơn bán. Cửa hàng có thể có một hoặc nhiều người bán, với mỗi hoá đơn bán hàng phải có thông tin của người bán cho khách hàng cụ thể.

2. Thiết kế cơ sở dữ liệu

a) Tạo ứng dụng mới

– Tên project: QuanLyBanHang

b) Tạo cơ sở dữ liệu

– Trong cửa sổ  Solution Explorer, nháy phải chuột lên tên ứng dụng, chọn Add ->New Item… Chọn Data -> Service-based Database (hoặc SQL Database trong Visual Studio Net 2005).

– Đặt tên cơ sở dữ liệu: Quanlybanhang.mdf

qlbh1

– Tạo các bảng: Trong cửa sổ Server Explorer, chọn cơ sở dữ liệu, nháy phải lên Tables, chọn Add New Table…

Bảng tblChatlieu (chất liệu)

tblchatlieu

Bảng tblKhach (khách)

tblkhach

Bảng tblHang (hàng)

tblhang

Bảng tblNhanvien (nhân viên)

tblnhanvien

Bảng tblHDBan (hoá đơn bán)

tblhoadonban

Bảng tblChitietHDBan (chi tiết hoá đơn bán)

tblcthdb

Quan hệ giữa các bảng (Relationship)

quanhebang

Một số chú ý

– Để cho phép người dùng sửa đổi thông tin của các bảng, thực hiện như sau:

Vào Tools -> Options, chọn Database Tools ->Table and Database Designers, bỏ dấu chọn ở mục Prevent saving changes that require table re-creation.

– Xoá bản sao cơ sở dữ liệu: trong cửa sổ Solution Explorer, nháy phải lên file dữ liệu (Quanlybanhang.mdf), chọn Exclude From Project

– Sao chép file dữ liệu (Quanlybanhang.mdf) vào thư mục bin\Debug (chứa file Quanlybanhang.exe) (phải đóng project trước khi thực hiện sao chép file dữ liệu).

– Thực hiện kết nối dữ liệu:

Trong Server Explorer, nháy phải Data Connections, chọn Add Connection, chọn Microsoft SQL Server Database File, nhấn Continue. Trong hộp thoại Add Connection, nhấn Browse tìm file dữ liệu (Quanlybanhang.mdf) (đã sao chép vào thư mục bin\Debug). Nhấn Test Connection, nếu thành công sẽ xuất hiện thông báo “Test connection succeeded”.

– Sao lưu dữ liệu (Quanlybanhang.mdf) bằng cách sao chép file dữ liệu này vào thư mục chứa các file mã nguồn (*.cs) của project.

– Nên tạo thư mục chứa ảnh: nháy phải lên tên project Quanlybanhang, chọn Add, chọn New Folder, đặt tên thư mục là Images. Nháy phải lên thư mục Images, chọn Add, chọn Existing Item và duyệt chọn các file ảnh, nhấn Add để thêm vào thư mục Images.

3. Thiết kế giao diện

a) Form chính

– Tên form: frmMain

 frmchinh

Các thành phần của menu

Name Text
mnuFile Tập tin
mnuThoat     Thoát
mnuDanhmuc Danh mục
mnuChatlieu      Chất liệu
mnuNhanvien      Nhân viên
mnuKhachhang      Khách hàng
mnuHanghoa      Hàng hoá
mnuHoadon Hoá đơn
mnuHoadonban      Hoá đơn bán
mnuTimkiem Tìm kiếm
mnuFindHoadon      Hoá đơn
mnuFindHang      Hàng
mnuFindKhachhang      Khách hàng
mnuBaocao Báo cáo
mnuBCHangton      Hàng tồn
mnuBCDoanhthu      Doanh thu
mnuTrogiup Trợ giúp
mnuHientrogiup      Trợ giúp
 mnuVainet      Vài nét

b) Form Danh mục chất liệu

 Tên form: frmDMChatlieu

 frmdanhmuc

Các thành phần trên form:

Điều khiển Name Text
TextBox txtMachatlieu
txtTenchatlieu
Button btnThem Thêm
btnXoa Xoá
btnSua Sửa
btnLuu Lưu
btnBoqua Bỏ qua
btnDong Đóng
DataGridView DataGridView

c) Form Danh mục nhân viên

 Tên form: frmDMNhanvien

frmdanhmucnv

Các thành phần trên form:

Điều khiển Name Text
TextBox txtManhanvien
txtTennhanvien
txtDiachi
Button btnThem, btnXoa, btnSua, btnLuu, btnBoqua, btnDong
CheckBox chkGioitinh Nam
MaskedTextBox mskDienthoai Mask: Phone Number
mskNgaysinh Mask: Short Date
DataGridView DataGridView

d) Form Danh mục khách hàng

 Tên form: frmDMKhachhang

frmdanhmuckh

Các thành phần trên form:

Điều khiển Name Text
TextBox txtMakhach
txtTenkhach
txtDiachi
Button btnThem, btnXoa, btnSua, btnLuu, btnBoqua, btnDong
CheckBox chkGioitinh Nam
MaskedTextBox mskDienthoai Mask: Phone Number
DataGridView DataGridView

e) Form Danh mục hàng hoá

 Tên form: frmDMHang

frmdanhmuchh

Các thành phần trên form

Điều khiển Name
TextBox txtMahang, txtTenhang, txtSoluong,  txtDongianhap, txtDongiaban, txtAnh,  txtGhichu
ComboBox cboMachatlieu
PictureBox picAnh (thuộc tính SizeMode = Zoom)
DataGridView DataGridView
Button btnThem, btnXoa, btnSua, btnLuu, btnBoqua,

btnTimkiem, btnHienthi, btnDong, btnOpen

f) Form Hoá đơn bán hàng

 Tên form: frmHoadonBan

frmhoadonbh

Các thành phần trên form

Điều khiển Name Text
Label lblBangchu Bằng chữ:
TextBox txtMaHDBan, txtNgayban, txtTennhanvien,txtTenkhach, txtDiachi, txtDienthoai, txtTongtien, txtTenhang, txtDongiaban, txtSoluong, txtGiamgia, txtThanhtien.
ComboBox cboManhanvien, cboMakhach, cboMahang, cboMaHDBan.
DataGridView DataGridView
Button btnNgay, btnThemmoi, btnLuu, btnXoa, btnInhoadon,

btnDong,  btnTimkiem

g) Form Tìm kiếm hoá đơn

 Tên form: frmTimHDBan

frmtkhd

Các thành phần trên form

Điều khiển Name
TextBox txtMaHDBan, txtThang, txtNam, txtManhanvien,

txtMakhach, txtTongtien.

DataGridView DataGridView
Button btnTimkiem, btnTimlai, btnDong

 

Chú ý:

– Tất cả các form (trừ frmMain), thuộc tính StartPostion = CenterParent, ShowInTaskbar = False

4. Xử lý sự kiện

4.1. Lớp Functions

– Chứa các phương thức dùng chung

– Trong khung Solution Explorer, nháy phải lên tên project, chọn Add -> New Folder, đặt tên thư mục là Class

– Nháy phải thư mục Class, nháy phải chọn Add -> Class, đặt tên Functions.cs

– Trong class Functions:

+ Khai báo bổ sung các thư viện:


using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;     // Sử dụng đối tượng MessageBox

+ Viết 2 phương thức: connect() và disconnect()


namespace QuanLyBanHang.Class
{
    class Functions
    {
        public static SqlConnection Con;  //Khai báo đối tượng kết nối        

        public static void Connect()
        {
            Con = new SqlConnection();   //Khởi tạo đối tượng
            Con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=" + Application.StartupPath + @"\Quanlybanhang.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
            Con.Open();                  //Mở kết nối
            //Kiểm tra kết nối
            if (Con.State == ConnectionState.Open)
                MessageBox.Show("Kết nối thành công");
            else MessageBox.Show("Không thể kết nối với dữ liệu");

        }
        public static void Disconnect()
        {
            if (Con.State == ConnectionState.Open)
            {
                Con.Close();   	//Đóng kết nối
                Con.Dispose(); 	//Giải phóng tài nguyên
                Con = null;
            }
        }
}

4.2. Form frmMain

a) Sự kiện frmMain_Load


private void frmMain_Load(object sender, EventArgs e)
        {
            Class.Functions.Connect(); //Mở kết nối
        }

b) Sự kiện mnuThoat_Click


private void mnuThoat_Click(object sender, EventArgs e)
        {
            Class.Functions.Disconnect(); //Đóng kết nối
            Application.Exit(); //Thoát
        }

c) Hiển thị các form khác

Cú pháp:

<Tên lớp form> <Tên đối tượng> = new <Tên lớp form>(); //Khởi tạo đối tượng

<Tên đối tượng>.ShowDialog(); //Hiển thị dưới dạng hộp thoại

Hoặc <Tên đối tượng>.Show(); //Hiện thị dạng thông thường

+ Hiển thị form frmChatlieu


private void mnuChatlieu_Click(object sender, EventArgs e)
        {
            frmDMChatlieu frmChatlieu = new frmDMChatlieu(); //Khởi tạo đối tượng
            frmChatlieu.ShowDialog(); //Hiển thị
        }

4.3. Form Chất liệu

a) Khai báo

– Khai báo


using System.Data.SqlClient; //Sử dụng thư viện để làm việc SQL server
using QuanLyBanHang.Class; //Sử dụng class Functions.cs

– Khai báo biến toàn cục


DataTable tblCL; //Chứa dữ liệu bảng Chất liệu

b) Sự kiện frmDMChatlieu_Load


private void frmDMChatlieu_Load(object sender, EventArgs e)
        {
            txtMachatlieu.Enabled = false;
            btnLuu.Enabled = false;
            btnBoqua.Enabled = false;
            LoadDataGridView(); //Hiển thị bảng tblChatlieu
        }

Trong đó, phương thức LoadDataGridView có tác dụng lấy dữ liệu từ bảng tblChatlieu đổ vào DataGridView

c) Phương thức LoadDataGridView


private void LoadDataGridView()
        {
            string sql;
            sql = "SELECT Machatlieu, Tenchatlieu FROM tblChatlieu";
            tblCL = Class.Functions.GetDataToTable(sql); //Đọc dữ liệu từ bảng
            DataGridView.DataSource = tblCL; //Nguồn dữ liệu            
            DataGridView.Columns[0].HeaderText = "Mã chất liệu";
            DataGridView.Columns[1].HeaderText = "Mã chất liệu";
            DataGridView.Columns[0].Width = 100;
            DataGridView.Columns[1].Width = 300;
            DataGridView.AllowUserToAddRows = false; //Không cho người dùng thêm dữ liệu trực tiếp
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically; //Không cho sửa dữ liệu trực tiếp
        }

Với GetDataToTable được viết trong lớp Functions có tác dụng thực hiện câu lệnh SQL truy vấn dữ liệu từ CSDL đổ vào đối tượng bảng.

d) Phương thức GetDataToTable

Mở cửa sổ lớp Class Functions viết mã lệnh như sau:


//Lấy dữ liệu vào bảng
        public static DataTable GetDataToTable(string sql)
        {
            SqlDataAdapter MyData = new SqlDataAdapter(); //Định nghĩa đối tượng thuộc lớp SqlDataAdapter
            //Tạo đối tượng thuộc lớp SqlCommand
            MyData.SelectCommand = new SqlCommand();
            MyData.SelectCommand.Connection = Functions.Con; //Kết nối cơ sở dữ liệu
            MyData.SelectCommand.CommandText = sql; //Lệnh SQL
            //Khai báo đối tượng table thuộc lớp DataTable
            DataTable table = new DataTable();
            MyData.Fill(table);
            return table;
        }

Hoặc có thể thực hiện ngắn gọn bằng cách gán tham số khi khai báo đối tượng như sau:


//Lấy dữ liệu vào bảng
        public static DataTable GetDataToTable(string sql)
        {
            SqlDataAdapter MyData = new SqlDataAdapter(sql, Con); //Định nghĩa đối tượng thuộc lớp SqlDataAdapter
            //Khai báo đối tượng table thuộc lớp DataTable
            DataTable table = new DataTable();
            MyData.Fill(table); //Đổ kết quả từ câu lệnh sql vào table
            return table;
        }

e) Phương thức dataGridView_Click

Phương thức này có tác dụng lấy nội dung dòng dữ liệu người dùng chọn trong lưới DataGridView và hiển thị lên các điều khiển trên Form.


private void dataGridView_Click(object sender, EventArgs e)
        {
            if (btnThem.Enabled == false)
            {
                MessageBox.Show("Đang ở chế độ thêm mới!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMachatlieu.Focus();
                return;
            }
            if (tblCL.Rows.Count == 0) //Nếu không có dữ liệu
            {
                MessageBox.Show("Không có dữ liệu!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            txtMachatlieu.Text = DataGridView.CurrentRow.Cells["Machatlieu"].Value.ToString();
            txtTenchatlieu.Text = DataGridView.CurrentRow.Cells["Tenchatlieu"].Value.ToString();
            btnSua.Enabled = true;
            btnXoa.Enabled = true;
            btnBoqua.Enabled = true;
        }

f) Phương thức btnThem_Click


    private void btnThem_Click(object sender, EventArgs e)
        {
            btnSua.Enabled = false;
            btnXoa.Enabled = false;
            btnBoqua.Enabled = true;
            btnLuu.Enabled = true;
            btnThem.Enabled = true;
            btnThem.Enabled = false;
            ResetValue(); //Xoá trắng các textbox
            txtMachatlieu.Enabled = true; //cho phép nhập mới
            txtMachatlieu.Focus();
        }

Với ResetValues là phương thức của form frmDMChatlieu có tác dụng xóa hết dữ liệu trong các điều khiển trên Form.

g) Phương thức ResetValues


private void ResetValue()
        {
            txtMachatlieu.Text = "";
            txtTenchatlieu.Text = "";
        }

h) Phương thức btnLuu_Click

Phương thức này có tác dụng kiểm tra thông tin người dùng nhập vào các điều khiển trên Form trong trường hợp thêm mới và lưu các thông tin đó vào CSDL.


private void btnLuu_Click(object sender, EventArgs e)
        {
            string sql; //Lưu lệnh sql
            if (txtMachatlieu.Text.Trim().Length == 0) //Nếu chưa nhập mã chất liệu
            {
                MessageBox.Show("Bạn phải nhập mã chất liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMachatlieu.Focus();
                return;
            }
            if(txtTenchatlieu.Text.Trim().Length==0) //Nếu chưa nhập tên chất liệu
            {
                MessageBox.Show("Bạn phải nhập tên chất liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtTenchatlieu.Focus();
                return;
            }
            sql = "Select MaChatlieu From tblChatlieu where MaChatlieu=N'" + txtMachatlieu.Text.Trim() + "'";
            if (Class.Functions.CheckKey(sql))
            {
                MessageBox.Show("Mã chất liệu này đã có, bạn phải nhập mã khác", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtMachatlieu.Focus();                
                return;
            }

            sql = "INSERT INTO tblChatlieu VALUES(N'" + 
                txtMachatlieu.Text + "',N'" + txtTenchatlieu.Text +"')";
            Class.Functions.RunSQL(sql); //Thực hiện câu lệnh sql
            LoadDataGridView(); //Nạp lại DataGridView
            ResetValue();
            btnXoa.Enabled = true;
            btnThem.Enabled = true;
            btnSua.Enabled = true;
            btnBoqua.Enabled = false;
            btnLuu.Enabled = false;
            txtMachatlieu.Enabled = false;
        }

Với CheckKeyRunSQL là các phương thức được viết trong lớp Functions.

CheckKey có tác dụng kiểm tra khóa trùng, RunSQL có tác dụng thực thi các câu lệnh SQL.

i) Hàm CheckKey

Mở cửa sổ lớp Class Functions viết mã lệnh:


//Hàm kiểm tra khoá trùng
        public static bool CheckKey(string sql)
        {
            SqlDataAdapter MyData = new SqlDataAdapter(sql,Con);
            DataTable table = new DataTable();
            MyData.Fill(table);
            if (table.Rows.Count > 0)
                return true;
            else return false;
        }

j) Phương thức RunSQL

Mở cửa sổ lớp Class Functions viết mã lệnh như sau:


//Hàm thực hiện câu lệnh SQL
        public static void RunSQL(string sql)
        {
            SqlCommand cmd; //Đối tượng thuộc lớp SqlCommand
            cmd = new SqlCommand();
            cmd.Connection = Con; //Gán kết nối
            cmd.CommandText = sql; //Gán lệnh SQL
            try
            {
                cmd.ExecuteNonQuery(); //Thực hiện câu lệnh SQL
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            cmd.Dispose();//Giải phóng bộ nhớ
            cmd = null;
        }

Chú ý: Đối tượng SqlCommand có hai phương thức để thực thi câu lệnh SQL, trong đó:

  • ExecuteReader: thực thi câu lệnh SQL có dữ liệu trả về, ví dụ SELECT.
  • ExecuteNoneQuery: thực thi các câu lệnh SQL không yêu cầu trả về tập dữ liệu, ví dụ: INSERT, UPDATE, DELETE.

k) Phương thức btnSua_Click

Khi người dùng nháy chuột vào một dòng bản ghi bất kỳ trên lưới để hiển thị dữ liệu của bản ghi đó lên Form thì người dùng có thể chỉnh sửa các thông tin đó.

Phương thức btnSua_Click có tác dụng lưu các thông tin người dùng đã sửa vào CSDL.


private void btnSua_Click(object sender, EventArgs e)
        {
            string sql; //Lưu câu lệnh sql
            if (tblCL.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMachatlieu.Text == "") //nếu chưa chọn bản ghi nào
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtTenchatlieu.Text.Trim().Length==0) //nếu chưa nhập tên chất liệu
            {
                MessageBox.Show("Bạn chưa nhập tên chất liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            sql = "UPDATE tblChatlieu SET Tenchatlieu=N'" + 
                txtTenchatlieu.Text.ToString() + 
                "' WHERE Machatlieu=N'" + txtMachatlieu.Text + "'";
            Class.Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValue();

            btnBoqua.Enabled = false;
        }

l) Phương thức btnXoa_Click


private void btnXoa_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblCL.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMachatlieu.Text == "") //nếu chưa chọn bản ghi nào
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (MessageBox.Show("Bạn có muốn xoá không?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                sql = "DELETE tblChatlieu WHERE Machatlieu=N'" + txtMachatlieu.Text + "'";
                Class.Functions.RunSqlDel(sql);
                LoadDataGridView();
                ResetValue();
            }
        }

m) Phương thức RunSQLDel

Phương thức RunSQLDel tương tự như RunSQL nhưng trong trường hợp xóa dữ liệu nếu dữ liệu đang được dùng bởi một đối tượng khác thì không được phép xóa.

Mở cửa sổ lớp Class Functions viết mã lệnh như sau:


public static void RunSqlDel(string sql)
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = Functions.Con;
            cmd.CommandText = sql;
            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Dữ liệu đang được dùng, không thể xoá...", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                MessageBox.Show(ex.ToString());
            }
            cmd.Dispose();
            cmd = null;
        }

n) Phương thức btnBoqua_Click

Phương thức này được gọi khi người dùng muốn hủy bỏ các chức năng Thêm mới hoặc Sửa dữ liệu.


private void btnBoqua_Click(object sender, EventArgs e)
        {
            ResetValue();
            btnBoqua.Enabled = false;
            btnThem.Enabled = true;
            btnXoa.Enabled = true;
            btnSua.Enabled = true;
            btnLuu.Enabled = false;
            txtMachatlieu.Enabled = false;
        }

o) Phương thức dùng phím Enter thay cho phím Tab


private void txtMachatlieu_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                SendKeys.Send("{TAB}");
        }

Thực hiện tương tự cho txtTenchatlieu_KeyUp
p) Phương thức btnDong_Click


 private void btnDong_Click(object sender, EventArgs e)
        {
            this.Close();
        }

4.4. Form Danh mục Nhân viên

a) Khai báo

– Thư viện:


using System.Data;
using System.Data.SqlClient;
using QuanLyBanHang.Class;

– Biến:


DataTable tblNV; //Lưu dữ liệu bảng nhân viên

b) Phương thức frmDMNhanvien_Load


private void frmDMNhanvien_Load(object sender, EventArgs e)
        {
            txtManhanvien.Enabled = false;
            btnLuu.Enabled = false;
            btnBoqua.Enabled = false;
            LoadDataGridView();
        }

c) Phương thức LoadDataGridView – Hiển thị dữ liệu lên lưới


public void LoadDataGridView()
        {
            string sql;
            sql = "SELECT Manhanvien,Tennhanvien,Gioitinh,Diachi,Dienthoai,Ngaysinh FROm tblNhanvien";
            tblNV = Functions.GetDataToTable(sql); //lấy dữ liệu
            DataGridView.DataSource = tblNV;
            DataGridView.Columns[0].HeaderText = "Mã nhân viên";
            DataGridView.Columns[1].HeaderText = "Tên nhân viên";
            DataGridView.Columns[2].HeaderText = "Giới tính";
            DataGridView.Columns[3].HeaderText = "Địa chỉ";
            DataGridView.Columns[4].HeaderText = "Điện thoại";
            DataGridView.Columns[5].HeaderText = "Ngày sinh";
            DataGridView.Columns[0].Width = 100;
            DataGridView.Columns[1].Width = 150;
            DataGridView.Columns[2].Width = 100;
            DataGridView.Columns[3].Width = 150;
            DataGridView.Columns[4].Width = 100;
            DataGridView.Columns[5].Width = 100;
            DataGridView.AllowUserToAddRows = false;
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

d) Phương thức DataGridView_Click


private void dataGridView_Click(object sender, EventArgs e)
        {
            if (btnThem.Enabled == false)
            {
                MessageBox.Show("Đang ở chế độ thêm mới!", "Thông báo",  MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtManhanvien.Focus();
                return;
            }
            if (tblNV.Rows.Count == 0)
            {
                MessageBox.Show("Không có dữ liệu!", "Thông báo", MessageBoxButtons.OK,  MessageBoxIcon.Information);
                return;
            }
            txtManhanvien.Text = DataGridView.CurrentRow.Cells["Manhanvien"].Value.ToString();
            txtTennhanvien.Text = DataGridView.CurrentRow.Cells["Tennhanvien"].Value.ToString();
            if (DataGridView.CurrentRow.Cells["Gioitinh"].Value.ToString() == "Nam") chkGioitinh.Checked = true;
            else chkGioitinh.Checked = false;
            txtDiachi.Text = DataGridView.CurrentRow.Cells["Diachi"].Value.ToString();
            mskDienthoai.Text = DataGridView.CurrentRow.Cells["Dienthoai"].Value.ToString();
            mskNgaysinh.Text = DataGridView.CurrentRow.Cells["Ngaysinh"].Value.ToString();
            btnSua.Enabled = true;
            btnXoa.Enabled = true;
            btnXoa.Enabled = true;
        }

e) Phương thức btnThem_Click


private void btnThem_Click(object sender, EventArgs e)
        {
            btnSua.Enabled = false;
            btnXoa.Enabled = false;
            btnBoqua.Enabled = true;
            btnLuu.Enabled = true;
            btnThem.Enabled = false;
            ResetValues();
            txtManhanvien.Enabled = true;
            txtManhanvien.Focus();
        }

f) Phương thức ResetValues


private void ResetValues()
        {
            txtManhanvien.Text = "";
            txtTennhanvien.Text = "";
            chkGioitinh.Checked = false;
            txtDiachi.Text = "";
            mskNgaysinh.Text = "";
            mskDienthoai.Text = "";
        }

g) Phương thức btnLuu_Click


private void btnLuu_Click(object sender, EventArgs e)
        {
            string sql,gt;
            if (txtManhanvien.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập mã nhân viên", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtManhanvien.Focus();
                return;
            }
            if (txtTennhanvien.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên nhân viên", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtTennhanvien.Focus();
                return ;
            }
            if (txtDiachi.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập địa chỉ", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtDiachi.Focus();
                return ;
            }
            if (mskDienthoai.Text == "(   )     -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mskDienthoai.Focus();
                return ;
            }
            if (mskNgaysinh.Text == "  /  /")
            {
                MessageBox.Show("Bạn phải nhập ngày sinh", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mskNgaysinh.Focus();
                return ;
            }
            if (!Functions.IsDate(mskNgaysinh.Text))
            {
                MessageBox.Show("Bạn phải nhập lại ngày sinh", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
               // mskNgaysinh.Text = "";
                mskNgaysinh.Focus();
                return ;
            }
            if (chkGioitinh.Checked == true)
                gt = "Nam";
            else
                gt = "Nữ";
            sql = "SELECT Manhanvien FROM tblNhanvien WHERE Manhanvien=N'" + txtManhanvien.Text.Trim() + "'";
            if (Functions.CheckKey(sql))
            {
                MessageBox.Show("Mã nhân viên này đã có, bạn phải nhập mã khác", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtManhanvien.Focus();
                txtManhanvien.Text = "";
                return ;
            }
            sql = "INSERT INTO tblNhanvien(Manhanvien,Tennhanvien,Gioitinh, Diachi,Dienthoai, Ngaysinh) VALUES (N'" + txtManhanvien.Text.Trim() + "',N'" + txtTennhanvien.Text.Trim() + "',N'" + gt + "',N'" + txtDiachi.Text.Trim() + "','" + mskDienthoai.Text + "','" + Functions.ConvertDateTime(mskNgaysinh.Text) + "')";
            Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValues();
            btnXoa.Enabled = true;
            btnThem.Enabled = true;
            btnSua.Enabled = true;
            btnBoqua.Enabled = false;
            btnLuu.Enabled = false;
            txtManhanvien.Enabled = false;
        }

Với IsDateConvertDateTime là các hàm được viết trong lớp Functions

IsDate có tác dụng kiểm tra một biến có ở dạng ngày tháng không, ConvertDateTime có tác dụng đổi một chuỗi ngày tháng do người dùng nhập có dạng dd/mm/yyyy thành chuỗi ngày tháng có dạng mm/dd/yyyy để lưu vào CSDL.

h) Hàm IsDate

Soạn thảo trong lớp Functions:


public static bool IsDate(string date)
        {
            string[] elements = date.Split('/');
            if ((Convert.ToInt32(elements[0]) >= 1) && (Convert.ToInt32(elements[0]) <= 31) && (Convert.ToInt32(elements[1]) >= 1) && (Convert.ToInt32(elements[1]) <= 12) && (Convert.ToInt32(elements[2]) >= 1900))
                return true;
            else return false;
        }

i) Hàm ConvertDateTime

Soạn thảo hàm trong lớp Functions:


public static string ConvertDateTime(string date)
        {
            string[] elements = date.Split('/');
            string dt = string.Format("{0}/{1}/{2}", elements[0], elements[1], elements[2]);
            return dt;
        }

j) Phương thức btnSua_Click


private void btnSua_Click(object sender, EventArgs e)
        {
            string sql, gt;
            if (tblNV.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu!", "Thông báo", MessageBoxButtons.OK,MessageBoxIcon.Information);
                return;
            }
            if (txtManhanvien.Text == "")
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtTennhanvien.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên nhân viên", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                txtTennhanvien.Focus();
                return;
            }
            if (txtDiachi.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập địa chỉ", "Thông báo", MessageBoxButtons.OK,MessageBoxIcon.Warning);
                txtDiachi.Focus();
                return;
            }
            if (mskDienthoai.Text == "(   )     -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mskDienthoai.Focus();
                return;
            }
            if (mskNgaysinh.Text == "  /  /")
            {
                MessageBox.Show("Bạn phải nhập ngày sinh", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mskNgaysinh.Focus();
                return;
            }
            if (!Functions.IsDate(mskNgaysinh.Text))
            {
                MessageBox.Show("Bạn phải nhập lại ngày sinh", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mskNgaysinh.Text = "";
                mskNgaysinh.Focus();
                return;
            }
            if (chkGioitinh.Checked == true)
                gt = "Nam";
            else
                gt = "Nữ";
            sql = "UPDATE tblNhanvien SET  Tennhanvien=N'" +txtTennhanvien.Text.Trim().ToString() +
                    "',Diachi=N'" + txtDiachi.Text.Trim().ToString() +
                    "',Dienthoai='" + mskDienthoai.Text.ToString() + "',Gioitinh=N'" + gt +
                    "',Ngaysinh='" + Functions.ConvertDateTime(mskNgaysinh.Text) +
                    "' WHERE Manhanvien=N'" + txtManhanvien.Text + "'";
            Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValues();
            btnBoqua.Enabled = false;
        }

k) Phương thức btnXoa_Click


private void btnXoa_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblNV.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu!", "Thông báo", MessageBoxButtons.OK,MessageBoxIcon.Information);
                return;
            }
            if (txtManhanvien.Text == "")
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (MessageBox.Show("Bạn có muốn xóa không?", "Thông báo",MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                sql = "DELETE tblNhanvien WHERE Manhanvien=N'" + txtManhanvien.Text + "'";
                Functions.RunSqlDel(sql);
                LoadDataGridView();
                ResetValues();
            }
        }

l) Phương thức btnBoqua_Click


private void btnBoqua_Click(object sender, EventArgs e)
        {
            ResetValues();
            btnBoqua.Enabled = false;
            btnThem.Enabled = true;
            btnXoa.Enabled = true;
            btnSua.Enabled = true;
            btnLuu.Enabled = false;
            txtManhanvien.Enabled = false;
        }

m) Phương thức dùng phím Enter thay cho phím Tab


private void txtManhanvien_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                SendKeys.Send("{TAB}");
        }

Thực hiện tương tự cho txtTennhanvien.KeyUp, txtDiachi.KeyUp, mskDienthoai.KeyUp, mskNgaysinh.KeyUp.

n) Phương thức btnDong_Click


private void btnDong_Click(object sender, EventArgs e)
        {
            this.Close();
        }

4.5. Form Danh mục Khách hàng

a) Khai báo

– Thư viện


using System.Data;
using System.Data.SqlClient;
using Quanlybanhang.Class;  

– Biến


DataTable tblKH; //Bảng khách hàng

b) Phương thức frmDMKhachhang_Load


private void frmDMKhachhang_Load(object sender, EventArgs e)
        {
            txtMakhach.Enabled = false;
            btnLuu.Enabled = false;
            btnBoqua.Enabled = false;
            LoadDataGridView();
        }

c) Phương thức LoadDataGridView


private void LoadDataGridView()
        {
            string sql;
            sql = "SELECT * from tblKhach";
            tblKH = Functions.GetDataToTable(sql); //Lấy dữ liệu từ bảng
            DataGridView.DataSource = tblKH; //Hiển thị vào dataGridView
            DataGridView.Columns[0].HeaderText = "Mã khách";
            DataGridView.Columns[1].HeaderText = "Tên khách";
            DataGridView.Columns[2].HeaderText = "Địa chỉ";
            DataGridView.Columns[3].HeaderText = "Điện thoại";
            DataGridView.Columns[0].Width = 100;
            DataGridView.Columns[1].Width = 150;
            DataGridView.Columns[2].Width = 150;
            DataGridView.Columns[3].Width = 150;
            DataGridView.AllowUserToAddRows = false;
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

d) Phương thức DataGridView_Click


private void dataGridView_Click(object sender, EventArgs e)
        {
            if (btnThem.Enabled == false)
            {
                MessageBox.Show("Đang ở chế độ thêm mới!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMakhach.Focus();
                return;
            }
            if (tblKH.Rows.Count == 0)
            {
                MessageBox.Show("Không có dữ liệu!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            txtMakhach.Text = DataGridView.CurrentRow.Cells["Makhach"].Value.ToString();
            txtTenkhach.Text = DataGridView.CurrentRow.Cells["Tenkhach"].Value.ToString();
            txtDiachi.Text = DataGridView.CurrentRow.Cells["Diachi"].Value.ToString();
            mskDienthoai.Text = DataGridView.CurrentRow.Cells["Dienthoai"].Value.ToString();
            btnSua.Enabled = true;
            btnXoa.Enabled = true;
            btnBoqua.Enabled = true;
        }

e) Phương thức btnThem_Click


private void btnThem_Click(object sender, EventArgs e)
        {
            btnSua.Enabled = false;
            btnXoa.Enabled = false;
            btnBoqua.Enabled = true;
            btnLuu.Enabled = true;
            btnThem.Enabled = false;
            ResetValues();
            txtMakhach.Enabled = true;
            txtMakhach.Focus();
        }

f) Phương thức ResetValues


private void ResetValues()
        {
            txtMakhach.Text = "";
            txtTenkhach.Text  = "";
            txtDiachi.Text = "";
            mskDienthoai.Text = "";
        }

g) Phương thức btnLuu_Click


private void btnLuu_Click(object sender, EventArgs e)
        {
            string sql;
            if (txtMakhach.Text.Trim().Length  == 0)
            {
                MessageBox.Show("Bạn phải nhập mã khách", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMakhach.Focus();
                return;
            }
            if (txtTenkhach.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên khách", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtTenkhach.Focus();
                return;
            }
            if (txtDiachi.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập địa chỉ", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtDiachi.Focus();
                return;
            }
            if (mskDienthoai.Text == "(  )    -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                mskDienthoai.Focus();
                return;
            }
            //Kiểm tra đã tồn tại mã khách chưa
            sql = "SELECT Makhach FROM tblKhach WHERE Makhach=N'" + txtMakhach.Text.Trim() + "'";
            if (Functions.CheckKey(sql))
            {
                MessageBox.Show("Mã khách này đã tồn tại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMakhach.Focus();
                return;                
            }
            //Chèn thêm
            sql = "INSERT INTO tblKhach VALUES (N'" + txtMakhach.Text.Trim() +
                "',N'" + txtTenkhach.Text.Trim() + "',N'" + txtDiachi.Text.Trim() + "','" + mskDienthoai.Text + "')";
            Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValues();

            btnXoa.Enabled = true;
            btnThem.Enabled = true;
            btnSua.Enabled = true;
            btnBoqua.Enabled = false;
            btnLuu.Enabled = false;
            txtMakhach.Enabled = false;
        }

h) Phương thức btnSua_Click


private void btnSua_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblKH.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMakhach.Text == "")
            {
                MessageBox.Show("Bạn phải chọn bản ghi cần sửa", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtTenkhach.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên khách", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtTenkhach.Focus();
                return;
            }
            if (txtDiachi.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập địa chỉ", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtDiachi.Focus();
                return;
            }
            if (mskDienthoai.Text=="(  )    -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                mskDienthoai.Focus();
                return;
            }
            sql = "UPDATE tblKhach SET Tenkhach=N'" + txtTenkhach.Text.Trim().ToString() + "',Diachi=N'" +
                txtDiachi.Text.Trim().ToString() + "',Dienthoai='" + mskDienthoai.Text.ToString() +
                "' WHERE Makhach=N'" + txtMakhach.Text + "'";
            Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValues();
            btnBoqua.Enabled = false;
        }

i) Phương thức btnXoa_Click


private void btnXoa_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblKH.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMakhach.Text.Trim() == "")
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (MessageBox.Show("Bạn có muốn xoá bản ghi này không?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                sql = "DELETE tblKhach WHERE Makhach=N'" + txtMakhach.Text + "'";
                Functions.RunSqlDel(sql);
                LoadDataGridView();
                ResetValues();
            }
        }

j) Phương thức btnBoqua_Click


private void btnBoqua_Click(object sender, EventArgs e)
        {
            ResetValues();
            btnBoqua.Enabled = false;
            btnThem.Enabled = true;
            btnXoa.Enabled = true;
            btnSua.Enabled = true;
            btnLuu.Enabled = false;
            txtMakhach.Enabled = false;
        }

k) Phương thức dùng phím Enter thay cho phím Tab


private void txtMakhach_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                SendKeys.Send("{TAB}");
        }

l) Phương thức btnDong_Click


private void btnDong_Click(object sender, EventArgs e)
{
this.Close();
}

4.6. Form Danh mục hàng

a) Khai báo

– Thư viện


using System.Data;
using System.Data.SqlClient;
using Quanlybanhang.Class;  

– Biến


DataTable tblH; //Bảng hàng

b) Phương thức frmDMHang_Load


private void frmDMHang_Load(object sender, EventArgs e)
        {
            string sql;
            sql = "SELECT * from tblChatlieu";
            txtMahang.Enabled = false;
            btnLuu.Enabled = false;
            btnBoqua.Enabled = false;
            LoadDataGridView();
            Functions.FillCombo(sql, cboMachatlieu, "Machatlieu", "Tenchatlieu");
            cboMachatlieu.SelectedIndex = -1;
            ResetValues();
        }

Với FillCombo là một phương thức được viết trong Class Functions, có tác dụng lấy dữ liệu từ một câu lệnh SQL đổ vào một ComboBox.

c) Phương thức FillCombo

Soạn thảo trong Class Functions :


public static void FillCombo(string sql, ComboBox cbo, string ma, string ten)
        {
            SqlDataAdapter Mydata = new SqlDataAdapter(sql, Con);
            DataTable table = new DataTable();
            Mydata.Fill(table);
            cbo.DataSource = table;
            cbo.ValueMember = ma; //Trường giá trị
            cbo.DisplayMember = ten; //Trường hiển thị
        }

d) Phương thức ResetValues


private void ResetValues()
        {
            txtMahang.Text = "";
            txtTenhang.Text = "";
            cboMachatlieu.Text = "";
            txtSoluong.Text = "0";
            txtDongianhap.Text = "0";
            txtDongiaban.Text = "0";
            txtSoluong.Enabled = true ;
            txtDongianhap.Enabled = false;
            txtDongiaban.Enabled = false;
            txtAnh.Text = "";
            picAnh.Image = null;
            txtGhichu.Text = "";
        }

e) Phương thức LoadDataGridView


private void LoadDataGridView()
        {
            string sql;
            sql = "SELECT * from tblHang";
            tblH = Functions.GetDataToTable(sql);
            DataGridView.DataSource = tblH;
            DataGridView.Columns[0].HeaderText = "Mã hàng";
            DataGridView.Columns[1].HeaderText = "Tên hàng";
            DataGridView.Columns[2].HeaderText = "Chất liệu";
            DataGridView.Columns[3].HeaderText = "Số lượng";
            DataGridView.Columns[4].HeaderText = "Đơn giá nhập";
            DataGridView.Columns[5].HeaderText = "Đơn giá bán";
            DataGridView.Columns[6].HeaderText = "Ảnh";
            DataGridView.Columns[7].HeaderText = "Ghi chú";
            DataGridView.Columns[0].Width = 80;
            DataGridView.Columns[1].Width = 140;
            DataGridView.Columns[2].Width = 80;
            DataGridView.Columns[3].Width = 80;
            DataGridView.Columns[4].Width = 100;
            DataGridView.Columns[5].Width = 100;
            DataGridView.Columns[6].Width = 200;
            DataGridView.Columns[7].Width = 300;
            DataGridView.AllowUserToAddRows = false;
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

f) Phương thức DataGridView_Click


private void DataGridView_Click(object sender, EventArgs e)
        {
            string machatlieu;
            string sql;
            if (btnThem.Enabled == false)
            {
                MessageBox.Show("Đang ở chế độ thêm mới!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMahang.Focus();
                return;
            }
            if (tblH.Rows.Count == 0)
            {
                MessageBox.Show("Không có dữ liệu!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);                
                return;
            }
            txtMahang.Text = DataGridView.CurrentRow.Cells["Mahang"].Value.ToString();
            txtTenhang.Text = DataGridView.CurrentRow.Cells["Tenhang"].Value.ToString();
            machatlieu = DataGridView.CurrentRow.Cells["Machatlieu"].Value.ToString();
            sql = "SELECT Tenchatlieu FROM tblChatlieu WHERE Machatlieu=N'" + machatlieu + "'";
            cboMachatlieu.Text = Functions.GetFieldValues(sql);
            txtSoluong.Text = DataGridView.CurrentRow.Cells["Soluong"].Value.ToString();
            txtDongianhap.Text = DataGridView.CurrentRow.Cells["Dongianhap"].Value.ToString();
            txtDongiaban.Text = DataGridView.CurrentRow.Cells["Dongiaban"].Value.ToString();
            sql = "SELECT Anh FROM tblHang WHERE Mahang=N'" + txtMahang.Text + "'";
            txtAnh.Text = Functions.GetFieldValues(sql);
            picAnh.Image = Image.FromFile(txtAnh.Text);
            sql = "SELECT Ghichu FROM tblHang WHERE Mahang = N'" + txtMahang.Text + "'";
            txtGhichu.Text = Functions.GetFieldValues(sql);
            btnSua.Enabled = true;
            btnXoa.Enabled = true;
            btnBoqua.Enabled = true;
        }

Với GetFieldValues là một hàm được viết trong Class Functions, có tác dụng lấy dữ liệu từ một câu lệnh SQL.
g) Hàm GetFieldValues
Soạn thảo trong Class Functions


public static string GetFieldValues(string sql)
        {
            string ma = "";
            SqlCommand cmd = new SqlCommand(sql, Con);
            SqlDataReader reader;
            reader = cmd.ExecuteReader();
            while (reader.Read())
                ma = reader.GetValue(0).ToString();
            reader.Close();
            return ma;
        }

h) Phương thức btnThem_Click


private void btnThem_Click(object sender, EventArgs e)
        {
            btnSua.Enabled = false;
            btnXoa.Enabled = false;
            btnBoqua.Enabled = true;
            btnLuu.Enabled = true;
            btnThem.Enabled = false;
            ResetValues();
            txtMahang.Enabled = true;
            txtMahang.Focus();
            txtSoluong.Enabled = true;
            txtDongianhap.Enabled = true;
            txtDongiaban.Enabled = true;
        }

i) Phương thức btnLuu_Click


private void btnLuu_Click(object sender, EventArgs e)
        {
            string sql;
            if (txtMahang.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập mã hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMahang.Focus();
                return;
            }
            if (txtTenhang.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtTenhang.Focus();
                return;
            }
            if (cboMachatlieu.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập chất liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                cboMachatlieu.Focus();
                return;
            }
            if (txtAnh.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải chọn ảnh minh hoạ cho hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                btnOpen.Focus();
                return;
            }
            sql = "SELECT Mahang FROM tblHang WHERE Mahang=N'" + txtMahang.Text.Trim() + "'";
            if (Functions.CheckKey(sql))
            {
                MessageBox.Show("Mã hàng này đã tồn tại, bạn phải chọn mã hàng khác", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMahang.Focus();
                return;
            }
            sql = "INSERT INTO tblHang(Mahang,Tenhang,Machatlieu,Soluong,Dongianhap, Dongiaban,Anh,Ghichu) VALUES(N'" 
                + txtMahang.Text.Trim() + "',N'" + txtTenhang.Text.Trim() + 
                "',N'" + cboMachatlieu.SelectedValue.ToString() +
                "'," + txtSoluong.Text.Trim() + "," + txtDongianhap.Text + 
                "," + txtDongiaban.Text + ",'" + txtAnh.Text + "',N'" + txtGhichu.Text.Trim() + "')";
            
            Functions.RunSQL(sql);
            LoadDataGridView();
            //ResetValues();
            btnXoa.Enabled=true;
            btnThem.Enabled = true;
            btnSua.Enabled = true;
            btnBoqua.Enabled = false;
            btnLuu.Enabled = false;
            txtMahang.Enabled = false;
        }

j) Phương thức btnSua_Click


private void btnSua_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblH.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMahang.Text == "")
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtMahang.Focus();
                return;
            }
            if (txtTenhang.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập tên hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtTenhang.Focus();
                return;
            }
            if (cboMachatlieu.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải nhập chất liệu", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                cboMachatlieu.Focus();
                return;
            }
            if (txtAnh.Text.Trim().Length == 0)
            {
                MessageBox.Show("Bạn phải ảnh minh hoạ cho hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtAnh.Focus();
                return;
            }
            sql = "UPDATE tblHang SET Tenhang=N'" + txtTenhang.Text.Trim().ToString() +
                "',Machatlieu=N'" + cboMachatlieu.SelectedValue.ToString() +
                "',Soluong="+txtSoluong.Text+
                ",Anh='" + txtAnh.Text + "',Ghichu=N'" + txtGhichu.Text +"' WHERE Mahang=N'" + txtMahang.Text + "'";
            Functions.RunSQL(sql);
            LoadDataGridView();
            ResetValues();
            btnBoqua.Enabled = false;
        }

k) Phương thức btnXoa_Click


private void btnXoa_Click(object sender, EventArgs e)
        {
            string sql;
            if (tblH.Rows.Count == 0)
            {
                MessageBox.Show("Không còn dữ liệu!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (txtMahang.Text == "")
            {
                MessageBox.Show("Bạn chưa chọn bản ghi nào", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (MessageBox.Show("Bạn có muốn xoá bản ghi này không?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                sql = "DELETE tblHang WHERE Mahang=N'" + txtMahang.Text + "'";
                Functions.RunSqlDel(sql);
                LoadDataGridView();
                ResetValues();
            }
        }

l) Phương thức btnBoqua_Click


private void btnBoqua_Click(object sender, EventArgs e)
        {
            ResetValues();
            btnXoa.Enabled = true;
            btnSua.Enabled = true;
            btnThem.Enabled = true;
            btnBoqua.Enabled = false;
            btnLuu.Enabled = false;
            txtMahang.Enabled = false;
        }

m) Phương thức btnOpen_Click


private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlgOpen = new OpenFileDialog();
            dlgOpen.Filter = "Bitmap(*.bmp)|*.bmp|JPEG(*.jpg)|*.jpg|GIF(*.gif)|*.gif|All files(*.*)|*.*";
            dlgOpen.FilterIndex = 2;
            dlgOpen.Title = "Chọn ảnh minh hoạ cho sản phẩm";
            if (dlgOpen.ShowDialog() == DialogResult.OK)
            {
                picAnh.Image = Image.FromFile(dlgOpen.FileName);
                txtAnh.Text = dlgOpen.FileName;
            }
        }

n) Phương thức btnTimkiem_Click

Phương thức tìm kiếm cho phép tìm các bản ghi thỏa mãn một số điều kiện nào đấy và hiển thị kết quả tìm được vào lưới DataGridView.


private void btnTimkiem_Click(object sender, EventArgs e)
        {
            string sql;
            if ((txtMahang.Text == "") && (txtTenhang.Text == "") && (cboMachatlieu.Text == ""))
            {
                MessageBox.Show("Bạn hãy nhập điều kiện tìm kiếm", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            sql = "SELECT * from tblHang WHERE 1=1";
            if (txtMahang.Text != "")
                sql += " AND Mahang LIKE N'%" + txtMahang.Text + "%'";
            if (txtTenhang.Text != "")
                sql += " AND Tenhang LIKE N'%" + txtTenhang.Text + "%'";
            if (cboMachatlieu.Text!="")
                sql += " AND Machatlieu LIKE N'%" + cboMachatlieu.SelectedValue + "%'";
            tblH = Functions.GetDataToTable(sql);
            if (tblH.Rows.Count == 0)
                MessageBox.Show("Không có bản ghi thoả mãn điều kiện tìm kiếm!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else MessageBox.Show("Có " + tblH.Rows.Count + "  bản ghi thoả mãn điều kiện!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            DataGridView.DataSource = tblH;
            ResetValues();
        }

o) Phương thức btnHienthi_Click


private void btnHienthi_Click(object sender, EventArgs e)
        {
            string sql;
            sql = "SELECT Mahang, Tenhang,Machatlieu,Soluong,Dongianhap,Dongiaban,Anh,Ghichu FROM tblHang";
            tblH = Functions.GetDataToTable(sql);
            DataGridView.DataSource = tblH;
        }

p) Phương thức btnDong_Click


private void btnDong_Click(object sender, EventArgs e)
        {
            this.Close();
        }

4.7. Form Hóa đơn bán

a) Khai báo

Chọn menu Project/Add Reference, chọn thẻ COM hộp thoại Add Reference, chọn Microsoft Excel 14.0 Object Library, nhấn OK.

frmkb

– Thư viện


using System.Data.SqlClient;
using QuanLyBanHang.Class;
using COMExcel = Microsoft.Office.Interop.Excel;

– Biến


DataTable tblCTHDB; //Bảng chi tiết hoá đơn bán

b) Phương thức frmHoadonBan_Load


private void frmHoadonBan_Load(object sender, EventArgs e)
        {
            btnThemmoi.Enabled = true;
            btnLuu.Enabled = false;
            btnXoa.Enabled = false;
            btnInhoadon.Enabled = false;
            txtMaHDBan.ReadOnly = true;
            txtTennhanvien.ReadOnly = true;
            txtTenkhach.ReadOnly = true;
            txtDiachi.ReadOnly = true;
            txtDienthoai.ReadOnly = true;
            txtTenhang.ReadOnly = true;
            txtDongiaban.ReadOnly = true;
            txtThanhtien.ReadOnly = true;
            txtTongtien.ReadOnly = true;
            txtGiamgia.Text = "0";
            txtTongtien.Text = "0";
            Functions.FillCombo("SELECT Makhach, Tenkhach FROM tblKhach", cboMakhach,"Makhach", "Makhach");
            cboMakhach.SelectedIndex = -1;
            Functions.FillCombo("SELECT Manhanvien, Tennhanvien FROM tblNhanvien",cboManhanvien, "Manhanvien", "Tenkhach");
            cboManhanvien.SelectedIndex = -1;
            Functions.FillCombo("SELECT Mahang, Tenhang FROM tblHang", cboMahang,"Mahang", "Mahang");
            cboMahang.SelectedIndex = -1;
            //Hiển thị thông tin của một hóa đơn được gọi từ form tìm kiếm
            if (txtMaHDBan.Text != "")
            {
                LoadInfoHoadon();
                btnXoa.Enabled = true;
                btnInhoadon.Enabled = true;
            }
            LoadDataGridView();
        }

c) Phương thức LoadDataGridView


private void LoadDataGridView()
        {
            string sql;
            sql = "SELECT a.Mahang, b.Tenhang, a.Soluong, b.Dongiaban, a.Giamgia,a.Thanhtien FROM tblChitietHDBan AS a, tblHang AS b WHERE a.MaHDBan = N'" + txtMaHDBan.Text + "' AND a.Mahang=b.Mahang";
            tblCTHDB = Functions.GetDataToTable(sql);
            DataGridView.DataSource = tblCTHDB;
            DataGridView.Columns[0].HeaderText = "Mã hàng";
            DataGridView.Columns[1].HeaderText = "Tên hàng";
            DataGridView.Columns[2].HeaderText = "Số lượng";
            DataGridView.Columns[3].HeaderText = "Đơn giá";
            DataGridView.Columns[4].HeaderText = "Giảm giá %";
            DataGridView.Columns[5].HeaderText = "Thành tiền";
            DataGridView.Columns[0].Width = 80;
            DataGridView.Columns[1].Width = 130;
            DataGridView.Columns[2].Width = 80;
            DataGridView.Columns[3].Width = 90;
            DataGridView.Columns[4].Width = 90;
            DataGridView.Columns[5].Width = 90;
            DataGridView.AllowUserToAddRows = false;
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

d) Phương thức LoadInfoHoadon()


private void LoadInfoHoadon()
        {
            string str;
            str = "SELECT Ngayban FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
            txtNgayban.Text = Functions.ConvertDateTime(Functions.GetFieldValues(str));
            str = "SELECT Manhanvien FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
            cboManhanvien.Text = Functions.GetFieldValues(str);
            str = "SELECT Makhach FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
            cboMakhach.Text = Functions.GetFieldValues(str);
            str = "SELECT Tongtien FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
            txtTongtien.Text = Functions.GetFieldValues(str);
            lblBangchu.Text = "Bằng chữ: " + Functions.ChuyenSoSangChu(txtTongtien.Text);
        }

e) Phương thức btnThemmoi_Click


private void btnThemmoi_Click(object sender, EventArgs e)
        {
            btnXoa.Enabled = false;
            btnLuu.Enabled = true;
            btnInhoadon.Enabled = false;
            btnThemmoi.Enabled = false;
            ResetValues();
            txtMaHDBan.Text = Functions.CreateKey("HDB");
            LoadDataGridView();
        }

Với CreateKey là một hàm được viết trong Class Functions, có tác dụng sinh khóa tự động cho Mã hóa đơn bán.

f) Hàm CreateKey

Soạn thảo trong Class Functions:


//Hàm tạo khóa có dạng: TientoNgaythangnam_giophutgiay
        public static string CreateKey(string tiento)
        {
            string key = tiento;
            string[] partsDay;
            partsDay = DateTime.Now.ToShortDateString().Split('/');
            //Ví dụ 07/08/2009
            string d = String.Format("{0}{1}{2}", partsDay[0], partsDay[1], partsDay[2]);
            key = key + d;
            string[] partsTime;
            partsTime = DateTime.Now.ToLongTimeString().Split(':');
            //Ví dụ 7:08:03 PM hoặc 7:08:03 AM
            if (partsTime[2].Substring(3, 2) == "PM")
                partsTime[0] = ConvertTimeTo24(partsTime[0]);
            if (partsTime[2].Substring(3, 2) == "AM")
                if (partsTime[0].Length == 1)
                    partsTime[0] = "0" + partsTime[0];
            //Xóa ký tự trắng và PM hoặc AM
            partsTime[2] = partsTime[2].Remove(2, 3);
            string t;
            t = String.Format("_{0}{1}{2}", partsTime[0], partsTime[1], partsTime[2]);
            key = key + t;
            return key;
        }

Với ConvertTimeTo24 là một hàm toàn cục được viết trong Class Functions, có tác dụng chuyển đổi giờ từ dạng PM sang dạng 24h.

g) Hàm ConvertTimeTo24

Soạn thảo trong Class Functions:


//Chuyển đổi từ PM sang dạng 24h
        public static string ConvertTimeTo24(string hour)
        {
            string h = "";
            switch (hour)
            {
                case "1":
                    h = "13";
                    break;
                case "2":
                    h = "14";
                    break;
                case "3":
                    h = "15";
                    break;
                case "4":
                    h = "16";
                    break;
                case "5":
                    h = "17";
                    break;
                case "6":
                    h = "18";
                    break;
                case "7":
                    h = "19";
                    break;
                case "8":
                    h = "20";
                    break;
                case "9":
                    h = "21";
                    break;
                case "10":
                    h = "22";
                    break;
                case "11":
                    h = "23";
                    break;
                case "12":
                    h = "0";
                    break;
            }
            return h;
        }

h) Phương thức ResetValues


private void ResetValues()
        {
            txtMaHDBan.Text = "";
            txtNgayban.Text = DateTime.Now.ToShortDateString();
            cboManhanvien.Text = "";
            cboMakhach.Text = "";
            txtTongtien.Text = "0";
            lblBangchu.Text = "Bằng chữ: ";
            cboMahang.Text = "";
            txtSoluong.Text = "";
            txtGiamgia.Text = "0";
            txtThanhtien.Text = "0";
        }

i) Phương thức btnLuu_Click


private void btnLuu_Click(object sender, EventArgs e)
        {
            string sql;
            double sl, SLcon, tong, Tongmoi;
            sql = "SELECT MaHDBan FROM tblHDBan WHERE MaHDBan=N'" + txtMaHDBan.Text + "'";
            if( ! Functions.CheckKey(sql) )
            {
                // Mã hóa đơn chưa có, tiến hành lưu các thông tin chung
                // Mã HDBan được sinh tự động do đó không có trường hợp trùng khóa
                if( txtNgayban.Text.Length == 0 )
                {
                    MessageBox.Show("Bạn phải nhập ngày bán", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Information);
                    txtNgayban.Focus();
                    return ;
                }
                if( cboManhanvien.Text.Length == 0 )
                {
                    MessageBox.Show("Bạn phải nhập nhân viên", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    cboManhanvien.Focus();
                    return;
                }
                if( cboMakhach.Text.Length == 0 )
                {
                    MessageBox.Show("Bạn phải nhập khách hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information );
                    cboMakhach.Focus();
                    return;
                }
                sql = "INSERT INTO tblHDBan(MaHDBan, Ngayban, Manhanvien, Makhach, Tongtien) VALUES (N'" + txtMaHDBan.Text.Trim() + "','" +
                        Functions.ConvertDateTime(txtNgayban.Text.Trim()) + "',N'" + cboManhanvien.SelectedValue + "',N'" + 
                        cboMakhach.SelectedValue + "'," + txtTongtien.Text + ")";                
                Functions.RunSQL(sql);
            }
            // Lưu thông tin của các mặt hàng
            if( cboMahang.Text.Trim().Length == 0 )
            {
                MessageBox.Show("Bạn phải nhập mã hàng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                cboMahang.Focus();
                return;
            }
            if( (txtSoluong.Text.Trim().Length == 0) || (txtSoluong.Text == "0" ))
            {
                MessageBox.Show("Bạn phải nhập số lượng", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information );
                txtSoluong.Text = "";
                txtSoluong.Focus();
                return;
            }
            if( txtGiamgia.Text.Trim().Length == 0 )
            {
                MessageBox.Show("Bạn phải nhập giảm giá", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtGiamgia.Focus();
                return;
            }
            sql = "SELECT Mahang FROM tblChitietHDBan WHERE MaHang=N'" + cboMahang.SelectedValue + "' AND MaHDBan = N'" + txtMaHDBan.Text.Trim() + "'";
            if(Functions.CheckKey(sql))
            {
                MessageBox.Show("Mã hàng này đã có, bạn phải nhập mã khác", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Information);
                ResetValuesHang();
                cboMahang.Focus();
                return;
            }
            // Kiểm tra xem số lượng hàng trong kho còn đủ để cung cấp không?
            sl = Convert.ToDouble(Functions.GetFieldValues("SELECT Soluong FROM tblHang WHERE Mahang = N'" + cboMahang.SelectedValue + "'"));
            if( Convert.ToDouble(txtSoluong.Text) > sl )
            {
                MessageBox.Show("Số lượng mặt hàng này chỉ còn " + sl, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                txtSoluong.Text = "";
                txtSoluong.Focus();
                return;
            }
            sql = "INSERT INTO tblChitietHDBan(MaHDBan,Mahang,Soluong,Dongia, Giamgia,Thanhtien) VALUES(N'" + txtMaHDBan.Text.Trim() + "',N'" + cboMahang.SelectedValue + "'," + txtSoluong.Text + "," + txtDongiaban.Text+ ","+  txtGiamgia.Text + "," + txtThanhtien.Text + ")";            
            Functions.RunSQL(sql);            
            LoadDataGridView();
            // Cập nhật lại số lượng của mặt hàng vào bảng tblHang
            SLcon = sl - Convert.ToDouble(txtSoluong.Text);
            sql = "UPDATE tblHang SET Soluong =" + SLcon + " WHERE Mahang= N'" + cboMahang.SelectedValue + "'";
            Functions.RunSQL(sql);
            // Cập nhật lại tổng tiền cho hóa đơn bán
            tong = Convert.ToDouble(Functions.GetFieldValues("SELECT Tongtien FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'"));
            Tongmoi = tong + Convert.ToDouble(txtThanhtien.Text);
            sql = "UPDATE tblHDBan SET Tongtien =" + Tongmoi + " WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
            Functions.RunSQL(sql);
            txtTongtien.Text = Tongmoi.ToString();
            lblBangchu.Text = "Bằng chữ: " + Functions.ChuyenSoSangChu(Tongmoi.ToString());
            ResetValuesHang();
            btnXoa.Enabled = true;
            btnThemmoi.Enabled = true;
            btnInhoadon.Enabled = true;
        }

Với ChuyenSoSangChu là một hàm toàn cục được viết trong Class Functions, có tác dụng đọc từ dạng số sang dạng chữ.

j) Hàm ChuyenSoSangChu

Soạn thảo trong Class Functions:


public static string ChuyenSoSangChu(string sNumber)
{
            int mLen, mDigit;
            string mTemp = "";
            string[] mNumText;
            //Xóa các dấu "," nếu có
            sNumber = sNumber.Replace(",", "");
            mNumText = "không;một;hai;ba;bốn;năm;sáu;bảy;tám;chín".Split(';');
            mLen = sNumber.Length - 1; // trừ 1 vì thứ tự đi từ 0
            for (int i = 0; i <= mLen; i++) { 
              mDigit = Convert.ToInt32(sNumber.Substring(i, 1));
              mTemp = mTemp + " " + mNumText[mDigit]; 
              if (mLen == i) // Chữ số cuối cùng không cần xét tiếp break; 
              switch ((mLen - i) % 9) { 
              case 0: 
                 mTemp = mTemp + " tỷ"; 
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3; 
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3; 
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3; 
                 break; 
              case 6: 
                 mTemp = mTemp + " triệu";
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3;
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3;
                 break; 
             case 3: 
                 mTemp = mTemp + " nghìn"; 
                 if (sNumber.Substring(i + 1, 3) == "000") i = i + 3;
                 break; 
            default: 
                 switch ((mLen - i) % 3) 
                 { 
                 case 2: 
                    mTemp = mTemp + " trăm"; 
                    break; 
                 case 1: 
                    mTemp = mTemp + " mươi"; 
                    break; 
                 } 
                break; 
            } 
         } 
         //Loại bỏ trường hợp x00
         mTemp = mTemp.Replace("không mươi không ", "");
         mTemp = mTemp.Replace("không mươi không", ""); //Loại bỏ trường hợp 00x 
         mTemp = mTemp.Replace("không mươi ", "linh "); //Loại bỏ trường hợp x0, x>=2
         mTemp = mTemp.Replace("mươi không", "mươi");
         //Fix trường hợp 10
         mTemp = mTemp.Replace("một mươi", "mười");
         //Fix trường hợp x4, x>=2
         mTemp = mTemp.Replace("mươi bốn", "mươi tư");
         //Fix trường hợp x04
         mTemp = mTemp.Replace("linh bốn", "linh tư");
         //Fix trường hợp x5, x>=2
         mTemp = mTemp.Replace("mươi năm", "mươi lăm");
         //Fix trường hợp x1, x>=2
         mTemp = mTemp.Replace("mươi một", "mươi mốt");
         //Fix trường hợp x15
         mTemp = mTemp.Replace("mười năm", "mười lăm");
         //Bỏ ký tự space
         mTemp = mTemp.Trim();
         //Viết hoa ký tự đầu tiên
         mTemp = mTemp.Substring(0, 1).ToUpper() + mTemp.Substring(1) + " đồng";
         return mTemp;
}

k) Phương thức ResetValuesHang


private void ResetValuesHang()
        {
            cboMahang.Text = "";
            txtSoluong.Text = "";
            txtGiamgia.Text = "0";
            txtThanhtien.Text = "0";
        }

l) Phương thức DataGridView_DoubleClick

Phương thức này cho phép người dùng nháy đúp chuột vào một mặt hàng trong lưới để xóa.


private void DataGridView_DoubleClick(object sender, EventArgs e)
        {
            string mahangxoa,sql;
            Double thanhtienxoa, soluongxoa, sl, slcon, tong, tongmoi;
            if (tblCTHDB.Rows.Count == 0)
            {
                MessageBox.Show("Không có dữ liệu!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if ((MessageBox.Show("Bạn có chắc chắn muốn xóa không?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes))
            {
                //Xóa hàng và cập nhật lại số lượng hàng 
                mahangxoa = DataGridView.CurrentRow.Cells["Mahang"].Value.ToString();
                soluongxoa = Convert.ToDouble(DataGridView.CurrentRow.Cells["Soluong"].Value.ToString());
                thanhtienxoa = Convert.ToDouble(DataGridView.CurrentRow.Cells["Thanhtien"].Value.ToString());
                sql = "DELETE tblChitietHDBan WHERE MaHDBan=N'" + txtMaHDBan.Text + "' AND Mahang = N'" + mahangxoa + "'";
                Functions.RunSQL(sql);
                // Cập nhật lại số lượng cho các mặt hàng
                sl = Convert.ToDouble(Functions.GetFieldValues("SELECT Soluong FROM tblHang WHERE Mahang = N'" + mahangxoa + "'"));
                slcon = sl + soluongxoa;
                sql = "UPDATE tblHang SET Soluong =" + slcon + " WHERE Mahang= N'" +  mahangxoa + "'";
                Functions.RunSQL(sql);
                // Cập nhật lại tổng tiền cho hóa đơn bán
                tong = Convert.ToDouble(Functions.GetFieldValues("SELECT Tongtien FROM tblHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'"));
                tongmoi = tong - thanhtienxoa;
                sql = "UPDATE tblHDBan SET Tongtien =" + tongmoi + " WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
                Functions.RunSQL(sql);
                txtTongtien.Text = tongmoi.ToString();
                lblBangchu.Text = "Bằng chữ: " + Functions.ChuyenSoSangChu(tongmoi.ToString());
                LoadDataGridView();
            }
        }

m) Phương thức btnXoa_Click

Phương thức này cho phép xóa toàn bộ thông tin của một hóa đơn


private void btnXoa_Click(object sender, EventArgs e)
        {
            double sl, slcon, slxoa;
            if (MessageBox.Show("Bạn có chắc chắn muốn xóa không?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 
            {
                string sql = "SELECT Mahang,Soluong FROM tblChitietHDBan WHERE MaHDBan = N'" + txtMaHDBan.Text + "'";
                DataTable tblHang = Functions.GetDataToTable(sql);
                for (int hang = 0; hang <= tblHang.Rows.Count - 1; hang++)
                {
                    // Cập nhật lại số lượng cho các mặt hàng
                    sl = Convert.ToDouble(Functions.GetFieldValues("SELECT Soluong FROM tblHang WHERE Mahang = N'" + tblHang.Rows[hang][0].ToString() + "'"));
                    slxoa = Convert.ToDouble(tblHang.Rows[hang][1].ToString());
                    slcon = sl + slxoa;
                    sql = "UPDATE tblHang SET Soluong =" + slcon + " WHERE Mahang= N'" + tblHang.Rows[hang][0].ToString() + "'";
                    Functions.RunSQL(sql);
                }

                //Xóa chi tiết hóa đơn
                sql = "DELETE tblChitietHDBan WHERE MaHDBan=N'" + txtMaHDBan.Text + "'";
                Functions.RunSqlDel(sql);

                //Xóa hóa đơn
                sql = "DELETE tblHDBan WHERE MaHDBan=N'" + txtMaHDBan.Text + "'";
                Functions.RunSqlDel(sql);
                ResetValues();
                LoadDataGridView();
                btnXoa.Enabled = false;
                btnInhoadon.Enabled = false;
            }
        }

n) Phương thức cboManhanvien_TextChanged


private void cboManhanvien_TextChanged(object sender, EventArgs e)
        {
            string str;
            if (cboManhanvien.Text == "")
                txtTennhanvien.Text = "";
            // Khi chọn Mã nhân viên thì tên nhân viên tự động hiện ra
            str = "Select Tennhanvien from tblNhanvien where Manhanvien =N'" + cboManhanvien.SelectedValue + "'";
            txtTennhanvien.Text = Functions.GetFieldValues(str);
        }

o) Phương thức cboMakhach_TextChanged


private void cboMakhach_TextChanged(object sender, EventArgs e)
        {
            string str;
            if (cboMakhach.Text == "")
            {
                txtTenkhach.Text = "";
                txtDiachi.Text = "";
                txtDienthoai.Text = "";
            }
            //Khi chọn Mã khách hàng thì các thông tin của khách hàng sẽ hiện ra
            str = "Select Tenkhach from tblKhach where Makhach = N'" + cboMakhach.SelectedValue+ "'";
            txtTenkhach.Text = Functions.GetFieldValues(str);
            str = "Select Diachi from tblKhach where Makhach = N'" + cboMakhach.SelectedValue + "'";
            txtDiachi.Text = Functions.GetFieldValues(str);
            str = "Select Dienthoai from tblKhach where Makhach= N'" + cboMakhach.SelectedValue  + "'";
            txtDienthoai.Text = Functions.GetFieldValues(str);
        }


p) Phương thức cboMahang_TextChanged


private void cboMahang_TextChanged(object sender, EventArgs e)
        {
            string str;
            if (cboMahang.Text == "")
            {
                txtTenhang.Text = "";
                txtDongiaban.Text = "";
            }
            // Khi chọn mã hàng thì các thông tin về hàng hiện ra
            str = "SELECT Tenhang FROM tblHang WHERE Mahang =N'" + cboMahang.SelectedValue+ "'";
            txtTenhang.Text = Functions.GetFieldValues(str);
            str = "SELECT Dongiaban FROM tblHang WHERE Mahang =N'" + cboMahang.SelectedValue+ "'";
            txtDongiaban.Text = Functions.GetFieldValues(str);
        }

q) Phương thức txtSoluong_TextChanged


private void txtSoluong_TextChanged(object sender, EventArgs e)
        {
            //Khi thay đổi số lượng thì thực hiện tính lại thành tiền
            double tt, sl, dg, gg;
            if (txtSoluong.Text == "")
                sl = 0;
            else
                sl = Convert.ToDouble(txtSoluong.Text);
            if (txtGiamgia.Text == "")
                gg = 0;
            else
                gg = Convert.ToDouble(txtGiamgia.Text);
            if (txtDongiaban.Text == "")
                dg = 0;
            else
                dg = Convert.ToDouble(txtDongiaban.Text);
            tt = sl * dg - sl * dg * gg / 100;
            txtThanhtien.Text = tt.ToString();
        }

r) Phương thức txtGiamgia_TextChanged


private void txtGiamgia_TextChanged(object sender, EventArgs e)
        {
            //Khi thay đổi giảm giá thì tính lại thành tiền
            double tt, sl, dg, gg;
            if (txtSoluong.Text == "")
                sl = 0;
            else
                sl = Convert.ToDouble(txtSoluong.Text);
            if (txtGiamgia.Text == "")
                gg = 0;
            else
                gg = Convert.ToDouble(txtGiamgia.Text);
            if (txtDongiaban.Text == "")
                dg = 0;
            else
                dg = Convert.ToDouble(txtDongiaban.Text);
            tt = sl * dg - sl * dg * gg / 100;
            txtThanhtien.Text = tt.ToString();
        }

s) Phương thức Inhoadon_Click


private void btnInhoadon_Click(object sender, EventArgs e)
        {
            // Khởi động chương trình Excel
            COMExcel.Application exApp = new COMExcel.Application();
            COMExcel.Workbook exBook; //Trong 1 chương trình Excel có nhiều Workbook
            COMExcel.Worksheet exSheet; //Trong 1 Workbook có nhiều Worksheet
            COMExcel.Range exRange; 
            string sql;
            int hang=0, cot=0;
            DataTable  tblThongtinHD, tblThongtinHang;
            exBook = exApp.Workbooks.Add(COMExcel.XlWBATemplate.xlWBATWorksheet);
            exSheet = exBook.Worksheets[1];
            // Định dạng chung
            exRange = exSheet.Cells[1, 1];
            exRange.Range["A1:Z300"].Font.Name = "Times new roman"; //Font chữ
            exRange.Range["A1:B3"].Font.Size = 10;            
            exRange.Range["A1:B3"].Font.Bold = true;
            exRange.Range["A1:B3"].Font.ColorIndex = 5; //Màu xanh da trời
            exRange.Range["A1:A1"].ColumnWidth = 7;
            exRange.Range["B1:B1"].ColumnWidth = 15;
            exRange.Range["A1:B1"].MergeCells = true;
            exRange.Range["A1:B1"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["A1:B1"].Value = "Shop B.A.";
            exRange.Range["A2:B2"].MergeCells = true;
            exRange.Range["A2:B2"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["A2:B2"].Value = "Chùa Bộc - Hà Nội";
            exRange.Range["A3:B3"].MergeCells = true;
            exRange.Range["A3:B3"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["A3:B3"].Value = "Điện thoại: (04)38526419";
            exRange.Range["C2:E2"].Font.Size = 16;
            exRange.Range["C2:E2"].Font.Bold = true;
            exRange.Range["C2:E2"].Font.ColorIndex = 3; //Màu đỏ
            exRange.Range["C2:E2"].MergeCells = true;
            exRange.Range["C2:E2"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["C2:E2"].Value = "HÓA ĐƠN BÁN";
            // Biểu diễn thông tin chung của hóa đơn bán
            sql = "SELECT a.MaHDBan, a.Ngayban, a.Tongtien, b.Tenkhach, b.Diachi, b.Dienthoai, c.Tennhanvien FROM tblHDBan AS a, tblKhach AS b, tblNhanvien AS c WHERE a.MaHDBan = N'" + txtMaHDBan.Text + "' AND a.Makhach = b.Makhach AND a.Manhanvien = c.Manhanvien";
            tblThongtinHD = Functions.GetDataToTable(sql);
            exRange.Range["B6:C9"].Font.Size = 12;
            exRange.Range["B6:B6"].Value = "Mã hóa đơn:";
            exRange.Range["C6:E6"].MergeCells = true;
            exRange.Range["C6:E6"].Value = tblThongtinHD.Rows[0][0].ToString();
            exRange.Range["B7:B7"].Value = "Khách hàng:";
            exRange.Range["C7:E7"].MergeCells = true;
            exRange.Range["C7:E7"].Value = tblThongtinHD.Rows[0][3].ToString();
            exRange.Range["B8:B8"].Value = "Địa chỉ:";
            exRange.Range["C8:E8"].MergeCells = true;
            exRange.Range["C8:E8"].Value = tblThongtinHD.Rows[0][4].ToString();
            exRange.Range["B9:B9"].Value = "Điện thoại:";
            exRange.Range["C9:E9"].MergeCells = true;
            exRange.Range["C9:E9"].Value = tblThongtinHD.Rows[0][5].ToString();
            //Lấy thông tin các mặt hàng
            sql = "SELECT b.Tenhang, a.Soluong, b.Dongiaban, a.Giamgia, a.Thanhtien " +
                  "FROM tblChitietHDBan AS a , tblHang AS b WHERE a.MaHDBan = N'" + 
                  txtMaHDBan.Text + "' AND a.Mahang = b.Mahang";
            tblThongtinHang = Functions.GetDataToTable(sql);
            //Tạo dòng tiêu đề bảng
            exRange.Range["A11:F11"].Font.Bold = true;
            exRange.Range["A11:F11"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["C11:F11"].ColumnWidth = 12;
            exRange.Range["A11:A11"].Value = "STT";
            exRange.Range["B11:B11"].Value = "Tên hàng";
            exRange.Range["C11:C11"].Value = "Số lượng";
            exRange.Range["D11:D11"].Value = "Đơn giá";
            exRange.Range["E11:E11"].Value = "Giảm giá";
            exRange.Range["F11:F11"].Value = "Thành tiền";
            for (hang = 0 ; hang < tblThongtinHang.Rows.Count; hang ++)
            {
                //Điền số thứ tự vào cột 1 từ dòng 12
                exSheet.Cells[1][hang + 12] = hang + 1;
                for (cot = 0; cot < tblThongtinHang.Columns.Count; cot++)
                //Điền thông tin hàng từ cột thứ 2, dòng 12
                {                    
                    exSheet.Cells[cot + 2][hang + 12] = tblThongtinHang.Rows[hang][cot].ToString();                    
                    if (cot == 3) exSheet.Cells[cot + 2][hang + 12] = tblThongtinHang.Rows[hang][cot].ToString() + "%";
                }
            }
            exRange = exSheet.Cells[cot][hang + 14];
            exRange.Font.Bold = true;
            exRange.Value2 = "Tổng tiền:";
            exRange = exSheet.Cells[cot + 1][hang + 14];
            exRange.Font.Bold = true;
            exRange.Value2 = tblThongtinHD.Rows[0][2].ToString();
            exRange = exSheet.Cells[1][hang + 15]; //Ô A1 
            exRange.Range["A1:F1"].MergeCells = true;
            exRange.Range["A1:F1"].Font.Bold = true;
            exRange.Range["A1:F1"].Font.Italic = true;
            exRange.Range["A1:F1"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignRight;
            exRange.Range["A1:F1"].Value = "Bằng chữ: " + Functions.ChuyenSoSangChu(tblThongtinHD.Rows[0][2].ToString ());
            exRange = exSheet.Cells[4][hang + 17]; //Ô A1 
            exRange.Range["A1:C1"].MergeCells = true;
            exRange.Range["A1:C1"].Font.Italic = true;
            exRange.Range["A1:C1"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            DateTime d = Convert.ToDateTime(tblThongtinHD.Rows[0][1]);
            exRange.Range["A1:C1"].Value = "Hà Nội, ngày " + d.Day + " tháng " + d.Month + " năm " + d.Year;
            exRange.Range["A2:C2"].MergeCells = true;
            exRange.Range["A2:C2"].Font.Italic = true;
            exRange.Range["A2:C2"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["A2:C2"].Value = "Nhân viên bán hàng";
            exRange.Range["A6:C6"].MergeCells = true;
            exRange.Range["A6:C6"].Font.Italic = true;
            exRange.Range["A6:C6"].HorizontalAlignment = COMExcel.XlHAlign.xlHAlignCenter;
            exRange.Range["A6:C6"].Value = tblThongtinHD.Rows[0][6];
            exSheet.Name = "Hóa đơn nhập";
            exApp.Visible = true;
        }
 

Kết quả ta có tệp Excel như sau: vdhd

t) Phương thức btnTimkiem_Click


private void btnTimkiem_Click(object sender, EventArgs e)
        {
            if (cboMaHDBan.Text == "")
            {
                MessageBox.Show("Bạn phải chọn một mã hóa đơn để tìm", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Information);
                cboMaHDBan.Focus();
                return;
            }
            txtMaHDBan.Text = cboMaHDBan.Text;
            LoadInfoHoadon();
            LoadDataGridView();
            btnXoa.Enabled = true;
            btnLuu.Enabled = true;
            btnInhoadon.Enabled = true;
            cboMaHDBan.SelectedIndex = -1;
        }

u) Phương thức txtSoluong_KeyPress


private void txtSoluong_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (((e.KeyChar >= '0') && (e.KeyChar <= '9')) || (Convert.ToInt32(e.KeyChar) == 8))
                e.Handled = false;
            else    e.Handled = true;
        }

Thực hiện tương tự cho txtGiamgia_KeyPress.

v) Phương thức cboMaHDBan_DropDown

Phương thức này cập nhật lại danh sách các mã hóa đơn bán và lưu vào cboMaHDBan mỗi khi người dùng nháy chuột vào nút xổ xuống của cbo.


private void cboMaHDBan_DropDown(object sender, EventArgs e)
        {
            Functions.FillCombo("SELECT MaHDBan FROM tblHDBan", cboMaHDBan, "MaHDBan","MaHDBan");
            cboMaHDBan.SelectedIndex = -1;
        }

w) Phương thức frmHoadonBan_FormClosing


private void frmHoadonBan_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Xóa dữ liệu trong các điều khiển trước khi đóng Form
            ResetValues();
        }

x) Phương thức btnDong_Click


private void btnDong_Click(object sender, EventArgs e)
        {
            this.Close();
        }

4.8. Form tìm kiếm Hóa đơn bán

a) Khai báo

– Thư viện


using System.Data.SqlClient;
using QuanLyBanHang.Class;

– Biến


DataTable tblHDB; //Hoá đơn bán

b) Phương thức frmTimHDBan_Load


private void frmTimHDBan_Load(object sender, EventArgs e)
        {
            ResetValues();
            DataGridView.DataSource = null;
        }

c) Phương thức ResetValues


private void ResetValues()
        {
            foreach (Control Ctl in this.Controls)
                if (Ctl is TextBox)
                    Ctl.Text = "";
            txtMaHDBan.Focus();
        }

d) Phương thức btnTimkiem_Click


private void btnTimkiem_Click(object sender, EventArgs e)
        {
            string sql;
            if ((txtMaHDBan.Text == "") && (txtThang.Text == "") && (txtNam.Text == "") &&
               (txtManhanvien.Text == "") && (txtMakhach.Text == "") &&
               (txtTongtien.Text == ""))
            {
                MessageBox.Show("Hãy nhập một điều kiện tìm kiếm!!!", "Yêu cầu ...",    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            sql = "SELECT * FROM tblHDBan WHERE 1=1";
            if (txtMaHDBan.Text != "")
                sql = sql + " AND MaHDBan Like N'%" + txtMaHDBan.Text + "%'";
            if (txtThang.Text != "")
                sql = sql + " AND MONTH(Ngayban) =" + txtThang.Text;
            if (txtNam.Text != "")
                sql = sql + " AND YEAR(Ngayban) =" + txtNam.Text;
            if (txtManhanvien.Text != "")
                sql = sql + " AND Manhanvien Like N'%" + txtManhanvien.Text + "%'";
            if (txtMakhach.Text != "")
                sql = sql + " AND Makhach Like N'%" + txtMakhach.Text + "%'";
            if (txtTongtien.Text != "")
                sql = sql + " AND Tongtien <=" + txtTongtien.Text;
            tblHDB = Functions.GetDataToTable(sql);
            if (tblHDB.Rows.Count == 0)
            {
                MessageBox.Show("Không có bản ghi thỏa mãn điều kiện!!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
                MessageBox.Show("Có " + tblHDB.Rows.Count + " bản ghi thỏa mãn điều kiện!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            DataGridView.DataSource = tblHDB;
            LoadDataGridView();
        }

e) Phương thức LoadDataGridView


private void LoadDataGridView()
        {
            DataGridView.Columns[0].HeaderText = "Mã HĐB";
            DataGridView.Columns[1].HeaderText = "Mã nhân viên";
            DataGridView.Columns[2].HeaderText = "Ngày bán";
            DataGridView.Columns[3].HeaderText = "Mã khách";
            DataGridView.Columns[4].HeaderText = "Tổng tiền";
            DataGridView.Columns[0].Width = 150;
            DataGridView.Columns[1].Width = 100;
            DataGridView.Columns[2].Width = 80;
            DataGridView.Columns[3].Width = 80;
            DataGridView.Columns[4].Width = 80;
            DataGridView.AllowUserToAddRows = false;
            DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

f) Phương thức btnTimlai_Click


private void btnTimlai_Click(object sender, EventArgs e)
        {
            ResetValues();
            DataGridView.DataSource = null;
        }

g) Phương thức txtTongtien_KeyPress


private void txtTongtien_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (((e.KeyChar >= '0') && (e.KeyChar <= '9')) || (Convert.ToInt32(e.KeyChar) == 8))
                e.Handled = false;
            else
                e.Handled = true;
        }

h) Phương thức DataGridView_DoubleClick

Phương thức này cho phép người dùng nháy đúp chuột chọn một hóa đơn trên lưới, rồi gọi và hiển thị thông tin của hóa đơn đó lên form frmHoadonBan.

Chú ý: Thay đổi phạm vi truy cập của điều khiển txtMaHDBan thành Public trong form frmHoadonBan (trong file frmHoadonBan.Designer.cs)

 


private void DataGridView_DoubleClick(object sender, EventArgs e)
        {
            string mahd;
            if (MessageBox.Show("Bạn có muốn hiển thị thông tin chi tiết?", "Xác nhận",MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                mahd = DataGridView.CurrentRow.Cells["MaHDBan"].Value.ToString();
                frmHoadonBan frm = new frmHoadonBan();
                frm.txtMaHDBan.Text = mahd;
                frm.StartPosition = FormStartPosition.CenterParent;
                frm.ShowDialog();
            }
        }

i) Phương thức btnDong_Click


private void btnDong_Click(object sender, EventArgs e)
        {
            this.Close();
        }

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

293 phản hồi

  1. Phùng Văn Thịnh viết:

    Mình làm như bài viết bạn hướng dẫn mà báo lỗi 1 số như sau:
    1. Lỗi khi nhập ngày sinh lớn hơn 12. máy tính mình đang để định dạng ngày là M/d/yyyy.
    2. Lỗi trong phương thức In hóa đơn. báo lỗi Error 1 Cannot apply indexing with [] to an expression of type ‘object’ exSheet.Cells[1][hang + 12]

    chỗ nào có exSheet.Cells là lỗi. Mong bạn giúp mình với. Ban hướng dẫn mình làm báo cáo luôn được không?

    • Phan Tiến viết:

      Chào bạn, mình xin trả lời các lỗi bạn gặp phải:
      1. Lỗi về ngày tháng là lỗi mà các bạn hay gặp khi lập trình Insert vào cơ sở dữ liệu. Lỗi này xảy ra do định dạng ngày tháng trên hệ thống và định dạng dữ liệu ngày tháng của người dùng nhập là khác nhau, người việt hay sử dụng định dạng là dd/MM/yyyy (ngày/tháng/năm) nhưng trên hệ thống (mặc định của người Mỹ/Anh …) sử dụng định dạng MM/dd/yyyy (tháng/ngày/năm)
      Trong chương trình trên sử dụng control MaskedTextBox để nhập nên sẽ phát sinh nhiều lỗi nhập dữ liệu ngày tháng. Bạn có thể thay thế sử dụng control DateTimePicker và thiết lập Format = Short, control này sẽ giúp giảm thiểu rất nhiều lỗi liên quan đến kiểu dữ liệu ngày tháng.
      2. Phần In hoá đơn này thực hiện việc xuất dữ liệu ra file Excel, phần này thực hiện lập trình thao tác với thư viện Excel do đó bạn cần phải Reference tới thư viện này thì sẽ không gặp lỗi. Bạn làm như sau: kích vào Solution Explorer > References, kích chuột phải chọn Add Reference … cửa sổ Add Reference hiện ra, bạn chọn Tab COM rồi tìm đến thư viện có tên Microsoft Excel 14.0 Object Library rồi kích nút OK. Như vậy bạn sẽ không gặp lõi đó nữa
      3. Về phần tạo báo cáo mình đã viết 2 bài, bạn có thể tham khảo làm theo nhé
      http://timoday.edu.vn/tao-bao-cao-dung-control-reportviewer/
      http://timoday.edu.vn/tao-bao-cao-voi-crystal-report-trong-c/
      Chúc bạn thành công.

      • AA viết:

        phần in hóa đơn vì sử dụng excel 2007 nên chỉ có ms excel 12.0 thì dùng vẫn ok chứ ạ hay buộc phải dùng 14.0 ạ . e dùng 12.0 k in dc nó báo lỗi exRange = exSheet.Cells[cot][hang + 14]; thầy ạ

  2. Phước viết:

    Mình không rành về c# lắm ! nhưng sao mình thấy ứng dụng của bạn ít form qá vậy.

    • Phan Tiến viết:

      Hi Bạn,
      Các form tương đối đầy đủ, bởi trong mỗi form gộp rất nhiều chức năng nên bạn cảm thấy ít. Và đây cũng là một CSDL tương đối đơn giản, chỉ có tất cả 6 bảng nên số form nó cũng không quá nhiều.
      Bạn có thể làm theo, form nào bạn cảm thấy thiếu thì có thể thông báo cho mình. Mình sẽ giải thích thêm.

  3. VoDanhLapTrinh viết:

    cho mình hỏi khi Xoá bản sao cơ sở dữ liệu: trong cửa sổ Solution Explorer rồi có mở lại được k. ví dụ mình cần cập nhật thêm 1 table nữa thì làm sao có để thêm .
    write me soon

  4. Maria viết:

    sau khi viết xong form nhân viên . chạy chương trình thì bị lỗi này :
    InvailidOperatationException was Unhandled
    An unhandled exception of type ‘System.InvalidOperationException’ occurred in System.Data.dll

    Additional information: Fill: SelectCommand.Connection property has not been initialized.
    ví trí lỗi chỉ tới :
    //Lấy dữ liệu vào bảng
    public static DataTable GetDataToTable(string sql)
    {

    SqlDataAdapter MyData = new SqlDataAdapter(); //Định nghĩa đối tượng thuộc lớp SqlDataAdapter
    //Tạo đối tượng thuộc lớp SqlCommand
    MyData.SelectCommand = new SqlCommand();
    MyData.SelectCommand.Connection = Functions.Con; //Kết nối cơ sở dữ liệu
    MyData.SelectCommand.CommandText = sql; //Lệnh SQL
    //Khai báo đối tượng table thuộc lớp DataTable
    DataTable table = new DataTable();
    MyData.Fill(table);
    return table;
    }
    giúp e với a

    • Phan Tiến viết:

      Hi Em,
      Lỗi của em xảy ra khi em chưa khởi tạo chuỗi kết nối tới cơ sở dữ liệu.
      Thứ nhất: Kiểm tra lại lớp Functions ở mục 4.1, chỗ phần phương thức public static void Connect() xem dòng code
      Con.ConnectionString = “chuỗi kết nối tới CSDL” xem em truyền đã đúng chưa.
      Thứ hai: Kiểm tra xem em khởi tạo đúng rồi thì em kiểm tra ở mục 4.2 phương thức frmMain_Load em đã gọi phương thức Connect() của hàm Functions chưa
      Class.Functions.Connect();

  5. Sơn viết:

    Làm thế nào để đóng gói phần mềm mình viết vậy thầy ơi. Mà khi cài ra máy tính khác, thì sử dụng được đó thầy. Thầy chỉ em với thầy ơi.

    • Phan Tiến viết:

      Cảm ơn câu hỏi rất hay của em. Phần đóng gói phần mềm là công đoạn cuối cùng trong quá trình phát triển phần mềm để đóng gói chuyển giao cho khách hàng.
      Trong Visual Studio em làm rất đơn giản:
      – Em kích chuột phải vào Solution của Project hiện tại của em (ví dụ em đang làm quản lý bán hàng), rồi am chọn Add => New Project => Other project type => Setup Project
      Chú ý: đối với những phiên bản VS 2012 trở đi, cần cài đặt thêm Visual Studio Installer (search google)
      Em thử nghịch, lựa chọn các tuỳ chọn để xem kết quả. Khi có thời gian mình sẽ viết bài hướng dẫn chi tiết.

  6. Phước viết:

    Thầy cho em hỏi. nút tìm kiếm với hiển thị danh sách trong form hàng để làm gì . với lại mnu tìm kiếm khách hàng với hàng liên kết với form nào vậy ! thanks.

    • Phan Tiến viết:

      Hi em,
      Trong form hàng hoá có rất nhiều hàng, chức năng nút tìm kiếm để cho phép tìm kiếm một sản phẩm theo một tiêu chí nào đó.
      mnuFindKhachHang hiện tại trong code thiếu, em có liên kết với form frmDMKhachHang, trong form này thêm một nút tìm kiếm

  7. Sơn viết:

    Thầy ơi, thầy chỉ cho em cách làm báo cáo từ ngày đến ngày của sản phẩm bài quản lý bán hàng mà thầy viết đi thầy. Em cảm ơn thầy nhiều ạ.

    • Phan Tiến viết:

      Em có thể xem sơ đồ thực thể liên kết (Relationship) thì em thấy chỉ trong bảng dữ liệu tblHDBan có trường Ngày tháng. Ví dụ muốn tạo báo cáo các sản phẩm bán ra trong một khoảng nào đó thì đâu tiên quan trọng em phải viết được câu lệnh SQL lấy dữ liệu mình cần để làm báo cáo, ví dụ câu lệnh SQL em có thể tham khảo:
      “Select Mahang, Tenhang From tblHang, tblChiTietHDBan, tblHDBan Where (tblHang.Mahang = tblChiTietHDBan.Mahang) AND (tblChiTietHDBan.MaHDBan = tblHDBan.MaHDBan) AND (NgayBan>#1/1/2016#) AND (NgayBan< #4/4/2016#)" Sau đó em có thể tham khảo thêm bài này để gắn dữ liệu lên báo cáo http://timoday.edu.vn/tao-bao-cao-dung-control-reportviewer/

  8. Sơn viết:

    Severity Code Description Project File Line Suppression State
    Error CS0161 ‘Functions.ChuyenSoSangChu(string)’: not all code paths return a value QuanLyBanHang C:\Users\SON\Documents\Visual Studio 2015\Projects\QuanLyBanHang\QuanLyBanHang\Class\Functions.cs 206 Active

    Em bị lỗi này là lỗi gì vậy thầy ơi hic hic

    • Phan Tiến viết:

      Em đưa vào dữ liệu cho hàm Functions.ChuyenSoSangChu(string) nhưng nó không thể chuyển được, em kiểm tra lại xem dữ liệu em đưa vào có đúng không.
      Ví dụ như
      Functions.ChuyenSoSangChu(“343545”) => thì ok
      Nhưng Functions.ChuyenSoSangChu(“343a54b5”) => thì sẽ bị lỗi

  9. Sơn viết:

    Dạ thầy ơi đây là lỗi gì vậy thầy. Thầy coi giúp em ạ. Em cảm ơn thầy nhiều ạ hic hic
    http://www.upsieutoc.com/image/54MI

    • Phan Tiến viết:

      Do em thay đổi cấu hình khi biên dịch nên khi biên dịch nó bị lỗi. Em kiểm tra lại:
      1. Đặt đường dẫn ouput cho đúng (kích vào menu Project > Tên Project Properties > Build > Output path đặt lại là bin\Debug)
      2. Vào menu Build > Configuration Manager, và bạn thấy có một dòng tên Project của bạn, kiểm tra xem nếu checkbox Build chưa được chọn thì kích vào để chọn.

  10. Sơn viết:

    Dạ thầy ơi sao em kết nối cơ sở dữ liệu không được thầy ơi. Đây là lỗi gì vậy thầy. Thầy giúp em với thầy. Em cảm ơn thầy nhiều ạ . Em cùi quá nên hỏi thầy riếc, mong thầy thông cảm ạ hic hic.
    http://www.upsieutoc.com/image/Rnhl

    • Phan Tiến viết:

      Đây là lỗi liên quan đến chuối kết nối đến CSDL, em cần kiểm tra lại thông tin kết nối đến SQL Server của em như tên server, tên database và user, password để truy cập CSDL đó.
      Ví dụ trong code :
      Con.ConnectionString = @”Data Source=.\SQLEXPRESS;AttachDbFilename=” + Application.StartupPath + @”\Quanlybanhang.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True”;
      – Data Source: em cần truyền vào tên SQL Server được cài trên máy em
      – AttachDbFilename: em đưa vào đường dẫn đến CSDL của em.

  11. Phước viết:

    Thầy cho e hỏi ! làm sao sứa lỗi khi load ảnh lên trong danh mục sản phẩm khi ảnh đó đã bị xóa.

    • Phan Tiến viết:

      Mình chưa hiểu rõ ý của em hỏi lắm. Khi ảnh đã bị xoá thì trên form hiển thị ảnh sẽ hiển thị dấu “x” và ảnh không được hiển thị. Để sửa thì em phải cập nhật ảnh lại hoặc kiểm tra không có ảnh thì cho hiển thị một ảnh mặc định nào đó.

  12. Vũ Lê Thục Nhi viết:

    http://www.upsieutoc.com/image/epFAl
    Thưa thầy cho em hỏi đây là lỗi gì? Em cảm ơn nhiều

  13. Vũ Lê Thục Nhi viết:

    Thưa thầy cho em hỏi code của btnNgay ở đâu ạ???

    • Phan Tiến viết:

      trong phần f. Form Hoá đơn bán hàng chỗ form frmHoadonBan có nút btnNgay, chức năng để lấy ngày hiện tại mà bán sản phẩm đó. Em có thể kích đúp vào nút đó và viết code:
      txtNgayBan.Text = DateTime.Now.ToString();
      – Chú ý, nếu em không muốn viết code thì có thể thay txtNgayBan và btnNgay bằng control có tên DateTimePicker để người sử dụng chọn vào ngày bán sản phẩm.

  14. Huỳnh Quốc Tuấn viết:

    Thầy ơi em làm giống như thầy mà sao phần dataGridView_Click không hiển thị các điều khiển lên trên Form vậy?

    • Phan Tiến viết:

      Em đang lập trình chức năng e) Phương thức dataGridView_Click này đúng không? Em có thể làm như sau để chắc chắn xem code của em có chạy vào sự kiện này hay không, em thử viết một thông báo hiển thị lên màn hình (ví dụ dùng MessageBox.Show(“Đây là sự kiện dataGridView_Click”), khi em chạy kích thử vào DataGridView mà nó hiển thị được thông báo này thì sự kiện này chạy bình thường.
      Nếu không xuất hiện thông báo trên thì sự kiện của em chưa tích hợp được vào code (có thể do em copy trực tiếp code trên trang rồi paste vào) => Nếu như vậy em xoá phần code này đi, rồi trên giao diện của Form, em kích đúp và DataGridView, nó sẽ tự động sinh cho em sự kiện này. Rồi em viết tiếp code vào đó.

      • Huỳnh Quốc Tuấn viết:

        thầy kiểm tra dùm em đây là lỗi gì mà em sửa dữ liệu ở frmDMNhanvien không được vậy thầy, https://uphinhnhanh.com/images/2016/10/30/loib9d28.png, đây là file của em: http://www.mediafire.com/file/mbigfqdj1si3d2m/QuanLyBanHang.rar

        • Phan Tiến viết:

          Trong frmDMNhanvien có trường dữ liệu nhập dữ liệu ngày sinh, người Việt Nam thường sử dụng định dạng dd/mm/yyyy nên trong chương trình sử dụng mặc định theo định dạng này => nên để không bị lỗi em cần nhập dữ liệu theo định dạng: 2 số cho ngày, 2 số cho tháng và 4 số cho năm.

          • Huỳnh Quốc Tuấn viết:

            em nhập vậy rồi mà vẫn không sửa được ở nút sửa dữ liệu thầy.

          • Huỳnh Quốc Tuấn viết:

            Em sửa dữ liệu ở frmDMNhanvien không được thầy ơi.

          • Phan Tiến viết:

            Chú ý: vì cột dữ liệu ngày sinh mình thiết kế là kiểu dữ liệu datetime nên khi insert một bản ghi vào dữ liệu sẽ có thêm cả thời gian, nên khi em kích trên DataGridView sẽ thấy có cả thời gian ví dụ như 12/02/1999 12:00:00 SA. Để tránh lỗi ta thêm một bước cắt ngày tháng riêng ra và thời gian riêng ra.
            Em có thể tham khảo hàm IsDate mình viết lại như sau:

            
              public static bool IsDate(string date)
                    {
                        string [] d = date.Split(' ');
                        string [] elements = d[0].Split('/');
                        if ((Convert.ToInt32(elements[0]) >= 1) && (Convert.ToInt32(elements[0]) < = 31) && (Convert.ToInt32(elements[1]) >= 1) && (Convert.ToInt32(elements[1]) < = 12) && (Convert.ToInt32(elements[2]) >= 1900))
                            return true;
                        else return false;
                    }
            
      • Huỳnh Quốc Tuấn viết:

        Em cám ơn thầy em làm được rồi!

      • Huỳnh Quốc Tuấn viết:

        Thầy cho em hỏi để bỏ 12:00:00 AM ở phía sau ngày sinh mình làm sao thầy?

  15. Huỳnh Quốc Tuấn viết:

    Thầy cho em hỏi để bỏ 12:00:00 AM ở phía sau ngày sinh mình làm sao thầy?

    • Phan Tiến viết:

      Em chỉ muốn lưu trữ nguyên ngày tháng thì chọn kiểu dữ liệu cho cột dữ liệu cho bảng cơ sở dữ liệu của em, em chọn kiểu dữ liệu là Date thay vì DateTime như hiện nay.

  16. Huỳnh Quốc Tuấn viết:

    Thầy ơi thầy có thể bổ sung thêm phần code phân trang cho datagridview được không thầy?

  17. Tấn Văn viết:

    Thầy có thể chỉ dùm em lam sao để in được nhiều hóa đơn xuất trên một trang giấy A4,ví dụ như một trang giấy em chia làm 4 hóa đơn,em muốn in 8 hóa đơn thì nó sẽ in ra 2 tờ,và mã hóa đơn trên đó tang dần theo ví dụ như 1,2,3,4,5,6,7,8

  18. Nhi viết:

    Thầy cho em hỏi,Ví dụ em muốn cộng cột đơn giá và thành tiền để ra cột mới là tổng của 2 cột trong excel thì sao ạ,giống hàm sum trong excel ạ nhưng em k biết code excel cho c# như thế nào??

    • Phan Tiến viết:

      Việc gì em phải viết code phức tạp làm gì, em chỉ cần viết câu lệnh SQL sau đó hiển thị lên DatagridView là được mà, ví dụ như
      MaSP | DGia | TTien |
      ——-+——-+——-+
      1 | 1.23 | 2.23 |
      2 | 23.03 | 12.23 |
      3 | 7.23 | 9.05 |
      Thì câu lệnh SQL như sau:

      
      SELECT DGia, TTien, (DGia + TTien) as 'Tong'
      FROM SanPham
      
  19. long viết:

    em muốn xem giao diện chạy khi viết code xong a.

    • Phan Tiến viết:

      Theo ý anh hiểu thì em muốn hỏi là sau khi viết xong code, chạy nó ra giao diện đúng không?
      Khi em thiết kế trong chế độ WinForm, em kéo thả các control vào Form và có thể code. Em muốn chạy thì chỉ cần ấn phím F5 trên bàn phím thì nó sẽ biên dịch chương trình. Nếu chương trình em không có lỗi thì sẽ xuất hiện giao diện form em đã thiết kế.

  20. Dũng viết:

    Em chào anh,
    Anh ơi, khi em làm theo anh ấy ạ, lúc chạy phần mềm, nó ko hiển thị ngay cơ sở dữ liệu ấy ạ, hiển thị 1 cái datagridview xám xám như mình mới kéo từ winform thôi. Sau đó em thêm dữ liệu thì nó mới lại có, bắt đầu từ dữ liệu thứ nhất. Nếu lần này em thêm 3 dữ liệu, em tắt đi thì trong SQL có 3 dữ liệu. Lần mở phần mềm sau, nó ko hiển thị gì, thêm thì lại từ dữ liệu thứ nhất. Có lẽ do hàm load dữ liệu vào datagridview có vấn đề ạ?

    • Phan Tiến viết:

      Với lỗi mô tả anh biết em bị lỗi gì rồi.
      Do em viết thiếu sự kiện Form_Load nên khi chương trình em mới đầu chạy nó không nạp dữ liệu lên DataGridView, chỉ khi em Insert dữ liệu thì nó mới hiển thị dữ liệu lên.
      Ví dụ như frmChatLieu, em gọi phương thức LoadDataGridView() ở sự kiện frmChatLieu_Load thì khi form hiển thị lên, nó sẽ nạp dữ liệu lên DataGridView

  21. Bảo Ngọc viết:

    ‘QuanLiBanHang.Class.Functions.ChuyenSoSangChu(string)’:not all code paths return a value

  22. Bảo Ngọc viết:

    Thầy xem giúp em lỗi này với ạ!

  23. My Dan viết:

    cho em hỏi , frmHOADONBAN là của form HÓA ĐƠN hay CHITIETHD vậy ạ :'(
    e code xong, lại ko biết 2 form đó liên kết với nhau bằng cách nào?
    – cái Phần MÃ hóa đơn, thầy đang dùng Combobox hay Text vậy ahj :'(

  24. My Dan viết:

    http://www.upsieutoc.com/image/cwGaMM
    thầy xem giúp em lỗi gì vậy ạ 🙁

    • Phan Tiến viết:

      Chào em,
      Lỗi này liên quan đến câu lệnh SQL của em, em viết sai nên nó không chạy được. Em thử show messagebox câu lệnh SQL lên rồi kiểm tra lại nhé

  25. TuanHung viết:

    An unhandled exception of type ‘System.InvalidOperationException’ occurred in System.Data.dll

    Additional information: Fill: SelectCommand.Connection property has not been initialized.
    ————————————————————————————————————————-
    Thầy xem giúp em lỗi này với ạ, em khắc phục nhưng có không kết quả 🙂

  26. TuanHung viết:

    public static bool CheckKey(string sql)
    {
    SqlDataAdapter MyData = new SqlDataAdapter(sql, con);
    DataTable table = new DataTable();
    MyData.Fill(table);
    if (table.Rows.Count > 0)
    return true;
    else return false;
    }
    ——————————————————-
    Em cop lại code bên trên, thầy xem họ em xem là còn thiếu gì không ạ!

  27. huế viết:

    thầy ơi trong class functions cái dòng public static DataTable GetDataToTable(string sql) này là mình tự đánh vào hay là code tự sinh do mình kích vào đâu ạ.

  28. Khoa viết:

    Thầy Ơi cho em hỏi? Em muốn làm web có chức năng login bằng facebook hay bằng CSDL với chức năng nạp tiền bằng card và chức năng mua nhạc chất lượng cao thì phải làm sao thầy?

  29. Tiến Đạt viết:

    Thầy ơi ! giúp em với.
    Em add References thì phiên bản của máy em là Microsoft Excel 15.0

    Em cần chỉnh lại câu lệnh để in háo đơn ra excel như thế nào vậy thầy ?

    CỨ bị lỗi này suốt

    Error 5 Cannot apply indexing with [] to an expression of type ‘object’

    • Phan Tiến viết:

      Lỗi ở dòng bao nhiêu hả em? Em phải cho mình dòng code nó bị lỗi thì mới biết được.
      Lỗi này liên quan đến việc gán dữ liệu không cùng kiểu với nhau.

  30. Lê Cao Thế viết:

    Thầy cho e hỏi, Chương trình này viết trên Visual 2012 được kô ạ, c.ơn thầy !!!

    • Phan Tiến viết:

      Hoàn toàn có thể viết trên VS 2012 em nhé!

    • Lê Cao Thế viết:

      Thầy ơi e chưa rành về CSDL. Không biết có bài viết nào hướng dẫn chi tiết cách tạo CSDL, tạo Table, quan hệ giữa các bảng và kết nối CSDL. Mong thầy giúp đỡ, tks Thầy !!!

  31. Đông viết:

    Thưa thầy e vẫn không hiểu về phần DataGridView_DoubleClick cho lắm.
    Phần Chú ý: Thay đổi phạm vi truy cập của điều khiển txtMaHDBan thành Public trong form frmHoadonBan (trong file frmHoadonBan.Designer.cs) e không hiểu là thay đổi phạm vi truy cập của điều khiển txtMaHDBan thành Public trong frmHoadonban như nào??

    h) Phương thức DataGridView_DoubleClick
    Phương thức này cho phép người dùng nháy đúp chuột chọn một hóa đơn trên lưới, rồi gọi và hiển thị thông tin của hóa đơn đó lên form frmHoadonBan.

    Chú ý: Thay đổi phạm vi truy cập của điều khiển txtMaHDBan thành Public trong form frmHoadonBan (trong file frmHoadonBan.Designer.cs)

    private void DataGridView_DoubleClick(object sender, EventArgs e)
    {
    string mahd;
    if (MessageBox.Show(“Bạn có muốn hiển thị thông tin chi tiết?”, “Xác nhận”,MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
    {
    mahd = DataGridView.CurrentRow.Cells[“MaHDBan”].Value.ToString();
    frmHoadonBan frm = new frmHoadonBan();
    frm.txtMaHDBan.Text = mahd;
    frm.StartPosition = FormStartPosition.CenterParent;
    frm.ShowDialog();
    }
    }

    • Phan Tiến viết:

      – Để thay đổi phạm vi của biến điều khiển, em có thể chọn vào Control đó (cửa ổ thiết kế giao diện) => Chọn thuộc tính Modifier của control rồi em thay đổi thành Public thì nó sẽ được sở mọi nơi.

  32. Lê Cao Thế viết:

    Hi, Thầy
    Em ấn vào “Test Connection” thì bị lỗi này,thầy giúp em với !!!
    http://www.upsieutoc.com/image/pqqGqD

  33. LÊ MINH NHỰT viết:

    Chào Thầy, em bị lỗi ngay bước đầu tiên
    “Trong cửa sổ Solution Explorer, nháy phải chuột lên tên ứng dụng, chọn Add ->New Item… Chọn Data -> Service-based Database”
    Em đã thử nhiều cách sửa lỗi trên “https://stackoverflow.com/questions/13754563/sql-network-interfaces-error-26-error-locating-server-instance-specified” nhưng vẫn không được.
    Mong thầy giúp em, em xin cảm ơn Thầy!
    http://www.upsieutoc.com/image/pK2bQt

    • Phan Tiến viết:

      Em có cài phiên bản SQL Server nào trên máy của em không?
      Em có thể mở SQL Server Management trên máy em được không?

  34. Nguyen Vu viết:

    thầy cho e hỏi cái phần load dữ liêu lên combobox rồi kích Mã chon Thì hiện tên tương ứng trong textbox thì mình cần có 2 hàm này la dc ạ
    1:hàm GetFieldValues ở class Functions
    2:private void cboManhanvien_TextChanged(object sender, EventArgs e)
    {
    string str;
    if (cboManhanvien.Text == “”)
    txtTennhanvien.Text = “”;
    // Khi chọn Mã nhân viên thì tên nhân viên tự động hiện ra
    str = “Select Tennhanvien from tblNhanvien where Manhanvien =N'” + cboManhanvien.SelectedValue + “‘”;
    txtTennhanvien.Text = Functions.GetFieldValues(str);
    }

    • Phan Tiến viết:

      Phần Load dữ liệu lên Combobox nó xảy ra ở sự kiện Form_Load với hàm Functions.FillCombo(….)
      Còn sự kiện cboManhanvien_TextChanged xảy ra khi em thay đổi dữ liệu trong Combobox.

  35. Chi viết:

    Thầy ơi, Sau khi em thêm dữ liệu vào rồi, nhưng lúc tắt chương trình mở lại thì dữ liệu ko còn hả Thầy ?

    • Phan Tiến viết:

      Vì database của em khi chạy, chương trình tự động copy một bản mới vào thư mục chạy của chương trình. Nên khi chương trình em chạy, em thêm dữ liệu thì OK. Nhưng chạy lại thì dữ liệu bị mất hết.
      Em chọn vào tên Database của em ở cửa sổ Solution Explorer, rồi chọn dưới cửa sổ Properties => Thay bằng Copy If Newer
      Xem ảnh tương tự:
      http://timoday.edu.vn/wp-content/uploads/2016/06/ThayDoiCopyReport.png

  36. Trần Anh viết:

    E có một thắc mắc, trong frmHoaDonBH, khi thêm hóa đơn mới, muốn thêm một mặt hàng mới vô hóa đơn thì sẽ thực hiện như nào ạ.
    Mong thầy giải đáp, em xin cảm ơn

  37. Thế viết:

    Thầy ơi, e lưu hình ảnh vào trong CSDL được rồi và cũng load hình ảnh ra form được luôn, nhưng khi chạy bài ở máy khác thì bị lỗi load ảnh ra form, thầy có thể hướng dẫn e cách lưu đường dẫn ảnh tương đối và load đường dẫn đó lên form kô ạ ???

    • Phan Tiến viết:

      Hi em!
      Em chú ý cần phải làm rõ làem đang lưu đường dẫn hay lưu trực tiếp ảnh vào CSDL.
      Nếu em lưu trực tiếp ảnh vào CSDL thì việc ở copy đến máy khác không vấn đề gì.
      Mình đang hiểu vấn đề của em là do em lưu đường dẫn, ví dụ D:\Images\test.jpg, nên khi em copy đến một máy khác nếu không có đường dẫn tương ứng thì sẽ không hiển thị được ảnh.
      Cách khắc phục: em có thể tạo một thư mục Images cùng cấp với chương trình chạy. Khi em upload ảnh thì em sẽ copy ảnh tới thư mục này và em sẽ lưu đường dẫn theo đường dẫn tương đối.

  38. FillForest viết:

    e không hiểu cái hàm toàn cục Chuyenchusangso viết ở functions lắm? e viết thì nó báo not all code paths return a value ? thế là sao ạ ?

    • Phan Tiến viết:

      Đây là hàm chức năng chuyển từ một số sang dạng chuỗi ví dụ như 123=> “một trăm hai ba”
      Phần code mình đã edit lại cho dễ nhìn hơn. Em kiểm tra lại code của mình nhé.
      Phần báo lỗi của em có thể một switch case nào đó không thể chạy đến được hoặc không có giá trị trả về.

  39. Kiên viết:

    thầy ơi e thử làm giống như thầy mà cứ gặp lỗi này ở mỗi form,sửa như thế nào được ạ?
    Error 1 An object reference is required for the non-static field, method, or property ‘System.Windows.Forms.DataGridView.DataSource.get’
    Error 2 An object reference is required for the non-static field, method, or property ‘System.Windows.Forms.DataGridView.Columns.get’
    ………..

  40. Tùng viết:

    Thưa thầy, ở FrmHoaDonBan, ban đầu load form lên thì làm sao mình biết đc MaHBBan mà sử dụng câu lệnh truy vấn sql để load data lên được ạ? Em xem mãi mà vẫn ko hiểu ạ. Em cảm ơn thầy.

    • Phan Tiến viết:

      Ví dụ đây là một đoạn code để đổ dữ liệu vào Combobox được đặt tên là cboMatHang.
      Functions.FillCombo(“SELECT Mahang, Tenhang FROM tblHang”, cboMahang,”Mahang”, “Mahang”);
      => Câu lệnh này lấy toàn bộ dữ liệu từ bảng tblHang (gồm 2 cột Mahang và Tenhang nhé), tham số thứ 3 và thứ 4 để thiết lập phần lấy dữ liệu và hiển thị lên ComboBox. Trong trường hợp này đều lấy cột Mahang nhé.

      • Tùng viết:

        Em hiểu rồi ạ.Thầy có tài liệu về phân tích thiết kế hệ thống hướng đối tượng UML không ạ? Em tìm 1 vài BT mẫu về phần đấy mà khó quá ạ, nếu có thầy có thể chia sẻ đc không ạ? Em cảm ơn!

  41. Phạm Đức viết:

    Lỗi An object reference is required for the non-static field, method, or property ‘DataGridView.DataSource’ Là sao vậy ạ @@@

    string sql;
    sql = “SELECT Manhanvien,Tennhanvien,Gioitinh,Diachi,Dienthoai,Ngaysinh FROm tblNhanvien”;
    tblNV = Functions.GetDataToTable(sql); //lấy dữ liệu
    DataGridView.DataSource = tblNV;
    DataGridView.Columns[0].HeaderText = “Mã nhân viên”;
    DataGridView.Columns[1].HeaderText = “Tên nhân viên”;
    DataGridView.Columns[2].HeaderText = “Giới tính”;
    DataGridView.Columns[3].HeaderText = “Địa chỉ”;
    DataGridView.Columns[4].HeaderText = “Điện thoại”;
    DataGridView.Columns[5].HeaderText = “Ngày sinh”;
    DataGridView.Columns[0].Width = 100;
    DataGridView.Columns[1].Width = 150;
    DataGridView.Columns[2].Width = 100;
    DataGridView.Columns[3].Width = 150;
    DataGridView.Columns[4].Width = 100;
    DataGridView.Columns[5].Width = 100;
    DataGridView.AllowUserToAddRows = false;
    DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;

    • Phan Tiến viết:

      Chú ý, ở form thiết kế em cần kéo một control có tên là DataGridView và đặt tên (Name) là DataGridView. Lỗi này do của em chưa kéo control vào form thôi.

  42. Ngọc Hùng viết:

    Thưa thầy, làm sao để tích hợp việc sử dụng máy quét barcode cho việc quản lý hàng hóa vào chương trình này ? Cám ơn thầy.

  43. duy viết:

    Cho em xin link tải ạ

    • Phan Tiến viết:

      Mình không cho các bạn link tải được vì các bạn có sẵn source code các bạn bạn sẽ lười không chịu làm.

  44. Phan Long viết:

    Thưa thầy, em code như trên bài nhưng dữ liệu trong bảng k load lên form khi formload (LoadDataGridView và Open, Close kết nối, đường dẫn em đã làm đúng)…….
    + Nếu click vào btnThem,Sua…thỳ bị lỗi này “NULL ReferenceException was unhanded”, “Object reference not set to an instance of an object.” tại dòng “if (tblNV.Rows.Count == 0)”
    + Nếu em làm thủ công click nút tam giác trên DataGridView=> Add DataSource=> chọn bảng thỳ load dữ liệu lên được nhưng các phương thức khác (như load dl dòng DataGridView click lên textbox ở trên) thỳ k được.
    Vì bài này rất qtrong với em nên mong thầy giúp đỡ. Em xin cảm ơn thầy ạ!

    • Phan Tiến viết:

      Lỗi này do dối tượng tblNV em khởi tạo ở đâu chưa?
      Em nên chụp hình code của em thì mình dễ tìm ra lỗi hơn.

  45. Phương Phạm viết:

    Thầy cho em hỏi là em bị dính lỗi này ở frmDMHang ạ: Use of unassigned local variable ‘sql’

  46. Chi Dương viết:

    cho em hỏi làm sao để bỏ ảnh được ạ
    vầ cách kết nối cơ sở dữ liệu

  47. nguyễn hữu viết:

    THƯA thầy ! thầy cho em hỏi là ..khi em chạy chương trình lên thì bị lỗi này ạ :Violation of PRIMARY KEY constraint ‘PK_DICHVU’. Cannot insert duplicate key in object ‘dbo.DICHVU’. thầy chỉ cho em cách khắc phục lỗi với ạ .. em cảm ơn ạ .

    • Phan Tiến viết:

      Trong bảng DICH VỤ của em khi em insert vào bảng này có bản ghi bị trùng khoá chính nên sẽ bị thông báo lỗi này.
      Để tránh bị lỗi này em nên kiểm tra xem đã tồn tại bản ghi với mã em định thêm chưa trước khi mình thêm bản ghi mới vào thì mới tránh bị lỗi như của em.
      Cách làm:
      Bước 1: Kiểm tra xem mã dịch vụ đã tồn tại chưa (sử dụng câu lệnh Select Count(*) From DichVu Where IdDichVu = id)
      Bước 2: Sử dụng phương thức ExcecuteScalar() của đối tượng Command xem có tồn tại bản ghi nào không (cmd.ExcecuteScalar() > 0 thì tồn tại bản ghi đã có mã này, và chúng ta kết thúc không ghi vào
      Bước 3: Nếu không có bản ghi nào tồn tại với mã này thì ta thêm mới.

  48. Nguyễn Minh Tú viết:

    hi….em không thấy câu lệnh insert thanhtien trong form hóa đơn bán hàng. anh có thể giải thích cho em với được không ạ. em cảm ơn

    • Nguyễn Minh Tú viết:

      à em thấy rồi nhưng lại thắc mắc ở chỗ cái Function.* em ko biết nó ở đâu nữa thư viện add vào hay hàm v ạ vd như
      txtTenhang.Text = Functions.GetFieldValues(str);

  49. Nguyễn Minh Tú viết:

    em không viết hàm function mà kết nối trực tiếp với từng form. v muốn viết được câu lệnh như trên thifem viết ntn ạ?

  50. Nguyễn Minh viết:

    Form tìm kiếm hóa đơn bán: sau khi kích đúp chuột thì có hiện ra form hóa đơn, nhưng chỉ có mã hóa đơn mà ko có thông tin chi tiết khác ạ.
    http://www.upsieutoc.com/image/4hE2bl

  51. Nhân Nguyễn viết:

    Chào Thầy,
    Mình làm theo giống như bài viết nhưng khi chạy thử báo lỗi như sau:
    An attempt to attach an auto-named database for file D:\Project\QuanLyBanHang\QuanLyBanHang\bin\Debug\Quanlybanhang.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
    Mong thầy giúp đỡ ạ, em mới tìm hiểu và học Visual ạ. Cám ơn thầy nhiều.

    • Phan Tiến viết:

      Chào bạn!
      Bạn phải kiểm tra lại file Quanlybanhang.mdf có tồn tại trong thư mục D:\Project\QuanLyBanHang\QuanLyBanHang\bin\Debug\

  52. Nguyễn Văn Bình viết:

    Chào Thầy,Em cũng đang làm chương trình quản lý bán hàng giống thầy. Em gặp vấn đề là “Khi nhân viên nghĩ việc thì làm sao để xóa nhân viên đó ra khỏi cơ sở dữ liệu. tại vì MANV là khóa ngoại của bảng hóa đơn.Nếu ta xóa đi nhân viên đồng nghĩa với ciệc ta xóa đi các hóa đơn của nhân viên đó”. Vậy em phải làm sao??Thầy cho em xin hướng giải quyết với ạ

    • Phan Tiến viết:

      Chào em,
      Với những dữ liệu quan trọng như trường hợp của em thì không nên xoá nhân viên khỏi CSDL vì dữ liệu của nhân viên này còn liên quan đến nhiều dữ liệu khác nữa. Ví dụ như nhân viên này liên quan đến lịch sử trả lương hàng tháng chẳng hạn.
      Cách đơn giản em cho thêm một cột Tạm Ngưng hoặc Nghỉ việc, Khi nhân viên này nghỉ việc thì cần cột này sẽ được thiết lập là true hoặc một giá trị nào đó.
      Rồi khi xử lý thì em cần kiểm tra xem nhân viên đó đã nghỉ việc chưa rồi mới thực hiện (ví dụ như những nhân viên đã nghỉ việc thì không cho hiển thị trên lưới nữa)

  53. Minh chiến viết:

    Chào thầy.
    Cho em hỏi ở đoạn kiểm tra số lượng tồn kho có đủ để cung cấp không.
    Em áp dụng đoạn code của thầy vào project của em thì nó báo lỗi như này: http://www.upsieutoc.com/image/4svaJm
    thầy sửa giúp em với ạ, Em cám ơn nhiều

  54. Minh chiến viết:

    Chào thầy
    Cho em hỏi ở đoạn kiểm tra số lượng tồn còn đủ để cung cấp không.
    Em áp dụng đoạn code của thầy vào project của em thì nó báo lỗi : http://www.upsieutoc.com/image/4svaJm
    Thầy xem và sửa giúp em với ạ, em cám ơn nhiều

  55. Nguyễn Minh viết:

    Thầy ơi nếu muốn tính chiết khấu có điều kiện (ví dụ: với hóa đơn trên 500.000 thì được chiết khấu 15%) thì làm như thế nào ạ.

  56. toantv viết:

    Xin cám ơn

  57. hảo viết:

    mình viết đến form chi tiết phiếu xuất thì bị lỗi, ai làm thành công rồi có thể cho mình xin code được k, thanks
    haohoang0902@gmail.com

  58. hảo viết:

    thông tin trên combobox mã khách hàng, mã nhân viên, mã hàng không hiện ra khi chọn mã , mặc dù thấy đã copi k sai , ai biết chỉ em voi

  59. hảo viết:

    em sử lý được rồi thì lại bị dính lỗi này, ai xem giúp với a
    https://drive.google.com/open?id=15-dep0d071434DE02M0WKioYyHr-oioA

    • Phan Tiến viết:

      Lỗi này là do số cột của em ít hơn số giá trị em truyền vào trong câu lệnh Insert.
      Em chú ý cú pháp:
      Insert Into tên_bảng(tên_các_cột) Values (các_giá_trị)
      – Số lượng các cột và các giá trị phải bằng nhau về số lượng. Và giá trị cùng kiểu với các cột đã thiết kế trong bảng.

  60. Hằng viết:

    Ad ơi cho e hỏi muốn in báo cáo ra file pdf tì làm ntn?

    • Phan Tiến viết:

      Em ơi khi chạy báo cáo, công cụ report nó đã có chức năng xuất dữ liệu ra các định dạng khách trong đó có file PDF rồi em

  61. Trần Ngọc Minh viết:

    ad giúp em lỗi này với :((( em sửa hoài ko đc ạ.
    em đang làm form NhanVien. đến cái đoạn sử dụng hàm CheckKey trong sự kiện btnLuu_click thì em bị lỗi dưới đây ạ, ngay cả khi em set đoạn code checkkey trong btnLuu thành note thì xuống đoạn sử dụng câu lệnh sql để insert vào csdl thì nó vẫn bị lỗi tương tự.

    https://drive.google.com/open?id=1dUSZ2E23SRgVm3xIOCkkaSegwbcPbp94

  62. Trần Ngọc Minh viết:

    nút xóa vs sửa cũng bị tương tự vậy luôn ạ :((

  63. Đào Đức viết:

    nút xoá vs sửa ở các form đều báo bạn chưa chọn bản ghi nào trong khi đã chọn dòng rồi thì fix sao thế thầy?

  64. Hằng viết:

    Thưa thầy thầy giúp e lỗi khi e nhập giá trị ngày tháng năm cụ thể để thống kê hàng bán của ngày đó và hiển thị lên gridview mà toàn bị lỗi
    Index was out of range. Must be non-negative and less than the size of the collection.
    Thầy giúp e vs ạ?

  65. Tran van Nam viết:

    Cho e hỏi trong cái form hóa đơn bán cái hàm FillCombo và GetDataTable ở đâu ra vậy ạ

  66. Nguyễn Văn Bảo viết:

    thầy ơi em vẫn chưa hiểu tại sao ở trong mục sản phẩm và mục chi tiết hóa đơn đền có đơn giá bán là sao ạ

    • Phan Tiến viết:

      Chào em! Giá bán này thiết kế trong tình huống họ cập nhật giá bán, thì hoá đơn chi tiết nó không bị thay đổi theo.
      Ví dụ: sản phẩm A tại thời điểm 01/01/2019 giá bán là a => thì khi bán giá sẽ được copy là a
      sau đó thời điểm 01/02/2018 giá bán là b được cập nhật => thì hoá hơn lập ngày 01/01/2019 với giá bán là a không bị thay đổi.

  67. Huỳnh Tiến Đạt viết:

    Thầy ơi. trên form báo cáo có nhiều radio button, 1 buton XEM, 1 button IN BÁO CÁO, nếu khi chọn lại radio button khác và nhấn button IN BÁO CÁO thì bắt phải click button XEM mới in được báo cáo thì sao ạ

    • Phan Tiến viết:

      Hi Em,
      Đó là việc xử lý code của em thôi. Khi em kích nút In Báo Cáo hoặc ấn nút Xem thì đều phải kiểm tra xem radio button đang chọn là gì để lấy dữ liệu theo đúng lựa chọn đó.

      Em cũng nên hiểu chức năng của 2 nút này, nút In Báo Cáo => mục đích để gửi dữ liệu ra máy in luôn
      Còn nút Xem giống như việc chúng ta xem trước dữ liệu để có thể lựa chọn in hoặc không in

      • Huỳnh Tiến Đạt viết:

        E thiết kế nút In báo cáo khi click sẽ xuất ra Reports dựa vào radio button để lấy dữ liệu và nút Xem để load dữ liệu lên Gridview cũng dựa vào radio button đó. Tránh trường hợp khi thay đổi radio buton khác mà không bắt load lại gridview và click In báo cáo thì dữ liệu trên Reports không giống với dữ liệu hiển thị trên gridview. Nhờ Thầy trợ giúp ạ. không biết có sự kiện nào để kiểm tra radio button vừa thay đổi, nếu thay đổi bắt phải load lại gridview rồi mới cho click nút In báo cáo.

  68. Lê Dung viết:

    Thầy ơi, cho em hoie, em đang làm đến form Hóa đơn bán thì gặp lỗi. Cụ thế là khi bấm nút Lưu dữ liệu ko được đưa vào DataGridView mà xuất hiện 2 dòng thông báo thế này ạ
    https://www.upsieutoc.com/image/kRdaAb
    Thầy giúp em với, em cảm ơn thầy nhiều ạ

  69. Nobita Phạm viết:

    Cảm ơn thày về bài viết. Em có 12 lỗi như thế này ạ. Mong thày giải thích giùm em

    https://www.upsieutoc.com/image/kY5LI2

    PS: em không cài được SQL Server nên dùng MS Access. Liệu có phải lỗi ở CSDL không ạ? Em cảm ơn

  70. Truong viết:

    Thay oi giup em dc k Em dang bi loi hic

  71. CuongNguyen viết:

    Thầy ơi em bị lỗi này khi xóa 1 hàng đã sử dụng bởi 1 bảng khác thì phải làm sao
    https://www.upsieutoc.com/image/image.xDUeEb
    https://www.upsieutoc.com/image/image.xDUDbO

  72. CuongNguyen viết:

    https://www.upsieutoc.com/image/image.xRLU3y
    em bị Lỗi câu lệnh
    cmd.ExecuteNonQuery();//Thực hiện câu lệnh SQL

  73. Ngọc Nhanh viết:

    Dạ em cảm ơn thầy về bài viết. Sẵn nhờ thầy xem giúp em lỗi này ạ.

    Sau khi nhập đủ thông tin và nhấn btn_luu thì nhận được lỗi này ạ
    https://drive.google.com/file/d/1tzT3TQvgsEFfXRExZYs4EZYU1MlQh4CO/view?usp=sharing

    sql = “SELECT * FROM db_Customer”;
    tblKH = Functions.GetDataToTable(sql);
    DataGridView.DataSource = tblKH;
    DataGridView.Columns[0].HeaderText = “Mã khách hàng”;
    DataGridView.Columns[1].HeaderText = “Tên khách hàng”;
    DataGridView.Columns[2].HeaderText = “Ngày sinh”;
    DataGridView.Columns[3].HeaderText = “Giới tính”;
    DataGridView.Columns[4].HeaderText = “Địa chỉ”;
    DataGridView.Columns[5].HeaderText = “Số điện thoại”;
    DataGridView.Columns[0].Width = 50;
    DataGridView.Columns[1].Width = 145;
    DataGridView.Columns[2].Width = 75;
    DataGridView.Columns[3].Width = 50;
    DataGridView.Columns[4].Width = 250;
    DataGridView.Columns[5].Width = 100;
    DataGridView.AllowUserToAddRows = false;
    DataGridView.EditMode = DataGridViewEditMode.EditProgrammatically;

    sql = “INSERT INTO db_Customer(MAKH,TENKH,NGAYSINH,GIOITINH,DIACHI,SODT) VALUES (N'”
    + txt_makh.Text + “‘,N'” + txt_tenkh.Text + dateTimePicker_kh.Value + “‘,N'” + gt + “‘,N'”
    + txt_diachikh.Text + “‘,'” + txt_sdtkh.Text + “‘)”;
    Functions.RunSQL(sql);

    Em cảm ơn thầy trước ạ

  74. NgaPea viết:

    Cho e hỏi là tại sao khi xuất hoá đơn ra excel thì đơn giá nó luôn mặc định là 20000 nhưng thành tiền thì vẫn đúng ạ

  75. Trung tính viết:

    mọi người ơi,sao mà form nhân viên của e không kết nối đc ạ,ai có thể giúp e không ạ,
    ai co bài hoàn chỉnh cho e tham khảo không ạ,cảm ơn mọi người nhiều,
    Email của e:nlttinh@gmail.com

  76. Minh công viết:

    DataTable tblCL; //Chứa dữ liệu bảng Chất liệu
    thầy ơi cái này đặt ở đâu cho đúng vậy thầy

    • Phan Tiến viết:

      Trong phần code có hướng dẫn em khai báo ở biến toàn cục => Vì vậy em đặt ngay phía dười của class.
      ví dụ:
      public class A
      {
      DataTable tblCL;
      …….
      }

  77. Hảo viết:

    Thầy ơi có thể chỉ cho em cách load dữ liệu từ nhiều bảng lên một form dạng như ở form Hoadon được không ạ

    • Phan Tiến viết:

      Em có thể viết một phương thức giống như Phương thức FillCombo trong lớp Functions.
      Ví dụ như:
      FillDataToControl(String sql, Loại Control);

      Rồi em muốn gọi ở form nào thì em gọi phương thức này lên.

  78. Hảo viết:

    Thầy có thể chỉ em cách chèn hình ảnh vào các nút lệnh thêm sửa xóa như của thầy được không ạ?

  79. Hảo viết:

    An exception of type ‘System.Data.SqlClient.SqlException’ occurred in System.Data.dll but was not handled in user code

    Additional information: Incorrect syntax near ‘System.Data.DataRowView’.
    ———————————————
    thầy ơi cho em hỏi lỗi này sửa sao ạ

  80. Hảo viết:

    An exception of type ‘System.Data.SqlClient.SqlException’ occurred in System.Data.dll but was not handled in user code

    Additional information: Incorrect syntax near ‘System.Data.DataRowView’.
    ————————-
    Dạ thầy cho e hỏi lỗi này sửa sao ạ?
    E hay bị lỗi ở form hóa đơn chỗ getfieldvalues á thầy

    • Phan Tiến viết:

      Lỗi này xảy ra khi em truyền tham số không đúng.
      Ví dụ câu lệnh:
      sql = “SELECT Tenchatlieu FROM tblChatlieu WHERE Machatlieu=N'” + machatlieu + “‘”;
      cboMachatlieu.Text = Functions.GetFieldValues(sql);
      => Tham số truyền vào GetFieldValues là 1 câu lệnh SQL ở trên. Nếu câu lênh SQL ở trên em select nhiều cột hoặc dữ liệu trả về nhiều bản ghi thì cũng có thể sinh ra lỗi.
      Đoạn code này thực hiện Select Tên chất liệu theo mã chất liệu. Và cboMachatlieu chọn mặc định theo dữ liệu select được.

  81. Hảo viết:

    An exception of type ‘System.Data.SqlClient.SqlException’ occurred in System.Data.dll but was not handled in user code Additional information: Conversion failed when converting the nvarchar value ‘System.Data.DataRowView’ to data type int.
    ———-
    Dạ thầy ơi lỗi này sửa sao vậy ạ?

  82. Hoàng viết:

    Thầy cho em xin code mã tự động của nhân viên không

  83. Hoàng viết:

    Thầy có code tạo mã tự động cho nhân viên

  84. Dung viết:

    thầy ơi làm sao để lấy ra được sản phẩm bán chạy trong các sản phẩm ạ.
    “Select Top 10 tblSanPham1.tenSP, SUM(tblChiTietHD.soLuong) as Tongsoluong
    from tblSanPham1, tblChiTietHD
    where tblSanPham1.maSP = tblCTietHD.maSP
    group by tenSP
    order by Tongsoluong desc”
    em dùng câu lệnh này mà k được ạ

  85. Hải viết:

    Thầy ơi thầy có code về tạo mã tự động cho nhân viên không VD: NV01 -> NV999

    • Phan Tiến viết:

      Tuỳ thuộc theo cách phát sinh mã của em. Ví dụ đoạn code sau sẽ sinh ra mã theo quy luật của em NV??? trong đó ??? là các số từ 001->999
      Trước hết cần đếm số bản ghi ở trong bảng dữ liệu của em
      cmd.Open();
      cmd = new SqlCommand(“Select Count(*)+1 from tblNhanVien”, con);
      int dem = cmd.ExecuteScalar();
      String maNV = “NV” + dem.ToString().PadLeft(3, ‘0’);

  86. Dung viết:

    Thưa thầy khi đã đưa ra được báo cáo giống vậy mà em muốn xuất ra excel để in ra thì làm như thế nào à

  87. Thắng viết:

    cho em hỏi ở chỗ ChuyenSoSangChu(string sNumber) nó cứ báo lỗi là “not all code paths return a value” thì phải sửa như thế nào?

  88. Hiếu viết:

    cho em hỏi muốn tìm kiếm mà hiện thị ra cả hóa đơn thì làm thế nào ạ

    • Phan Tiến viết:

      Em làm ở chức năng tìm kiếm nào? Em mô tả chi tiết thêm việc em muốn hiển thi ra cả hoá đơn thì sẽ hiển thị thêm những cái gì?
      Về cơ bản việc em muốn hiển thị những gì thì em viết câu lệnh SQL phù hợp.
      Ví dụ như chức năng 4.8. Form tìm kiếm Hóa đơn bán thì câu lệnh SQL chỉ tìm kiếm trên 1 mảng
      sql = “SELECT * FROM tblHDBan WHERE 1=1”;
      …..
      Nếu em muốn lấy thêm thông tin trên các bảng khác thì em cần thực hiện liên join các bảng với nhau, ví dụ như giữa lấy thêm phần chi tiết hoá đơn:
      sql = “SELECT hd.*, cthd.* FROM tblHDBan hd inner join tblChiTietHDBan cthd on hd.MaHDBan = cthd.MaHDBan WHERE 1=1”;
      ……

      Xem thêm inner join https://timoday.edu.vn/bai-5-toan-ven-du-lieu-va-cac-ky-thuat-truy-van-nang-cao/#muc4

  89. trung viết:

    Thầy ơi , em chạy bị lỗi : ‘Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index’ thì phải sảu sao ạ

  90. trung viết:

    lỗi ở phần frmHDN vsfrmHDban dó ạ

  91. Minh An viết:

    Thầy ơi, cho em hỏi đây là lỗi gì ạ, em ấn thêm hóa đơn thì bị lỗi này ạ
    https://i.imgur.com/lccOE7a.png

  92. Khánh viết:

    Chào mấy anh chị, có thể cho em xin bản code hoàn chỉnh để em tham khảo được không ạ.. mail em là: tfive2512@gmail.com, em cảm ơn ạ.

  93. Na viết:

    Chào mấy anh chị, có thể cho em xin bản code hoàn chỉnh được không ạ, địa chủ mail: nho238894@gmail.com…em cảm ơn.

  94. Gà Con viết:

    thầy ơi, giúp em cái lỗi này với ạ
    https://s4.upanh.pro/2019/07/26/Loi.png
    em cảm ơn thầy nhiều ạ

    • Phan Tiến viết:

      Theo ảnh em chụp thì do cái control có tên là txtMaHDBan ở form frmHoaDonBan không thể truy cập được từ form frmTimHDBan. Em muốn truy cập được thì mở lại form frmHoaDonBan sau đó chọn vào control txtMaHDBan, tìm thuộc tính Modifier đổi nó thành Internal

  95. Khanh viết:

    thầy ơi sao em làm đến mục này thì dòng LoadDataGridView(); lại báo gạch đỏ ạ? Mong thầy giúp đỡ.

    Sự kiện frmDMChatlieu_Load
    private void frmDMChatlieu_Load(object sender, EventArgs e)
    {
    txtMachatlieu.Enabled = false;
    btnLuu.Enabled = false;
    btnBoqua.Enabled = false;
    LoadDataGridView(); //Hiển thị bảng tblChatlieu
    }

  96. Minh Tú viết:

    thầy ơi em bị báo lỗi dòng LoadDataGridView(); //Hiển thị bảng tblChatlieu trong Sự kiện frmDMChatlieu_Load. như thế thì làm như nào được ạ?

  97. Hường viết:

    Thầy ơi em làm form Nhân Viên khi chạy thì nó báo lỗi ở phần Isdate như này ạ:
    https://www.upsieutoc.com/image/isdate.JQShAq

    • Phan Tiến viết:

      Em đưa chuột vào giá trị elements[1] xem nó đang chứa giá trị là gì? Lỗi này xảy ra khi giá trị truyền vào hàm Convert.ToInt32(giá_trị_chuyển_đổi), nhưng giá_trị_chuyển_đổi không phải là một kiểu số.

  98. viết:

    Chào Thầy,
    Em bị lỗi ở chuỗi kết nối : login failed for user, tuy là e làm trên máy tính không có pass và trong sql cũng sử dụng window authentication ah

  99. cường viết:

    thầy ơi em làm form hóa đơn bán khi chạy nó bão lỗi như này trong đoạn Chuyensosangchu:
    https://www.upsieutoc.com/image/9h46.JHtZKO

  100. Cường viết:

    thầy ơi em bị báo lỗi này trong mục chuyensosangchu:
    https://www.upsieutoc.com/image/9h46.JHtZKO

  101. Thuy viết:

    EM CHÀO THẦY, CHÀO MỌI NGƯỜI. Cho em hỏi em đang làm một bài nhỏ về quản lý thiết bị công ty. Cần: khi nhập thiết bị vào công ty thì nhập 1 mã, khi xuất ra vẫn là mã đấy, khi hủy là mã đấy. Xuất – Nhập – Hủy là một vòng tròn. Em nhập được mã đó và lưu trên CSDL được, nhưng e k hiểu lúc xuất thì xuất kiểu gì theo cái mã đấy, và hủy mã đấy nữa. em mới học và đang tìm hiểu cái barcode nhưng chưa rõ lắm. Và làm sao để kiểm tra điều kiện lúc xuất mã đấy. Tức là kiểm tra xem mã đấy có nằm trong CSSDL chưa, nếu có rồi thì được xuất, chưa có hiện thông báo.
    Em có 1 bảng hóa đơn, 1 bảng nhập thiết bị. Bảng hóa đơn có trường số lượng em nhập tổng VD: tổng PC = 10. Còn bảng nhập thiết bị: thì em k có cột số lượng, vì mỗi lần nhập chỉ nhập được 1 bởi mỗi thiết bị có thông số khác nhau. Bây giờ làm sao để em có thể hiện thông báo khi nhập thiết bị quá số lượng đơn hàng ạ
    Thật sự em rất mong sự giúp đỡ của thầy, em chỉ mới tìm hiểu, chưa biết gì, tìm hiểu đâu làm đến đó, rất mong nhận được sự giúp đỡ từ thầy và mn ạ.
    Email của em: thuthuytut@gmail.com

    • Phan Tiến viết:

      Chào em, để giải quyết bài toán của em cách đơn giản:
      1. Một bảng Danh mục hàng hoá dùng chung có Mã SP, Tên SP …
      2. Một bảng hoá đơn có chứa tổng hoá đơn nhập và loại hoá đơn (Nhập, Xuất)
      3. Một bảng Hoá đơn chi tiết chứa các hoá đơn nhập/xuất chi tiết cho từng sản phẩm, có số lượng, số lô nhập …
      Như vậy nhập xuất em sẽ chỉ quản lý trên 2 bảng: HoaDon và HoaDonChiTiet

  102. Cầm Trung Tín viết:

    Em chào Thầy ạ. Thầy ơi cho em hỏi em phải viết phương thức LoadDataGridView ở đâu thì mới không hiển thị được lên DataGridView ạ
    https://www.upsieutoc.com/image/35.J78TsU
    em cảm ơn và rất mong nhận được phản hồi từ thầy ạ

  103. Cầm Trung Tín viết:

    https://www.upsieutoc.com/image/35.Lq0Jb0
    Em Chào Thầy ạ . Thầy ơi . Thầy chỉ em cách khác phục Lỗi Này với ạ

  104. Lê Hoàng Tuấn Anh viết:

    Sao em xóa không được vậy ạ ? trong bảng tblChatlieu

  105. Chí Nguyễn viết:

    DataTable tblCL; //Chứa dữ liệu bảng Chất liệu code này thì viết ở đoạn nào vậy thầy

    • Phan Tiến viết:

      Hi em,

      Đây là biến toàn cục chứa các bảng dữ liệu được nạp ở trong các phần code của các method, ví dụ em có thể xem trong phương thức LoadDataGridView()

  106. Ngô Việt Hoàng viết:

    Thầy giúp em khắc phục lỗi này với ạ! Lỗi này bị khi em click vào datagridview để sửa và xóa
    https://www.upsieutoc.com/image/e0Ukmt

  107. Ngô Việt Hoàng viết:

    Thưa thầy em bị lỗi như này, khi lấy dữ liệu từ combobox ra textbox ở hóa đơn
    https://www.upsieutoc.com/image/endoF2
    Thầy giụp em khắc phục với ạ!

    • Phan Tiến viết:

      Em kéo con chuột lên trên biến sql xem câu lệnh truy vấn của em là gì? Phải debug thì mới biết được, chứ nhìn vào 1 cái ảnh khó có thể biết được.

  108. Hoàng Quốc Chung viết:

    thưa thầy.
    em bị lỗi ở đoạn FillCombo em ko thìm đc cách khác phục thầy giúp em vs ạ …
    1 phần của form Hóa Đơn Bán :
    ” Functions.FillCombo(“SELECT MaKH, TenKH FROM dbo.KHACHHANG”, cboMakhach, “Makhach”, “Makhach”);”

  109. Hoàng Quốc Chung viết:

    em có gửi ảnh rồi sao ko thấy khi gửi lại thì nó báo trùng ạ…
    thầy giúp em sửa lỗi vs ạ… em cãm ơn….
    https://www.upsieutoc.com/image/image.edvruY
    https://www.upsieutoc.com/image/untitled.edvvT2

    • Phan Tiến viết:

      Theo hình em chụp thì 2 cái hàm FillCombo và GetFieldValues chưa định nghĩa, em phải kiểm tra lại xem hai hàm này đã có trong class Functions chưa hoặc cũng có thể em sai tên khi em gõ. Em nên sử dụng chức năng gợi nhớ của Visual Studio bằng cách ấn Ctrl + Space để nó hiển thị ra các thành phần trong class em đang sử dụng.

  110. Phạm Thanh Tâm viết:

    Thưa thầy em bị lỗi như này, khi em ấn vào button Sửa thì chương trình không chạy và báo lỗi như này.
    https://www.upsieutoc.com/image/eXYXu8
    Thầy giúp em khắc phục với ạ.

    • Phan Tiến viết:

      Khi lỗi dừng ở vị trí này, em đưa con trỏ lên dòng date xem giá trị truyền vào là bao nhiêu?
      Có thể dữ liệu truyền vào của em không theo định dạng dd/mm/yyyy

  111. Phúc viết:

    Khi em ấn Lưu hóa đơn thì bị lỗi này ạ
    https://www.upsieutoc.com/image/untitled.etkSMt
    Mong thầy xem qua giúp em với. e cảm ơn thầy nhiều ạ

  112. Phúc viết:

    Thầy cho em hỏi với ạ, Khi em ấn vào nút lưu hóa đơn nó hiện lỗi như này ạ:
    https://www.upsieutoc.com/image/2.et2NRA
    và nó báo lỗi trong file Function.cs như này ạ:
    https://www.upsieutoc.com/image/untitled1.etkaBr
    Mong thầy chỉ giúp em cách khắc phục với ạ, em cảm ơn thầy nhiều

  113. Ân viết:

    Anh ơi em bị lỗi trong form frmHoadonBan khi đóng frmHoadonBan thì dữ liệu trong form không được lưu lại như những form khác VÀ lỗi không in duoc thông tin của HĐ ra excel
    System.InvalidCastException: ‘Unable to cast COM object of type ‘Microsoft.Office.Interop.Excel.ApplicationClass’ to interface type ‘Microsoft.Office.Interop.Excel._Application’. This operation failed because the QueryInterface call on the COM component for the interface with IID ‘{000208D5-0000-0000-C000-000000000046}’ failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).’

    • Phan Tiến viết:

      Em chưa nạp đúng thư viện Microsoft.Office.Interop.Excel.ApplicationClass
      => Trong cửa sổ Server Explorer => kích chuột phải vào References => Add Reference …=>Assemblies => Tìm đến Microsoft.Office.Interop.Excel rồi OK

    • Phan Tiến viết:

      https://www.upsieutoc.com/image/e1sHZm => Em xem bảng dữ liệu của em có phải là hoadon không? Em thử chạy câu lện truy vấn của em ở cửa sổ query của SQL Server xem có chạy được không để fix lỗi.
      https://www.upsieutoc.com/image/e1sO8s => Câu lệnh truy vấn của em bị sai, em phải đặt con trỏ debug vào đoạn code của em thì mới biết được sai ở chỗ nào, hiện tại nó đang báo lỗi lên là câu lệnh truy vấn của em cần phải cắt ngắn lại, có thể dữ liệu truyền vào không đúng kiểu hoặc không phù hợp.

  114. Hi viết:

    Hàm chuyển số sang chủ bị lỗi này ạ
    https://www.upsieutoc.com/image/eWWABs

  115. cat viết:

    -DataTable tblCL; //Chứa dữ liệu bảng Chất liệu (tblCL minh đổi thành tblChatlieu hả anh)

    – Con.ConnectionString = @”Data Source=.\SQLEXPRESS;AttachDbFilename=” + Application.StartupPath + @”\Quanlybanhang.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True”;
    (doạn này em phải gi giong hay sữa sao lai sao anh
    —–rất mong được giải đáp—–

    • Phan Tiến viết:

      Đây là chuỗi kết nối đến CSDL được cấu hình trên máy em, Phần .\SQLEXPRESS => có thể thay đổi tuỳ thuộc vào máy tên máy chủ CSDL của em là gì
      AttachDbFilename=” + Application.StartupPath + @”\Quanlybanhang.mdf => nếu em làm đúng theo hướng dẫn về đặt tên và nơi lưu trữ thì không phải thay đổi gì nữa.

      • cat viết:

        cảm ơn thầy em kết nối được rồi ạ
        mà em chỉ vào được mỗi mnuChatlieu còn mấy me nu kia em bấm vào k xuất hiện ạ
        ở menu chất liệu em bấm them thì txtTenchatlieu k xoa trắng (nên k điền vào được ạ)mong thầy giúp đỡ

  116. cat viết:

    -DataTable tblCL; //Chứa dữ liệu bảng Chất liệu
    cho em hỏi cái này ghi y trên hay sua lại là
    DataTable tblChatlieu ;//

    • Phan Tiến viết:

      Đây là khai báo một biến có tên tblCL để chứa dữ liệu cho bảng Chất liệu, và nó sử dụng trong toàn bộ chương trình, nếu em sửa thành tên tblChatLieu thì phải sửa tất code lại ở trong chương trình mà có tên biến là tblCL => tblChatLieu

  117. hihi viết:

    anh chi nào làm xong chạy được rồi cho em xin code được k ạ em làm mãi mà k điuọc chán quá

  118. TVT viết:

    Thầy ơi, em đang làm Form Hóa đơn Bán hàng, khi nhấn lưu báo lỗi phần đọc số ra chữ, thầy xem giúp em với ạ

Trả lời trung Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

3 Shares
Share via
Copy link
Powered by Social Snap