Code VBA thay hàm và công thức excel

Liên hệ QC

vocongtu

Thành viên mới
Tham gia
12/5/08
Bài viết
19
Được thích
2
Giới tính
Nam
Chào các bác, Em có file excel như đính kèm. Hiện tại em đang dùng công thức ở 2 cột tô màu vàng (cột F và H). Vì số lượng dữ liệu quá nhiều (hiện tại đã trên 20k dòng, em cắt bớt để ví dụ), nên file cực kỳ nặng và tính toán chậm. Tuy em đã thử giới hạn dòng nhưng cũng không cải thiện gì nhiều. Các bác hỗ trợ giúp em viết code VBA cho 2 cột này với ạ. Cám ơn các bác. P/s: Em trừ đuổi từ trên xuống theo điều kiện và dữ liệu ở các cột tương ứng.
 

File đính kèm

  • Code VBA.xlsx
    26.5 KB · Đọc: 7
Chào các bác, Em có file excel như đính kèm. Hiện tại em đang dùng công thức ở 2 cột tô màu vàng (cột F và H). Vì số lượng dữ liệu quá nhiều (hiện tại đã trên 20k dòng, em cắt bớt để ví dụ), nên file cực kỳ nặng và tính toán chậm. Tuy em đã thử giới hạn dòng nhưng cũng không cải thiện gì nhiều. Các bác hỗ trợ giúp em viết code VBA cho 2 cột này với ạ. Cám ơn các bác. P/s: Em trừ đuổi từ trên xuống theo điều kiện và dữ liệu ở các cột tương ứng.
Nhìn công thức trong ô thấy oải, Excel chạy "cứng mình" cũng phải
PHP:
SUMIFS(E:E;B:B;B2;A:A;A2)
1 côt E có 1048576 ô, cột B và cột A cũng vậy. Tính toán cho 1 ô đã oải, đàng này hơn 20.000 ô chỉ 1 cột.
Công thức có điều kiện của cột D là "Pipes" , dữ liệu thật có dòng nào là Pipes ?
 
Upvote 0
Nhìn công thức trong ô thấy oải, Excel chạy "cứng mình" cũng phải
PHP:
SUMIFS(E:E;B:B;B2;A:A;A2)
1 côt E có 1048576 ô, cột B và cột A cũng vậy. Tính toán cho 1 ô đã oải, đàng này hơn 20.000 ô chỉ 1 cột.
Công thức có điều kiện của cột D là "Pipes" , dữ liệu thật có dòng nào là Pipes ?
Thành thật xin lỗi bác. Tại em copy rồi paste value một vài cột không ảnh hưởng nên mới bị vậy. Em xin gửi lại file ạ.
 

File đính kèm

  • Code VBA.xlsx
    25.7 KB · Đọc: 8
Upvote 0
Thành thật xin lỗi bác. Tại em copy rồi paste value một vài cột không ảnh hưởng nên mới bị vậy. Em xin gửi lại file ạ.
Thử code này xem sao
Mã:
Option Explicit
Sub NTKTNN()
Dim sArr(), I&, U&, f1#, f2#, h1#, h2#, iKeyF$, iKeyH$, ResF, ResH, X
Dim DicF As Object, DicH As Object, ArrH
Set DicF = CreateObject("Scripting.Dictionary")
Set DicH = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
    sArr = .Range("A2:K" & .Cells(Rows.Count, "A").End(xlUp).Row).Value
    U = UBound(sArr, 1)
    ReDim ArrH(1 To U, 1 To 2)
    ReDim ResF(1 To U)
    ReDim ResH(1 To U)
    For I = 1 To U
        iKeyF = Trim(sArr(I, 2)) & Trim(sArr(I, 3))
        iKeyH = Trim(sArr(I, 1)) & Trim(sArr(I, 2))
        If Not DicF.exists(iKeyF) Then
            DicF.Add iKeyF, sArr(I, 5)
        Else
            ArrH(I, 1) = DicF.Item(iKeyF)
            DicF.Item(iKeyF) = DicF.Item(iKeyF) + sArr(I, 5)
        End If

        If Not DicH.exists(iKeyH) Then
            DicH.Add iKeyH, Array(sArr(I, 5), sArr(I, 8))
        Else
            ArrH(I, 2) = DicH.Item(iKeyH)(1)
            X = DicH.Item(iKeyH)
            X(0) = DicH.Item(iKeyH)(0) + sArr(I, 5)
            X(1) = DicH.Item(iKeyH)(1) + sArr(I, 8)
            DicH.Item(iKeyH) = X
        End If
    Next
    For I = 1 To U
        iKeyF = Trim(sArr(I, 2)) & Trim(sArr(I, 3))
        iKeyH = Trim(sArr(I, 1)) & Trim(sArr(I, 2))
        f1 = DicF.Item(iKeyF)
        f2 = ArrH(I, 1)
        h1 = DicH.Item(iKeyH)(0)
        h2 = ArrH(I, 2)
        If InStr(1, sArr(I, 4), "Pipes", 1) Then
            ResF(I) = sArr(I, 7) * sArr(I, 5) / f1
            ResH(I) = sArr(I, 9) * sArr(I, 5) / h1
        Else
            If sArr(I, 7) - f2 < 0 Then
                ResF(I) = 0
            ElseIf sArr(I, 7) - f2 >= sArr(I, 5) Then
                ResF(I) = sArr(I, 5)
            Else
                ResF(I) = sArr(I, 7) - f2
            End If
            
            If sArr(I, 9) - h2 < 0 Then
                ResH(I) = 0
            ElseIf sArr(I, 9) - h2 >= sArr(I, 5) Then
                ResH(I) = sArr(I, 5)
            Else
                ResH(I) = sArr(I, 9) - h2
            End If
        End If
    Next
    .Range("M2").Resize(U, 1) = Application.Transpose(ResF)
    .Range("N2").Resize(U, 1) = Application.Transpose(ResH)
