Hỏi code nào chạy hàm max nhanh hơn ko? (1 người xem)

  • Thread starter Thread starter qtm1987
  • Ngày gửi Ngày gửi
Liên hệ QC

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

qtm1987

Thành viên thường trực
Tham gia
15/9/09
Bài viết
352
Được thích
262
Nghề nghiệp
Kế toán tổng hợp
Trong excel mình gõ vào ô A2 = max($A$1:A1) + 1 {đây là cột số thứ tự 1 2 3 4 5 ....n số} rồi kéo công thức này cho các ô bên dưới. Nếu khoản chục hàng thì công thức xử lý nhanh nhưng nếu khoản 60.000 dòng thì thấy tốc độ xử lý công thức này rất chậm làm máy treo lun &&&%$R. Cho mình hỏi có code nào trong VBA thực hiện được công việc giống công thức này ko và tốc độ khi xử lý số dòng lớn như vậy có nhanh được không? Mong sự giúp đỡ của các bạn trong diễn đàn.
 

File đính kèm

Lần chỉnh sửa cuối:
Trong excel mình gõ vào ô A2 = max($A$1:A1) + 1 {đây là cột số thứ tự 1 2 3 4 5 ....n số} rồi kéo công thức này cho các ô bên dưới. Nếu khoản chục hàng thì công thức xử lý nhanh nhưng nếu khoản 60.000 dòng thì thấy tốc độ xử lý công thức này rất chậm làm máy treo lun &&&%$R. Cho mình hỏi có code nào trong VBA thực hiện được công việc giống công thức này ko và tốc độ khi xử lý số dòng lớn như vậy có nhanh được không? Mong sự giúp đỡ của các bạn trong diễn đàn.
Nếu danh sách liên tục thì thay vì hàm MAX, bạn có thể sử dụng hàm ROW, chẳng hạn: A2=ROW(1:1) --> fill xuống.
 
Upvote 0
hix. file của mình thì danh sách ko liên tục, hok sài được hàm ROW. Chủ yếu công thức nói trên mình kết hợp với hàm IF để đếm số thứ tự tại những ô của Cột B, ô nào có dữ liệu thì số thứ tự là 1 rồi tiếp theo ô nào ko có dữ liệu thì bỏ trống ko đếm, cứ thế mà đếm lên 2, 3, 4.... n số .v.v...
 
Upvote 0
hix. file của mình thì danh sách ko liên tục, hok sài được hàm ROW. Chủ yếu công thức nói trên mình kết hợp với hàm IF để đếm số thứ tự tại những ô của Cột B, ô nào có dữ liệu thì số thứ tự là 1 rồi tiếp theo ô nào ko có dữ liệu thì bỏ trống ko đếm, cứ thế mà đếm lên 2, 3, 4.... n số .v.v...
Nếu là 60,000 dòng dữ liệu thì chẳng có công thức nào "nhanh" được đâu!
- Một là bạn gõ công thức, xong copy và paste values vào dữ liệu
- Hai là dùng code VBA
 
Upvote 0
Bạn xài cái này khá nhanh nè, khoảng 1/4 giây, nếu là dữ liệu liên tục

Sub STT()
[A2:A65536] = [row(A:A)]
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn xài cái này khá nhanh nè, khoảng 1/4 giây, nếu là dữ liệu liên tục

Sub STT()
[A2:A65536] = [row(A:A)]
End Sub
Người ta đã nói không dùng được ROW rồi cơ mà
Ngoài ra, do bạn test trên 1 bảng tính trắng nên thấy nhanh ---> Nếu trong 1 file đang chưa nhiều công thức thì.. code này vẫn chưa nhanh đâu ---> Code cho tốc độ nhanh nhất là dùng mảng
------------
Cũng định làm nhưng chẳng thấy tác giả cho file lên nên chẳng biết giúp thế nào
 
Upvote 0
Oh code của mình không áp dụng cho bạn được rồi.
 
Upvote 0
Cũng định làm nhưng chẳng thấy tác giả cho file lên nên chẳng biết giúp thế nào

Em bổ sung file đính kèm rồi. Anh giúp em code cho cột số thứ tự (Cột tô màu hồng) anh nhé. file này e lọc ra có mấy chục dòng thôi, nhưng vì số chứng từ thu chi thực tế nhiều lắm nên hàm max trong cột STT em đặt khi làm nhiều dòng nó bị treo máy.
 
