我怎样才能申报VBA一个PTRSAFE子? Windows 7,Excel 2016、64位

时间:2019-02-02 18:36:38

标签: excel vba long-long

我正在尝试将大量的VBA应用程序从Long数据类型升级到LongLong或LongPtr,以便能够处理更多数字。 但我无法弄清楚如何调用该PTRSAFE子...一些帮助将是非常有益的。

我尝试了一个简单的示例Sub来隔离问题。 但是不知道哪个库我应该叫和最重要的是:应该这样子是私人或公共

Public Declare PtrSafe Sub Example Lib "??????" (ByVal x, y, z As LongPtr)

Dim x, y, z As LongPtr

x = 123456789
y = 123456789
MsgBox z = x * y

End Sub

有人可以一步一步地向我解释如何调用PtrSafe的Sub吗?

2 个答案:

答案 0 :(得分:2)

PtrSafe

仅使用PtrSafe在64位系统上启用32位API调用,如下所示:

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long

Public Sub TestScreenResolution()
    Debug.Print ScreenResolution
End Sub
Private Function ScreenResolution() As Double
     Dim hDC As LongPtr
     hDC = GetDC(0)
     ScreenResolution = GetDeviceCaps(hDC, 88)
     ReleaseDC 0, hDC
End Function

有条件的编译

您可以使用通过条件编译

#If Win64 Then
    Private Declare PtrSafe Function MakeSureDirectoryPathExists _
        Lib "imagehlp.dll" (ByVal DirPath As String) As Boolean
#Else
    Private Declare Function MakeSureDirectoryPathExists Lib _
        "imagehlp.dll" (ByVal DirPath As String) As Boolean
#End If

您自己的带有64位变量的Sub或Function

可以这样声明:

Public Sub TestMySub()
    Call MySub(123456789, 123456789)
End Sub

Private Sub MySub(ByVal x As LongLong, ByVal y As LongPtr)
    Dim z As LongLong
    z = x * y
    MsgBox z
End Sub

我更喜欢Private,只要可能的和Public仅当需要 “外部” 的访问。

数据类型LongLong vs.LongPtr vs.Decimal

在64位LongLongLongPtr均为 “LONGLONG整数” 具有8个字节:
-9.223.372.036.854.775.808到9.223.372.036.854.775.807

但是请注意:但是,如果您使用LongLong,它将仅在64bit上工作,而32bit的LongPtr将被简单地处理为4字节的Long,这将导致
-2.147.483.648到2.147.483.647

因此,如果您确实在两个系统上都需要很高的价值,而Long还是不够的,请考虑使用Double(8字节,包括舍入效果!)或Decimal(14字节,必须被声明为Variant第一):

Private Sub DataTypeDecimal()
    ' Decimal only via declaration as Variant and type cast as Decimal
    Dim d As Variant
    d = CDec("79.228.162.514.264.337.593.543.950.335")
    Debug.Print d
    d = CDec("-79.228.162.514.264.337.593.543.950.335")
    Debug.Print d
End Sub

答案 1 :(得分:-1)

我给你的例子很好,谢谢你:-)。

但是,当我尝试用“ True”-布尔值(摘录)填充Arr(z)时,实际的应用程序现在会显示“类型不匹配”(它对Long数据类型的效果很好):

Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hDC As LongPtr) As Long

Public Sub TestScreenResolution()
    Debug.Print ScreenResolution
End Sub
Private Function ScreenResolution() As Double
     Dim hDC As Long
     hDC = GetDC(0)
     ScreenResolution = GetDeviceCaps(hDC, 88)
     ReleaseDC 0, hDC
End Function

Public Sub TestMySub()
    Call MySub(999999999)
End Sub
Private Sub MySub(ByVal x As LongLong)

Dim z As LongLong
Dim Max, Min As LongLong

Max = x * x
Min = (x - 2) * (x - 2)

Dim Arr() As Boolean 'Default Boolean type is False
ReDim Arr(Min To Max)

For z = Max To Min Step -2
    Arr(z) = True
Next z

End Sub