Nhờ hướng dẫn (gợi ý) giải quyết vấn đề bằng VBA

Liên hệ QC
Anh thử Select Top 2 xem coi được hong nhé.
Nhưng nếu top 2 sotien không thỏa dk là HLMT, thì nó kg chịu
VD: Max là 100.000 và 111.000 nhưng là XN
PHP:
Sub LocADO_04()
Dim ST01, ST02
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
End With
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
lsSQL = lsSQL & "and sotien in (select top 2 sotien from [data$] order by sotien DESC)"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
If rst.RecordCount Then
  sArr = rst.GetRows()
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
Erase sArr, rArr
End Sub
 
Nhưng nếu top 2 sotien không thỏa dk là HLMT, thì nó kg chịu
VD: Max là 100.000 và 111.000 nhưng là XN
PHP:
Sub LocADO_04()
Dim ST01, ST02
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
End With
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
lsSQL = lsSQL & "and sotien in (select top 2 sotien from [data$] order by sotien DESC)"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
If rst.RecordCount Then
  sArr = rst.GetRows()
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
Erase sArr, rArr
End Sub


Anh ra kết quả không như mong đợi chắc có lẽ là do anh select top 2 của toàn bộ dữ liệu trong bảng data, mà đề bài yêu cầu là chỉ lấy HLMT, em nghĩ anh thử thêm điều kiện lọc là HLMT vào cái sub query chạy xem sao.
 
