[Nhờ trợ giúp] Vấn đề truy xuất Thẻ kho của 1 mặt hàng từ 1 sheet Dữ liệu nguồn

Liên hệ QC

vistaab

Thành viên chính thức
Tham gia
1/8/09
Bài viết
92
Được thích
78
Giới tính
Nam
Nghề nghiệp
Kế toán
Trong file đính kèm có 3 sheet: DMHH, DKHO và TheKho.
Khi thay đổi giá trị mã hàng hóa tại ô C8, sheet TheKho thì tự động chạy Sub InTheKho thuộc modules TheKho nhằm mục đích trích ra thông tin Nhập - xuất - tồn của mặt hàng ở ô C8 nêu trên.
Code tại modules TheKho như sau:
Mã:
Option Explicit
Sub InTheKho()

Dim cn As Object, rst As Object
Dim mySQL As String
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")

With cn
    .Provider = "Microsoft.Jet.OLEDB.4.0"
      If Val(Application.Version) < 12 Then
      .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"";"
     Else
      .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
     End If
    .Open
End With
    
   mySQL = "Select ngay_ct as c1,IIF(loai_nv='N',so_ct,'') as c2, IIF(loai_nv='X',so_ct,'') as c3, dien_giai as c4,ngay_phieu as c5,IIF(loai_nv='N',so_luong,'')as C6,IIF(loai_nv='N',don_gia,'')as c7, IFF(loai_nv='N',thanh_tien,'') as c8,IIF(loai_nv='X',so_luong,'')as c9,IIF(loai_nv='X',don_gia,'')as c10, IFF(loai_nv='X',thanh_tien,'') as c11 " & _
            "from DKHO where ma_hh='" & (Range("TK_MAHANG").Value) & "' " & _
            "Order by c6,c3,c4"
    
    Set rst = cn.Execute(mySQL)
    
    With Sheet5
        .[B17:O100000].Clear
        .[B17].CopyFromRecordset rst
    End With
    
    rst.Close: cn.Close
    Set rst = Nothing: Set cn = Nothing
    
End Sub
Khi em cho chạy Sub InTheKho thì có báo lỗi:
"Run-time error '-2147217900 (80040e14)':
Undefined function 'IFF' in expression.

Em chỉ mới tập tành qua chỗ câu lệnh sql này nên còn chưa hiểu rõ lỗi phát sinh và cách khắc phục để đạt kết quả như mong muốn. Mong các thầy và anh chị em trên diễn đàn giúp đỡ hoàn thiện code để em được học hỏi thêm và ứng dụng vào công việc thực tế. Em cảm ơn mọi người đã đọc bài và góp ý.
 

File đính kèm

  • Nho tro giup THE KHO.xlsm
    35.3 KB · Đọc: 18
Trong file đính kèm có 3 sheet: DMHH, DKHO và TheKho.
Khi thay đổi giá trị mã hàng hóa tại ô C8, sheet TheKho thì tự động chạy Sub InTheKho thuộc modules TheKho nhằm mục đích trích ra thông tin Nhập - xuất - tồn của mặt hàng ở ô C8 nêu trên.
Code tại modules TheKho như sau:
Mã:
Option Explicit
Sub InTheKho()

Dim cn As Object, rst As Object
Dim mySQL As String
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")

With cn
    .Provider = "Microsoft.Jet.OLEDB.4.0"
      If Val(Application.Version) < 12 Then
      .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"";"
     Else
      .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
     End If
    .Open
End With
 
   mySQL = "Select ngay_ct as c1,IIF(loai_nv='N',so_ct,'') as c2, IIF(loai_nv='X',so_ct,'') as c3, dien_giai as c4,ngay_phieu as c5,IIF(loai_nv='N',so_luong,'')as C6,IIF(loai_nv='N',don_gia,'')as c7, IFF(loai_nv='N',thanh_tien,'') as c8,IIF(loai_nv='X',so_luong,'')as c9,IIF(loai_nv='X',don_gia,'')as c10, IFF(loai_nv='X',thanh_tien,'') as c11 " & _
            "from DKHO where ma_hh='" & (Range("TK_MAHANG").Value) & "' " & _
            "Order by c6,c3,c4"
 
    Set rst = cn.Execute(mySQL)
 
    With Sheet5
        .[B17:O100000].Clear
        .[B17].CopyFromRecordset rst
    End With
 
    rst.Close: cn.Close
    Set rst = Nothing: Set cn = Nothing
 
End Sub
Khi em cho chạy Sub InTheKho thì có báo lỗi:


