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:
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

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
Em xin chào các bác ạ,
Em đang tập tành học VBA và hiện tại đang gặp khó về vấn đề này ạ.
Cụ thể là em có 1 file với số tiền phải chi cho người lao động thuộc các cụm, dữ liệu mỗi cụm cách nhau bởi 1 dòng trống.
Em muốn viết 1 code tự tìm dòng cuối của 1 cụm sau đó, xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) của cụm đó vào ô trống của dòng "cuối +1". Sau đó tiếp tục tìm đến dòng cuối của cụm thứ 2 và xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) chỉ của cụm thứ 2 vào ô trống của dòng "cuối +1". Cứ thế lặp lại cho đến khi hết dữ liệu.
Hiện tại em chỉ viết được code cho 1 cụm và ko biết viết vòng lặp như thế nào ạ.
Mã:
Sub TinhTong()

    Sheet1.Activate
    Dim Lr As Long
    Dim i As Long

    ' Lay dong cuoi
    Lr = Sheet1.Range("G1").End(xlDown).Row
    i = Lr + 1
    
    ' To dam o dong cuoi +1
    Rows(i).Select
    Selection.ClearContents
    Selection.Font.Bold = True
    
    ' Tinh tong o dong cuoi +1
    Dim Rng As Range
    Dim c As Range
    Set Rng = Range("G1:G" & Lr)
    Set c = Range("G1").End(xlDown).Offset(1, 0)
    c.Formula = "=SUM(" & Rng.Address(False, False) & ")"
    
End Sub
Kính mong các bác xem giúp em file ạ.
Em xin chân thành cám ơn các bác ạ.
 

File đính kèm

Upvote 0
Em xin chào các bác ạ,
Em đang tập tành học VBA và hiện tại đang gặp khó về vấn đề này ạ.
Cụ thể là em có 1 file với số tiền phải chi cho người lao động thuộc các cụm, dữ liệu mỗi cụm cách nhau bởi 1 dòng trống.
Em muốn viết 1 code tự tìm dòng cuối của 1 cụm sau đó, xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) của cụm đó vào ô trống của dòng "cuối +1". Sau đó tiếp tục tìm đến dòng cuối của cụm thứ 2 và xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) chỉ của cụm thứ 2 vào ô trống của dòng "cuối +1". Cứ thế lặp lại cho đến khi hết dữ liệu.
Hiện tại em chỉ viết được code cho 1 cụm và ko biết viết vòng lặp như thế nào ạ.
Mã:
Sub TinhTong()

    Sheet1.Activate
    Dim Lr As Long
    Dim i As Long

    ' Lay dong cuoi
    Lr = Sheet1.Range("G1").End(xlDown).Row
    i = Lr + 1
   
    ' To dam o dong cuoi +1
    Rows(i).Select
    Selection.ClearContents
    Selection.Font.Bold = True
   
    ' Tinh tong o dong cuoi +1
    Dim Rng As Range
    Dim c As Range
    Set Rng = Range("G1:G" & Lr)
    Set c = Range("G1").End(xlDown).Offset(1, 0)
    c.Formula = "=SUM(" & Rng.Address(False, False) & ")"
   
End Sub
Kính mong các bác xem giúp em file ạ.
Em xin chân thành cám ơn các bác ạ.
Không biết đúng ý bạn không nhưng thử test code xem.
Mã:
Sub GPE()
Dim rLast As Long, Rng As Range, sCell As Range
    With Sheet1
        rLast = .Range("G1000000").End(xlUp).Row
        Set Rng = .Range("G1:G" & rLast).SpecialCells(xlCellTypeConstants, 1)
        For Each sCell In Rng.Areas
            sCell.Cells(1, 1).Offset(sCell.Rows.Count).Formula = "=SUM(" & sCell.Address(0, 0) & ")"
        Next sCell
    End With
End Sub
 
Upvote 0
Không biết đúng ý bạn không nhưng thử test code xem.
Mã:
Sub GPE()
Dim rLast As Long, Rng As Range, sCell As Range
    With Sheet1
        rLast = .Range("G1000000").End(xlUp).Row
        Set Rng = .Range("G1:G" & rLast).SpecialCells(xlCellTypeConstants, 1)
        For Each sCell In Rng.Areas
            sCell.Cells(1, 1).Offset(sCell.Rows.Count).Formula = "=SUM(" & sCell.Address(0, 0) & ")"
        Next sCell
    End With
End Sub
Quá tuyệt vời bác ạ.
Em xin cảm ơn bác nhiều ạ.
Và em xin mạo muội nhờ bác thêm 1 chút nữa được ko ạ.
Bác có thể thêm vào tác vụ xóa hết dữ liệu của cả dòng mà có chứa ô có hàm tổng, chỉ để lại ô có hàm tổng và đồng thời tô đậm ô đó được ko ạ.
Em xin cảm ơn bác 1 lần nữa ạ.
 
