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:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
     Dim a As Long, lr As Long, i As Long, j As Byte
     Dim arr, arr1
     If Target.Address = "$C$1" Then
       With Sheet1
         lr = .Range("B" & Rows.Count).End(xlUp).Row
         If lr < 3 Then MsgBox "khong co du lieu": Exit Sub
         arr = .Range("A3:E" & lr).Value
         ReDim arr1(1 To UBound(arr, 1), 1 To 5)
         For i = 1 To UBound(arr, 1)
             If arr(i, 1) = Target.Value Then
                a = a + 1
                For j = 1 To 5
                    arr1(a, j) = arr(i, j)
                Next j
             End If
         Next i
       End With
       With Sheet2
            lr = .Range("B" & Rows.Count).End(xlUp).Row
            If lr > 2 Then .Range("a3:e" & lr).ClearContents
            If a Then .Range("A3").Resize(a, 5).Value = arr1
       End With
     End If
End Sub

a/c GIÚP EM DỊCH CÁI CODE NÀY VỚI , MÌNH KHÔNG HIỂU CHỔ 2 HÀM FOR LỒNG VÀO NHAU !!!
 
Upvote 0
Mã:
         For i = 1 To UBound(arr, 1)
1             If arr(i, 1) = Target.Value Then
                a = a + 1
3               For j = 1 To 5
                    arr1(a, j) = arr(i, j)
  5              Next j
             End If
         Next i
a/c GIÚP EM DỊCH CÁI CODE NÀY VỚI , MÌNH KHÔNG HIỂU CHỔ 2 HÀM FOR LỒNG VÀO NHAU !!!
Vòng lặp ngoài (theo tham biến i) duyệt từ đầu đến cuối mảng (dữ liệu)
D1: (Nếu dòng đang duyệt) thỏa điều kiện thì thực hiện các lệnh trước D6
D2: Tăng biến đềm a lên 1 đơn vị
D3: Tạo vòng lặp theo cột (1 -> 5)
D4 Ghi 5 giá trị ứng với 5 cột của dòng dữ liệu (thỏa Đ/K) vô mảng đích (Arr1())

Vui nếu giúp bạn ít nhiều
 
Lần chỉnh sửa cuối:
Upvote 0
Nhờ các thầy cô xem giúp em file đính kèm ạ. File đính em em cũng đang dùng code sẵn rồi. Nhưng lại chưa đúng ý lắm.
Các thầy cô có thể giúp em viết code. Hoặc tư vấn em nên dùng hàm gì trong excel để đáp ứng được các yêu cầu trong đó ạ.
Em cám ơn
Formmau
 
Upvote 0
Nhờ các thầy cô xem giúp em file đính kèm ạ. File đính em em cũng đang dùng code sẵn rồi. Nhưng lại chưa đúng ý lắm.
Các thầy cô có thể giúp em viết code. Hoặc tư vấn em nên dùng hàm gì trong excel để đáp ứng được các yêu cầu trong đó ạ.
Em cám ơn
Formmau
Bấm vào Link của bạn nó ra cái này
1545918324237.png
Nếu không phải là gải thích, gỡ rối về Code Bạn lập Topic mới sẽ có nhiều người tư vấn cho Bạn
 
Upvote 0

File đính kèm

Upvote 0
. . . . (1) File đính em cũng đang dùng code sẵn rồi. Nhưng lại chưa đúng ý lắm.
(2) Các thầy cô có thể giúp em viết code. Hoặc tư vấn em nên dùng hàm gì trong excel để đáp ứng được các yêu cầu trong đó ạ.
(1) Trong file không thấy miếng Code nào cả, nên chưa thể biết ý bạn là sao?
(2) Trong file có mỗi trang dữ liệu; Các dữ liệu thuộc 31 dòng & trãi dài từ cột A đến cột G, TRong đó công thức tại 2 cột E & G đang lỗi
Nên không rõ iêu cầu của bạn là gì.

