Access
 sql >> Teknologi Basis Data >  >> RDS >> Access

Pernyataan DefType di VBA:Sisi Gelap Kompatibilitas Mundur

Hanya karena Anda bisa melakukan sesuatu, bukan berarti Anda harus melakukannya.

Saya sangat percaya pada kesucian kompatibilitas ke belakang. Tapi itu datang dengan sisi gelap. Terkadang cara lama dalam melakukan sesuatu tidak lagi disukai. Penggunaannya menjadi sangat misterius sehingga kita cenderung melupakan keberadaan mereka.

Begitu juga dengan pernyataan DefType.

Apa yang Tidak Anda Ketahui Dapat Menyakiti Anda

Beberapa bulan yang lalu, saya menulis artikel tentang modul kelas Operasi Registri Romke Soldaat.

Saya memublikasikan perubahan yang saya buat pada deklarasi API Romke untuk membuat kode berjalan di bawah VBA 64-bit. Setiap panggilan API dibungkus dengan #If VBA7 tag kompilasi bersyarat dan diperbarui dengan PtrSafe kata kunci.

Hanya ada satu masalah.

Saya lupa menyertakan perubahan kunci yang telah saya buat pada salah satu deklarasi tingkat modul dalam kode Romke. Tanpa perubahan ini, kode modifikasi Romke tidak akan dikompilasi di bawah VBA 64-bit. Kesalahan kompilasi terjadi pada baris berikut:

Pesan kesalahannya adalah "Ketidakcocokan tipe argumen ByRef " dan variabel yang disorot adalah hCurKey .

Berikut baris kode yang menyinggung dari modul kelas asli Romke:

Private hCurKey

Untuk memperbaiki kesalahan kompilasi, baris kode di atas dapat diubah menjadi ini:

Private hCurKey As Variant

Tapi tunggu, katamu, bukankah kedua baris kode itu melakukan hal yang sama?!?! Semua orang tahu bahwa jika Anda tidak mendeklarasikan tipe variabel di VBA, itu secara implisit dideklarasikan sebagai Varian. ...  Atau ya?

Eksplisit Lebih Baik Daripada Implisit

Jadi apa yang sebenarnya terjadi di sini?

Masalahnya adalah baris pertama kode di atas–Private hCurKey –mendefinisikan variabel hCurKey sebagai Long tipe data.

Bagaimana ini bisa terjadi?

Itu karena baris aneh ini di bagian atas modul kelas Romke:

DefLng H-I, L, N

Apa yang dilakukan garis itu? Dikatakan bahwa setiap variabel yang dideklarasikan dalam modul saat ini tanpa tipe yang dideklarasikan secara eksplisit yang nama variabelnya dimulai dengan H , I , L , atau N , akan diperlakukan oleh kompiler sebagai Long tipe data.

Jadi, baris Private hCurKey melakukan secara implisit mendeklarasikan tipe untuk variabel hCurKey, tetapi deklarasi implisit adalah sebagai tipe data Long, bukan Varian.

Mengapa Bervariasi Kompilasi Tapi Panjang Bukan?

Mengapa kode dikompilasi saat hCurKey adalah Varian tetapi gagal saat Long, itu masalah proses konversi 32-bit ke 64-bit.

Untuk menemukan sumber masalahnya, kita perlu memeriksa kode yang dimigrasikan untuk deklarasi API RegCreateKeyEx:

#If VBA7 Then
    Private Declare PtrSafe Function RegCreateKeyEx _
      Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
          ByVal hKey As LongPtr, ByVal lpSubKey As String, _
          ByVal Reserved As Long, ByVal lpClass As String, _
          ByVal dwOptions As Long, ByVal samDesired As Long, _
          lpSecurityAttributes As SECURITY_ATTRIBUTES, _
          phkResult As LongPtr, lpdwDisposition As Long) As Long
#Else
    Private Declare Function RegCreateKeyEx _
      Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
          ByVal hKey As Long, ByVal lpSubKey As String, _
          ByVal Reserved As Long, ByVal lpClass As String, _
          ByVal dwOptions As Long, ByVal samDesired As Long, _
          lpSecurityAttributes As SECURITY_ATTRIBUTES, _
          phkResult As Long, lpdwDisposition As Long) As Long
