Nhờ xem lại hàm sumifs trong vba (1 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

kid.phan2705

Thành viên mới
Tham gia
14/5/14
Bài viết
12
Được thích
0
Hiện tại e có 1 file tổng hợp nhập xuất tồn, nếu dùng hàm sumifs thì ra đúng kết quả. Tuy nhiên nếu dùng function.sumifs trong vba thì nó không hoạt động đúng.
Yêu cầu là check mã vật tư trước ngày start => số lượng hàng tồn
E đã thử nghiệm ở hàm sumifs thì ra đúng. Lò mò xài vba với đoạn code như hình thì nó lại bỏ qua cái điều kiện thứ 2 (check ngày).
Mọi người giúp e sai ở chỗ nào với.


1651907347322.png
 

File đính kèm

Giải pháp
Hiện tại e có 1 file tổng hợp nhập xuất tồn, nếu dùng hàm sumifs thì ra đúng kết quả. Tuy nhiên nếu dùng function.sumifs trong vba thì nó không hoạt động đúng.
Yêu cầu là check mã vật tư trước ngày start => số lượng hàng tồn
E đã thử nghiệm ở hàm sumifs thì ra đúng. Lò mò xài vba với đoạn code như hình thì nó lại bỏ qua cái điều kiện thứ 2 (check ngày).
Mọi người giúp e sai ở chỗ nào với.
Code thay thế thì dễ thôi, chỉ cần nhờ ai đó viết hộ. Nhưng nếu bạn không biết sai ở đâu thì ngày mai, tuần sau, tháng tới bạn cũng sẽ lặp lại lỗi đó. Chả nhẽ cứ đi nhờ viết code thay thế?

Lỗi của bạn là tham chiếu chưa đủ (dòng phải từ 4) nên kết quả nếu có sẽ không chính xác. Đó là lỗi nhỏ...
Hiện tại e có 1 file tổng hợp nhập xuất tồn, nếu dùng hàm sumifs thì ra đúng kết quả. Tuy nhiên nếu dùng function.sumifs trong vba thì nó không hoạt động đúng.
Yêu cầu là check mã vật tư trước ngày start => số lượng hàng tồn
E đã thử nghiệm ở hàm sumifs thì ra đúng. Lò mò xài vba với đoạn code như hình thì nó lại bỏ qua cái điều kiện thứ 2 (check ngày).
Mọi người giúp e sai ở chỗ nào với.

Code của bạn thiếu đoạn này :

Mã:
    Dim Ton As Worksheet
    Dim Xuat As Worksheet
    Dim Nhap As Worksheet
    Set Ton = ThisWorkbook.Sheets("NXT")
    Set Xuat = ThisWorkbook.Sheets("Xuat")
    Set Nhap = ThisWorkbook.Sheets("Nhap")

Dữ liệu của bạn bắt đầu từ hàng 4, không phải 5:

Mã:
 For i = 4 To lrnxt

Ngoài ra, một số biến khai báo chưa tối ưu, code làm việc trên range, không phải trên mảng nên chạy chậm ...

.
 
Upvote 0
Code của bạn thiếu đoạn này :

Mã:
    Dim Ton As Worksheet
    Dim Xuat As Worksheet
    Dim Nhap As Worksheet
    Set Ton = ThisWorkbook.Sheets("NXT")
    Set Xuat = ThisWorkbook.Sheets("Xuat")
    Set Nhap = ThisWorkbook.Sheets("Nhap")

Dữ liệu của bạn bắt đầu từ hàng 4, không phải 5:

Mã:
 For i = 4 To lrnxt

Ngoài ra, một số biến khai báo chưa tối ưu, code làm việc trên range, không phải trên mảng nên chạy chậm ...

.
Cảm ơn bác. Thật ra thì e tách ra từ 1 file khác, việc khai báo worksheet theo e nghĩ không phải là vấn đề khiến code chạy khác với hàm trực tiếp? Vì ở file khác không khai báo nhưng vẫn không sao.
Bác cho e hỏi cách chạy theo mảng được không? Em muốn cải thiện thêm :D
 
Upvote 0
Mã:
For i = 5 To lrnxt
        a = WorksheetFunction.SumIfs(rngslnhap, rngvtnhap, Ton.Range("A" & i), rngngaynhap, "<" & day1)
        'b = WorksheetFunction.SumIfs(rngslxuat, rngvtxuat, Ton.Range("A" & i), rngngayxuat, "<" & day1)
        Ton.Range("D" & i).Value = a
    Next


ban chay i từ 5, nhưng range bạn từ 4
 
Upvote 0
Cảm ơn bác. Thật ra thì e tách ra từ 1 file khác, việc khai báo worksheet theo e nghĩ không phải là vấn đề khiến code chạy khác với hàm trực tiếp? Vì ở file khác không khai báo nhưng vẫn không sao.

Mới nghe lần đầu.

Không khai báo và không set, nhưng vẫn không sao!

.
 
Upvote 0
Hiện tại e có 1 file tổng hợp nhập xuất tồn, nếu dùng hàm sumifs thì ra đúng kết quả. Tuy nhiên nếu dùng function.sumifs trong vba thì nó không hoạt động đúng.
Yêu cầu là check mã vật tư trước ngày start => số lượng hàng tồn
E đã thử nghiệm ở hàm sumifs thì ra đúng. Lò mò xài vba với đoạn code như hình thì nó lại bỏ qua cái điều kiện thứ 2 (check ngày).
Mọi người giúp e sai ở chỗ nào với.


View attachment 275558
Thử cái code này xem.
Mã:
Sub tinhsoluong()
   Dim i As Long, lr As Long, dic As Object, arr, data, kq() As Double, a As Long, dk As String, b As Long, ngaybd As Long, ngaykt As Long
   Set dic = CreateObject("scripting.dictionary")
   With Sheets("NXT")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A4:B" & lr).Value
        ngaybd = .Range("o2").Value2
        ngaykt = .Range("R2").Value2
        For i = 1 To UBound(arr)
            dk = arr(i, 1)
            If Not dic.exists(dk) Then
               dic.Add dk, i
            End If
        Next i
        ReDim kq(1 To UBound(arr), 1 To 8)
   End With
   With Sheets("Nhap")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:i" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) + arr(i, 7)
                  kq(a, 2) = kq(a, 2) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 3) = kq(a, 3) + arr(i, 7)
                  kq(a, 4) = kq(a, 4) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            End If
       Next i
  End With
  With Sheets("Xuat")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:K" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) - arr(i, 9)
                  kq(a, 2) = kq(a, 2) - arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 5) = kq(a, 5) + arr(i, 9)
                  kq(a, 6) = kq(a, 6) + arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            End If
       Next i
  End With
  With Sheets("NXT")
       .Range("D4:K4").Resize(UBound(kq)).Value = kq
  End With
  Set dic = Nothing
