VBA Nâng cao: WinAPI - Khai báo Long và LongPtr tương thích đa nền tảng (2 người xem)

Liên hệ QC

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

HeSanbi

Nam Nhân✨Hiếu Lễ Nghĩa Trí Tín✨
Tham gia
24/2/13
Bài viết
2,782
Được thích
4,434
Giới tính
Nam
Nếu các bạn đang hăng say học VBA hoặc đang lập trình VBA và vọc mã WinAPI thì hãy học ngay mẹo này để viết cho ứng dụng của bạn gọn nhẹ hơn. Khi ứng dụng của bạn viết đa nền tảng và đa phiên bản thì gặp phải nhiều vấn đề về tương thích. Nhất là khai báo Long, LongPtr, LongLong, hoặc các hàm VarPtr, StrPtr, ...
Hoặc các bạn cần bộ nhớ kiểu biến lớn hơn là LongLong trong dự án của bạn. Để tận dụng vào các thuật toán mà bạn tạo ra.

Với mẹo vô cùng đơn giản dưới đây là các bạn có thể bỏ qua các dòng mã rườm rà làm mã của bạn rối và khó đọc.

Đơn giản thôi các bạn hãy thêm dòng mã sau vào bất kì dự án nào của bạn có sử dụng các API 32 và 64 bit.


JavaScript:
#If VBA7 = 0 Then
   Public Enum LongLong:[__]:End Enum
   Public Enum LongPtr:[_]:End Enum
#End If

***Lưu ý: Khi các bạn chép mã vào VBA, nếu các dòng mã Hiện màu đỏ là bình thường nhé. VBA sẽ không thông dịch mã đó, vì hệ điều hành của các bạn tương thích mã đủ điều kiện.
(Mã này không nên đặt vào module có khai báo cục bộ là Option Private Module.
Vì sẽ không thể khai báo tham chiếu biến trong Class và Module Object (Sheet, Form).

Hãy chạy thử thủ tục TestPretreatment dưới đây để xem thông tin máy tính và Office

JavaScript:
Sub TestPretreatment ()
#If VBA7 Then
#If Win64 Then
     Debug.Print "VBA7 64bit"
#Else
     Debug.Print "VBA7 32Bit"
#End If
#ElseIf VBA6 Then
#If Win64 Then
     Debug.Print "VBA6 64bit"
#Else
     Debug.Print "VBA6 32Bit"
#End If
#Else
     Debug.Print "________"
#End If
End Sub



Như đã nói trên, chỉ cần các bạn khai báo như vậy là có thể viết những dòng mã tương thích đa nền tảng mà không cần phải nhờ đến hai PC hoặc hai ứng dụng khác phiên bản để kiểm thử mã, sau khi đã viết mã tương thích.

Ví dụ khai báo như sau, sẽ làm cho mã bị rối và dài:


JavaScript:
#If VBA7 And Win64 Then
Private Sub TimeProc_ApiWindowFlexMove(ByVal hwnd As LongPtr, ByVal wMsg^, ByVal idEvent As LongPtr, ByVal dwTime^)
#ElseIf VBA7 Then
Private Sub TimeProc_ApiWindowFlexMove(ByVal hwnd As LongPtr, ByVal wMsg&, ByVal idEvent As LongPtr, ByVal dwTime&)
#Else
Private Sub TimeProc_ApiWindowFlexMove(ByVal hwnd&, ByVal wMsg&, ByVal idEvent&, ByVal dwTime&)
#End If
End Sub

Bạn chỉ cần khai báo như sau, khi đã chép mã đã nói trên:
JavaScript:
Private Sub TimeProc_ApiWindowFlexMove(ByVal hwnd As LongPtr, ByVal wMsg As LongLong, ByVal idEvent As LongPtr, ByVal dwTime As LongLong)

End Sub


Các khai báo trước đây, như dưới đây hãy bỏ nó đi:

JavaScript:
#If VBA7  Then
Dim hwnd As LongPtr
#Else
Dim hwnd As Long
#End If

Và bây giờ các bạn chỉ cần khai báo, khi có mã đã nói trên, là đủ để tương thích, mà không cần khai báo tiền xử lý #:
JavaScript:
Dim hwnd As LongPtr

Với mẹo khai báo biến Long như vậy, các bạn có thể chép lại mã có các API với các tham số biến LongPtr, LongLong rất đơn giản.

Nếu các bạn chép mã API đang ở nền tảng win64, thì chỉ cần bỏ PtrSafe trong dòng mã để tương thích với Nền tảng win32 (Còn tùy thuộc vào hàm API, có hàm API không có ở Win32).
Bạn không cần sửa LongPtr, LongLong thành Long để tương thích với win32 nữa. Khi đã có mã nói trên.


Lưu ý: Sửa từ API không có PtrSafe sang API có PtrSafe thì có những trường hợp Long phải sửa thành LongPtr hoặc LongLong

Ví dụ khai báo tương thích và các hàm API tương thích đa nền tảng:

JavaScript:
' Khai báo tương thích đa nền tảng
#If VBA7 = 0 Then
   Public Enum LongLong:[__]:End Enum
   Public Enum LongPtr:[_]:End Enum
#End If
' Các hàm API tương thích đa nền tảng
#If VBA7 Then
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As Any, ByVal hwnd As LongPtr) As Long
#Else
Private Declare Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As Any, ByVal hwnd As LongPtr) As Long
#End If

#If VBA7 Then
  #If Win64 Then
  Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
  Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
  Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
  Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
  #Else
  Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
  Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  Declare PtrSafe Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
  Private Declare PtrSafe Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  #End If
#Else
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetClassLong Lib "user32" Alias "GetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetClassLong Lib "user32" Alias "SetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End If

Có thể các bạn đang hỏi tại sao lại có kiểu LongPtr. Đơn giản thôi, nó là kiểu khai báo tương thích. Nếu LongPtr ở môi trường 32 bit thì nó là Long, nếu nó ở 64bit thì nó là LongLong. Nó không thực sự là Long và LongLong.

