Hỏi đáp về VBA (các vấn đề căn bản nhất) (2 người xem)

Liên hệ QC

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

havietchuong

Thành viên tiêu biểu
Tham gia
16/6/09
Bài viết
490
Được thích
570
Giới tính
Nam
Nghề nghiệp
Giáo viên tiểu học.
Tôi không biết đặt đặt câu hỏi này nơi nào cho đúng, xin gởi vào đây. Nếu có sai xin thông cảm cho người mới học VBA.
Trong 1 cửa sổ Module có thể ghi nhiều nhiều Macro và mỗi macro có thể ứng với 1 tổ hợp phím nào đó được không?
Tôi thử nhiều lần thì khi được khi không. Không biết nó thế nào? Trong tập tin sau có lỗi gì không trong cách ghi Macro? Cám ơn.
 

File đính kèm

Lần chỉnh sửa cuối:
Em tập viết một ví dụ để kiểm tra một range, Nếu
- Range <> "" và
-Có chiều dài < 5 Thì

Nối "HP/TM/V/C/" vào arr

Em test thấy báo lỗi dòng này

Sheet3.Range("H3:H" & K).Value = "HP/TM/V/C/" & arr

XIn chỉ giúp em

Bạn sai một cách cơ bản. Lẽ ra phải xử lý, nối chuỗi trong mảng trước rồi mới gán xuống sheet, bạn lại vừa gán với sheet lại ghép vào cùng với mảng, như thế sẽ không phù hợp.

Tạm sửa lại như sau:

Mã:
Sub add()
    Dim sArr, Arr, i As Long
    Sheet3.Range("H:H").ClearContents
    sArr = Range(Sheet3.Range("A1"), Sheet3.Range("A65536").End(xlUp)).Value
    ReDim Arr(1 To UBound(sArr, 1), 1 To 1)
    For i = 1 To UBound(sArr, 1)
        If sArr(i, 1) <> vbNullString And Len(sArr(i, 1)) < 5 Then
            [COLOR=#ff0000][B]Arr(i, 1) = "HP/TM/V/C/" & sArr(i, 1)[/B][/COLOR]
        Else
            Arr(i, 1) = sArr(i, 1)
        End If
    Next
    Sheet3.Range("H1").Resize(UBound(Arr, 1), 1).Value = Arr
End Sub

Lấy dữ liệu tại cột A và gán vào cột H cho dễ nhận thấy trước đi.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Đầu tiên em làm thử với range thì em làm
PHP:
For each clls in range...
             if clls.value <> "" and len(clls) < 5 then
                 cells = "HP/TM/V/C/" & cells

           End if

Next

Qua đoạn code trên em học thêm là
trong mảng "" phải thay bằng vbnulstring và

Cám ơn Anh Minh Thiên nhé
 
Upvote 0
Qua đoạn code trên em học thêm là
trong mảng "" phải thay bằng vbnulstring và

Cám ơn Anh Minh Thiên nhé
Hổng phải vậy đâu, viết vb.. gì gì đó hay = "" đâu có sao
Vấn đề của bạn là triển khai thuật toán không đúng là thôi ---> Vầy đây:
- Duyệt qua từng phần tử
- Xét điều kiện và nạp giá trị và mảng
- Hết vòng lập mới gán mảng xuống Range (đàng này bạn lại gán giá trị xuống range ngay trong vòng lập)
===> Như minhthien đã nói: Chỉ là sai về cơ bản
 
Upvote 0
Đầu tiên em làm thử với range thì em làm
PHP:
For each clls in range...
             if clls.value <> "" and len(clls) < 5 then
                 cells = "HP/TM/V/C/" & cells

           End if

Next

Qua đoạn code trên em học thêm là
trong mảng "" phải thay bằng vbnulstring và

Cám ơn Anh Minh Thiên nhé

Có những cách viết tương đương hoặc bằng nhau, như:

1) vbNullString = ""

2) Sheet3.Range("H1") = Sheet3.[H1]

3) vbNewLine = Chr(10) = Chr(13)

4) If A = B Then MsgBox "A = B" sẽ tương đương với:
If A = B Then
MsgBox "A = B"
End If


5) ...

Bạn sai về cấu trúc chứ không phải sai về cách gọi tên. Riêng tôi thích viết dài dòng như vậy để dễ nhớ, dễ thấy vậy thôi.
 