Anh ra kết quả không như mong đợi chắc có lẽ là do anh select top 2 của toàn bộ dữ liệu trong bảng data, mà đề bài yêu cầu là chỉ lấy HLMT, em nghĩ anh thử thêm điều kiện lọc là HLMT vào cái sub query chạy xem sao.
Tìm ra rồi, select top và lồng thêm where.
Phức tạp quá
Nếu xử lý arr thì phải duyệt qua arr để lấy top 2.
PHP:
Sub LocADO_05()
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
End With
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where sotien in (select top 2 sotien from [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
lsSQL = lsSQL & "order by sotien DESC)"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
If rst.RecordCount Then
  sArr = rst.GetRows()
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
Erase sArr, rArr
End Sub
Học SQL này vui quá. HL cho đề tài next đi.
 
Tìm ra rồi, select top và lồng thêm where.
Phức tạp quá
Nếu xử lý arr thì phải duyệt qua arr để lấy top 2.

Học SQL này vui quá. HL cho đề tài next đi.

Anh ThuNghi ơi, chắc là em tạm dừng đến đây, chiều nay em xin quay về bài 1 vì bài 1 chưa giải quyết xong, thắc mắc của Tùng là nhập liệu (Em sẽ hướng dẫn nhập liệu = ADO), định dạng số thì anh giải quyết xong, còn cái TextBox ngày nữa Tùng muốn không dùng DTPicker. Khi giải quyết xong các vấn đề của Tùng mình tiếp tục nha anh. Tốc độ chậm chậm thôi anh à, anh chạy nhanh quá, em chóng hết cả mặt...
 
To anh Thunghi:
Là cái điều kiện lọc của anh hơi dài, có thể rút gọn mà không cần dùng hàm left([NCC],4)

Tùng sắp ....bực mình rồi anh ạ! Không theo bài 1 là bạn í vào đây, ...ăn vạ đó.!!! Hihi...
Em cũng cần học hỏi thêm nhiều vấn đề nữa ạ!
 
Lần chỉnh sửa cuối:
... còn cái TextBox ngày nữa Tùng muốn không dùng DTPicker. Khi giải quyết xong các vấn đề của Tùng mình tiếp tục nha anh. Tốc độ chậm chậm thôi anh à, anh chạy nhanh quá, em chóng hết cả mặt...
Nhập ngày trên form có nhiều cách, lâu rồi OB cũng đã làm 1 form nhập ngày. Hay cũng có bài làm form nhập ngày theo dạng 3 txtBox dd/mm/yyyy và ghép lại nhưng tất cả đều có thể nhập sai cả và cũng phức tạp. Nếu muốn nhập trên form mà kg nghiên cứu DTPicker thì dùng cách khác càng khó hơn.
 

File đính kèm

Nhập ngày trên form có nhiều cách, lâu rồi OB cũng đã làm 1 form nhập ngày. Hay cũng có bài làm form nhập ngày theo dạng 3 txtBox dd/mm/yyyy và ghép lại nhưng tất cả đều có thể nhập sai cả và cũng phức tạp. Nếu muốn nhập trên form mà kg nghiên cứu DTPicker thì dùng cách khác càng khó hơn.
Theo em nếu không muốn dùng DTPicker thì em dùng hàm để thay đổi định dạng của hệ thống, ai muốn nhập kiểu nào thì chọn kiểu ấy. Nếu Tùng theo cách này thì ta tiếp tục.
 
Theo em nếu không muốn dùng DTPicker thì em dùng hàm để thay đổi định dạng của hệ thống, ai muốn nhập kiểu nào thì chọn kiểu ấy. Nếu Tùng theo cách này thì ta tiếp tục.

Đúng là em không rành lắm cái này, tuy nhiên thấy cái DTPicker thì bất tiện vì không phải máy nào cũng "tự nhiên" mà chạy được. còn cái cách thay đổi ngày hệ thống thì sao?? nó có ảnh hưởng đến chương trình (cụ thể là 1 phần mềm) nào đó đang cùng chạy trên máy tính không?.
 
Đúng là em không rành lắm cái này, tuy nhiên thấy cái DTPicker thì bất tiện vì không phải máy nào cũng "tự nhiên" mà chạy được. còn cái cách thay đổi ngày hệ thống thì sao?? nó có ảnh hưởng đến chương trình (cụ thể là 1 phần mềm) nào đó đang cùng chạy trên máy tính không?.
Muốn cái bất tiện trở thành tiện cũng không phải không có cách:
- Viết 1 chương trình (VB chẳng hạn)
- Mang file mình + file chương trình sang máy khác và chạy file chương trình
- Chương trình sẽ dò tìm xem trong máy cái thằng DTPicker đã cài chưa. Nếu chưa cài, nó sẽ tiến hành cài đặt (cũng khá dễ bằng cách copy mscomct2.ocx vào thư mục System32 rồi đăng ký nó)
- Cuối cùng khởi động file Excel là cứ thế vi vu, chẳng lo gì vụ báo lỗi
 
Đúng là em không rành lắm cái này, tuy nhiên thấy cái DTPicker thì bất tiện vì không phải máy nào cũng "tự nhiên" mà chạy được. còn cái cách thay đổi ngày hệ thống thì sao?? nó có ảnh hưởng đến chương trình (cụ thể là 1 phần mềm) nào đó đang cùng chạy trên máy tính không?.
Chắc chắn sẽ ảnh hưởng nếu như phần mềm nào đó có định dạng ngày tháng không cùng với định dạng của người chọn kiểu nhập.
Ý định khác phục là vầy, khi mở form, mình lấy kiểu định dạng của hệ thống là gì rồi lưu nó vào 1 biến nào đó, người dùng chọn kiểu nhập nào thì khi thoát khỏi form thì nó sẽ reset lại theo như định dạng ban đầu. Tuy nhiên sẽ ảnh hưởng đến phần mềm khác đang chạy song song.
Nếu thấy cách này không được thì Tùng nên chọn cách của anh OKBab, hoặc phải sử dụng DTPicker.
 
Muốn cái bất tiện trở thành tiện cũng không phải không có cách:
- Viết 1 chương trình (VB chẳng hạn)
- Mang file mình + file chương trình sang máy khác và chạy file chương trình
- Chương trình sẽ dò tìm xem trong máy cái thằng DTPicker đã cài chưa. Nếu chưa cài, nó sẽ tiến hành cài đặt (cũng khá dễ bằng cách copy mscomct2.ocx vào thư mục System32 rồi đăng ký nó)
- Cuối cùng khởi động file Excel là cứ thế vi vu, chẳng lo gì vụ báo lỗi
Tiện đây NDU hd cụ thể cácch tạo DTPicker giúp.
Tôi cũng đã copy ocx và đã run rồi nhưng trên form cũng kg thể hiện DTPicker. Chỉ copy từ file có sẵn sang thì dùng được.
Và NDU hd dùng cho Ex 2010 luôn nhé.
Cám ơn nhiều.
Có bài mở 1 form mới và import sang mà tìm hoài không thấy link đó.
Tìm mãi mới thấy link, bài NDU nhiều quá, tìm kg thấy từ khóa NDU phải chuyển sang ...1066.
http://www.giaiphapexcel.com/forum/...t-tình-trạng-Additional-Controls-mất-tác-dụng
.. OK rồi
 
Lần chỉnh sửa cuối:
Đúng là em không rành lắm cái này, tuy nhiên thấy cái DTPicker thì bất tiện vì không phải máy nào cũng "tự nhiên" mà chạy được. còn cái cách thay đổi ngày hệ thống thì sao?? nó có ảnh hưởng đến chương trình (cụ thể là 1 phần mềm) nào đó đang cùng chạy trên máy tính không?.

Sao lại thay đổi ngày hệ thống? Kể cả thay đổi thiết lập hiển thị, nhập ngày tháng cũng thế. Phần mềm của mình sang máy người khác chạy thì phải lấy thiết lập của người ta chứ. Máy của người ta, người ta là chủ, thiết lập của người ta sao lại tự ý đổi?
Theo tôi bạn qui định cho người dùng là phải nhập ngày tháng theo mẫu: dd/mm/yyyy (hoặc tăng thêm vài mẫu). Tất nhiên phải kiểm tra dữ liệu được nhập và bắt nhập lại nếu sai. vd. 42/11/2012 là sai. Trên shett định dạng các ô là DATE. Còn chuyện Excel hiển thị thế nào thì tùy thiết lập tron CP. Người nhập vào vd. 21/08/2012, xuống sheet trên máy của bạn thì thấy 21/08/2012, mang sang máy khác thì lại thấy 2012-08-21. Tất cả đều là cùng một ngày. Như em Hà My hôm nay tô môi, mặc váy đầm thì không còn là Hà My mắt nâu nữa à?
DTPicker có ưu điểm là bạn chọn chứ không gõ, mà không gõ thì sẽ không bị gõ sai.
 
Sao lại thay đổi ngày hệ thống? Kể cả thay đổi thiết lập hiển thị, nhập ngày tháng cũng thế. Phần mềm của mình sang máy người khác chạy thì phải lấy thiết lập của người ta chứ. Máy của người ta, người ta là chủ, thiết lập của người ta sao lại tự ý đổi?
Theo tôi bạn qui định cho người dùng là phải nhập ngày tháng theo mẫu: dd/mm/yyyy (hoặc tăng thêm vài mẫu). Tất nhiên phải kiểm tra dữ liệu được nhập và bắt nhập lại nếu sai. vd. 42/11/2012 là sai. Trên shett định dạng các ô là DATE. Còn chuyện Excel hiển thị thế nào thì tùy thiết lập tron CP. Người nhập vào vd. 21/08/2012, xuống sheet trên máy của bạn thì thấy 21/08/2012, mang sang máy khác thì lại thấy 2012-08-21. Tất cả đều là cùng một ngày. Như em Hà My hôm nay tô môi, mặc váy đầm thì không còn là Hà My mắt nâu nữa à?
DTPicker có ưu điểm là bạn chọn chứ không gõ, mà không gõ thì sẽ không bị gõ sai.

Hihi.. như đã nói từ đầu là em chằng có rành cái món VB này nên --> hỏng biết cái nào tiện và cái nào không tiện cũng như cách thức thực hiện đó nên hay hỏi để các anh chị giải thích từng cách --> em có sự lựa chọn tiện cho em sử dụng nhất.

Rất nhiều cách đưa ra và mỗi cách có ưu điểm và nhược điểm và tất nhiên ngoải việc chọn được cách "phù hợp nhất với kiến thức sử dụng của mình thì bản thân những ai chưa biết như em cũng có điều kiện học hỏi thêm, biết thêm nhiều cách khác nhau.

Đó cũng là ý tưởng và lý do tại sao tên của topic là [h=1]Nhờ hướng dẫn (gợi ý) giải quyết vấn đề bằng VBA[/h]
Mong rằng tiếp tục nhận được nhiều hơn sự giúp đỡ và chỉ dẫn từ tất cả các anh chị.
 
Đúng là em không rành lắm cái này, tuy nhiên thấy cái DTPicker thì bất tiện vì không phải máy nào cũng "tự nhiên" mà chạy được. còn cái cách thay đổi ngày hệ thống thì sao?? nó có ảnh hưởng đến chương trình (cụ thể là 1 phần mềm) nào đó đang cùng chạy trên máy tính không?.

Vào bài này của tên Ếch Xanh nè, có form tự tạo tuyệt vời hơn cả cái DTPicker đấy (có cả lịch âm dương mới ghê).

http://www.giaiphapexcel.com/forum/...t-caption-cho-nhiều-Label&p=242423#post242423
 
Thôi thì bây giờ anh làm định dạng bình thường, sau này Tùng giỏi lên rồi biến chế nhé.

1. Định dạng TextBox

Mã:
Private Sub TextBox1_AfterUpdate() 
TextBox1 = Format(TextBox1, "dd/mm/yyyy")
 
End Sub

2. Đưa dữ liệu vào sheet = ADO

Mã:
Private Sub CommandButton1_Click()
Dim rst As New ADODB.Recordset
If cnn.State <> 1 Then Moketnoi
rst.Open "SELECT * FROM [data$]", cnn, 1, 3
 With rst
     .AddNew
        ![Ngay] = TextBox1
        ![NCC] = ComboBox1
        ![Ten_NCC] = TextBox3
        ![So Tien] = TextBox4
        ![Dien Giai] = TextBox5
        .Update
       .Close
End With
Set rst = Nothing


End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
2. Đưa dữ liệu vào sheet = ADO

Mã:
Private Sub CommandButton1_Click()
Dim rst As New ADODB.Recordset
If cnn.State <> 1 Then Moketnoi
rst.Open "SELECT * FROM [data$]", cnn, 1, 3
 With rst
     .AddNew
        ![Ngay] = TextBox1
        ![NCC] = ComboBox1
        ![Ten_NCC] = TextBox3
        ![So Tien] = TextBox4
        ![Dien Giai] = TextBox5
        .Update
       .Close
End With
Set rst = Nothing


End Sub

Code trên mà không bẫy lỗi rỗng cho các TextBox hay Combobox thì sẽ phát sinh lỗi đấy nhé bạn Hai Lúa.
 
Hì, cũng đang học ADO, chưa xem được nhiều, nhưng có 1 chỗ thấy chưa hợp lý: khi xem NCC thì lại đóng form, cho nên khi đóng PrintPreview trở lại form thì thông tin đã nhập trước đó bị mất. Đề nghị thay lệnh:

unload NHAPLIEU bằng lệnh NHAPLIEU.Hide

trong Private Sub cmdXem_Click()
 
Chắc chắn sẽ lỗi nếu như không nhập đủ thông tin điều mà em biết chứ, ta có thể dùng hàm IIF để xử lổi này. Mình chỉ đưa ví dụ về cách nhập liệu 1 cách căn bản cho người mới học dể hiểu. Sẽ còn 1 cách khong cần xử lí lổ niày
 
Lần chỉnh sửa cuối:
Em thêm xử lý lỗi TextBox trống như sau:

Mã:
Private Sub CommandButton1_Click()
Dim rst As New ADODB.Recordset
If cnn.State <> 1 Then Moketnoi
rst.Open "SELECT * FROM [data$]", cnn, 1, 3
 
With rst
     .AddNew
        ![Ngay] = IIf(IsDate(TextBox1) = False, Format(Date, "dd/mm/yyyy"), TextBox1)
        ![NCC] = IIf(IsNull(ComboBox1), "", ComboBox1)
        ![Ten_NCC] = IIf(TextBox3 = "", "", TextBox3)
        ![So Tien] = IIf(IsNumeric(TextBox4) = True, TextBox4, 0)
        ![Dien Giai] = IIf(Len(TextBox5) = 0, "", TextBox3)
        .Update
       .Close
End With
Set rst = Nothing
 
End Sub

Ngoài ra code nhập liệu này cần phải them 1 code xóa trống các TextBox sau khi nhập liệu vào sheet xong.
 
Em thêm xử lý lỗi TextBox trống như sau:

Mã:
Private Sub CommandButton1_Click()
Dim rst As New ADODB.Recordset
If cnn.State <> 1 Then Moketnoi
rst.Open "SELECT * FROM [data$]", cnn, 1, 3
 
With rst
     .AddNew
        ![Ngay] = IIf(IsDate(TextBox1) = False, Format(Date, "dd/mm/yyyy"), TextBox1)
        ![NCC] = IIf(IsNull(ComboBox1), "", ComboBox1)
        ![Ten_NCC] = IIf(TextBox3 = "", "", TextBox3)
        ![So Tien] = IIf(IsNumeric(TextBox4) = True, TextBox4, 0)
        ![Dien Giai] = IIf(Len(TextBox5) = 0, "", TextBox3)
        .Update
       .Close
End With
Set rst = Nothing
 
End Sub

Ngoài ra code nhập liệu này cần phải them 1 code xóa trống các TextBox sau khi nhập liệu vào sheet xong.
Đã dùng form thì xử lý trên form trước khi OK, ai lại làm ngược, OK xong mới xử lý rec.
 
Web KT

Bài viết mới nhất

Back
Top Bottom