Giúp sửa lỗi activex component can't create object khi load Form (1 người xem)

Liên hệ QC

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

Status
Không mở trả lời sau này.

Cao Mạnh Sơn

Tôi đồng ý
Tham gia
26/11/07
Bài viết
568
Được thích
586
Tôi có 1 file sử dụng Form. Theo chương trình khi mở File lên sẽ tự động load Form, từ Form sẽ vào chương trình bảng tính bằng nút lệnh VÀO BẢNG TÍNH và kết thúc chương trình bằng nút THOÁT CHƯƠNG TRÌNH.
Bây giờ tôi đang bị lỗi như sau: nếu thoát chương trình bằng lệnh đóng file của Excel(Dấu x góc phải của bảng tính) thì khi mở lại bảng tính hoàn toàn không có lỗi gì. Ngược lại nếu tôi thoát chương trình bằng nút lệnh trên Form thì khi mở lại bảng tính sẽ xuất hiện lỗi: activex component can't create object.
Tôi không cho rằng code viết bị lỗi mà cho rằng máy tính của tôi đang thiếu một Control nào đó, tôi gửi ảnh minh họa và file lỗi nhờ mọi người giúp giải quyết lỗi. Xin cám ơn
 

File đính kèm

Tôi có 1 file sử dụng Form. Theo chương trình khi mở File lên sẽ tự động load Form, từ Form sẽ vào chương trình bảng tính bằng nút lệnh VÀO BẢNG TÍNH và kết thúc chương trình bằng nút THOÁT CHƯƠNG TRÌNH.
Bây giờ tôi đang bị lỗi như sau: nếu thoát chương trình bằng lệnh đóng file của Excel(Dấu x góc phải của bảng tính) thì khi mở lại bảng tính hoàn toàn không có lỗi gì. Ngược lại nếu tôi thoát chương trình bằng nút lệnh trên Form thì khi mở lại bảng tính sẽ xuất hiện lỗi: activex component can't create object.
Tôi không cho rằng code viết bị lỗi mà cho rằng máy tính của tôi đang thiếu một Control nào đó, tôi gửi ảnh minh họa và file lỗi nhờ mọi người giúp giải quyết lỗi. Xin cám ơn

Code cũ
Mã:
Private Sub QuitAndSave_Click()
    Sheets("InTemThung").Select
    Cells.Select
    Selection.Delete
    Sheets("Menu").Select
    ThisWorkbook.Close SaveChanges:=True
    Application.WindowState = xlMaximized
End Sub

Anh cần sửa lại là
Mã:
Private Sub QuitAndSave_Click()
    ThisWorkbook.Close SaveChanges:=True
    Application.WindowState = xlMaximized
    [COLOR="#FF0000"]Unload Me[/COLOR] 'Giải phóng form & bộ nhớ
End Sub

Các code xóa vì nó đã chạy trong sự kiện ThisWorkbook.BeforeSave().
Khi đóng form anh phải chạy lệnh "Unload Me" để giải phóng bộ nhớ và đóng form thực sự.
Trong file Excel của anh không có dùng controls nào lạ cả nên chạy máy nào cũng được.
 
Upvote 0
Các code xóa vì nó đã chạy trong sự kiện ThisWorkbook.BeforeSave().
Khi đóng form anh phải chạy lệnh "Unload Me" để giải phóng bộ nhớ và đóng form thực sự.
Tuân à, nếu bỏ các lệnh xóa đi thì khi đóng Form nó không xóa mặc dù đã có lệnh trong sự kiện trước khi Save.
Trên máy của anh vẫn không hết lỗi như anh đã nêu: activex component can't create object.
 
Upvote 0
Thuốc đặc trị cho anh đây:
Code cũ
Mã:
Private Sub UserForm_Activate()
    On Error Resume Next
    If Application.WindowState = xlMinimized Then
     DonmauDonco.Enabled = False
     DonmauDonco2.Enabled = False
     DonmauDaco.Enabled = False
     DamauDaco.Enabled = False
     Assort.Enabled = False
     GhepTam.Enabled = False
 Else
     DonmauDonco.Enabled = True
     DonmauDonco2.Enabled = True
     DonmauDaco.Enabled = True
     DamauDaco.Enabled = True
     Assort.Enabled = True
     GhepTam.Enabled = True
 End If
  
    Dunglai = False
    Me.Caption = "SONDONG GAMENT JOINT STOCK COMPANY - SONDONG.,JSC - "
    ChuChay = Me.CompanyName
[COLOR="#008000"]Thuchien:
     PauseTime = 0.2
     Start = Timer
     Do While Timer < Start + PauseTime
         DoEvents
     Loop
         L = Len(CompanyName.Caption)
         CompanyName.Caption = Right(CompanyName.Caption, L - 1) + Left(CompanyName.Caption, 1)
     If Dunglai = False Then GoTo Thuchien[/COLOR]
End Sub