Ngay từ lúc này tôi khuyên các bạn nên tận dụng Kiểu LongLong vì nó khai thác bộ nhớ lớn hơn Long khá nhiều.
Vì khi bạn đang sử dụng Win64 mà lại dùng kiểu Long cho một thuật toán mạnh mẽ thì thật là tiếc nuối cho đà phát triển của bạn.


Mẹo tôi hướng dẫn trên đây sẽ giúp các bạn đơn giản việc viết mã đa nền tảng, các bạn có thể tận dụng nó trên con đường lập trình của mình.
Chúc các bạn thành công!

-------------------------------------------
Các bạn có thể tham khảo thêm bài viết của tôi tại tag
#sanbi udf
 
Lần chỉnh sửa cuối:
Giải pháp
Thay bằng Public cũng báo lỗi vậy thôi bạn.
Cảm ơn Bác nhé!

Vậy là kết luận, không có lỗi như Bác đã báo cáo ở #4.

Vì khi tôi viết bài viết khai báo đầu tiên mã nên sử dụng để tương thích như dưới đây:

JavaScript:
#If VBA7 Then
#Else
   Public Enum LongPtr:[_]:End Enum
   Public Enum LongLong:[__]:End Enum
#End If

Các cách khai báo sau đều phù hợp để tận dụng:

JavaScript:
#If VBA7 = 0 Then
   Public Enum LongPtr:[_]:End Enum
   Public Enum LongLong:[__]:End Enum
#End If
Hay quá! Để lúc nào lôi cái mã 32 ra cải tạo lại xem.
 
Upvote 0
Em cũng có file, trước được thầy viết trên nền Office 32bit, giờ máy lại cài Office 64bit, nên chạy lỗi.
Mong anh @HeSanbi có thể giúp đỡ.
 
Upvote 0
Chỗ khai báo LongPtr này không được bạn à?
1680054150970.png
 
Upvote 0
Win11 64 bit và Office 2019 32bit
Bác kiểm thử mã dưới.
Vì kiểu khai báo LongPtr vẫn có trong Win64 và VBA Office32bit nên buộc phải làm như vậy


JavaScript:
#If VBA7 Then
#Else
Public Enum LongLong: [_]: End Enum
#If Win64 Then
#ElseIf Win32 Then
#Else
Public Enum LongPtr: [_]: End Enum
#End If
#End If
 
Lần chỉnh sửa cuối:
Upvote 0
Bác kiểm thử mã dưới.
Vì kiểu khai báo LongPtr vẫn có trong Win64 và VBA Office32bit nên buộc phải làm như vậy


JavaScript:
#If VBA7 Then
#Else
Public Enum LongLong: [_]: End Enum
#const office32 = true
#If office32 Then
#Else
Public Enum LongPtr: [_]: End Enum
#End If
#End If
Cũng vậy bạn ơi. Máy vẫn không đồng ý với LongPtr
 
Upvote 0
Win11 64 bit và Office 2019 32bit
Nếu không được nữa thì bác tiếp tục thử mã dưới đây, vì tôi chỉ có một pc 64bit và office 64bit nên không thể kiểm tra được hết. Mã tôi viết chỉ dựa theo kinh nghiệm lập trình.

JavaScript:
#If VBA7 Then
  #If Win64 Then
  #ElseIf Win32 Then
  #Else
  #End If
#Else
  Public Enum LongLong:[_]:End Enum
  #If Win32 Then
  #Else
    Public Enum LongPtr:[_]:End Enum
  #End If
#End If
 
Upvote 0
Nếu không được nữa thì bác tiếp tục thử mã dưới đây, vì tôi chỉ có một pc 64bit và office 64bit nên không thể kiểm tra được hết. Mã tôi viết chỉ dựa theo kinh nghiệm lập trình.

JavaScript:
#If VBA7 Then
  #If Win64 Then
  #ElseIf Win32 Then
  #Else
  #End If
#Else
  Public Enum LongLong:[_]:End Enum
  #If Win32 Then
  #Else
    Public Enum LongPtr:[_]:End Enum
  #End If
#End If
LongPtr để vào đâu cũng không được chấp nhận. Có lẽ câu lệnh đó không đúng.
 
Upvote 0
Không biết áp dụng code có đúng chưa nhưng tôi thử nghiệm thì thấy chạy bình thường trên:
- Windows 10 64, Office 2103 32
- Windows 11 64, Office 2021 64

Screen Shot 2023-03-29 at 10.54.55.png
 
Upvote 0
Tại trên GPE này họ ít quan tâm tới VB6 vì xem là thứ đã bỏ đi lâu rồi ... còn Tôi lâu lâu vẫn ngó tới nó

Kỹ thuật này khoãng 6 năm trước tay code Nga ngố đã dùng rồi kiểu như sau

Mã:
#Const HasPtrSafe = (VBA7 <> 0)
#If HasPtrSafe Then
    Private Declare PtrSafe Function SHCreateStreamOnFile Lib "shlwapi" Alias "SHCreateStreamOnFileW" (ByVal pszFile As LongPtr, ByVal grfMode As Long, ppStm As stdole.IUnknown) As Long
    Private Declare PtrSafe Function DispCallFunc Lib "oleaut32" (ByVal pvInstance As LongPtr, ByVal oVft As LongPtr, ByVal lCc As Long, ByVal vtReturn As VbVarType, ByVal cActuals As Long, prgVt As Any, prgpVarg As Any, pvargResult As Variant) As Long
#Else
    Private Enum LongPtr
        [_]
    End Enum
    Private Declare Function SHCreateStreamOnFile Lib "shlwapi" Alias "SHCreateStreamOnFileW" (ByVal pszFile As LongPtr, ByVal grfMode As Long, ppStm As stdole.IUnknown) As Long
    Private Declare Function DispCallFunc Lib "oleaut32" (ByVal pvInstance As LongPtr, ByVal oVft As LongPtr, ByVal lCc As Long, ByVal vtReturn As VbVarType, ByVal cActuals As Long, prgVt As Any, prgpVarg As Any, pvargResult As Variant) As Long
#End If

chịu khó tìm chút có File WinAPI.tlb trong đó họ khai báo hết các hàm API của Windows và các hằng của nó ... còn ta chỉ xơi
Trên VBA Add nó vào là dùng mà không cần khai báo API và các hằng nữa
xem hình

