【问题标题】:How can I declare a PtrSafe Sub in VBA? Windows 7, Excel 2016, 64-bit如何在 VBA 中声明 PtrSafe Sub? Windows 7、Excel 2016、64 位
【发布时间】:2019-06-27 00:27:53
【问题描述】:

我正在尝试将我的大量 VBA 应用程序从 Long 数据类型升级到 LongLong 或 LongPtr 以便能够处理更多数字。 但我不知道如何调用这个 PtrSafe Sub...一些帮助会很有帮助。

我尝试了一个简单的示例 Sub 来隔离问题。 但不知道我应该调用哪个 Lib,最重要的是:这个 Sub 应该是 Private 还是 Public?

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?

【问题讨论】:

    标签: excel vba long-long


    【解决方案1】:

    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 位变量的子或函数

    可以这样声明:

    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 都是 8 字节的“LongLong 整数”:
    -9.223.372.036.854.775.808 到 9.223.372.036.854.775.807

    但请注意:但如果您使用 LongLong,它将仅适用于 64 位,其中 32 位上的 LongPtr 将被简单地处理为 4 个字节的 Long,这会导致
    -2.147.483.648 到 2.147.483.647

    因此,如果您确实需要在两个系统上都具有较高的值,而 Long 还不够,请考虑使用 Double(8 字节,包括舍入效果!)或 Decimal(14 字节,必须声明为 @ 987654333@先):

    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
    

    【讨论】:

      【解决方案2】:

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

      然而,当我尝试用“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
      

      【讨论】:

      • 抱歉,您在写这篇文章时正忙着编辑我的答案/新问题。但无论如何都将您的答案标记为有帮助:-)。
      • 如果你声明 Dim Max, Min As LongLong 那么 Max 只是一个变体!声明Dim Max As LongLong, Min As LongLong
      • 谢谢,我按照你说的做了,但 VBA 仍然在行:ReDim Arr(Min, Max) 处显示“类型不匹配”
      • A到B不同于A、B!在 cmets 或答案中发布一个新问题,但请提出一个新主题
      猜你喜欢
      • 1970-01-01
      • 2018-01-22
      • 2015-01-05
      • 1970-01-01
      • 1970-01-01
      • 2015-05-04
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多