Tạm biết!
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào các bạn.
Oanh Thơ tạo 1 hàm tìm kiếm địa chỉ của 1 chuỗi ký tự như sau:
Mã:
Function MyFind(txtFind As String, rng As Range) As Range
    If Not IsError(Application.Match(txtFind, rng, 0)) Then
         Set MyFind = Cells(Application.Match(txtFind, rng, 0), 1)
         Debug.Print MyFind.Address
    End If
End Function
Nhờ các bạn giúp đỡ làm thế nào để gán được địa chỉ của chuỗi cần tìm vào biến "txtAddress" khi chạy testMyFind:
Mã:
Sub testMyFind()
    Dim rngtxt As Range, txtAddress As Range
    Set rngtxt = ThisWorkbook.Worksheets("Sheet1").Range("A1:A" & 10000)
    MyFind "NguyenHoangOanhTho", rngtxt
End Sub
 
Upvote 0
Xin chào các bạn.
Oanh Thơ tạo 1 hàm tìm kiếm địa chỉ của 1 chuỗi ký tự như sau:
Mã:
Function MyFind(txtFind As String, rng As Range) As Range
    If Not IsError(Application.Match(txtFind, rng, 0)) Then
         Set MyFind = Cells(Application.Match(txtFind, rng, 0), 1)
         Debug.Print MyFind.Address
    End If
End Function
Nhờ các bạn giúp đỡ làm thế nào để gán được địa chỉ của chuỗi cần tìm vào biến "txtAddress" khi chạy testMyFind:
Mã:
Sub testMyFind()
    Dim rngtxt As Range, txtAddress As Range
    Set rngtxt = ThisWorkbook.Worksheets("Sheet1").Range("A1:A" & 10000)
    MyFind "NguyenHoangOanhTho", rngtxt
End Sub
Cái này thì gán bình thường thôi mà.
Mã:
Set  txtAddress = MyFind("NguyenHoangOanhTho", rngtxt)
 
Upvote 0
Xin chào các bạn.
Oanh Thơ tạo 1 hàm tìm kiếm địa chỉ của 1 chuỗi ký tự như sau:
Mã:
Function MyFind(txtFind As String, rng As Range) As Range
    If Not IsError(Application.Match(txtFind, rng, 0)) Then
         Set MyFind = Cells(Application.Match(txtFind, rng, 0), 1)
         Debug.Print MyFind.Address
    End If
End Function
Nhờ các bạn giúp đỡ làm thế nào để gán được địa chỉ của chuỗi cần tìm vào biến "txtAddress" khi chạy testMyFind:
Mã:
Sub testMyFind()
    Dim rngtxt As Range, txtAddress As Range
    Set rngtxt = ThisWorkbook.Worksheets("Sheet1").Range("A1:A" & 10000)
    MyFind "NguyenHoangOanhTho", rngtxt
End Sub
Kết quả hàm MyFind là cái gì vậy bạn? Tôi chưa hình dung được áp dụng vào việc gì.
 
Lần chỉnh sửa cuối:
Upvote 0
O. Thơ cần tạo 1 hàm tìm kiếm địa chỉ của 1 chuỗi ký tự
Hình như bạn này đang cần tìm kiếm trên cột [A:A] 1 chuỗi kí tự nhập vô từ bàn fím
Nếu tìm thấy thì liệt kê địa chỉ ô được tìm thấy?

Nếu vấy thì thực hiện trong 1 macro thôi, gồm các công đoạn sau:

Nhấp kí tự cần tìm vô 1 tham biến (kiểu chuỗi) bằng hàm InputBox()
Tới đây có thể có chí ít các trường hợp như sau:
1./ Không tìm thấy: Trả lời "Nothing"
2./ Tìm thấy chỉ có 1 ô: Trả vế địa chỉ ô đó
3./ Tìm thấy từ 2 ô trở lên:
Khai báo từ đầu 1 mảng ghi kết quả của công cuộc tìm kiếm đó
Trả về là dẫy địa chỉ các ô được tìm thấy.