1680063547271.png
 
Upvote 0
Người ta đang cố gắng bớt khai báo và sử dụng API từ VBA cho tốc độ code chạy nhanh hơn còn mình cắm đầu khai báo cho lắm lại càng ngu

Khi Excel mở lên nó tính toán lại mọi cái trong File ... càng khai báo nhiều API là càng tăng thêm phần Ngu
 
Upvote 0
Tự nhận mình "ngu" thì về học những cái ngu thôi
 
Upvote 0
trong 1 File .TLB có file lớn có cả 1000 hàm API + các hằng khai báo sẳn khi Add vào Excel nó bình thường như những File Excel chưa gì trong đó
xong Lưu lại xem là thấy

Còn 1 File Excel khai khoãng 1000 hàm API + các hằng trong đó ... mở lên xem mới thấy ....

2 cái nó khác nhau hoàn toàn 1 cái sử dụng TLB còn 1 cái viết cả 1000 hàm + Hằng trên Module VBA
 
Lần chỉnh sửa cuối:
Upvote 0
@ptm0412
Tôi tưởng rằng thánh "khoe hàng" không bao giờ rãnh rỗi ghé bài viết tôi khoe "giống", nay độc lạ xuất hiện, tôi hơi ngỡ ngàng, nên mời bác vào xem trưng bày. Tiễn được bác tiễn giùm tôi sang "Dubai chơi siêu xe" giúp tôi.

Thánh này được "người ngoài hành tinh" phái xuống trái đất khoe "công nghệ ngoài hệ mặt trời" tôi không thể tiếp nhận kịp công nghệ đó. Nên mời thánh lên đĩa bay về lại không gian.
 
Upvote 0
Sao lại lôi tôi vào những tranh cãi và chửi nhau ngu? Ai cũng có câu chửi đối phương là ngu thì kêu tôi vào ban nick cả 2 à?
Thánh đấy tự nhận ngu chứ tôi hơi sức nào. Tôi cho thánh vào danh sách "Vip" từ vài năm trước rồi. Kiểu người khoe khoang, học của người xong lấy làm của mình. Rồi lại đi khoe lại cho người.

Không xứng đáng để tôi bỏ vài giây để "xoi"
 
Upvote 0
Không thể đem cái file TLB ứng dụng trong VB6 để lập trình cho môi trường VBA được bởi vì VBA (từ Office 2010 trở lên) người lập trình phải tích hợp cả hai tình huống 32-bit và 64-bit trong một project, trong khi VB6 chỉ là 32-bit.
File TLB tạo ra bởi C++ hoặc Delphi hay IDE nào đó nó (biết định nghĩa cho Windows hiểu) không có kiểu LongLong hay LongPtr, Any vì thế file định nghĩa các hàm API khó có thể thể bao đủ tính huống, cách áp dụng trong VBA, hay có thể làm cho linh động so với việc hiểu và tự khai báo API.
Bản chất những gì khai báo trong file TLB rồi trong VBA lại nhúng vào thì VBA vẫn phải nạp vạp bộ nhớ thì trình biên dịch mới compile được chứ. Vì thế việc nhúng TLB vào với các khai báo các hàm API thừa thãi sẽ làm ứng dụng bị chiếm dụng bộ nhớ.

Tôi thấy topic này của tác giả là hữu ích cho mọi người cần học lập trình API trong VBA nên để người ta vui vẻ và tâm huyết làm.
 
Upvote 0
Không thể đem cái file TLB ứng dụng trong VB6 để lập trình cho môi trường VBA được bởi vì VBA (từ Office 2010 trở lên) người lập trình phải tích hợp cả hai tình huống 32-bit và 64-bit trong một project, trong khi VB6 chỉ là 32-bit.
File TLB tạo ra bởi C++ hoặc Delphi hay IDE nào đó nó (biết định nghĩa cho Windows hiểu) không có kiểu LongLong hay LongPtr, Any vì thế file định nghĩa các hàm API khó có thể thể bao đủ tính huống, cách áp dụng trong VBA, hay có thể làm cho linh động so với việc hiểu và tự khai báo API.
Bản chất những gì khai báo trong file TLB rồi trong VBA lại nhúng vào thì VBA vẫn phải nạp vạp bộ nhớ thì trình biên dịch mới compile được chứ. Vì thế việc nhúng TLB vào với các khai báo các hàm API thừa thãi sẽ làm ứng dụng bị chiếm dụng bộ nhớ.

Tôi thấy topic này của tác giả là hữu ích cho mọi người cần học lập trình API trong VBA nên để người ta vui vẻ và tâm huyết làm.
Tôi không tranh cải thớt này nữa .... Tôi nói lại là trước đây họ viết TLB chỉ có 32 bít sử dụng cho VB6 ... thì này họ thêm cả 64 bít và sử dụng cho VBA rồi bao gồm cả các hằng khai báo cho 64 bít

còn các chuyện khác tôi không bàn cải

Tôi đưa ra 1 ví dụ còn bạn tự suy nghĩ

1/ Khi cái Atools.dll của Bạn mang hết các hàm đó viết vào trong 1 File trên Module VBA thì khi mở File Excel lên buộc nó sẽ tính toán lại mọi cái có trên Excel

2/ Khi Check Atools.dll khai báo COM kết nối sớm cho VBA thì khi nào bạn cần sử dụng Hàm liên quan Tới Atools.dll thì nó mới chi phí thời gian phát sinh và chạy code còn không thì thôi nên nó sẽ rất nhanh hơn viết hết tất cả vào 1 Module trên VBA

3/ chi phí thời gian cho tham chiếu thư viện ngoài là không đáng kể ... quá nhỏ

.................
 
Lần chỉnh sửa cuối:
Upvote 0
Trong lúc chúng ta đang tranh cãi về sử dụng API 32 64
Thì người ta đã đưa chúng lên công nghệ web, đám mây từ lâu, việc cập nhật bấy giờ đơn giản do người chủ server quản lý (hay những nhà cung cấp dịch vụ quản lý) thay vì phải lo việc sai khác nữa.