Upvote 0
Em bổ sung file đính kèm rồi. Anh giúp em code cho cột số thứ tự (Cột tô màu hồng) anh nhé. file này e lọc ra có mấy chục dòng thôi, nhưng vì số chứng từ thu chi thực tế nhiều lắm nên hàm max trong cột STT em đặt khi làm nhiều dòng nó bị treo máy.
Thử code này vào file của bạn xem (Viết theo thuật toán trong công thức của bạn)
PHP:
Sub STT()
  Dim i As Long, n As Long, tmp1 As String, tmp2 As String, sArray, Arr()
  With Sheets("Phat sinh")
    sArray = .Range(.[P6], .[P65536].End(xlUp))
    tmp1 = CStr(.Range("P5").Value)
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
      If CStr(sArray(i, 1)) <> "" Then
        tmp2 = CStr(sArray(i, 1))
        If tmp2 <> tmp1 Then
          n = n + 1
          Arr(i, 1) = n
        End If
      End If
      tmp1 = CStr(sArray(i, 1))
    Next
    If n Then .Range("A6").Resize(i - 1).Value = Arr
  End With
End Sub
 
Upvote 0
Em bổ sung file đính kèm rồi. Anh giúp em code cho cột số thứ tự (Cột tô màu hồng) anh nhé. file này e lọc ra có mấy chục dòng thôi, nhưng vì số chứng từ thu chi thực tế nhiều lắm nên hàm max trong cột STT em đặt khi làm nhiều dòng nó bị treo máy.
Bạn thử code này xem
PHP:
Sub STT()
Dim rngHD As Variant, kqstt() As Variant, irow As Long, i As Long
With Sheets("Phat sinh")
rngHD = .Range("P5:P" & .Range("p65000").End(xlUp).Row).Value
ReDim kqstt(1 To UBound(rngHD, 1), 1 To 1)

    For irow = 1 To UBound(rngHD, 1) - 1

        If rngHD(irow, 1) <> rngHD(irow + 1, 1) Then
            i = i + 1
            kqstt(irow, 1) = i
        End If
    
    Next irow

.Range("A6").Resize(irow).Value = kqstt
End With
End Sub
 
Upvote 0
Thử code này vào file của bạn xem (Viết theo thuật toán trong công thức của bạn)

Tuyệt vời , 1 click là ra ngay kết quả cho 65536 hàng. Chân thành cám ơn sự giúp đỡ của ndu960818631. Đoạn code này giải thuật là thế nào vậy anh, em đang làm quen với VBA nên muốn học hỏi thêm.
 
Upvote 0
Mình góp vui code này. Code cua anh NDU chạy nhanh hơn nhưng cao cấp quá

Anh quanghai1969 ơi, sao em test thử code của anh em tăng lên nhìu hàng nữa thì code của anh chạy tới khoảng stt 51 là ko chạy típ nữa vậy anh. Code của anh cũng hay thiệt. Cám ơn sự giúp đỡ của anh.
 
Upvote 0
Tại dòng bắt đầu chạy công thức (row 6), bạn có :
Mã:
=IF(AND($P6>0)*($P6<>$P5),MAX($A$4:$A5)+1,"")
Bạn chỉ cần sửa lại thành:
Mã:
=IF(AND(P6>0)*(P6<>P5),MAX(A1:A5)+1,"")
:bye1:
Mã:
MAX($A$4:$A5) thành MAX(A1:A5)
là có thể đáp ứng với mục tiêu của bạn.

Trường hợp với 1 số thứ tự ra nhiều hơn 4 kết quả liên quan thì bạn có thể chèn thêm dòng trống vào ở "Row 1". Chẳng hạn ước lượng tối đa ra 10 kết quả liên quan bạn thêm vào 6 dòng, tối đa 20 kết quả thì thêm 16 dòng. Bạn ẩn các dòng trống này đi cho đẹp mắt %#^#$.

Hy vọng đúng như ý bạn.
 