#End If

Saat kita memanggil RegCreateKeyEx dari kode, kami melewati hCurKey variabel sebagai argumen kedua hingga terakhir dalam fungsi. Dengan kata lain, itu diteruskan sebagai phkResult argumen. Perhatikan bahwa dalam versi pra-VBA7 (Access 2007 dan sebelumnya), phkResult dideklarasikan sebagai Long, tetapi dalam versi VBA7 dideklarasikan sebagai LongPtr .

Itu karena phkResult menerima pegangan ke kunci registri yang dibuat atau dibuka. Setiap kali Anda melihat kata "pegangan" yang terkait dengan panggilan API, Anda dapat menerjemahkannya dengan aman di kepala Anda ke "alamat memori". Itu sebabnya argumen didefinisikan ulang sebagai LongPtr dalam kode VBA7:saat mengeksekusi di lingkungan 32-bit, sebuah LongPtr diperlakukan sebagai Long 32-bit integer, tetapi dalam lingkungan 64-bit, sebuah LongPtr diperlakukan sebagai LongLong 64-bit bilangan bulat.

Mendeklarasikan hCurKey sebagai Variant adalah sedikit jalan pintas. Adaptasi berikut juga akan berfungsi (dan bekerja lebih cepat, meskipun peningkatan kecepatan mungkin tidak terlihat oleh pengguna kecuali jika dipanggil berkali-kali di dalam satu lingkaran):

#If VBA7 Then
    Private hCurKey As LongPtr
#Else
    Private hCurKey As Long
#End If

Seperti yang saya katakan, pendekatan di atas lebih eksplisit dalam menyampaikan maksud pengembang, berkinerja lebih baik, dan akan meningkatkan lebih banyak kesalahan waktu kompilasi daripada Private hCurKey As Variant alternatif.

Tapi saya dikenal pemalas, dan Private hCurKey As Variant adalah hampir sama baiknya dengan lebih sedikit mengetik.

Gunakan Pengetahuan Anda Untuk Kebaikan

Sekarang, ingat apa yang saya katakan di awal artikel ini?

Hanya karena Anda bisa melakukan sesuatu, bukan berarti Anda harus melakukannya.

Saya menulis artikel ini karena dua alasan:

  1. Untuk mendorong Anda untuk secara eksplisit mendeklarasikan Variabel Variant As Variant
  2. Untuk meningkatkan kesadaran tentang aspek misterius VBA yang dapat membuat Anda tersandung jika Anda mempertahankan (atau menyalin-menempel) kode orang lain

Saya TIDAK tulis artikel ini untuk menginspirasi Anda untuk menulis pernyataan DefType dalam kode Anda sendiri. JANGAN LAKUKAN ITU!!! Ingat, hanya karena Anda bisa melakukan sesuatu bukan berarti Anda harus melakukannya.

Referensi eksternal

Pernyataan Deftype (VBA)Topik referensi Office VBAMicrosoft Docso365devx Deklarasi Windows API di VBA untuk 64-bitBagaimana mengonversi Deklarasi API Anda ke 64-bit. - Mitos umum dibantah, faktor kunci dijelaskan! CodekabinettPhilipp Stiefel

Artikel yang dirujuk

Penghormatan untuk Kompatibilitas MundurFitur yang banyak digunakan oleh sebagian kecil pengguna listrik telah dipertahankan selama lima peningkatan berikutnya (dan terus bertambah). Sekarang itu menunjukkan penghormatan terhadap kompatibilitas ke belakang. Tidak Lagi SetMike Wolfe Kelas RegOp untuk VBA 64-bitMemperbarui modul kelas membaca dan menulis registri VBA klasik untuk kompatibilitas 64-bit. Tidak Lagi SetMike Wolfe

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 5 Alasan Bagus untuk Mengunduh dan Menggunakan Template Microsoft Access

  2. Bergabunglah dengan Kami untuk Pengenalan Akses dengan SQL Server

  3. Cara Membuat Laporan dengan Report Wizard di Microsoft Access

  4. Bagaimana Kami Menggunakan Basis Data dalam Kehidupan Sehari-hari

  5. Mengapa Anda Harus Menggunakan PHPs PDO untuk Akses Database