Chuyên đề giải đáp những thắc mắc về code VBA (1 người xem)

Liên hệ QC

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

maytinhvp01

Thành viên thường trực
Tham gia
27/7/13
Bài viết
390
Được thích
179
Mình muốn nhờ giải thich câu lệnh " If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c) "
trong ví du:
Public Function LonNhat(Ran As Range)
Dim max As Double, v As Integer, d As Integer, c As Integer
max = Ran.Cells(1, 1)
For d = 1 To Ran.Rows.Count
For c = 1 To Ran.Columns.Count
If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c)
Next c
Next d
v = Tim(max, Ran)
LonNhat = max
End Function
-------------------------------------------------------
[INFO1]Thông báo:
Vì topic này:
http://www.giaiphapexcel.com/forum/...ải-thích-các-code-đề-nghị-các-bạn-gửi-vào-đây
đã quá dài nên BQT đóng lại.
Nay tôi mở topic mới với cùng chủ đề: GIẢI THÍCH NHỮNG THẮC MẮC VỀ CODE
Các bạn nếu có nhu cầu giải thích code, vui lòng post tại đây nhé
NDU96081631

[/INFO1]
 
Chỉnh sửa lần cuối bởi điều hành viên:
Anh Chị cho em hỏi! khi xuất hiện msgbox thông báo phải tắt đi thì mới kích chuột được ra vùng khác phải làm như nào. Em xin cảm ơn
 
Upvote 0
Cho em hỏi có code nào bắt được sự kiện enter không?
Em muốn nếu khi em enter ở sheet chỉ định thì nó sẽ thực hiện một lệnh nào đó
Em tìm được code này trên mạng nhưng chưa làm cho nó chạy được (Em gán trực tiếp code này vào sheet)
PHP:
Private Sub BatsuKien()
    Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Sub MyEnterEvent()
    Cells(RDB_Last(1, [B:B]), 2).Select
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi có code nào bắt được sự kiện enter không?
Em muốn nếu khi em enter ở sheet chỉ định thì nó sẽ thực hiện một lệnh nào đó
Em tìm được code này trên mạng nhưng chưa làm cho nó chạy được (Em gán trực tiếp code này vào sheet)
PHP:
Private Sub BatsuKien()
    Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Sub MyEnterEvent()
    Cells(RDB_Last(1, [B:B]), 2).Select
End Sub
Thử dùng lệnh batsukien trong sub auto_open xem sao.
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi có code nào bắt được sự kiện enter không?
Em muốn nếu khi em enter ở sheet chỉ định thì nó sẽ thực hiện một lệnh nào đó
Em tìm được code này trên mạng nhưng chưa làm cho nó chạy được (Em gán trực tiếp code này vào sheet)
PHP:
Private Sub BatsuKien()
    Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Sub MyEnterEvent()
    Cells(RDB_Last(1, [B:B]), 2).Select
End Sub
Sao bạn không đọc Help nhỉ? Bởi nếu có đọc thì sẽ biết:
- Phím Enter trên bàn phím số được ghi là "{ENTER}"
- Phím Enter thường được ghi là "~"
Vậy bạn đang cần cái Enter nào?
Ngoài ra, muốn code chạy khi gõ bàn phím thì đương nhiên phải kích hoạt nó trước. Cụ thể để code của bạn hoạt động thì phải chạy Sub BatsuKien trước, sau đó gõ phím rồi Enter mới có tác dụng
 
Upvote 0
Sao bạn không đọc Help nhỉ? Bởi nếu có đọc thì sẽ biết:
- Phím Enter trên bàn phím số được ghi là "{ENTER}"
- Phím Enter thường được ghi là "~"
Vậy bạn đang cần cái Enter nào?
Ngoài ra, muốn code chạy khi gõ bàn phím thì đương nhiên phải kích hoạt nó trước. Cụ thể để code của bạn hoạt động thì phải chạy Sub BatsuKien trước, sau đó gõ phím rồi Enter mới có tác dụng

Em có đọc về hai phím enter như thầy bảo và em chọn bắt sự kiện enter trên bàn phím số.
Em muốn khi em enter bàn phím số thì Sub MyEnterEvent sẽ chạy.
Cụ thể khi em enter thì em muốn nó sẽ tự động chuyển xuống dòng cuối cùng của cột B tại sheet mà em gán code.
 
Lần chỉnh sửa cuối:
Upvote 0
Em có đọc về hai phím enter như thầy bảo và em chọn bắt sự kiện enter trên bàn phím số.
Em muốn khi em enter bàn phím số thì Sub MyEnterEvent sẽ chạy.
Cụ thể khi em enter thì em muốn nó sẽ tự động chuyển xuống dòng cuối cùng của cột B tại sheet mà em gán code.
Xem thử đúng yêu cầu chưa.
 

File đính kèm

Upvote 0
Xem thử đúng yêu cầu chưa.
Đúng ý mình rồi, cảm ơn bạn nhé :)

Cho mình hỏi đoạn này có tác dụng gì mà xóa đi vẫn thấy chạy
PHP:
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = "GPE" Then Application.OnKey "{ENTER}", ""
End Sub

À có một điều là khi tải file về mình phải chuyển sang sheet khác để Enter rồi quay lại sheet GPE mới có tác dụng. Vì sao vậy nhỉ bạn?
 
Lần chỉnh sửa cuối:
Upvote 0
Cho mình hỏi đoạn này có tác dụng gì mà xóa đi vẫn thấy chạy
PHP:
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = "GPE" Then Application.OnKey "{ENTER}", ""
End Sub
Bạn thử xóa nó và chọn qua sheet1, sheet2 và nhấn Enter thử xem.
À có một điều là khi tải file về mình phải chuyển sang sheet khác để Enter rồi quay lại sheet GPE mới có tác dụng. Vì sao vậy nhỉ bạn?
Bạn thêm đoạn code này vào ThisWorkbook thử xem.
Mã:
Private Sub Workbook_Open()
    If ActiveSheet.Name = "GPE" Then Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Cụ thể code trong ThisWorkbook sẽ là.
Mã:
Private Sub Workbook_Open()
    If ActiveSheet.Name = "GPE" Then Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
     If Sh.Name = "GPE" Then Application.OnKey "{ENTER}", "MyEnterEvent"
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    If Sh.Name = "GPE" Then Application.OnKey "{ENTER}", ""
End Sub
 
Upvote 0
Cho em hỏi hai cái này thì có gì khác nhau?
Tem = arr(i,1)
1. Dic.Add Tem, i
2. Dic.Item(Tem) = i

Em có đọc trong bài Tổng quan về Scripting Ditionary thì có đoạn code sau
PHP:
With MyDictionary
         .Add 1, "number"
         .Item("1") = "text"
End With

Như vậy về bản chất cái Tem trong 1 và 2 của em nó đều là key còn i là item có phải không?
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi hai cái này thì có gì khác nhau?
Tem = arr(i,1)
1. Dic.Add Tem, i
2. Dic.Item(Tem) = i
...

Khác nhau:
trường hợp 1, sẽ ghi thêm một cặp key-item với key là Tem và item là i. Vì vậy nếu đã có Tem sẵn rồi thì sẽ bị lỗi.
trường hợp 2, sẽ lôi cặp key-item với key là Tem ra và sửa item nó thành i. Nếu chưa có Tem thì tự thêm vào. Nếu đã có sẵn Tem thì item trước đó sẽ bị ghi chồng.
(chú: nhiều ngừoi ở diễn đàn này có thói quen dùng từ Tem để đặt tên cho biến. Theo lệ chung của lập trình thì tem, tmp temp chỉ nên dùng cho biến có giá trj tạm. Dùng để đặt tên key là lạm dụng)

Dictionary, theo định nghĩa là một tập hợp của những phát sinh, mỗi phát sinh là một cặp key-item.
 
Upvote 0
Phiếm bàn về "Tem":
Tôi đoán là khi viết code, ngừoi ta muốn nói đến từ "temporary" (tạm thời) trong tiếng Anh. Chứ thực sự, trong ngữ cảnh những đoạn code được dùng ở diễn đàn này thì Têm (trầu?) hay Tem (thư?) chả có nghĩa lý gì cả.
Với tên gọi (từ ngữ lập trình là identifier) "tem", người lập trình viên căn bản chỉ dùng cho biến có mục đích tạm, nó không nhất thiết phải mang ý nghĩa hay chỉ vào cái gì. Trường hợp điển hình là code hoán chuyển trị
tem = a: a = b: b = tem ' đoạn code hoán chuyển trị a và b
tem đáp ứng điều kiện thứ nhất: mục đích tạm; và điều kiện thứ hai: nó làm nhiệm vụ trung gian giữa a b mà không cần biết a và b là cái gì.
Cái "mục đích tạm" nó cần được diễn giải thêm rằng thường thì người đọc code tự động hiểu rằng cái tầm vực của trị này không đi xa quá 3 dòng.

Dùng tem cho trường hợp chung chung khác có thể gây hiểu lầm cho người không quen đọc code của mình.
Trên thực tế tem, tm, tmp, temp còn có thể là từ tắt của temperature.
 
Upvote 0
Chào mọi người.
Mình có file như này, muốn làm Macro Filter nhưng chỉ áp dụng được khi dùng Filter chữ,
Còn filter số trong file thì lại ra kết quả Blank.
Ví dụ Filter cột 2 (chữ) ra kết quả, nhưng cột 4 thì không.
 

