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

kokano90

Thành viên chính thức
Tham gia ngày
10 Tháng tám 2019
Bài viết
64
Được thích
17
Điểm
20
Tuổi
30
Nhờ các thầy cô coi giúp em đoạn code dưới đây sai ở đoạn nào với ạ
Mã:
Sub Tach_sheet()
    Dim i%, LR%, Rng As Range, Cll As Range
On Error Resume Next
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each Cll In Rng
    If ActiveSheet.Name = Cll.Value Then
        Exit For
    Else
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = Cll.Value
    End If
Next Cll
End Sub
Mục đích là em muốn copy sheet mẫu và đặt tên sheet được tạo theo giá trị của vùng được chọn.
Nhưng có 1 bất cập là. Chẳng hạn vùng chọn có những giá trị trùng với tên sheet rồi thì bỏ qua. Không tạo thêm nữa mà loay hoay mãi tới giờ chưa ra.
Mong mọi người chỉ giúp với ạ
 

CHAOQUAY

Thành viên tích cực
Tham gia ngày
24 Tháng tám 2018
Bài viết
1,084
Được thích
1,132
Điểm
360
Nhờ các thầy cô coi giúp em đoạn code dưới đây sai ở đoạn nào với ạ
Mã:
Sub Tach_sheet()
    Dim i%, LR%, Rng As Range, Cll As Range
On Error Resume Next
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each Cll In Rng
    If ActiveSheet.Name = Cll.Value Then
        Exit For
    Else
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = Cll.Value
    End If
Next Cll
End Sub
Mục đích là em muốn copy sheet mẫu và đặt tên sheet được tạo theo giá trị của vùng được chọn.
Nhưng có 1 bất cập là. Chẳng hạn vùng chọn có những giá trị trùng với tên sheet rồi thì bỏ qua. Không tạo thêm nữa mà loay hoay mãi tới giờ chưa ra.
Mong mọi người chỉ giúp với ạ
Chạy thử code dưới.
Mã:
Sub Tach_sheet()
    Dim i%, LR%, Rng As Range, Cll As Range
'On Error Resume Next
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each Cll In Rng
    'If ActiveSheet.Name = Cll.Value Then
    If ActiveSheet.Name <> Cll.Value Then
        'Exit For
    'Else
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = Cll.Value
    End If
Next Cll
End Sub
 

kokano90

Thành viên chính thức
Tham gia ngày
10 Tháng tám 2019
Bài viết
64
Được thích
17
Điểm
20
Tuổi
30
Chạy thử code dưới.
Mã:
Sub Tach_sheet()
    Dim i%, LR%, Rng As Range, Cll As Range
'On Error Resume Next
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each Cll In Rng
    'If ActiveSheet.Name = Cll.Value Then
    If ActiveSheet.Name <> Cll.Value Then
        'Exit For
    'Else
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = Cll.Value
    End If
Next Cll
End Sub
1588582528193.png
Cám ơn thầy ạ. Nếu trường hợp nó có tên trùng với vùng chọn rồi. Thì nó báo lỗi. Mà em chưa biết phải làm thế nào.
Ý muốn là nếu có tên rồi thì sẽ bỏ qua. không tạo nữa.
Phiền thầy và mọi người giúp đỡ ạ.
 

snow25

Thành viên gắn bó
Tham gia ngày
24 Tháng bảy 2018
Bài viết
2,566
Được thích
2,439
Điểm
360
View attachment 236819
Cám ơn thầy ạ. Nếu trường hợp nó có tên trùng với vùng chọn rồi. Thì nó báo lỗi. Mà em chưa biết phải làm thế nào.
Ý muốn là nếu có tên rồi thì sẽ bỏ qua. không tạo nữa.
Phiền thầy và mọi người giúp đỡ ạ.
Thử.
Mã:
Sub Tach_sheet()
    Dim i%, LR%, Rng As Range, Cll As Range, sh As Worksheet, s As String
    s = "#"
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each sh In ThisWorkbook.Worksheets
    s = s & UCase(sh.Name) & "#"
