Những câu đố giúp ích cho lập trình code VBA

Liên hệ QC

HeSanbi

Nam Nhân✨Hiếu Lễ Nghĩa Trí Tín✨
Tham gia
24/2/13
Bài viết
2,610
Được thích
4,046
Giới tính
Nam
Hôm nay tôi có hai câu đố mà lập trình viên VBA nên biết để giúp ích cho các bạn trong quá trình lập trình code.
Hai câu hỏi như sau:
1. Có bao nhiêu cách để chú thích code trong IDE VBA?
2. Các bạn đã biết đến lấy giá trị từ một đối tượng, ví dụ như:

Biến a = Range("A1") và a = Range("A1").Value thì cả hai a đều cùng nhận một giá trị.
a = Range("A1") không có hướng sự kiện
a = Range("A1").Value có hướng sự kiện là .Value
Tương tự với nhiều trường hợp:
a = TextBox1 tương đương a = TextBox1.Value
ComboBox1 và ComboBox1.Value
CheckBox1 và CheckBox1.Value
ListBox1 và ListBox1.List
... Rất nhiều
vậy trong VBA viết như thế nào để đạt được cả hai trường hợp có và không có hướng sự kiện như vậy?

Đã trả lời ở #8:

Sau hai câu hỏi trên sẽ có một câu hỏi đặt biệt nữa, mà tôi chắc chắn rằng 99% thành viên lập trình VBA trên diễn đàn chưa biết đến.

Nếu các bạn có thêm câu hỏi nào hóc búa, và có tính chất học hỏi hãy đăng ở bên dưới.
Để các thành viên tham gia.
 
Lần chỉnh sửa cuối:
Câu 1. Có 2 cách
Câu 2. Không hiểu.
Textbox.text và textbox.value khác nhau chỗ nào?
 
Upvote 0
Hôm nay tôi có hai câu đố mà lập trình viên VBA nên biết để giúp ích cho các bạn trong quá trình lập trình code.
Hai câu hỏi như sau:
1. Có bao nhiêu cách để chú thích code trong IDE VBA?
2. Range("A1") và Range("A1").Value, TextBox1 và TextBox1.Value, ... đều cho kết quả như nhau, vậy trong VBA viết như thế nào để đạt được như vậy?


Nếu các bạn có thêm câu hỏi nào hóc búa, và có tính chất học hỏi hãy đăng ở bên dưới.
Để các thành viên tham gia.
Câu 1 : Em cũng chỉ biết 2 cách
Câu 2: chắc khai báo 1 biến và gán biến đó bằng giá trị của textbox rồi gọi chăng?
 
Upvote 0
Thực tình tôi cũng không hiểu ở câu 2 thớt muốn hỏi gì: viết thế nào để đạt được như vậy.
 
Upvote 0
*Câu hỏi thứ 3:
Trong khai báo tiền xử lý
#Const Win64_Plus = TRUE
Ví dụ:​
JavaScript:
#Const Win64_Plus = TRUE
#IF Win64_Plus Then
Function TestLockCode()
   TestLockCode = False
End Function
#End If
Nếu khai báo Toàn cục thì khai báo như thế nào?​


---------------------------------------------------
Thôi thì tôi trả lời hai câu hỏi bài #1, với phương pháp của tôi để cho các bạn tham khảo cho nhanh:

Đáp án câu 1: Có 3 cách comment trong IDE VBA.