Upvote 0
Tốc độ làm trên mảng thật khủng khiếp. Em test code thấy chạy nhanh thật, đúng là mảng muôn năm
 
Upvote 0
PHP:
Option Base 1
Private Sub Worksheet_Change(ByVal Target As Range)
 Application.ScreenUpdating = False
 On Error GoTo Err
  If Target.Address = "$B$1" And Target.Value <> "" Then
        
        Dim Arr(), SArr, lRow As Long, lR As Long, item, sh As Worksheet, KQ
        Sheet5.Range("A5:J65000").ClearContents
        With CreateObject("Scripting.Dictionary")
        
        For Each sh In Worksheets
            If Left(sh.Name, 2) <> "RP" Then
        
                SArr = sh.Range(sh.[A5], sh.[A65536].End(xlUp)).Resize(, 27).Value
                
                     For lRow = 1 To UBound(SArr, 1)
                        If SArr(lRow, 27) = Target.Value Then
                            item = SArr(lRow, 8) & " " & SArr(lRow, 13)
                          
                                If Not .Exists(item) Then
                                     lR = lR + 1
                                    .Add item, lR
                                    
                                    KQ = Split(item, " ", 2)
                                    ReDim Preserve Arr(1 To UBound(SArr, 1) * 2, 1 To 4)
                                    Arr(lR, 1) = KQ(0)
                                    Arr(lR, 3) = KQ(1)
                                    Arr(lR, 4) = -SArr(lRow, 12)
                                Else
                                    Arr(.item(item), 4) = (Arr(.item(item), 4) - SArr(lRow, 12))
                                End If
                        End If
                      Next lRow
                End If
               
            Next sh
           
        End With
        Sheet5.Range("A5").Resize(lR, 4).Value = Arr
        
        dgFCR = Sheet5.[A65000].End(xlUp).Row
        Range("I5:I" & dgFCR).Value = "12040"
        Range("J5:J" & dgFCR).Value = "VNHPH"
  End If
  
  
Err:
Application.ScreenUpdating = True
End Sub

Trong đoạn code trên em chưa hiểu chỗ này, chỉ giúp em nhé

ReDim Preserve Arr(1 To UBound(SArr, 1) * 2, 1 To 4)
 
Upvote 0
Khi ReDim thì sẽ mất tất cả dữ liệu chứa trong mảng đó, nhưng khi ReDim Preserve thì sẽ giữ lại dữ liệu còn tồn tại trên mảng.
 
Upvote 0
Thêm 1 chút với Kyo: Redim Preserve không áp dụng được cho chiều 1 mà chỉ có thể áp dụng thay đổi chiều thứ 2 trở đi của mảng nếu là mảng đa chiều
 
Upvote 0
Tôi hỏi mong mọi người đừng chê cười, vì tôi mới tập nên đọc thấy nhiều cái mới quá, chưa đủ khả năng phân tích nhiều vấn đề

Tôi thấy nhiều phương thức ví dụ như sau:

PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)

End Sub

PHP:
Function DienGiai(FVal, FindRng As Range, RestRng As Range) As String
  Dim i As Long, j As Long, Temp, Arr(), Dic1, Dic2
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  For i = 1 To FindRng.Rows.Count
    If FindRng(i, 1) = FVal Then
      Temp = RestRng(i, 1)
      If Not Dic1.Exists(Temp) Then
        j = j + 1
        Dic1.Add Temp, 1
        Dic2.Add Temp, j
      Else
        Dic1.Item(Temp) = Dic1.Item(Temp) + 1
      End If
      ReDim Preserve Arr(1 To j)
      Arr(Dic2.Item(Temp)) = Temp & "(" & Dic1.Item(Temp) & ")"
    End If
  Next
  DienGiai = Join(Arr, ", ")
End Function
...................
Tôi thắc mắc là những cụm từ bôi đỏ trong dấu ngoặc trong những cụm từ sau: (ByVal Target As Range), ]Function DienGiai(FVal, FindRng As Range, RestRng As Range) As String thì có thể người dùng tự thay đổi thành chữ khác được không? Hay những từ này bắt buộc phải thế
(Đôi khi tôi có Test thử thay đổi thấy bị lỗi)