Em chỉ mới tập tành qua chỗ câu lệnh sql này nên còn chưa hiểu rõ lỗi phát sinh và cách khắc phục để đạt kết quả như mong muốn. Mong các thầy và anh chị em trên diễn đàn giúp đỡ hoàn thiện code để em được học hỏi thêm và ứng dụng vào công việc thực tế. Em cảm ơn mọi người đã đọc bài và góp ý.
Trong đoạn này:
IFF(loai_nv='N',thanh_tien,'')
IFF(loai_nv='X',thanh_tien,'')

Bạn phải sửa lại thành:
IIF(loai_nv='N',thanh_tien,'')
IIF(loai_nv='X',thanh_tien,'')

2 chữ I chứ không phải 2 chữ F.

Mã:
mySQL = "Select ngay_ct as c1,IIF(loai_nv='N',so_ct,'') as c2,IIF(loai_nv='X',so_ct,'') as c3, dien_giai as c4,ngay_phieu as c5," & _
        "IIF(loai_nv='N',so_luong,'')as C6,IIF(loai_nv='N',don_gia,'')as c7,IIF(loai_nv='N',thanh_tien,'') as c8," & _
        "IIF(loai_nv='X',so_luong,'') as c9,IIF(loai_nv='X',don_gia,'')as c10,IIF(loai_nv='X',thanh_tien,'') as c11 " & _
        "from DKHO where ma_hh='" & (Range("TK_MAHANG").Value) & "' " & _
        "Order by c6,c3,c4"
 
Lần chỉnh sửa cuối:
Nghĩ cũng lạ, tại sao bạn không sắp xếp theo cột ngày tháng mà lại đi sắp sếp theo cột số lượng? Nếu là tôi, tôi sẽ làm như thế này có phải ngắn gọn và dễ nhìn hơn hay không!
Mã:
mySQL = "Select ngay_ct, IIF(loai_nv='N',so_ct,''), IIF(loai_nv='X',so_ct,''), dien_giai, ngay_phieu," & _
        "IIF(loai_nv='N',so_luong,''), IIF(loai_nv='N',don_gia,''), IIF(loai_nv='N',thanh_tien,'') ," & _
        "IIF(loai_nv='X',so_luong,''), IIF(loai_nv='X',don_gia,''), IIF(loai_nv='X',thanh_tien,'') " & _
        "from DKHO where ma_hh='" & Range("TK_MAHANG").Value & "' " & _
        "Order by ngay_ct,so_ct"
 
Lần chỉnh sửa cuối:
Nghĩ cũng lạ, tại sao bạn không sắp xếp theo cột ngày tháng mà lại đi sắp sếp theo cột số lượng? Nếu là tôi, tôi sẽ làm như thế này có phải ngắn gọn và dễ nhìn hơn hay không!
Mã:
mySQL = "Select ngay_ct, IIF(loai_nv='N',so_ct,''), IIF(loai_nv='X',so_ct,''), dien_giai, ngay_phieu," & _
        "IIF(loai_nv='N',so_luong,''), IIF(loai_nv='N',don_gia,''), IIF(loai_nv='N',thanh_tien,'') ," & _
        "IIF(loai_nv='X',so_luong,''), IIF(loai_nv='X',don_gia,''), IIF(loai_nv='X',thanh_tien,'') " & _
        "from DKHO where ma_hh='" & Range("TK_MAHANG").Value & "' " & _
        "Order by ngay_ct,so_ct"
Dạ, cảm ơn anh đã trợ giúp, vấn đề em thắc mắc đã giải quyết xong.
Nghĩ cũng lạ, tại sao bạn không sắp xếp theo cột ngày tháng mà lại đi sắp sếp theo cột số lượng?
Chỗ sắp xếp lỗi là do ban đầu em gán giá trị cho c6 là ngày chứng từ, sau điều chỉnh lại code trong Select thì lại quên điều chỉnh Order by
 
Góp vui, Thẻ kho bạn nên chạy theo ngày và từng kho nên mình cũng hướng ứng theo. hihi:p


SQL:
Sub InTheKho()

Dim cn As Object, rst As Object, ngaybd As Long, ngaykt As Long, Tenkho As String
Dim mySQL As String
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
Tenkho = Sheet5.[C6].Value
ngaybd = CLng(Sheet5.Range("I8"))
ngaykt = CLng(Sheet5.Range("I9"))

With cn
    .Provider = "Microsoft.Jet.OLEDB.4.0"
      If Val(Application.Version) < 12 Then
      .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"";"
     Else
      .ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
     End If
    .Open