Ngoài ra cũng nói trước là: Công cuộc tìm kiếm này có fải tìm nguyên thể hay chỉ tìm gần đúng,
Ví dụ tìm mọi người có họ là 'Nguyễn' hay họ & đệm là 'Nguyễn Văn',. . . . (?)
Tìm chữ hoa lẫn chữ thường, chuỗi thể hiện ngày-tháng
Trị cầm tìm là kiểu số, như 2019
Trị cần tìm là thể loại 'Ngày-Tháng-Năm',. . . .

Dù gì thì cũng không nhất thiết fải viết hàm
Vì fương thức FIND() sẽ chỉ tìm 1 lần duy nhất, ta không thu kết quả của FinNext() (Kết quả của FindNext chỉ thấy trên cửa số Immediate mà thôi.)
. . . . . .
Mong fản hồi từ bạn & chúc vui khi sắp sang xuân!
 
Upvote 0
Xin cảm ơn chú @giaiphap ,anh @huuthang_bd ,bác @SA_DQ nhiều ạ.

OT sử dụng hàm MyFind với mục đích tìm 1 chuỗi trong một vùng dữ liệu bao gồm các ô gộp(trộn) ạ, vì phương thức find không tìm kiếm được với các ô bị trộn(gộp).
Mới đầu OT cũng viết như chú @giaiphap rồi nhưng chắc do viết sai lỗi chính tả trong code nên báo lỗi đỏ, loay hoay mãi không được nên gửi lên GPE để hỏi ạ.
Cảm ơn bác @SA_DQ cháu đã xử lý được vấn đề với hàm MyFind rồi ạ.
Kính chúc Bác/Chú/Anh năm mới nhiều sức khỏe.
Oanh Thơ
 
Upvote 0
OT sử dụng hàm MyFind với mục đích tìm 1 chuỗi trong một vùng dữ liệu bao gồm các ô gộp(trộn) ạ, vì phương thức find không tìm kiếm được với các ô bị trộn(gộp).
Trong các hàm UDF thì mình sẽ thử, nhưng FIND() vẫn có thể tìm trong các ô trộn như thường (trong macro); Chỉ là fải xài với tí chút mẹo
Ví dụ tìm trong cột dữ liệu có các ô trộn theo:
Cột, có nghĩa là vài 3 ô trong cột bị trộn lại thì ta fải tăng vùng tìm kiếm lên theo hàng (dòng), ví dụ từ 99 hàng lên 120 hàng chẵng hạn
Hàng, có nghĩa là vài hàng nào đó trong cột đã bị trộn ô theo hàng thì vùng tìm kiếm cần tăng số cột lên thêm chục hay hơn số cột.

Còn trong UDF, mình xin nhắc lại là FINDNext chỉ cho ta kết quả trên cửa số Immediate mà thôi.
 
Upvote 0
Trong các hàm UDF thì mình sẽ thử, nhưng FIND() vẫn có thể tìm trong các ô trộn như thường (trong macro); Chỉ là fải xài với tí chút mẹo
Ví dụ tìm trong cột dữ liệu có các ô trộn theo:
Cột, có nghĩa là vài 3 ô trong cột bị trộn lại thì ta fải tăng vùng tìm kiếm lên theo hàng (dòng), ví dụ từ 99 hàng lên 120 hàng chẵng hạn
Hàng, có nghĩa là vài hàng nào đó trong cột đã bị trộn ô theo hàng thì vùng tìm kiếm cần tăng số cột lên thêm chục hay hơn số cột.

Còn trong UDF, mình xin nhắc lại là FINDNext chỉ cho ta kết quả trên cửa số Immediate mà thôi.

Cháu cảm ơn bác Sa,
Nghĩa là mở rộng vùng tìm kiếm so với vùng chứa dữ liệu thì vẫn sử dụng được phương thức Find ạ.
Thảo nào khi cháu thao tác thủ công crtl+F vẫn tìm được với các ô trộn nhưng khi chạy code trong vùng có dữ liệu thì không được, cháu sẽ thử lại ạ.
 
