Özellik ikonu

PtrSafe

İndirme izni yok

Genel Bakış

PtrSafe (PtrSafe keyword), Declare deyiminde kullanılan ve bildirimin 64 bit ortamda güvenle çalışacağını VBA derleyicisine bildiren anahtar sözcüktür. Windows API ya da başka bir DLL işlevini çağıran bildirimlerde, VBA7 (Excel 2010 ve sonrası) ile gelen bu sözcük yazılmazsa 64 bit Excel kodu derlemeyi reddeder. Eski ve yeni Excel sürümlerinin ikisinde de çalışan kod için genellikle #If VBA7 Then koşullu derlemesiyle birlikte kullanılır.

Söz dizimi​

PtrSafe ayrı bir deyim değildir; Declare deyiminde Sub ya da Function sözcüğünden hemen önce yazılır:
VBA 2 satır
[Public | Private] Declare PtrSafe Sub ad Lib "kitaplık" [Alias "takma_ad"] [([bağımsız_değişkenler])]
[Public | Private] Declare PtrSafe Function ad Lib "kitaplık" [Alias "takma_ad"] [([bağımsız_değişkenler])] [As dönüş_türü]
  • Public / Private: bildirimin erişim düzeyi; isteğe bağlıdır. Standart modülde belirtilmezse bildirim Public kabul edilir. Sınıf ve sayfa modüllerinde yalnız Private kullanılabilir.
  • PtrSafe: 64 bit uyumluluğunu bildirir; VBA7 çalıştıran Excel'de (2010 ve sonrası) bildirimde bulunması gerekir. Excel 2007 ve öncesi bu sözcüğü tanımaz.
  • Sub / Function: çağrılan yordamın değer döndürüp döndürmediğini belirtir; zorunludur.
  • ad: yordamı VBA'da çağıracağınız ad; zorunludur.
  • Lib: işlevin bulunduğu DLL adı (kernel32, user32 gibi); zorunludur.
  • Alias: DLL içindeki gerçek işlev adı; isteğe bağlıdır. VBA'daki ad DLL'dekinden farklıysa kullanılır.
  • bağımsız_değişkenler: parametre listesi; isteğe bağlıdır. Genellikle ByVal ya da ByRef ile yazılır.
  • dönüş_türü: Function için dönen değerin veri türü; isteğe bağlıdır, yazılmazsa Variant olur.

Neden gerekli ve ne anlama gelir​

64 bit Excel'de bellek adresleri ve tutamaçlar (pencere, dosya, nesne tutamacı) 8 bayt uzunluğundadır; 32 bit Excel'de ise 4 bayttır. Bildirimde bu değerler Long olarak bırakılırsa 64 bit ortamda adres kesilir ve Excel çökebilir. Bu nedenle 64 bit Excel, PtrSafe içermeyen Declare satırında derleme hatası verir; hata, kodun 64 bit sistemler için gözden geçirilip bildirimlerin PtrSafe ile işaretlenmesi gerektiğini söyler.
PtrSafe yazmak tek başına kodu düzeltmez; derleyiciye "bu bildirimi inceledim, işaretçi boyutundaki değerleri doğru türde tanımladım" demektir. Asıl düzeltme, adres ve tutamaç türündeki parametrelerin ve dönüş değerlerinin LongPtr olarak yazılmasıdır:
VBA 5 satır
#If VBA7 Then
    Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr
#Else
    Private Declare Function GetForegroundWindow Lib "user32" () As Long
#End If
  • LongPtr: 32 bit Excel'de 4 bayt, 64 bit Excel'de 8 bayt olan işaretçi türü; tutamaç ve adresler için kullanılır.
  • LongLong: yalnız 64 bit Excel'de bulunan 8 baytlık tam sayı türü.
  • Long: 32 bit değerler için (DWORD, int) her ortamda 4 bayt kalır; bu tür parametreleri değiştirmeniz gerekmez.

Koşullu derleme ile eski sürümlerle uyum​

Excel 2007 ve öncesinde PtrSafe sözcüğü bilinmediği için bildirim derleme hatası verir. Aynı dosyanın her sürümde açılması gerekiyorsa #If VBA7 Then ... #Else ... #End If yapısı kullanılır. Derleyici yalnız geçerli dalı derler, diğer dalı yok sayar.
  • VBA7: Excel 2010 ve sonrasında (32 ya da 64 bit) True olan derleme sabitidir.
  • Win64: yalnız 64 bit Excel'de True olan derleme sabitidir.