Lần chỉnh sửa cuối:
Upvote 0
Tuyệt vời , 1 click là ra ngay kết quả cho 65536 hàng. Chân thành cám ơn sự giúp đỡ của ndu960818631. Đoạn code này giải thuật là thế nào vậy anh, em đang làm quen với VBA nên muốn học hỏi thêm.
Vẫn là thuật toán y chang như trong công thức của bạn thôi, tức giá trị tại cột P khác rổng đồng thời "thằng em" phía dưới khác phía trên thì điền STT... vậy thôi
Vấn đề là tôi dùng phương pháp xử lý mảng, toàn bộ xử lý theo kiểu "ảo", xong việc ta gán 1 lần vào bảng tính (chứ không xử lý từng cell)... Vì lẽ đó mà tốc độ rất nhanh
Bạn mới học VBA thì không cần phải vội, cứ từ từ với những điều đơn giản nhất ---> Rồi cũng sẽ hiểu mọi thứ thôi!
 
Upvote 0
Anh quanghai1969 ơi, sao em test thử code của anh em tăng lên nhìu hàng nữa thì code của anh chạy tới khoảng stt 51 là ko chạy típ nữa vậy anh. Code của anh cũng hay thiệt. Cám ơn sự giúp đỡ của anh.

Mình cũng chèn thêm dòng và test thử thấy bình thường mà
 

File đính kèm

Upvote 0
Tại dòng bắt đầu chạy công thức (row 6), bạn có :
Mã:
=IF(AND($P6>0)*($P6<>$P5),MAX($A$4:$A5)+1,"")
Bạn chỉ cần sửa lại thành:
Mã:
=IF(AND(P6>0)*(P6<>P5),MAX(A1:A5)+1,"")
:bye1:
Mã:
MAX($A$4:$A5) thành MAX(A1:A5)
là có thể đáp ứng với mục tiêu của bạn.
uh. mình hiểu rồi, với cách của App là giới hạn lại vùng cho hàm MAX thì tốc độ xử lý mau hơn. Cám ơn bạn nhé.
 
Upvote 0
Để giúp bạn hiệu rõ hiệu quả của phương pháp rút gọn, mình sẽ đưa ra giải thích sau đây:


Tại phương pháp ban đầu của với 60.000 dòng thì khi sử dụng hàm MAX bạn sẽ có tổng cộng: 2+3+4+...+59.999= 59.999x60.000:2-1= 1.799.969.999 ≈ 1.800.000.000 phép so sánh. Đây là lý do khiến phép tính của bạn làm treo máy.


Với phương pháp rút gọn với hàm MAX bạn sẽ có: 10x60.000=600.000 phép so sánh. Ít hơn ...3.000 lần.


Còn với phương án có dùng tới lệnh redim, với mỗi lần ra lệnh redim máy tính sẽ phải thực hiện việc sau:
1. Cấp phát bộ nhớ cho mảng mới. (xác định vùng nhớ có thể đủ sử dụng)
2. Giải phóng bộ nhớ dành cho mảng ban đầu.
Và bạn phải làm thêm một số công việc như gán dữ liệu cho từng ô nhớ, so sánh...
Cho nên lệnh redim không được khuyến khích sử dụng trong giới lập trình. Trong khi đó với hàm MAX, công việc của máy tính đơn giản là so sánh từng ô nhớ với 1 ô nhớ trung gian để tìm ra giá trị lớn nhất.

Tuy nhiên đây chỉ là lý thuyết, thực nghiệm mới cho bạn sự lựa chọn chính xác và phù hợp.

Thân chào.
 
Lần chỉnh sửa cuối:
Upvote 0
Tại dòng bắt đầu chạy công thức (row 6), bạn có :
Mã:
=IF(AND($P6>0)*($P6<>$P5),MAX($A$4:$A5)+1,"")
Bạn chỉ cần sửa lại thành:
Mã:
=IF(AND(P6>0)*(P6<>P5),MAX(A1:A5)+1,"")
:bye1:
Mã:
MAX($A$4:$A5) thành MAX(A1:A5)
là có thể đáp ứng với mục tiêu của bạn.

Trường hợp với 1 số thứ tự ra nhiều hơn 4 kết quả liên quan thì bạn có thể chèn thêm dòng trống vào ở "Row 1". Chẳng hạn ước lượng tối đa ra 10 kết quả liên quan bạn thêm vào 6 dòng, tối đa 20 kết quả thì thêm 16 dòng. Bạn ẩn các dòng trống này đi cho đẹp mắt %#^#$.