File đính kèm

  • Testing.rar
    Testing.rar
    385 bytes · Đọc: 5
  • Filter 2.PNG
    Filter 2.PNG
    79.2 KB · Đọc: 4
  • Filter 4.PNG
    Filter 4.PNG
    50.7 KB · Đọc: 4
Upvote 0
Chào mọi người.
Mình có file như này, muốn làm Macro Filter nhưng chỉ áp dụng được khi dùng Filter chữ,
Còn filter số trong file thì lại ra kết quả Blank.
Ví dụ Filter cột 2 (chữ) ra kết quả, nhưng cột 4 thì không.
Nếu ý bạn muốn lọc những ô không rỗng thì Criteria1:="<>"

Chú ý: tôi chỉ đưa Criteria1:="<>", tức sau đoạn đó không còn gì đâu nhé. Tức chỉ có chân không thôi. Đừng sáng tạo thêm
 
Lần chỉnh sửa cuối:
Upvote 0
Chào mọi người.
Mình có file như này, muốn làm Macro Filter nhưng chỉ áp dụng được khi dùng Filter chữ,
Còn filter số trong file thì lại ra kết quả Blank.
Ví dụ Filter cột 2 (chữ) ra kết quả, nhưng cột 4 thì không.
Bạn viết code thế nào mà không được? Đưa file, đưa luôn code lên cho người ta biết chứ
Mà file csv thì làm gì có code trong đó?
 
Upvote 0
Bạn viết code thế nào mà không được? Đưa file, đưa luôn code lên cho người ta biết chứ
Mà file csv thì làm gì có code trong đó?
Ui chít quên, mình xin lỗi,
Code đây ạ

Mã:
    Sub test()

    Workbooks("testing.csv").Activate
    ActiveSheet.Range("$A:$I").AutoFilter Field:=4, Criteria1:="=*" & InputBox("Filter ") & "*"
    
    End Sub
Bài đã được tự động gộp:

Bạn xem bài #28, tại đây
Link

Đã giải quyết xong ạ.
Cảm ơn bạn nhiều :)
 
Upvote 0
Em có sub này. sub này là xét theo ngày trước xét với ngày sau.
Giờ em muốn nó xét theo 7 ngày thì sửa ở đoạn nào vậy.
Mong các Bác chỉ bảo giúp em ạ
Sub XuLy()
Dim dat1 As Date, dat2 As Date, lr As Long, arr As Variant, tmp As String, TongTam As Byte
Dim i As Long, j As Integer, m As Byte, N As Byte, kq(), kq2(), d As Integer, s As Integer
Dim bd As Long, kt As Long, ViTriCuoi As String
Dim i1 As Long, i2 As Long
dat1 = Sheet5.Range("F7").Value
dat2 = Sheet5.Range("H7").Value
Sheet7.Range("B2:C100000").ClearContents
With Sheet1
lr = .Range("B65000").End(3).Row
arr = .Range("B2:AC" & lr).Value

For i = 1 To UBound(arr)
If bd = 0 Then
If arr(i, 1) >= dat1 Then
bd = i
End If
End If
If kt = 0 Then
If arr(i, 1) >= dat2 Then
kt = i - 1
End If
End If
If bd > 0 And kt > 0 Then Exit For
Next i

If bd = 0 Or kt = 0 Then
MsgBox "Ngay Nhap Khong Hop Le"
Exit Sub
End If
ReDim kq(1 To 5672, 1 To kt - bd + 2)
For i = bd To kt
i2 = i2 + 1
i1 = 1
tmp = ""
tmp2 = ""
kq(1, i2) = arr(i, 1)
For j = 1 To 27
tmp = tmp & arr(i, j + 1)
tmp2 = tmp2 & arr(i + 1, j + 1)
Next j

For m = 1 To 106
For N = m + 1 To 107

i1 = i1 + 1
TongTam = Mid(arr(i + 1, 2), 4, 1)
ViTriCuoi = Mid(tmp2, m, 1) & "," & Mid(tmp2, N, 1)
If InStr(1, TongTam, Mid(tmp, m, 1)) > 0 Or InStr(1, TongTam, Mid(tmp, N, 1)) > 0 Then
kq(i1, i2) = 1
Else
kq(i1, i2) = 2
End If
If i = kt Then
kq(i1, i2 + 1) = ViTriCuoi
End If

Next N
Next m
Next i
End With
With Sheet12
.Range("E2").Resize(5672, 1000).ClearContents
.Range("E2").Resize(5672, kt - bd + 2).Value = kq
.Range("E2").Resize(5672, kt - bd + 2).EntireColumn.AutoFit
ReDim kq2(1 To 5671, 1 To 2)
For i = 1 To 5671
d = 0: s = 0
For j = 1 To kt - bd + 1
If kq(i + 1, j) = 1 Then
d = d + 1
Else
s = s + 1
End If
Next j
kq2(i, 1) = d
kq2(i, 2) = s
Next i
.Range("C3").Resize(5671, 2).Value = kq2
.Range("A2").Resize(5672, kt - bd + 5).Copy Sheet7.Range("B2")
.Range("D3").Offset(0, kt - bd + 2).Resize(5671, 1).Copy Sheet7.Range("AAA3")
End With
With Sheet7
.Range("F2:ZZ2").NumberFormat = "dd"
.Range("B3:AAA5673").Sort .Range("D3"), xlDescending
.Range("F1:ZZ1").EntireColumn.Hidden = False
.Range(.Cells(1, kt - bd + 1 + 6), .Cells(1, 702)).EntireColumn.Hidden = True
.Range("AAA2").Value = Sheet3.Range("D9").Value
.Select
End With
End Sub
 
Upvote 0
Em đang có một vấn đề nhờ các anh viết code giúp em ạ em nghĩ mãi không ra.
Em có một cột G ( là cột chênh lệch) khoảng 2K dòng . Nếu không lệch thì sẽ là 0 và nếu lệch sẽ là <> 0
Bây giờ em muốn viết một buttun để khi nhấp vào sẽ go to những ô lớn hơn hoặc nhỏ hơn 0 lần lượt từ trên xuống dưới
Ví dụ Ô G10 , G100 , G500 đang khác 0, thì khi click vào button đó sẽ lần lượt nhảy tới ô G10 , click lần 2 vào button đó sẽ tớ ô G100 , click lần 3 sẽ tới Ô G500 , Lần 4 sẽ Quay lại Ô G10. Nếu không có ô nào <> 0 sẽ hiện msgbox ( cân bằng)

Em cám ơn ạ
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi khai báo Sub thế nào để nó chỉ chạy trong file chứa nó?
 
Upvote 0
Cho em hỏi khai báo Sub thế nào để nó chỉ chạy trong file chứa nó?
Thêm phần WorkBooks vào, ví dụ:
Thay vì viết:
PHP:
Dim lr&
    lr = Sheets(1).Range("B" & Rows.Count).End(3).Row
Thì viết:

PHP:
Dim lr&
    lr = Workbooks("abcd.xlsm").Sheets(1).Range("B" & Rows.Count).End(3).Row

Trong đó abcd là WorkBook ta cần tác động.
 
Upvote 0
Thêm phần WorkBooks vào, ví dụ:
Thay vì viết:
PHP:
Dim lr&
    lr = Sheets(1).Range("B" & Rows.Count).End(3).Row
Thì viết:

PHP:
Dim lr&
    lr = Workbooks("abcd.xlsm").Sheets(1).Range("B" & Rows.Count).End(3).Row

Trong đó abcd là WorkBook ta cần tác động.
Chỉ có cách này thôi à bạn. Vì Mình xây dựng form và gửi cho nhiều người. Họ sẽ đặt tên theo quy định của mình (Ví dụ là tên bộ phận) như vậy để mà gửi cho 10 người mình phải làm 10 cái form với code khác nhau.
 
Upvote 0
Chỉ có cách này thôi à bạn. Vì Mình xây dựng form và gửi cho nhiều người. Họ sẽ đặt tên theo quy định của mình (Ví dụ là tên bộ phận) như vậy để mà gửi cho 10 người mình phải làm 10 cái form với code khác nhau.
Vậy thì đặt tên WB bằng một biến đi,
ví dụ:

Mã:
vName = ThisWorkbook.Name
lr = Workbooks(vName).Sheets(1).Range("B" & Rows.Count).End(3).Row
 
Upvote 0
Vậy thì đặt tên WB bằng một biến đi,
ví dụ:

Mã:
vName = ThisWorkbook.Name
lr = Workbooks(vName).Sheets(1).Range("B" & Rows.Count).End(3).Row
Cảm ơn bạn! Như vậy ngoài những thủ thuật này thì không cách nào khác để cho code đó chỉ có tác dụng cho file chứa nó. Ngày xưa cứ nghĩ khai báo Private là nó chỉ chạy trên file đó còn Public là toàn bộ :D
 
Upvote 0
Cảm ơn bạn! Như vậy ngoài những thủ thuật này thì không cách nào khác để cho code đó chỉ có tác dụng cho file chứa nó. Ngày xưa cứ nghĩ khai báo Private là nó chỉ chạy trên file đó còn Public là toàn bộ :D
Cách viết tắt (Không thêm Workbooks) chỉ phù hợp khi bạn làm việc trên một WB. còn nếu bạn phải thường xuyên làm việc trên nhiều WB mình vẫn khuyên nên viết đầy đủ theo thứ tự: WB-WS-Range/Cell
 
Upvote 0
Bài #1476:
. Có phải làm (khai báo) gì đâu nhỉ? Phải hỏi lại gọi Sub bằng cách nào?
.. Biết thành viên này hay hỏi lòng vòng, sao không nêu luôn cái đang làm lên cho cụ thể vấn đề.
 