Upvote 0
Tôi cũng có lúc nghĩ nhầm. Cứ đổ tôi cho ghép ô nhưng không phải 100% là như vậy.

Giả sử ta tìm trong cột I, nhưng Ik:Nk, Im:Nm, Ip:Np, với k, m, q là các số nguyên dương nào đó, là các ô ghép (tức tìm trong cột nhưng các ô được ghép theo dòng chứ không phải theo cột đang tìm kiếm) thì
Mã:
Set rng = ThisWorkbook.Worksheets("DL").Range("I1:I" & Rows.Count).Find(Target.Value, , xlValues, xlWhole, xlByColumns, xlNext)
sẽ trả về rng = Nothing.

Nhưng
Mã:
Set rng = ThisWorkbook.Worksheets("DL").Range("I1:I" & Rows.Count - 1).Find(Target.Value, , xlValues, xlWhole, xlByColumns, xlNext)

sẽ trả về ô merge trong cột I mà có giá trị Target.Value

Tóm lại sự khác nhau chỉ là Rows.Count - 1 thay cho Rows.Count. Hoặc không dùng Rows.Count mà tìm dòng cuối có dữ liệu bằng End(xlUp)

Tóm lại không bắt buộc phải mở rộng (tìm dòng cuối có dữ liệu bằng End(xlUp) rồi FIND trong vùng đó thôi). Còn nếu lười không xác định vùng dữ liệu mà chỉ dùng mở rộng thì không được mở rộng tới Rows.Count. Chỉ mở rộng cùng lắm tới Rows.Count-1
 
Lần chỉnh sửa cuối:
Upvote 0
Con cảm ơn bác Siwtom về những chỉ dẫn rất chi tiết ạ.
Vấn đề tìm kiếm với ô ghép con cũng đã xử lý được ngay tức thời rồi ạ,trước khi tìm thì hủy merge là được. Có chút cảm hứng nên con tìm hiểu để biết thêm về cách viết hàm và lấy giá trị của hàm ạ.
Con chúc bác sức khỏe.
Oanh Thơ.
 
Upvote 0
Con cảm ơn bác Siwtom về những chỉ dẫn rất chi tiết ạ.
Vấn đề tìm kiếm với ô ghép con cũng đã xử lý được ngay tức thời rồi ạ,trước khi tìm thì hủy merge là được. Có chút cảm hứng nên con tìm hiểu để biết thêm về cách viết hàm và lấy giá trị của hàm ạ.
Con chúc bác sức khỏe.
Oanh Thơ.
Thì tôi cũng chỉ muốn lưu ý là không cần hủy merge.
Nếu tôi viết
Mã:
Set rng = ThisWorkbook.Worksheets("DL").Range("I1:I" & Rows.Count).Find(Target.Value, , xlValues, xlWhole, xlByColumns, xlNext)
mà FIND không tìm thấy, tức rng là Nothing, thì không bắt buộc phải hủy merge mà chỉ cần sửa thành Rows.Count-1 hoặc thay Rows.Count bằng lastRow, với lastRow được xác định bằng End(xlUp). Tôi chỉ muốn nhấn mạnh là có lúc tôi tưởng phải bỏ merge nhưng thực ra tôi lầm.

Còn về cái bạn hỏi trong chủ đề này thì đơn giản thôi. Hàm của bạn trả về 1 đối tượng, ở đây là đối tượng Range. Với đối tượng thì bạn phải dùng từ khóa SET
Mã:
Set txtAddress = MyFind("NguyenHoangOanhTho", rngtxt)

Tất nhiên txtAddress là cái tên không đúng vì nó là đối tượng Range chứ không phải giá trị String (address)
 
