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:
Upvote 0
Sub locdulieu()
Sheets(1).Range("A1" & lastcolumn & lastRow).AutoFilter Field:=3, Criteria1:="活动优惠"
lastRow = Range("A85536").End(xlUp).Row
If Sheets("活动优惠").Cells(1, 1) = "" Then
Range("A1:I" & lastRow).Select
Selection.Copy
Sheets("活动优惠").Select
Range("A1").Select
ActiveSheet.Paste
Columns("A:H").Select
Columns("A:H").EntireColumn.AutoFit
Else
Range("A2:I" & lastRow).Select
Selection.Copy
Sheets("活动优惠").Select
lastRow = Range("A85536").End(xlUp).Row
Range("A" & lastRow + 1).Select
ActiveSheet.Paste
Columns("A:H").Select
Columns("A:H").EntireColumn.AutoFit
End If
astRow = Range("A85536").End(xlUp).Row
Range("A" & lastRow + 1).Select
Sheets(1).Select
Trong code có đoạn nào nói về đường lưỡi bò không vậy bạn?
 
Upvote 0
mong mn giúp đỡ
Bài đã được tự động gộp:

Sub locdulieu()

Sheets(1).Range("A1" & lastcolumn & lastRow).AutoFilter Field:=3, Criteria1:="tangthuong"
lastRow = Range("A85536").End(xlUp).Row
If Sheets("tangthuong").Cells(1, 1) = "" Then
Range("A1:I" & lastRow).Select
Selection.Copy
Sheets("tangthuong").Select
Range("A1").Select
ActiveSheet.Paste
Columns("A:H").Select
Columns("A:H").EntireColumn.AutoFit
Else

Range("A2:I" & lastRow).Select
Selection.Copy
Sheets("tangthuong").Select
lastRow = Range("A85536").End(xlUp).Row
Range("A" & lastRow + 1).Select
ActiveSheet.Paste
Columns("A:H").Select
Columns("A:H").EntireColumn.AutoFit
End If
lastRow = Range("A85536").End(xlUp).Row
Range("A" & lastRow + 1).Select
Sheets(1).Select

mọi người cho hỏi là trong đoạn code này dùng AutoFilter để lọc dữ liệu nhưng khi lọc không có kêt quả nó lại copy ngay dòng tiêu đề để paste ,vậy mn cho hỏi là code sửa ntn để khi autofilter mà không ra kết quả như thế này View attachment 237539 thì sẽ không copy nữa mà thực hiện lệnh tiếp theo của đoạn code sau ah?
mong mn giúp đỡ
 
Upvote 0
Tôi chưa từng biết Sub Mẹ Sub, Con viết như Bác @VetMini gợi ý.
Làm liều thử 1 bài xem, nếu có người sửa sai thì sẽ là 1 cách học "Chiêu" mới.
PHP:
Public Sub Cha()
Dim I As Long, J As Long, X As Long
    For I = 1 To 10
        X = X + 1           'Cong Viec 1- Lam gi do'
        For J = 1 To 10  
            Cells(X, J) = "GPE" & Format(I, "000")
        Next J
        X = X + 1
        GoSub Con           'Goi Sub Con'
            X = X + 1       'Cong Viec 2 - Lam gi do'
            For J = 1 To 10
                Cells(X, J) = "Hic!" & Format(I, "000")
            Next J
        X = X + 1
        GoSub Con           'Goi Sub Con'
    Next I
    Exit Sub    'Thoat Sub Cha'
Con:            'Sub Con Lam gi do'
        For J = 1 To 10
            Cells(X, J) = "Con" & " - " & Format(J, "000")
        Next J
Return  'Quay lai dong lenh sau GoSub'
End Sub

Mục đích chính của GoSub là để tránh lặp lại code.
Nếu công việc 1 và công việc 2 gần giống nhau thì bạn cũng có thể tạo một sub con nữa.
Lưu ý rằng hai công việc có các lệnh giống nhau nhưng thong số khác nhau cho nên ta phải dùng một biến để thực hiện thông số này (biến danDau trong code).

PHP:
Public Sub Cha()
Dim I As Long, J As Long, X As Long
DIM daDau As String
    For I = 1 To 10
      ' công việc 1, làm gì đó '
      danDau = "GPE"
      GoSub Con_Ruot
      danDau = "Con - "
      GoSub Con_Ghe
      ' công việc 2, làm gì đó '
      danDau = "Hic!"
      GoSub Con_Ruot
      danDau = "Con - "
      GoSub Con_Ghe
    Next I
    Exit Sub    'Thoat Sub Cha'