Next
For Each Cll In Rng
    If InStr(1, s, "#" & UCase(Cll.Value) & "#") = 0 Then
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = Cll.Value
    End If
Next Cll
End Sub
 

CHAOQUAY

Thành viên tích cực
Tham gia ngày
24 Tháng tám 2018
Bài viết
1,084
Được thích
1,132
Điểm
360
View attachment 236819
Cám ơn thầy ạ. Nếu trường hợp nó có tên trùng với vùng chọn rồi. Thì nó báo lỗi. Mà em chưa biết phải làm thế nào.
Ý muốn là nếu có tên rồi thì sẽ bỏ qua. không tạo nữa.
Phiền thầy và mọi người giúp đỡ ạ.
Thử 1 lần nữa
Mã:
Sub Tach_sheet()
Dim i%, LR%, Rng As Range, Cll As Range
Dim t As Variant
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
With CreateObject("Scripting.Dictionary")
    For Each Cll In Rng
        If Trim(Cll) <> "" Then .Item(Trim(Cll)) = ""
    Next Cll
    'For Each t In ActiveWorkbook.Names
    '    If .exists(t) Then .Remove t
    'Next t

    For Each t In Worksheets
        If .exists(t.Name) Then .Remove t.Name
    Next t
    For Each t In .keys
        Sheet2.Copy after:=Sheets(Sheets.Count)
        ActiveSheet.Name = t
    Next t
End With
End Sub
 
Lần chỉnh sửa cuối:

kokano90

Thành viên chính thức
Tham gia ngày
10 Tháng tám 2019
Bài viết
64
Được thích
17
Điểm
20
Tuổi
30
Cám ơn anh @snow25@CHAOQUAY nhiều nhiều ạ. Code của anh @snow25 thấy chạy ổn ạ
Code anh @CHAOQUAY không hiểu sao nó báo lỗi như hình ảnh trên ạ.1588584201168.png
Có điều em chưa hiểu lắm đoạn
Mã:
For Each t In ActiveWorkbook.Names
        If .exists(t) Then .remove t
    Next t
Tức là duyệt qua tên của từng sheet. nếu cái nào trùng trong key thì loại bỏ ạ.
Nếu anh có thời gian. có thể bớt chút thời gian chỉ cho em hiểu với ạ
 

File đính kèm

CHAOQUAY

Thành viên tích cực
Tham gia ngày
24 Tháng tám 2018
Bài viết
1,084
Được thích
1,132
Điểm
360
Cám ơn anh @snow25@CHAOQUAY nhiều nhiều ạ. Code của anh @snow25 thấy chạy ổn ạ
Code anh @CHAOQUAY không hiểu sao nó báo lỗi như hình ảnh trên ạ.View attachment 236828
Có điều em chưa hiểu lắm đoạn
Mã:
For Each t In ActiveWorkbook.Names
        If .exists(t) Then .remove t
    Next t
Tức là duyệt qua tên của từng sheet. nếu cái nào trùng trong key thì loại bỏ ạ.
Nếu anh có thời gian. có thể bớt chút thời gian chỉ cho em hiểu với ạ
Sửa lại bên dưới.
Mã:
Sub A_Tach_sheet()
Dim i%, LR%, Rng As Range, Cll As Range
Dim t As Variant
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
With CreateObject("Scripting.Dictionary")
    For Each Cll In Rng
        If Trim(Cll) <> "" Then .Item(Trim(Cll)) = ""
    Next Cll
    For Each t In Worksheets
        If .exists(t.Name) Then .Remove t.Name
    Next t
    If .Count Then
        For Each t In .keys
            Sheet2.Copy after:=Sheets(Sheets.Count)
            ActiveSheet.Name = t
        Next t
    End If