Bởi đến bây giờ tôi vẫn lúng túng không biết những từ nào do chương trình định nghĩa "cứng", kiểu như là từ khóa vậy, nghĩa là không thay đổi được. Bởi thi thoảng khi viết Code những từ màu xanh thì dễ nhận biết rồi, còn những từ khác nhưng tôi thấy một số kí tự của chương trình khác vẫn để màu chữ đen như các biến khác do người đọc định nghĩa


Xin vô cùng cảm tạ
 
Upvote 0
Tôi hỏi mong mọi người đừng chê cười, vì tôi mới tập nên đọc thấy nhiều cái mới quá, chưa đủ khả năng phân tích nhiều vấn đề

Tôi thấy nhiều phương thức ví dụ như sau:

PHP:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)

End Sub

PHP:
Function DienGiai(FVal, FindRng As Range, RestRng As Range) As String
  Dim i As Long, j As Long, Temp, Arr(), Dic1, Dic2
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  For i = 1 To FindRng.Rows.Count
    If FindRng(i, 1) = FVal Then
      Temp = RestRng(i, 1)
      If Not Dic1.Exists(Temp) Then
        j = j + 1
        Dic1.Add Temp, 1
        Dic2.Add Temp, j
      Else
        Dic1.Item(Temp) = Dic1.Item(Temp) + 1
      End If
      ReDim Preserve Arr(1 To j)
      Arr(Dic2.Item(Temp)) = Temp & "(" & Dic1.Item(Temp) & ")"
    End If
  Next
  DienGiai = Join(Arr, ", ")
End Function
...................
Tôi thắc mắc là những cụm từ bôi đỏ trong dấu ngoặc trong những cụm từ sau: (ByVal Target As Range), ]Function DienGiai(FVal, FindRng As Range, RestRng As Range) As String thì có thể người dùng tự thay đổi thành chữ khác được không? Hay những từ này bắt buộc phải thế
(Đôi khi tôi có Test thử thay đổi thấy bị lỗi)

Bởi đến bây giờ tôi vẫn lúng túng không biết những từ nào do chương trình định nghĩa "cứng", kiểu như là từ khóa vậy, nghĩa là không thay đổi được. Bởi thi thoảng khi viết Code những từ màu xanh thì dễ nhận biết rồi, còn những từ khác nhưng tôi thấy một số kí tự của chương trình khác vẫn để màu chữ đen như các biến khác do người đọc định nghĩa


Xin vô cùng cảm tạ

ByVal, Function, As Range, As String là những từ khóa không được thay đổi, thông thường thì nó sẽ chuyển thành màu xanh và nếu bạn đánh không đúng thì chương trình sẽ báo lỗi. Đôi khi có một vài chỗ thì có chữ đen chẳng hạn như scripting.dictionary, nhưng theo mình thì cái đó thuộc về kinh nghiệm rồi, bạn làm quen bạn sẽ khắc biết thôi
 
Upvote 0
Tôi vẫn loay hoay đi tìm kiếm phương pháp học VBA, nhìn trên diễn đàn thấy mọi người siêu quá, bản thân tôi rất thích nghiên cứu mấy cái vụ này. Xin được phép hỏi thêm 1 chút:
Tôi thắc mắc là trong cửa sổ VBA liệu có cách gì để biết được một từ hoặc cụm từ đó có nằm trong ngôn ngữ của nó không? Ví dụ các từ vbBack, Replace...làm sao biết được chúng có có thể được sử dụng trong VBA, tức là ta tra cứu nó ở đâu để có thể dùng được.

PHP:
Function DienGiai(FVal, FindRng As Range, RestRng As Range) As String
    Dim sRet As String, sTemp As String, iRun As Long, iPos As Long, iOpenPos As Long, iClosePos As Long
    For iRun = 1 To FindRng.Rows.Count
        If FindRng(iRun, 1) = FVal Then
            sTemp = RestRng(iRun, 1)
            iPos = InStr(1, sRet, vbBack & sTemp & vbBack)
            If iPos = 0 Then
                sRet = sRet & vbBack & sTemp & vbBack & "(1),"
            Else
                iOpenPos = InStr(iPos, sRet, "(")
                iClosePos = InStr(iOpenPos, sRet, ")")
                sRet = Left(sRet, iOpenPos) & (Mid(sRet, iOpenPos + 1, iClosePos - iOpenPos - 1) + 1) & Mid(sRet, iClosePos)
            End If
        End If
    Next
    DienGiai = Replace(Left(sRet, Len(sRet) - 1), vbBack, "")