Nên có thể bàn cứ bàn, có ích thì còn có ích cho chúng ta, và vài ứng dụng vừa trong 1 application hay môi trường cụ thể.
Còn để có giá trị hữu ích thật thì ta phải thay đổi từ hệ thống quan niệm. Và ngay cả cách chúng ta bàn luận và để xây dựng phát triển.

Góc độ tôi, thì hạn chế sử dụng các API _vì ta đâu biết mai họ (hệ điều hành) lại thay đổi, cực chẳng đã buộc phải áp dụng - thường xảy ra khi muốn thiệp vào hệ thống, giao diện , con trỏ (mouse) ...vvv
 
Lần chỉnh sửa cuối:
Upvote 0
LongPtr để vào đâu cũng không được chấp nhận. Có lẽ câu lệnh đó không đúng.
Máy Bác @Maika8008 còn lỗi này không.

Nếu còn bác thử với mã sau xem sao, chạy thử thủ tục TestPretreatment để xem trong Immediate giá trị trả lại.

JavaScript:
#If (VBA6 And Win64 = 0) Or (VBA7 = 0 And VBA6 = 0) Then
  Public Enum LongLong:[_]:End Enum
  Public Enum LongPtr:[_]:End Enum
#End If

Sub TestPretreatment ()
#If VBA7 Then
#If Win64 Then
     Debug.Print "VBA7 64bit"
#Else
     Debug.Print "VBA7 32Bit"
#End If
#ElseIf VBA6 Then
#If Win64 Then
     Debug.Print "VBA6 64bit"
#Else
     Debug.Print "VBA6 32Bit"
#End If
#Else
     Debug.Print "________"
#End If
End Sub
 
Upvote 0
Máy Bác @Maika8008 còn lỗi này không.

Nếu còn bác thử với mã sau xem sao, chạy thử thủ tục TestPretreatment để xem trong Immediate giá trị trả lại.

JavaScript:
#If (VBA6 And Win64 = 0) Or (VBA7 = 0 And VBA6 = 0) Then
  Public Enum LongLong:[_]:End Enum
  Public Enum LongPtr:[_]:End Enum
#End If

Sub TestPretreatment ()
#If VBA7 Then
#If Win64 Then
     Debug.Print "VBA7 64bit"
#Else
     Debug.Print "VBA7 32Bit"
#End If
#ElseIf VBA6 Then
#If Win64 Then
     Debug.Print "VBA6 64bit"
#Else
     Debug.Print "VBA6 32Bit"
#End If
#Else
     Debug.Print "________"
#End If
End Sub
Nó báo lỗi identifier chỗ LongPtr bạn à. Nếu sửa LongPtr thành gì đó (chẳng hạn LongPtrA) thì Sub TestPretreatment chạy cho ra kết quả là: VBA7 32Bit.

Máy tôi: Win 64 và Office 32
 
Upvote 0
@Maika8008 Bác thử thêm lần nữa mã dưới đây xem sao

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
#Else
  Public Enum LongLong:[_]:End Enum
  Public Enum LongPtr:[_]:End Enum
#End If
 
Upvote 0
Nếu khôn ấy thì từng bước loại bỏ sự lệ thuộc vào các hàm API của Ms ra xong sử dụng bất kỳ 1 Tools lập trình hiện đại nào đang phát triển mà viết

trừ khi không có khả năng thì loanh quan luẩn quẩn tái sử dụng lại các hàm API của Ms

Việc tái sử dụng hàm API có nhiều hàm Ms không công bố hoặc không có chỉ dẫn mà do người dùng mò mẫm xong viết các hàm trung gian và khai báo các hằng tùy chỉnh cho nó nên có trường hợp đúng trên máy này và sai trên máy khác xong lại mò tiếp ....

còn trên VBA thì quá lỗi thời , tù túng và ọp ẹp khi muốn bứt phá ra và phát triển lên 1 tầm cao mới không có gì hay cả khi dựa vào nền tảng đã phát triển mấy chục năm trước không còn phát triển nữa

cứ loanh quanh luẩn quẩn hoài trên VBA xong tái sử dụng các Hàm API khai báo kiểu mò mẫm thì không phải là giải pháp khôn lắm --=0
 
Lần chỉnh sửa cuối:
Upvote 0
Cũng vậy thôi. Máy không chấp nhận LongPtr.
Máy của bác Thông dịch cả mã nằm trong khối phủ định của tiền xử lý, vẫn không hiểu sao lại có chuyện này xảy ra.

Nhét LongPtr tới tận Win16 bit, mà còn lỗi nữa thì không có cách nào khác. (win16 thì không còn dành cho người dùng cuối)

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
#Else
    #If Win64 Then
    #ElseIf Win32 Then
    #Else
          Public Enum LongLong:[_]:End Enum
          Public Enum LongPtr:[_]:End Enum
    #End If
#End If


Không biết GPE, máy tính bạn nào chạy Windows 11 64bit và Office 32bit có gặp điều tương tự không.
 
Lần chỉnh sửa cuối:
Upvote 0

Theo hình chụp thì bạn khai báo sai kìa. Sao lại #ElseIf Win32. Đã test cả Windows XP, Office 2003 cũng Ok.

Máy tôi Windows 10 64-bit, Office 365 32-bit không lỗi.
Code điều hướng biên dịch trong VBA không cho phép sử dụng các toán tử NOT, AND, OR, = để kết hợp tạo biểu thức. Nếu đưa vào là lỗi, tôi từng kiểm nghiệm việc này. Vậy nên chỉ khai báo code chân phương như #IF VBA7 hay #IF VBA6 , #ElseIf VBA7 (hoặc VBA6) thì OK.
 
Upvote 0
Upvote 0
Máy của bác Thông dịch cả mã nằm trong khối phủ định của tiền xử lý, vẫn không hiểu sao lại có chuyện này xảy ra.

Nhét LongPtr tới tận Win16 bit, mà còn lỗi nữa thì không có cách nào khác. (win16 thì không còn dành cho người dùng cuối)

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
#Else
    #If Win64 Then
    #ElseIf Win32 Then
    #Else
          Public Enum LongLong:[_]:End Enum
          Public Enum LongPtr:[_]:End Enum
    #End If