Lỗi là ở lệnh lặp từ đoạn Thuchien:, trong suốt quá trình chạy form nó không thoát khỏi vòng lặp này được và một số sự kiện của đối tượng máy tính không nhận được đúng. Anh sử dụng vòng lặp này cốt để chạy một thủ tục chạy chữ mà thôi. Giải pháp là thay thế bằng hàm Windows API SetTimer() tốt hơn và chạy độc lập với form, nó định kỳ (theo mili giây) chạy một thủ tục.

Code trong form sửa lại và thêm như sau:
+ Trong sự kiện Activate(): Xóa từ dòng Thuchien: và thêm lệnh StartTimer - Khởi hoạt chế độ chạy Timer
+ Thêm sự kiện Terminate() và gán lệnh StopTimer - Ngưng chế độ chạy Timer
Mã:
Private Sub UserForm_Activate()
    On Error Resume Next
    If Application.WindowState = xlMinimized Then
     DonmauDonco.Enabled = False
     DonmauDonco2.Enabled = False
     DonmauDaco.Enabled = False
     DamauDaco.Enabled = False
     Assort.Enabled = False
     GhepTam.Enabled = False
 Else
     DonmauDonco.Enabled = True
     DonmauDonco2.Enabled = True
     DonmauDaco.Enabled = True
     DamauDaco.Enabled = True
     Assort.Enabled = True
     GhepTam.Enabled = True
 End If

    Dunglai = False
    Me.Caption = "SONDONG GAMENT JOINT STOCK COMPANY - SONDONG.,JSC - "
    ChuChay = Me.CompanyName
    [COLOR="#FF0000"]StartTimer[/COLOR]
End Sub

Private Sub UserForm_Terminate()
    [COLOR="#FF0000"]StopTimer[/COLOR]
End Sub

Tạo một Module tên là modTimer chứa code của các hàm và thủ tục StartTimer, StopTimer, TimeProc - Thủ tục chạy chữ

Mã:
Option Explicit

Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Const nIDEvent = 9999 [COLOR="#008000"]'Tuy chon, so > 0[/COLOR]

Sub StartTimer()
    StopTimer
    SetTimer Application.hwnd, nIDEvent, 100, AddressOf TimeProc [COLOR="#008000"]'100 -- Tốc độ chạy chữ = mili giây[/COLOR]
End Sub

Sub StopTimer()
    KillTimer Application.hwnd, nIDEvent
End Sub
[COLOR="#008000"]'Thủ tục chạy chữ[/COLOR]
Function TimeProc(ByVal H As Long, ByVal nMSG As Long, ByVal nID As Long, ByVal nTsys As Long)
    On Error Resume Next
    If Not frmMain Is Nothing Then
        Dim L As Long
        L = Len(frmMain.CompanyName.Caption)
        frmMain.CompanyName.Caption = Right(frmMain.CompanyName.Caption, L - 1) + Left(frmMain.CompanyName.Caption, 1)
    End If
End Function

Kỹ thuật chạy Timer trong VBA nên thay thế bởi hàm API SetTimer chứ không nên dùng Application.OnTime() hay Do While .. Loop.
Về chữ chạy anh có thể tham khảo code em viết ở bài Tặng các bạn ScrollText - Cuộn chữ: lên, xuống, trái phải,...

File của anh em đã sửa và gửi đính kèm theo bài này, anh kiểm tra xem ok chưa.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Được rồi Tuân à. Cám ơn nhiều. Vậy mà anh cứ cho rằng tại máy tính của anh thiếu control nào đó, anh loay hoay mãi không được.
 
Upvote 0
Kỹ thuật chạy Timer trong VBA nên thay thế bởi hàm API SetTimer chứ không nên dùng Application.OnTime() hay Do While .. Loop.
Về chữ chạy anh có thể tham khảo code em viết ở bài Tặng các bạn ScrollText - Cuộn chữ: lên, xuống, trái phải,...

File của anh em đã sửa và gửi đính kèm theo bài này, anh kiểm tra xem ok chưa.
Nếu dùng SetTimer, tôi thường thấy nó đi cặp với 1 hàm TimeProc(các tham số)
Sẵn tiên cho tôi hỏi tí:
- Hàm
TimeProc thường có 1 lô tham số đi kèm, nó dùng để làm gì vậy?
- Do không hiểu mấy tham số này nên tôi thường bỏ luôn ---> Vì thật ra có để nguyên mấy tham số ấy thì tôi cũng đâu thấy chung tham gia gì vào quá trình tính toán đâu
 