Upvote 0
Quá tuyệt vời bác ạ.
Em xin cảm ơn bác nhiều ạ.
Và em xin mạo muội nhờ bác thêm 1 chút nữa được ko ạ.
Bác có thể thêm vào tác vụ xóa hết dữ liệu của cả dòng mà có chứa ô có hàm tổng, chỉ để lại ô có hàm tổng và đồng thời tô đậm ô đó được ko ạ.
Em xin cảm ơn bác 1 lần nữa ạ.
Sửa code lại chút.
Mã:
Sub GPE()
Dim rLast As Long, Rng As Range, sCell As Range, iRow As Long
    With Sheet1
        rLast = .Range("G1000000").End(xlUp).Row
        .Range("G1:G" & rLast).Font.Bold = False
        Set Rng = .Range("G1:G" & rLast).SpecialCells(xlCellTypeConstants, 1)
        For Each sCell In Rng.Areas
            iRow = sCell.Cells(1, 1).Offset(sCell.Rows.Count).Row
            .Rows(iRow).ClearContents
            .Range("G" & iRow).Formula = "=SUM(" & sCell.Address(0, 0) & ")"
            .Range("G" & iRow).Font.Bold = True
        Next sCell
    End With
End Sub
 
Upvote 0
Em xin chào các bác ạ,
Em đang tập tành học VBA và hiện tại đang gặp khó về vấn đề này ạ.
Cụ thể là em có 1 file với số tiền phải chi cho người lao động thuộc các cụm, dữ liệu mỗi cụm cách nhau bởi 1 dòng trống.
Em muốn viết 1 code tự tìm dòng cuối của 1 cụm sau đó, xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) của cụm đó vào ô trống của dòng "cuối +1". Sau đó tiếp tục tìm đến dòng cuối của cụm thứ 2 và xóa dữ liệu thừa ở dòng "cuối +1" và lấy tổng số tiền (cột G) chỉ của cụm thứ 2 vào ô trống của dòng "cuối +1". Cứ thế lặp lại cho đến khi hết dữ liệu.
Hiện tại em chỉ viết được code cho 1 cụm và ko biết viết vòng lặp như thế nào ạ.
Mã:
Sub TinhTong()

    Sheet1.Activate
    Dim Lr As Long
    Dim i As Long

    ' Lay dong cuoi
    Lr = Sheet1.Range("G1").End(xlDown).Row
    i = Lr + 1
   
    ' To dam o dong cuoi +1
    Rows(i).Select
    Selection.ClearContents
    Selection.Font.Bold = True
   
    ' Tinh tong o dong cuoi +1
    Dim Rng As Range
    Dim c As Range
    Set Rng = Range("G1:G" & Lr)
    Set c = Range("G1").End(xlDown).Offset(1, 0)
    c.Formula = "=SUM(" & Rng.Address(False, False) & ")"
   
End Sub
Kính mong các bác xem giúp em file ạ.
Em xin chân thành cám ơn các bác ạ.
Thêm một cách viết đơn giản.
PHP:
Sub TinhTong2()
Dim Lr As Long, i As Long, k As Long
With Sheet1
    Lr = .Range("G1000").End(xlUp).Row + 1  ' Lay dong trong cuoi'
    For i = 1 To Lr                         'Xet cot G tu dong 1 den dong cuoi'
        k = k + 1                           'Dem so dong'
        If .Range("G" & i).Value = Empty Then           'Neu gap o trong cot G = trong'
            .Range("A" & i).Resize(, 10).ClearContents  'Xoa du lieu tu cot A den cot J'
            .Range("G" & i).Font.Bold = True            'To dam chi mot o cot G'
            .Range("G" & i).Value = "=SUM(R[-" & k - 1 & "]C:R[-1]C)"   'Cong thuc Tong'
            k = 0   'So dem =0, bat dau dem lai'
        End If
    Next i
End With
End Sub
 
Upvote 0
Sửa code lại chút.
Mã:
Sub GPE()
Dim rLast As Long, Rng As Range, sCell As Range, iRow As Long
    With Sheet1
        rLast = .Range("G1000000").End(xlUp).Row
        .Range("G1:G" & rLast).Font.Bold = False
        Set Rng = .Range("G1:G" & rLast).SpecialCells(xlCellTypeConstants, 1)
        For Each sCell In Rng.Areas
            iRow = sCell.Cells(1, 1).Offset(sCell.Rows.Count).Row
            .Rows(iRow).ClearContents
            .Range("G" & iRow).Formula = "=SUM(" & sCell.Address(0, 0) & ")"
            .Range("G" & iRow).Font.Bold = True
        Next sCell
    End With
End Sub
Thêm một cách viết đơn giản.
PHP:
Sub TinhTong2()
Dim Lr As Long, i As Long, k As Long
With Sheet1
    Lr = .Range("G1000").End(xlUp).Row + 1  ' Lay dong trong cuoi'
    For i = 1 To Lr                         'Xet cot G tu dong 1 den dong cuoi'
        k = k + 1                           'Dem so dong'
        If .Range("G" & i).Value = Empty Then           'Neu gap o trong cot G = trong'
            .Range("A" & i).Resize(, 10).ClearContents  'Xoa du lieu tu cot A den cot J'
            .Range("G" & i).Font.Bold = True            'To dam chi mot o cot G'
            .Range("G" & i).Value = "=SUM(R[-" & k - 1 & "]C:R[-1]C)"   'Cong thuc Tong'
            k = 0   'So dem =0, bat dau dem lai'
        End If
    Next i
End With
End Sub
Cám ơn 2 bác nhiều ạ. Code quá tuyệt.
 
Upvote 0
Web KT

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

Back
Top Bottom