Upvote 0
Thì tôi cũng chỉ muốn lưu ý là không cần hủy merge.
Nếu tôi viết
Mã:
Set rng = ThisWorkbook.Worksheets("DL").Range("I1:I" & Rows.Count).Find(Target.Value, , xlValues, xlWhole, xlByColumns, xlNext)
mà FIND không tìm thấy, tức rng là Nothing, thì không bắt buộc phải hủy merge mà chỉ cần sửa thành Rows.Count-1 hoặc thay Rows.Count bằng lastRow, với lastRow được xác định bằng End(xlUp). Tôi chỉ muốn nhấn mạnh là có lúc tôi tưởng phải bỏ merge nhưng thực ra tôi lầm.

Còn về cái bạn hỏi trong chủ đề này thì đơn giản thôi. Hàm của bạn trả về 1 đối tượng, ở đây là đối tượng Range. Với đối tượng thì bạn phải dùng từ khóa SET
Mã:
Set txtAddress = MyFind("NguyenHoangOanhTho", rngtxt)

Tất nhiên txtAddress là cái tên không đúng vì nó là đối tượng Range chứ không phải giá trị String (address)

Dạ vâng,con hiểu rồi.Con cảm ơn bác nhiều ạ.
 
Upvote 0
PHP:
Option Explicit
Sub SendMail()
    Dim OutApp As Object
    Dim OutMail As Object
    Dim cell As Range
    Dim i As Long
    Dim Addresslist As Object
    Application.ScreenUpdating = False
    Set Addresslist = CreateObject("Scripting.Dictionary")

    Set OutApp = CreateObject("Outlook.Application")
    OutApp.Session.Logon
   
    For Each cell In Columns("C").Cells.SpecialCells(xlCellTypeConstants)
        If cell.Value Like "?*@?*.?*" And LCase(Cells(cell.Row, "F").Value) = "y" Then
                Set OutMail = OutApp.CreateItem(0)
                With OutMail
                    .Attachments.Add Cells(2, 5) & cell.Offset(0, 2) & ".xlsx"
                    .To = cell.Value
                    .Subject = Cells(cell.Row, "I").Value
                    .Body = Cells(cell.Row, "D").Value
                    .Send  'Or use Send us Display
                End With
                Set OutMail = Nothing
        End If
    Next cell

    Set OutApp = Nothing
    Set Addresslist = Nothing
    Application.ScreenUpdating = True
   
    MsgBox "Game over"
   
End Sub

Cho em hỏi làm thế nào để em chèn thêm chữ ký khi gửi mail hàng loạt (Tên chữ ký mặc định trong outlook em đặt là "Ky chung")
 
Upvote 0
PHP:
Option Explicit
Sub SendMail()
    Dim OutApp As Object
    Dim OutMail As Object
    Dim cell As Range
    Dim i As Long
    Dim Addresslist As Object
    Application.ScreenUpdating = False
    Set Addresslist = CreateObject("Scripting.Dictionary")

    Set OutApp = CreateObject("Outlook.Application")
    OutApp.Session.Logon
  
    For Each cell In Columns("C").Cells.SpecialCells(xlCellTypeConstants)
        If cell.Value Like "?*@?*.?*" And LCase(Cells(cell.Row, "F").Value) = "y" Then
                Set OutMail = OutApp.CreateItem(0)
                With OutMail
                    .Attachments.Add Cells(2, 5) & cell.Offset(0, 2) & ".xlsx"
                    .To = cell.Value
                    .Subject = Cells(cell.Row, "I").Value
                    .Body = Cells(cell.Row, "D").Value
                    .Send  'Or use Send us Display
                End With
                Set OutMail = Nothing
        End If
    Next cell

    Set OutApp = Nothing
    Set Addresslist = Nothing
    Application.ScreenUpdating = True
  
    MsgBox "Game over"
  
End Sub

Cho em hỏi làm thế nào để em chèn thêm chữ ký khi gửi mail hàng loạt (Tên chữ ký mặc định trong outlook em đặt là "Ky chung")
Bạn xóa cái code body đi.
Hoặc là bạn tạo chữ ký trong cells rồi gọi vào.
 
Upvote 0
Web KT

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

Back
Top Bottom