> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 64-bit Unsigned Integers in VBA
- URL: https://nolongerset.com/64-bit-unsigned-integers-in-vba/
- Published: 2021-11-23T02:33:26.000Z
- Updated: 2026-05-08T12:51:33.000Z
- Description: VBA is missing a data type. The workaround--while not pretty--is at least straightforward.
- Author: Mike Wolfe
- Tags: Advanced, Memory Management, #Import 2026-05-20 02:59

VBA is missing a data type.

There is no native 64-bit unsigned integer data type in VBA. In practice, this is rarely an issue. But "rarely" is not the same as "never." To take advantage of certain Windows API calls, you'll need a workaround.

Luckily, with a bit of memory manipulation, we can **simulate a 64-bit unsigned integer data type in VBA**.

## New Features in VBA Version 7

Let's start with a bit of background.

The last major feature release for the VBA language–version 7–came as part of Office 2010\. VBA7 provided 64-bit support for the VBA language. Well, mostly.

Here are the new keywords introduced in VBA7:

- `#If Win64`
- `#If VBA7`
- `PtrSafe`
- `LongPtr`
- `LongLong`

The `#If Win64` compiler constant returns True if the code is executing in 64-bit mode. It actually doesn't get used that much, because of the other new compiler constant.

The `#If VBA7` compiler constant returns True if the code is executing in version 7 of VBA. That's important, because it means you can use the `PtrSafe` and `LongPtr` keywords without raising a compile error.

The `PtrSafe` keyword is your way as the developer to say to the VBA compiler, "Yes, I reviewed this API call and it works properly in 64-bit mode."

The `LongLong` data type is a 64-bit *signed* integer. It also gets used surprisingly little, because of the other new "data type."

The `LongPtr` data type is a chameleon. In 64-bit mode, it's a `LongLong`. In 32-bit mode, it's a `Long`.

## Missing Feature in VBA7

The one omission from the above list is an *unsigned* 64-bit integer type. 

While it's not something you use that often, its absence is annoying when working with certain Windows API functions. Interestingly, this is not simply a 64-bit VBA issue. Some of these API functions require a 64-bit unsigned integer even when running in 32-bit VBA. 

For example, the API functions that return hard disk space ([GetDiskFreeSpaceEx](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa)) need to support numbers larger than 32 bits, otherwise you wouldn't be able to query the size of hard disks that are larger than 4 GB.

## Querying Memory Usage in 64-bit VBA

In a recent article, I wrote about how to return the available virtual memory in VBA. 

The focus of the article was on the memory limitations of 32-bit VBA, and the promise of expanding usable memory via the [Large Address Aware (LAA) flag](https://nolongerset.com/laa-flag/). To help make my point, I provided some code that runs fine in 32-bit VBA. It blew up if you tried running it in 64-bit VBA, though. 

Thanks to commenter Jörgen Rindstedt for reporting the problem:

> I get a strange result: Total memory: -1987477504 B Memory used: -1987477508 B Memory free: 4 B Pct used: 100,00%

Well, Jörgen, I have good news. I scoured the internet for information on the topic of unsigned 64-bit integers and re-wrote the code to work for both 32-bit *and* 64-bit environments.

Here's the sample output when running on my [64-bit VBA development machine](https://nolongerset.com/64-bit-now-the-default/):

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/11/image-65.png)

Sample output in 64-bit VBA.

Here's the sample output from a 32-bit VBA development machine:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/02/image-32.png)

Sample output in 32-bit VBA.

Note that in the sample output in 32-bit VBA, the Total Paging File returns a value of -1\. This indicates an overflow, as the total size of the paging file does not fit in a Long integer, which is the return type for the `GlobalMemoryStatus` API call. 