1. Dấu nháy đơn (')
2. Từ khóa REM
3. Block Tiền sử lý #IF .. THEN #END IF, Cách thứ 3 này để bạn có thể đọc code dễ dàng để sao chép lại một đoạn code, mà đoạn code đó có đủ Highlight Code để có cái nhìn trực quan cho người lập trình.


Ví dụ:
JavaScript:
' 1. Dau nhay don
REM 2. tu khoa REM
#IF TestLockCode________ Then
Function TestLockCode()
   TestLockCode = False
End Function
#End If
Function TestLockCode()
   TestLockCode = True
End Function

-------------------
Đáp án câu 2:
Khai báo một Attribute VB_UserMemId = 0 trong hàm của một lớp, để khẳng định rằng hàm đấy là hàm chính trong lớp.


Class sẽ có các khai báo Attribute như dưới đây.
Để class hoạt động thì code phải được Import từ tệp bên ngoài.

Cách lập trình này dành cho lập trình viên ở bậc cao, trong lập trình lớp hướng sự kiện.
Nếu các bạn muốn hiểu thêm về khai báo Attribute trong VBA thì có thể tham khảo trên internet.
Ứng dụng của nó là miễn bàn, vì nó ở cấp độ nâng cao.

Các bạn lưu ý ở TextBox có TextBox.Text và TextBox.Value là hai hướng sự kiện khác nhau.
TextBox.Text chỉ trả về giá trị duy nhất là kiểu chuỗi.
TextBox.Value là trả về kiểu giá trị nhập vào trước đó, nếu giá trị nhập là chuỗi số thì kiểu số sẽ được trả về.


JavaScript:
VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "TestObject"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False

Option Explicit
Private backupValue As Variant
Public Property Let Value(ByVal sValue As Variant)
Attribute Value.VB_UserMemId = 0
  backupValue = sValue
End Property
Public Property Get Value()
Attribute Value.VB_UserMemId = 0
  Value = backupValue
End Property

Tải file testObject.txt và import vào VBA.
Copy đoạn code bên dưới vào module để kiểm tra


JavaScript:
Public testClass As TestObject
Private Sub Sub_Test()
  Set testClass = New TestObject
  testClass = 1
  Debug.Print testClass
  testClass.Value = 2
  Debug.Print testClass.Value
End Sub
 

File đính kèm

  • TestObject.txt
    500 bytes · Đọc: 5
Lần chỉnh sửa cuối:
Upvote 0
Câu 2 hình như gọi là thuộc tính mặc định (default property) chứ bạn. Ở link này thì người ta gọi chung là thành viên mặc định (default member).
 
Upvote 0
Bạn đố khó bỏ cha. Trình tớ làm sao trả lời được.
 
Upvote 0
Câu 3: thay vì dùng #Const chỉ có phạm vi private, ta khai báo trong VBA Properties - Conditional comlication arguments sẽ có phạm vi toàn cục.
 
Upvote 0
Hôm nay tôi có hai câu đố mà lập trình viên VBA nên biết để giúp ích cho các bạn trong quá trình lập trình code.
Hai câu hỏi như sau:
1. Có bao nhiêu cách để chú thích code trong IDE VBA?
2. Các bạn đã biết đến lấy giá trị từ một đối tượng, ví dụ như:

Biến a = Range("A1") và a = Range("A1").Value thì cả hai a đều cùng nhận một giá trị.
a = Range("A1") không có hướng sự kiện
a = Range("A1").Value có hướng sự kiện là .Value
Tương tự với nhiều trường hợp:
a = TextBox1 tương đương a = TextBox1.Value
ComboBox1 và ComboBox1.Value
CheckBox1 và CheckBox1.Value
ListBox1 và ListBox1.List
... Rất nhiều
vậy trong VBA viết như thế nào để đạt được cả hai trường hợp có và không có hướng sự kiện như vậy?

Đã trả lời ở #8:

Sau hai câu hỏi trên sẽ có một câu hỏi đặt biệt nữa, mà tôi chắc chắn rằng 99% thành viên lập trình VBA trên diễn đàn chưa biết đến.

Nếu các bạn có thêm câu hỏi nào hóc búa, và có tính chất học hỏi hãy đăng ở bên dưới.
Để các thành viên tham gia.
Câu 1: có 3 cách
 
Upvote 0
vậy trong VBA viết như thế nào để đạt được cả hai trường hợp có và không có hướng sự kiện như vậy?
Câu 2 anh @HeSanbi cho mình hỏi lợi ích của việc hướng tới việc gộp chung 2 trường hợp thành 1 là gì? Theo mình biết việc gõ .text và .value sẽ cho hai kết quả khác nhau, tùy vào mục đích mình muốn dùng thuộc tính nào. Nếu mình định dạng ngoài Range("A1") giá trị ngày tháng thành format("yyyy-mm-dd") thì khi muốn lấy định dạng thì ta dùng thuộc tính .Text, khi muốn lấy giá trị theo type thì mình chọn thuộc tính .Value, cũng như một số control trong userform, combobox nạp vào 2 cột, 1 cột text hiển thị cho người dùng, 1 cột value tương ứng dùng cho việc xử lý thông tin đằng sau mà người dùng không nhìn thấy.
 
Upvote 0
Câu 2 anh @HeSanbi cho mình hỏi lợi ích của việc hướng tới việc gộp chung 2 trường hợp thành 1 là gì? Theo mình biết việc gõ .text và .value sẽ cho hai kết quả khác nhau, tùy vào mục đích mình muốn dùng thuộc tính nào. Nếu mình định dạng ngoài Range("A1") giá trị ngày tháng thành format("yyyy-mm-dd") thì khi muốn lấy định dạng thì ta dùng thuộc tính .Text, khi muốn lấy giá trị theo type thì mình chọn thuộc tính .Value, cũng như một số control trong userform, combobox nạp vào 2 cột, 1 cột text hiển thị cho người dùng, 1 cột value tương ứng dùng cho việc xử lý thông tin đằng sau mà người dùng không nhìn thấy.
Hiểu đơn giản:
.Text trả về chuỗi
.Value trả về giá trị có thể tính toán

Nếu bạn lấy số trong .Text để tính thì Trình dịch sẽ thêm một vài bước nữa để chuyển sang số, dẫn đến tốn tài nguyên.
 
Lần chỉnh sửa cuối:
Upvote 0
Câu 2 anh @HeSanbi cho mình hỏi lợi ích của việc hướng tới việc gộp chung 2 trường hợp thành 1 là gì?
Thực ra không phải là gộp chung mà là thay vì viết a = Range("A1").Value thì có thể viết a = Range("A1")

1. Về viết tắt.
Khi viết code VBA nếu các bạn có thể viết tường minh thì nên viết tường minh. Tôi không thích kiểu a = Range("A1"). Viết tường minh a = Range("A1").Value thôi.

2. Về 2 kiểu viết mà ý nghĩa như nhau thì nó là thế này: Giả sử ta có đối tượng ABC, và nó có thuộc tính, phương thức xyz. Lúc này a = ABC.xyz (xyz là thuộc tính) tương đương với a = ABC, hoặc ABC.xyz (xyz là phương thức) tương đương với ABC KHI VÀ CHỈ KHI xyz là thuộc tính, phương thức MẶC ĐỊNH của đối tượng ABC.

Từ 2 cũng thấy là nếu đối tượng ABC không có thuộc tính nào là mặc định (thường sảy ra khi lớp - class là do user tạo ra) thì không bao giờ có chuyện (vd. a As Long) viết a = ABC. Sẽ có lỗi.

Khi xyz là thuộc tính mặc định của đối tượng ABC thì thay vì viết a = ABC.xyz ta có thể viết a = ABC. Nhưng cái thú vị nó không nằm ở chỗ viết ít tiết kiệm ngón tay, viết không tường minh để đánh đố người khác, làm code trở nên tối đi. Cái mẫu chốt là có những tình huống trong VBA khi không có cái gọi là "thuộc tính mặc định" thì ta sẽ khóc ròng hoặc rất cực. Tôi cho ví dụ cụ thể như sau.

Tải tập tin "download user posts.xlsm" từ bài #1 tôi đã viết từ 3 năm trước:


-> mở tập tin -> Alt + F11 -> chọn clsXMLHTTPHandler trong "Class Modules" -> menu File -> Export File ... -> chọn vd. Desktop -> mở tập tin clsXMLHTTPHandler.cls trong notepad -> sẽ thấy như sau:
...
Sub EventCallback()
Attribute EventCallback.VB_UserMemId = 0
If XmlHttpRequest.readyState = 4 Then
If XmlHttpRequest.Status = 200 Then
If Len(pCallback) Then Application.Run pCallback, XmlHttpRequest.responseText, plink, pid, Me
Set XmlHttpRequest = Nothing
End If
End If
End Sub

Private Sub Class_Initialize()
Set XmlHttpRequest = CreateObject("MSXML2.XMLHTTP")
XmlHttpRequest.OnReadyStateChange = Me
End Sub


Do có đỏ đỏ nên EventCallback là MẶC ĐỊNH.

Dòng XmlHttpRequest.OnReadyStateChange = Me thực ra tường minh nó là XmlHttpRequest.OnReadyStateChange = Me.EventCallback

Ý nghĩa của thiết lập như thế là: mỗi khi sảy ra sự kiện OnReadyStateChange thì thực hiện code của EventCallback

Thử nghiệm
:
Các bạn thêm 1 module với code
Mã:
Option Explicit

Public myClass As clsXMLHTTPHandler

Sub test()
    Set myClass = New clsXMLHTTPHandler
    Set myClass = Nothing
End Sub

Sau đó các bạn chạy sub test. Tất nhiên code này "vô lý" vì nó chả làm gì. Nhưng các bạn chạy được code.

Bây giờ sửa trong clsXMLHTTPHandler thành
Private Sub Class_Initialize()
Set XmlHttpRequest = CreateObject("MSXML2.XMLHTTP")
XmlHttpRequest.OnReadyStateChange = Me.EventCallback
End Sub

Bây giờ các bạn không chạy được sub test vì có lỗi như hình

loi.jpg

Như vậy chuyện viết a = ABC thay cho ABC.xyz không chỉ đơn giản là "tiết kiệm ngón tay và sơn móng tay, viết không tường minh để đánh đố người khác, làm code trở nên tối đi" mà là đôi khi không thể làm khác hoặc rất cực. Trong trường hợp này không thể viết tường minh, và do vậy phải thiết lập sao cho EventCallBack là MẶC ĐỊNH của đối tượng clsXMLHTTPHandler.
 
Upvote 0
Do có đỏ đỏ nên EventCallback là MẶC ĐỊNH.

Dòng XmlHttpRequest.OnReadyStateChange = Me thực ra tường minh nó là XmlHttpRequest.OnReadyStateChange = Me.EventCallback
Đồng ý với bác là EventCallback lúc này là thành viên mặc định và nó còn là một sub ( tức không trả lại giá trị), Cháu đang nghĩ xem có phải OnReadyStateChange là thuộc tính chứa object, để khi dùng tới thì nó kết nối tới thành viên mặc định của object đó không?
Bài đã được tự động gộp:

.Text trả về chuỗi
.Value trả về giá trị có thể tính toán
Bạn có thể tạo một ví dụ để mình họa rõ nét điều này không, mình quan tâm tới sự khác biệt của hai thuộc tính này.
 
Upvote 0
Web KT

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

Back
Top Bottom