End With
End Sub
---
Mã:
For Each t In ActiveWorkbook.Names
        If .exists(t) Then .remove t
    Next t
"Tức là duyệt qua tên của từng sheet. nếu cái nào trùng trong key thì loại bỏ ạ."

Đúng là phải thực hiện bước này.
Ý định là như vậy nhưng viết không đúng. Phải sửa lại for each t in worksheets như trên.
Workbook.Names là name người dùng, không phải tên sheet nên không đúng.
 
Lần chỉnh sửa cuối:

PacificPR

Thành viên gắn bó
Tham gia ngày
6 Tháng năm 2016
Bài viết
1,849
Được thích
2,449
Điểm
360
Nơi ở
Cái Bang
Cám ơn anh @snow25@CHAOQUAY nhiều nhiều ạ. Code của anh @snow25 thấy chạy ổn ạ
Code anh @CHAOQUAY không hiểu sao nó báo lỗi như hình ảnh trên ạ.View attachment 236828
Có điều em chưa hiểu lắm đoạn
Mã:
For Each t In ActiveWorkbook.Names
        If .exists(t) Then .remove t
    Next t
Tức là duyệt qua tên của từng sheet. nếu cái nào trùng trong key thì loại bỏ ạ.
Nếu anh có thời gian. có thể bớt chút thời gian chỉ cho em hiểu với ạ
Bon chen 1 tý. Bạn tham khảo thêm nhé
Mã:
Sub Tach_sheet()
    Dim Rng As Range, Cll As Range
On Error GoTo Handle
Set Rng = Application.InputBox("Quet vung chon:", "Thong bao", Type:=8)
For Each Cll In Rng
    If Not WsExit(Cll.Value) Then
        Sheet2.Copy after:=Sheets(Sheets.Count)
        Worksheets(Worksheets.Count).Name = Cll.Value       
    End If
Next Cll
Handle:
End Sub
Function WsExit(wsName As String) As Boolean
    On Error Resume Next
    WsExit = CBool(Len(Worksheets(wsName).Name) > 0)
End Function
 
Lần chỉnh sửa cuối:

kokano90

Thành viên chính thức
Tham gia ngày
10 Tháng tám 2019
Bài viết
64
Được thích
17
Điểm
20
Tuổi
30
Em chào các thầy cô ạ.
Em có 1 file gồm 3 sheet:
DATA: chứa dữ liệu
DULEU: Là nơi chứa dữ liệu lọc trùng theo số hóa đơn từ sheet DATA
Form: để in dữ liệu từ số hóa đơn

