Báo lỗi khi gọi Sub nằm trong worksheet nhưng khi Sub đó nằm trong Module thì không bị lỗi (1 người xem)

Liên hệ QC

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

Cát Lượng

Thành viên tiêu biểu
Tham gia
14/11/18
Bài viết
403
Được thích
66
Em có sử dụng Form để in.
Khi copy "Sub gian" vào Sheet19 (NT A_B) thì gọi Sub trong Form báo lỗi như hình thứ nhất
Nhưng khi chuyển "Sub gian" vào Module2, lúc này gọi Sub trong Form để in (Khi in có tác dụng giãn dòng luôn) thì lại được.
"Sub gian" code như sau:
Mã:
Sub gian()
  Application.ScreenUpdating = False
    'Rows(FitRows).EntireRow.AutoFit
    Range("A20").EntireRow.AutoFit
    Application.ScreenUpdating = True
End Sub
Toàn bộ code trong Form in như sau:
Mã:
Private Sub OkInBB_All_Click()
    Dim inStart As Long, inFinish As Long
    Dim I As Long
    Dim CotD As Range
    Dim Ws As Worksheet
    On Error GoTo Thoat
    Set Ws = Sheet19
    Ws.DisplayPageBreaks = False
    inStart = TextBox1.Value
    inFinish = TextBox2.Value
    For I = inStart To inFinish
        With Ws
            ActiveSheet.DisplayPageBreaks = False
            .Range("L10").Value = I
            Call gian
            For Each CotD In Range("D8:D12")
                If CotD.Value = "0" Then
                    CotD.EntireRow.Hidden = True
                End If
            Next CotD
            .PrintOut 'Vùng in Set
        End With
    Next I
Thoat:
    Unload Me
    ActiveSheet.DisplayPageBreaks = False
End Sub