Genel kural: önce VBA7 ile PtrSafe gerekip gerekmediğine, gerekirse Win64 ile 64 bit'e özgü türlere (LongLong gibi) karar verin. Yalnız 2010 ve sonrası kullanılacaksa koşullu derlemeye gerek kalmaz; doğrudan Declare PtrSafe yazabilirsiniz.

1. Sleep API bildirimi ve çağrısı​

Windows'un kernel32 kitaplığındaki Sleep yordamı, belirtilen milisaniye kadar Excel'i bekletir. Aşağıdaki kodu standart modüle yapıştırın; Declare satırları modülün en üstünde, yordamlardan önce durmalıdır. Bildirim hem eski hem yeni Excel sürümlerinde derlenecek biçimde #If VBA7 ile yazılmıştır.
VBA 14 satır
Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub YarimSaniyeBekle()
    ' Excel'i 500 milisaniye bekletir
    Sleep 500
    ' Bekleme bittikten sonra sayfaya not düşer
    Worksheets("Sleep Çağrısı").Range("B2").Value = "Bekleme tamamlandı"
End Sub
PtrSafe
Formülünü incelemek için bir hücre seçin.
AB
1AdımAçıklama
2Bekleme
3BildirimDeclare PtrSafe Sub Sleep
4Bekleme süresi (ms)500
Sleep ÇağrısıExcelDepo v1.0.0
Bu örnek Windows API çağırdığı için burada çalıştırılmadı. Makroyu kendi bilgisayarınızda çalıştırırsanız Excel yarım saniye yanıt vermez, ardından B2 hücresine bekleme mesajı yazılır. 64 bit Excel'de #If VBA7 dalı derlenir ve PtrSafe içeren satır kullanılır; Excel 2007 gibi eski sürümlerde #Else dalı derlenir. Sleep'in parametresi 32 bit bir değer olduğu için Long olarak kalır, LongPtr'ye çevrilmesi gerekmez.

2. Excel ortamını koşullu derleme sabitleriyle sorgulama​

PtrSafe kullanıp kullanamayacağınızı belirleyen VBA7 ve Win64 derleme sabitlerini sayfaya yazan bir makro. Kodu standart modüle yapıştırın. Makro, işaretçi boyutunu da LongPtr ile ölçer; böylece Excel'in 32 ya da 64 bit olduğunu görebilirsiniz.
VBA 23 satır
Option Explicit

Sub OrtamBilgisiYaz()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Ortam Bilgisi")

    #If VBA7 Then
        Dim p As LongPtr
        ws.Range("B2").Value = "Evet"
    #Else
        Dim p As Long
        ws.Range("B2").Value = "Hayır"
    #End If

    #If Win64 Then
        ws.Range("B3").Value = "Evet"
    #Else
        ws.Range("B3").Value = "Hayır"
    #End If

    ' İşaretçi türünün bayt cinsinden boyutu
    ws.Range("B4").Value = LenB(p)
End Sub
PtrSafe
Formülünü incelemek için bir hücre seçin.
AB
1ÖlçütSonuç
2VBA7 derleyicisi (Excel 2010 ve sonrası)Evet
364 bit ExcelHayır
4LongPtr boyutu (bayt)4
Ortam BilgisiExcelDepo v1.0.0
B2 hücresi Evet değerini alır; bu değer Excel'in PtrSafe sözcüğünü tanıyan VBA7 derleyicisini kullanıp kullanmadığını gösterir. B3 hücresindeki Hayır sonucu Excel'in 64 bit olup olmadığını, B4 hücresindeki 4 ise işaretçi boyutunu bayt olarak verir. 64 bit Excel'de boyut 8, 32 bit Excel'de 4'tür.

3. Veri türlerinin bayt boyutlarını karşılaştırma​

Long, LongPtr ve LongLong türlerinin boyut farkını gösteren makro. Kodu standart modüle yapıştırın. LongLong yalnız 64 bit Excel'de bulunduğu için ilgili kısım #If Win64 ile korunur; 32 bit Excel'de de hatasız derlenir.
VBA 29 satır
Option Explicit

Sub BoyutlariYaz()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Bayt Boyutları")

    Dim i As Integer
    Dim l As Long

    #If VBA7 Then
        Dim lp As LongPtr
    #Else
        Dim lp As Long
    #End If

    #If Win64 Then
        Dim ll As LongLong
    #End If

    ws.Range("B2").Value = LenB(i)
    ws.Range("B3").Value = LenB(l)
    ws.Range("B4").Value = LenB(lp)

    #If Win64 Then
        ws.Range("B5").Value = LenB(ll)
    #Else
        ws.Range("B5").Value = "Yok (32 bit)"
    #End If