Upvote 0
Cách viết tắt (Không thêm Workbooks) chỉ phù hợp khi bạn làm việc trên một WB. còn nếu bạn phải thường xuyên làm việc trên nhiều WB mình vẫn khuyên nên viết đầy đủ theo thứ tự: WB-WS-Range/Cell
Ừm, cảm ơn bạn nhé!
Bài đã được tự động gộp:

Bài #1476:
. Có phải làm (khai báo) gì đâu nhỉ? Phải hỏi lại gọi Sub bằng cách nào?
.. Biết thành viên này hay hỏi lòng vòng, sao không nêu luôn cái đang làm lên cho cụ thể vấn đề.
Cảm ơn Befaint!
 
Upvote 0
K/G các anh chị, em có 1 file exel đính kèm cần dùng VBA để thực hiện ý tưởng gán nút thêm dòng và bớt dòng sao cho:
Khi muốn thêm 1 dòng để nhập dữ liệu thì người dùng nhấp vào biểu tượng thêm dòng, excel tự động thêm một dòng và nhảy các công thức liên quan. Tưng tự khi người dùng muốn xóa 1 dòng. Em chưa biết gì về VBA mong các anh chị viết giúp ạ, e cảm ơn rất nhiều.
 

File đính kèm

Upvote 0
K/G các anh chị, em có 1 file exel đính kèm cần dùng VBA để thực hiện ý tưởng gán nút thêm dòng và bớt dòng sao cho:
Khi muốn thêm 1 dòng để nhập dữ liệu thì người dùng nhấp vào biểu tượng thêm dòng, excel tự động thêm một dòng và nhảy các công thức liên quan. Tưng tự khi người dùng muốn xóa 1 dòng. Em chưa biết gì về VBA mong các anh chị viết giúp ạ, e cảm ơn rất nhiều.
Dùng định dạng Table là được.
Chọn vùng dữ liệu, nhấn Ctrl + T, nhấn Enter. Vậy thôi.
 
Upvote 0
Em mới mò mẫm VBA có thắc mắc như sau, nhờ các anh chị chỉ giúp ạ:

Em muốn thêm một Cell chứa công thức bằng VBA

Công thức đó phải thỏa mãn:

Chứa 1 chuối text tiếng việt + một hàm tương ứng:

Ví dụ:
Tại ô A1 sẽ hiện lên hàm ="Số thứ tự là "&counta(B1:B5)

Em xin cảm ơn
 
Upvote 0
Em mới mò mẫm VBA có thắc mắc như sau, nhờ các anh chị chỉ giúp ạ:

Em muốn thêm một Cell chứa công thức bằng VBA

Công thức đó phải thỏa mãn:

Chứa 1 chuối text tiếng việt + một hàm tương ứng:

Ví dụ:
Tại ô A1 sẽ hiện lên hàm ="Số thứ tự là "&counta(B1:B5)

Em xin cảm ơn
Cái này mình Record Macro cũng sinh ra code cho bạn mà. Khi Record Macro thì những từ mình gõ tiếng việt Unicode sẽ không ghi lại được, vì vậy nó sẽ là những dấu "?". Bạn phải thay những dấu "?" này thành hàm chuyển mã phù hợp. Bạn tham khảo đoạn code dưới.
Mã:
Sub GPE()
    Range("A1").FormulaR1C1 = "=""S" & ChrW(7889) & " th" & ChrW(7913) & " t" & ChrW(7921) & " là ""&COUNTA(RC[1]:R[4]C[1])"
End Sub
 
Upvote 0
Cái này mình Record Macro cũng sinh ra code cho bạn mà. Khi Record Macro thì những từ mình gõ tiếng việt Unicode sẽ không ghi lại được, vì vậy nó sẽ là những dấu "?". Bạn phải thay những dấu "?" này thành hàm chuyển mã phù hợp. Bạn tham khảo đoạn code dưới.
Mã:
Sub GPE()
    Range("A1").FormulaR1C1 = "=""S" & ChrW(7889) & " th" & ChrW(7913) & " t" & ChrW(7921) & " là ""&COUNTA(RC[1]:R[4]C[1])"
End Sub
Em cảm ơn:
Hiện tại em đang copy code của 1 bác trong giải pháp excel.
Trong đó em gán được cho biến Text = UniVBAT("Soos thuws tuwj laf") với ý nghĩa biến Text sẽ gắn với chữ "số thứ tự là", Vậy nếu em đưa biến text này vào code thì làm thế nào ạ
 
Upvote 0
Thì đưa theo cách... bình thương đi. Có vấn đề gì chứ?
Tại vì nhiều lúc em muốn đoạn text dài và sử dụng text đó nhiều lần ạ.
Thực sự là chuyên gia trong diễn đàn GPE đã nói vậy tức là em hết cách rồi. Em cám ơn bác rất nhiều ạ
Bài đã được tự động gộp:

Thì đưa theo cách... bình thương đi. Có vấn đề gì chứ?
Em đã giải quyết được vẫn đề, tại mới tiếp xúc với VBA nên còn chưa thuận. Cám ơn bác rất nhiều em đã đọc rất nhiều hướng dẫn của bác trên diễn đàn GPE, rất hữu ích và dễ hiểu. Chúc bác luôn khỏe và tiếp tục hướng dẫn mọi người
 
Lần chỉnh sửa cuối:
Upvote 0
Các anh/chị cho em hỏi chút: lúc em copy 1 sheet tạo thành file mới hoặc trong Vba em để code : sheet1.copy thì lại báo lỗi. Cách sửa là như thế nào ạ
 
Upvote 0
Các anh/chị cho em hỏi chút: lúc em copy 1 sheet tạo thành file mới hoặc trong Vba em để code : sheet1.copy thì lại báo lỗi. Cách sửa là như thế nào ạ
Vấn đề là trong file của bạn có cái sheet nào là sheet1 hay không? Cái chổ màu đỏ là NameCode nhé.
 
Upvote 0
Vấn đề là trong file của bạn có cái sheet nào là sheet1 hay không? Cái chổ màu đỏ là NameCode nhé.
Có bạn ạ. Code vba của mình lấy đúng sheet cần copy rồi. Và mình thực hiện bằng chuột đơn thuần cũng ko copy được sheet cần copy thành file mới
 
Upvote 0
Với dữ liệu excel hơn 45.000 dòng, khi em sử dụng code sau thời gian chờ code chạy xong lâu quá! Mong các sư phụ chỉ giúp cách xử lý sao cho thời gian nhanh sớm hơn ah! Em cũng đã search rồi nhưng vẫn chưa thấy code nào tối ưu hơn ah.
Sub Code_TonThoiGian()
Dim tg As Double
tg = Timer

'Voi hon 45.000 dong, thoi gian lau qua
Sheets("DuLieu").Select
SoDongDuLieu = Range("A1").End(xlDown).Row

Dim j As Long
For j = 1 To SoDongDuLieu
If Range("A" & j).Value Like "05" Then
Range("B" & j).Value = "PGD05"
End If
If Range("A" & j).Value Like "00" Then
Range("B" & j).Value = "HoiSo"
End If
If Range("A" & j).Value Like "03" Then
Range("B" & j).Value = "PGD03"
End If
If Range("A" & j).Value Like "04" Then
Range("B" & j).Value = "PGD04"
End If
If Range("A" & j).Value Like "07" Then
Range("B" & j).Value = "PGD07"
End If
If Range("A" & j).Value Like "09" Then
Range("B" & j).Value = "PGD09"
End If
If Range("A" & j).Value Like "10" Then
Range("B" & j).Value = "PGD10"
End If
If Range("A" & j).Value Like " " Then
Range("A" & j).Value = "KoPhongBan"
Range("B" & j).Value = "KoPhongBan"
End If
If Range("C" & j).Value = "" Then
Range("C" & j).Value = "KoMaNhanSu"
End If
If Range("D" & j).Value = "" Then
Range("D" & j).Value = "KoTenTuoi"
End If
Next

tg = Timer - tg
MsgBox tg & " done."
End Sub
 
Upvote 0
Thử xem:
Mã:
Sub Code_TonThoiGian_sua()
    Dim tg As Double, arr()
    tg = Timer

    Sheets("DuLieu").Select
    SoDongDuLieu = Range("A1").End(xlDown).Row
    Dim j As Long

    arr = Range("A1:D" & SoDongDuLieu)
    For j = 1 To UBound(arr, 1)
        If InStr(1, arr(j, 1), "05", vbTextCompare) > 0 Then arr(j, 2) = "PGD05"
        If InStr(1, arr(j, 1), "00", vbTextCompare) > 0 Then arr(j, 2) = "HoiSo"
        If InStr(1, arr(j, 1), "03", vbTextCompare) > 0 Then arr(j, 2) = "PGD03"
        If InStr(1, arr(j, 1), "04", vbTextCompare) > 0 Then arr(j, 2) = "PGD04"
        If InStr(1, arr(j, 1), "07", vbTextCompare) > 0 Then arr(j, 2) = "PGD07"
        If InStr(1, arr(j, 1), "09", vbTextCompare) > 0 Then arr(j, 2) = "PGD09"
        If InStr(1, arr(j, 1), "10", vbTextCompare) > 0 Then arr(j, 2) = "PGD10"
        If Trim(arr(j, 1)) = "" Then
            arr(j, 1) = "KoPhongBan"
            arr(j, 2) = arr(j, 1)
        End If
        If Trim(arr(j, 3)) = "" Then arr(j, 3) = "KoMaNhanSu"
        If Trim(arr(j, 4)) = "" Then arr(j, 4) = "KoTenTuoi"
    Next
    Range("A1:D" & SoDongDuLieu).Value = arr

    tg = Timer - tg
    MsgBox tg & " done."