End Sub
 
Upvote 0
Mã:
a = WorksheetFunction.SumIfs(rngslnhap, rngvtnhap, Ton.Range("A" & i), rngngaynhap, ">=" & day1, rngngaynhap, "<=" & day2)
 
Upvote 0
Thử cái code này xem.
Mã:
Sub tinhsoluong()
   Dim i As Long, lr As Long, dic As Object, arr, data, kq() As Double, a As Long, dk As String, b As Long, ngaybd As Long, ngaykt As Long
   Set dic = CreateObject("scripting.dictionary")
   With Sheets("NXT")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A4:B" & lr).Value
        ngaybd = .Range("o2").Value2
        ngaykt = .Range("R2").Value2
        For i = 1 To UBound(arr)
            dk = arr(i, 1)
            If Not dic.exists(dk) Then
               dic.Add dk, i
            End If
        Next i
        ReDim kq(1 To UBound(arr), 1 To 8)
   End With
   With Sheets("Nhap")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:i" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) + arr(i, 7)
                  kq(a, 2) = kq(a, 2) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 3) = kq(a, 3) + arr(i, 7)
                  kq(a, 4) = kq(a, 4) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            End If
       Next i
  End With
  With Sheets("Xuat")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:K" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) - arr(i, 9)
                  kq(a, 2) = kq(a, 2) - arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 5) = kq(a, 5) + arr(i, 9)
                  kq(a, 6) = kq(a, 6) + arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            End If
       Next i
  End With
  With Sheets("NXT")
       .Range("D4:K4").Resize(UBound(kq)).Value = kq
  End With
  Set dic = Nothing