'***********************************************************************************************************************
'LUA CHON MÁY IN
Private Sub Printer_Properties_Click()
    Call Shell("rundll32 printui.dll,PrintUIEntry /p /n """ & ComboBox1.Value & """", vbNormalFocus)
End Sub

Sub List_Printer()
    Dim aPrinters As Object
    Dim I As Long, N As Long
    With CreateObject("WScript.Network")
        Set aPrinters = .EnumPrinterConnections
        For I = 1 To aPrinters.Count Step 2
            ComboBox1.AddItem aPrinters.Item(I)
        Next
    End With
End Sub

Sub Get_Default_Printer()
    Dim WSHshell As Object, RegKey As String, RegKeySplit As Variant
    Dim RegDefault As String, MyPrinter As String
    RegKey = _
            "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device"
    Set WSHshell = CreateObject("WScript.Shell")
    RegDefault = WSHshell.RegRead(RegKey)
    Set WSHshell = Nothing
    RegKeySplit = Split(RegDefault, ",")
    MyPrinter = RegKeySplit(0)
    ComboBox1.Text = MyPrinter
End Sub

Private Sub UserForm_Initialize()
    Call List_Printer
    Call Get_Default_Printer
End Sub
'***********************************************************************************************************************
"Sub gian" em đã gọi trong Form

Mã:
.....
Call gian
......

>> Nhờ các anh các chị giúp em chỉnh code trong Form mà có thể gọi "Sub gian" khi sử dụng Form in mà vị trí " Sub gian" nằm trong worksheet (NT A_B) mà không bị báo lỗi.
Em xin chân thành cảm ơn!

q.png
 

File đính kèm

Lần chỉnh sửa cuối:
Em có sử dụng Form để in.
Khi copy "Sub gian" vào Sheet19 (NT A_B) thì gọi Sub trong Form báo lỗi như hình thứ nhất
Nhưng khi chuyển "Sub gian" vào Module2, lúc này gọi Sub trong Form để in (Khi in có tác dụng giãn dòng luôn) thì lại được.
"Sub gian" code như sau:
Mã:
Sub gian()
  Application.ScreenUpdating = False
    'Rows(FitRows).EntireRow.AutoFit
    Range("A20").EntireRow.AutoFit
    Application.ScreenUpdating = True
End Sub
Toàn bộ code trong Form in như sau:
Mã:
Private Sub OkInBB_All_Click()
    Dim inStart As Long, inFinish As Long
    Dim I As Long
    Dim CotD As Range
    Dim Ws As Worksheet
    On Error GoTo Thoat
    Set Ws = Sheet19
    Ws.DisplayPageBreaks = False
    inStart = TextBox1.Value
    inFinish = TextBox2.Value
    For I = inStart To inFinish
        With Ws
            ActiveSheet.DisplayPageBreaks = False
            .Range("L10").Value = I
            Call gian
            For Each CotD In Range("D8:D12")
                If CotD.Value = "0" Then
                    CotD.EntireRow.Hidden = True
                End If
            Next CotD
            .PrintOut 'Vùng in Set
        End With
    Next I
Thoat:
    Unload Me
    ActiveSheet.DisplayPageBreaks = False
End Sub

'***********************************************************************************************************************
'LUA CHON MÁY IN
Private Sub Printer_Properties_Click()
    Call Shell("rundll32 printui.dll,PrintUIEntry /p /n """ & ComboBox1.Value & """", vbNormalFocus)
End Sub

Sub List_Printer()
    Dim aPrinters As Object
    Dim I As Long, N As Long
    With CreateObject("WScript.Network")
        Set aPrinters = .EnumPrinterConnections
        For I = 1 To aPrinters.Count Step 2
            ComboBox1.AddItem aPrinters.Item(I)
        Next
    End With
End Sub

Sub Get_Default_Printer()
    Dim WSHshell As Object, RegKey As String, RegKeySplit As Variant
    Dim RegDefault As String, MyPrinter As String
    RegKey = _
            "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device"
    Set WSHshell = CreateObject("WScript.Shell")
    RegDefault = WSHshell.RegRead(RegKey)
    Set WSHshell = Nothing
    RegKeySplit = Split(RegDefault, ",")
    MyPrinter = RegKeySplit(0)
    ComboBox1.Text = MyPrinter
End Sub

Private Sub UserForm_Initialize()
    Call List_Printer
    Call Get_Default_Printer
End Sub
'***********************************************************************************************************************
"Sub gian" em đã gọi trong Form

Mã:
.....
Call gian
......

>> Nhờ các anh các chị giúp em chỉnh code trong Form mà có thể gọi "Sub gian" khi sử dụng Form in mà vị trí " Sub gian" nằm trong worksheet (NT A_B) mà không bị báo lỗi.
Em xin chân thành cảm ơn!

View attachment 229892
Theo mình hiểu là khi để sub gian ở trong sheet thì chỉ dùng cho code trong sheets đó được thôi.Và khi để ở module thì nó sẽ dùng cho mọi vị trí.
 
Thử như vầy chưa?
Call Sheets("NT A_B").gian
Khi biết project phức tạp thì cố gắng đặt tên Sheet theo luật Alphanumeric (chỉ có a-z, 0-9, và _ thôi). Sẽ tránh được nhiểu rắc rối về sau.

Phụ chú:
Sub gian()
Application.ScreenUpdating = False
'Rows(FitRows).EntireRow.AutoFit
Range("A20").EntireRow.AutoFit
Application.ScreenUpdating = True
End Sub

Khi biết sub sẽ được sub khác gọi thì phải coi chừng cái lệnh tô đỏ ở trên
Sub A()
Application.ScreenUpdating = False
Call gian ' gian nó đưa screen update về True -> A bị hẫng
' kể từ đây, A chạy với trạng thái srcreen update
.
Application.ScreenUpdating = True
End Sub '

Làm đúng đắn thì phải là:
Sub gian()
scrnupdt = Application.ScreenUpdating
Application.ScreenUpdating = False
'Rows(FitRows).EntireRow.AutoFit
Range("A20").EntireRow.AutoFit
Application.ScreenUpdating = scrnupdt
End Sub
 
Thử như vầy chưa?
Call Sheets("NT A_B").gian
Khi biết project phức tạp thì cố gắng đặt tên Sheet theo luật Alphanumeric (chỉ có a-z, 0-9, và _ thôi). Sẽ tránh được nhiểu rắc rối về sau.

Phụ chú:
Sub gian()
Application.ScreenUpdating = False
'Rows(FitRows).EntireRow.AutoFit
Range("A20").EntireRow.AutoFit
Application.ScreenUpdating = True
End Sub

Khi biết sub sẽ được sub khác gọi thì phải coi chừng cái lệnh tô đỏ ở trên
Sub A()
Application.ScreenUpdating = False
Call gian ' gian nó đưa screen update về True -> A bị hẫng
' kể từ đây, A chạy với trạng thái srcreen update
.
Application.ScreenUpdating = True
End Sub '

Làm đúng đắn thì phải là:
Sub gian()
scrnupdt = Application.ScreenUpdating
Application.ScreenUpdating = False
'Rows(FitRows).EntireRow.AutoFit
Range("A20").EntireRow.AutoFit
Application.ScreenUpdating = scrnupdt
End Sub
Dạ! con cám ơn chú nhiều!
Bài đã được tự động gộp:

Để ở đâu cũng gọi được hết. Private vẫn gọi cổ nó lên được cơ mà.

PHP:
 call sheet19.gian
Vâng, em cảm ơn thầy!
Bài đã được tự động gộp:

Theo mình hiểu là khi để sub gian ở trong sheet thì chỉ dùng cho code trong sheets đó được thôi.Và khi để ở module thì nó sẽ dùng cho mọi vị trí.
Vâng nếu hiểu đơn thuần thì em cũng nghĩ vậy. cảm ơn anh!
 
1576295016697.png
.
Theo luật của lập trình hướng đối tượng thì nó không hẳn đơn giản như vậy.

Mỗi Sheet là một đối tượng. Các sub/functions bên trong Sheet thuộc về đối tượng ấy. Và đối với bên ngoài, chúng phải được đối xử như là thuộc tính (properties) và phương thức (methods) của đối tượng (Object).
Vì vậy, muốn đề cập/gọi (invoke) thuộc tính và phương thức của đối tượng thì phải thông qua đối tượng chủ, tức là phải tiền tố (prefix) phương thức với tên của đối tượng.

Ở trên Sheet1 (NT A_B) là một đối tượng. Và gian là một phương thức của đối tượng ấy.
Như vậy, muốn gọi gian, phải thông qua Sheet1 ----> Call Sheet1.gian, hoặc Sheets("NT A_B").gian

Mặt khác, các code đặt trong module thì coi như thuộc về đối tượng mặc định. Các Modules 1, 2, ... coi như có thể sử dụng Sub/Functions và biến toàn cục của nhau. Chỉ khi nào cần phân biệt những Sub/Functions và biến toàn cục bạn mới phải gài tiền tố tên module.
 
View attachment 229901
.
Theo luật của lập trình hướng đối tượng thì nó không hẳn đơn giản như vậy.

Mỗi Sheet là một đối tượng. Các sub/functions bên trong Sheet thuộc về đối tượng ấy. Và đối với bên ngoài, chúng phải được đối xử như là thuộc tính (properties) và phương thức (methods) của đối tượng (Object).
Vì vậy, muốn đề cập/gọi (invoke) thuộc tính và phương thức của đối tượng thì phải thông qua đối tượng chủ, tức là phải tiền tố (prefix) phương thức với tên của đối tượng.

Ở trên Sheet1 (NT A_B) là một đối tượng. Và gian là một phương thức của đối tượng ấy.
Như vậy, muốn gọi gian, phải thông qua Sheet1 ----> Call Sheet1.gian, hoặc Sheets("NT A_B").gian

Mặt khác, các code đặt trong module thì coi như thuộc về đối tượng mặc định. Các Modules 1, 2, ... coi như có thể sử dụng Sub/Functions và biến toàn cục của nhau. Chỉ khi nào cần phân biệt những Sub/Functions và biến toàn cục bạn mới phải gài tiền tố tên module.
Cảm ơn chú nhiều! Chú ơi con có gọi Sub "gian_17" trong luôn sheet (17_Kinh Nghiem)
Con thấy báo lỗi chú ạ!
Là do đâu vậy chú?
Con tải file và hình ảnh chú xem gúp con chú nhé!
Cám ơn chú!
loidau.pngloi1.png
 

File đính kèm

Mã:
Dim scrnupdt
Dạ thay dòng
[CODE]scrnupdt = Application.ScreenUpdating
bằng
Mã:
Dim scrnupdt
ý cháu nhầm!
Bài đã được tự động gộp:

Dim scrnupdt
scrnupdt = Application.ScreenUpdating
Chú con hỏi Thay dòng "scrnupdt = Application.ScreenUpdating" bằng"Dim scrnupdt"
Hay là thêm
"Dim scrnupdt" vào dữ liệu cũ vậy chú ơi?
 
Lần chỉnh sửa cuối:
Lỗi ở bài #7 là do biến scrnupdt chưa được khai báo trước khi dùng.
Thêm dòng Dim ... tức là khai báo nó.

Chú: Nếu bạn không hiểu về khai báo thì cái dòng "Option Explicit" ở đầu mô đun chỉ là thừa.
 
Lỗi ở bài #7 là do biến scrnupdt chưa được khai báo trước khi dùng.
Thêm dòng Dim ... tức là khai báo nó.

Chú: Nếu bạn không hiểu về khai báo thì cái dòng "Option Explicit" ở đầu mô đun chỉ là thừa.
Vâng con lắp theo chú giúp đã gọi được Sub cần gọi nhưng khi con in trong Form con cũng gọi Sub đó để in, nhưng không hiểu sao lệnh in lại không chạy chú ạ! Không báo lỗi nhưng khi ấn in thì "nháy màn hình" một cái và giao diện Form biến mất.
Code con thêm vào để gọi Sub "gian_17" trong Form như sau:
Mã:
....
Call Trang_tính16("17_Kinh Nghiem").gian_17
........
Nhờ chú giúp con để con có thể in được mới chú nhé!
 

File đính kèm

Call Sheets("17_Kinh Nghiem").gian_17

Cái file này khá rắc rối, mà bạn lại không có căn bản về code. Nếu tôi chỉnh nhỏ giọt như thế hì chắc hết tuần mới xong.
Tốt hơn hết là nhờ chủ nhân của nó chỉnh sửa theo yêu cầu của bạn.
 
Call Sheets("17_Kinh Nghiem").gian_17

Cái file này khá rắc rối, mà bạn lại không có căn bản về code. Nếu tôi chỉnh nhỏ giọt như thế hì chắc hết tuần mới xong.
Tốt hơn hết là nhờ chủ nhân của nó chỉnh sửa theo yêu cầu của bạn.
Dạ! cám ơn chú nhiều!
 
Web KT

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

Back
Top Bottom