End With
End Sub
 

File đính kèm

  • Code VBA.xlsm
    40 KB · Đọc: 15
Upvote 0
Nhìn công thức trong ô thấy oải, Excel chạy "cứng mình" cũng phải
PHP:
SUMIFS(E:E;B:B;B2;A:A;A2)
1 côt E có 1048576 ô, cột B và cột A cũng vậy. Tính toán cho 1 ô đã oải, đàng này hơn 20.000 ô chỉ 1 cột.
Công thức có điều kiện của cột D là "Pipes" , dữ liệu thật có dòng nào là Pipes ?
Ngày xưa, thời Excel 2003, thấy dữ liệu khủng (trên 10 ngàn dòng) thì nghĩ tới "VBA mới giải quyết nổi"
Kể từ 2015, Microsoft đã phổ biến Data Model (và Power BI). Khi thấy dữ liệu khủng thì nên nghĩ đến Data Model.
Cho đến giờ phút này mà còn nghĩ dùng VBA để giải quyết dữ liệu khủng là hơi lạc hậu.
 
Upvote 0
Thử code này xem sao
Mã:
Option Explicit
Sub NTKTNN()
Dim sArr(), I&, U&, f1#, f2#, h1#, h2#, iKeyF$, iKeyH$, ResF, ResH, X
Dim DicF As Object, DicH As Object, ArrH
Set DicF = CreateObject("Scripting.Dictionary")
Set DicH = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
    sArr = .Range("A2:K" & .Cells(Rows.Count, "A").End(xlUp).Row).Value
    U = UBound(sArr, 1)
    ReDim ArrH(1 To U, 1 To 2)
    ReDim ResF(1 To U)
    ReDim ResH(1 To U)
    For I = 1 To U
        iKeyF = Trim(sArr(I, 2)) & Trim(sArr(I, 3))
        iKeyH = Trim(sArr(I, 1)) & Trim(sArr(I, 2))
        If Not DicF.exists(iKeyF) Then
            DicF.Add iKeyF, sArr(I, 5)
        Else
            ArrH(I, 1) = DicF.Item(iKeyF)
            DicF.Item(iKeyF) = DicF.Item(iKeyF) + sArr(I, 5)
        End If

        If Not DicH.exists(iKeyH) Then
            DicH.Add iKeyH, Array(sArr(I, 5), sArr(I, 8))
        Else
            ArrH(I, 2) = DicH.Item(iKeyH)(1)
            X = DicH.Item(iKeyH)
            X(0) = DicH.Item(iKeyH)(0) + sArr(I, 5)
            X(1) = DicH.Item(iKeyH)(1) + sArr(I, 8)
            DicH.Item(iKeyH) = X
        End If
    Next
    For I = 1 To U
        iKeyF = Trim(sArr(I, 2)) & Trim(sArr(I, 3))
        iKeyH = Trim(sArr(I, 1)) & Trim(sArr(I, 2))
        f1 = DicF.Item(iKeyF)
        f2 = ArrH(I, 1)
        h1 = DicH.Item(iKeyH)(0)
        h2 = ArrH(I, 2)
        If InStr(1, sArr(I, 4), "Pipes", 1) Then
            ResF(I) = sArr(I, 7) * sArr(I, 5) / f1
            ResH(I) = sArr(I, 9) * sArr(I, 5) / h1
        Else
            If sArr(I, 7) - f2 < 0 Then
                ResF(I) = 0
            ElseIf sArr(I, 7) - f2 >= sArr(I, 5) Then
                ResF(I) = sArr(I, 5)
            Else
                ResF(I) = sArr(I, 7) - f2
            End If
           
            If sArr(I, 9) - h2 < 0 Then
                ResH(I) = 0
            ElseIf sArr(I, 9) - h2 >= sArr(I, 5) Then
                ResH(I) = sArr(I, 5)
            Else
                ResH(I) = sArr(I, 9) - h2
            End If
        End If
    Next
    .Range("M2").Resize(U, 1) = Application.Transpose(ResF)
    .Range("N2").Resize(U, 1) = Application.Transpose(ResH)
End With
End Sub
Cám ơn bác rất nhiều. Mình đã chạy thử và đáp số ok. Tuy nhiên, mình cần trả về đáp số như 2 cột F và H chứ không phải lấy 2 cột F và H làm data. Bác xem lại giúp với. Bác có thể dùng lại file đính kèm này vì mình mới update. Cám ơn bác nhiều.
 

File đính kèm

  • Code VBA.xlsx
    25.7 KB · Đọc: 4
Upvote 0
Cám ơn bác rất nhiều. Mình đã chạy thử và đáp số ok. Tuy nhiên, mình cần trả về đáp số như 2 cột F và H chứ không phải lấy 2 cột F và H làm data. Bác xem lại giúp với. Bác có thể dùng lại file đính kèm này vì mình mới update. Cám ơn bác nhiều.
Mình không có lấy cột F và H làm data nhé, chẳng qua là gán qua cột một bên để bạn so sánh kết quả sau và trước không thay đổi
.Range("M2").Resize(U, 1) = Application.Transpose(ResF)
.Range("N2").Resize(U, 1) = Application.Transpose(ResH)
Sửa phần M2 -> F2, N2->H2 là ra kết quả mong muốn của bạn
 
Upvote 0
Web KT

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

Back
Top Bottom