End With
    
   mySQL = "Select ngay_ct, IIF(loai_nv='N',so_ct,''), IIF(loai_nv='X',so_ct,''), dien_giai, ngay_phieu," & _
        "IIF(loai_nv='N',so_luong,''), IIF(loai_nv='N',don_gia,''), IIF(loai_nv='N',thanh_tien,'') ," & _
        "IIF(loai_nv='X',so_luong,''), IIF(loai_nv='X',don_gia,''), IIF(loai_nv='X',thanh_tien,'') " & _
        "from DKHO where ma_hh='" & Range("TK_MAHANG").Value & "' and ngay_phieu >= " & ngaybd & " and ngay_phieu <= " & ngaykt & " and Kho = '" & Tenkho & "' " & _
        "Order by ngay_ct,so_ct"
    
    Set rst = cn.Execute(mySQL)
    
    With Sheet5
        .[B17:O100000].Clear
        .[B17].CopyFromRecordset rst
    End With
    
    rst.Close: cn.Close
    Set rst = Nothing: Set cn = Nothing
    
End Sub
 
ngaybd = CLng(Sheet5.Range("I8"))
ngaykt = CLng(Sheet5.Range("I9"))

"from DKHO where ma_hh='" & Range("TK_MAHANG").Value & "' and ngay_phieu >= " & ngaybd & " and ngay_phieu <= " & ngaykt & " and Kho = '" & Tenkho & "' " & _
Cảm ơn bạn Huu.hoang, với những thay đổi này thêm của bạn, mình có thể trích lọc dữ liệu thêm với điều kiện trong 1 khoảng thời gian nhất định được gán vào ô I8 và I9; và thêm lựa chọn khi mình phải quản lý nhiều kho trên cùng 1 bảng dữ liệu. Cảm ơn bạn.

1. Cho em hỏi thêm mọi người về việc định dạng dữ liệu khi được trích lọc ra.
Mong muốn: - Dữ liệu tại các cột số lượng thuộc kiểu định dạng "#,##0.0" (ví dụ 15.000,8)
- Dữ liệu tại các cột Đơn giá và Thành tiền kiểu định dạng "#,##0" (ví dụ 15.000)
Cách làm của em là tạo thêm 1 Thủ tục định dạng (có đính kèm theo file), cụ thể: Tại dòng 16, các ô được định dạng sẵn, sau đó các ô từ dòng 17 trở đi được định dạng giống theo các ô của dòng 16.
For ik = 0 To 16 Sheet5.Range("A17").Offset(0, ik).Resize(LrTK - 16, 1).NumberFormat = Sheet5.Range("A17").Offset(-1, ik).NumberFormat Next ik
Với cách làm này, em không hiểu đã sai ở đâu mà kết quả không như mong muốn.
Khi em thử kết hợp cách làm trên và thêm 1 công đoạn là lấy kết quả trích lọc ra từ mySQL cho vào 1 mảng, rồi lại gán mảng đó trở lại từ vị trí ô B17 thì kết quả là có ô thì định dạng đúng theo mục đích của mình, có ô thì lại không cho ra định dạng như mong muốn.
LrTK = Sheet5.Range("B100000").End(xlUp).Row ReDim ArrTK(1 To LrTK - 16, 1 To 14) ArrTK = Range("B17:O" & LrTK).Value Sheet5.Range("B17").Resize(UBound(ArrTK, 1), UBound(ArrTK, 2)).Value = ArrTK
Vậy cho em hỏi làm sao để định dạng được kết quả như mong muốn trong sheet Thẻ Kho?

