2017-02-06 12 views
9

Đây là một trong những điều tôi không hiểu.Lỗi Excel khi nhập dấu ngoặc đơn mở

Với mô-đun lớp này (rút gọn đến mức tối thiểu cần thiết để tái tạo vụ tai nạn):

VERSION 1.0 CLASS 
BEGIN 
    MultiUse = -1 'True 
END 
Attribute VB_Name = "TestCrashClass" 
Attribute VB_GlobalNameSpace = False 
Attribute VB_Creatable = False 
Attribute VB_PredeclaredId = True 
Attribute VB_Exposed = False 
Option Explicit 

Public Function Init() As TestCrashClass 
Attribute Init.VB_UserMemId = 0 
    Dim tcc As New TestCrashClass 
    Set Init = tcc 
End Function 

Public Property Get Data() As String 
    Data = "test data" 
End Property 

bất cứ ai có thể cho tôi biết tại sao Excel hoàn toàn craps ra khi tôi gõ vào mã này:

Sub MakeExcelCrash() 
    With TestCrashClass(

Tại thời điểm này, tôi này nhắn đáng yêu:

Excel crash - oops!

Ngay cả khi tôi nhập một thủ tục đầy đủ mà không có dấu ngoặc đơn vi phạm và sau đó cố gắng thêm chúng sau này, tôi nhận được cùng một vụ tai nạn.

Cách duy nhất tôi có thể làm cho Excel không gặp sự cố là sao chép/dán một tập hợp () từ một nơi khác sang dòng mã này.

Sub MakeExcelCrash() 
    With TestCrashClass() 
     Debug.Print .Data 
    End With 
End Sub 

Nếu phương pháp Init() có tham số — ngay cả một tùy chọn — nó sẽ không bị lỗi khi mở dấu ngoặc đơn.

Tôi tò mò hơn về lý do tại sao điều này xảy ra hơn các cách xung quanh nó; nó không thực sự xuất hiện thường xuyên trong mã của tôi và khi nào tôi có thể sửa nó bằng cách thay đổi cách tiếp cận, nhưng tôi thực sự thất vọng vì tôi không biết nguyên nhân gây ra những sự cố này. Vì vậy, có lẽ ai đó biết nhiều hơn về công việc bên trong của VBA có thể giải thích cho tôi?

+0

Excel có cung cấp một số loại tự động hoàn thành khi bạn nhập không? – Carcigenicate

+0

Tôi đoán rằng việc tạo ra một phương thức tạo ra một thể hiện của lớp của bạn, phương thức mặc định là tạo ra một vòng lặp vô hạn. Có thể có một số đánh giá về mã của lớp đang diễn ra khi bạn gõ dòng đó ... Mục đích của phương pháp đó là gì? –

+2

Tôi nghĩ vì bạn đã tạo thành 'Init' thành viên mặc định, VBE sẽ cố gắng cung cấp cho bạn một trình đơn thả xuống Intellisense dựa vào đó - ngay sau khi nó cố gắng thực hiện nó vào vòng lặp vô hạn (vì giá trị trả về từ' Init' là một thể hiện khác của cùng một lớp, cũng với cùng thành viên mặc định đó, v.v ...) và Excel bị treo. –

Trả lời

9

Bạn thậm chí không cần khối With. Bất kỳ nào cố gắng nhập ( sau khi tên lớp mất Excel.

Sự cố là bạn đã đặt VB_PredeclaredId thành true và thành viên mặc định đang cố gắng trả lại chính nó. Khi bạn đính kèm một debugger để dụ Excel chết, bạn có thể thấy rằng các vấn đề cơ bản là một stack overflow:

Unhandled ngoại lệ tại 0x0F06EC84 (VBE7.DLL) trong Excel.exe: 0xC00000FD: Stack Overflow (thông số : 0x00000001, 0x00212FFC).

Khi bạn gõ With TestCrashClass(, những gì xảy ra là VBA bắt đầu tìm kiếm một indexer trên thuộc tính mặc định, vì Init() không có bất kỳ tài sản. Ví dụ: hãy xem xét Collection. Bạn có thể sử dụng (Item) indexer tài sản của mặc định như thế này:

Dim x As Collection 
Set x = New Collection 
x.Add 42 
Debug.Print x(1) '<--indexed access via default member. 

Đây chính là tương đương với Debug.Print x.Items(1). Đây là nơi bạn bắt đầu chạy vào các vấn đề. Init() không có tham số, vì vậy VBA bắt đầu khoan xuống thông qua các thành viên mặc định để tìm đầu tiên có trình chỉ mục để IntelliSense có thể hiển thị danh sách tham số. Nó bắt đầu làm điều này:

x.[default].[default].[default].[default].[default]...

Trong trường hợp của bạn, nó tạo ra một vòng lặp vô hạn vì [default]lợi nhuậnx. Điều tương tự cũng xảy ra trong các mã Collection trên (ngoại trừ nó tìm thấy một):

IntelliSense on open parens

Ném trong thực tế là bạn có một trường hợp mặc định, và kết quả cuối cùng là một cái gì đó như thế này:

Private Sub Class_Initialize() 
    Class_Initialize 
End Sub 
+0

OK, điều đó có ý nghĩa. Cảm ơn các chi tiết. –

-4

Âm thanh như một số loại tham nhũng. Tôi đã có Excel hành xử irrationally như thế này trước đây, thông thường trong các dự án lớn, và cách duy nhất để có được xung quanh nó là kéo tất cả các lớp học của bạn vv vào một dự án mới.

Tôi nghi ngờ điều đó xảy ra vì Excel không thực sự xóa các lớp, mô-đun, trang tính vv đã bị xóa. Bạn có thể nói điều này vì kích thước tệp.

Không có chức năng Compact và sửa chữa, như trong Access, như xa như tôi biết

+0

Điều tương tự cũng xảy ra với một dự án hoàn toàn mới. –

7

Như @TimWilliams chỉ ra, có một thành viên mặc định mà trả về một thể hiện của cùng một lớp (hoặc một vòng lặp lớp, ví dụ: ParentClass.ChildClass.ParentClass.ChildClass... trong đó ParentClass và ChildClass đều có các thành viên mặc định) và khi được sử dụng trong một số trường hợp cú pháp nhất định, chẳng hạn như khối With, sẽ khiến VBE cố gắng giải quyết thành viên mặc định.

Dấu ngoặc đầu tiên làm cho VBE giả định rằng phải có một phương pháp, được lập chỉ mục get hoặc chỉ mục mảng sẽ lấy một đối số, vì vậy nó đặt ra để giải quyết thành viên đích cuối cùng.

Vì vậy, các không đầy đủ dòng, với một con trỏ nằm sau dấu ngoặc đơn:

With TestCrashClass(

là có hiệu quả tương tự như:

With TestCrashClass.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init '....You're inquisitive scrolling this far over, but you get the point. 

Tại một số điểm, hệ thống hoặc VBE của bạn chạy ra khỏi nguồn lực và lối thoát với ân sủng và sự điềm tĩnh của một cái ôm nhóm nhiệt hạch.

+1 để ứng biến với bản sao/mì ống của cặp dấu ngoặc đơn.

+2

ôm nhóm nhiệt hạch được +1 –

+2

Tôi phải thừa nhận rằng tôi đã cuộn hết cỡ sang bên phải, chỉ để xem bạn sẽ đi bao xa. Cảm ơn! –

Các vấn đề liên quan