2010-01-29 40 views
26

Tôi đang thực hiện một số chương trình VBA trong Excel 2007 và có một sổ làm việc nơi tất cả các biểu dữ liệu sẽ được sao chép từ, vào một trang tính khác. Trang tính mới sẽ có nhiều hàng tiêu đề và tôi muốn theo dõi vị trí của chúng, vì vậy tôi không phải tìm các từ trong chúng liên tục.Lợi ích của việc sử dụng Lớp học trong VBA là gì?

Điều đơn giản nhất là sử dụng các lớp học và giữ chúng chạy trong khi tài liệu excel được mở? Hoặc điều này sẽ làm cho nó nặng nề và khó xử lý, và tôi nên tiếp tục làm việc với các chương trình con? Những lợi ích khi sử dụng các lớp học là gì? Nó không giống như tôi có một số đối tượng, chỉ có tờ và xác nhận trên cột.

Cảm ơn!

Trả lời

6

Nếu có nhiều chương trình con hoặc chương trình con rất dài thì việc cấu trúc mã vào các lớp có thể hữu ích. Nếu chỉ có một vài chương trình con, nói rằng, mỗi chỉ có 10 dòng mã sau đó điều này là hơn giết. Lợi ích của việc cấu trúc mã trong các lớp là việc đọc và thay đổi dễ dàng hơn khi bạn quay trở lại nó xuống dòng. Vì vậy, một lý do khác để cấu trúc mã thành các lớp là nếu mã có thể cần thay đổi xuống dòng

69

Lợi thế của việc sử dụng các lớp thay vì chỉ các chương trình con là các lớp tạo ra mức trừu tượng cho phép bạn viết mã sạch hơn. Phải thừa nhận rằng, nếu bạn chưa bao giờ sử dụng các lớp học trước đây trong VBA, có một đường cong học tập, nhưng tôi tin rằng nó chắc chắn đáng để dành thời gian để tìm ra nó.

Một chỉ báo chính mà bạn nên chuyển sang lớp học là nếu bạn liên tục thêm thông số vào các hàm và chương trình con của mình. Trong trường hợp này, nó hầu như luôn luôn tốt nhất để sử dụng các lớp học.

tôi đã sao chép một lời giải thích của các tầng lớp từ one of my previous Stack Overflow answers:


Dưới đây là một ví dụ dài về cách sử dụng một lớp học có thể giúp bạn. Mặc dù ví dụ này là dài nhưng nó sẽ cho bạn thấy một vài nguyên tắc của lập trình hướng đối tượng thực sự có thể giúp bạn làm sạch mã của bạn như thế nào.

Trong trình chỉnh sửa VBA, hãy truy cập Insert > Class Module. Trong cửa sổ Properties (dưới cùng bên trái của màn hình theo mặc định), thay đổi tên của module thành WorkLogItem. Thêm mã sau vào lớp học:

Option Explicit 

Private pTaskID As Long 
Private pPersonName As String 
Private pHoursWorked As Double 

Public Property Get TaskID() As Long 
    TaskID = pTaskID 
End Property 

Public Property Let TaskID(lTaskID As Long) 
    pTaskID = lTaskID 
End Property 

Public Property Get PersonName() As String 
    PersonName = pPersonName 
End Property 

Public Property Let PersonName(lPersonName As String) 
    pPersonName = lPersonName 
End Property 

Public Property Get HoursWorked() As Double 
    HoursWorked = pHoursWorked 
End Property 

Public Property Let HoursWorked(lHoursWorked As Double) 
    pHoursWorked = lHoursWorked 
End Property 

Mã trên sẽ cung cấp cho chúng tôi đối tượng mạnh mẽ dành riêng cho dữ liệu mà chúng tôi đang làm việc. Khi bạn sử dụng mảng nhiều thứ nguyên để lưu trữ dữ liệu của mình, mã của bạn tương tự như sau: arr(1,1) là ID, arr(1,2) là Tên người dùng và arr(1,3) là HoursWorked. Sử dụng cú pháp đó, thật khó để biết cái gì là gì. Giả sử bạn vẫn tải các đối tượng của bạn vào một mảng, nhưng thay vào đó hãy sử dụng WorkLogItem mà chúng tôi đã tạo ở trên. Tên này, bạn sẽ có thể làm arr(1).PersonName để lấy tên của người đó. Điều đó làm cho mã của bạn dễ đọc hơn nhiều.