Em có viết 1 đoạn code:
Mã:
Sub ABC()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
    Dim iRow&, sWS As Worksheet, sArr(), KQ(), iC&, a&, b&, rC&, WF As Object
    Dim i&, j&, dC&, Arr(), ans&, WS As Worksheet, dWS As Worksheet
    Set WF = Application.WorksheetFunction
    Set WS = Sheets("Form"): Set sWS = Sheets("DATA"): Set dWS = Sheets("DULIEU")
        iRow = sWS.Range("E" & Rows.Count).End(xlUp).Row
        dC = dWS.Range("D" & Rows.Count).End(xlUp).Row
        Arr = dWS.Range("A3:F" & dC).Value
        sArr = sWS.Range("A15:T" & iRow).Value2
        ReDim KQ(1 To UBound(sArr, 1), 1 To 6)
        WS.Range("A8:F10000").Delete
            For i = 1 To UBound(Arr)
                WS.Range("D1").Value = UCase(Arr(i, 4))
                WS.Range("D2").Value = UCase(Arr(i, 5))
                WS.Range("D3").Value = UCase(Arr(i, 3))
                WS.Range("A6").Value = dWS.Range("I1").Value & _
                Arr(i, 1) & "/" & Day(Arr(i, 2)) & Month(Arr(i, 2)) & _
                Year(Arr(i, 2)) & " KH: YT/18P"
                For iC = 1 To UBound(sArr)
                    If sArr(iC, 5) = Arr(i, 1) Then
                    a = a + 1
                    KQ(a, 1) = a
                    KQ(a, 2) = sArr(iC, 11)
                    KQ(a, 3) = sArr(iC, 12)
                    KQ(a, 4) = sArr(iC, 13)
                    KQ(a, 5) = sArr(iC, 14)
                    KQ(a, 6) = sArr(iC, 15)
                    End If
                Next iC
                With WS
                If a Then .Range("A8:F8").Resize(a).Value = KQ
                .Range("A7:F7").Resize(a + 1).Borders.LineStyle = 1
                rC = .Range("A" & Rows.Count).End(xlUp).Row
                dWS.Range("I2:N9").Copy .Range("A" & rC)
                .PrintPreview
                End With
                a = 0: KQ = Empty
            Next i
    MsgBox ("da xong")
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
như file đính kèm
Nhưng không hiểu sao cứ tới lúc bắt đầu vào vòng lặp
Mã:
For i = 1 To UBound(Arr)
này trở đi thì nó lại bị hiện tượng treo máy.
Nhờ các thầy cô có thể giải thích giúp em được không ạ. Hoặc có cách nào hay hơn nhờ thầy cô giúp với ạ.
Em xin cám ơn
 

File đính kèm

panda1112009

Thành viên mới
Tham gia ngày
8 Tháng tám 2017
Bài viết
12
Được thích
1
Điểm
165
Tuổi
28
Em có đoạn code ntn.. và e muốn khi chạy đoạn mã này nó sẽ hiện ra 1 ô thông báo để mình chọn số đơn vị muốn làm tròn cd: 3;0;-3. Vì trong code này nó mặc định bằng 0 nên nhiều lúc phải chỉnh tay khá mất công.. e xin cảm ơn ạ.

Public Sub ChenRound()
Dim Vung, Cll, Tam
Set Vung = Application.InputBox("Nhap vung muon chen ham ROUND", , , , , , , 8)
For Each Cll In Vung
Tam = Replace(Cll.Formula, "=", "")
Cll.Formula = "=ROUND(" & Tam & ",0)"
Next Cll
End Sub
 

khuyenbachmao

Thành viên mới
Tham gia ngày
18 Tháng mười 2010
Bài viết
11
Được thích
4
Điểm
365
Tuổi
37
Em chào các thầy cô ạ.
Em có 1 file gồm 3 sheet:
DATA: chứa dữ liệu
DULEU: Là nơi chứa dữ liệu lọc trùng theo số hóa đơn từ sheet DATA
Form: để in dữ liệu từ số hóa đơn