Upvote 0
Nếu dùng SetTimer, tôi thường thấy nó đi cặp với 1 hàm TimeProc(các tham số)
Sẵn tiên cho tôi hỏi tí:
- Hàm
TimeProc thường có 1 lô tham số đi kèm, nó dùng để làm gì vậy?
- Do không hiểu mấy tham số này nên tôi thường bỏ luôn ---> Vì thật ra có để nguyên mấy tham số ấy thì tôi cũng đâu thấy chung tham gia gì vào quá trình tính toán đâu
Để giải thích các tham số của TimerProc sẽ bắt đầu từ việc gọi SetTimer
Mã:
Const nIDEvent = 9999
SetTimer(Application.hwnd, nIDEvent, 100, AddressOf TimeProc)
Hàm SetTimer để thiết lập chế độ gọi thông điệp WM_TIMER trong thủ tục Windows (nguyên lý hoạt động chương trình trong Windows là duyệt các thông điệp (Message) trong một vòng lặp, hàm để bắt thông điệp này thường có tên WndProc() nó được cài vào Handle của chương trình. Application.hwnd chính là Handle của Microsoft Excel đang chạy). Nếu không gán TimeProc trong SetTimer thì hàm WndProc sẽ gửi thông điệp WM_TIMER để chúng ta xử lý.

Trong việc gọi trên, SetTimer luôn trả về giá trị là ID của lần gọi SetTimer, và nó chính bằng nIDEvent.

Trong một hoàn cảnh nào đó chúng ta có thể gọi hai hay nhiều lần SetTimer với cùng thủ tục có tên TimeProc
Mã:
SetTimer(ExcelHwnd, nIDEventExcel, 100, AddressOf TimeProc)
SetTimer(WordHwnd, nIDEventWord, 100, AddressOf TimeProc)

Trong trường hợp này thủ tục TimeProc được gọi trên hai thread (hiểu như là chạy trên hai luồng). Một cái theo Winword - WordHwnd và cái kia theo Excel - ExcelHwnd với 2 ID là nIDEventWord, nIDEventExcel (có thể đặt hằng số cho các ID với giá trị là 9999, 9998).

Cấu trúc của thủ tục TimeProc như sau:
Mã:
Sub TimeProc(ByVal hwnd As Long, ByVal nMSG As Long, ByVal idEvent As Long, ByVal dwTime As Long)
   [COLOR="#008000"] 'On Error Resume Next[/COLOR]

End Sub

+ hwnd: là Handle của ứng dụng mà được gọi trong hàm SetTimer, nếu TimeProc chạy trên luồng Winword thì giá trị của nó chính là WordHwnd, nếu Excel thì là ExcelHwnd. Trong ví dụ bài trước thì nó chính là Application.hwnd. Trong lập trình API biết được giá trị Handle sẽ là đầu mối để làm mọi việc xử lý tới ứng dụng chứa Handle đó.

+ nMSG: là thông điệp/Message mà Windows gửi đến, nó chính là WM_TIMER với giá trị 275.

+ idEvent: là ID của thủ tục TimeProc, nó được nạp khi gọi hàm SetTimer, nếu TimeProc chạy trên luồng Winword thì giá trị của nó chính là nIDEventWord, nếu Excel thì là nIDEventExcel. Trong ví dụ bài trước thì nó chính là 9999. Biết được giá trị ID ta biết là TimerProc đang chạy trên luồng nào.

+ dwTime: trả về số mili giây kể từ lúc hệ thống được khởi động. Giá trị này trùng với giá trị trả về bởi hàm GetTickCount.

(*) Trong ví dụ ở bài trước hay ở đâu đó chúng ta nhầm hay gọi hàm function TimeProc nhưng cách gọi này là sai dẫn đến giá trị các tham số trong TimerProc trả về không đúng, đúng phải là Sub TimeProc.

Việc giải thích cách thức hoạt động của mấy hàm API này có vẻ trừu tượng, không dễ ngấm. Vậy hiểu nôm na thế này.

Ngôn ngữ tin học là:
Mã:
SetTimer(ExcelHwnd, nIDEventExcel, 100, AddressOf TimeProc)
SetTimer(WordHwnd, nIDEventWord, 100, AddressOf TimeProc)

Công việc ngoài đời là:
Mã:
SetTimer(Lào, Số hộ chiếu ở Lào, thời gian nhắc việc, đ/c ndu96081631)
SetTimer(Campuchia, Số hộ chiếu ở Campuchia, thời gian nhắc việc, đ/c ndu96081631)

Như vậy cùng một người là ndu96081631 nhưng phải làm việc ở ở hai nơi Lào và Campuchia. Máy tính có khả năng nhân bản ndu96081631 thành hai, cùng một thời điểm có mặt và làm việc cả hai quốc gia Lào và Campuchia. đ/c ndu96081631 chỉ biết mình đang ở đâu khi nhìn vào idEvent.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi xóa mọi bài tranh luận không liên quan đến chủ đề.
Chủ topic cũng đã thỏa mãn, nên tôi khóa chủ đề này,
Ai muốn tranh luận bên ngoài chủ đề, thì mở topic khác.

Gởi siwtom,
Tôi biết bạn có lưu lại các bài viết ở đây, nếu bạn muốn tranh luận thì mở topic khác, dán bản sao lưu vào hay không tùy bạn.
 
Lần chỉnh sửa cuối:
Upvote 0
Status
Không mở trả lời sau này.
Web KT

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

Back
Top Bottom