Hãy tiếp tục di chuyển với ví dụ này. Thay vì lưu trữ các đối tượng trong mảng, chúng tôi sẽ thử sử dụng collection.

Tiếp theo, thêm mô-đun lớp mới và gọi số ProcessWorkLog. Đặt mã sau đây vào đó:

Option Explicit 

Private pWorkLogItems As Collection 

Public Property Get WorkLogItems() As Collection 
    Set WorkLogItems = pWorkLogItems 
End Property 

Public Property Set WorkLogItems(lWorkLogItem As Collection) 
    Set pWorkLogItems = lWorkLogItem 
End Property 

Function GetHoursWorked(strPersonName As String) As Double 
    On Error GoTo Handle_Errors 
    Dim wli As WorkLogItem 
    Dim doubleTotal As Double 
    doubleTotal = 0 
    For Each wli In WorkLogItems 
     If strPersonName = wli.PersonName Then 
      doubleTotal = doubleTotal + wli.HoursWorked 
     End If 
    Next wli 

Exit_Here: 
    GetHoursWorked = doubleTotal 
     Exit Function 

Handle_Errors: 
     'You will probably want to catch the error that will ' 
     'occur if WorkLogItems has not been set ' 
     Resume Exit_Here 


End Function 

Lớp trên sẽ được sử dụng để "làm điều gì đó" với colleciton WorkLogItem. Ban đầu, chúng tôi chỉ thiết lập để đếm tổng số giờ làm việc. Hãy kiểm tra mã chúng tôi đã viết.Tạo một Module mới (không phải là một mô-đun lớp lần này, chỉ là một mô-đun "thông thường"). Dán đoạn mã sau trong module:

Option Explicit 

Function PopulateArray() As Collection 
    Dim clnWlis As Collection 
    Dim wli As WorkLogItem 
    'Put some data in the collection' 
    Set clnWlis = New Collection 

    Set wli = New WorkLogItem 
    wli.TaskID = 1 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 4.5 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 2 
    wli.PersonName = "Sally" 
    wli.HoursWorked = 3 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 3 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 2.5 
    clnWlis.Add wli 

    Set PopulateArray = clnWlis 
End Function 

Sub TestGetHoursWorked() 
    Dim pwl As ProcessWorkLog 
    Dim arrWli() As WorkLogItem 
    Set pwl = New ProcessWorkLog 
    Set pwl.WorkLogItems = PopulateArray() 
    Debug.Print pwl.GetHoursWorked("Fred") 

End Sub 

Trong đoạn mã trên, PopulateArray() chỉ đơn giản là tạo ra một bộ sưu tập của WorkLogItem. Trong mã thực của bạn, bạn có thể tạo lớp để phân tích các trang tính Excel hoặc các đối tượng dữ liệu của bạn để điền vào một bộ sưu tập hoặc một mảng.

TestGetHoursWorked() chỉ đơn giản là minh họa cách các lớp được sử dụng. Bạn nhận thấy rằng ProcessWorkLog được khởi tạo như một đối tượng. Sau khi nó được khởi tạo, một bộ sưu tập của WorkLogItem trở thành một phần của đối tượng pwl. Bạn nhận thấy điều này trong dòng Set pwl.WorkLogItems = PopulateArray(). Tiếp theo, chúng ta chỉ cần gọi hàm mà chúng ta đã viết có tác dụng lên bộ sưu tập WorkLogItems.

Tại sao điều này hữu ích?

Giả sử thay đổi dữ liệu của bạn và bạn muốn thêm phương thức mới. Giả sử WorkLogItem của bạn hiện bao gồm một trường cho HoursOnBreak và bạn muốn thêm một phương thức mới để tính toán.

Tất cả bạn cần làm là thêm một tài sản để WorkLogItem như vậy:

Private pHoursOnBreak As Double 

Public Property Get HoursOnBreak() As Double 
    HoursOnBreak = pHoursOnBreak 
End Property 

Public Property Let HoursOnBreak(lHoursOnBreak As Double) 
    pHoursOnBreak = lHoursOnBreak 
End Property 