Hy vọng đúng như ý bạn.
Để giúp bạn hiệu rõ hiệu quả của phương pháp rút gọn, mình sẽ đưa ra giải thích sau đây:

Tại phương pháp ban đầu của với 60.000 dòng thì khi sử dụng hàm MAX bạn sẽ có tổng cộng: 2+3+4+...+59.999= 59.999x60.000:2-1= 1.799.969.999 ≈ 1.800.000.000 phép so sánh. Đây là lý do khiến phép tính của bạn làm treo máy.
Với phương pháp rút gọn với hàm MAX bạn sẽ có: 10x60.000=600.000 phép so sánh. Ít hơn ...3.000 lần.
Nghe thì có vẽ rất có lý, thế nhưng không biết bạn đã thí nghiệm chắc chưa?
Hãy thử trong trường hợp ở cột P có 6 cell liên tiếp trùng nhau
Nói chung, muốn tính MAX thì phải so sánh "từ đầu đến chân"
 
Upvote 0
Như mình đã nói:
Tuy nhiên đây chỉ là lý thuyết, thực nghiệm mới cho bạn sự lựa chọn chính xác và phù hợp.
Trường hợp với 1 số thứ tự ra nhiều hơn 4 kết quả liên quan thì bạn có thể chèn thêm dòng trống vào ở "Row 1". Chẳng hạn ước lượng tối đa ra 10 kết quả liên quan bạn thêm vào 6 dòng, tối đa 20 kết quả thì thêm 16 dòng. Bạn ẩn các dòng trống này đi cho đẹp mắt %#^#$.
.
Mình thiếu sót khi quên nói cách hiệu chỉnh công thức tương ứng theo số dòng bổ sung. Tuy nhiên đây là công thức rút gọn ra của bạn qtm1987 nên bạn qtm1987 chắc chắn đã hiểu rõ để có thể tự giải quyết.:-=

Một số ý mình dẫn từ lý thuyết về CTDL và HĐH nên có vẻ không ăn nhập lắm với Excel hay VBA.

Thân chào.
 
Lần chỉnh sửa cuối:
Upvote 0
Anh ndu96081631 ơi, cũng file đó giờ ở cột T là số thự tự của phiếu thu thỏa 3 điều kiện (giá trị tại cột A <> "", giá trị tại cột F = "1111", giá trị tại cột G <> "33311") thì mới đánh số thự tự. Cột T này có thể sử dụng code theo kiểu mảng mà anh viết cho cột A được không anh.
 
Upvote 0
Anh ndu96081631 ơi, cũng file đó giờ ở cột T là số thự tự của phiếu thu thỏa 3 điều kiện (giá trị tại cột A <> "", giá trị tại cột F = "1111", giá trị tại cột G <> "33311") thì mới đánh số thự tự. Cột T này có thể sử dụng code theo kiểu mảng mà anh viết cho cột A được không anh.
Vậy đánh STT cùng lúc cho cột A và cột T luôn nha
PHP:
Sub STT()
  Dim i As Long, n As Long, k As Long, tmp1 As String, tmp2 As String, sArray, Arr1(), Arr2()
  With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[P65536].End(xlUp))
    ReDim Arr1(1 To UBound(sArray, 1), 1 To 1)
    ReDim Arr2(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
      If CStr(sArray(i, 16)) <> "" Then
        tmp2 = CStr(sArray(i, 16))
        If tmp2 <> tmp1 Then
          n = n + 1
          Arr1(i, 1) = n
          If (sArray(i, 6) = 1111) And (sArray(i, 7) <> 33311) Then
            k = k + 1
            Arr2(i, 1) = k
          End If
        End If
      End If
      tmp1 = CStr(sArray(i, 16))
    Next
    If n Then
      .Range("A6").Resize(i - 1).Value = Arr1
      .Range("T6").Resize(i - 1).Value = Arr2
    End If
  End With
End Sub
 
Upvote 0
Mọi người cho mình hỏi, với file excel số lượng dòng quá lớn thì những hàm công thức tính toán trong excel sẽ làm tốc độ đọc file chậm đúng không vậy. Cái file excel của mình sử dụng nhiều cột phụ để đi đến 1 kết quả nên dùng các hàm index, offset, match,.... khi mở file thì như rùa bò ////// bây giờ nếu mình sử dụng code để thay thế thì việc dùng hàm công thức của excel để viết trong VBA thì tốc độ có nhanh hơn không?
Trong file excel của mình, tại cột AJ (lọc ra giá trị thuế đầu ra), mình dùng quá nhiều cột phụ để tìm ra kết quả cho cột AJ, bây giờ mình dùng code này: (em bắt chước viết theo kiểu của anh ndu, có gì sai anh sửa giúp em với nhé -+*/ )
PHP:
Sub tinh33311()
Dim i As Long, j As Long, n As Long, sArray, Arr()
With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[AO65536].End(xlUp))
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
        For j = i + 1 To UBound(sArray, 1)
        If (CStr(sArray(j, 1)) = "") And (sArray(j, 7) = 33311) And (sArray(j, 3) = sArray(i, 34)) Then
            Arr(i, 1) = sArray(j, 10)
        End If
        Next
    Next
    .Range("AJ6").Resize(i - 1).Value = Arr
