Chuyên đề giải đáp những thắc mắc về code VBA

Liên hệ QC

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:
Í, 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
Web KT
Back
Top Bottom