End Sub
bác giải thích giúp e đoạn
Mã:
ReDim kq(1 To UBound(arr), 1 To 8)
và cái dic.Item với nhé
Bài đã được tự động gộp:

.
Không hiểu. Trước ngày 1, điều kiện là: "<" & day1. Vậy vướng chỗ nào?

.
bác thử chạy code xem nó có ra được không? E chạy nó không dính điều kiện đó, cứ cộng hết các ngày luôn. Vậy e mới thắc mắc đó bác.
 
Upvote 0
Mới nghe lần đầu.

Không khai báo và không set, nhưng vẫn không sao!

.
Trong bài của người ta không cần các dòng trong bài #2 đâu. Họ dùng Nhap, Xuat, Ton, đó là code name của 3 shet "Nhap", "Xuat" và "NXT" mà bạn.

À, thì bài #6 cũng đã giải thích :D
 
Upvote 0
bác giải thích giúp e đoạn
Mã:
ReDim kq(1 To UBound(arr), 1 To 8)
và cái dic.Item với nhé
Bài đã được tự động gộp:


bác thử chạy code xem nó có ra được không? E chạy nó không dính điều kiện đó, cứ cộng hết các ngày luôn. Vậy e mới thắc mắc đó bác.
Tìm hiểu về Array với dictionary có nhé.Mà ở diễn đàn này đọc bài này cũng được.
 
Upvote 0
Tìm hiểu về Array với dictionary có nhé.Mà ở diễn đàn này đọc bài này cũng được.
để e nghiên cứu thêm về việc sử dụng mảng :D cảm ơn bác nhiều :D
 
Upvote 0
Hiện tại e có 1 file tổng hợp nhập xuất tồn, nếu dùng hàm sumifs thì ra đúng kết quả. Tuy nhiên nếu dùng function.sumifs trong vba thì nó không hoạt động đúng.
Yêu cầu là check mã vật tư trước ngày start => số lượng hàng tồn
E đã thử nghiệm ở hàm sumifs thì ra đúng. Lò mò xài vba với đoạn code như hình thì nó lại bỏ qua cái điều kiện thứ 2 (check ngày).
Mọi người giúp e sai ở chỗ nào với.
Code thay thế thì dễ thôi, chỉ cần nhờ ai đó viết hộ. Nhưng nếu bạn không biết sai ở đâu thì ngày mai, tuần sau, tháng tới bạn cũng sẽ lặp lại lỗi đó. Chả nhẽ cứ đi nhờ viết code thay thế?

Lỗi của bạn là tham chiếu chưa đủ (dòng phải từ 4) nên kết quả nếu có sẽ không chính xác. Đó là lỗi nhỏ. Lỗi lớn ở dòng a = ..., cụ thể ở "<" & day1
Mã:
For i = 4 To lrnxt
        a = WorksheetFunction.SumIfs(rngslnhap, rngvtnhap, Ton.Range("A" & i), rngngaynhap, "<" & day1)
Hiện tại NXT!O2 = 12.04.2022 (trên máy tôi ngày tháng có dạng dd.mm.yyyy) nên day1 = 12.04.2022 (do Dim day1 As Variant, day2 As Variant), và "<" & day1 = "<12.04.2022". Trong VBA chuỗi kiểu đó sẽ sai.