#End If
Vẫn thế thôi bạn. Nằm ở đâu thì nó vẫn từ chối.
 
Upvote 0
Máy của bác Thông dịch cả mã nằm trong khối phủ định của tiền xử lý, vẫn không hiểu sao lại có chuyện này xảy ra.

Nhét LongPtr tới tận Win16 bit, mà còn lỗi nữa thì không có cách nào khác. (win16 thì không còn dành cho người dùng cuối)

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
#Else
    #If Win64 Then
    #ElseIf Win32 Then
    #Else
          Public Enum LongLong:[_]:End Enum
          Public Enum LongPtr:[_]:End Enum
    #End If
#End If


Không biết GPE, máy tính bạn nào chạy Windows 11 64bit và Office 32bit có gặp điều tương tự không.

Máy tôi không bị lỗi nhé. Windows 11 64bit + Office 2013 32bit.

Screen Shot 2023-10-11 at 12.10.56.png


@cantl: code bị đỏ trong khai báo cho Win32/64 là bình thường khi nó ở các môi trường khác nhau, quan trong là Compile không báo lỗi.
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
@Maika8008 @cantl
Trời đất, mã màu đỏ không phải là lỗi, mà là mã tương thích giữa các Windows và Office. VBA sẽ đọc mã đủ điều kiện để thông dịch.
Vì #If là tiền xử lý mã.

Vậy là lâu nay bỏ công đi tìm lỗi, là do các Bác hiểu sai về cách VBA thông dịch mã

Không biết có ai nhầm giữa thông dịch và biên dịch không? "chạy đâu khỏi nắng"
 
Lần chỉnh sửa cuối:
Upvote 0
VBA không cho phép sử dụng các toán tử NOT, AND, OR, = để kết hợp tạo biểu thức. Nếu đưa vào là lỗi, tôi từng kiểm nghiệm việc này
Chắc anh có hiểu lầm gì rồi.
Hoàn toàn không có lỗi khi sử dụng các toán tử này.

MAC, VBA7, VBA6, VBA5, Win64, Win32, Win16 là các đối số biên dịch có giá trị 0 hoặc 1

Sử dụng các toán tử bình thường, nhưng hãy so sánh các đối số này với 0, như sau:

VBA7 <> 0 AND WIN64 <> 0
NOT -VBA7 sẽ trả về 0 (False), NOT VBA7 là NOT 1 trả về -2 vẫn là TRUE.

Các toán tử không phải trả về Boolean, đã đề cập tại bài viết, không biết anh đã đọc qua bài viết này chưa?

 
Upvote 0
@Maika8008 @cantl
Trời đất, mã màu đỏ không phải là lỗi, mà là mã tương thích giữa các Windows và Office. VBA sẽ đọc mã đủ điều kiện để thông dịch.
Vì #If là tiền xử lý mã.

Vậy là lâu nay bỏ công đi tìm lỗi, là do các Bác hiểu sai về cách VBA thông dịch mã

Không biết có ai nhầm giữa thông dịch và biên dịch không? "chạy đâu khỏi nắng"
Xin lỗi đã làm cho bạn phải vất vả. Tôi không biết thông dịch với biên dịch, cứ thấy màu đỏ thì nghĩ là lỗi gì rồi.
 
Upvote 0
@Maika8008
Bác kiểm tra giúp đoạn mã xem có còn lỗi gì không.
Bác nhớ vào Debug nhấn Compile .... xem có cảnh báo identifier nữa không.

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
  Public Enum LongLong:[_]:End Enum
  #If Win64 = 0 Then
    Public Enum LongPtr:[_]:End Enum
  #End If
#Else
  Public Enum LongLong:[_]:End Enum
  Public Enum LongPtr:[_]:End Enum
#End If
 
Upvote 0
@Maika8008
Bác kiểm tra giúp đoạn mã xem có còn lỗi gì không.
Bác nhớ vào Debug nhấn Compile .... xem có cảnh báo identifier nữa không.

JavaScript:
#If VBA7 Then
#ElseIf VBA6 Then
  Public Enum LongLong:[_]:End Enum
  #If Win64 = 0 Then
    Public Enum LongPtr:[_]:End Enum
  #End If
#Else
  Public Enum LongLong:[_]:End Enum
  Public Enum LongPtr:[_]:End Enum
#End If
Ổn cả rồi bạn .
1697355269356.png
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Rất cảm ơn Bác @Maika8008 đã kiểm tra.

Mã cuối cùng tương thích đa nền tảng được rút gọn lại là:

JavaScript:
#If VBA7 = 0 Then
   Public Enum LongLong:[_]:End Enum
   #If VBA6 = 0 OR Win64 = 0 Then
   Public Enum LongPtr:[_]:End Enum
   #End If
#End If
Em áp dụng mã của anh mà lúc biên dịch báo lỗi:
#If VBA7 = 0 Then
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#If VBA6 = 0 Or Win64 = 0 Then
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If
#End If

Private Const WM_CLOSE = &H10
Public Sub CloseExplorer()
CloseByClass "CabinetWClass"
End Sub
Private Sub CloseByClass(className As String)
PostMessage FindWindow("CabinetWClass", vbNullString), WM_CLOSE, 0, 0
End Sub
 
Upvote 0
Rất cảm ơn Bác @Maika8008 đã kiểm tra.

Mã cuối cùng tương thích đa nền tảng được rút gọn lại là:

JavaScript:
#If VBA7 = 0 Then
   Public Enum LongLong:[_]:End Enum
   #If VBA6 = 0 OR Win64 = 0 Then
   Public Enum LongPtr:[_]:End Enum
   #End If
#End If

Tớ hỏi thêm:
Nếu chỉ sử dụng Office 2010 trở lên thì có thể không cần đoạn đầu này luôn:

1697428761086.png

Và sẽ khai báo đồng bộ tất cả các hàm API như thế này:
'---------------------------
Private Declare PtrSafe Sub TimeProc_ApiWindowFlexMove(ByVal hwnd As LongPtr, ByVal wMsg As LongPtr, ByVal idEvent As LongPtr, ByVal dwTime As LongPtr)
'---------------------------