The [documentation](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalmemorystatus) for `GlobalMemoryStatus` says to use \`GlobalMemoryStatusEx instead:

> On computers with more than 4 GB of memory, the **GlobalMemoryStatus** function can return incorrect information, reporting a value of –1 to indicate an overflow. For this reason, applications should use the [GlobalMemoryStatusEx](https://learn.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex) function instead.

However, when I tried running `GlobalMemoryStatusEx` on my 32-bit VBA development machine, I got no information at all:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/02/image-33.png)

Sample output running `GlobalMemoryStatusEx` in 32-bit VBA.

## Sample Code

I wrote earlier that `#If Win64` is rarely necessary, since the combination of `#If VBA7` and `LongPtr` are a simpler alternative. However, `#If Win64` exists for a reason. And, as I also wrote earlier, "rarely" is not the same as "never." The `#If Win64` compiler constant makes several appearances in the sample code below.

Without further ado, here's the sample code:

```vba
Option Compare Database
Option Explicit

'Inspired by: https://stackoverflow.com/a/48626253/154439  (h/t Charles Williams)
#If VBA7 Then
    Private Declare PtrSafe Sub CopyMemory Lib "Kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
    Private Declare Sub CopyMemory Lib "Kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
#End If

#If Win64 Then
    Declare PtrSafe Sub GlobalMemoryStatusEx Lib "kernel32" (lpBuffer As MEMORYSTATUS)
    
    Private Type LARGE_INTEGER
        LowPart As Long
        HighPart As Long
    End Type
    
    'GlobalMemoryStatusEx outputs memory sizes in 64-bit *un*-signed integers;
    '   LongLong won't give us correct values because it is a signed type;
    '   the workaround is to use a custom data type and convert the result to Currency,
    '   as Currency is a fixed-point numeric data type supporting large values
    Public Type MEMORYSTATUS
       dwLength As Long
       dwMemoryLoad As Long
       dwTotalPhys As LARGE_INTEGER
       dwAvailPhys As LARGE_INTEGER
       dwTotalPageFile As LARGE_INTEGER
       dwAvailPageFile As LARGE_INTEGER
       dwTotalVirtual As LARGE_INTEGER
       dwAvailVirtual As LARGE_INTEGER
       dwAvailExtendedVirtual As LARGE_INTEGER
    End Type
    
#Else
    Declare Sub GlobalMemoryStatus Lib "kernel32" (lpBuffer As MEMORYSTATUS)
    Public Type MEMORYSTATUS
       dwLength As Long
       dwMemoryLoad As Long
       dwTotalPhys As Long
       dwAvailPhys As Long
       dwTotalPageFile As Long
       dwAvailPageFile As Long
       dwTotalVirtual As Long
       dwAvailVirtual As Long
    End Type
#End If

#If Win64 Then
'Convert raw 64-bit unsigned integers to Currency data type
Private Function LargeIntToCurrency(liInput As LARGE_INTEGER) As Currency
    'copy 8 bytes from the large integer to an empty currency
    CopyMemory LargeIntToCurrency, liInput, LenB(liInput)
    'adjust it
    LargeIntToCurrency = LargeIntToCurrency * 10000
End Function
#End If

Sub ShowMemStats()
    Dim Mem As MEMORYSTATUS
    Mem.dwLength = LenB(Mem)
#If Win64 Then
    GlobalMemoryStatusEx Mem
#Else
    GlobalMemoryStatus Mem
#End If

    Debug.Print "Memory load:", , Mem.dwMemoryLoad; "%"
    Debug.Print
    Debug.Print "Total physical memory:", BytesToXB(Mem.dwTotalPhys)
    Debug.Print "Physical memory free: ", BytesToXB(Mem.dwAvailPhys)
    Debug.Print
    Debug.Print "Total paging file:", BytesToXB(Mem.dwTotalPageFile)
    Debug.Print "Paging file  free: ", BytesToXB(Mem.dwAvailPageFile)
    Debug.Print
    Debug.Print "Total virtual memory:", BytesToXB(Mem.dwTotalVirtual)
    Debug.Print "Virtual memory free: ", BytesToXB(Mem.dwAvailVirtual)
    
End Sub

'Convert raw byte count to a more human readable format
#If Win64 Then
Private Function BytesToXB(RawValue As LARGE_INTEGER) As String
    Dim Value As Currency
    Value = LargeIntToCurrency(RawValue)
    
#Else
Private Function BytesToXB(Value As Long) As String

#End If
    Select Case Value
    Case Is > (2 ^ 30)
        BytesToXB = Round(Value / (2 ^ 30), 2) & " GB"
    Case Is > (2 ^ 20)
        BytesToXB = Round(Value / (2 ^ 20), 2) & " MB"
    Case Is > (2 ^ 10)
        BytesToXB = Round(Value / (2 ^ 10), 2) & " KB"
    Case Else
        BytesToXB = Value & " B"
    End Select
End Function

```