Nếu bạn sửa thành
Dim day1 As Long, day2 As Long

thì day1 = 44663, và "<" & day1 = "<44663". Lúc này code sẽ chạy đúng.

Tóm lại sửa thành
Mã:
Dim day1 As Long, day2 As Long
 
Upvote 0
Giải pháp
Chú @batman1 nếu giả sử cháu không khai day1 as long...... Mà chỉ khai dim day1, day2. Kết quả có đúng không nhỉ? Và không gán type cho biến có bất lợi gì không nhỉ? Tại cháu không ngồi máy mà tò mò
 
Upvote 0
Chú @batman1 nếu giả sử cháu không khai day1 as long...... Mà chỉ khai dim day1, day2. Kết quả có đúng không nhỉ? Và không gán type cho biến có bất lợi gì không nhỉ? Tại cháu không ngồi máy mà tò mò
Kết quả giống như khai báo của tác giả thôi vì mặc định là Variant.

Bất lợi gì ở đây? Bất lợi là khai báo không đúng hoặc không "tối ưu" thôi, chứ không phải là ở chỗ khai báo hay không khai báo. Không gán kiểu thì mặc định là Variant. Nếu trong trường hợp cụ thể biến chuẩn phải nên là Variant thì khai báo kiểu Variant tường minh hay không đều như nhau. Nhưng nếu biến phải là Long thì dù khai báo nhưng là Variant thì vẫn sai.
 
Upvote 0
Kết quả giống như khai báo của tác giả thôi vì mặc định là Variant.

Bất lợi gì ở đây? Bất lợi là khai báo không đúng hoặc không "tối ưu" thôi, chứ không phải là ở chỗ khai báo hay không khai báo. Không gán kiểu thì mặc định là Variant. Nếu trong trường hợp cụ thể biến chuẩn phải nên là Variant thì khai báo kiểu Variant tường minh hay không đều như nhau. Nhưng nếu biến phải là Long thì dù khai báo nhưng là Variant thì vẫn sai.
Cám ơn chú nhiều. Tại nhiều khi biếng viết code nháp. Không có options ở đầu sub. Viết xong bắt đầu khai báo biến. Thành ra không điền kiểu biến. Nên mới hỏi chú việc bất lợi. Cám ơn chú vì những thông tin đã chia sẻ
 
Upvote 0
Cám ơn chú nhiều. Tại nhiều khi biếng viết code nháp. Không có options ở đầu sub. Viết xong bắt đầu khai báo biến. Thành ra không điền kiểu biến. Nên mới hỏi chú việc bất lợi. Cám ơn chú vì những thông tin đã chia sẻ
Vấn đề là khai báo và thực thi theo kiểu ít hoặc tốt nhất là không phụ thuộc vào những thay đổi hay thiết lập nào đó. Vd.
ngày 12 tháng 4 năm 2022 trên máy tôi là 12.04.2022, trên máy bạn là 12/04/2022, trên máy khác lại khác nữa. Rồi lăn tăn chuyện trong VBA là mm/dd/yyyy hay dd/mm/yyyy, là ngày 12 tháng 4 năm 2022 hay ngày 4 tháng 12 năm 2022. Thế có phải rách việc không? Khác gì bàn tay trần thọc xuống bể phốt. Trong khi đó nếu Dim day1 As Long thì day1 = 44663 trên bất kỳ máy nào, mọi lúc mọi nơi. Con số 44663 luôn luôn đại diên cho ngày 12 tháng 4 năm 2022, không thể hiểu khác được, không thể là ngày 4 tháng 12 năm 2022 được.

Tóm lại tuy không được lanh lợi như con nhà người ta thì phải khôn ngoan hơn con nhà người ta. :D
 
Upvote 0
@batman1 dạ. Cháu hiểu rồi ạ. Cám ơn chú nhiều về thông tin chú chia sẻ ạ
 