Con_Ruot:
        ' công việc 3, làm gì đó '
        ' sau khi hoàn tất công việc 3, gọi sub Con_Ghe để thực hiện việc tăng X và ghi trị vào 10 cells '
        GoSub Con_Ghe
Return

Con_Ghe:            'Sub Con Lam gi do'
        X = X + 1
        For J = 1 To 10
            Cells(X, J) = danDau & Format(J, "000")
        Next J
Return
End Sub

Code trên tôi cố tình cho thấy Con_Ruot có thể gọi Con_Ghe vô tư.
(ngược lại, Con_Ghe có thể gọi Con_Ruot nếu muốn)
 
Upvote 0
Mục đích chính của GoSub là để tránh lặp lại code.
Nếu công việc 1 và công việc 2 gần giống nhau thì bạn cũng có thể tạo một sub con nữa.
Lưu ý rằng hai công việc có các lệnh giống nhau nhưng thong số khác nhau cho nên ta phải dùng một biến để thực hiện thông số này (biến danDau trong code).

PHP:
Public Sub Cha()
Dim I As Long, J As Long, X As Long
DIM daDau As String
    For I = 1 To 10
      ' công việc 1, làm gì đó
      danDau = "GPE"
      GoSub Con_Ruot
      danDau = "Con - "
      GoSub Con_Ghe
      ' công việc 2, làm gì đó
      danDau = "Hic!"
      GoSub Con_Ruot
      danDau = "Con - "
      GoSub Con_Ghe
    Next I
    Exit Sub    'Thoat Sub Cha'

Con_Ruot:
        ' công việc 3, làm gì đó
        ' sau khi hoàn tất công việc 3, gọi sub Con_Ghe để thực hiện việc tăng X và ghi trị vào 10 cells
        GoSub Con_Ghe           'Goi Sub Con'
Return

Con_Ghe:            'Sub Con Lam gi do'
        X = X + 1
        For J = 1 To 10
            Cells(X, J) = danDau & Format(J, "000")
        Next J
Return
End Sub

Code trên tôi cố tình cho thấy Con_Ruot có thể gọi Con_Ghe vô tư.
(ngược lại, Con_Ghe có thể gọi Con_Ruot nếu muốn)
Bác cứ phức tạp vấn đề, cứ chia ra sub con riêng cho nhanh, và như thế thỏa mãi số con mà không rối... còn truyền biến thì độc lập hay phụ thuộc cũng tùy thích

GoSub đúng như bác nói người ta hạn chế dùng, nếu dùng dùng cho trường hợp đặc biệt hay vui mà thôi
 
Upvote 0
Bác cứ phức tạp vấn đề, cứ chia ra sub con riêng cho nhanh, và như thế thỏa mãi số con mà không rối... còn truyền biến thì độc lập hay phụ thuộc cũng tùy thích

GoSub đúng như bác nói người ta hạn chế dùng, nếu dùng dùng cho trường hợp đặc biệt hay vui mà thôi
Sẵn đề tài ở bài #2724, Tôi chỉ dẫn dắt về một kỹ thuật code mà nó gần sát nhất với yêu cầu củab bài.

Vì là dẫn dắt cho nên tôi thêm hoa lá cành cho nó hơi phức tạp một chút. Chứ đơn giản quá thì chả có mấy để học.

Trước khi vào, tôi cũng có nói rằng Go<...> là kỹ thuật phi cấu trúc (non-structred). Chính bản thân tôi cũng không thích dùng.
Nhất là khi Sub con dựa vào nhiều thông số và thay đổi nhiều biến, rất khó kiểm soát và debug.

Nhưng nếu tôn chỉ của diễn đàn này là tốc độ code thì Go<...> là con đường đáng bỏ tâm nghiên cứu.
Code phi cấu trúc thường chạy nhanh hơn. GoSub là lệnh rẽ nhánh lập tức, VBA chỉ phải nhét ngăn xếp cái địa chỉ để 'Return'. Nếu gọi hàm riêng biệt thì VBA phải nhét ngăn xếp nhiều thứ nữa. Đồng thời, vì không phải dùng ngăn xếp nhiều nên dệ quy cũng lâu bị tràn ngăn xếp hơn.
 
