Do chưa biết nhiều về VBA nên gặp khó khăn khi muốn tạo userform từ file frm và code có sẵn, nên em nhờ các anh chị trên diễn đàn khối phục giúp em 1 userform.
code nằm trong file mẫu excel, code userform nằm trong file formdongia và các code có liên quan.
Public DbConDG As ADODB.Connection
Public Sub ChenMaDonGia(MDG As String, Rn As Long)
Dim Rs As ADODB.Recordset
If DbConDG Is Nothing Then
Set DbConDG = CreateObject("ADODB.Connection")
DbConDG.Open "Provider = Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "\DonGia1728.mdb"
End If
Set Rs = CreateObject("ADODB.RecordSet")
Rs.Open "SELECT MADG, MAVUA, MADM, TENCV, DONVI, '' , DGVL, DGNC, DGMAY FROM [DonGia] Where Ucase(MADG) = '" & UCase(MDG) & "'", DbConDG, adOpenKeyset, adLockPessimistic
Cells(Rn, 1).CopyFromRecordset Rs
Rs.Close
Set Rs = Nothing
End Sub
Public Sub ShowDonGia()
FormDonGia.Show
End Sub
Em xin cám ơn.
Do mình sửa lui sửa tới nhiều lần quá. Mình sẽ rút kinh nghiệm.
- Sau khi hiện form, click vào listbox và chọn 1 công việc bất kỳ VD: mình chọn công việc có mà đơn giá AF11111 có tền công việc (bê tông .......M100) rồi chọn cmdxoa: xóa đi 1 hàng được chọn trong listbox , cmdsua: sửa nội dung tên công việc của 1 hàng nào đó trong listbox thì tự save vào listox tại hàng chỉnh sửa , cmdchọn: copy hàng được chọn vào excel "mauhien" bắt đầu từ cột A, thoát đều bình thường riêng cmdthem mờ đi.(lúc này chắc cmdthem không cho hoạt động)
- Còn nếu khi hiện form hiện lên mình gõ vào txtboxMĐG, (ví dụ V00001) cái này không trùng với các mã đã có, txtboxMĐM (trùng hoặc không trùng với txtboxMĐG) cũng được, txtboxtenCV (gõ tên công việc bất kỳ)
thì nút cmd Them bị mờ đi không cho click để thêm công việc mới vào trong listbox
- Trong form hiện tại chưa có code của
Private Sub LstDMCV_Enter()
If LstDMCV.ListIndex < 0 Then LstDMCV.ListIndex = 0
LstDMCV.Selected(0) = True
End If
End Sub
Nếu thêm vào thì khi click đúp tại cột A thì sẽ hiện thông báo runtime error 380 (could not set the ListIndex property. Invalid property value). Debug thì báo lỗi tại dòng màu đỏ ở code trên.
Mình đang test thấy phát hiện những vấn đề sau:
1. Khi hiện form lên, mình mới click vào nút hình tam giác trên thanh cuộn listbox (để tìm công việc phù hợp) thì listbox đã mặc định chọn cho mình công việc đầu tiên trong listbox.
2. Khi hiện form lên, nếu mình không click vào nút tam giác mà chọn 1 hàng (hay 1 công việc) thì trong listbox được tô đậm 1 lúc 2 hàng (được chọn 2 hàng), có nghĩa hàng đầu luôn được chọn.
Mình thử phiên bản "mauhien.xls" hôm qua không bị như vây.
3. cmdthem đã hoạt động cũng như thêm được dữ liệu mới vào trong listbox với điều kiện là 3 txtboxVL, txtboxNC, txtboxMay (để nguyên dữ liệu thì được còn thay đổi là bị lỗi ).
Nếu nhập vào txtNC thì báo lỗi sub or Function not defined tại (bị lỗi ở dòng màu đỏ)
Private Sub TxtNC_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
KeyCode = CheckKeyCode(KeyCode)
End Sub
tương tự cũng bị vậy nếu nhập txtNC hoặc txtMay
4. Tại cmdsua, mình click vào 1 hàng và chọn vào txtTenCV để sửa thì vẫn được( số liệu vẫn được lưu vào listbox) nhưng khi đó listbox bị đơ
5. Tại cmdxoa, khi mình click chọn 1 hàng nào đó để xóa, khi xóa xong thì trong lisbox tự chọn hàng và nhảy về hàng đầu tiên (hàng số 1) phiên bản hôm qua thì chỉ nhảy lên 1 hàng kế tiếp thôi
Mình đang test thấy phát hiện những vấn đề sau:
1. Khi hiện form lên, mình mới click vào nút hình tam giác trên thanh cuộn listbox (để tìm công việc phù hợp) thì listbox đã mặc định chọn cho mình công việc đầu tiên trong listbox.
2. Khi hiện form lên, nếu mình không click vào nút tam giác mà chọn 1 hàng (hay 1 công việc) thì trong listbox được tô đậm 1 lúc 2 hàng (được chọn 2 hàng), có nghĩa hàng đầu luôn được chọn.
Mình thử phiên bản "mauhien.xls" hôm qua không bị như vây.
Private Sub LstDMCV_Enter()
If LstDMCV.ListIndex < 0 Then
LstDMCV.ListIndex = 0
LstDMCV.Selected(0) = True
End If
End Sub
3. cmdthem đã hoạt động cũng như thêm được dữ liệu mới vào trong listbox với điều kiện là 3 txtboxVL, txtboxNC, txtboxMay (để nguyên dữ liệu thì được còn thay đổi là bị lỗi ).
Do bạn có "THÊM" chứ không phải là "Thêm" nên khi nhấn nút thì rõ ràng điều kiện CmdThem.Caption = "Thêm" không thỏa, tức ngay lập tức code thực hiện phần Else, trái với dụng ý.
Nếu nhập vào txtNC thì báo lỗi sub or Function not defined tại (bị lỗi ở dòng màu đỏ)
Private Sub TxtNC_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
KeyCode = CheckKeyCode(KeyCode)
End Sub
tương tự cũng bị vậy nếu nhập txtNC hoặc txtMay
Private Sub CmdSua_Click()
TxtMDG.ForeColor = vbBlack
TxtTenCV.ForeColor = vbBlack
If CmdSua.Caption = "Sua" Then
CmdSua.Caption = "Xong"
OnOffTxt True
Else
Dim ID As Long
ID = LstDMCV.ListIndex
With RsDmcv
.Fields("MADG") = TxtMDG.Text
.Fields("TENCV") = TxtTenCV.Text
.Update
.Requery
End With
UpdataToListBox
LstDMCV.ListIndex = ID
LstDMCV.TopIndex = ID
LstDMCV.Selected(ID) = True
CmdSua.Caption = "Sua"
OnOffTxt False
End If
End Sub
Bạn nhấn Sửa mà đã đươc sửa ngay là trái với dụng ý của người viết code. Nguyên nhân là do là bạn có Caption của CmdSua là "SUA", nên điều kiện If CmdSua.Caption = "Sua" Then không thỏa nên code thực hiện luôn nhánh Else ... End If
Khi đã sửa được có nghĩa là nhánh Else ... End If được thực hiện, mà trong đó có
Private Sub OnOffTxt(Ebl As Boolean)
Dim Ctl As Control
For Each Ctl In Me.Controls
If Ctl.TabIndex >= 3 And Ctl.TabIndex <= 8 Then
Ctl.Enabled = Ebl
End If
Next
End Sub
Tức khi đã sửa được thì 6 control có TabIndex từ 3 đến 8 sẽ bị khóa. Kiểm tra lại thì thấy hiện thời ListBox có TabIndex = 8 nên nó bị khóa, bị đơ.
Bạn có 8 TextBox, trong csdl có 8 trường. Nhưng tôi thấy code chỉ thêm vào MDB có 7 trường
Mã:
If Ctl.TabIndex < 2 Then
.Fields(Ctl.TabIndex) = Ctl.Text
ElseIf Ctl.TabIndex > 2 And Ctl.TabIndex < 8 Then
.Fields(Ctl.TabIndex - 1) = Replace(Ctl.Text, ".", "")
End If
Do bạn có "THÊM" chứ không phải là "Thêm" nên khi nhấn nút thì rõ ràng điều kiện CmdThem.Caption = "Thêm" không thỏa, tức ngay lập tức code thực hiện phần Else, trái với dụng ý.
Do trong toàn bộ tập tin không có code CheckKeyCode, thế thôi. Tôi có thể đoán là người ta sẽ kiểm tra phím nhấn và không chấp nhận một số phím nào đó. Có thể tự viết code cho CheckKeyCode, nhưng làm sao mà đoán được người ta muốn loại bỏ / cấm những phím nào.
Tôi đề nghị tìm tất cả những dòng có CheckKeyCode và biến chúng thành chú thích - vd. gõ ký tự nháy đơn ở đầu. Còn khi nhập liệu thì tránh nhập những ký tự mà phần đó không chấp nhận.
Thì vẫn vấn đề như CmdThem thôi
Mã:
Private Sub CmdSua_Click()
TxtMDG.ForeColor = vbBlack
TxtTenCV.ForeColor = vbBlack
If CmdSua.Caption = "Sua" Then
CmdSua.Caption = "Xong"
OnOffTxt True
Else
Dim ID As Long
ID = LstDMCV.ListIndex
With RsDmcv
.Fields("MADG") = TxtMDG.Text
.Fields("TENCV") = TxtTenCV.Text
.Update
.Requery
End With
UpdataToListBox
LstDMCV.ListIndex = ID
LstDMCV.TopIndex = ID
LstDMCV.Selected(ID) = True
CmdSua.Caption = "Sua"
OnOffTxt False
End If
End Sub
Bạn nhấn Sửa mà đã đươc sửa ngay là trái với dụng ý của người viết code. Nguyên nhân là do là bạn có Caption của CmdSua là "SUA", nên điều kiện If CmdSua.Caption = "Sua" Then không thỏa nên code thực hiện luôn nhánh Else ... End If
Khi đã sửa được có nghĩa là nhánh Else ... End If được thực hiện, mà trong đó có
Xem code của OnOffTxt có
Mã:
Private Sub OnOffTxt(Ebl As Boolean)
Dim Ctl As Control
For Each Ctl In Me.Controls
If Ctl.TabIndex >= 3 And Ctl.TabIndex <= 8 Then
Ctl.Enabled = Ebl
End If
Next
End Sub
Tức khi đã sửa được thì 6 control có TabIndex từ 3 đến 8 sẽ bị khóa. Kiểm tra lại thì thấy hiện thời ListBox có TabIndex = 8 nên nó bị khóa, bị đơ.
Bạn có 8 TextBox, trong csdl có 8 trường. Nhưng tôi thấy code chỉ thêm vào MDB có 7 trường
Mã:
If Ctl.TabIndex < 2 Then
.Fields(Ctl.TabIndex) = Ctl.Text
ElseIf Ctl.TabIndex > 2 And Ctl.TabIndex < 8 Then
.Fields(Ctl.TabIndex - 1) = Replace(Ctl.Text, ".", "")
End If
Quá tuyệt vời luôn bạn ơi, Không biết nói gì hơn là chân thành cám ơn bạn nhiều.
Bạn có thể giúp mình thêm chút nữa nhé. Chả là trong file "mauhien.xls" có 1 module2, trong đó có code mà mình không biết làm sao để gọi nó ?
Mục đích cửa code đó là:
Ví vụ tại sheet DTCT mình đã chọn được (1 dòng) công việc từ uerform có Mã Đ.giá là:
AF11111, thì tại sheet PTVT sẽ xuất hiện các loại vật liệu, nhân công mà Mã hiệu ĐM AF11110 có được lấy từ Định mức 24. Mình có mô tả trong excel
(nói chung là chọn được 1 hạng mục công việc bên sheetDTCT thì bến sheet PTVT sẽ xuất hiện 1 hạng mục tương ứng nhưng phân tích ra nhiều công việc con để hình thành 1 công việc mang tên AF11111)
Một lần nữa cám ơn bạn nhiều nhé