Em có viết 1 đoạn code:
Mã:
Sub ABC()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
    Dim iRow&, sWS As Worksheet, sArr(), KQ(), iC&, a&, b&, rC&, WF As Object
    Dim i&, j&, dC&, Arr(), ans&, WS As Worksheet, dWS As Worksheet
    Set WF = Application.WorksheetFunction
    Set WS = Sheets("Form"): Set sWS = Sheets("DATA"): Set dWS = Sheets("DULIEU")
        iRow = sWS.Range("E" & Rows.Count).End(xlUp).Row
        dC = dWS.Range("D" & Rows.Count).End(xlUp).Row
        Arr = dWS.Range("A3:F" & dC).Value
        sArr = sWS.Range("A15:T" & iRow).Value2
        ReDim KQ(1 To UBound(sArr, 1), 1 To 6)
        WS.Range("A8:F10000").Delete
            For i = 1 To UBound(Arr)
                WS.Range("D1").Value = UCase(Arr(i, 4))
                WS.Range("D2").Value = UCase(Arr(i, 5))
                WS.Range("D3").Value = UCase(Arr(i, 3))
                WS.Range("A6").Value = dWS.Range("I1").Value & _
                Arr(i, 1) & "/" & Day(Arr(i, 2)) & Month(Arr(i, 2)) & _
                Year(Arr(i, 2)) & " KH: YT/18P"
                For iC = 1 To UBound(sArr)
                    If sArr(iC, 5) = Arr(i, 1) Then
                    a = a + 1
                    KQ(a, 1) = a
                    KQ(a, 2) = sArr(iC, 11)
                    KQ(a, 3) = sArr(iC, 12)
                    KQ(a, 4) = sArr(iC, 13)
                    KQ(a, 5) = sArr(iC, 14)
                    KQ(a, 6) = sArr(iC, 15)
                    End If
                Next iC
                With WS
                If a Then .Range("A8:F8").Resize(a).Value = KQ
                .Range("A7:F7").Resize(a + 1).Borders.LineStyle = 1
                rC = .Range("A" & Rows.Count).End(xlUp).Row
                dWS.Range("I2:N9").Copy .Range("A" & rC)
                .PrintPreview
                End With
                a = 0: KQ = Empty
            Next i
    MsgBox ("da xong")
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
như file đính kèm
Nhưng không hiểu sao cứ tới lúc bắt đầu vào vòng lặp
Mã:
For i = 1 To UBound(Arr)
này trở đi thì nó lại bị hiện tượng treo máy.
Nhờ các thầy cô có thể giải thích giúp em được không ạ. Hoặc có cách nào hay hơn nhờ thầy cô giúp với ạ.
Em xin cám ơn
Mình có một số góp ý tiến trình xử lý tiện nhất:

Thứ tự thực hiện:
B1. Do DATA được bạn dùng kiểu bảng tính
--> Bạn không tận dụng được tối đa object table trong viết VBA
--> Giải pháp: sheet data format thành table + bỏ các dòng không cần thiết
B2. PIVOT DATA thành danh sách HD muốn in (cần phải có điều kiện PIVOT) hoặc viết điều kiện input trong VBA (chắc chưa cần) --> đưa vào biến mảng (theo mình nên học thêm collection hoặc Dictionary) sẽ tiện dụng hơn
B3. Đọc biến lưu và truyền vào FORM; nếu in mỗi lần bằng input số hóa đơn thì không cần sheet DU LIEU

Mình có làm mẫu thử trên file đính kèm để theo tham khảo nhé. Alt + F8 --> chạy xem kết quả lấy dữ liệu. Nếu viết tiếp thì từ đó đưa vào sheet FORM là xong
 

File đính kèm

Nguyễn Hoàng Oanh Thơ

Thành viên tích cực
Tham gia ngày
5 Tháng mười một 2015
Bài viết
1,146
Được thích
495
Điểm
235
Nơi ở
Hà Nội
Xin chào tất cả mọi người,

OT viết một câu lệnh đại loại như sau,nếu như thế này, sau khi xử lý hết công việc 1 sẽ tiến hành công việc 2.

Mã:
Sub macro

    Cong viec 1
    Goto Xuly

    Cong viec 2
    Goto Xuly
Xuly:
    Cau lenh xu ly
End sub
Nhưng khi xong công việc 1 thì code không xử lý công việc 2 do câu lệnh Goto Xuly
Nếu viết như thế này, thì sẽ lặp có 2 dòng Cau lenh xu ly :
Mã:
Sub macro

    Cong viec 1
    Cau lenh xu ly

    Cong viec 2
    Cau lenh xu ly

End sub
OT muốn viết 1 dòng "Cau lenh xu ly" rồi sử dụng Goto Xuly thì sẽ viết như thế nào ạ?
 

VetMini

Chuyên gia GPE
Tham gia ngày
21 Tháng mười hai 2012
Bài viết
8,917
Được thích
10,441
Điểm
1,560
Đi tìm hiểu về từ khoá GoSub.
Tôi chỉ như vậy là do ý bạn muốn vậy. Chứ nếu toi viết code thì thiết kế giải thuật khác. Đối với tôi, Go <cái gì đó> là loại lệnh bất đắc dĩ mới phải dùng.