Special thanks to [Charles Williams](https://stackoverflow.com/users/88173/charles-williams), whose [answer on StackOverflow](https://stackoverflow.com/a/48626253/154439) heavily influenced the changes I made in the above code. 

If you would like to learn more about 64-bit unsigned integers in VBA, I posted some good articles in the Further Reading section below.

---

### Referenced articles

[Large Address Aware FlagGetting a lot of “Out of memory” errors in newer versions of Access? This trick can more than triple your available memory in 32-bit versions of Access.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/11/american-flags-2756185_1920.jpg)](https://nolongerset.com/laa-flag/)

[Office 2019 Runs in 64-bit Mode By Default. Here’s What That Means for VBA DevelopersThrough Office 2016, default installs used the 32-bit version of the software. Now that 64-bit is the default, it’s time to bite the bullet and convert your VBA code.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2021/07/vacations-1569608_1920.jpg)](https://nolongerset.com/64-bit-now-the-default/)

### External references

[Detecting the environment: ‘Large Address Aware’ and the 3GB Boot SwitchCan VBA detect the /3GB boot switch? Microsoft have documented it here on MSDN and it’s quite good, as MSDN pages go: they have explained what it is as well as how to use it. This question is aim...![](https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a)Stack OverflowNigel Heffernan![](https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon@2.png?v=73d79a89bded)](https://stackoverflow.com/a/48626253/154439)

### Further reading

[Windows API Guide: Faking 64-bit Integers in Visual BasicHow to get around Visual Basic’s lack of a true 64-bit integer data type.![](http://www.jasinskionline.com/favicon.ico)vbapivbapi.com](http://www.jasinskionline.com/windowsapi/articles/64bit/index.html)

[High-precision timing with the QueryPerformanceCounter API functionWhile VB Timer functions is sufficiently precise for most tasks, it doesn’t provide the highest possible resolution most modern computer can provide. If your hardware supports high-resolution counters, you can do a much better job with a pair of API functions: Private Type LARGE\_INTEGER lowpart As L…![](https://www.devx.com/wp-content/uploads/devxfav.png)DevXdevx-admin![](https://www.devx.com/wp-content/uploads/2022/02/thumbnail.jpg)](https://www.devx.com/tip-bank/18482/)

[Accurate Performance Timers in VBAThere are many times when you want to know how fast your code really is. Especially if you find your VBA application responding slowly you need to know where the bottleneck is occurring. You can bu…bytecombPrecision Time Delay | VBA Tips![](https://s0.wp.com/i/blank.jpg)](https://bytecomb.com/accurate-performance-timers-in-vba/)

*Image by [Rudy and Peter Skitterians](https://pixabay.com/users/skitterphoto-324082/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=672985) from [Pixabay](https://pixabay.com/?utm%5Fsource=link-attribution&utm%5Fmedium=referral&utm%5Fcampaign=image&utm%5Fcontent=672985)*

***UPDATE*** *\[2022-09-09\]: Fix broken link to QueryPerformanceCounter API article.*

***UPDATE*** *\[2023-02-19\]: Bug fix for 32-bit VBA (added `#If Win64` conditional compilation around `LargeIntToCurrency` function). Also added screenshots for calling code in 32-bit VBA. Thanks for reporting, Tom Wickerath!*