End Sub
PtrSafe
Formülünü incelemek için bir hücre seçin.
AB
1Veri türüBayt boyutu
2Integer2
3Long4
4LongPtr4
5LongLongYok (32 bit)
Bayt BoyutlarıExcelDepo v1.0.0
Integer için 2 ve Long için 4 bayt bulunur; bu iki türün boyutu Excel'in 32 ya da 64 bit olmasından etkilenmez. LongPtr ise ortama uyum sağlar ve B4 hücresinde 4 bayt görünür. LongLong satırında (Yok (32 bit)) 64 bit Excel'de 8 bayt boyutu, 32 bit Excel'de ise türün bulunmadığını bildiren metin çıkar.

Kullanırken dikkat edin​

  • PtrSafe tek başına yeterli değildir: Declare satırına PtrSafe eklemek hatayı susturur ama tutamaç ve adres parametrelerini kendiliğinden düzeltmez. Pencere tutamacı, bellek adresi ve nesne işaretçisi gibi değerleri Long bırakırsanız 64 bit Excel'de veri kaybı olur ve Excel beklenmedik biçimde kapanabilir. Bu parametreleri LongPtr yapın.
  • Eski sürümlerde derleme hatası: Excel 2007 ve öncesi PtrSafe sözcüğünü tanımaz ve söz dizimi hatası verir. Dosya eski sürümlerde de açılacaksa Declare satırlarını mutlaka #If VBA7 Then ve #Else dallarıyla ikiye ayırın.
  • Declare yerleşimi: Standart modülde Declare satırları modülün başında, yordamlardan önce yer almalıdır. Sınıf modüllerinde, sayfa modüllerinde ve UserForm modüllerinde bildirim yalnız Private olabilir; Public bildirim için standart modül kullanın.
  • Dönüştürme işlevi: Bir sayıyı işaretçi türüne çevirmeniz gerekirse CLngPtr işlevini kullanın. 64 bit ortamda CLng ile dönüştürmek 8 baytlık değeri 4 bayta sığdırmaya çalışır ve taşma hatası verebilir.
  • Win64 sabitini doğru yorumlayın: Win64 sabiti Excel'in 64 bit olduğunu, Windows'un 64 bit olduğunu değil gösterir. 64 bit Windows üzerinde 32 bit Excel çalışıyorsa Win64 False, VBA7 ise Excel 2010 ve sonrasında True olur. Bu durumda PtrSafe gerekir, ama LongLong kullanılamaz.
  • Kodu denemeden önce: Windows API çağıran makroları denemeden önce dosyanızı kaydedin. Yanlış tür ya da parametre sırası Excel'i anında kapatabilir ve kaydedilmemiş çalışmanız kaybolur.
  • İlgili konular:
    • Declare deyimi: DLL işlevlerini VBA'ya tanıtır, PtrSafe bu deyimin bir parçasıdır.
    • LongPtr: 32 bit'te 4, 64 bit'te 8 bayt olan işaretçi veri türü.
    • LongLong: yalnız 64 bit Excel'de bulunan 8 baytlık tam sayı türü.
    • CLngPtr: bir ifadeyi LongPtr türüne çeviren işlev.
    • #If...Then...#Else: koşullu derleme yönergesi.
    • VBA7 ve Win64: koşullu derleme sabitleri.
    • Alias: Declare deyiminde DLL'deki gerçek işlev adını belirtir.
    • ByVal ve ByRef: parametrenin değer ya da başvuru olarak geçirilmesini belirler.
    • VarPtr, ObjPtr ve StrPtr: değişken, nesne ve metin adresini veren, LongPtr döndüren işlevler.
Örneklerdeki makroların tamamı indirilebilir Excel dosyasındadır (.xlsm). Dosyayı açtıktan sonra makroları etkinleştirin, ardından Alt + F11 ile Visual Basic Düzenleyicisi'nde kodları inceleyebilir ve Alt + F8 ile çalıştırabilirsiniz.
Yazar
ExcelDepo
İndirme sayısı
0
Gösterim
11
İlk yayın
Güncel

Puanlar

0.00 Oylama 0 İnceleme
Geri
Üst