End Sub
 
Upvote 0
Thử xem:
Mã:
Sub Code_TonThoiGian_sua()
    Dim tg As Double, arr()
    tg = Timer

    Sheets("DuLieu").Select
    SoDongDuLieu = Range("A1").End(xlDown).Row
    Dim j As Long

    arr = Range("A1:D" & SoDongDuLieu)
    For j = 1 To UBound(arr, 1)
        If InStr(1, arr(j, 1), "05", vbTextCompare) > 0 Then arr(j, 2) = "PGD05"
        If InStr(1, arr(j, 1), "00", vbTextCompare) > 0 Then arr(j, 2) = "HoiSo"
        If InStr(1, arr(j, 1), "03", vbTextCompare) > 0 Then arr(j, 2) = "PGD03"
        If InStr(1, arr(j, 1), "04", vbTextCompare) > 0 Then arr(j, 2) = "PGD04"
        If InStr(1, arr(j, 1), "07", vbTextCompare) > 0 Then arr(j, 2) = "PGD07"
        If InStr(1, arr(j, 1), "09", vbTextCompare) > 0 Then arr(j, 2) = "PGD09"
        If InStr(1, arr(j, 1), "10", vbTextCompare) > 0 Then arr(j, 2) = "PGD10"
        If Trim(arr(j, 1)) = "" Then
            arr(j, 1) = "KoPhongBan"
            arr(j, 2) = arr(j, 1)
        End If
        If Trim(arr(j, 3)) = "" Then arr(j, 3) = "KoMaNhanSu"
        If Trim(arr(j, 4)) = "" Then arr(j, 4) = "KoTenTuoi"
    Next
    Range("A1:D" & SoDongDuLieu).Value = arr

    tg = Timer - tg
    MsgBox tg & " done."
End Sub
Code này chưa chắc đúng. Vì nó chỉ tăng tốc chứ mức độ chính xác thì thua cả code ban đầu.
 
Upvote 0
1.
Cho vào đây.
1538933880080.png
2.
SoDongDuLieu = Range("A1").End(xlDown).Row
Khi không có dữ liệu thì tụt tận gót chân.

3.
If Range("A" & j).Value Like " " Then
Range("A" & j).Value = "KoPhongBan"
Range("B" & j).Value = "KoPhongBan"
End If
Lần xử lý thứ 2 trở đi thì [Aj]= "KoPhongBan" thì xử lý sao?

4.
thì không đọc và ghi kết quả vào từng cell nữa.

PHP:
Option Explicit

Sub vidu()
    Const CodeMatch As String = "|||05||00||03||04||07||09||10||Ko|| "
    Const KMNS As String = "KhongMaNhanSu"
    Const KTT As String = "KhongTenTuoi"
    Dim PGD, lR As Long, arr(), i As Long, ws As Worksheet, N As Long, idx As Long, sCode As String
    PGD = Array("PGD05", "HoiSo", "PGD03", "PGD04", "PGD07", "PGD09", "PGD10", "KoPhongBan", "KoPhongBan")
    N = UBound(PGD)
    Set ws = ThisWorkbook.Worksheets("Dulieu")
    With ws
        lR = .Range("A" & Rows.Count).End(xlUp).Row
        arr = .Range("A1:D" & lR).Value2
        '//Côt A format: Text'
    End With
    For i = 1 To lR
        sCode = Left(arr(i, 1), 2)
        idx = 0
        If Len(sCode) > 0 Then idx = InStr(1, CodeMatch, sCode)
        If idx > 0 Then
            idx = idx / 4 - 1
            arr(i, 2) = PGD(idx)
            If idx = N Then arr(i, 1) = PGD(N)
        End If
        If Len(arr(i, 3)) = 0 Then arr(i, 3) = KMNS
        If Len(arr(i, 4)) = 0 Then arr(i, 4) = KTT
    Next i
    ws.Range("A1").Resize(lR, 4).Value = arr
End Sub
 
Upvote 0
Thử thôi rồi tính tiếp mà anh, có biết dữ liệu họ như thế nào, để họ tự phát triển thêm nữa. Ví dụ trong dữ liệu có công thức ...
Đã nói sai là sai.
Khi code có điều kiện ghi chồng dữ liệu là code luộm thuộm.
Code của bạn (và code ban đầu) phải thực hiện đủ 8 lần IF trong khi thực tế khong cần vậy, số lần duyệt trung bình ít hơn.
Trường hợp điều kiện 8 chồng lên điều kiện 7, 6, ... thì người ta dùng ELSE IF và xét ngược lại, 8 trước.

...
...
PGD = Array("PGD05", "HoiSo", "PGD03", "PGD04", "PGD07", "PGD09", "PGD10", "KoPhongBan", "KoPhongBan")
N = UBound(PGD)
...

Select Case trông dài hơn nhưng là cách sáng sủa nhất trong trường hợp này.
 
Lần chỉnh sửa cuối:
Upvote 0
Em thu gọn if lại thì lại ko ổn nên em để nhiều if, em biết là nhìn luộm thuộm. Mong VetMini chỉ giúp cho code nhanh ah.
Bài đã được tự động gộp:

Đúng vậy, thế mà em ko nhớ là dung select Case. Tuyệt. Gọn gàng code hơn. Hoàn toàn dữ liệu ko công thức ah.
 
Upvote 0
Đã nói sai là sai.
Khi code có điều kiện ghi chồng dữ liệu là code luộm thuộm.
Code của bạn (và code ban đầu) phải thực hiện đủ 8 lần IF trong khi thực tế khong cần vậy, số lần duyệt trung bình ít hơn.
Trường hợp điều kiện 8 chồng lên điều kiện 7, 6, ... thì người ta dùng ELSE IF và xét ngược lại, 8 trước.
Thuật toán và ý đồ là của tác giả, họ muốn nhanh thì mình dựa vào code của họ làm cho nhanh thôi. Tôi không cần biết và không thể biết ý của họ. Nhiều khi họ cố tình xét If như vậy thì sao?
Anh toàn đi bắt lỗi mà không đưa code ra.
Anh có thể viết code hoàn hảo trong khi chỉ dựa vào code của họ không?
 
Upvote 0
Thầy @VetMini nhà mình có tính rất xấu. Không bao giờ "Vở sạch chứ đẹp" được :p:p:p
 
Lần chỉnh sửa cuối:
Upvote 0
Thuật toán và ý đồ là của tác giả, họ muốn nhanh thì mình dựa vào code của họ làm cho nhanh thôi. Tôi không cần biết và không thể biết ý của họ. Nhiều khi họ cố tình xét If như vậy thì sao?
Anh toàn đi bắt lỗi mà không đưa code ra.
Anh có thể viết code hoàn hảo trong khi chỉ dựa vào code của họ không?
Xét If như vậy là luộm thuộm.
Tuy nhiên, code ngừoi ta khác code của bạn ở chỗ là nó so sánh thẳng (tuy like có wildcard hì cũng như so sánh thẳng) nên không bị sai trường hợp chồng điều kiện. Code của bạn dùng hàm InStr cho nên có thể bị chồng điều kiện (chuỗi kia có thể chứa 030405 thì sao?). Và như vậy là không đúng.

Về sự luộm thuộm của dãy code này. Đáng lẽ cỡ bạn không khích nổi tôi phải viết code biểu diễn đâu. Nhưng tôi thấy có người "like" bài ấy cho nên tôi giải thích luôn cho các thành viên khác biết:

If InStr(1, arr(j, 1), "05", vbTextCompare) > 0 Then arr(j, 2) = "PGD05" ' xét chuỗi lần 1
If InStr(1, arr(j, 1), "00", vbTextCompare) > 0 Then arr(j, 2) = "HoiSo" ' lần thứ 2
If InStr(1, arr(j, 1), "03", vbTextCompare) > 0 Then arr(j, 2) = "PGD03"
If InStr(1, arr(j, 1), "04", vbTextCompare) > 0 Then arr(j, 2) = "PGD04"
If InStr(1, arr(j, 1), "07", vbTextCompare) > 0 Then arr(j, 2) = "PGD07"
If InStr(1, arr(j, 1), "09", vbTextCompare) > 0 Then arr(j, 2) = "PGD09"
If InStr(1, arr(j, 1), "10", vbTextCompare) > 0 Then arr(j, 2) = "PGD10" ' lần thứ 8
If Trim(arr(j, 1)) = "" Then ' lần thứ 9
arr(j, 1) = "KoPhongBan"
arr(j, 2) = arr(j, 1)
End If
Nếu arr(j, 1) = "05000304070910" thì arr(j,2) được gán tất cả 8 lần, xét 9 lần, và kết quả cuối cùng là "PGD10"
Tuy trường hợp này không có khả năng xảy ra, nhưng đó không thể là cái cớ để bảo rằng code không luộm thuộm
(chỗ tô đỏ ở phần quote trên là lời phê của tôi)