Đại khái nó sử dụng như vầy:

Sub TestCodeGoSub()
code...
congviec1
GoSub CongViecChung
congviec2
GoSub CongViecChung
code...
Exit Sub ' lệnh này rất quan trọng, dùng để tránh code chạy vào sub con bên dưới

CongViecChung:
' sub con, chứa bên trong sub mẹ
những câu lệnh xử lý gì đó...
Return ' lệnh này bảo VBA trở về chạy tiếp dòng sau lệnh gosub

End Sub ' TestCodeGoSub

Lưu ý: sub con là code nội của sub mẹ. Nó sử dụng mọi biến nội của sub mẹ.
 

SA_DQ

/(hông là gì!
Thành viên danh dự
Tham gia ngày
8 Tháng sáu 2006
Bài viết
11,397
Được thích
17,305
Điểm
1,860
Hình như phải xài 2 macro Cha & Con, như sau:
PHP:
Sub MacroCha
'Các Công Viêc Cua CôngViec01  '
XuLy
'Các Công Viêc Cua CôngViec02    '
XuLy '?'
End Sub
Mã:
Sub XuLy()
'Các Câu Lênh Trung Gian
End Sub
 

Nguyễn Hoàng Oanh Thơ

Thành viên tích cực
Tham gia ngày
5 Tháng mười một 2015
Bài viết
1,146
Được thích
495
Điểm
235
Nơi ở
Hà Nội
Đi tìm hiểu về từ khoá GoSub.
Tôi chỉ như vậy là do ý bạn muốn vậy. Chứ nếu toi viết code thì thiết kế giải thuật khác. Đối với tôi, Go <cái gì đó> là loại lệnh bất đắc dĩ mới phải dùng.

Đại khái nó sử dụng như vầy:

Sub TestCodeGoSub()
code...
congviec1
GoSub CongViecChung
congviec2
GoSub CongViecChung
code...
Exit Sub ' lệnh này rất quan trọng, dùng để tránh code chạy vào sub con bên dưới

CongViecChung:
' sub con, chứa bên trong sub mẹ
những câu lệnh xử lý gì đó...
Return ' lệnh này bảo VBA trở về chạy tiếp dòng sau lệnh gosub

End Sub ' TestCodeGoSub

Lưu ý: sub con là code nội của sub mẹ. Nó sử dụng mọi biến nội của sub mẹ.
Xin chào Bác VetMini,
Con cảm ơn Bác đã chỉ dẫn ạ, con không có kinh nghiệm viết code nên không biết dùng cách nào cho tối con mới chỉ nghĩ đến cách đó.
Nếu Bác có cách nào khác xin chỉ dẫn cho con thêm ạ.
Cảm ơn Bác VetMini.

Hình như phải xài 2 macro Cha & Con, như sau:
PHP:
Sub MacroCha
'Các Công Viêc Cua CôngViec01  '
XuLy
'Các Công Viêc Cua CôngViec02    '
XuLy '?'
End Sub
Mã:
Sub XuLy()
'Các Câu Lênh Trung Gian
End Sub
Con cảm ơn Bác SA_DQ đã chỉ dẫn
Bài đã được tự động gộp:

Đi tìm hiểu về từ khoá GoSub.
Tôi chỉ như vậy là do ý bạn muốn vậy. Chứ nếu toi viết code thì thiết kế giải thuật khác. Đối với tôi, Go <cái gì đó> là loại lệnh bất đắc dĩ mới phải dùng.

Đại khái nó sử dụng như vầy:

Sub TestCodeGoSub()
code...
congviec1
GoSub CongViecChung
congviec2
GoSub CongViecChung
code...
Exit Sub ' lệnh này rất quan trọng, dùng để tránh code chạy vào sub con bên dưới

CongViecChung:
' sub con, chứa bên trong sub mẹ
những câu lệnh xử lý gì đó...
Return ' lệnh này bảo VBA trở về chạy tiếp dòng sau lệnh gosub

End Sub ' TestCodeGoSub

Lưu ý: sub con là code nội của sub mẹ. Nó sử dụng mọi biến nội của sub mẹ.
Xin chào Bác VetMini
Bác ơi, Bác có thể chỉ con cách dùng câu lệnh với: Resume <label> trong trường hợp này được không ạ?
 
Lần chỉnh sửa cuối:

VetMini

Chuyên gia GPE
Tham gia ngày
21 Tháng mười hai 2012
Bài viết
8,917
Được thích
10,441
Điểm
1,560
Hình như phải xài 2 macro Cha & Con, như sau:
...
2 macro Cha và Con là 2 khối riêng biệt và độc lập với nhau. Chúng không chia sẻ biến nội hay cái gì cả, ngoại trừ biến toàn cục.

Nếu macro Con không cần gì đến biến nào của Cha thì nên dùng 2 macro's. Nếu cần một vài biến thì cũng có thể dùng tham để truyền. Cách này khiến Con độc lập với Cha, và rất dễ kiểm soát.

Nhưng nếu đúng theo yêu cầu ở bài #2474, phần sub con cần chạy một số lệnh nào đó, và không xác định cách truyền biến thì GoSub đúng là cái mà người hỏi muốn. Trong bài #2475, code của sub con là code của sub mẹ.

Xin chào Bác VetMini
Bác ơi, Bác có thể chỉ con cách dùng câu lệnh với: Resume <label> trong trường hợp này được không ạ?
Resume không áp dụng cho trường hợp này. Resume là lệnh của bắt lỗi, dùng để tháo bẫy lỗi.
Return là câu lệnh bảo trở về dòng lệnh kế tiếp dòng GoSub, chả liên quan gì đến lỗi cả.

Từ Resume có nghĩa là "tiếp tục lại...". Sau khi xử lý lỗi xong thì lại tiếp tục ở vị trí nào đó.
Từ Return có nghĩa là "trở về...". Sau khi chạy xong đống lệnh trong sub con thì trở về nơi đã gọi sub.
 
Lần chỉnh sửa cuối:

Cu Tồ

Thành viên mới
Tham gia ngày
6 Tháng năm 2020
Bài viết
39
Được thích
7
Điểm
15
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 1589789855949.png thì sẽ không copy nữa mà thực hiện lệnh tiếp theo của đoạn code sau ah?
 
Lần chỉnh sửa cuối:

Ba Tê

Gội Rồi Mới Cạo
Tham gia ngày
5 Tháng năm 2009
Bài viết
11,487
Được thích
16,395
Điểm
1,860
Tuổi
61
Nơi ở
An Giang
Đi tìm hiểu về từ khoá GoSub.
Tôi chỉ như vậy là do ý bạn muốn vậy. Chứ nếu toi viết code thì thiết kế giải thuật khác. Đối với tôi, Go <cái gì đó> là loại lệnh bất đắc dĩ mới phải dùng.

Đại khái nó sử dụng như vầy:

Sub TestCodeGoSub()
code...
congviec1
GoSub CongViecChung
congviec2
GoSub CongViecChung
code...
Exit Sub ' lệnh này rất quan trọng, dùng để tránh code chạy vào sub con bên dưới

CongViecChung:
' sub con, chứa bên trong sub mẹ
những câu lệnh xử lý gì đó...
Return ' lệnh này bảo VBA trở về chạy tiếp dòng sau lệnh gosub

End Sub ' TestCodeGoSub

Lưu ý: sub con là code nội của sub mẹ. Nó sử dụng mọi biến nội của sub mẹ.
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
 
Lần chỉnh sửa cuối:
Top Bottom