Upvote 0
Xin chào tất cả mọi mọi người,
OT có một vấn đề như sau:
Làm thế nào để từ bảng 1 chuyển sang bảng 2 thay đổi định dạng.
Cột A -> F (Long-> String)
Cột B -> G (Stirng -> Long)
OT đã code một đoạn sau để thử nhưng không được:
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = CStr(Vao(I, 1))
       Ra(I, 2) = CLng(Vao(I, 2))
       Ra(I, 3) = Ra(I, 1) + Ra(I, 2)
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub

Nhờ các Bạn chỉ dẫn cho cách làm ạ.

Untitled.jpg
 

File đính kèm

  • LongString.xlsx
    11.7 KB · Đọc: 8
Lần chỉnh sửa cuối:
Upvote 0
Xin chào tất cả mọi mọi người,
OT có một vấn đề như sau:

OT đã code một đoạn sau để thử nhưng không được:
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = CStr(Vao(I, 1))
       Ra(I, 2) = CLng(Vao(I, 2))
       Ra(I, 3) = Ra(I, 1) + Ra(I, 2)
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub

Nhờ các Bạn chỉ dẫn cho cách làm ạ.

View attachment 237625

Hình như cả CStr & CLng đều không có tác dụng trong trường hợp này ạ?
Nếu làm như thế này thì lại được:
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = "'" & Vao(I, 1)
       Ra(I, 2) = Vao(I, 2)
       Ra(I, 3) = "=SUM(RC[-2]:RC[-1])"
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub
Có cách làm khác không ạ?
 
Upvote 0
Hình như cả CStr & CLng đều không có tác dụng trong trường hợp này ạ?
Nếu làm như thế này thì lại được:
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = "'" & Vao(I, 1)
       Ra(I, 2) = Vao(I, 2)
       Ra(I, 3) = "=SUM(RC[-2]:RC[-1])"
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub
Có cách làm khác không ạ?
Chưa thử nhưng dùng lệnh clear xóa vùng ("F3").resize... trước khi điền xuống sheet xem.
 
Upvote 0
Chưa thử nhưng dùng lệnh clear xóa vùng ("F3").resize... trước khi điền xuống sheet xem.
Xin chào CHAOQUAY
Dạ thì kết quả nó trả về giống Bảng 2 như ảnh trong bài 2489 theo ý muốn của OT đó Bạn.
Vấn đề là ở đây OT muốn hỏi xem có cách nào chuyển kiểu số sang kiểu text hoặc ngược lại trong mảng không ạ, nhưng mà với trường hợp của OT hình như cứ đưa số định dạng text vào mảng là nó chuyển thành số hay sao ấy,, híc!
'-------------------------------------
Ah nó có dấu ' ở đầu Bạn ơi...
 
Lần chỉnh sửa cuối:
Upvote 0
Xin chào CHAOQUAY
Dạ thì kết quả nó trả về giống Bảng 2 như ảnh trong bài 2489 theo ý muốn của OT đó Bạn.
Vấn đề là ở đây OT muốn hỏi xem có cách nào chuyển kiểu số sang kiểu text hoặc ngược lại trong mảng không ạ, nhưng mà với trường hợp của OT hình như cứ đưa số định dạng text vào mảng là nó chuyển thành số hay sao ấy,, híc!
'-------------------------------------
Ah nó có dấu ' ở đầu Bạn ơi...
bạn thử khai báo
dim Ra() as string xem
 
Upvote 0
bạn thử khai báo
dim Ra() as string xem
Dạ , nếu làm thế này thì cả mảng Ra thàn chuỗi hết ạ, kết quả trả về không chỉ riêng cột F là chuỗi mà cả G & H cũng thành chuỗi theo luôn.
Có cách nào vẫn xử lý trong cùng mảng được không Bạn?
 
Upvote 0
Dạ , nếu làm thế này thì cả mảng Ra thàn chuỗi hết ạ, kết quả trả về không chỉ riêng cột F là chuỗi mà cả G & H cũng thành chuỗi theo luôn.
Có cách nào vẫn xử lý trong cùng mảng được không Bạn?
Thường là mảng chỉ khai báo theo một kiểu, nếu vậy bạn tách mảng Ra() thành 1 vài mảng có kiểu khác nhau xem sao.
Bài đã được tự động gộp:

Xóa format của vùng điền kết quả trong sheet cũng cần quan tâm đó bạn
 