Code đúng đắn:
If Trim(arr(j, 1)) = "" Then ' lần thứ 1
arr(j, 1) = "KoPhongBan"
arr(j, 2) = arr(j, 1)
ElseIf InStr(1, arr(j, 1), "10", vbTextCompare) > 0 Then ' lần thứ 2, nhưng chỉ xảy ra khi lần thứ nhất khong đạt
arr(j, 2) = "PGD10"
ElseIf InStr(1, arr(j, 1), "09", vbTextCompare) > 0 Then ' lần thứ 3, nhưng chỉ xảy ra khi lần thứ 1 và 3 khong đạt
arr(j, 2) = "PGD09"
ElseIf...
...
ElseIf InStr(1, arr(j, 1), "05", vbTextCompare) > 0 Then
arr(j, 2) = "PGD05"
End If
Trung bình số lần xét là 4,5. Và số lần gán vào arr(j,2) tối đa là 1
Nếu arr(j, 1) = "05000304070910" thì arr(j,2) được gán chỉ 1 lần, xét 2 lần, và kết quả cuối cùng là "PGD10"

Chú thêm về select case:
Nếu dùng select case thì cái nhóm 03, 04, 05, 07, 09, 10 có thể gộp vào 1 case và kết qả là "PGD" & (trị của ô)
 
Upvote 0
Í, vậy là mình biết cách mời anh vetmini viết code rồi, hễ thấy ai mời anh vetmini viết code thì ta cứ bấm "lai" bài viết đó, anh vetmini nhìn thấy thì sẽ cho chúng ta được xem code, phải không anh vetmini ? Hihi
 
Upvote 0
Í, vậy là mình biết cách mời anh vetmini viết code rồi, hễ thấy ai mời anh vetmini viết code thì ta cứ bấm "lai" bài viết đó, anh vetmini nhìn thấy thì sẽ cho chúng ta được xem code, phải không anh vetmini ? Hihi
"mời" viết code chi vậy? Code tôi viết thì có gì đặc biệt?
Cũng như chuyện văn chương, tôi bàn thơ mới đáng kể chứ thơ tôi làm nó lạt như nước ốc.
 
Upvote 0
Sub haskl()
Dim a, b As Long
Dim rng As Range
Dim hm As WorksheetFunction
Set hm = Application.WorksheetFunction
a = hm.RandBetween(1, 25)
b = hm.RandBetween(1, 25)

With Worksheets(1)
.Range(.Cells(a, b), .Cells(a + 8, b + 8)) _
.Borders.LineStyle = xlThick

End With
End Sub
Dạ moij nguoi giup minh viet them Code dat ten cho Range do dc hok\
 
Upvote 0
"mời" viết code chi vậy? Code tôi viết thì có gì đặc biệt?
Cũng như chuyện văn chương, tôi bàn thơ mới đáng kể chứ thơ tôi làm nó lạt như nước ốc.
Hu hu hu.......Trời oi là trời
Bác
VetMini
chỉ biết luật thơ thui
Còn không biết làm thơ đâu bà con ui.
 
Upvote 0
Mình có đoạn code muốn mọi người chỉ cho cách để hoàn thiện đoạn code này với ạ .( phần chữ màu đỏ mình chưa biết cách viết như thế nào)

Sub tinh_tong()
Dim KTcancat As Range, rVung As Range, LastCell, stt, lan
Dim ChuaCat As Range, KT As Range, rKtra As Range
Dim KTchuacat As Long, Chieudai1cay As Long
Dim Sothanhdacat As Long, Sothanhcancat As Long, Tongsothanhdacat As Long
Dim Tongsothanhcancat As Long, Socay As Long


On Error Resume Next
Application.DisplayAlerts = False
Set rVung = Application.InputBox(Prompt:="Chon vung", Title:="GPE", Type:=8)
On Error GoTo 0
Application.DisplayAlerts = True
If rVung Is Nothing Then Exit Sub
If rVung.Columns.Count <> 2 Then Exit Sub

LastCell = rVung.Item(rVung.Count).Address
Socay = 10
rVung.Select
Selection.Copy
Set rVung = rVung.Columns.Item(1)
rVung.Columns.Item(2).Offset(0, 1).FormulaR1C1 = "=RC[-2]*RC[-1]"


Range(LastCell).Select
ActiveCell.Offset(0, 3).FormulaR1C1 = Socay
ActiveCell.Offset(0, 4).FormulaR1C1 = " bằng tổng của cột vừa được nhân ra(phần code chữ màu xanh), rồi chia cho 6. kết quả nếu nhỏ hơn "socay" thì trả kết quả là đúng và lơn hơn"socay" thì trả kết quả là sai"
End Sub
 
Upvote 0
Em chào anh chị, em có mã code này mong anh chị giúp đỡ.
Mục đích: em muốn code chạy đến dò điểm từ cột G3:G14. Sau đó trả về kết quả từ cột H3:H14.
Vì em tự viết code nên khi run nó chỉ chạy ra kết quả ở cột H3.
Mong mọi người hỗ trợ em ạ
Code của em đây:
Sub hocluc()
Sheets("sheet1").Select
Range("G3:G14").Select
If ActiveCell >= 8 Then
Range("H3").Value = " Gioi"
ElseIf ActiveCell >= 6.5 Then
Range("H3").Value = " Kha"
ElseIf ActiveCell >= 6.5 Then
Range("H3").Value = " Trung Binh"
Else
Range("H3").Value = " Kem"
End If
End Sub
 
Upvote 0
Em chào anh chị, em có mã code này mong anh chị giúp đỡ.
Mục đích: em muốn code chạy đến dò điểm từ cột G3:G14. Sau đó trả về kết quả từ cột H3:H14.
Vì em tự viết code nên khi run nó chỉ chạy ra kết quả ở cột H3.
Mong mọi người hỗ trợ em ạ
Code của em đây:
Sub hocluc()
Sheets("sheet1").Select
Range("G3:G14").Select
If ActiveCell >= 8 Then
Range("H3").Value = " Gioi"
ElseIf ActiveCell >= 6.5 Then
Range("H3").Value = " Kha"
ElseIf ActiveCell >= 6.5 Then
Range("H3").Value = " Trung Binh"
Else
Range("H3").Value = " Kem"
End If
End Sub
Sub HocLuc()
Dim r As Long, sh As Worksheet
Set sh = Sheets("sheet1")
For r = 3 To 14
If sh.Cells(r, "G").Value >= 8 Then
sh.Cells(r, "H").Value = "Gioi"
ElseIf sh.Cells(r, "G").Value >= 6.5 Then
sh.Cells(r, "H").Value = "Kha"
ElseIf sh.Cells(r, "G").Value >= 5 Then
sh.Cells(r, "H").Value = "Trung Binh"
ElseIf sh.Cells(r, "G").Value >= 3.5 Then
sh.Cells(r, "H").Value = "Kem"
Else
sh.Cells(r, "H").Value = "Yeu"
End If
Next
End Sub
 
Upvote 0
mọi người cho mình hỏi:
cái đoạn code TextJoin ở dưới mình xài, khi mình chọn vùng tham chiếu từ A1:E1 (ví dụ) thì code chạy được.
nhưng khi mình bấm F9 cái vùng (A1:E1) nó thành {1,2,3,4,5} thì hàm ko chạy được báo lỗi #Value!
là thế nào mọi người.
Theo mình biết thì 2 cái đó cũng là mảng như nhau mà???

Mã:
Public Function TEXTJOIN(Delimiter As String, Ignore_Empty As Boolean, ParamArray Text1() As Variant) As String
Dim RangeArea As Variant
Dim Cell As Range
For Each RangeArea In Text1
If TypeName(RangeArea) = "Range" Then
For Each Cell In RangeArea
If Len(Cell.Value) <> 0 Or Ignore_Empty = False Then
TEXTJOIN = TEXTJOIN & Delimiter & Cell.Value
End If
Next Cell
Else
If Len(RangeArea) <> 0 Or Ignore_Empty = False Then
TEXTJOIN = TEXTJOIN & Delimiter & RangeArea
End If
End If
Next
TEXTJOIN = Mid(TEXTJOIN, Len(Delimiter) + 1)
End Function
 
Upvote 0
Sao không hỏi ngừoi viết code?
A1:E1 là mảng cell
{1,2,3,4,5} là mảng số.
Cell là object có thuộc tính Value. Số là kiểu cơ bản, không có thuộc tính.
If Len(Cell.Value) <> 0 Or Ignore_Empty = False Then
TEXTJOIN = TEXTJOIN & Delimiter & Cell.Value
End If
 
Upvote 0
Nếu tôi hiểu được mô tả của bạn thì lúc đó dữ liệu truyền vào là một mảng có 5 giá trị.
Tức RangeArea nó là mảng. Là mảng nên Len(RangeArea) sẽ có lỗi.
 
Upvote 0
Sao không hỏi ngừoi viết code?
A1:E1 là mảng cell
{1,2,3,4,5} là mảng số.
Cell là object có thuộc tính Value. Số là kiểu cơ bản, không có thuộc tính.
If Len(Cell.Value) <> 0 Or Ignore_Empty = False Then
TEXTJOIN = TEXTJOIN & Delimiter & Cell.Value
End If
{1,2,3,4,5} là mình ví dụ thôi chứ ko phải mảng số @@
Lụm lặt ở trên mạng thì biết ai viết đâu mà hỏi bạn.

Nếu tôi hiểu được mô tả của bạn thì lúc đó dữ liệu truyền vào là một mảng có 5 giá trị.
Tức RangeArea nó là mảng. Là mảng nên Len(RangeArea) sẽ có lỗi.
Đúng rồi ý mình là vậy đó bạn... sửa làm sao bạn nhỉ
 
Upvote 0
Ờ nhỉ, tôi khong để ý đến cái chỗ
If TypeName(RangeArea) = "Range" Then
 