Upvote 0
Code thay thế thì dễ thôi, chỉ cần nhờ ai đó viết hộ. Nhưng nếu bạn không biết sai ở đâu thì ngày mai, tuần sau, tháng tới bạn cũng sẽ lặp lại lỗi đó. Chả nhẽ cứ đi nhờ viết code thay thế?

Lỗi của bạn là tham chiếu chưa đủ (dòng phải từ 4) nên kết quả nếu có sẽ không chính xác. Đó là lỗi nhỏ. Lỗi lớn ở dòng a = ..., cụ thể ở "<" & day1
Mã:
For i = 4 To lrnxt
        a = WorksheetFunction.SumIfs(rngslnhap, rngvtnhap, Ton.Range("A" & i), rngngaynhap, "<" & day1)
Hiện tại NXT!O2 = 12.04.2022 (trên máy tôi ngày tháng có dạng dd.mm.yyyy) nên day1 = 12.04.2022 (do Dim day1 As Variant, day2 As Variant), và "<" & day1 = "<12.04.2022". Trong VBA chuỗi kiểu đó sẽ sai.

Nếu bạn sửa thành


thì day1 = 44663, và "<" & day1 = "<44663". Lúc này code sẽ chạy đúng.

Tóm lại sửa thành
Mã:
Dim day1 As Long, day2 As Long
Em cảm ơn a nhiều, đã được thông não. Đúng là e từng gặp trường hợp như a nói. Giờ đã hiểu sơ sơ ra rồi :D
 
Upvote 0
Thử cái code này xem.
Mã:
Sub tinhsoluong()
   Dim i As Long, lr As Long, dic As Object, arr, data, kq() As Double, a As Long, dk As String, b As Long, ngaybd As Long, ngaykt As Long
   Set dic = CreateObject("scripting.dictionary")
   With Sheets("NXT")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A4:B" & lr).Value
        ngaybd = .Range("o2").Value2
        ngaykt = .Range("R2").Value2
        For i = 1 To UBound(arr)
            dk = arr(i, 1)
            If Not dic.exists(dk) Then
               dic.Add dk, i
            End If
        Next i
        ReDim kq(1 To UBound(arr), 1 To 8)
   End With
   With Sheets("Nhap")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:i" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) + arr(i, 7)
                  kq(a, 2) = kq(a, 2) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 4)
               a = dic.Item(dk)
               If a Then
                  kq(a, 3) = kq(a, 3) + arr(i, 7)
                  kq(a, 4) = kq(a, 4) + arr(i, 9)
                  kq(a, 7) = kq(a, 1) + kq(a, 3)
                  kq(a, 8) = kq(a, 2) + kq(a, 4)
               End If
            End If
       Next i
  End With
  With Sheets("Xuat")
        lr = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A3:K" & lr).Value
        For i = 1 To UBound(arr)
            If CLng(arr(i, 2)) < ngaybd Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 1) = kq(a, 1) - arr(i, 9)
                  kq(a, 2) = kq(a, 2) - arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            ElseIf CLng(arr(i, 2)) <= ngaykt Then
               dk = arr(i, 6)
               a = dic.Item(dk)
               If a Then
                  kq(a, 5) = kq(a, 5) + arr(i, 9)
                  kq(a, 6) = kq(a, 6) + arr(i, 11)
                  kq(a, 7) = kq(a, 1) + kq(a, 3) - kq(a, 5)
                  kq(a, 8) = kq(a, 2) + kq(a, 4) - kq(a, 6)
               End If
            End If
       Next i
  End With
  With Sheets("NXT")
       .Range("D4:K4").Resize(UBound(kq)).Value = kq
  End With
  Set dic = Nothing
End Sub
Bạn làm hay quá
Bạn giúp mình bài của mình phần nhập + xuất + tồn cuối kỳ
Cảm ơn bạn trước
 

File đính kèm

Upvote 0

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

Back
Top Bottom