Tất nhiên, bạn sẽ cần phải thay đổi phương thức của bạn cho Populating sưu tập của bạn (phương pháp mẫu Tôi đã từng là PopulateArray(), nhưng bạn có lẽ nên có một lớp riêng biệt chỉ cho việc này). Sau đó, bạn chỉ cần thêm phương pháp mới của bạn đến lớp ProcessWorkLog của bạn:

Function GetHoursOnBreak(strPersonName As String) As Double 
    'Code to get hours on break 
End Function 

Bây giờ, nếu chúng ta muốn cập nhật phương thức của chúng tôi TestGetHoursWorked() để trả về kết quả của GetHoursOnBreak, tất cả chúng ta sẽ phải làm như thêm dòng sau:

Debug.Print pwl.GetHoursOnBreak("Fred") 

Nếu bạn chuyển qua một mảng giá trị đại diện cho dữ liệu của mình, bạn sẽ phải tìm mọi vị trí trong mã nơi bạn đã sử dụng mảng và sau đó cập nhật nó cho phù hợp. Thay vào đó, nếu bạn sử dụng các lớp (và các đối tượng instantiated của chúng), bạn có thể dễ dàng cập nhật mã của mình để làm việc với các thay đổi. Ngoài ra, khi bạn cho phép lớp được tiêu thụ theo nhiều cách (có lẽ một hàm chỉ cần 4 thuộc tính đối tượng trong khi một hàm khác sẽ cần 6), chúng vẫn có thể tham chiếu cùng một đối tượng. Điều này giúp bạn không có nhiều mảng cho các loại hàm khác nhau.

Để đọc thêm, tôi sẽ cao khuyên bạn nên nhận bản sao VBA Developer's Handbook, 2nd edition. Cuốn sách có đầy đủ các ví dụ tuyệt vời và thực hành tốt nhất và tấn mã mẫu. Nếu bạn đang đầu tư nhiều thời gian vào VBA cho một dự án nghiêm túc, bạn cũng nên dành thời gian để xem cuốn sách này.

+7

+1, Câu trả lời tuyệt vời. Rõ ràng, sắc nét và rất hữu ích cho tất cả mọi người. –

+2

+1 cho Sổ tay của Nhà phát triển VBA! –

+0

Vẫn hữu ích 5 năm sau, cảm ơn Ben! +1 từ tôi. – FreeMan

3

Có một điều khác bạn có thể thêm vào những lợi ích mà những người đóng góp khác đã nêu (xin lỗi nếu nó ở đâu đó trong câu trả lời tuyệt vời của Ben McCormack và tôi đã bỏ lỡ nó). Các lớp có thể sử dụng chúng nếu kịch bản VBA của bạn có khả năng được lập trình lại tại một số điểm.

Ví dụ: tôi đang thiết kế một loại hệ thống quản lý đơn hàng. Nó sẽ được sử dụng bởi một số đồng nghiệp trong một thời gian, nhưng nó có thể cần tái progamming nếu quy tắc đặt hàng thay đổi. Do đó, tôi đã thiết kế một lớp mục cổ phiếu cơ bản, tập hợp tất cả thông tin về một mục cổ phiếu. Tuy nhiên, các quy tắc về cách phân tích dữ liệu này cho bất kỳ thứ tự nào, được viết trong các thường trình con được nhận xét dễ dàng và được nhận xét tốt.Bằng cách này, tôi hy vọng rằng các lập trình viên VBA trong tương lai có thể dễ dàng thay đổi các quy tắc toán học theo đó các lệnh được tạo ra mà không phải xử lý tất cả dữ liệu được thu thập về một mục cổ phiếu cụ thể như thế nào (điều này được thực hiện bởi các chương trình con và các hàm trong lớp. , được kích hoạt khi lớp được giao một số cổ phiếu). Các thuộc tính công khai của Class cũng được chọn bởi intellisense, cho phép lập trình viên tiếp theo, cũng như chính bạn, để có thời gian dễ dàng hơn. Tôi đoán điểm là các lớp học có thể giúp cuộc sống dễ dàng hơn cho người dùng sau theo cách này nếu họ mã hóa một số thông tin cơ bản hoặc một số đối tượng khái niệm, luôn có khả năng liên quan đến ngữ cảnh của chương trình sử dụng.

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