Như vậy, có được không bạn nhỉ?
Theo hướng dẫn này nè:
1697429111430.png
 
Upvote 0
@cantl
Xin chịu thua thôi, không giải thích được.

Bác biết về vấn đề chồng chéo cần giải viết khi lập trình API, song hành cùng các hàm VBA, các hàm tự tạo, tương thích các mã win64 và win32, trong Win64 vùng nhớ các kiểu dữ liệu lại lớn hơn win32, từ phiên bản không có con trỏ bộ nhớ đến có con trỏ bộ nhớ?

Nếu Bác biết rồi, thì mới bàn thêm được.
 
Upvote 0
Cháu mạn phép phát biểu như này, có thì các bác và anh chị tha thứ cho cháu nhé.
Mặc dù code của anh @HeSanbi có chuẩn sác đi bao nhiêu chăng nữa, nhưng riêng cháu không dám dùng.
Lý do không biết đâu mà lần.
 
Upvote 0
Cháu mạn phép phát biểu như này, có thì các bác và anh chị tha thứ cho cháu nhé.
Mặc dù code của anh @HeSanbi có chuẩn sác đi bao nhiêu chăng nữa, nhưng riêng cháu không dám dùng.
Lý do không biết đâu mà lần.
Thì sau này khi lập trình đụng đến nó thì tìm lại bài cũ mà xài... :D
 
Upvote 0
Có người bỏ cả cuộc đời đi cài lại windows hoặc office giữa 64 và 32 bit chỉ để chạy một sổ làm việc Excel.
Có những người tha thiết nhờ vã chuyển mã 32bit sang 64bit cho sổ làm việc của họ.


Hãy tìm những người đó "hỏi thăm sức khỏe"!
 
Upvote 0
Tôi vẫn dùng code chuẩn Microsoft hướng dẫn, nó chạy ổn định trên nhiều máy tính. Đi theo lối mòn thì an toàn mà :)
Còn Tác giả muốn đi con đường riêng dù chấp nhận chông gai, ban đầu chắc chắn chưa phù hợp với nhiều máy tính (không tránh được). Một bài toán được giải theo nhiều cách cũng là cái hay cho người dùng trải nghiệm.
 
Lần chỉnh sửa cuối:
Upvote 0
@PhanTuHuong

Em đúc kết kinh nghiệm đã có được, để nhận thức cách khai báo tốt nhất cho lập trình WinAPI. Mà không ảnh hưởng đến quá trình thông dịch của chúng.
Và từ đó tạo ra cách khai báo tốt nhất trong mã.
Đi chuyên sâu để giải thích tại sao lại có cách khai báo như vậy.
Vì Enum được tận dụng nên trước hết nói về Enum, chính xác là Enumrates, là một kiểu liệt kê hằng số được định nghĩa với bộ nhớ lưu trữ tương đương kiểu Long trên một hằng giá trị.
Khai báo Enum LongPtr ở trên chỉ đủ điều kiện thông dịch khi hệ điều hành và phiên bản Office tương thích.
Cũng giống như Microsoft đã định nghĩa LongPtr như một con trỏ bộ nhớ tương thích tùy vào điều kiện hệ điều hành và phiên bản office mà nó có độ dài vùng nhớ là Long hay LongLong. Từ đó mà trình thông dịch sẽ dịch LongPtr thành Long hay LongLong.
Cách khai báo ở bài viết này cũng tương tự. Nhờ vậy mà phù hợp hầu hết các nền tảng và phiên bản Office.
 
Upvote 0
Tớ hỏi thêm:
Nếu chỉ sử dụng Office 2010 trở lên thì có thể không cần đoạn đầu này luôn:

View attachment 295767

Và sẽ khai báo đồng bộ tất cả các hàm API như thế này:
'---------------------------
Private Declare PtrSafe Sub TimeProc_ApiWindowFlexMove(ByVal hwnd As LongPtr, ByVal wMsg As LongPtr, ByVal idEvent As LongPtr, ByVal dwTime As LongPtr)
'---------------------------

Như vậy, có được không bạn nhỉ?
Theo hướng dẫn này nè:
View attachment 295768
Nếu có thời gian hay đam mê mong muốn chinh phục đỉnh cao của code ấy thì chỉ có các Tools lập trình hiện đại nhất đang còn Phát triển sẻ hổ trợ tốt nhất cho Bạn như C/c++, Delphi, Python, C# ...

Từng bước bỏ dần VBA đi ... nếu có chỉ khai báo các hàm tái sử dụng lại các hàm trong DLL do mình viết Thì mới an toàn và không lỗi thời tù túng và ọp ẹp khi viết mọi thứ trên VBA


Nếu muốn học API thì dò học Delphi thì bạn sẻ thấy trong Delphi có các unit dựng sẳn khai báo các hằng tùy chỉnh cho 32 bít và 64 bít còn bạn chỉ sử dụng đã được các kỹ sư lập trình tầm quốc tế viết nên khá yên tâm không phải mất thời gian Ngu dò mà viết nữa

bên cạnh đó có nhiều hàm API trung gian bạn có thể xem nó hay copy ra unit mới dựa vào đó tùy chỉnh viết lại theo ý mình

cái gì cũng cứ lôi API của Ms ra tái sử dụng chỉ chứng minh 1 điều khả năng không viết được ( dốt ) nên mới tái sử dụng nó tất cả .. đó là sự
thật

Còn muốn tìm hiểu khai báo các hằng API kiểu mò hay dò mà viết thì tìm các diễn đàn VB6 mà xem từ rất lâu đã có rồi và hơn thế nữa

VB6 lỗi thời Ms đã bỏ từ lâu nhưng nó tốt và hay hơn VBA nhiều thứ ...
 
Lần chỉnh sửa cuối:
Upvote 0
@Maika8008 Bác có thể kiểm tra giúp tôi cho những trường hợp sau trên máy của Bác được không?
Vì khi khai báo trên, chạy được trên máy của Bác thì lại không chạy được trên máy khác.

Trường hợp 1:
JavaScript:
#If VBA7 = 0 Then
   #If VBA6 = 0 OR Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
   #End If
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

