Bạn có thể cụ thể thêmEm nhờ các thầy, anh chị trên diễn đàn chuyển giúp hộ em từ công thức sang code VBA với ạ. Trong file em dùng hàm Vookup, hàm Sumproduct nên file chạy rất chậm. Công thức ở bên Sheet BAOCAO đấy ạ.
Sub TaoBC()
Dim endR&, i&, s&, k&, nR&, nC&
Dim fDate&, eDate&
Dim sTmp01$, sTmp02$
Dim Arr, ArrPX, ArrDM, ArrSL
Dim Dic01 As Object, Dic02 As Object
Set Dic01 = CreateObject("Scripting.Dictionary")
Set Dic02 = CreateObject("Scripting.Dictionary")
With Sheets("BaoCao")
fDate = CLng(.[J4])
eDate = CLng(.[L4])
ArrPX = .Range("F9:AB9").Value
End With
With Sheets("Xuat")
endR = .Cells(65000, "E").End(3).Row
Arr = .Range("D6:N" & endR).Value
End With
s = 0
For i = 1 To UBound(ArrPX, 2) Step 2
sTmp01 = Trim(Mid(ArrPX(1, i), 4, 10))
s = s + 1
Dic01.Add sTmp01, s
Next i
ReDim ArrDM(1 To 10000, 1 To 5)
ReDim ArrSL(1 To 10000, 1 To 24)
s = 0
For i = 1 To UBound(Arr)
If CLng(Arr(i, 1)) <= eDate Then
If CLng(Arr(i, 1)) >= fDate Then
If Len(Arr(i, 2)) > 0 Then
sTmp02 = Arr(i, 2)
sTmp01 = Arr(i, 8)
If Not Dic02.Exists(sTmp02) Then
s = s + 1
Dic02.Add sTmp02, s
ArrDM(s, 1) = s 'TT
For k = 2 To 4
ArrDM(s, k) = Arr(i, k)
Next k
End If
nR = Dic02.Item(sTmp02)
nC = 2 * Dic01.Item(sTmp01) - 1
ArrSL(nR, nC) = ArrSL(nR, nC) + Arr(i, 5)
ArrSL(nR, nC + 1) = ArrSL(nR, nC + 1) + Arr(i, 7)
ArrDM(nR, 5) = ArrDM(nR, 5) + Arr(i, 5)
End If
End If
End If
Next i
If s Then
With Sheets("BaoCao")
.[A11].Resize(1000, 29).ClearContents
.[A11].Resize(s, 5) = ArrDM
.[F11].Resize(s, 24) = ArrSL
End With
Erase ArrDM, ArrSL
End If
Set Dic01 = Nothing: Set Dic02 = Nothing
Erase Arr, ArrPX
End Sub
Vấn đề chính là file trên đúng yêu cầu chưa?Cảm ơn thầy ạ. Đúng là BAOCAO em chỉ lấy dữ liệu bên Sheet Xuat thôi. Nhưng tên vật tư em muốn lấy bên Sheet CDNXT vì bên Xuat cũng là vật tư đó nhưng em có thể chú thích thêm vào tên của nó.
VD:AU001 là Ấu nối xích máng cào SKAt 80 nhưng khi xuất em lại ghi chú cho nó thêm là Ấu nối xích máng cào SKAt 80 (DV-25) chẳng hạn. Em sợ như thế thì không lấy đc tên vật tư theo Sheet Xuat.
Thầy có thể dịch code sang tiếng việt giúp em được không ạ. Cảm ơn thầy nhiều.
A/ Nếu chưa có cột K thì báo lỗi, cần thì viết thêm 1 dòng codeVâng file trên đúng yêu cầu rồi ạ. Em hỏi thêm chút nữa là bên
Sheet Xuat nếu có 1 vật tư nào chưa vào mã ĐV Lĩnh (cột K) thì sẽ bị báo lỗi. Giờ bên BAOAO em xóa hết các cột Nợ Phiếu đi thì code phải sửa thế nào ạ. Nhờ thầy chỉ giúp.
Cái hàm UBound(Arr) này là hàm gì ấy ạ.
If Not Dic01.Exists(sTmp01) Then
MsgBox "Chua nhap " & sTmp01 & " tai cot K dong " & i + 5
Exit Sub
End If
For i = 1 To UBound(ArrPX, 2) Step 2
For i = 1 To UBound(ArrPX, 2)
nC = 2 * Dic01.Item(sTmp01) - 1
nC = Dic01.Item(sTmp01)
.[F11].Resize(s, 24) = ArrSL
.[F11].Resize(s, 12) = ArrSL
Sub TaoBC()
Dim endR&, i&, s&, k&, nR&, nC&
Dim fDate&, eDate&
Dim sTmp01$, sTmp02$
Dim Arr, ArrPX, ArrDM, ArrSL
Dim Dic01 As Object, Dic02 As Object
Set Dic01 = CreateObject("Scripting.Dictionary")
Set Dic02 = CreateObject("Scripting.Dictionary")
With Sheets("BaoCao")
fDate = CLng(.[J4])
eDate = CLng(.[L4])
ArrPX = .Range("F9:Q9").Value
End With
With Sheets("Xuat")
endR = .Cells(65000, "E").End(3).Row
Arr = .Range("D6:N" & endR).Value
End With
s = 0
'For i = 1 To UBound(ArrPX, 2) Step 2'
For i = 1 To UBound(ArrPX, 2)
sTmp01 = Trim(Mid(ArrPX(1, i), 4, 10))
s = s + 1
Dic01.Add sTmp01, s
Next i
ReDim ArrDM(1 To 10000, 1 To 5)
ReDim ArrSL(1 To 10000, 1 To 12)
s = 0
For i = 1 To UBound(Arr)
If CLng(Arr(i, 1)) <= eDate Then
If CLng(Arr(i, 1)) >= fDate Then
If Len(Arr(i, 2)) > 0 Then
sTmp02 = Arr(i, 2)
sTmp01 = Arr(i, 8)
If Not Dic01.Exists(sTmp01) Then
MsgBox "Chua nhap " & sTmp01 & " tai cot K dong " & i + 5
Exit Sub
End If
If Not Dic02.Exists(sTmp02) Then
s = s + 1
Dic02.Add sTmp02, s
ArrDM(s, 1) = s 'TT'
For k = 2 To 4
ArrDM(s, k) = Arr(i, k)
Next k
End If
nR = Dic02.Item(sTmp02)
nC = Dic01.Item(sTmp01)
'nC = 2 * Dic01.Item(sTmp01) - 1'
ArrSL(nR, nC) = ArrSL(nR, nC) + Arr(i, 5)
' ArrSL(nR, nC + 1) = ArrSL(nR, nC + 1) + Arr(i, 7)'
ArrDM(nR, 5) = ArrDM(nR, 5) + Arr(i, 5)
End If
End If
End If
Next i
If s Then
With Sheets("BaoCao")
.[A11].Resize(1000, 29).ClearContents
.[A11].Resize(s, 5) = ArrDM
'.[F11].Resize(s, 24) = ArrSL'
.[F11].Resize(s, 12) = ArrSL
End With
Erase ArrDM, ArrSL
End If
Set Dic01 = Nothing: Set Dic02 = Nothing
Erase Arr, ArrPX
End Sub
Vâng chính xác, còn cái vụ "Sheet Xuat nếu có 1 vật tư nào chưa vào mã ĐV Lĩnh (cột K) thì sẽ bị báo lỗi". Ý của em là nếu chưa có Mã ĐVL thì bỏ qua không cộng dòng đó. Chỉ cộng tổng những dòng nào có mã ĐVL thôi.
If Not Dic01.Exists(sTmp01) Then
MsgBox "Chua nhap " & sTmp01 & " tai cot K dong " & i + 5
Exit Sub
End If
If Not Dic01.Exists(sTmp01) Then Goto Next_For
Thầy ThuNghi ơi cho em làm phiền thầy chút nữa. Giờ em có tình huống phức tạp hơn trước nhờ thầy giúp đỡ. Yêu cầu cũng tựa như trên là tính tổng theo mã vật tư nhưng không lọc theo mã ĐL Lĩnh nữa mà lọc theo mã Xe, máy bên cột Mục đích của Sheet Xuat. Làm sao có thể lọc chính xác số xe, máy ra? Nhờ thầy giúp đỡ.
Dung code sauVâng bên Sheet Xuat em có Cột Mã Xe-Máy (cột S) chính là tên xe, máy em đã lọc ra đó. Có thể lọc theo Cột S cũng đc. Nhưng em muốn lọc từ cột Mục đích (cột N) cho chính xác. Vì khi xuất đôi khi còn chèn dòng mà lại quên copy công thức từ dòng trên xuống thì cột S(mã xe, máy) không lọc ra được tên xe, máy.
- Những hàng nào mà không có xe, máy thì không thuộc xe, máy (không cần báo cáo)
Dim myStr$, Str$
Dim ArrXM()
Dim Obj As Object
Public Function LocArr(sTmp As String, sArr) As String
Set Obj = CreateObject("VBScript.RegExp")
For i = 1 To UBound(sArr)
If Len(ArrXM(i, 1)) > 0 Then
If Len(myStr) = 0 Then
myStr = sArr(i, 1)
Else
myStr = myStr & "|" & sArr(i, 1)
End If
End If
Next i
With Obj
.Global = True
.IgnoreCase = True
.Pattern = myStr
If .Test(sTmp) Then
myStr = .Execute(sTmp)(0)
Else
myStr = ""
End If
End With
LocArr = myStr
End Function
Public Function IsArrayEmtpy(Mang As Variant) As Boolean
On Error GoTo XulyError
Dim i As Integer
i = UBound(Mang)
IsArrayEmtpy = False
Exit Function
XulyError:
IsArrayEmtpy = True
End Function
Sub TaoArr()
With Sheets("Xemay")
ArrXM = .Range("C6:C100").Value
End With
End Sub
Sub TaoBC()
With Application
.ScreenUpdating = False: .Calculation = xlCalculationManual
End With
Dim endR&, i&, s&, k&, nR&, nC&
Dim fDate&, eDate&
Dim sTmp01$, sTmp02$
Dim Arr, ArrPX, ArrDM, ArrSL
Dim Dic01 As Object, Dic02 As Object
Set Dic01 = CreateObject("Scripting.Dictionary")
Set Dic02 = CreateObject("Scripting.Dictionary")
With Sheets("BaoCao")
fDate = CLng(.[J4])
eDate = CLng(.[L4])
ArrTd = .Range("F9:BP9").Value
End With
If IsArrayEmtpy(ArrXM) Then
TaoArr
End If
s = 0
For i = 1 To UBound(ArrTd, 2)
Str = ArrTd(1, i)
sTmp01 = LocArr(Str, ArrXM)
If Len(sTmp01) = 0 Then sTmp01 = i
s = s + 1
Dic01.Add sTmp01, s
Next i
With Sheets("Xuat")
endR = .Cells(65000, "E").End(3).Row
Arr = .Range("D6:N" & endR).Value
End With
ReDim ArrDM(1 To 10000, 1 To 5)
ReDim ArrSL(1 To 10000, 1 To 63)
s = 0
For i = 1 To UBound(Arr)
If CLng(Arr(i, 1)) <= eDate Then
If CLng(Arr(i, 1)) >= fDate Then
If Len(Arr(i, 2)) > 0 Then
Str = Arr(i, 11)
sTmp01 = LocArr(Str, ArrXM)
If Len(sTmp01) > 0 Then
sTmp02 = Arr(i, 2)
If Not Dic02.Exists(sTmp02) Then
s = s + 1
Dic02.Add sTmp02, s
ArrDM(s, 1) = s 'TT'
For k = 2 To 4
ArrDM(s, k) = Arr(i, k)
Next k
End If
nR = Dic02.Item(sTmp02)
nC = Dic01.Item(sTmp01)
ArrSL(nR, nC) = ArrSL(nR, nC) + Arr(i, 5)
ArrDM(nR, 5) = ArrDM(nR, 5) + Arr(i, 5)
End If
End If
End If
End If
Next i
If s Then
With Sheets("BaoCao")
.[A11].Resize(1000, 68).ClearContents
.[A11].Resize(s, 5) = ArrDM
.[F11].Resize(s, 63) = ArrSL
End With
Erase ArrDM, ArrSL
End If
Set Dic01 = Nothing: Set Dic02 = Nothing
Erase Arr, ArrTd
With Application
.ScreenUpdating = True: .Calculation = xlCalculationAutomatic
End With
End Sub
Tôi thấy bạn viết UDF Loc rất cáo siêu mà sao kg chịu nghiên cứu code.Thú thực là đọc code em không hiểu được. Thầy có thể chỉnh hộ sao cho từ F9:BZ9 để em có thể gõ số xe trực tiếp vào đó (0245, 0146, 7949, PC, TS,....) được không. Vì sau này xe, máy có thể có thêm nữa. Cảm ơn thầy nhiều
With Sheets("BaoCao")
fDate = CLng(.[J4])
eDate = CLng(.[L4])
eC = .Cells(9, 6).End(xlToRight).Column
ArrTd = .Cells(9, 6).Resize(, eC - 5).Value
'ArrTd = .Range("F9:BP9").Value'
End With
Bài này cũng giống như bài file NXT, bạn vận dụng vào, thay tên sh BaoCao -> TongHop.Xin lỗi làm phiền thầy 1 lần này nữa thôi. Giờ em tạo thêm 1 Sheet TONGHOP nữa để tổng hợp số lượng theo đơn vị lĩnh. Đơn vị vừa là số vừa là chữ lại lẫn lộn không theo quy định nào. Nhờ thầy sửa giúp code tính tổng theo Mã VT và Mã ĐV lĩnh với.
Tham gia 1 code cho vui, vừa học hỏi mấy cái "Đic Đic lộn xộn".Xin lỗi làm phiền thầy 1 lần này nữa thôi. Giờ em tạo thêm 1 Sheet TONGHOP nữa để tổng hợp số lượng theo đơn vị lĩnh. Đơn vị vừa là số vừa là chữ lại lẫn lộn không theo quy định nào. Nhờ thầy sửa giúp code tính tổng theo Mã VT và Mã ĐV lĩnh với.
Public Sub GPE1()
Dim Rng(), Rng1(), Arr(), I As Long, K As Long, Dic As Object, Dic1 As Object, ND As Long, NC As Long
Set Dic = CreateObject("Scripting.Dictionary")
Set Dic1 = CreateObject("Scripting.Dictionary")
Rng = Sheets("Xuat").Range(Sheets("Xuat").[D6], Sheets("Xuat").[D65000].End(xlUp)).Resize(, 8).Value
Rng1 = Sheets("Tonghop").Range(Sheets("Tonghop").[F10], Sheets("Tonghop").[F10].End(xlToRight)).Value
ND = Sheets("Tonghop").[J4].Value: NC = Sheets("Tonghop").[L4].Value
ReDim Arr(1 To UBound(Rng, 1), 1 To UBound(Rng1, 2) + 5)
For I = 1 To UBound(Rng1, 2)
Dic1.Add Rng1(1, I), I
Next I
For I = 1 To UBound(Rng, 1)
If Rng(I, 2) <> "" Then
If Not Dic.exists(Rng(I, 2)) Then
K = K + 1
Dic.Add Rng(I, 2), K
Arr(K, 1) = K: Arr(K, 2) = Rng(I, 2)
Arr(K, 3) = Rng(I, 3): Arr(K, 4) = Rng(I, 4)
If Rng(I, 1) >= ND And Rng(I, 1) <= NC Then
Arr(K, Dic1.Item(Rng(I, 8)) + 5) = Rng(I, 5)
Arr(K, 5) = Arr(K, 5) + Rng(I, 5)
End If
Else
If Rng(I, 1) >= ND And Rng(I, 1) <= NC Then
Arr(Dic.Item(Rng(I, 2)), Dic1.Item(Rng(I, 8)) + 5) = Arr(Dic.Item(Rng(I, 2)), Dic1.Item(Rng(I, 8)) + 5) + Rng(I, 5)
Arr(Dic.Item(Rng(I, 2)), 5) = Arr(Dic.Item(Rng(I, 2)), 5) + Rng(I, 5)
End If
End If
End If
Next I
Sheets("Tonghop").[A11:A1000].Resize(, UBound(Rng1, 2) + 5).ClearContents
Sheets("Tonghop").[A11].Resize(K, UBound(Rng1, 2) + 5).Value = Arr
Set Dic = Nothing
Set Dic1 = Nothing
End Sub
Tham gia 1 code cho vui, vừa học hỏi mấy cái "Đic Đic lộn xộn".
Code dùng cho sheet TongHop.
Kiểm tra số liệu thấy sai, tìm cả buổi trời rồi tức muốn "hộc máu".PHP:For I = 1 To UBound(Rng1, 2) Dic1.Add Rng1(1, I), I Next I For I = 1 To UBound(Rng, 1) If Rng(I, 2) <> "" Then If Not Dic.exists(Rng(I, 2)) Then K = K + 1 Dic.Add Rng(I, 2), K Arr(K, 1) = K: Arr(K, 2) = Rng(I, 2) Arr(K, 3) = Rng(I, 3): Arr(K, 4) = Rng(I, 4) If Rng(I, 1) >= ND And Rng(I, 1) <= NC Then Arr(K, Dic1.Item(Rng(I, 8)) + 5) = Rng(I, 5) Arr(K, 5) = Arr(K, 5) + Rng(I, 5) End If Else If Rng(I, 1) >= ND And Rng(I, 1) <= NC Then Arr(Dic.Item(Rng(I, 2)), Dic1.Item(Rng(I, 8)) + 5) = Arr(Dic.Item(Rng(I, 2)), Dic1.Item(Rng(I, 8)) + 5) + Rng(I, 5) Arr(Dic.Item(Rng(I, 2)), 5) = Arr(Dic.Item(Rng(I, 2)), 5) + Rng(I, 5) End If End If End If Next I
VD:dòng 1348 mã " MĐ" (có khoảng trắng phía trước).Híc!
Dữ liệu vài chục ngàn dòng mà nhập kiểu này "thất thoát tài sản" chết luôn.
Dic1.Add Trim(Rng1(1, I)), I
Arr(K, Dic1.Item(Trim(Rng(I, 8))) + 5) = Rng(I, 5)
NewC=Dic1.Item(Trim(Rng(I, 8)))
NeWR=Dic.Item(Rng(I, 2))
If Rng(I, 2) <> "" Then
If Rng(I, 1) >= ND then
If Rng(I, 1) <= NC then
...