End With
End Sub
với 2 vòng for như thế này thì tốc độ có bị chậm khi dữ liệu lớn không?
 
Upvote 0
với 2 vòng for như thế này thì tốc độ có bị chậm khi dữ liệu lớn không?
Thì bạn cứ thí nghiệm đi sẽ có ngay câu trả lời, cần gì hỏi
Nếu như dùng mảng mà vẫn chậm thì:
- Xem lại cấu trúc dữ liệu ---> Suy nghĩ liệu có cần phải bố trí lại cho hợp lý hơn không?
- Xem lại giải thuật của code ---> Suy nghĩ xem phương án mà ta đang dùng trong code liệu đã tối ưu chưa?
2 cái này rất quan trọng đấy
 
Upvote 0
Anh NDU xem giúp em lỗi này với. Tại cột C em có công thức=IF(N65=N64,C64,IF(T65<>0,"PT_"&RIGHT("000"&T65,4),IF(U65<>0,"PC_"&RIGHT("000"&U65,4),"CK_"&RIGHT("000"&V65,4)))) và em đổi sang dùng code cho cột C này như sau:
PHP:
Sub soct()
Dim i As Long, j As Long, tmp1 As String, tmp2 As String, sArray, Arr()
With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[AG65536].End(xlUp))
    tmp1 = CStr(.Range("P5").Value)
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
    If (CStr(sArray(i, 6)) = "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "PT_" & Right("0000" & sArray(i, 20), 4)
        End If
    ElseIf (CStr(sArray(i, 7)) = "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "PC_" & Right("0000" & sArray(i, 21), 4)
        End If
    ElseIf (CStr(sArray(i, 6)) <> "1111") And (CStr(sArray(i, 7)) <> "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "CK_" & Right("0000" & sArray(i, 22), 4)
        End If
    End If
    tmp1 = sArray(i, 16)
    Next
    .Range("C6").Resize(i - 1).Value = Arr
End With
End Sub
khi chạy code này thì em phải chạy code 3 lần thì nó mới ra kết quả (click vào nút command button 3 hoặc 4 lần) code em sai chỗ nào vậy anh.
 

File đính kèm

Upvote 0
Anh NDU xem giúp em lỗi này với. Tại cột C em có công thức=IF(N65=N64,C64,IF(T65<>0,"PT_"&RIGHT("000"&T65,4),IF(U65<>0,"PC_"&RIGHT("000"&U65,4),"CK_"&RIGHT("000"&V65,4)))) và em đổi sang dùng code cho cột C này như sau:
PHP:
Sub soct()
Dim i As Long, j As Long, tmp1 As String, tmp2 As String, sArray, Arr()
With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[AG65536].End(xlUp))
    tmp1 = CStr(.Range("P5").Value)
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
    If (CStr(sArray(i, 6)) = "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "PT_" & Right("0000" & sArray(i, 20), 4)
        End If
    ElseIf (CStr(sArray(i, 7)) = "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "PC_" & Right("0000" & sArray(i, 21), 4)
        End If
    ElseIf (CStr(sArray(i, 6)) <> "1111") And (CStr(sArray(i, 7)) <> "1111") Then
        If sArray(i, 16) <> "" And CStr(sArray(i, 16)) = tmp1 Then
            j = i - 1
            Arr(i, 1) = sArray(j, 3)
        ElseIf sArray(i, 16) <> "" And CStr(sArray(i, 16)) <> tmp1 Then
            Arr(i, 1) = "CK_" & Right("0000" & sArray(i, 22), 4)
        End If
    End If
    tmp1 = sArray(i, 16)
    Next
    .Range("C6").Resize(i - 1).Value = Arr
End With
End Sub
khi chạy code này thì em phải chạy code 3 lần thì nó mới ra kết quả (click vào nút command button 3 hoặc 4 lần) code em sai chỗ nào vậy anh.
Theo công thức màu đỏ cho ở trên thì code phải vầy mới đúng
PHP:
Sub soct()
  Dim i As Long, j As Long, tmp1 As String, tmp2 As String, sArray, Arr()
  With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[A65536].End(xlUp)).Resize(, 22).Value
    tmp1 = CStr(.Range("N5").Value)
    tmp2 = CStr(.Range("C5").Value)
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
      If CStr(sArray(i, 14)) = tmp1 Then
        Arr(i, 1) = tmp2
      ElseIf CStr(sArray(i, 20)) <> "" Then
        Arr(i, 1) = "PT_" & Right("0000" & sArray(i, 20), 4)
      ElseIf sArray(i, 21) <> "" Then
        Arr(i, 1) = "PC_" & Right("0000" & sArray(i, 21), 4)
      Else
        Arr(i, 1) = "CK_" & Right("0000" & sArray(i, 22), 4)
      End If
      tmp1 = CStr(sArray(i, 14))
      tmp2 = CStr(sArray(i, 3))
    Next
    .Range("C6").Resize(i - 1).Value = Arr
  End With
End Sub
Code này dùng để đánh STT cho cột C
 
Lần chỉnh sửa cuối:
Upvote 0
Theo công thức màu đỏ cho ở trên thì code phải vầy mới đúng
PHP:
Sub soct()
  Dim i As Long, j As Long, tmp1 As String, tmp2 As String, sArray, Arr()
  With Sheets("Phat sinh")
    sArray = .Range(.[A6], .[A65536].End(xlUp)).Resize(, 22).Value
    tmp1 = CStr(.Range("N5").Value)
    tmp2 = CStr(.Range("C5").Value)
    ReDim Arr(1 To UBound(sArray, 1), 1 To 1)
    For i = 1 To UBound(sArray, 1)
      If CStr(sArray(i, 14)) = tmp1 Then
        Arr(i, 1) = tmp2
      ElseIf CStr(sArray(i, 20)) <> "" Then
        Arr(i, 1) = "PT_" & Right("0000" & sArray(i, 20), 4)
      ElseIf sArray(i, 21) <> "" Then
        Arr(i, 1) = "PC_" & Right("0000" & sArray(i, 21), 4)
      Else
        Arr(i, 1) = "CK_" & Right("0000" & sArray(i, 22), 4)
      End If
      tmp1 = CStr(sArray(i, 14))
      tmp2 = CStr(sArray(i, 3))
    Next
    .Range("C6").Resize(i - 1).Value = Arr
  End With
End Sub
Anh ơi, em vẫn không hiểu tại sao chạy code này vẫn phải chạy code nhiều lần thì mới điền hết số chứng từ vào cột C. Có cách nào điền hết số chứng từ vào cột C chỉ với 1 lần chạy code không anh.
 
Upvote 0
Anh ơi, em vẫn không hiểu tại sao chạy code này vẫn phải chạy code nhiều lần thì mới điền hết số chứng từ vào cột C. Có cách nào điền hết số chứng từ vào cột C chỉ với 1 lần chạy code không anh.
Tôi sơ ý!
Bạn sửa chổ này:
tmp2 = CStr(sArray(i, 3))
thành:
tmp2 = CStr(Arr(i, 1))
thử lại nhé
 
Upvote 0
hay quá. code chạy được rồi /-*+/. cám ơn anh NDU nhìu nhìu
 
Upvote 0
Em thay code này:
PHP:
sArray = .Range(.[A6], .[A65536].End(xlUp)).Resize(, 22).Value
bằng code:
PHP:
sArray = .Range(.[A6], .[V65536].End(xlUp))
2 kiểu này là giống nhau đúng không anh NDU.-+*/
 
Upvote 0
Sẽ giống, chỉ khi dòng cuối có dữ liệu của cột 'A' trùng với dòng cuối có dữ liệu của cột 'V'
 
Upvote 0
PHP:
Sub Thang()
Dim i As Long, arr(), sArray
With Sheets("Phat sinh")
    .Range("AF6:AF65536").ClearContents
    sArray = .Range(.[C6], .[D65536].End(xlUp))
    ReDim arr(1 To UBound(sArray, 1), 1 To 1) 
    For i = 1 To UBound(sArray, 1)
        If Not IsEmpty(sArray(i, 2)) Then
            arr(i, 1) = Month(sArray(i, 2))
        Else
            .Range("D" & (i + 5)).Select
            MsgBox "Vui long nhap vao ngay chung tu tai o D" & (i + 5), vbYesNo, "Thong bao"    
        End If
    Next
.Range("AF6").Resize(i, 1).Value = arr
End With
End Sub
Khi chạy code này tại sao ô cuối cùng trong cột D khi giá trị rỗng thì code thỏa điều kiện nhưng ko nhảy ra thông báo nhập ngày chứng từ cho ô này và kết quả ở ô cuối cột AF luôn hiện giá trị #N/A. Ai giúp mình lỗi này với.
 

File đính kèm

Upvote 0
PHP:
Sub Thang()
Dim i As Long, arr(), sArray
With Sheets("Phat sinh")
    .Range("AF6:AF65536").ClearContents
    sArray = .Range(.[C6], .[D65536].End(xlUp))
    ReDim arr(1 To UBound(sArray, 1), 1 To 1) 
    For i = 1 To UBound(sArray, 1)
        If Not IsEmpty(sArray(i, 2)) Then
            arr(i, 1) = Month(sArray(i, 2))
        Else
            .Range("D" & (i + 5)).Select
            MsgBox "Vui long nhap vao ngay chung tu tai o D" & (i + 5), vbYesNo, "Thong bao"    
        End If
    Next
.Range("AF6").Resize(i, 1).Value = arr
End With
End Sub
Khi chạy code này tại sao ô cuối cùng trong cột D khi giá trị rỗng thì code thỏa điều kiện nhưng ko nhảy ra thông báo nhập ngày chứng từ cho ô này và kết quả ở ô cuối cột AF luôn hiện giá trị #N/A. Ai giúp mình lỗi này với.
Khi chạy code này tại sao ô cuối cùng trong cột D khi giá trị rỗng thì code thỏa điều kiện nhưng ko nhảy ra thông báo nhập ngày chứng từ cho ô này ?
Code chạy đúng, bạn khai báo:
Câu 1
sArray = .Range(.[C6], .[D65536].End(xlUp))
Cell cuối cùng có dữ liệu ở cột D là cell [D62] chứ không phải cell [D63]
Nếu cột C luôn chứa đủ dữ liệu bạn khai báo lại:
sArray = .Range(.[C6], .[C65536].End(xlUp)).Resize(, 2)
Câu 2
kết quả ở ô cuối cột AF luôn hiện giá trị #N/A.
Bạn khai báo:
For i = 1 To UBound(sArray, 1)
Trong code bạn sử dụng vòng lặp For.....Next ==> khi chạy hết vòng lặp biến i luôn luôn lớn hơn UBound(sArray, 1) một bước nhảy (ở code này là 1)
.Range("AF6").Resize(i, 1).Value = arr
Số phần tử gán cho vùng từ [AF6] trở xuống i dòng, nhiều hơn số phần tử của mảng Arr là 1 nên cell cuối cùng báo lỗi:
Bạn khai báo lại:
.Range("AF6").Resize(UBound(sArray)).Value = Arr
Hoặc trong khai báo của bạn thì thế này cũng được
.Range("AF6").Resize(i-1, 1).Value = arr
Thân
 
Upvote 0

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

Back
Top Bottom