Trường hợp 2:
JavaScript:
#If VBA7 = 0 And Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

Trường hợp 3:
JavaScript:
#If VBA7 = 0 Or Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

Trường hợp 4:
JavaScript:
#If Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

(Sau khi chép mã Bác nhấn vào Debug, nhấn Compile....)
 
Lần chỉnh sửa cuối:
Upvote 0
@Maika8008 Bác có thể kiểm tra giúp tôi cho những trường hợp sau trên máy của Bác được không?
Vì khi khai báo trên, chạy được trên máy của Bác thì lại không chạy được trên máy khác.

Trường hợp 1:
JavaScript:
#If VBA7 = 0 Then
   #If VBA6 = 0 OR Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
   #End If
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

Trường hợp 2:
JavaScript:
#If VBA7 = 0 And Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

Trường hợp 3:
JavaScript:
#If VBA7 = 0 Or Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
    #If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #End If

(Sau khi chép mã Bác nhấn vào Debug, nhấn Compile....)
Trường hợp 3 bị báo lỗi identifier. còn 2 trường hợp đầu thì OK.
 
Upvote 0
Trường hợp 3 bị báo lỗi identifier. còn 2 trường hợp đầu thì OK.
Nếu vậy thì khai báo như dưới đây trên máy của Bác vẫn sẽ hoạt động


JavaScript:
#If Win64 = 0 Then
    Private Enum LongPtr:[_]:End Enum
#End If
#If VBA7 Then
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#End If