End Function

Vì còn bỡ ngỡ, xin kính mong sự chỉ bảo.
 
Upvote 0
Tôi vẫn loay hoay đi tìm kiếm phương pháp học VBA, nhìn trên diễn đàn thấy mọi người siêu quá, bản thân tôi rất thích nghiên cứu mấy cái vụ này. Xin được phép hỏi thêm 1 chút:
Tôi thắc mắc là trong cửa sổ VBA liệu có cách gì để biết được một từ hoặc cụm từ đó có nằm trong ngôn ngữ của nó không? Ví dụ các từ vbBack, Replace...làm sao biết được chúng có có thể được sử dụng trong VBA, tức là ta tra cứu nó ở đâu để có thể dùng được.

Trong cửa sổ VBA, bấm F2 sẽ có mọi thứ bạn cần
Hoặc bạn cũng có thể bôi đen từ cần tìm hiểu rồi bấm F1 xem Help
 
Upvote 0
Các bác chỉ giúp em hàm InStr cách dùng thế nào? Em tìm mãi mà không có.
 
Upvote 0
Các bác chỉ giúp em hàm InStr cách dùng thế nào? Em tìm mãi mà không có.
Bạn nhấn Alt+F11 để mở cửa số VBE, nhấn Ctrl+G (hoặc chèn 1 module cũng được), gõ InStr --> Chọn từ này và nhấn F1, bạn sẽ nhận được sự trợ giúp về hàm này.
Về công dụng, hàm này tương tự hàm FIND của Excel, được sử dụng để tìm vị trí xuất hiện của một chuỗi trong một chuỗi khác (có phân biệt chữ hoa, chữ thường)
Cách dùng phổ biến nhất của hàm này là InStr(Chuỗi gốc, Chuỗi cần tìm). Nếu có Chuỗi cần tìm ở trong Chuỗi gốc thì hàm sẽ trả về vị trí đầu tiên tìm thấy, ngược lại thì hàm trả về 0 (khác với hàm FIND của Excel một xíu, nếu không tìm thấy thì phát sinh lỗi #N/A).
 
Upvote 0
Cách dùng Hàm Vlookup trong VBA

Trong Excel muốn dò tìm dữ liệu từ sheet này sang sheet khác thì dùng hàm Dò tìm còn trong VBA mình làm như thế nào?, mong các Anh/Chị chỉ giáo.
Thanks
 

File đính kèm

Upvote 0
Trường hợp này có rất nhiều nhiều cách mình xin lấy đại 1 cách nào đó đi mình dùng Find tìm kiếm rồi ghi dữ liệu vào bạn có thể phát triển thêm đặt biệt bạn thích tìm hiểu về Array thì Các câu hỏi về mảng trong VBA (Array) vào đó nhen
Mã:
Sub Timkiem()
Dim DMHH As Range, KQ As Range, clls As Range
With Sheets("DM-KH")
Set DMHH = .Range("A2:A" & .Range("A65000").End(xlUp).Row)
End With
For Each clls In Sheets("BC").Range("A2:A12")
    Set KQ = DMHH.Find(clls.Value, , xlValues, xlWhole, xlByRows, xlNext, , , False)
        If KQ Is Nothing Then
            clls.Offset(, 1).Value = ""
            clls.Offset(, 2).Value = ""
        Else
            clls.Offset(, 1).Value = KQ.Offset(, 2).Value
            clls.Offset(, 2).Value = KQ.Offset(, 3).Value
        End If
Next
End Sub
 
Upvote 0
Em định tất cả các Sheet khi giới hạn vùng in phần có dữ liệu thôi thì Code này của em phải sửa thế nào ah?
PHP:
Sub Thuoc_tinh()
Dim wS As Worksheet
For Each wS In ThisWorkbook.Worksheets
wS.Select
wS.PageSetup.PrintArea = Range(wS.[A5], wS.[A65000].End(xlUp)).Resize(, 10)
Next
End Sub
 
Upvote 0
Nhờ giải thích dùm các dùng phương thức Find trong VBA

Nhờ mọi người giúp em hiểu số 2 trong đoạn sau phản ánh cái gì

PHP:
Set Cll = [B:B].Find("T", [B1], xlValues, 2)
 
Upvote 0
Web KT

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

Back
Top Bottom