Upvote 0
Dạ , nếu làm thế này thì cả mảng Ra thàn chuỗi hết ạ, kết quả trả về không chỉ riêng cột F là chuỗi mà cả G & H cũng thành chuỗi theo luôn.
Có cách nào vẫn xử lý trong cùng mảng được không Bạn?
Tự động chuyển đổi kiểu là một đặc điểm của VBA. Khi bạn đã biết 1 cột là text, 1 cột là number thì tốt nhất đừng cộng vào nhau để tránh ra kết quả không mong muốn. Phép tính trên sheet và VBA cũng có thể khác nhau, chẳng hạn trong VBA "1"+"1"="11" (bạn nhập ?"1"+"1" trong cửa sổ immediate sẽ thấy kết quả là 11) nhưng trên sheet thì "1"+"1"=2 (bạn nhập công thức A1 ="1"+"1" kết quả là 2). Do đó trước khi làm phép tính thì bạn cần tự quyết định các toán hạng trong phép tính là số hay chuỗi và đừng mong chờ VBA chuyển đổi đúng ý mình. Nếu trong VBA mà ta cần cộng nhiều ô trên sheet và chỉ cộng các số, bỏ qua text thì có thể dùng Application.Sum để tính.
 
Upvote 0
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = CStr(Vao(I, 1))
       Ra(I, 2) = CLng(Vao(I, 2))
       Ra(I, 3) = Ra(I, 1) + Ra(I, 2)
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub

Thực ra là theo cách trên đổi kiểu dữ liệu trong mảng là được nhưng khi gán xuống Sheet thì không như ý. Vấn đề này thì anh chưa biết nguyên nhân của nó.
Đối với code trên anh nghĩ không cần tạo thêm mảng Ra(), chuyển đổi luôn trong mảng Vao() cũng được (thay chữ "Ra" -> "Vao" xem thử) . Anh test với Typename thì thấy ra đúng kiểu dữ liệu cần chuyển, chỉ gán xuống Sheet là lỗi.
Chờ các bạn nào biết giải thích thêm để học hỏi vụ này.
 
Upvote 0
Thực ra là theo cách trên đổi kiểu dữ liệu trong mảng là được nhưng khi gán xuống Sheet thì không như ý. Vấn đề này thì anh chưa biết nguyên nhân của nó.
Đối với code trên anh nghĩ không cần tạo thêm mảng Ra(), chuyển đổi luôn trong mảng Vao() cũng được (thay chữ "Ra" -> "Vao" xem thử) . Anh test với Typename thì thấy ra đúng kiểu dữ liệu cần chuyển, chỉ gán xuống Sheet là lỗi.
Chờ các bạn nào biết giải thích thêm để học hỏi vụ này.

Đúng rồi anh, trong mảng thì không vấn đề gì nhưng khi đưa xuống sheet thì thay đổi do đó phải thêm dòng code: NumberFormat trước khi đưa dữ liệu xuống sheet anh ạ.
OT cũng đang chờ một giải pháp khác ạ.
Cảm ơn anh đã thông tin ạ
 
Upvote 0
Xin chào tất cả mọi mọi người,
OT có một vấn đề như sau:

OT đã code một đoạn sau để thử nhưng không được:
Mã:
Option Explicit

Sub Test_String_And_Long()
    Dim Vao(), Ra(), I As Long
    Vao = Sheet1.Range("A3:C12").Value
    ReDim Ra(1 To UBound(Vao, 1), 1 To UBound(Vao, 2))
    For I = 1 To UBound(Vao, 1)
       Ra(I, 1) = CStr(Vao(I, 1))
       Ra(I, 2) = CLng(Vao(I, 2))
       Ra(I, 3) = Ra(I, 1) + Ra(I, 2)
    Next I
    Sheet1.Range("F3").Resize(UBound(Ra, 1), UBound(Ra, 2)) = Ra
End Sub

Nhờ các Bạn chỉ dẫn cho cách làm ạ.

View attachment 237625
Khai báo 1 mảng vào 2 mảng Ra
Dim Vao(), Ra() as string, Ra2() as long
Hoặc
Dim Vao(), Ra() as string, Ra2()
 
Upvote 0
mn cho hỏi là trong diễn đang mình có ai sử dụng bộ soạn thảo wps không ah? vì mình thấy giữa mrs và wps khi chạy vba thì có một số không tương đồng về cách viết code
 
Upvote 0
Web KT
Back
Top Bottom