Phân biệt khi nào dùng "Set" khi nào không dùng "Set"

Liên hệ QC

Đình Phán

Thành viên thường trực
Tham gia
23/11/10
Bài viết
232
Được thích
68
Giới tính
Nam
Nghề nghiệp
kt
Chào các anh chị,

Em mới tập tành VBA, tuy nhiên thật sự chưa phân biệt được khi nào thì dùng "Set" cho biến, khi nào thì không.
Giả sử em có đoạn Code mở file khác như sau. Khi em thêm Set vào trước DieuKien1 thì SUB không chạy, khi bỏ đi SUB mới chạy.
Anh chị có thể giải thích chi tiết giúp em vì sao được không ạ? Đồng thời hướng dẫn giúp em khi nào dùng "Set", khi nào không?
Em cảm ơn!

Sub MoFile()
Dim DieuKien1 As Boolean
DieuKien1 = Workbooks("Doi soat BBVA thang 5.xlsx").Sheets("Sheet1").Range("B1").Value
If DieuKien1 = True Then
Workbooks.Open Filename:="D:\PHANND\DOANH THU\DOI SOAT\T05\Doi soat Scotiabank thang 5.xlsx"
End If
End Sub
 
Khi em thêm Set vào trước DieuKien1 thì SUB không chạy, khi bỏ đi SUB mới chạy.

Bạn chi tiết thêm "không chạy" có nghĩa là thế nào, và nếu là lỗi thì nó có báo lõi hay không, và nếu có thì lỗi báo ra sao.

Giải thích không khó nhưng nếu có câu báo lỗi của bạn để làm ví dụ thì bạn sẽ dễ hiểu hơn.
 
Upvote 0
Bạn chi tiết thêm "không chạy" có nghĩa là thế nào, và nếu là lỗi thì nó có báo lõi hay không, và nếu có thì lỗi báo ra sao.

Giải thích không khó nhưng nếu có câu báo lỗi của bạn để làm ví dụ thì bạn sẽ dễ hiểu hơn.

Dạ, nó không báo lỗi mà chỉ hiển thị dòng bị sai ạ. SUB không chạy tức không mở được file theo đường dẫn lên.
Mong anh chỉ giúp.
Em cảm ơn!
 
Upvote 0
Lệnh Set chỉ dùng với biến đối tượng, bạn dùng với biến Boolean sẽ lỗi. Cái này do quy định của ngôn ngữ lập trình rồi.
 
Upvote 0
Dạ, nó không báo lỗi mà chỉ hiển thị dòng bị sai ạ. SUB không chạy tức không mở được file theo đường dẫn lên.
Mong anh chỉ giúp.
Em cảm ơn!
Bạn khai báo biến boolean nên nó là 1 biến chứa giá trị true/False. Nói chung tất cả biến chứa giá trị chuỗi, số, ngày, ... đều không dùng Set. Set chỉ dùng khi khai báo biến object và gán giá trị 1 object cho biến.
Nói thêm, biến đối tượng (object) lưu trữ các đối tượng như Cells, Range, Sheet, workbook, Dictionary, Chart, controls, ...
 
Upvote 0
Dữ liệu trong VBA chia ra làm hai loại chính: loại đơn giản (như integer, string, ...) và loại phức tạp (đại khái gọi chung là loại đối tượng, hay Object)

Từ Set mà bạn hỏi nằm trong ngữ cảnh của lệnh gán trị.

Đối với VBA (xem chú thích 1) thì lệnh gán trị gồm từ khoá =
Để phân biệt cách gán của loại đơn giản và loại đối tượng, VBA có luật là lệnh gán đối tượng phải kèm từ khoá Set với =, trong khi lệnh gán đơn giản thì chỉ = trơn (xem chú thích 2)
Nếu a và b là hai biến đơn giản. hi bạn gán a = b thì VBA copy trị chứa trong b nhét vào a. Hai biến a và b là hai cá thể tách rời, không liên quan gì nhau cả.
Object không làm như thế, vì 2 lý do: 1 là copy Object rất tốn tài nguyên máy (xem chú thích 3), và 2 là có những object không thể nào copy được, ví dụ như object range là một vùng trên bảng tính, copy là thế nào? chả có nghĩa lý gì cả.
Vì vậy VBA đặt ra quy luật rằng biến Object chỉ là một con trỏ tham chiếu (reference) đến object. Lúc bạn gán Set ob1 = ob2 thì VBA đem con trỏ ob2 gán vào ob1. Hai biến ob1 và ob1 sau đó cùng chỉ vào một object, không phải là 2 object riêng biệt. Nếu bạn thay đổi một thuộc tính của ob1, sẽ thấy thuộc tính đó trong ob2 thay đổi theo (xem chú thích 4)

Chú thích 1: quy luật gán của mỗi ngôn ngữ mỗi khác. Ở đây chỉ nói VBA. Làm việc với lập trình thì phải nắm vững điều này đầu tiên.

Chú thích 2:
(a) thực ra ngày xưa, BASIC bắt buộc lệnh gán đơn giản phải đi kèm từ khoá Let. Về sau người ta bỏ đi vì thấy không cần thiết.
(b) một số phiên bản BASIC (không phải VB, VBA...) có lệnh LSet và RSet để làm việc với string cho hiệu quả hơn. Nếu bạn để ý sẽ thấy tôi thỉnh thoảng vẫn nói phép gán chuỗi và cộng chuỗi rất tốn tài nguyên máy.

Chú thích 3: object là hiện thân (đối tượng) của class. Bên trong class có thuộc tính và phương thức. Muốn copy một object thì phải copy tất cả các thuộc tính của nó. Bên trong object có thể có phương thức ngầm dùng để ép kiểu và/hoặc đổi dạng. Ví dụ bạn dùng = để gán một range vào một array thì VBA phải gọi một phương thức nào đó để lấy tất cả trị trong từng ô của range và gán vào từng phần tử của array (thực ra nó dùng memory map, rất nhanh). Ngược lại cũng vậy.

Chú thcihs 4: vì sự không tách rời object này mà người ta vẫn khuyên rằng nếu code của bạn có phần Set cái gì đó thì trước khi thoát khỏi hàm nên xét xem có phần Set cái đó = Nothing hay không.
 
Upvote 0
Web KT
Back
Top Bottom