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


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. Tham khảo thêm khoá học đầy đủ lập trình .NETkhoá thành thạo với lập trình C#.

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)

Tạo bảng tblChatLieuBảng tblKhach (khách)

Tạo bảng tblKhach

Bảng tblHang (hàng)

Tạo bảng tblHang

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

Tạo bảng tblNhanVien

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

Tạo bảng tblHDBan

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

Tạo bảng tblChiTietHDBan

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á liên kết tới 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

– 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) (tìm đến thư mục Project của bạn). Nhấn Test Connection, nếu thành công sẽ xuất hiện thông báo “Test connection succeeded”.

– 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.

Xem video hướng dẫn

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

Xem Video hướng dẫn

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 dgvChatLieu

Xem Video hướng dẫn

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 mtbDienThoai Mask: Phone Number
mskNgaySinh Mask: Short Date
DataGridView dgvNhanVien

Xem Video hướng dẫn

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
MaskedTextBox mtbDienThoai Mask: Phone Number
DataGridView dgvKhachHang

Xem Video hướng dẫn

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 dgvHang
Button btnThem, btnXoa, btnSua, btnLuu, btnBoQua, btnTimKiem, btnHienThi, btnDong, btnOpen

Xem Video hướng dẫn

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 dgvHDBanHang
Button btnNgay, btnThem, btnLuu, btnXoa, btnInHoaDon, btnDong,  btnTimKiem

Xem Video hướng dẫn

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 dgvTKHoaDon
Button btnTimKiem, btnTimLai, btnDong

Xem Video hướng dẫn

 

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()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
            dgvChatLieu.DataSource = tblCL; //Nguồn dữ liệu            
            dgvChatLieu.Columns[0].HeaderText = "Mã chất liệu";
            dgvChatLieu.Columns[1].HeaderText = "Mã chất liệu";
            dgvChatLieu.Columns[0].Width = 100;
            dgvChatLieu.Columns[1].Width = 300;
            dgvChatLieu.AllowUserToAddRows = false; //Không cho người dùng thêm dữ liệu trực tiếp
            dgvChatLieu.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 dap = new SqlDataAdapter(); //Định nghĩa đối tượng thuộc lớp SqlDataAdapter
            //Tạo đối tượng thuộc lớp SqlCommand
            dap.SelectCommand = new SqlCommand();
            dap.SelectCommand.Connection = Functions.Con; //Kết nối cơ sở dữ liệu
            dap.SelectCommand.CommandText = sql; //Lệnh SQL
            //Khai báo đối tượng table thuộc lớp DataTable
            DataTable table = new DataTable();
            dap.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 dap = 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();
            dap.Fill(table); //Đổ kết quả từ câu lệnh sql vào table
            return table;
        }

Xem Video hướng dẫn

e) Phương thức dgvChatLieu_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 dgvChatLieu_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 = dgvChatLieu.CurrentRow.Cells["MaChatLieu"].Value.ToString();
            txtTenChatLieu.Text = dgvChatLieu.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 = 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 dap = new SqlDataAdapter(sql,Con);
            DataTable table = new DataTable();
            dap.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();
        }

Xem video hướng dẫn phần trên

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
            dgvNhanVien.DataSource = tblNV;
            dgvNhanVien.Columns[0].HeaderText = "Mã nhân viên";
            dgvNhanVien.Columns[1].HeaderText = "Tên nhân viên";
            dgvNhanVien.Columns[2].HeaderText = "Giới tính";
            dgvNhanVien.Columns[3].HeaderText = "Địa chỉ";
            dgvNhanVien.Columns[4].HeaderText = "Điện thoại";
            dgvNhanVien.Columns[5].HeaderText = "Ngày sinh";
            dgvNhanVien.Columns[0].Width = 100;
            dgvNhanVien.Columns[1].Width = 150;
            dgvNhanVien.Columns[2].Width = 100;
            dgvNhanVien.Columns[3].Width = 150;
            dgvNhanVien.Columns[4].Width = 100;
            dgvNhanVien.Columns[5].Width = 100;
            dgvNhanVien.AllowUserToAddRows = false;
            dgvNhanVien.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

d) Phương thức dgvNhanVien_Click


private void dgvNhanVien_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 = dgvNhanVien.CurrentRow.Cells["MaNhanVien"].Value.ToString();
            txtTenNhanVien.Text = dgvNhanVien.CurrentRow.Cells["TenNhanVien"].Value.ToString();
            if (dgvNhanVien.CurrentRow.Cells["GioiTinh"].Value.ToString() == "Nam") chkGioiTinh.Checked = true;
            else chkGioiTinh.Checked = false;
            txtDiaChi.Text = dgvNhanVien.CurrentRow.Cells["DiaChi"].Value.ToString();
            mtbDienThoai.Text = dgvNhanVien.CurrentRow.Cells["DienThoai"].Value.ToString();
            mskNgaySinh.Text = dgvNhanVien.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 = "";
            mtbDienThoai.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 (mtbDienThoai.Text == "(   )     -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mtbDienThoai.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() + "','" + mtbDienThoai.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 (mtbDienThoai.Text == "(   )     -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo",MessageBoxButtons.OK, MessageBoxIcon.Warning);
                mtbDienThoai.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='" + mtbDienThoai.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, mtbDienThoai.KeyUp, mskNgaySinh.KeyUp.

n) Phương thức btnDong_Click


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

Xem video hướng dẫn chi tiết

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
            dgvKhachHang.DataSource = tblKH; //Hiển thị vào dataGridView
            dgvKhachHang.Columns[0].HeaderText = "Mã khách";
            dgvKhachHang.Columns[1].HeaderText = "Tên khách";
            dgvKhachHang.Columns[2].HeaderText = "Địa chỉ";
            dgvKhachHang.Columns[3].HeaderText = "Điện thoại";
            dgvKhachHang.Columns[0].Width = 100;
            dgvKhachHang.Columns[1].Width = 150;
            dgvKhachHang.Columns[2].Width = 150;
            dgvKhachHang.Columns[3].Width = 150;
            dgvKhachHang.AllowUserToAddRows = false;
            dgvKhachHang.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

d) Phương thức dgvKhachHang_Click


private void dgvKhachHang_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 = dgvKhachHang.CurrentRow.Cells["MaKhach"].Value.ToString();
            txtTenKhach.Text = dgvKhachHang.CurrentRow.Cells["TenKhach"].Value.ToString();
            txtDiaChi.Text = dgvKhachHang.CurrentRow.Cells["DiaChi"].Value.ToString();
            mtbDienThoai.Text = dgvKhachHang.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 = "";
            mtbDienThoai.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 (mtbDienThoai.Text == "(  )    -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                mtbDienThoai.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() + "','" + mtbDienThoai.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 (mtbDienThoai.Text=="(  )    -")
            {
                MessageBox.Show("Bạn phải nhập điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                mtbDienThoai.Focus();
                return;
            }
            sql = "UPDATE tblKhach SET TenKhach=N'" + txtTenKhach.Text.Trim().ToString() + "',DiaChi=N'" +
                txtDiaChi.Text.Trim().ToString() + "',DienThoai='" + mtbDienThoai.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();
}

Xem video hướng dẫn Quản lý Khách Hàng

4.6. Form Danh mục Hàng hóa

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 dap = new SqlDataAdapter(sql, Con);
            DataTable table = new DataTable();
            dap.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);
            dgvHang.DataSource = tblH;
            dgvHang.Columns[0].HeaderText = "Mã hàng";
            dgvHang.Columns[1].HeaderText = "Tên hàng";
            dgvHang.Columns[2].HeaderText = "Chất liệu";
            dgvHang.Columns[3].HeaderText = "Số lượng";
            dgvHang.Columns[4].HeaderText = "Đơn giá nhập";
            dgvHang.Columns[5].HeaderText = "Đơn giá bán";
            dgvHang.Columns[6].HeaderText = "Ảnh";
            dgvHang.Columns[7].HeaderText = "Ghi chú";
            dgvHang.Columns[0].Width = 80;
            dgvHang.Columns[1].Width = 140;
            dgvHang.Columns[2].Width = 80;
            dgvHang.Columns[3].Width = 80;
            dgvHang.Columns[4].Width = 100;
            dgvHang.Columns[5].Width = 100;
            dgvHang.Columns[6].Width = 200;
            dgvHang.Columns[7].Width = 300;
            dgvHang.AllowUserToAddRows = false;
            dgvHang.EditMode = DataGridViewEditMode.EditProgrammatically;
        }

f) Phương thức dgvHang_Click


private void dgvHang_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 = dgvHang.CurrentRow.Cells["MaHang"].Value.ToString();
            txtTenHang.Text = dgvHang.CurrentRow.Cells["TenHang"].Value.ToString();
            MaChatLieu = dgvHang.CurrentRow.Cells["MaChatLieu"].Value.ToString();
            sql = "SELECT TenChatLieu FROM tblChatLieu WHERE MaChatLieu=N'" + MaChatLieu + "'";
            cboMaChatLieu.Text = Functions.GetFieldValues(sql);
            txtSoLuong.Text = dgvHang.CurrentRow.Cells["SoLuong"].Value.ToString();
            txtDonGiaNhap.Text = dgvHang.CurrentRow.Cells["DonGiaNhap"].Value.ToString();
            txtDonGiaBan.Text = dgvHang.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);
            dgvHang.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);
            dgvHang.DataSource = tblH;
        }

p) Phương thức btnDong_Click


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

Xem Video hướng dẫn Quản lý Hàng Hoá

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)
        {
            btnThem.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);
            dgvHDBanHang.DataSource = tblCTHDB;
            dgvHDBanHang.Columns[0].HeaderText = "Mã hàng";
            dgvHDBanHang.Columns[1].HeaderText = "Tên hàng";
            dgvHDBanHang.Columns[2].HeaderText = "Số lượng";
            dgvHDBanHang.Columns[3].HeaderText = "Đơn giá";
            dgvHDBanHang.Columns[4].HeaderText = "Giảm giá %";
            dgvHDBanHang.Columns[5].HeaderText = "Thành tiền";
            dgvHDBanHang.Columns[0].Width = 80;
            dgvHDBanHang.Columns[1].Width = 130;
            dgvHDBanHang.Columns[2].Width = 80;
            dgvHDBanHang.Columns[3].Width = 90;
            dgvHDBanHang.Columns[4].Width = 90;
            dgvHDBanHang.Columns[5].Width = 90;
            dgvHDBanHang.AllowUserToAddRows = false;
            dgvHDBanHang.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 btnThem_Click