2. Vấn đề thứ 2 cho em hỏi là cách bẫy lỗi khi gán công thức trong vba thì được viết như thế nào?
Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=RC[+1] / RC[-1]"
Khi trường hợp hàng đã xuất hết thì công thức trên sẽ dẫn đến lỗi chia cho số 0 (#DIV/0").
Em cảm ơn mọi người đã đọc bài và góp ý.
 

File đính kèm

  • Nho tro giup THE KHO.xlsm
    685.2 KB · Đọc: 11
Hi bạn,

2. Vấn đề thứ 2 cho em hỏi là cách bẫy lỗi khi gán công thức trong vba thì được viết như thế nào?
Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=RC[+1] / RC[-1]"
Khi trường hợp hàng đã xuất hết thì công thức trên sẽ dẫn đến lỗi chia cho số 0 (#DIV/0").


---> Ở Sheet 5: bạn bổ sung 2 đoạn

On Error Resume Next
On Error GoTo 0
Trường hợp này khi Sub ko tìm thấy mã hàng thì thủ tục sẽ bỏ qua.



---> bạn chỉ cho hàm IFERROR vô thôi nhé.

Cách làm này nó chỉ đối phó bạn phải kiểm tra lại dữ liệu, xuất quá số lượng kho là không đúng.

---> bạn nên chép vùng công thức thành value sau này file của bạn nó nhẹ.


Bạn xem đoạn 1


ElseIf LrTK = 17 Then
'Gan cong thuc vao ô M17, ô O17 và côt N

Sheet5.Range("M17").FormulaR1C1 = "=R13C+RC[-6]-RC[-3]"
Sheet5.Range("O17").FormulaR1C1 = "=R13C+RC[-6]-RC[-3]"

Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=IFERROR(RC[1]/RC[-1],"""")"
Sheet5.Range("N17:N" & LrTK).Value = Sheet5.Range("N17:N" & LrTK).Value

'ActiveCell.FormulaR1C1 = "=IFERROR(RC[-3]/RC[-5],"""")"

Bạn xem đoạn 2
ElseIf LrTK > 17 Then
'Gan cong thuc vao ô M17, ô O17 và côt N
Sheet5.Range("M17").FormulaR1C1 = "=R13C + RC[-6] - RC[-3]"
Sheet5.Range("O17").FormulaR1C1 = "=R13C + RC[-6] - RC[-3]"
'Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=RC[+1] / RC[-1]"

'Gan cong thuc cho cot M va cot O tu hang 18 cho den t
Sheet5.Range("M18:M" & LrTK).FormulaR1C1 = "=R[-1]C + RC[-6] - RC[-3]"
Sheet5.Range("M18:M" & LrTK).Value = Sheet5.Range("M18:M" & LrTK).Value
Sheet5.Range("O18:O" & LrTK).FormulaR1C1 = "=R[-1]C + RC[-6] - RC[-3]"
Sheet5.Range("O18:O" & LrTK).Value = Sheet5.Range("O18:O" & LrTK).Value

Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=IFERROR(RC[1]/RC[-1],"""")"
Sheet5.Range("N17:N" & LrTK).Value = Sheet5.Range("N17:N" & LrTK).Value

Đó là ý kiến nhỏ bé, hy vọng nó có ích cho bạn
Cảm ơn bạn Huu.hoang, với những thay đổi này thêm của bạn, mình có thể trích lọc dữ liệu thêm với điều kiện trong 1 khoảng thời gian nhất định được gán vào ô I8 và I9; và thêm lựa chọn khi mình phải quản lý nhiều kho trên cùng 1 bảng dữ liệu. Cảm ơn bạn.

1. Cho em hỏi thêm mọi người về việc định dạng dữ liệu khi được trích lọc ra.
Mong muốn: - Dữ liệu tại các cột số lượng thuộc kiểu định dạng "#,##0.0" (ví dụ 15.000,8)
- Dữ liệu tại các cột Đơn giá và Thành tiền kiểu định dạng "#,##0" (ví dụ 15.000)
Cách làm của em là tạo thêm 1 Thủ tục định dạng (có đính kèm theo file), cụ thể: Tại dòng 16, các ô được định dạng sẵn, sau đó các ô từ dòng 17 trở đi được định dạng giống theo các ô của dòng 16.
For ik = 0 To 16 Sheet5.Range("A17").Offset(0, ik).Resize(LrTK - 16, 1).NumberFormat = Sheet5.Range("A17").Offset(-1, ik).NumberFormat Next ik
Với cách làm này, em không hiểu đã sai ở đâu mà kết quả không như mong muốn.
Khi em thử kết hợp cách làm trên và thêm 1 công đoạn là lấy kết quả trích lọc ra từ mySQL cho vào 1 mảng, rồi lại gán mảng đó trở lại từ vị trí ô B17 thì kết quả là có ô thì định dạng đúng theo mục đích của mình, có ô thì lại không cho ra định dạng như mong muốn.
LrTK = Sheet5.Range("B100000").End(xlUp).Row ReDim ArrTK(1 To LrTK - 16, 1 To 14) ArrTK = Range("B17:O" & LrTK).Value Sheet5.Range("B17").Resize(UBound(ArrTK, 1), UBound(ArrTK, 2)).Value = ArrTK
Vậy cho em hỏi làm sao để định dạng được kết quả như mong muốn trong sheet Thẻ Kho?

2. Vấn đề thứ 2 cho em hỏi là cách bẫy lỗi khi gán công thức trong vba thì được viết như thế nào?
Sheet5.Range("N17:N" & LrTK).FormulaR1C1 = "=RC[+1] / RC[-1]"
Khi trường hợp hàng đã xuất hết thì công thức trên sẽ dẫn đến lỗi chia cho số 0 (#DIV/0").
Em cảm ơn mọi người đã đọc bài và góp ý.
 
Lần chỉnh sửa cuối:
Qua sự trợ giúp của các anh chị và đọc bài tham khảo trên diễn đàn, em đã giải quyết được 2 vấn đề nêu ra tại bài #6.
Xin chia sẻ code làm thẻ kho với mọi người để em được học hỏi thêm:
(Lưu ý: Trong file đính kèm tại bài #1, tại sheet Thẻ kho, tại ô M16 gắn công thức =M13, ô O16 gắn công thức =O13, xong rồi chọn màu chữ trắng cho 2 ô M16, O16)
Option Explicit
Sub InTheKho()
Dim ArrTK()
Dim LrTK As Long, i As Long, j As Long
Dim rng As Range
Dim cn As Object, rst As Object
Dim mySQL As String

Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")

With cn
.Provider = "Microsoft.Jet.OLEDB.4.0"
If Val(Application.Version) < 12 Then
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"";"
Else
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1"";"
End If
.Open
End With

mySQL = "Select ngay_ct, IIF(loai_nv='N',so_ct,''), IIF(loai_nv='X',so_ct,''), dien_giai, ngay_phieu," & _
"IIF(loai_nv='N',so_luong,''), IIF(loai_nv='N',don_gia,''), IIF(loai_nv='N',thanh_tien,'') ," & _
"IIF(loai_nv='X',so_luong,''), IIF(loai_nv='X',don_gia,''), IIF(loai_nv='X',thanh_tien,'') " & _
"from DKHO where ma_hh='" & Range("TK_MAHANG").Value & "' " & _
"Order by ngay_ct,so_ct"
Set rst = cn.Execute(mySQL)

With Sheet5
.[B17:p1000].Clear
.[B17].CopyFromRecordset rst
.[A17:p17].EntireColumn.AutoFit
End With

rst.Close: cn.Close
Set rst = Nothing: Set cn = Nothing

LrTK = Sheet5.Range("B100000").End(xlUp).Row
ReDim ArrTK(1 To LrTK - 16, 1 To 14)
ArrTK = Range("B17:O" & LrTK).Value
Sheet5.Range("B17").Resize(UBound(ArrTK, 1), UBound(ArrTK, 2)).Value = ArrTK

' Xoa duong vien luon
With Sheet5.[A17:p1000]
.Borders(xlEdgeLeft).LineStyle = xlNone
.Borders(xlEdgeTop).LineStyle = xlNone
.Borders(xlEdgeBottom).LineStyle = xlNone
.Borders(xlEdgeRight).LineStyle = xlNone
.Borders(xlInsideVertical).LineStyle = xlNone
.Borders(xlInsideHorizontal).LineStyle = xlNone
End With

'Can chinh le giua cho mot so cot
With Sheet5
.Range("B16:D400").HorizontalAlignment = xlCenter
.Range("F16:F400").HorizontalAlignment = xlCenter
.Range("H:H").NumberFormat = "#,##0"
.Range("K:K").NumberFormat = "#,##0"
.Range("N:N").NumberFormat = "#,##0"
End With
' Gan cong thuc vao cac o
For i = 17 To LrTK
Sheet5.Range("H" & i).FormulaR1C1 = "=iferror(RC[+1] / RC[-1],"""")"
Sheet5.Range("K" & i).FormulaR1C1 = "=iferror(RC[+1] / RC[-1],"""")"
Sheet5.Range("M" & i).FormulaR1C1 = "=R[-1]C + RC[-6] - RC[-3]"
Sheet5.Range("O" & i).FormulaR1C1 = "=R[-1]C + RC[-6] - RC[-3]"
Sheet5.Range("N" & i).FormulaR1C1 = "=iferror(RC[+1] / RC[-1],"""")"
Next i

For j = 0 To 16
Sheet5.Range("A17").Offset(0, j).Resize(LrTK - 16, 1).NumberFormat = Sheet5.Range("A17").Offset(-1, j).NumberFormat
Next j

'Ke duong vien moi
Set rng = Sheet5.Range("A17:p" & LrTK)
With rng
.Borders(xlEdgeLeft).LineStyle = xlContinuous
.Borders(xlEdgeTop).LineStyle = xlContinuous
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.Borders(xlEdgeRight).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyle = xlContinuous
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.EntireColumn.AutoFit
End With
Set rng = Nothing

End Sub
 
Web KT
Back
Top Bottom