Upvote 0
Còn code này mình tìm thấy ở trên forum cũng tương tự code ở trên.
Nó thì ko bị cái lỗi của mình nói là A1:E1 hay {1,2,3,4,5,6} đều xài được.
nhưng bị 1 vấn đề với ô trống là khi nối ô với điều kiện "-" ví dụ như {1,"","",4,"",6} thì nó thành: 1---4--6 (thay vì = 1-4-6)


Mã:
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    If Not IsArray(aTmp) Then aTmp = Array(aTmp)
    For Each Item In aTmp
      If TypeName(Item) <> "Error" Then
        tmp = CStr(Item)
        n = n + 1
        ReDim Preserve arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
 
Upvote 0
...
Đúng rồi ý mình là vậy đó bạn... sửa làm sao bạn nhỉ
Đúng là đáng sợ các hàm viết đại trà mà không có chú thích chỉ dẫn.
Ngừoi viết hàm muốn hàm có thể nối tất cả các loại dữ liệu, bất kỳ vụn vặt như thế nào.
Trước khi sửa, bạn phải xác định lại mình muốn gì?
{1,2,3,4,5} là một mảng, mảng này được truyền vào hàm như một tham chính thức, tức là một phần tử của cái Paramarray; chứ không phải là cả cái Paramarray.
Trong trường hợp này, bạn muốn nối như thế nào? Xem nó như là một range?
 
Upvote 0
Còn code này mình tìm thấy ở trên forum cũng tương tự code ở trên.
Nó thì ko bị cái lỗi của mình nói là A1:E1 hay {1,2,3,4,5,6} đều xài được.
nhưng bị 1 vấn đề với ô trống là khi nối ô với điều kiện "-" ví dụ như {1,"","",4,"",6} thì nó thành: 1---4--6 (thay vì = 1-4-6)


Mã:
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    If Not IsArray(aTmp) Then aTmp = Array(aTmp)
    For Each Item In aTmp
      If TypeName(Item) <> "Error" Then
        tmp = CStr(Item)
        n = n + 1
        ReDim Preserve arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
Uổi. Đó là lỗi do người truyền dữ liệu chứ. Chứ bản thân hàm thì đưa dữ liệu kiiểu gì thì mần kiểu ấy thui
 
Upvote 0
Đúng là đáng sơh các hàm viết đại trà mà không có chú thích chỉ dẫn.
Ngừoi viết hàm muốn hàm có thể nối tất cả các loại dữ liệu, bất kỳ vụn vặt như thế nào.
Trước khi sửa, bạn phải xác định lại mình muốn gì?
{1,2,3,4,5} là một mảng, mảng này được truyền vào hàm như một tham chính thức, tức là một phần tử của cái Paramarray; chứ không phải là cả cái Paramarray.
Trong trường hợp này, bạn muốn nối như thế nào? Xem nó như là một range?

mình cũng còn lờ mờ chưa rành lắm nên mấy cái khái niêm cũng ko rõ ràng lắm.
nhưng đại khái là ý mình là xem nó là 1 array ý.
khi kéo 1 vùng nào đó có trên 2 ô ngang thì nó tạo ra 1 mảng {x,y} còn 2 ô dọc thì {x;y} còn có ngang có dọc thì {x,y;x,y}
như khi mình kéo 1 vùng nào đó bất kỳ rồi nhấn F9 nó ra { } ý

như cái code dưới này nó làm được á bạn
Mã:
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    If Not IsArray(aTmp) Then aTmp = Array(aTmp)
    For Each Item In aTmp
      If TypeName(Item) <> "Error" Then
        tmp = CStr(Item)
        n = n + 1
        ReDim Preserve arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
 
Upvote 0
mình cũng còn lờ mờ chưa rành lắm nên mấy cái khái niêm cũng ko rõ ràng lắm.
nhưng đại khái là ý mình là xem nó là 1 array ý.
khi kéo 1 vùng nào đó có trên 2 ô ngang thì nó tạo ra 1 mảng {x,y} còn 2 ô dọc thì {x;y} còn có ngang có dọc thì {x,y;x,y}
như khi mình kéo 1 vùng nào đó bất kỳ rồi nhấn F9 nó ra { } ý

như cái code dưới này nó làm được á bạn
Mã:
Function JoinText(ByVal Delimiter As String, ParamArray Arrays()) As String
  Dim aTmp, arrDes(), Item, tmp As String
  Dim idx As Long, n As Long
  'On Error Resume Next
  For idx = LBound(Arrays) To UBound(Arrays)
    aTmp = Arrays(idx)
    If Not IsArray(aTmp) Then aTmp = Array(aTmp)
    For Each Item In aTmp
      If TypeName(Item) <> "Error" Then
        tmp = CStr(Item)
        n = n + 1
        ReDim Preserve arrDes(1 To n)
        arrDes(n) = tmp
      End If
    Next
  Next
  If n Then JoinText = Join(arrDes, Delimiter)
End Function
Khi khai báo ParamArray thì dữ liệu là mảng tham số ... Em có đọc tại https://bettersolutions.com/vba/arrays/paramarray.htm
 