private void btnThem_Click(object sender, EventArgs e)
        {
            btnXoa.Enabled = false;
            btnLuu.Enabled = true;
            btnInHoaDon.Enabled = false;
            btnThem.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;
            btnThem.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 dgvHDBanHang_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 dgvHDBanHang_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 = dgvHDBanHang.CurrentRow.Cells["MaHang"].Value.ToString();
                SoLuongxoa = Convert.ToDouble(dgvHDBanHang.CurrentRow.Cells["SoLuong"].Value.ToString());
                ThanhTienxoa = Convert.ToDouble(dgvHDBanHang.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 btnInHoaDon_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();
        }

Xem Video hướng dẫn Quản lý Hoá Đơn

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();
            dgvTKHoaDon.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);
            dgvTKHoaDon.DataSource = tblHDB;
            LoadDataGridView();
        }

e) Phương thức LoadDataGridView


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

f) Phương thức btnTimLai_Click


private void btnTimLai_Click(object sender, EventArgs e)
        {
            ResetValues();
            dgvTKHoaDon.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 dgvTKHoaDon_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 dgvTKHoaDon_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 = dgvTKHoaDon.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…

572 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é
      https://timoday.edu.vn/tao-bao-cao-dung-control-reportviewer/
      https://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 ạ

      • giki viết:

        internal static string ConvertDateTime(string text) //đổ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.
        {
        string[] elements = date.Split(‘/’);
        string dt = string.Format(“{0}/{1}/{2}”, elements[0], elements[1], elements[2]);
        return dt;
        }

        Severity Code Description Project File Line Suppression State
        Error CS0103 The name ‘date’ does not exist in the current context DoAn_QliBH E:\DoAn_QliBH\DoAn_QliBH\Functions.cs 71 Active

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

        Severity Code Description Project File Line Suppression State
        Error CS0542 ‘NhanVien’: member names cannot be the same as their enclosing type DoAn_QliBH E:\DoAn_QliBH\DoAn_QliBH\NhanVien.cs 16 Active

        thầy ơi giúp e vs

        • Phan Tiến viết:

          1. lỗi biến date không tồn tại trong phương thức ConvertDateTime, phương thức này dữ liệu đầu vào của em là biến text mà
          2. Em kiểm tra dòng 16 ở file NhanVien.cs, em đặt tên biến DataTable NhanVien; lại trùng tên với class NhanVien

      • Đạt viết:

        Em bị lỗi ở phần dap.Fill(table) khi mở form hoá đơn bán. Mong thầy giúp ạ
        public static DataTable GetDataToDataTable(string sql)

        {
        DataTable table = new DataTable();
        SqlDataAdapter dap = new SqlDataAdapter(sql, Conn);
        dap.Fill(table);
        return table;
        }

        • Phan Tiến viết:

          Em chụp hình ảnh báo lỗi rồi đưa lên google drive rồi share để mình xem lỗi gì.
          Chứ đoạn code này chẳng có lỗi gì cả, chỉ có lỗi khi em truyền vào các tham số như kết nối sai cơ sở dữ liệu hoặc sai câu lệnh truy vấn thôi.

      • Nguyễn Phước Tuấn viết:

        cho em hỏi cái csdl em lưu rồi mà lại bắt lưu lại là sao ạ??

      • zsaka2003 viết:

        thưa thầy em gặp phải lỗi như bên dưới thì sửa kiểu gì ạ mong thầy giup
        System.Data.SqlClient.SqlException (0x80131904): The conversion of a varchar data type to a datetime data type resulted in an out-of-range
        System.Data.SqlClient.SqlException (0x80131904): The conversion of a varchar data type to a datetime data type resulted in an out-of-range

    • tùng viết:

      trong trường hợp đầu tiên tốt nhất là bạn sử dụng Rules ngay trong database để tránh lỗi như này nhé

    • long viết:

      Thaày ơi cho e hỏi chỗ này làm ntnt ạ
      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).

      • Phan Tiến viết:

        Mình chưa hiểu câu hỏi của bạn lắm, nhưng mình đang hiểu bạn đang thắc mắc về đoạn “Sao chép file dữ liệu (Quanlybanhang.mdf) vào thư mục bin\Debug ” => Khi mình chạy code trong Visual Studio, tuỳ chọn mặc định khi biên dịch và chạy chương trình, Visual Studio sẽ copy database vào thư mục bin\Debug.

  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.

  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

  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 https://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

  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 đó.

  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?

  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 ạ 🙁

  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’

  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 !!!

  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();
    }
    }

  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

  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 ?

  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;

  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 ạ

  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 ạ!

  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

  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.

  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. 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

  57. 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

  58. 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

  59. Hằng viết:

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

  60. 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

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

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

  62. Đà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?

  63. 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 ạ?

  64. 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 ạ

  65. 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.

  66. 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.

  67. 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 ạ

  68. 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

  69. Truong viết:

    Thay oi giup em dc k Em dang bi loi hic

  70. 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

  71. 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

  72. 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 ạ

  73. 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 ạ

  74. 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

  75. 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

  76. 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.

  77. 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 ạ?

  78. 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 ạ

  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’.
    ————————-
    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.

  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: 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 ạ?

  81. Hoàng viết:

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

  82. Hoàng viết:

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

  83. 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 ạ

  84. 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’);

  85. 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 à

  86. 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?

  87. 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

  88. 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 ạ

  89. trung viết:

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

  90. 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

  91. 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 ạ.

  92. 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.

  93. 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 ạ

  94. 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
    }

  95. 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 ạ?

  96. 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ố.

  97. 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

  98. 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

  99. 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

  100. 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

  101. 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 ạ

  102. 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 ạ

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

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

  104. 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

  105. 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

  106. 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 ạ!

  107. 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”);”

  108. 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

  109. 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 ạ.

  110. 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 ạ

  111. 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

  112. Â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

  113. 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 đỡ

  114. 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 ;//

  115. 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á

  116. 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 ạ

  117. Tan viết:

    Thưa thầy, cho e hỏi ở Form Hóa đơn bán khi e thêm 1 hóa đơn bán thì báo lỗi khóa ngoại với ChiTietHDBan, e đã thêm MaHDBan đó vào ChiTietHDBan thì nó lại báo lỗi khóa ngoại với MaHang, rồi sau đó thì đến MaNV và MaKhach. (Mặc dù e đã làm giống như trên bài). Mong thầy giúp đỡ ạ. Em cảm ơn !

  118. Cường viết:

    thầy ơi cho e hỏi là mình làm chương trình này mà trên cơ sở dữ liệu phân tán thì cũng tương tự như vậy phải k ạ,. em cảm ơn thầy nhiều

  119. nam 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?

    • Phan Tiến viết:

      Em kiểm tra sự kiện DataGridView_Click xem đã viết chưa? Phần sự kiện này để đảm bảo khi em click một hàng nào đó trên DataGridView thì dữ liệu ở trên lưới sẽ được nạp sang các control để thực hiện việc sửa và xoá.

  120. Khải viết:

    Anh có thể cho em xin ảnh giao diện được không ạ?

  121. Nhân Đoàn viết:

    Thầy cho e hỏi lỗi như này là sao ạ
    Mong thầy sớm giải đáp.
    https://drive.google.com/drive/folders/1voArzRsSSsdcXQByqIq0l4GVpIT3rcO8

  122. Nguyễn Trí viết:

    em chào thầy
    thầy hướng dẫn giúp em với, khi em khai báo kiểu số tiền là Decimal trong SQL, sau đó thiết kết form thêm số tiền, khi nhập số 123 nhưng khi vào CSDL kiểm tra thì số được thêm vào là số khác lớn hơn rất nhiều 1535306601 như này ạ!

    • Phan Tiến viết:

      Chú ý em kiểm tra xem câu lệnh SQL em có INSERT đúng vào các cột trong bảng dữ liệu của em hay không. Để biết được lỗi sai em nên sử dụng chức năng Debug của Visual Studio để biết được lỗi của mình.
      Xem video hướng dẫn về cách Debug lỗi: https://www.youtube.com/watch?v=u6n0d3xPIHU

      • Nguyễn Trí viết:

        Nhờ thầy xem giúp em đoạn code này ạ
        //kiểm tra số tiền trợ cấp
        if (txtTroCapMTP.EditValue != null)
        {
        _TroCap = txtTroCapMTP.EditValue.GetHashCode();
        }
        else
        {
        XtraMessageBox.Show(“Số tiền Trợ cấp nếu có, hoặc = 0”, “Thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Error);
        txtTroCapMTP.Focus();
        return false;
        }
        //xử lý thêm dữ liệu
        try
        {
        KetNoiDataMTPDataContext db = new KetNoiDataMTPDataContext();
        SoTien _SoTien = null;

        _SoTien.TroCap = _TroCap;

        db.SoTiens.InsertOnSubmit(_SoTien);
        db.SubmitChanges();
        XtraMessageBox.Show(“Thêm dữ liệu thành công”, “Thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);

        return true;
        }
        catch (Exception)
        {

        return false;
        }

  123. Trọng Minh viết:

    Cho em xin cơ sở dữ liệu được không ạ, do em làm mà nó xuất hiện 2 khoá

  124. NgHuy viết:

    Thầy ơi bài r ở frmHDBan bị lỗi cứ lưu lại là đưa ra thông báo lỗi kết nối,mong thầy giúp đỡ em cảm ơn thầy ạ

  125. BThanh viết:

    Thầy có thể share code phần thống kê được ko ạ

  126. Tuân viết:

    project này là mô hình 3 lớp đúng ko thầy

  127. Khanh viết:

    nếu mô hình này làm 3 lớp thì như thế nào vậy thầy.

    • Phan Tiến viết:

      Nếu mô hình 3 lớp thì em sẽ cần tổ chức thành 3 tầng: Tầng giao diện (Presentation), Tầng nghiệp vụ (Business) và Tầng truy cập cơ sở dữ liệu (Data Access Layer)
      Tầng giao diện <=> Tầng nghiệp vụ <=> Tầng truy cập CSDL
      – Tầng giao diện: toàn bộ phần giao diện người dùng thiết kế ở phần này
      – Tầng nghiệp vụ: các nghiệp vụ liên quan đến quy trình, xử lý nghiệp vụ ví dụ như nghiệp vụ sẽ xử lý ở đây
      – Tầng truy cập CSDL: chứa các câu lệnh để thao tác với Hệ quản trị CSDL

  128. Khanh viết:

    xóa và sửa đều không được. Xin thầy cách khăc phục.
    https://www.upsieutoc.com/image/capture.FCvSO0

  129. than viết:

    thưa thầy! e muốn làm form hiển thị thông tin về nhân viên rồi, trong form e có 1 nút “xem file pdf” thì phần mềm sẽ hiện thị đúng file pdf liên quan đến nhân viên đó có được không thầy tư vấn giúp e với

  130. Hoàng Mạnh Thắng viết:

    thầy ơi cho em hỏi em bị báo lỗi the path is not of a legal form ở phần picAnh.Image = Image.FromFile(txtAnh.Text); thì sửa như thế nào ạ??? em cảm ơn thầy ạ

  131. tran viết:

    Chào anh!
    em làm theo như hướng dẫn.
    chổ function
    public static DataTable GetDataToTable(string sql)
    {
    SqlDataAdapter dap = 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();
    dap.Fill(table); //Đổ kết quả từ câu lệnh sql vào table
    return table;
    }

    private void LoadDataGridView()
    {
    string sql;
    sql = “SELECT MaChatLieu, TenChatLieu FROM tblChatLieu”;
    tblCL = Class.Functions.GetDataToTable(sql); //Đọc dữ liệu từ bảng
    dgvChatLieu.DataSource = tblCL; //Nguồn dữ liệu
    dgvChatLieu.Columns[0].HeaderText = “Mã chất liệu”;
    dgvChatLieu.Columns[1].HeaderText = “Mã chất liệu”;
    dgvChatLieu.Columns[0].Width = 100;
    dgvChatLieu.Columns[1].Width = 300;
    dgvChatLieu.AllowUserToAddRows = false; //Không cho người dùng thêm dữ liệu trực tiếp
    dgvChatLieu.EditMode = DataGridViewEditMode.EditProgrammatically; //Không cho sửa dữ liệu trực tiếp
    }
    ———
    khi chạy chương trình nó báo lỗi vậy là sao ạ? ví dụ em có table tblCauHinh trong csdl sqlserver (đã connect thành công)

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

    Additional information: Invalid object name ‘tblCauHinh’.

  132. Anh Le Thi Ngoc viết:

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

    Additional information: Fill: SelectCommand.Connection property has not been initialized.
    em bị lỗi này ở bảng chất lượng, phương thức getdatatotable ạ . thầy sửa giúp em với ạ

  133. Anh Le Thi Ngoc viết:

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

    Additional information: Fill: SelectCommand.Connection property has not been initialized.
    lỗ này là lỗi gì ạ ở bảng chất liệu ạ

  134. Anh Le Thi Ngoc viết:

    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)

    thay đổi này làm như thế nào ạ

  135. Anh Le Thi Ngoc viết:

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

    Additional information: Operand type clash: date is incompatible with int

    phần tìm kiếm em không tìm kiếm được do lỗi này ạ . thầy giúp em với ạ

  136. Anh Le Thi Ngoc viết:

    anh ơi ở hàm tạo mã hóa đơn ý ạ em muốn tạo hóa đơn có dạng HD001 thì như phần code ở trên ở hàm creatkey lại không ra được định dạng như trên ạ

  137. Anh Le Thi Ngoc viết:

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

    Additional information: Incorrect syntax near ‘=’.
    anh cho em hỏi cách chữa lỗi này ạ

  138. Ánh viết:

    Rm có một số vấn đề cần hỏi vì em đang làm chuyên đề anh có thể cho em xin mail để được phản hồi nhanh dược không ạ

  139. Ánh viết:

    Anh ơi em gửi mail nhưg vẫn chưa nhận đc câu trả lời ạ

  140. hòa viết:

    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) thì thay đổi này làm như thế nào ạ

  141. Cuong viết:

    Thầy ơi, cho em xin code hoàn chỉnh đc ko ạ

  142. Đoàn Thành Luân viết:

    Em đang học làm web, em có phần phản hồi tin tức để người xem góp ý, phản hồi bình luận. Em muốn thiết kế nó giống dạng Thầy đang làm này, Thầy có thể cho em xin hướng dẫn hoặc link để tham khảo không Thầy! Em làm bằng ngôn ngũ C#

  143. Truc viết:

    Dạ không biết có file pdf để báo cáo không ạ

  144. Nguyen Tran Thoai viết:

    Cho em hỏi: Ctrinh của em đang viết g chạy cũng ok tuy nhiên thỉnh thoảng dữ liệu trong data mất hết, không biết do lỗi gì vậy thầy

    • Phan Tiến viết:

      Chào bạn, do khi bạn mỗi lần chạy lại, nó copy lại file database từ thư mục gốc vào thư mục bin\Debug nên dữ liệu bị xoá hết.
      Cách khắc phục: bạn kích vào file database của bạn ở cửa sổ Solution Explorer > Bạn kích chuột phải chọn bật ra menu chọn Properties, bạn sẽ nhìn thấy có thuộc tính hiển thi đường dẫn đầy đủ của database, sau đó bạn copy đường dẫn này, mở file App.config thay phần “|DataDirectory|\Quanlybanhang.mdf” bằng đường dẫn cố định của file database của bạn.

  145. Quang Lê Minh viết:

    thầy ơi sao e không đổ được dữ liệu khi sử dụng hàm này ở form fdmHoaDonBan
    private void cboMaHang_SelectedIndexChanged(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 = Function.GetFieldValues(str);
    str = “SELECT DonGiaBan FROM tblHang WHERE MaHang =N'” + cboMaHang.SelectedValue + “‘”;
    txtDonGiaBan.Text = Function.GetFieldValues(str);
    }
    Mong thầy giải đáp . Cảm ơn thầy !!!

  146. Hoàng viết:

    Thầy cho em hỏi khi em nhấn lưu hoá đơn báo lỗi như thế này thầy:
    System.FormatException: ‘Input string was not in a correct format.’
    tong = Convert.ToDouble(Functions.GetFieldValues(“SELECT TongTien FROM tblHDBan WHERE MaHDBan = N'” + txtMaHDBan.Text + “‘”));

  147. Hoàng viết:

    Dấu nháy của em là: tong = Convert.ToDouble(Functions.GetFieldValues(“SELECT Tongtien FROM tblHDBan WHERE MaHDBan = N’ ” + txtMaHDBan.Text + ” ‘ “));.
    xong báo lỗi này thầy ơi: https://ibb.co/fqLMsff.

  148. Hoàng viết:

    Thêm chức năng autocomplex cho combobox nữa đi thầy .

    • Phan Tiến viết:

      Em thử đoạn code này xem sao

      private void frmMain_Load(object sender, EventArgs e)
      {
      cboComboBox1.Items.Clear();
      cboComboBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
      cboComboBox1.AutoCompleteSource = AutoCompleteSource.ListItems;
      //Phần load dữ liệu vào comboBox => cboComboBox1.DataSource = .....
      //Các phần code khác nếu có
      }

      private void cboComboBox1_KeyPress(object sender, KeyPressEventArgs e)
      {
      cboComboBox1.DroppedDown = false;
      }

  149. Hoàng viết:

    Em làm trên form HDBan thầy ơi là chổ này bị lỗi. Em đánh AutocompletMode ko được: CausesValidation.AutoCompletMode = AutoCompleteMode.Suggest;
    – Thầy giúp em đoạn code AutoComplet chổ combobox mã hàng nha thầy. Em cám ơn!
    – code form load HDBan của em ạ:
    private void frmHoaDonBan_Load(object sender, EventArgs e)
    {

    btnThem.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”;
    // ——————- Autocomplet
    cboMaHang.Items.Clear();
    CausesValidation.AutoCompletMode = AutoCompleteMode.Suggest;
    cboMaHang.AutoCompleteSource = AutoCompleteSource.ListItems;
    //Phần load dữ liệu vào comboBox => cboComboBox1.DataSource = …..
    //——————–end
    Funtions.FillCombo(“SELECT MaKhach, TenKhach FROM tblKhach”, cboMaKhach, “MaKhach”, “TenKhach”);
    cboMaKhach.SelectedIndex = -1;
    Funtions.FillCombo(“SELECT MaNhanVien, TenNhanVien FROM tblNhanVien”, cboMaNhanVien, “MaNhanVien”, “TenNhanVien”);
    cboMaNhanVien.SelectedIndex = -1;
    Funtions.FillCombo(“SELECT MaHang, TenHang FROM tblHang”, cboMaHang, “MaHang”, “TenHang”);
    cboMaHang.SelectedIndex = -1;
    Funtions.FillCombo(“select MaHDBan,Tongtien from tblHDBan”, cboMaHDBan,”MaHDBan”,”MaHDBan”);
    cboMaHDBan.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();

    }

  150. Hoàng viết:

    Em cám ơn thầy, em có làm theo hướng dẫn của thầy nhưng khi load form HDBan thì cboMaHang ko có dữ liệu thầy ơi. Thầy giúp em với ạ.

    private void frmHoaDonBan_Load(object sender, EventArgs e)
    {

    btnThem.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”;
    Funtions.FillCombo(“SELECT MaKhach, TenKhach FROM tblKhach”, cboMaKhach, “MaKhach”, “TenKhach”);
    cboMaKhach.SelectedIndex = -1;
    Funtions.FillCombo(“SELECT MaNhanVien, TenNhanVien FROM tblNhanVien”, cboMaNhanVien, “MaNhanVien”, “TenNhanVien”);
    cboMaNhanVien.SelectedIndex = -1;
    // Funtions.FillCombo(“SELECT MaHang, TenHang FROM tblHang”, cboMaHang, “MaHang”, “TenHang”);
    cboMaHang.SelectedIndex = -1;
    Funtions.FillCombo(“select MaHDBan,Tongtien from tblHDBan”, cboMaHDBan,”MaHDBan”,”MaHDBan”);
    cboMaHDBan.SelectedIndex = -1;
    // Conbobox Auto Complet
    //cboMaHang.Items.Clear();
    cboMaHang.AutoCompleteMode = AutoCompleteMode.Suggest;
    cboMaHang.AutoCompleteSource = AutoCompleteSource.ListItems;
    //Phần load dữ liệu vào comboBox
    cboMaHang.DataSource = tblCTHDB;
    //————————————————————–
    //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();

    }

    • Phan Tiến viết:

      Hức hức, em đóng mất phần code load dữ liệu vào cboMatHang còn đâu.

      private void frmHoaDonBan_Load(object sender, EventArgs e)
      {

      btnThem.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”;
      Funtions.FillCombo(“SELECT MaKhach, TenKhach FROM tblKhach”, cboMaKhach, “MaKhach”, “TenKhach”);
      cboMaKhach.SelectedIndex = -1;
      Funtions.FillCombo(“SELECT MaNhanVien, TenNhanVien FROM tblNhanVien”, cboMaNhanVien, “MaNhanVien”, “TenNhanVien”);
      cboMaNhanVien.SelectedIndex = -1;
      // Conbobox Auto Complet
      //cboMaHang.Items.Clear();
      cboMaHang.AutoCompleteMode = AutoCompleteMode.Suggest;
      cboMaHang.AutoCompleteSource = AutoCompleteSource.ListItems;
      Funtions.FillCombo(“SELECT MaHang, TenHang FROM tblHang”, cboMaHang, “MaHang”, “TenHang”);
      cboMaHang.SelectedIndex = -1;
      //Phần load dữ liệu vào comboBox
      Funtions.FillCombo(“select MaHDBan,Tongtien from tblHDBan”, cboMaHDBan,”MaHDBan”,”MaHDBan”);
      cboMaHDBan.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();

      }

  151. Hoàng viết:

    Em cám ơn thầy rất nhiều, em đã làm được.
    Thầy cho em hỏi thêm là hiện tại em chỉ tìm được ký tự đầu của của dãy ký tự trong cboMaHang. Thầy có thể hướng dẫn em cách tìm 1 ký tự bất kỳ của 1 mã hàng ko ạ.

  152. Lâm Anh viết:

    Thưa thầy cho em hỏi ạ. Phần from Hóa đơn bán đang có phần Đơn giá bán, Đơn giá nhập đều tiếp nhận cả 2 loại giá trị dương và âm. Phải làm thế nào để Đơn giá nhập, Đơn giá bán chỉ tiếp nhận giá trị dương thôi ạ, còn nếu nhập vào giá trị âm thì sẽ báo lỗi ạ??? Mong thầy giúp em với ạ.

  153. Lâm Anh viết:

    Thưa thầy cho em hỏi ạ. Trong danh mục Hàng hóa, em muốn phần số lượng chỉ nhận giá trị dương nếu nhập giá trị âm sẽ báo lỗi thì nên làm thế nào ạ???
    Và khi nhấp vào 1 dữ liệu đã được nhập thì có thể sửa thêm cả Đơn giá nhập, đơn giá bán (Điều kiện: Đơn giá bán > Đơn giá nhập) (Đơn giá nhập, bán đang bị khóa) thì nên làm thế nào ạ??? Mong thầy giúp em với ạ.
    https://drive.google.com/file/d/1hEnwXJ-nK8VHW_SJ0cFI6QC-tyMHmX-z/view?usp=sharing

  154. Hoàng viết:

    Thầy cho em hỏi là ở form Nhân viên em viết code như thế này mà sao trên lưới datagridview không hiển thị được thông tin nhân viên Thầy ơi.
    private void frmNhanvien_Load(object sender, EventArgs e)
    {
    txtMaNhanVien.Enabled = false;
    btnLuu.Enabled = false;
    btnBoQua.Enabled = false;
    LoadDataGridView();
    }
    public void LoadDataGridView()
    {
    string sql;
    sql = “SELECT * from tblNhanvien”;
    tblNV = Funtions.GetDataToTable(sql); //lấy dữ liệu
    dgvNhanVien.DataSource = tblNV;
    dgvNhanVien.Columns[0].HeaderText = “Mã nhân viên”;
    dgvNhanVien.Columns[1].HeaderText = “Tên nhân viên”;
    dgvNhanVien.Columns[2].HeaderText = “Giới tính”;
    dgvNhanVien.Columns[3].HeaderText = “Địa chỉ”;
    dgvNhanVien.Columns[4].HeaderText = “Điện thoại”;
    dgvNhanVien.Columns[5].HeaderText = “Ngày sinh”;
    dgvNhanVien.Columns[0].Width = 100;
    dgvNhanVien.Columns[1].Width = 150;
    dgvNhanVien.Columns[2].Width = 100;
    dgvNhanVien.Columns[3].Width = 150;
    dgvNhanVien.Columns[4].Width = 100;
    dgvNhanVien.Columns[5].Width = 100;
    dgvNhanVien.AllowUserToAddRows = false;
    dgvNhanVien.EditMode = DataGridViewEditMode.EditProgrammatically;
    }

  155. Hoàng viết:

    Em làm được rồi ạ.

  156. Nguyễn Minh Đạt viết:

    thưa thầy, e có một vấn đề là khi load formNhanVien thì dữ liệu từ sql server vẫn dc upload,nhưng khi thêm dữ liệu từ textbox nhấn nút lưu thì báo lỗi, e đã định dạng ngày giờ của máy tính giống ngày giờ sql server.Lỗi báo như thế này.
    https://www.upsieutoc.com/image/error.ffAvjs

  157. Nghi viết:

    Thầy cho em hỏi chút là khi thực hiện chức năng thêm xóa sửa trong form chất liệu thì chạy bình thường, nhưng khi ngừng debug thì toàn bộ dữ liệu mình vừa thêm vào cũng k còn nữa là sao ạ

  158. Sơn viết:

    Mọi người ai có bài code hoàn chỉnh cho em xin với ạ.
    E code giống thầy vẫn bị lỗi.
    E cảm ơn.

  159. Nghi viết:

    Thầy cho em hỏi là trong hướng dẫn của thầy không có phần sourcecode của chức năng báo cáo hàng tồn, báo cáo doanh thu, tìm kiếm khách hàng và tìm kiếm hàng ạ

  160. Đức viết:

    Thầy cho em hỏi ở chỗ hướng dẫn nút Thêm trong mục hóa đơn. Sau khi em kick nút Thêm thì phần mềm không chạy và báo lỗi ở dòng if (partsTime[2].Substring(3, 2) == “PM”) trong hàm Creatkey như sau: System.ArgumentOutOfRangeException: ‘startIndex cannot be larger than length of string.
    Parameter name: startIndex’ là sao ạ. Em cảm ơn thầy

  161. Nghi viết:

    Thầy cho em hỏi là form hóa đơn e nhập dữ liệu thì được nhưng tren dgv thì k hiển thị gi cả như trong hình này là sao ạ
    https://i.imgur.com/zT1WqX3.png

    • Nghi viết:

      Dữ liệu hóa đơn vẫn được cập nhật trong database bình thường nhưng không hiển thị trên dgv ạ. các form khác thì dgv hiển thị bình thường

    • Nghi viết:

      E code ngay sau đoạn Loaddatagridview, LoadInfoHoaDon và Chuyentusosangchu rồi chạy thử thì đã thấy dgv không hiện như trên demo của thầy rồi ạ
      code Loaddatagridview của e:
      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);
      dgvHDBanHang.DataSource = tblCTHDB;
      dgvHDBanHang.Columns[0].HeaderText = “Mã hàng”;
      dgvHDBanHang.Columns[1].HeaderText = “Tên hàng”;
      dgvHDBanHang.Columns[2].HeaderText = “Số lượng”;
      dgvHDBanHang.Columns[3].HeaderText = “Đơn giá”;
      dgvHDBanHang.Columns[4].HeaderText = “Giảm giá %”;
      dgvHDBanHang.Columns[5].HeaderText = “Thành tiền”;
      dgvHDBanHang.Columns[0].Width = 80;
      dgvHDBanHang.Columns[1].Width = 130;
      dgvHDBanHang.Columns[2].Width = 80;
      dgvHDBanHang.Columns[3].Width = 90;
      dgvHDBanHang.Columns[4].Width = 90;
      dgvHDBanHang.Columns[5].Width = 90;
      dgvHDBanHang.AllowUserToAddRows = false;
      dgvHDBanHang.EditMode = DataGridViewEditMode.EditProgrammatically;
      }

    • Nghi viết:

      Em thử xóa hết đi rồi code lại 3 phương thức Loaddatagridview, LoadInfoHoaDon và ChuyenTuSoSangChu rồi chạy thử thì đã thấy dgv trong frm HoaDon không hiện gì rồi ạ

  162. Nghi viết:

    Em thử xóa hết đi rồi code lại 3 phương thức Loaddatagridview, LoadInfoHoaDon và ChuyenTuSoSangChu rồi chạy thử thì đã thấy dgv trong frm HoaDon không hiện gì rồi ạ

  163. Hoàng viết:

    Thầy cho em hỏi trong form Hoá đơn bán. thi em thêm 1 mặt hàng thì mặt hàng đó ko tự nhảy xuống datagridview mà em phài nhấn lưu mới thấy ạ. Như vậy khi bán 2 mặt hàng thì làm như thấy nào thấy ơi.
    Thầy hướng dẫn em cách nào mà khi em đánh số lượng thì mặt hàng đó tự nhảy xuống datagridview, để em nhập mặt hàng thứ 2 ko ạ.
    Cám ơn thầy nhiều ạ!

  164. Lưu quang vũ viết:

    anh ơi cho e hỏi chỗ em kết nối SQL sao nó cứ bảo không thể kết nối dữ liệu vậy ạ

  165. Hoàng viết:

    Thầy cho em hỏi em tạo nút in Hoá đơn bằng report như thế này:
    SqlConnection Con= new SqlConnection( @”Data Source=ADMIN;Initial Catalog=Quanlybanhang;Integrated Security=True”);
    Con.Open();
    SqlCommand cmd = new SqlCommand(“SELECT tblChitietHDBan.Mahang where MaHDBan=N'” + txtMaHDBan.Text + “‘”,Con);
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    DataTable dt = new DataTable();
    da.Fill(dt);
    Con.Dispose();
    Con.Close();

    Nhưng giờ em muốn viết trong class Funtion như các class khác để gọi ra trên nút In hoá đơn thì viết class như thế nào ạ, em cũng thử viết mà cứ báo lỗi hoài Thầy ơi. Mong thầy hướng dẫn em chổ này ạ
    Em cám ơn Thầy nhiều!

    • Phan Tiến viết:

      Trong kớp Functions.cs mình đã viết tất các phương thức rồi, giờ bạn chì cần gọi ra thôi.
      Ví dụ đoạn code này bạn có thể gọi như sau:

      
      Functions.Connect();
      string sql = "SELECT * FROM tblChitietHDBan WHERE MaHDBan=N'" + txtMaHDBan.Text + "'";
      DataTable dt = Functions. GetDataToTable(sql);
      

      có dữ liệu lưu ở dt rồi, em có thể gắn vào đâu thì gắn thôi

  166. Nguyễn+Minh+Đạt viết:

    Thưa thầy, khi load from lên thì danh sách hóa đơn hiện ra, e tìm kiếm một mã hóa đơn bất kì thì trên datagridview không hiện hóa đơn tìm kiếm, mà lại hiện danh sách hóa đơn.Bây h muốn hiện một hóa đơn tìm kiếm thì phải làm sao ạ. Em đã thử nhiều cách nhưng kh thành.
    https://www.upsieutoc.com/image/f7s5RK
    https://www.upsieutoc.com/image/f7s8ML

  167. Ánh Dương viết:

    em chào thầy ạ, thầy cho em hỏi lúc em chạy code của form HoaDonBanHang thì nó báo lỗi trong lớp Functions ở phương thức FillCombo như này ạ: System.InvalidOperationException: ‘Fill: SelectCommand.Connection property has not been initialized.’
    Thầy cho em hỏi lỗi gì đây và cách sửa như nào thế ạ, e cảm ơn thầy ạ

  168. Nghi viết:

    Thầy cho em hỏi là em thử tạo ra một form tìm kiếm nhân viên, khi truy suất từ sql thì em có dùng bộ lệnh sau:
    sql = “SELECT * FROM tblNhanVien WHERE 1=1 “;
    if (txtMaNhanVien.Text != “”)
    sql += ” AND MaNhanVien LIKE N’%” + txtMaNhanVien.Text + “%'”;
    if (txtTenNhanVien.Text != “”)
    sql += ” AND TenNhanVien LIKE N’%” + txtTenNhanVien.Text + “%'”;
    if (mtbDienThoai.Text != “”)
    sql = sql + ” AND DienThoai Like N’%” + mtbDienThoai.Text + “%'”;
    tblNV = Functions.GetDataToTable(sql);
    if (tblNV.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ó ” + tblNV.Rows.Count + ” bản ghi thỏa mãn điều kiện!”, “Thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);
    dgvTKNhanVien.DataSource = tblNV;
    LoadDataGridView();
    Nhưng khi chạy phần mềm thì chỉ tìm được nhân viên bằng số điện thoại, còn khi tìm bằng tên nhân viên và mã nhân viên thì luôn bị ghi là “Không có bản ghi thỏa mãn điều kiện”. Thầy giúp em xem code này lỗi ở đâu được không ạ

  169. Sơn viết:

    tong = Convert.ToDouble(Functions.GetFieldValues(“SELECT TongTien FROM ChiTietHoaDon WHERE MaHoaDon = N'” + tb_mahoadon.Text + “‘”));
    Tongmoi = tong + Convert.ToDouble(tb_thanhtien.Text);
    sql = “UPDATE ChiTietHoaDon SET TongTien =” + Tongmoi + ” WHERE MaHoaDon = N'” + tb_mahoadon.Text + “‘”;
    Functions.RunSQL(sql);
    tb_tongtien.Text = Tongmoi.ToString();
    em làm đến bước này thì báo lỗi sql của tổng tiền xin thầy sửa giúp em

  170. Khang Nguyễn viết:

    thầy ơi, cho e hỏi cách tạo SQL như trên thì có thêm các khóa ngoại ko ạ! e ko hiểu lắm

  171. Kieutien viết:

    Thầy ơi trong phần load trong frmmain class.function.conection() bị báo lỗi trong phần function rằng exception unhandled… login user … là sao ạ mong thầy giúp đỡ

    • Phan Tiến viết:

      Em phải chụp chi tiết lỗi lên thì mới biết được. Như phần mô tả này thì nó liên quan đến tài khoản để truy xuất vào Database

    • Ngọc Tú viết:

      Chuỗi kết nối mỗi máy khác nhau và cũng khác nhau tùy vào việc bạn dùng dịch vụ Database nào.
      Để lấy được chuỗi kết nối Database, bạn vào View->server explorer, trong cửa sổ này, bấm vào hình tam giác đen cạnh Data Connections sẽ sổ xuống, nhìn thấy Database của bạn, click phải chọn propreties, trong đây có thuộc tính Connection string, copy từ chữ Data source tới hết chuỗi.
      Past vào dòng code tương tự như của mình thế này: Con.ConnectionString = @”Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = D:\Documents\QuanLyBanHang\Quan_Ly_Ban_Hang\Quan_Ly_Ban_Hang\bin\Debug\QuaLyBanHang.mdf; Integrated Security = True; Connect Timeout = 30″;

      Good luck!

  172. Lâm Phú viết:

    Thầy ơi ở phần (g) sau khi em thêm dữ liệu trên bảng nhân viên thì khi nhấn nút lưu nó hiện lỗi là: Additional information: An expression of non-boolean type specified in a context where a condition is expected, near ‘Nhân’ nó chỉ sai ở hàm Checkey (dap.Fill(table)); Thầy giúp em sửa lỗi với ạ!

  173. kien viết:

    em thưa thầy cho e hỏi khi em nhập dữ liệu vào ô textbox xong e nhấn nút lưu thì nó báo lỗi như trong ảnh https://www.upsieutoc.com/image/vLbn8b mong thầy giải đáp

    • Phan Tiến viết:

      Lỗi này liên quan đến việc em đã đóng mất kết nối rồi nên em không thể lưu dữ liệu vào CSDL được nữa.
      Quy trình thực hiện truy cập với CSDL:
      Mở kết nối
      Thực hiện truy vấn
      Đóng kết nối
      => Vì vậy em muốn xử lý lỗi này chỉ cần mởi lại kết nối là OK

  174. lek viết:

    thầy ơi giúp cái frm tìm hóa đơn bán vậy
    h) Phương thức dgvTKHoaDon_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) làm thế nào

  175. SK viết:

    anh ơi! làm ơn cho cho e hỏi…?
    em đang làm phần frmHDBan nhưng khi em [Thêm Hóa đơn] thì bị lỗi :”‘StartIndex giá trị chỉ định không được lớn hơn độ dài của chuỗi.”
    https://www.upsieutoc.com/image/error.wSSIjk
    Mong được anh giải đáp/

  176. Đạt viết:

    thầy ơi cho em hỏi với ạ e, làm đến form hóa đơn em xem video của thầy em chỉnh lỗi lưu hóa đơn nhưng khi làm theo thầy thì em lại bị lỗi này ạ hình
    https://drive.google.com/file/d/1WPVIxvQN82bx4uY9sIZGtei5laNhyEOh/view?usp=sharing
    và sau đó khi em ấn ok thì bị lỗi này ạ https://drive.google.com/file/d/19McdQPyrZ6-2GE-xLovWwm7BknZ4TtXu/view?usp=sharing
    và trong phần in ra ex thì em lại bị lỗi này ạ https://drive.google.com/file/d/1n4RtT9xZj2UBTuDrZiyZVbimPh177eds/view?usp=sharing
    thầy có thể giúp em dc luôn vid mai em phải nộp rồi ạ em cảm ơn thầy nhiều ạ

  177. Nguyễn Hoàng viết:

    thầy ơi cho em hỏi phần SelectedIndexChanged, tất cả các cbo e làm không lổi gì hết. nhưng chạy lại ko ra. Thầy cho e hỏi lổi thường do đâu ạ.

  178. Trung Le viết:

    thầy cho em hỏi e đã xóa frmLogin và tblLogin (e tạo thêm), đi rồi và trên Program em để gọi form Main ra nhưng sao F5 nó vẫn mở form Login (ko biết ở đâu ra)?

    • Phan Tiến viết:

      Em vào menu Build > Rebuild để biên dịch lại code của em, xem nó có báo lỗi gì.
      Như em nói, khi em ấn F5, nó biên dịch có thể nó báo lỗi nhưng em vẫn ấn Yes để chạy, nên nó chạy file cũ (.exe) đã biên dịch cũ trước đây.

  179. Nguyễn Hoàng viết:

    Chào thầy ạ. Em đóng gói bằng setup project. Cài đặt ok. Vô chương trình ok. Nhưng đến khi lưu bị lổi “because database read only”. Mong thầy giúp. Em cám ơn ạ.

  180. trunglh viết:

    Em chào thầy
    Hiện e đang code đến bảng quản lý nhân viên. Khi save code ko báo lỗi gì, chạy cũng ok, nhưng khi nhập xong thông tin nhân viên rồi lưu lại thì báo lỗi ở hàm kiểm tr khóa trùng.
    //Hàm kiểm tra khoá trùng
    public static bool CheckKey(string sql)
    {
    SqlDataAdapter dap = new SqlDataAdapter(sql,Con);
    DataTable table = new DataTable();
    dap.Fill(table);
    if (table.Rows.Count > 0)
    return true;
    else return false;
    }

    Báo lỗi tại Function
    tại dòng “dap.Fill(table);”
    Lỗi Invalid column name ‘MaNhanVien’.
    Invalid column name ‘MaNhanVien’.

    Xin thầy support
    Em cảm ơn

  181. Lê Lợi viết:

    Thầy cho e hỏi lúc thêm dữ liệu trên giao diện xong rồi khởi động lại thì dữ liệu bị mất hết,không lưu được trong SQL. Lỗi như thế là vì lí do gì vậy ạ? Em đã chuyển sang chế độ Copy always

    • Lê Lợi viết:

      Cùng với Click chuột lúc chưa có dữ liệu gì thì vẫn không hiện MessageBox “Không có dữ liệu!” ah. Kết nối dữ vẫn thành công.

    • Phan Tiến viết:

      Vì em chọn Copy Always nên mỗi lần chạy mới, Chương trình biên dịch sẽ copy database từ bên ngoài vào thư mục chạy của chương trình (thư mục Debug) nên dữ liệu của em sẽ bị mất hết. Em nên để chế độ Copy if newer hoặc chỉnh sửa đường dẫn đến file database ở bên ngoài.

  182. Duy viết:

    thầy cho em hỏi, em nhấn vào nút lưu trong hóa đơn bán hàng và nó bị lỗi như này thì phải sửa như thế nào ạ?
    System.ArgumentOutOfRangeException: ‘Index and length must refer to a location within the string.
    Parameter name: length’

  183. đăng bùi viết:

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

    Additional information: Invalid object name ‘tblChiTietHDBan’.

  184. Tường Vy viết:

    Anh ơi, cho em xin dữ liệu của bảng với ,em cảm ơn

  185. Tran viết:

    Dạ e chào thầy, thầy cho e hỏi là e bị lỗi ở FillCombo ở dòng dap.Fill(table):

    An unhandled exception of type ‘System.InvalidOperationException’ occurred in System.Data.dll
    Additional information: Fill: SelectCommand.Connection property has not been initialized.

    Lỗi e ở class Functions, và nó báo lỗi ở frmHDBan

    Functions.FillCombo(“SELECT MaKH, TenKH FROM tbKHACHHANG”, cboMaKH, “MaKH”, “TenKH”);

    E làm đúng trên vid bài form Hóa đơn bán của thầy nhưng k hiểu sao e bị lỗi vậy. Mong thầy giúp e với ạ. E cảm ơn thầy!

  186. viết:

    Chào anh!
    em có 1 thắc mắc là khi tạo localDB, em mang sang máy khác, cũng đã cài đặt SQLLOCALDB nhưng ko biết thay đổi sao cho phù hợp DB em để chung thư mục với chương trình. máy khác em chỉ cài mỗi SQLLOCALDB đc ko anh?.

    chuỗi connection của em trong file config là:
    connectionString=”Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Demo.mdf;Integrated Security=True;Connect Timeout=30″

    nếu là localDB thì em giữ nguyện được phải ko anh?

    • Phan Tiến viết:

      Tuỳ thuộc vào việc cài đặt trên máy tính của bạn, nhưng bạn chú ý
      (LocalDB) => có thể thay bằng tương ứng với tên máy tính của bạn hoặc địa chỉ IP máy tính của bạn
      MSSQLLocalDB => là tên install (bản cài đặt) trên máy bạn, SQL Server cho phép bạn cài đặt nhiều bản khác nhau trên cùng một máy tính
      Nên để nó chạy được thì bạn cần kiểm tra lại chính xác phần Data Source=(LocalDB)\MSSQLLocalDB, nếu tên MSSQLLocalDB khác thì bạn cần phải sửa cho đúng. Còn (LocalDB) cũng có thể thay bằng tên máy tính của bạn hoặc địa chỉ IP cũng được.

      • viết:

        Chào anh,
        cảm ơn anh đã trả lời thắc mắc của em.
        em đã thử đổi tên máy(hoặc ip) thay cho (LocalDB), còn MSSQLLocalDB em kiểm tra trong cmd thì đúng tên MSSQLLocalDB này (cùng version sqllocaldb 2016).
        nó có ảnh hưởng gì đến quyền truy cập file mdf hay ko anh? khi em copy data source trong visual (connection string) nó lại chạy bình thường trên máy em , còn máy khác vẫn ko được(đã thay đổi đường dẫn file).
        em cảm ơn anh.

        • Phan Tiến viết:

          Mình rõ phần em nói “khi em copy data source trong visual (connection string) nó lại chạy bình thường trên máy em” => vì chương trình này vẫn chạy trên máy em mà.
          Em thử chạy trên máy tính kia xem nó báo lỗi chi tiết là gì chụp ảnh gửi link cho anh.

  187. Thanh Hung viết:

    Khi nhấn nút lưu làm sao để kiểm tra và hiển thị thông báo lưu thành công ạ

  188. Thanh Thiện viết:

    System.NullReferenceException: ‘Object reference not set to an instance of an object.’
    lỗi này fix làm sao ạ.
    Trong phần này của code btnLuu của FrmDMHangHoa
    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() + “‘)”;

  189. hưng viết:

    nếu em muốn update cái giá mới của sản phẩm mà không làm thay đổi những hóa đơn cũ thì có phải thêm bảng nào không ạ em xin cảm ơn mong anh phản hồi

    • Phan Tiến viết:

      Cảm ơn câu hỏi hay của bạn! Hiện tại theo CSDL ở trên, việc bạn thay đổi giá sản phẩm thì sẽ không ảnh hưởng gì đến hoá đơn cũ cả, vì theo thiết kế này, tại thời điểm lập hoá đơn, giá đã được copy sang bảng hoá đơn chi tiết. Nên sau đó bạn cập nhật giá bên bảng sản phẩm thì cũng không ảnh hưởng gì đến các hoá đơn đã lập.

  190. duy viết:

    lỗi này fix làm sao ạ Input string was not in a correct format
    tong = Convert.ToDouble(Functions.GetFieldValues(“SELECT TongTien FROM HDBan WHERE MaHDBan = N'” + txtMaHoaDon.Text + “‘”));
    Tongmoi = tong + Convert.ToDouble(txtThanhTien.Text);
    sql = “UPDATE HDBan SET TongTien =” + Tongmoi + ” WHERE MaHDBan = N'” + txtMaHoaDon.Text + “‘”;
    Functions.RunSQL(sql);
    txtTongTien.Text = Tongmoi.ToString();

    • Phan Tiến viết:

      Em xem nó báo lỗi ở dòng nào? Như trường hợp của em lỗi liên quan đến việc chuyển đổi dữ liệu sang kiểu double bị lỗi.
      Em chạy riêng câu SQL: SELECT TongTien FROM HDBan WHERE MaHDBan = ‘mã hoá đơn của em’ xem nó ra dữ liệu là bao nhiêu
      Tiếp theo kiểm tra giá trị truyền vào txtThanhTien.Text

      • duy viết:

        em chạy debug thì nó lỗi ở phần :
        INSERT INTO HDBan(MaHDBan, NgayBan, MaNhanVien, MaKhach, TongTien) VALUES (N’HDB12272020_184715′,’12/27/2020 12:00:00 AM’,N’NV01′,N’K01′,) .
        em thấy thiếu tổng tiền nhưng k biết xử lí sao 🙁

        • duy viết:

          sql = “INSERT INTO HDBan(MaHDBan, NgayBan, MaNhanVien, MaKhach, TongTien) VALUES (N'” + txtMaHoaDon.Text.Trim() + “‘,'” +
          dtpNgayBan.Value + “‘,N'” + cbxMaNhanVien.SelectedValue + “‘,N'” +
          cboMaKhach.SelectedValue + “‘,” + txtTongTien.Text.Trim() + “)”;
          đây là câu truy vấn của e

        • Phan Tiến viết:

          Trường hợp của em do ô Tổng tiền nó bị trống nên câu lệnh Insert nó thiếu phần tổng tiền. Em nên để giá trị mặc định cho Tổng tiền = 0 hoặc em kiểm tra nếu tổng tiền không có thì gán giá trị mặc định cho nó bằng 0 là chạy dc.

  191. dungkq viết:

    Em muốn tự học lập trình phần mềm quản lý bán hàng như thế này, cách học như thế nào vậy thầy, có thể lưu videos về để tự học được hay không thầy.

    • Phan Tiến viết:

      Bạn muốn học về lập trình đặc biệt là tự học thì cần phải có:
      – Tinh thần tự giác cực kỳ cao, khi gặp khó, gặp lỗi không được bỏ cuộc
      – Nên bắt đầu từ các bài tập lập trình căn bản trước để có kiến thức, tư duy về lập trình
      – Rồi bắt đầu làm những bài tập, project phức tạp hơn
      Làm nhiều, thực hành nhiều thì trình độ sẽ tăng lên. Gặp vấn đề gì thì tích cực vào google tìm kiếm giải pháp, hiện nay tìm trên google là có hết, quan trọng mình có hiểu và biến thành cái của mình hay không thôi.
      Chúc bạn thành công!

  192. Nguyễn Anh Trung viết:

    Em Chào Thầy!
    Thầy cho em hỏi làm sao để thay đổi kích thước anh cho vừa với pictureBox trong giao diện vậy ạ.Em Import vào vào hiện không đủ ảnh

  193. Nguyễn Nam Long viết:

    cho e hỏi ạ??? e làm đến đoạn thêm và lưu đc như đoạn này:
    https://youtu.be/8rBQLCrl6OM?t=649
    nhưng sau khi thoát ra ngoài, vào lại thì thông tin trc đó ko còn nữa ạ, ko giống thầy đoạn: https://youtu.be/8rBQLCrl6OM?t=1195
    vẫn còn KH01 ạ
    video gốc: https://www.youtube.com/watch?v=8rBQLCrl6OM&t=2s

    • Phan Tiến viết:

      Do khi chạy lại, chương trình của bạn lại copy lại Database từ bên ngoài vào nơi chứa chương trình chạy trong thư mục Debug nên toàn bộ dữ liệu bạn đã nhập bị mất hết.
      Bạn có thể xử lý đơn giản như sau:
      Sửa lỗi bị mất dữ liệu nhập vào sau khi chạy lại chương trình

      Bạn có thể xử lý cách khác bằng cách thay đường dẫn cố định đến nơi thư mục chứa database của bạn.

  194. Hoài viết:

    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

  195. Minh Đức viết:

    Cho em hỏi khi em ấn nút thêm ở frmDMNhanVien thì nó báo lỗi The conversion of the varchar data type to a datetime data type resulted in an out-of-range value. là sao ạ?

  196. khoa viết:

    hình thức bán hàng này so với hàng kí gửi thì khác nhau, thì xây dựng cơ sở dữ liệu như thế nào ạ!

    • Phan Tiến viết:

      Một câu hỏi khá hay! Hiểu thêm về hàng ký gửi, tức là các nhà cung cấp sẽ gửi hàng tại các cửa hàng, các đại lý mà đơn vị bán hàng không phải bỏ tiền ra trước. Khi có khách hàng mua, thì cửa hàng mới thanh toán cho nhà cung cấp. Hàng sau một thời gian ký gửi nếu không bán được, hết hạn thì có thể trả lại cho nhà cung cấp. Vì vậy hàng ký gửi đương nhiên là sẽ phải thiết kế để quản lý khác. Bạn cần phải phân tích nhu cầu thực tế để có hướng giải quyết thích hợp.
      Mình xin tư vấn một số phần bạn cần thiết kế CSDL:
      – Danh mục nhà cung cấp sẽ ký gửi
      – Danh mục hàng hoá ký gửi
      – Bảng quản lý hàng ký gửi theo nhà cung cấp, số lượng, số lô, số hoá đơn ….
      – Bảng quản lý hàng ký gửi bán cho khách hàng => Sau này sẽ tính doanh thu

  197. Toàn viết:

    không cập nhật được số lượng hàng hóa hã thầy???

  198. Ngọc viết:

    chỗ bảng nhân viên, khi nhập ngày sinh r nhấn nút lưu thì lại hiện dòng lỗi như này là sao ạ “Conversion failed when converting date and/or time from character string”

  199. longdang886 viết:

    Thầy có thể giúp e chi tiết hơn phần cuối của project form tìm kiếm ạ “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 chưa hiểu và chưa làm được chỗ này ạ

  200. Thành viết:

    Thầy hướng dẫn form tìm khách hàng và hàng đi ạ

  201. Mạnh Đức viết:

    Thưa thầy. Thầy cho e hỏi phần Quan hệ giữa các bảng (Relationship) thực hiện như thế nào ạ. E cảm ơn

  202. Mạnh Đức viết:

    https://drive.google.com/file/d/1ys5ZC1eX6uevLLX6fgkYBvcdxz1icO-M/view?usp=sharing
    Thưa thầy. E chạy thử thì báo lỗi như ảnh trên. Thầy giải đáp giúp e vs

  203. Long viết:

    em chào thầy, em có chỗ muốn hỏi thầy giải đáp giúp e với ạ.
    public static string GetFieldValues(string sql)
    {
    string ma = “”;
    SqlCommand cmd = new SqlCommand(sql, conn);
    SqlDataReader reader;
    reader = cmd.ExecuteReader();
    while (reader.Read())
    ma = reader.GetValue(0).ToString();
    reader.Close();
    return ma;
    }
    em muốn chuyển đoạn code này sang dạng int thì làm nnao ạ, của thầy đang đổ sang dạng varchar với các mã, của em là dạng int ạ.

    • Phan Tiến viết:

      Khi bắt đầu chỉnh sửa, em cần phải xem đầu vào, đầu ra của em. Ví dụ như hàm trên em nhìn thấy có câu lệnh return ma; mà biến “ma” khai báo ở trên là string. Nên em muốn trả về kiểu int thì em cần sửa 2 chỗ: 1 là kiểu trả về của phương thức, 2 là kiểu giá trị mà mình sẽ trả về.

      public static int GetFieldValues(string sql)
      {
      int ma = -1;
      SqlCommand cmd = new SqlCommand(sql, conn);
      SqlDataReader reader;
      reader = cmd.ExecuteReader();
      while (reader.Read())
      ma = int.Parse(reader.GetValue(0).ToString());
      reader.Close();
      return ma;
      }

      Chú ý: nếu reader.GetValue(0) trả về giá trị khác kiểu int ví dụ như string có thể gây lỗi nhé.

      • Long viết:

        em muốn dùng câu functions trên để hiển thị sang textbox khi chọn 1 dữ liệu trên cbo ý ạ, em dùng đoạn trên của thầy để chuyển sang vẫn không được thì làm như nào ạ, vdu đây ạ:
        private void cboId_MaMH_SelectedIndexChanged(object sender, EventArgs e)
        {
        string str;
        if (cboId_MH.Text == “”)
        txtTenMH.Text = “”;
        str = “SELECT TenMH FROM tblMonHoc WHERE ID='” + cboId_MH.SelectedValue + “‘”;
        txtTenMH.Text = Connect.GetFieldValues(str);
        }

  204. Huy viết:

    A ơi, e bị lỗi: “Project File Line Suppression State
    Error CS5001 Program does not contain a static ‘Main’ method suitable for an entry poin”

    Lỗi này là chưa có hàm Main pk anh, mà e cũng k thấy hàm Main ở trên đâu anh nhỉ

    • Phan Tiến viết:

      Bạn tạo ứng dụng dạng winform hay ứng dụng dạng Console đó?
      Mỗi Project sẽ có một hàm Main để chạy chương trình. Nếu ứng dụng của bạn là winform, bạn có thể tìm thấy file Program.cs nằm cùng cấp với các form của bạn.
      Đây là nội dung file Program.cs:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Threading.Tasks;
      using System.Windows.Forms;

      namespace QuanLyBanHang
      {
      static class Program
      {
      ///

      /// The main entry point for the application.
      ///

      [STAThread]
      static void Main()
      {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new frmMain());
      }
      }
      }

  205. Thọ Hiền viết:

    thầy cho em hỏi làm sao để thiết lập quan hệ giữ các bảng trong database vậy ạ

  206. Nguyễn Phước Tuấn viết:

    cho em hỏi lỗi “số lượng tham số không khớp với số lượng giá trị tham số” sửa như nào ạ. Mong thầy giúp em ạ
    Email: phuoctuan088@gmail.com

  207. Hải Đào Văn viết:

    Mọi người ơi cho em hỏi là cái tbl hóa đơn chi tiết mình sẽ bỏ trống để nhập dữ liệu vào sau ạ?

  208. Nguyễn Phước Tuấn viết:

    System.NullReferenceException: ‘Object reference not set to an instance of an object.’
    Cho em hỏi lỗi này sửa sao ạ

  209. Xuân Quyết viết:

    thưa thầy khi em thục hiện nút lưu ở from hóa đơn bán thì nó bão lỗi ở đây
    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ỗ cmd.ExecuteNonQuery(); //Thực hiện câu lệnh SQL
    và không show ra đucợ hóa đơn đã lưu ạ

  210. KhÁNH viết:

    dap.Fill(table); em bị báo nỗi khi lưu thông tin khách hàng thì phải làm sao ạ

  211. Hoà viết:

    Em làm được rồi thầy
    em cam on ah

  212. Dũng viết:

    Cho em hỏi xíu, kiến trúc bài toán này anh viết theo kiểu gì ạ? Client-server hay 3-tiers

  213. Vo Duy viết:

    Thầy ơi cho e hỏi là chức năng xóa hàng hóa, có xóa được hàng hóa vừa thêm vào thôi hay sao ạ? tại vì e chạy chương trình không xóa được hàng hóa có sẵn trong database ạ!

  214. huynhvanquy viết:

    thầy oi ! ở phần hàng hóa em nhập thông tin đầy đủ và bấm lưu thì nó bị lỗi code ở phần này ,
    hay là do ảnh sai v thầy ???
    public static void FillCombo(string sql, ComboBox cbo, string ma, string ten)
    {
    SqlDataAdapter dap = new SqlDataAdapter(sql, con);
    DataTable table = new DataTable();
    dap.Fill(table);
    cbo.DataSource = table;
    cbo.ValueMember = ma; //Trường giá trị
    cbo.DisplayMember = ten; //Trường hiển thị
    }

  215. DongNguyen viết:

    Thầy ơi em cho em hỏi là , của em ở frm Hàng hóa sự kiến cell click khi ấn vào nó cứ báo lỗi ở picAnh ạ
    https://drive.google.com/file/d/1iOy4iCF4rqmVEerzH_3ts1-sH6la6VNf/view?usp=sharing

  216. huynhvanquy viết:

    Thầy cho e hỏi khi em nhập thông tin vào form và lưu nó xong em thoát ra visual và nó lại mất e ko tại sao nó lại ko lưu dữ liệu thầy hay là mình thêm dữ liệu cho nó ạ ???

  217. overcome viết:

    https://drive.google.com/file/d/1s_WjqE3yabskPi2ActXwygyJJjYjTyDL/view?usp=sharing
    Thầy giúp em với ạ, em lưu 2 sản phẩm không được nó bị lỗi này ạ

  218. Kha viết:

    Thầy giúp em lỗi này với ạ
    https://drive.google.com/file/d/18NMMgUAJXmpsYP_koRCfBKnuF99b8t5r/view?usp=sharing
    khi em thêm một hóa đơn thì nó bị như vậy

  219. NguyenDuc viết:

    Thầy hỗ trợ em với ạ, em có làm 1 bài Quản lý bán laptop cũng giống bài này của thầy, khi em thêm hóa đơn thì bị lỗi như này ạ
    https://drive.google.com/file/d/1DLiYdhj4payCUQE5RgI_l9zh4OHAQbBd/view?usp=sharing

  220. maymay viết:

    https://drive.google.com/file/d/1MhK4SBGKgNp_doYYpiAUsEFnD0DxhGQD/view?usp=sharing
    thầy ơi em bị lỗi này khi bấm nút lưu ạ :(( thầy giúp e với ạ

  221. duytran4321 viết:

    Em bị lỗi ở phần dap.Fill(table) khi mở form Nhân viên ạ. Mong thầy giúp ạ https://drive.google.com/file/d/1b0CSTQtINIxYD1Ty818P8kCtrCls2lMP/view?usp=sharing

  222. kplusflower viết:

    Thầy ơi cho em hỏi e code phần thêm hóa đơn ý ạ nhưng khi thêm sản phẩm thứ 2 nó báo lỗi trùng khóa nhưng tắt thông báo ấy đi thì nó vẫn thêm đc sản phẩm
    code hóa đơn của e đây ạ
    string sql;
    double sl, SLcon, tong, Tongmoi;
    sql = “Select MaHDBan from tblHDBan where MaHDBan=N'” + txtMaHoaDon + “‘”;//kiểm tra mã hàng đã tồn tại hay chưa
    if (!Function.CheckKey(sql))
    {
    //mã hóa đơn chưa có,tiến hành lưu các thông tin chug
    //Mã hd được sinh tự động do đó không có TH trùng khóa
    if (cboMaNhanVien.Text.Length == 0)
    {
    MessageBox.Show(“Bạn phải nhập mã nhân viên”, “Đây là thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);
    cboMaNhanVien.Focus();
    return;
    }
    if (cboMaKhachHang.Text.Length == 0)
    {
    MessageBox.Show(“Bạn phải nhập mã khách hàng”, “Đây là thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);
    cboMaKhachHang.Focus();
    return;
    }
    sql = “insert into tblHDBan(MaHDBan, Ngayban, Manhanvien, Makhach, Tongtien) values(N'” + txtMaHoaDon.Text + “‘,'” + dpkNgayBan.Value + “‘,” + cboMaNhanVien.SelectedValue + “,N'” + cboMaKhachHang.SelectedValue + “‘,” + txtTongTien.Text + “)”;
    Function.RunSQL(sql);
    }

    //Lưu thông tin hàng
    if (cboMaHang.Text.Trim().Length == 0)
    {
    MessageBox.Show(“Bạn phải nhập mã hàng”, “Đây là 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”, “Đây là 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á”, “Đây là thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);
    txtGiamGia.Focus();
    return;
    }
    sql = “select Mahang from tblChitietHDBan where Mahang =N'” + cboMaHang.SelectedValue + “‘ and MaHDBan=N'” + txtMaHoaDon.Text + “‘”;
    if (Function.CheckKey(sql))
    {
    MessageBox.Show(“Mã hàng này đã có bạn hãy nhập mã hàng khác”, “Đây là thông báo”, MessageBoxButtons.OK, MessageBoxIcon.Information);
    ResetValuesHang();
    cboMaHang.Focus();
    return;
    }
    //kt số lượng hàng trog kho có đủ để cung cấp ko
    sl = Convert.ToDouble(Function.GetFieldValues(“select Soluong from tblHang where Mahang=N'” + cboMaHang.SelectedValue + “‘”));
    if (Convert.ToDouble(txtSoLuong.Text) > sl)
    {
    MessageBox.Show(“Số lượng hàng này chỉ còn ” + sl, “Đây là 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'” + txtMaHoaDon.Text.Trim() + “‘,N'” + cboMaHang.SelectedValue + “‘,” + txtSoLuong.Text + “,” + txtDonGia.Text + “,” + txtGiamGia.Text + “,” + txtThanhTien.Text + “)”;
    Function.RunSQL(sql);
    LoadDataGridView();
    //Cạp nhật lại số lượng mặt hàng trong database
    SLcon = sl – Convert.ToDouble(txtSoLuong.Text);
    sql = “update tblHang set Soluong =” + SLcon + ” where Mahang=N'” + cboMaHang.SelectedValue + “‘”;
    Function.RunSQL(sql);
    //Cập nhật lại tổng tiền trong hóa đơn bán
    tong = Convert.ToDouble(Function.GetFieldValues(“select Tongtien from tblHDBan where MaHDBan =N'” + txtMaHoaDon.Text + “‘”));
    Tongmoi = tong + Convert.ToDouble(txtThanhTien.Text);
    sql = “update tblHDBan set Tongtien=” + Tongmoi + ” where MaHDBan =N'” + txtMaHoaDon.Text + “‘”;
    Function.RunSQL(sql);
    txtTongTien.Text = Tongmoi.ToString();
    lblBangChu.Text = “Bằng chữ: ” + Function.ChuyenSoSangChuoi(double.Parse(Tongmoi.ToString()));
    ResetValuesHang();
    btnXoa.Enabled = true;
    btnThemHoaDon.Enabled = true;
    btnInHoaDon.Enabled = true;

  223. ChiTan viết:

    https://drive.google.com/file/d/1WX9xM69NnTAQyt0p1mPfpoEBupnerJfs/view?usp=sharing
    https://drive.google.com/file/d/1LPs9Mhm8P7HJJC4ssJ5AuUPMkvf8OiKo/view?usp=sharing\

    Thầy ơi, sao lúc em tạo được nút Sửa thì click vào nó hiện ra lỗi như trên ạ. Mong thầy hướng dẫn em cách fix với ạ.

  224. BaHung viết:

    Thầy cho hỏi em khi lưu ở frmChitietHDban bị lỗi sau:
    System.Data.SqlClient.SqlException (0x80131904): Undosed quotation
    mark after the character string, 150000,,1500000).
    Incorrect syntax near ,150000, 1500000).at System.Data.SqlClient.SqlConnection.OnError(SqlException
    exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParser
    StateObject stateObj, Boolean callerHasConnectionLock, BooleanasyncClose)
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
    System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
    System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCom pletionSource 1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean
    inRetry) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery at Quanly.Class.Funtion.RunSQL(String sql) in
    D:\Quanly Quanly\Class Funtion.cs:line 61 ClientConnectionid:1124a7c5-4a9e-4e60-9ac5-4f4f8ae819e4 Error Number: 105, State:1,Class:15

  225. trunghieu1702 viết:

    Thầy xem em lỗi gì với ạ. trong bảng hàng hóa e bấm lưu thì nó hiện ntn
    https://drive.google.com/drive/u/0/folders/1KD9yb12C2jX6UeuXfJHMuBtKreYlhLn1

  226. trunghieu1702 viết:

    Thầy xem em lỗi gì với ạ. trong bảng hàng hóa e bấm lưu thì nó hiện ntn https://drive.google.com/drive/u/0/folders/1KD9yb12C2jX6UeuXfJHMuBtKreYlhLn1

  227. Son8902 viết:

    thầy ơi cái form TimHDBan của em nó đang bị lỗi chỗ truy vấn vào txtMaHDBan thầy ạ ,
    frmHoaDonBancs frm = new frmHoaDonBancs();
    frm.txtMaHDBan.Text = mahd;

    Severity Code Description Project File Line Suppression State
    Error CS0122 ‘frmHoaDonBancs.txtMaHDBan’ is inaccessible due to its protection level
    Thầy giúp em với ạ

  228. Son8989 viết:

    Thầy ơi thầy hỗ trợ em với, khi em thêm một sản phẩm mới vào hóa đơn thì hiện lỗi thầy
    Lỗi” System.Data.SqlException: Violation of primary key constraint KEY constraint “PK_tblChiTietHDBan’. The duplicate key value is(HDB4202022_082748)

  229. hung7890 viết:

    Thầy ơi thầy giúp em với ạ, khi thêm sản phẩm vào hóa đơn, khi mình đã tạo hóa đơn đấy sẵn rồi, thì nó bảo lỗi trùng khóa Mã Hóa Đơn, thì lỗi đấy fix như thế nào vậy thầy, em cảm ơn thầy nhiều ạ

  230. NguyenDinhLinh viết:

    Thầy hỗ trợ em với ạ!
    Em có thêm mấy cái pictureBox ở form cha, đến lúc chạy thì form con bị mấy cái picture đó đè lên. Có cách nào sửa k ạ?
    Mong thầy trả lời em sớm :))

  231. duyvu07112003 viết:

    Thầy ơi giúp em với, ở form Menu ấy thì phần trợ giúp thì nên xây dựng chức năng cho nó như nào vậy ạ

  232. khanh linh viết:

    thầy ơi, phần hóa đơn thay vì in ra excel, thầy làm một bài hướng dẫn in ra bằng Crystal Reports được không ạ

  233. hmnam viết:

    a giúp e lỗi phần datetime, e làm những vẫn lỗi định dạng ngày tháng, ngày tháng bị đảo nên insert vào databse bị lỗi System.FormatException: ‘Input string was not in a correct format.’

  234. GamEboyGSD viết:

    Thầy ơi, em làm đến bước tạo Database, thì nó báo cái lỗi

    Connections to SQL Server database files (.mdf) require LocalDB or SQL Server Express to be installed and running on the local computer.
    You may need to modify the setup and ensure Microsoft SQL Server Data Tools is selected or install the current version at: https://go.microsoft.com/fwlink/?LinkId=125883

    thì em phải tìm cái SQL Server Express ở đâu ạ.

  235. duy0912 viết:

    anh ơi có bài báo cáo chương trình này ko cho em xin với ạ? cảm ơn anh

  236. duy0912 viết:

    Thầy ơi cho em xin file app này em tham thảo với ạ

  237. LuanHuynh viết:

    Thầy có thể cho em xin database của bài này không ạ, em cảm ơn thầy nhiều

  238. manhdz24pl viết:

    cho e hỏi lúc e viết fc cho lưu ở form chất liệu thì chạy nó báo ntn ạ : System.InvalidOperationException: ExecuteNonQuery requires an open and available Connection. The connection’s current state is closed. at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
    at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCom pletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery( at QuanlyBanHang.Class.Functions.RunSQL(String sql) in E:\thucthapcnhttt\QuanlyBanHang Quan LyBan Hang\Class\Functions.cs:
    line 54
    thầy sửa giúp e với
    e cảm ơn !

  239. manhdz24pl viết:

    mấy cái chức năng còn lại như báo cáo trợ giúp a có hướng dẫn k ạ
    có thì e xin cái link hướng dẫn v ạ

  240. Viet Hung viết:

    Chào thầy! em muốn hỏi về dòng lệnh PicAnh.Image=Image.FromFile(txtAnh.Text) , tại sao lại load một file Text vào PictureBox

  241. tien_tx1210 viết:

    thầy ơi, thầy xem giúp em lỗi này là bị gì ạ
    dap.Fill(table); System.Data.SqlClient.SqlException: ‘A connection was successfully established with the server, but then an error occurred during the login process. (provider: Named Pipes Provider, error: 0 – No process is on the other end of the pipe.)’

  242. kuchiba123 viết:

    Dạ anh ơi cho em hỏi lỗi lúc e chạy thử chương trình thì báo lỗi ở trang Class Function ở dòng “con.ConnectionString = Properties.Settings.Default.QL_BanHangConnectionString;” là sao ạ lỗi này ạ “System.ArgumentException: ‘Invalid value for key “

  243. NinhAql viết:

    Cho em hỏi là bài này mình sử dụng cấu trúc dữ liệu nào ạ

    • Phan Tiến viết:

      Mình đang hiểu bạn đang hỏi về hệ quản trị cơ sở dữ liệu mình đang dùng trong bài này phải không? Cơ sở dữ liệu bài này mình làm trên hệ quản trị cơ sở dữ liệu SQL Server. Còn cấu trúc dữ liệu khác Cơ sở dữ liệu bạn nhé!

  244. viet5121198 viết:

    Thầy ơi em bị ntn làm cách nào để sửa ạ
    https://upanh.tv/image/y08Uzs

  245. nha viết:

    Dạ em chào thầy em đang làm đề tài này,thầy cho em hỏi là khi em làm formHDBanhang đã viết LoadDataGridView nhưng khi tìm kiếm MaHD thì lại chỉ hiện ra các textbox không hiện trong lưới của dgvHDBanhang là lỗi gì ạ

  246. zsaka2003 viết:

    còn mục hàng tồn và doanh thu đâu ạ??

  247. Minh Nguyen viết:

    Cho em hỏi là em code giống vs mẫu sao lúc điền mã và tên chất liệu xong ấn nút thêm lại ko đc vậy ạ

  248. bichhuynh viết:

    dạ anh ơi cho em hỏi chức năng doubleclick ở form tìm kiếm hóa đơn vô 1 hàng để hiện qua form hóa đơn á e làm theo nhưng nó báo lỗi kh nhận được mahd á anh xem giúp e được không ạ:

    private void dgvTKHoaDon_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 = dgvTKHoaDon.CurrentRow.Cells[“sohd”].Value.ToString(); //bị lỗi dòng này
    FrHoaDon frm = new FrHoaDon();
    frm.txtmhd.Text = mahd;
    frm.StartPosition = FormStartPosition.CenterParent;
    frm.ShowDialog();
    }
    }

    // khai báo bên form hóa đơn
    namespace PhanMemDT
    {
    public partial class FrHoaDon : Form
    {
    public TextBox txtmhd; // Khai báo txtMaHDBan là public ở đây

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