(@ongke0711 anh ghé qua test từ #55 giúp nhé anh)
 
Upvote 0
@Maika8008 Bác giúp chạy đoạn mã dưới đây trên máy của Bác, Bác chụp giúp màn hình, đây là đề xuất của một lập trình viên nước ngoài, làm phiền Bác lần nữa. Họ cần sự chắc chắn.

JavaScript:
Sub TestPreCompilerConstants()
    Dim m As String
    Dim b As String
    Dim v As String
    '
    #If Mac Then
        m = "Mac"
    #Else
        m = "Windows"
    #End If
    '
    #If Win64 Then
        b = "x64"
    #Else
        b = "x32"
    #End If
    '
    #If VBA7 Then
        v = "VBA7"
    #Else
        v = "VBA6 (or prior)"
    #End If
    '
    MsgBox "You are on " & m & " OS, on " & b & " Office, on " & v
End Sub
 
Upvote 0
@Maika8008 Bác giúp chạy đoạn mã dưới đây trên máy của Bác, Bác chụp giúp màn hình, đây là đề xuất của một lập trình viên nước ngoài, làm phiền Bác lần nữa. Họ cần sự chắc chắn.

JavaScript:
Sub TestPreCompilerConstants()
    Dim m As String
    Dim b As String
    Dim v As String
    '
    #If Mac Then
        m = "Mac"
    #Else
        m = "Windows"
    #End If
    '
    #If Win64 Then
        b = "x64"
    #Else
        b = "x32"
    #End If
    '
    #If VBA7 Then
        v = "VBA7"
    #Else
        v = "VBA6 (or prior)"
    #End If
    '
    MsgBox "You are on " & m & " OS, on " & b & " Office, on " & v
End Sub
1. Khai báo của bài #57 (tức là trường hợp 4 của #55) vẫn bị báo lỗi identifier.
2. Dùng trường hợp 1 và 2 của bài #55 để chạy code của bài #58 thì kết quả như sau:
1698719522007.png
 
Upvote 0
@HeSanbi

1. Windows 11 (64bit) + Office 2013 (32bit): báo lỗi TH3, 4 và code bài #57

Screen Shot 2023-10-31 at 13.01.52.png. Screen Shot 2023-10-31 at 13.05.43.png

2. Windows 11 (64bit) + Microsoft 365: không báo lỗi trường hợp nào.

Screen Shot 2023-10-31 at 13.11.34.png
 
Upvote 0
@ongke0711 rất cảm ơn anh

Mã tương thích phù em đã cập nhật vào bài viết.

Các mã khai báo trước đây gây ra lỗi khai báo nếu LongPtr nằm trong mã các hàm Win32 API.
 
Upvote 0
Trước hết em cám ơn chủ thớt chia sẻ thông tin ạ, em cũng mò mẩm học hỏi từ diễn đàn nhiều cái. Tuy nhiên em thấy vấn đề chung mà khi người chia sẻ đưa ra lại có một số ý kiến như Kiều Mạnh thường xãy ra nhiều nên vì thế anh em thành viên nhiều khi muốn chia sẻ cũng không dám nói ra. em chỉ nêu suy nghĩ của mình, nên suy nghĩ thoáng ra các bác ạ, ai chia sẻ gì thì mình ghi nhận không nên nặng lời kia nọ. "Hãy yêu thương và chia sẻ, bạn sẽ nhận về niềm vui và hạnh phúc'', "Có tài mà không có đức là người vô dụng".
 
Upvote 0
Anh @ongke0711 và Bác @Maika8008

Thử giúp cho một trường hợp nữa. Lỗi này xuất phát từ trình thông dịch VBA, không biết là bản mới nhất đã được vá lỗi chưa.

Tạo một lớp với tên cClass với mã:
JavaScript:
Private Sub Class_Terminate()
End Sub

Tạo một Module với mã và chạy thử tục bug, chỉ cần có một dòng được in, thì phiên bản trình thông dịch có lỗi
JavaScript:
Sub Bug()
    ' We don't really need a Clone method to reproduce the bug
    If Falsee(New cClass) Then
        Debug.Print "This does print, although it shouldn't!"
    End If

    ' If we add a logical operator and a second method call then the bug disappears:
    If Falsee(New cClass) Or Falsee(New cClass) Then
        Debug.Print "This doesn't print, as it shouldn't."
    End If

    ' It could be any other method. The order of the methods also doesn't matter
    If Falsee(New cClass) Or Sin(0) Then
        Debug.Print "This doesn't print, as it shouldn't."
    End If

    ' The above workaround does not work if we simply use a boolean value after the method call
    If Falsee(New cClass) Or False Then
        Debug.Print "This does print, although it shouldn't!"
    End If

    ' But it does work if we add the boolean before the method call:
    If False Or Falsee(New cClass) Then
        Debug.Print "This doesn't print, as it shouldn't."
    End If
    If True And Falsee(New cClass) Then
        Debug.Print "This doesn't print, as it shouldn't."
    End If
End Sub

Function Falsee(oClass As cClass) As Boolean
    Falsee = False
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Đã thử, sub Bug không in dòng nào cả.
 
Upvote 0
Đã thử, sub Bug không in dòng nào cả.
Bác giúp Debug hai cách khai báo này, đây là mong muốn của một lập trình viên nước ngoài, tôi đã cố gắng giải thích cho họ, nhưng họ nhất quyết muốn biết kết quả. Làm phiền Bác lần nữa. Bác chụp cho hình ảnh nếu lỗi.

JavaScript:
#If VBA7 = 0 And True Then
   Private Enum LongPtr:[_]:End Enum
#End If


JavaScript:
#If True And VBA7 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
 
Upvote 0
@HeSanbi
Đã thử code của bài #64 và #66 trên 2 phiên bản Office như bài trước và không báo lỗi gì cả, cái sub Bug cũng không in gì luôn nhé.

Screen Shot 2023-11-01 at 00.02.40.png. Screen Shot 2023-11-01 at 00.08.04.png
 
Upvote 0
Bác giúp Debug hai cách khai báo này, đây là mong muốn của một lập trình viên nước ngoài, tôi đã cố gắng giải thích cho họ, nhưng họ nhất quyết muốn biết kết quả. Làm phiền Bác lần nữa. Bác chụp cho hình ảnh nếu lỗi.

JavaScript:
#If VBA7 = 0 And True Then
   Private Enum LongPtr:[_]:End Enum
#End If


JavaScript:
#If True And VBA7 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
Debug cả hai trường hợp đều không báo lỗi.
 
Upvote 0
Debug cả hai trường hợp đều không báo lỗi.
Vấn đề xảy ra trên máy tính của Bác ở biến số biên dịch.

Bác giúp kiểm tra lại đoạn mã dưới đây một lần nữa.
Bác chép tất cả mã vào Module, sau đó nhấn Debug Compile, dòng nào lỗi Bác Comment lại rồi tiếp tục Debug.
Xin lỗi đã làm khó cho Bác nhé


Trường hợp khai báo toàn cục:
JavaScript:
#If VBA7 Then
#Else
   Public Enum LongPtr:[_]:End Enum
#End If

#If VBA7 = 0 Then
   Public Enum LongPtr:[_]:End Enum
#End If

#If Not -VBA7 Then
   Public Enum LongPtr:[_]:End Enum
#End If

#If CBool(VBA7 = 0) Then
   Public Enum LongPtr:[_]:End Enum
#End If

#If VBA7= 0 And Win64 = 0 Then
   Public Enum LongPtr:[_]:End Enum
#End If

#If Not (-VBA7 Or -Win64) Then
   Public Enum LongPtr:[_]:End Enum
#End If

Trường hợp khai báo cục bộ:
JavaScript:
#If VBA7 Then
#Else
   Private Enum LongPtr:[_]:End Enum
#End If

#If VBA7 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If Not -VBA7 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If CBool(VBA7 = 0) Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If VBA7= 0 And Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If Not (-VBA7 Or -Win64) Then
   Private Enum LongPtr:[_]:End Enum
#End If
 
Lần chỉnh sửa cuối:
Upvote 0
@ongke0711 cảm ơn anh, vấn đề này chỉ xảy ra trên máy tính Bác @Maika8008
Trường hợp này rất hiếm gặp, lỗi này nằm trong trình thông dịch mã
 
Upvote 0
Upvote 0
Hình ảnh ở #4 xảy ra lỗi, nay lại không có, có gì đó không hợp lí. Ở trên có một trường hợp của #4 lại không có lỗi.

Bác chép từng trường hợp vào một book và module mới thử lại được không?
Bạn xem lại đi, không có TH nào của bài #55 cả.
- Bài #55 là #If VBA7 = 0 Or Win64 = 0 Then
- Bài #69 là #If VBA7 = 0 And Win64 = 0 Then

Đây tôi tổng hợp lại code khai báo của 2 bài:
Mã:
'--------'Day là khai bao o bài #69 => Không báo loi
#If VBA7 Then
#Else
   Private Enum LongPtr:[_]:End Enum
#End If

#If VBA7 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If Not -VBA7 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If CBool(VBA7 = 0) Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If VBA7 = 0 And Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If

#If Not (-VBA7 Or -Win64) Then
   Private Enum LongPtr:[_]:End Enum
#End If
'------- het code bài #69

'Day là truong hop 3 bài #55 => Báo loi
'#If VBA7 = 0 Or Win64 = 0 Then
'   Private Enum LongPtr:[_]:End Enum
'#End If

'Day là truong hop 4 bài #55 => Báo loi
'#If Win64 = 0 Then
'   Private Enum LongPtr:[_]:End Enum
'#End If
 
Upvote 0
@Maika8008

Bác sửa Private thành Public và thử lại. Có lẻ vấn đề còn nằm ở cục bộ và toàn cục.

Rất cảm ơn Bác đã bỏ thời gian để kiểm tra.
 
Upvote 0
Thay bằng Public cũng báo lỗi vậy thôi bạn.
Cảm ơn Bác nhé!

Vậy là kết luận, không có lỗi như Bác đã báo cáo ở #4.

Vì khi tôi viết bài viết khai báo đầu tiên mã nên sử dụng để tương thích như dưới đây:

JavaScript:
#If VBA7 Then
#Else
   Public Enum LongPtr:[_]:End Enum
   Public Enum LongLong:[__]:End Enum
#End If

Các cách khai báo sau đều phù hợp để tận dụng:

JavaScript:
#If VBA7 = 0 Then
   Public Enum LongPtr:[_]:End Enum
   Public Enum LongLong:[__]:End Enum
#End If
 
Lần chỉnh sửa cuối:
Upvote 0
Giải pháp

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

Back
Top Bottom