Upvote 0
Về cái vụ "mảng" thì bài #1518 đã giải thích rồi.
Code TextJoin của bạn bị lỗi khi nó xét thấy {1,2,3,4,5} không phải là Range (điều kiện If, bài #1520), và tự động (mệnh đề Else) coi như là một chuỗi, hoặc một kiểu dữ liệu có thể ngầm ép thành chuỗi.
Hàm Len nhận tham là chuỗi, nếu tham là kiểu khác chuỗi thì nó sẽ cố gắng ép thành chuỗi. Thường thì chỉ có kiểu đơn giản (như Integer, Double, Boolean,...) mới ép được thành chuỗi. Mảng {1,2,3,4,5} không phải là kiểu đơn giản cho nên không ép được và hàm Len trả về lỗi

Code JoinText biến tất cả các mẫu dữ liệu trong Paramarry thành mảng VBA (mảng VBA khác với mảng Range). Sau đó nó cứ việc duyệt mảng mà khong sợ nhầm lẫn.

Khi khai báo ParamArray thì dữ liệu là mảng tham số ... Em có đọc tại https://bettersolutions.com/vba/arrays/paramarray.htm

Câu cuối của bài trên nói rằng nếu bạn nạp tham mảng vào Paramarry thì nó sẽ thành mảng 2 chiều. Điều này không hẳn đúng ý nghĩa của mảng 2 chiều. Thực tế thì Paramarray luôn luôn là mảng 1 chiều. Nếu bạn nạp tham mảng thì cả cái mảng ấy sẽ là 1 phần tử của Paramarray.
Ví dụ, bạn nạp
1,2,3,4,5
Thì Paramarray sẽ cho về 1 mảng Arr với 5 phần tử: Arr(0) = 1, Arr(1) = 2, ... Arr(4) = 5
Mặt khác, bạn nạp:
{1,2,3,4,5}
Thì Paramarray sẽ cho về 1 mảng Arr với 1 phần tử, và phần tử này là một mảng 5 phần tử: Arr(0)(1) = 1,... Arr(0)(5) = 5
Nói cách khác, đây là mảng trong mảng chứ không phải mảng 2 chiều.

Chú thích: { } là lệnh gọi hàm Evaluate để dựng mảng. Vì vậy kết quả là mảng Excel (Worksheet), Lbound là 1
Paramarray dùng mảng VBA, LBound luôn luôn là 0. Tôi dùng từ "luôn luôn" bởi vì Option Base 1 chỉ ảnh hưởng hàm Array thường, nhưng không ảnh hưởng được hàm VBA.Array
 
Lần chỉnh sửa cuối:
Upvote 0
Các anh/chị cho em hỏi chút.
Em có 1 sub sau:
Sub Xoadongtrong()
Dim i as Integer
For i = 1 to 100
If cells(i,1) = "" Then
Rows(i).Delete
End if
Next
End Sub

Nhưng khi em chạy sub thì sau lần chạy đầu tiên chỉ xóa được vài dòng, sau đó em phải ấn tiếp thì lại xóa thêm được vài dòng, và em phải chạy sub nhiều lần mới xóa được hết các dòng trống.
Như vậy là lỗi gì ạ.

Nhân tiện đây, em muốn hỏi chút là, em muốn sau khi thực hiên code rows(i).Delete thì 1s sau đó mới tiếp tục thực hiện code tiếp theo trong sub thì phải làm như thế nào ạ.
Em cảm ơn các anh/chị ạ
 
Upvote 0
Các anh/chị cho em hỏi chút.
Em có 1 sub sau:
Sub Xoadongtrong()
Dim i as Integer
For i = 1 to 100
If cells(i,1) = "" Then
Rows(i).Delete
End if
Next
End Sub

Nhưng khi em chạy sub thì sau lần chạy đầu tiên chỉ xóa được vài dòng, sau đó em phải ấn tiếp thì lại xóa thêm được vài dòng, và em phải chạy sub nhiều lần mới xóa được hết các dòng trống.
Như vậy là lỗi gì ạ.

Nhân tiện đây, em muốn hỏi chút là, em muốn sau khi thực hiên code rows(i).Delete thì 1s sau đó mới tiếp tục thực hiện code tiếp theo trong sub thì phải làm như thế nào ạ.
Em cảm ơn các anh/chị ạ
Vấn đề thứ nhất: Giả sử từ hàng 1 đến hàng 100 có 2 hàng trống là hàng 2 và hàng 3. Khi bạn cho i chạy từ 1 đến 100, khi i bằng 2 thì thỏa mãn điều kiện bạn xóa hàng 2 đi, vậy hàng 3 bây giờ đố bạn là hàng mấy? Và khi i bằng 3 đố bạn điều kiện có thỏa mãn hay không? bạn trả lời được 2 câu hỏi của tôi thì bạn hiểu được vấn đề do đâu.
Vấn đề thứ hai: Muốn chạy xong lệnh xóa hàng và chờ 1 giây mới chạy tiếp thì thêm lệnh sau vào sau lệnh xóa hàng.
Mã:
Application.Wait Now + #0:00:01#
 
Upvote 0
Vấn đề thứ nhất: Giả sử từ hàng 1 đến hàng 100 có 2 hàng trống là hàng 2 và hàng 3. Khi bạn cho i chạy từ 1 đến 100, khi i bằng 2 thì thỏa mãn điều kiện bạn xóa hàng 2 đi, vậy hàng 3 bây giờ đố bạn là hàng mấy? Và khi i bằng 3 đố bạn điều kiện có thỏa mãn hay không? bạn trả lời được 2 câu hỏi của tôi thì bạn hiểu được vấn đề do đâu.
Vấn đề thứ hai: Muốn chạy xong lệnh xóa hàng và chờ 1 giây mới chạy tiếp thì thêm lệnh sau vào sau lệnh xóa hàng.
Mã:
Application.Wait Now + #0:00:01#
Em đã hiểu vì sao em phải chạy sub nhiều lần rồi ạ.
Em cảm ơn anh đã hỗ trợ ạ
Bài đã được tự động gộp:

Vấn đề thứ nhất: Giả sử từ hàng 1 đến hàng 100 có 2 hàng trống là hàng 2 và hàng 3. Khi bạn cho i chạy từ 1 đến 100, khi i bằng 2 thì thỏa mãn điều kiện bạn xóa hàng 2 đi, vậy hàng 3 bây giờ đố bạn là hàng mấy? Và khi i bằng 3 đố bạn điều kiện có thỏa mãn hay không? bạn trả lời được 2 câu hỏi của tôi thì bạn hiểu được vấn đề do đâu.
Vấn đề thứ hai: Muốn chạy xong lệnh xóa hàng và chờ 1 giây mới chạy tiếp thì thêm lệnh sau vào sau lệnh xóa hàng.
Mã:
Application.Wait Now + #0:00:01#
Anh cho em hỏi thêm về vấn đề 2.
Em đã thêm code Application.Wait Now + #0:00:01# , nhưng sau khi xuống dòng thì lại hiện thành
Application.Wait Now + #12:00:01 AM#
Có cách nào hiện đúng 1s không ạ, và nếu em muốn chờ 0,5s sau mới chạy tiếp chẳng hạn thì sẽ để định dang như thế nào ạ.
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn biết tụi Tây hồi xưa nó có câu chuyện vui (xin lỗi rất là Tây, bởi vì nó rất kỳ thị chủng tộc):
Đem tất cả dân Tàu sắp hàng đi xuống biển thì cái hàng ấy sẽ không bao giờ dứt.

Bằng ý tưởng đó, nếu muốn xoá dòng thì phải làm ngược từ dưới lên:
For i = 100 to 1 step -1
 
Upvote 0
Bạn biết tụi Tây hồi xưa nó có câu chuyện vui (xin lỗi rất là Tây, bởi vì nó rất kỳ thị chủng tộc):
Đem tất cả dân Tàu sắp hàng đi xuống biển thì cái hàng ấy sẽ không bao giờ dứt.

Bằng ý tưởng đó, nếu muốn xoá dòng thì phải làm ngược từ dưới lên:
For i = 100 to 1 step -1
Cũng được nhưng cách làm này nếu dữ liệu nhiều đợi nó chạy xong mệt xỉu luôn. Cách để nó chạy nhanh là khi điều kiện thỏa mãn thì đưa hàng đó vào một biến vùng (Biến này để lưu hàng trống), khi xong vòng For dùng lệnh xóa một lần, Thứ hai nửa là bạn nên đưa dữ liệu vào mảng duyệt mảng sẽ nhanh hơn duyệt Cell.
 
Upvote 0
Bạn biết tụi Tây hồi xưa nó có câu chuyện vui (xin lỗi rất là Tây, bởi vì nó rất kỳ thị chủng tộc):
Đem tất cả dân Tàu sắp hàng đi xuống biển thì cái hàng ấy sẽ không bao giờ dứt.

Bằng ý tưởng đó, nếu muốn xoá dòng thì phải làm ngược từ dưới lên:
For i = 100 to 1 step -1
Em cảm ơn anh đã hướng dẫn ạ.
Nhưng em chưa hiểu câu chuyện của tụi Tây sao lại suy ra được code kia ạ
 
Upvote 0
Em đã hiểu vì sao em phải chạy sub nhiều lần rồi ạ.
Em cảm ơn anh đã hỗ trợ ạ
Bài đã được tự động gộp:


Anh cho em hỏi thêm về vấn đề 2.
Em đã thêm code Application.Wait Now + #0:00:01# , nhưng sau khi xuống dòng thì lại hiện thành
Application.Wait Now + #12:00:01 AM#
Có cách nào hiện đúng 1s không ạ, và nếu em muốn chờ 0,5s sau mới chạy tiếp chẳng hạn thì sẽ để định dang như thế nào ạ.
Dùng lại thế này xem sao?
Mã:
Application.Wait (Now + TimeValue("0:00:01"))
Có chắc là 0,5 giây không hay hướng dẫn xong lại 0,15 giây... Lúc đầu chỉ hỏi 1 giây bây giờ lại 0,5 giây, trước khi hỏi bạn nên lường trước trường hợp đặc biệt chứ. Gợi ý bạn tìm hàm API Sleep để sử dụng.
 
Upvote 0
Dùng lại thế này xem sao?
Mã:
Application.Wait (Now + TimeValue("0:00:01"))
Có chắc là 0,5 giây không hay hướng dẫn xong lại 0,15 giây... Lúc đầu chỉ hỏi 1 giây bây giờ lại 0,5 giây, trước khi hỏi bạn nên lường trước trường hợp đặc biệt chứ. Gợi ý bạn tìm hàm API Sleep để sử dụng.
Ban đầu em muốn để chờ 1s. Sau đó thử giảm xuống 0,5s xem lệnh có chạy không. Em thấy không được nên mới hỏi cho trường hợp <1s để nếu lần sau muốn dùng hoặc thậm chí dùng ngay ở lần này, coi như là tích lũy thêm kiến thức ạ.
Em sẽ tìm kiếm hàm API Sleep và tìm hiểu về nó ạ.
Em cảm ơn anh nhiều ạ!
 
Upvote 0
Chào các bạn, tôi có 1 sheet HD có 5 cột Tên hàng, MHH, SL, DGiá, thành tiền và các dữ liệu đã được liên kết với nhau để khi nhập vào dữ liệu của MHH và SL thì các số liệu khác sẽ thể hiện tương ứng (sheet HD có 3 liên của 1 hóa đơn trình bày trên cùng 1 trang chứ không phải 3 Hóa đơn khác nhau) và 1 sheet TH cũng có 5 cột y như ở sheet HD dùng để copy các dữ liệu trong từng Hóa đơn (vùng được tô màu vàng của Hóa đơn) nối tiếp nhau để sau đó tổng hợp lại thành lượng bán trong ngày của từng mặt hàng. Số lượng hóa đơn mỗi ngày khá nhiều nên copy thủ công rất vất vả, các bạn có thể chỉ giúp đoạn code VBA hoặc Macro để khi nhập số liệu vào các sheet HD thì sheet TH cũng chép các số liệu tương ứng và dữ liệu của Hóa đơn sau nối tiếp và nằm dưới dữ liệu của Hóa đơn trước, xin cảm ơn nhiều.
 

File đính kèm

Upvote 0
Chào các bạn, tôi có 1 sheet HD có 5 cột Tên hàng, MHH, SL, DGiá, thành tiền và các dữ liệu đã được liên kết với nhau để khi nhập vào dữ liệu của MHH và SL thì các số liệu khác sẽ thể hiện tương ứng (sheet HD có 3 liên của 1 hóa đơn trình bày trên cùng 1 trang chứ không phải 3 Hóa đơn khác nhau) và 1 sheet TH cũng có 5 cột y như ở sheet HD dùng để copy các dữ liệu trong từng Hóa đơn (vùng được tô màu vàng của Hóa đơn) nối tiếp nhau để sau đó tổng hợp lại thành lượng bán trong ngày của từng mặt hàng. Số lượng hóa đơn mỗi ngày khá nhiều nên copy thủ công rất vất vả, các bạn có thể chỉ giúp đoạn code VBA hoặc Macro để khi nhập số liệu vào các sheet HD thì sheet TH cũng chép các số liệu tương ứng và dữ liệu của Hóa đơn sau nối tiếp và nằm dưới dữ liệu của Hóa đơn trước, xin cảm ơn nhiều.
Muốn truy vấn dữ liệu của từng Hóa đơn thì sheet theo dõi của bạn phài có cột số Hóa đơn và ngày Hóa đơn.
Bạn có thể tham khảo cách làm trong bài viết ở Link sau:
https://www.giaiphapexcel.com/diendan/threads/giúp-lưu-hóa-đơn-từ-sheet1-vào-sheet-theo-dõi-và-xuất-sheet-theo-dõi-ra-file-mới-để-import-dữ-liệu-vào-phần-mềm.138276/

Hoặc Link sau:
https://www.giaiphapexcel.com/diend...iếu-thu-chi-từ-dữ-liệu-của-sheet-data.138272/
 
Upvote 0
Các anh/chị cho em hỏi chút.
Em có 2 file tương ứng với 2 sub test1 và test2
Giờ em mở file 1 lên chạy sub test1.
Vậy có cách nào để khi em chạy sub test1 thì file 2 mở lên và chạy sub test2 cho file số 2 không ạ?
 
Upvote 0

Bạn thử code bên dưới xem có được không ạ?

Mã:
'code de trong module file 1

Sub tes1_file1()

    Workbooks.Open Filename:=ThisWorkbook.Path & "\file2.xls"

End Sub


'code de trong ThisWorkbook file 2

Private Sub Workbook_Open()

    tes2_file2

End Sub

Sub tes2_file2()

    'code cua tes2_file2

    'lam ji do tuy ban...

End Sub
 
Upvote 0
Bạn thử code bên dưới xem có được không ạ?

Mã:
'code de trong module file 1

Sub tes1_file1()

    Workbooks.Open Filename:=ThisWorkbook.Path & "\file2.xls"

End Sub


'code de trong ThisWorkbook file 2

Private Sub Workbook_Open()

    tes2_file2

End Sub

Sub tes2_file2()

    'code cua tes2_file2

    'lam ji do tuy ban...

End Sub
bạn ơi! code như trên có nghĩa là. File1 đang mở, file2 đang đóng. Mình chạy sub test1_file1, thì file 2 sẽ mở lên và chạy sub test2_file2 cho file thứ 2 đúng ko?
 
Upvote 0
bạn ơi! code như trên có nghĩa là. File1 đang mở, file2 đang đóng. Mình chạy sub test1_file1, thì file 2 sẽ mở lên và chạy sub test2_file2 cho file thứ 2 đúng ko?

Dạ hình như là vậy ạ, bạn chạy thử xem có đúng ý không ạ?
Nhưng với điều kiện là 2 file cùng để chung trong 1 thư mục bạn nhé và file 2 phải có tên là "file2.xls" hoặc nếu bạn muốn sửa tên file 2 thì sửa trong code ạ.
còn file 1 đang mở bạn có thể đặt tên gì cho file 1 cũng được.
 
Upvote 0
Bạn thử code bên dưới xem có được không ạ?

Mã:
'code de trong module file 1

Sub tes1_file1()

    Workbooks.Open Filename:=ThisWorkbook.Path & "\file2.xls"

End Sub


'code de trong ThisWorkbook file 2

Private Sub Workbook_Open()

    tes2_file2

End Sub

Sub tes2_file2()

    'code cua tes2_file2

    'lam ji do tuy ban...

End Sub
Mình chạy không được rồi. hiện ra thông báo Macro disable
 
Upvote 0
Mình chạy không được rồi. hiện ra thông báo Macro disable
Ôi,... thế này thì lâu lắm !
Vậy bạn thử vào link sau tìm hiểu thêm về cách cho tập tin hoạt động khi có chứa macro,
https://www.giaiphapexcel.com/diendan/threads/bài-0-kiến-thức-chung-về-vba.130635/

hoặc link:
https://support.office.com/vi-vn/ar...p-office-12b036fd-d140-4e74-b45e-16fed1a7e5c6

để tham khảo thêm ạ.
 
Upvote 0
Bài đã được tự động gộp:

mình đang vận dụng hướng dẫn của bạn, rất cám ơn sự giúp đở của bạn, chúc bạn ngày mới an lành.
 
Upvote 0
Xin chào các bạn, nhờ các bạn giúp đỡ 1 vấn đề sau ạ:
Oanh Thơ (OT) tạo 1 sub có tên MySub:
Mã:
Sub MySub(shTongHop As String, shList As String, shData As String, _
        colSum1 As Integer, colSum2 As Integer, colSum3 As Integer, _
        rngKQ As String)

    'code...

End Sub



Và OT tạo thêm 1 sub testMySub để gọi và truyền các tham số như bên dưới

Sub testMySub()
    Call MySub("Sheet1", "Sheet2", "Sheet3", 5, 7, , "A9")
End Sub

Code báo lỗi: Argument not optional (Error 449)
Nguyên nhân là do Call MySub("Sheet1", "Sheet2", "Sheet3", 5, 7, , "C5") thiếu 1 tham số sau số 7.
---
Mong muốn khai báo các biến trong MySub như thế nào để có thể nhập hoặc không nhập ạ.
Bài đã được tự động gộp:
 
Upvote 0
Lệnh gọi trên báo lỗi vì bạn chưa truyền tham biến
colSum3 As Integer
Để như bạn muốn ta cần khai báo:
PHP:
Sub MySub(ShTH As String, ShList As String, ShData As String, _
        ColSum1 As Integer, ColSum2 As Integer, Optional ColSum3 As Integer= 0, _
                 Optional RngKQ As String = "GPE.COM")

    'code...     '
End Sub
 
Upvote 0
Lệnh gọi trên báo lỗi vì bạn chưa truyền tham biến
colSum3 As Integer
Để như bạn muốn ta cần khai báo:
PHP:
Sub MySub(ShTH As String, ShList As String, ShData As String, _
        ColSum1 As Integer, ColSum2 As Integer, Optional ColSum3 As Integer= 0, _
                 Optional RngKQ As String = "GPE.COM")

    'code...     '
End Sub

A, thêm Optional trước biến.
Dạ ,cháu cảm ơn bác SA_DQ
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các bạn giúp đỡ Oanh Thơ trường hợp sau với ạ,với code sau:

Mã:
Sub MySub(ColSum1 As Integer, Optional ColSum2 As Integer = 0, Optional ColSum3 As Integer = 0)
     Dim arr()
     arr = Range("C3:F11").Value
     Range("K3").Resize(9, 1) = arr(1, ColSum1) + arr(1, ColSum2) + arr(1, ColSum3)
End Sub

Sub testMySub()
    Call MySub(1, 2)
End Sub

Khi Oanh Thơ chạy testMySub,
code báo lỗi: Subscript out of range (Error 9) tại dòng: Range("K3").Resize(9, 1) = arr(1, ColSum1) + arr(1, ColSum2) + arr(1, ColSum3)
Nguyên nhân do: MySub(1, 2) truyền vào thiếu 1 tham số.

Vậy để khắc phục lỗi này thì trong MySub phải đặt câu lệnh khắc phục lỗi như thê nào để khi chạy testMySub code vẫn hoạt động bình thường
khi Call MySub truyền đủ hoặc không đủ tham số?
 
Upvote 0
Nhờ các bạn giúp đỡ Oanh Thơ trường hợp sau với ạ,với code sau:

Mã:
Sub MySub(ColSum1 As Integer, Optional ColSum2 As Integer = 0, Optional ColSum3 As Integer = 0)
     Dim arr()
     arr = Range("C3:F11").Value
     Range("K3").Resize(9, 1) = arr(1, ColSum1) + arr(1, ColSum2) + arr(1, ColSum3)
End Sub

Sub testMySub()
    Call MySub(1, 2)
End Sub

Khi Oanh Thơ chạy testMySub,
code báo lỗi: Subscript out of range (Error 9) tại dòng: Range("K3").Resize(9, 1) = arr(1, ColSum1) + arr(1, ColSum2) + arr(1, ColSum3)
Nguyên nhân do: MySub(1, 2) truyền vào thiếu 1 tham số.

Vậy để khắc phục lỗi này thì trong MySub phải đặt câu lệnh khắc phục lỗi như thê nào để khi chạy testMySub code vẫn hoạt động bình thường
khi Call MySub truyền đủ hoặc không đủ tham số?
Dùng hàm IIF(ColSum2=0,0,arr(1, ColSum2)) gọn nhưng nghe nói chạy chậm, có thể vẫn còn lỗi
 
Upvote 0
#1549:
. Giả sử đơn giản bẫy lỗi khi chỉ số cột <1 thì trả về giá trị =0.
PHP:
Dim heso as Long
If colSum <1 then
 heso =0 
 colSum =1 
Else 
heso =1
End if
Ketqua= heso*arr(1,colSum)
 
Upvote 0
Dùng hàm IIF(ColSum2=0,0,arr(1, ColSum2)) gọn nhưng nghe nói chạy chậm, có thể vẫn còn lỗi
Chậm: phải trên chục ngàn lượt chạy mới có khác biệt.
Lỗi: IIF là một hàm. Khi gọi hàm thì VBA phải tính tất cả các tham để nạp vào. Tức là biểu thức arr(1, ColSum2) không thoát.
Chạy thử sub t sau đây thì biết
Function f1()
f1 = 1
MsgBox "f1 called"
End Function
Function f2()
f2 = 2
MsgBox "f2 called"
End Function
Sub t()
MsgBox "ket qua la " & IIf(1 > 0, f1, f2)
End Sub
 
Upvote 0
Chậm: phải trên chục ngàn lượt chạy mới có khác biệt.
Lỗi: IIF là một hàm. Khi gọi hàm thì VBA phải tính tất cả các tham để nạp vào. Tức là biểu thức arr(1, ColSum2) không thoát.
Chạy thử sub t sau đây thì biết
Function f1()
f1 = 1
MsgBox "f1 called"
End Function
Function f2()
f2 = 2
MsgBox "f2 called"
End Function
Sub t()
MsgBox "ket qua la " & IIf(1 > 0, f1, f2)
End Sub
Các bài trước bạn đã lưu ý rồi, nhưng không nhớ hết :( cảm thấy không yên tâm nên mới thòng thêm câu "có thể còn lỗi" o_O
 
Upvote 0

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

Back
Top Bottom