Application Development
for Microsoft® Office
Declaring API functions in 64 bit Office
Introduction
With the introduction of Windows 7 and Office 2010 VBA developers face
a new challenge: ensuring their applications work on both 32 bit and 64
bit platforms.
This page is meant to become the first stop for anyone who needs the
proper syntax for his API declaration statement in Office VBA.
Many of the declarations were figured out by Charles Williams of
www.decisionmodels.com
when he created the 64 bit version of our
Name Manager.
Links
Of course Microsoft documents how to do this. There is an introductory
article on Microsoft MSDN:
Compatibility Between the 32-bit and 64-bit Versions of Office 2010
That article describes the how-to's to properly write the declarations.
What is missing is which type declarations go with which API function or
sub.
Microsoft has provided an updated version of the Win32API.txt with all
proper declarations available for download here:
Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support
When you run the installer after downloading the file form
the link above, it does not tell you where it installed the information.
Look in this -new- folder on your C drive:
C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe
You can find a list of the old Win32 API declarations here:
Visual Basic Win32 API Declarations
Microsoft also published a tool to check your code for 64 bit related
problems, called the
Microsoft Office Code Compatibility inspector addin.
API functions that were added/modified in 64-bit Windows:
http://msdn.microsoft.com/en-us/library/aa383663(VS.85).aspx
API Functions by Windows release:
http://msdn.microsoft.com/en-us/library/aa383687(VS.85).aspx
Utter Access API declarations (a comprehensive list of many declarations)
Last, but certainly not least: Dennis Walentin has built an API viewer
that is really helpful. You can
find the API viewer here.
Declarations by API function
Function name |
Declarations (32 bit followed by 64 bit) |
CloseClipboard |
Declare PtrSafe Function
CloseClipboard Lib "User32" ()
As LongPtr
Declare Function
CloseClipboard Lib "User32" ()
As Long
|
CreateProcess |
We start off with a complicated one because it has a lot of
arguments. A fully functional example is included below the example
declaration lines.
Courtesy:
The
example code was taken from this page
Declare Function
CreateProcess Lib "kernel32"
_
Alias "CreateProcessA" (ByVal
lpApplicationName As
String, _
ByVal lpCommandLine
As String,
_
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles
As Long,
_
ByVal dwCreationFlags
As Long,
_
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String,
_
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As Long
Declare PtrSafe
Function CreateProcess Lib "kernel32"
_
Alias "CreateProcessA" (ByVal
lpApplicationName As
String, _
ByVal lpCommandLine
As String,
_
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles
As Long,
_
ByVal dwCreationFlags
As Long,
_
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String,
_
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As LongPtr
'Full example shown below, including the necessary structures
#If VBA7 Then
Declare PtrSafe
Function CreateProcess Lib "kernel32"
_
Alias "CreateProcessA" (ByVal
lpApplicationName As
String, _
ByVal lpCommandLine
As String,
_
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles
As Long,
_
ByVal dwCreationFlags
As Long,
_
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String,
_
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As LongPtr
Const INFINITE = &HFFFF
Const STARTF_USESHOWWINDOW = &H1
Private Enum
enSW
SW_HIDE = 0
SW_NORMAL = 1
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
End Enum
Private Type
PROCESS_INFORMATION
hProcess As LongPtr
hThread As LongPtr
dwProcessId As Long
dwThreadId As Long
End Type
Private Type
STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As
Long
dwYCountChars As
Long
dwFillAttribute As
Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Byte
hStdInput As LongPtr
hStdOutput As LongPtr
hStdError As LongPtr
End Type
Private Type
SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As
LongPtr
bInheritHandle As
Long
End Type
Private Enum
enPriority_Class
NORMAL_PRIORITY_CLASS = &H20
IDLE_PRIORITY_CLASS = &H40
HIGH_PRIORITY_CLASS = &H80
End Enum
#Else
Declare Function
CreateProcess Lib "kernel32"
_
Alias "CreateProcessA" (ByVal
lpApplicationName As
String, _
ByVal lpCommandLine
As String,
_
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles
As Long,
_
ByVal dwCreationFlags
As Long,
_
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String,
_
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As Long
Const INFINITE = &HFFFF
Const STARTF_USESHOWWINDOW = &H1
Private Enum
enSW
SW_HIDE = 0
SW_NORMAL = 1
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
End Enum
Private Type
PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Private Type
STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As
Long
dwYCountChars As
Long
dwFillAttribute As
Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Byte
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type
SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As
Long
bInheritHandle As Long
End Type
Private Enum
enPriority_Class
NORMAL_PRIORITY_CLASS = &H20
IDLE_PRIORITY_CLASS = &H40
HIGH_PRIORITY_CLASS = &H80
End Enum
#End If
Private Function
SuperShell(ByVal App
As String,
ByVal WorkDir As
String, dwMilliseconds
As Long,
_
ByVal start_size
As enSW, ByVal
Priority_Class As enPriority_Class)
As Boolean
Dim pclass As
Long
Dim sinfo As
STARTUPINFO
Dim pinfo As
PROCESS_INFORMATION
'Not used, but needed
Dim sec1 As
SECURITY_ATTRIBUTES
Dim sec2 As
SECURITY_ATTRIBUTES
'Set the structure size
sec1.nLength = Len(sec1)
sec2.nLength = Len(sec2)
sinfo.cb = Len(sinfo)
'Set the flags
sinfo.dwFlags = STARTF_USESHOWWINDOW
'Set the window's startup position
sinfo.wShowWindow = start_size
'Set the priority class
pclass = Priority_Class
'Start the program
If CreateProcess(vbNullString, App,
sec1, sec2, False, pclass, _
0&, WorkDir, sinfo, pinfo) Then
'Wait
' WaitForSingleObject
pinfo.hProcess, dwMilliseconds
SuperShell = True
Else
SuperShell = False
End If
End Function
Sub Test()
Dim sFile As
String
'Set the dialog's title
sFile = Application.GetOpenFilename("Executables (*.exe),
*.exe", , "")
SuperShell sFile, Left(sFile, InStrRev(sFile, "\")),
0, SW_NORMAL, HIGH_PRIORITY_CLASS
End Sub
|
DrawMenuBar |
#If VBA7 Then
Public Declare
PtrSafe Function DrawMenuBar
Lib "user32" (ByVal
hWnd As LongPtr)
As Long
#Else
Public Declare
Function DrawMenuBar
Lib "user32" (ByVal
hWnd As Long)
As Long
#End If
|
EmptyClipboard |
Declare PtrSafe Function
EmptyClipboard Lib "User32" ()
As LongPtr
Declare Function
EmptyClipboard Lib "User32" ()
As Long
|
FindWindow |
Private Declare
Function FindWindow
Lib "USER32" Alias "FindWindowA"
(ByVal lpClassName
As String,
ByVal lpWindowName
As String)
As Long
Private Declare PtrSafe
Function FindWindow
Lib "USER32" Alias "FindWindowA"
(ByVal lpClassName
As String,
ByVal lpWindowName
As String)
As LongPtr
|
FindWindowEx |
Private Declare
Function FindWindowEx
Lib "USER32" _
Alias "FindWindowExA" (ByVal
hWnd1 As Long,
ByVal hWnd2 As
Long, _
ByVal lpsz1 As
String, ByVal
lpsz2 As String)
As Long
Private Declare PtrSafe
Function FindWindowEx
Lib "USER32" _
Alias "FindWindowExA" (ByVal
hWnd1 As LongPtr,
ByVal hWnd2 As
LongPtr, _
ByVal lpsz1 As
String, ByVal
lpsz2 As String)
As LongPtr
|
GdipCreateBitmapFromFile |
Private Declare
Function GdipCreateBitmapFromFile
Lib "GDIPlus" (ByVal
filename As Long,
bitmap As Long)
As Long
Private Declare
PtrSafe Function GdipCreateBitmapFromFile
Lib "GDIPlus" (ByVal
filename As LongPtr, bitmap
As LongPtr) As
LongPtr
|
GdipCreateHBITMAPFromBitmap |
Private Declare
Function GdipCreateHBITMAPFromBitmap
Lib "GDIPlus" (ByVal
bitmap As Long,
hbmReturn As Long,
ByVal background
As Long)
As Long
Private Declare
PtrSafe Function GdipCreateHBITMAPFromBitmap
Lib "GDIPlus" (ByVal
bitmap As LongPtr, hbmReturn
As LongPtr,
ByVal background
As Long) As
LongPtr
|
GdipDisposeImage |
Private Declare
Function GdipDisposeImage
Lib "GDIPlus" (ByVal
image As Long)
As Long
Private Declare
PtrSafe Function GdipDisposeImage
Lib "GDIPlus" (ByVal
image As LongPtr)
As LongPtr
|
GdiplusShutdown |
Private Declare
Function GdiplusShutdown
Lib "GDIPlus" (ByVal
token As Long)
As Long
Private Declare
PtrSafe Function GdiplusShutdown
Lib "GDIPlus" (ByVal
token As LongPtr)
As LongPtr
|
GdiplusStartup |
Private Declare
Function GdiplusStartup
Lib "GDIPlus" (token
As Long,
inputbuf As GdiplusStartupInput,
Optional ByVal
outputbuf As Long
= 0) As Long
Private Type
GdiplusStartupInput
GdiplusVersion As
Long
DebugEventCallback As
Long
SuppressBackgroundThread As
Long
SuppressExternalCodecs As
Long
End Type
Private Declare
PtrSafe Function GdiplusStartup
Lib "GDIPlus" (token
As LongPtr, inputbuf
As GdiplusStartupInput,
Optional ByVal
outputbuf As LongPtr = 0)
As LongPtr
Private Type
GdiplusStartupInput
GdiplusVersion As
Long
DebugEventCallback As LongPtr
SuppressBackgroundThread As
Long
SuppressExternalCodecs As
Long
End Type
|
GetClassName |
Public Declare
Function GetClassName
Lib "USER32" Alias "GetClassNameA"
_
(ByVal hWnd As
Long, ByVal lpClassName
As String, _
ByVal nMaxCount
As Long) As Long
Public Declare
PtrSafe Function GetClassName
Lib "USER32" Alias "GetClassNameA"
_
(ByVal hWnd As
LongPtr, ByVal
lpClassName As String, _
ByVal nMaxCount
As LongPtr)
As Long
|
GetDiskFreeSpaceEx |
Private Declare
Function GetDiskFreeSpaceEx
Lib "kernel32" _
Alias "GetDiskFreeSpaceExA" (ByVal
lpDirectoryName As
String, _
lpFreeBytesAvailableToCaller As
Currency, _
lpTotalNumberOfBytes As
Currency, _
lpTotalNumberOfFreeBytes As
Currency) As
Long
Private Declare
PtrSafe Function GetDiskFreeSpaceEx
Lib "kernel32" Alias _
"GetDiskFreeSpaceExA" (ByVal lpDirectoryName
As String,
_
lpFreeBytesAvailableToCaller As
Currency, lpTotalNumberOfBytes As
_
Currency, lpTotalNumberOfFreeBytes
As Currency)
As LongPtr
|
getDC |
Private Declare
Function GetDC
Lib "USER32" (ByVal
hWnd As Long)
As Long
Private Declare PtrSafe
Function GetDC
Lib "USER32" (ByVal
hWnd As LongPtr)
As LongPtr
|
GetDesktopWindow |
Public Declare
Function GetDesktopWindow
Lib "USER32" ()
As Long
Public Declare PtrSafe Function GetDesktopWindow Lib "USER32"
() As LongPtr
|
getDeviceCaps |
Private Declare
Function GetDeviceCaps
Lib "gdi32" (ByVal
hDC As Long,
ByVal nIndex As
Long) As
Long
Private Declare PtrSafe
Function GetDeviceCaps
Lib "gdi32" (ByVal
hDC As LongPtr,
ByVal nIndex As
Long) As
Long
|
GetDriveType |
Private Declare
Function GetDriveType
Lib "kernel32" Alias _
"GetDriveTypeA"
(ByVal sDrive As
String) As
Long
Private Declare PtrSafe Function GetDriveType Lib "kernel32"
Alias _
"GetDriveTypeA"
(ByVal sDrive As String) As LongPtr
|
GetExitCodeProcess |
#If VBA7 Then
Declare PtrSafe
Function GetExitCodeProcess
Lib "kernel32" (ByVal _
hProcess As
LongPtr, lpExitCode As
Long) As
Long
#Else
Declare Function
GetExitCodeProcess Lib "kernel32"
(ByVal _
hProcess As
Long, lpExitCode
As Long)
As Long
#End If
|
GetForegroundWindow |
Declare Function
GetForegroundWindow Lib "user32.dll"
() As Long
Declare PtrSafe Function GetForegroundWindow Lib "user32.dll"
() As LongPtr
|
getFrequency |
Declare Function
getFrequency Lib "kernel32"
Alias "QueryPerformanceFrequency" (cyFrequency
As Currency)
As Long
Private Declare PtrSafe
Function getFrequency
Lib "kernel32" Alias "QueryPerformanceFrequency"
(cyFrequency As
Currency) As
Long
|
GetKeyState |
Declare Function
GetKeyState Lib "USER32"
(ByVal vKey As
Long) As
Integer
Declare PtrSafe Function GetKeyState
Lib "USER32" (ByVal
vKey As Long)
As Integer
|
GetLastInputInfo |
#If VBA7 Then
Private Type
LASTINPUTINFO
cbSize As LongPtr
dwTime As LongPtr
End Type
Private Declare
PtrSafe Sub GetLastInputInfo
Lib "USER32" (ByRef
plii As LASTINPUTINFO)
#Else
Private Type
LASTINPUTINFO
cbSize As
Long
dwTime As
Long
End Type
Private Declare
Sub GetLastInputInfo
Lib "USER32" (ByRef
plii As LASTINPUTINFO)
#End If
|
GetOpenFileName |
Option Explicit
#If VBA7 Then
Public Declare
PtrSafe Function GetOpenFileName
Lib "comdlg32.dll" Alias _
"GetOpenFileNameA"
(pOpenfilename As OPENFILENAME)
As Long
Public Type
OPENFILENAME
lStructSize As
Long
hwndOwner As
LongPtr
hInstance As
LongPtr
lpstrFilter As
String
lpstrCustomFilter
As String
nMaxCustFilter
As Long
nFilterIndex
As Long
lpstrFile As
String
nMaxFile As
Long
lpstrFileTitle
As String
nMaxFileTitle
As Long
lpstrInitialDir
As String
lpstrTitle As
String
flags As
Long
nFileOffset As
Integer
nFileExtension
As Integer
lpstrDefExt As
String
lCustData As
LongPtr
lpfnHook As
LongPtr
lpTemplateName
As String
End Type
#Else
Public Declare
Function GetOpenFileName
Lib "comdlg32.dll" Alias _
"GetOpenFileNameA"
(pOpenfilename As OPENFILENAME)
As Long
Public Type
OPENFILENAME
lStructSize As
Long
hwndOwner As
Long
hInstance As
Long
lpstrFilter As
String
lpstrCustomFilter
As String
nMaxCustFilter
As Long
nFilterIndex
As Long
lpstrFile As
String
nMaxFile As
Long
lpstrFileTitle
As String
nMaxFileTitle
As Long
lpstrInitialDir
As String
lpstrTitle As
String
flags As
Long
nFileOffset As
Integer
nFileExtension
As Integer
lpstrDefExt As
String
lCustData As
Long
lpfnHook As
Long
lpTemplateName
As String
End Type
#End If
'/////////////////////////////////
'// End code GetOpenFileName //
'/////////////////////////////////
Public Function
GetMyFile(strTitle As
String) As
String
Dim OpenFile As
OPENFILENAME
Dim lReturn
As Long
OpenFile.lpstrFilter = ""
OpenFile.nFilterIndex = 1
OpenFile.hwndOwner = 0
OpenFile.lpstrFile = String(257,
0)
#If VBA7 Then
OpenFile.nMaxFile = LenB(OpenFile.lpstrFile)
- 1
OpenFile.lStructSize = LenB(OpenFile)
#Else
OpenFile.nMaxFile = Len(OpenFile.lpstrFile)
- 1
OpenFile.lStructSize = Len(OpenFile)
#End If
OpenFile.lpstrFileTitle = OpenFile.lpstrFile
OpenFile.nMaxFileTitle = OpenFile.nMaxFile
OpenFile.lpstrInitialDir = "C:\"
OpenFile.lpstrTitle = strTitle
OpenFile.flags = 0
lReturn = GetOpenFileName(OpenFile)
If lReturn = 0
Then
GetMyFile = ""
Else
GetMyFile = Trim(Left(OpenFile.lpstrFile,
InStr(1, OpenFile.lpstrFile, vbNullChar) - 1))
End If
End Function
|
GetSystemMetrics |
Private Declare
Function GetSystemMetrics
Lib "USER32" (ByVal
nIndex As Long)
As Long
Private Declare PtrSafe
Function GetSystemMetrics
Lib "USER32" (ByVal
nIndex As Long)
As Long
|
GetTempPath |
Declare Function
GetTempPath Lib "kernel32"
_
Alias "GetTempPathA" (ByVal
nBufferLength As
Long, _
ByVal lpbuffer
As String)
As Long
Declare PtrSafe Function GetTempPath Lib "kernel32"
_
Alias "GetTempPathA" (ByVal nBufferLength As longptr,
_
ByVal lpbuffer As String) As Long
|
getTickCount |
Private Declare
Function getTickCount
Lib "kernel32" Alias "QueryPerformanceCounter"
(cyTickCount As
Currency) As
Long
Private Declare PtrSafe
Function getTickCount
Lib "kernel32" Alias "QueryPerformanceCounter"
(cyTickCount As
Currency) As
Long
'
|
getTime |
Private Declare
Function timeGetTime
Lib "winmm.dll" ()
As Long
Private Declare PtrSafe
Function timeGetTime
Lib "winmm.dll" ()
As Long
|
GetWindow |
Public Declare
Function GetWindow
Lib "USER32" _
(ByVal hWnd As
Long, ByVal
wCmd As Long)
As Long
Public Declare PtrSafe Function GetWindow
Lib "USER32" _
(ByVal hWnd As
LongPtr, ByVal wCmd As Long) As LongPtr
|
GetWindowLong |
This is one of the few API functions that requires the Win64
compile constant:
#If VBA7 Then
#If Win64 Then
Private
Declare PtrSafe
Function GetWindowLongPtr Lib "USER32"
Alias "GetWindowLongPtrA" (ByVal
hWnd As LongPtr,
ByVal nIndex As
Long) As LongPtr
#Else
Private
Declare PtrSafe
Function GetWindowLongPtr Lib "USER32"
Alias "GetWindowLongA" (ByVal
hWnd As LongPtr,
ByVal nIndex As
Long) As LongPtr
#End If
#Else
Private Declare
Function GetWindowLong
Lib "USER32" Alias "GetWindowLongA"
(ByVal hWnd As
Long, ByVal nIndex
As Long)
As Long
#End If
|
GetWindowsDirectory |
Declare Function
GetWindowsDirectory& Lib "kernel32"
Alias _
"GetWindowsDirectoryA"
(ByVal lpbuffer
As String,
_
ByVal nSize As
Long)
Declare PtrSafe
Function GetWindowsDirectory&
Lib "kernel32" Alias _
"GetWindowsDirectoryA"
(ByVal lpbuffer
As String,
_
ByVal nSize As LongPtr)
|
GetWindowText |
Public Declare
Function GetWindowText
Lib "USER32" Alias "GetWindowTextA"
_
(ByVal hWnd As
Long, ByVal
lpString As String,
_
ByVal cch As
Long) As
Long
Public Declare PtrSafe Function GetWindowText Lib "USER32"
Alias "GetWindowTextA" _
(ByVal hWnd As LongPtr, ByVal lpString As String, _
ByVal cch As LongPtr) As Long
|
GlobalAlloc |
Declare PtrSafe Function
GlobalAlloc Lib "kernel32" (ByVal
wFlags As LongPtr,
ByVal dwBytes As
LongPtr) As LongPtr
Declare Function
GlobalAlloc Lib "kernel32" (ByVal
wFlags As Long,
ByVal dwBytes As
Long) As
Long
|
GlobalLock |
Declare PtrSafe Function
GlobalLock Lib "kernel32" (ByVal
hMem As LongPtr)
As LongPtr
Declare Function
GlobalLock Lib "kernel32" (ByVal
hMem As Long)
As Long
|
InternetGetConnectedState |
Public Declare
Function InternetGetConnectedState
_
Lib "wininet.dll"
(lpdwFlags As Long,
_
ByVal dwReserved
As Long)
As Boolean
Public Declare PtrSafe Function InternetGetConnectedState _
Lib "wininet.dll" (lpdwFlags
As LongPtr, _
ByVal dwReserved As long) As Boolean
|
IsCharAlphaNumericA |
Private Declare
Function IsCharAlphaNumericA
Lib "USER32" (ByVal
byChar As Byte)
As Long
Private Declare PtrSafe
Function IsCharAlphaNumericA
Lib "USER32" (ByVal
byChar As Byte)
As Long
|
lstrcopy |
Declare PtrSafe Function
lstrcpy Lib "kernel32" (ByVal
lpString1 As Any,
ByVal lpString2
As Any) As
LongPtr
Declare Function
lstrcpy Lib "kernel32" (ByVal
lpString1 As Any,
ByVal lpString2
As Any) As Long
|
Mouse_Event |
#If VBA7 Then
Declare PtrSafe
Sub mouse_event
Lib "user32" (ByVal dwFlags
As Long,
ByVal dx As
Long, _
ByVal
dy As Long,
ByVal cButtons
As Long, _
ByVal
dwExtraInfo As LongPtr)
#Else
Private Declare
Sub mouse_event
Lib "user32" (ByVal dwFlags
As Long,
ByVal dx As
Long, _
ByVal
dy As Long,
ByVal cButtons
As Long, _
ByVal
dwExtraInfo As
Long)
#End If
Private Const
MOUSEEVENTF_MOVE = &H1
' mouse move
|
OleCreatePictureIndirect |
Private Declare
Function OleCreatePictureIndirect
Lib "oleaut32.dll" (PicDesc
As PICTDESC, RefIID
As GUID, ByVal
fPictureOwnsHandle As
Long, IPic As
IPicture) As Long
Private Type PICTDESC
Size As Long
Type As Long
hPic As Long
hPal As Long
End Type
Private Declare
PtrSafe Function OleCreatePictureIndirect
Lib "oleaut32.dll" (PicDesc
As PICTDESC, RefIID
As GUID, ByVal
fPictureOwnsHandle As LongPtr, IPic
As IPicture) As
LongPtr
Private Type
PICTDESC
Size As Long
Type As
Long
hPic As LongPtr
hPal As LongPtr
End Type
|
OpenClipboard |
Declare PtrSafe Function
OpenClipboard Lib "User32" (ByVal
hwnd As LongPtr)
As LongPtr
Declare Function
OpenClipboard Lib "User32" (ByVal
hwnd As Long)
As Long
|
OpenProcess |
#If VBA7 Then
Declare PtrSafe
Function OpenProcess
Lib "kernel32" (ByVal _
dwDesiredAccess
As Long,
ByVal bInheritHandle
As Long,
ByVal _
dwProcessId As
Long) As
LongPtr
#Else
Declare Function
OpenProcess Lib "kernel32" (ByVal
_
dwDesiredAccess
As Long,
ByVal bInheritHandle
As Long,
ByVal _
dwProcessId As
Long) As
Long
#End If
|
ReleaseDC |
Private Declare
Function ReleaseDC
Lib "USER32" (ByVal
hWnd As Long,
ByVal hDC As
Long) As
Long
Private Declare PtrSafe
Function ReleaseDC
Lib "USER32" (ByVal
hWnd As LongPtr,
ByVal hDC As
LongPtr) As Long
|
SendMessage |
Public Declare
Function SendMessageA
Lib "user32" (ByVal
hWnd As Long,
ByVal wMsg As
Long, _
ByVal wParam As
Long, lParam As
Any) As Long
Public Declare
PtrSafe Function SendMessageA
Lib "user32" (ByVal
hWnd As LongPtr,
ByVal wMsg As
Long, _
ByVal wParam As
LongPtr, lParam
As Any) As LongPtr
|
SetActiveWindow |
Declare Function
SetActiveWindow Lib "user32.dll"
(ByVal hWnd As
Long) As Long
Declare PtrSafe
Function SetActiveWindow Lib "user32.dll"
(ByVal hWnd As
LongPtr) As
LongPtr
|
SetClipboardData |
Declare PtrSafe Function
SetClipboardData Lib "User32" (ByVal
wFormat As LongPtr,
ByVal hMem As
LongPtr) As
LongPtr
Declare Function
SetClipboardData Lib "User32" (ByVal
wFormat As Long,
ByVal hMem As
Long) As Long
|
SetCurrentDirectory |
Private Declare
Function SetCurrentDirectoryA
Lib "kernel32" (ByVal
lpPathName As String)
As Long
Private Declare PtrSafe
Function SetCurrentDirectoryA
Lib "kernel32" (ByVal
lpPathName As String)
As Long
|
SetWindowLongPtr |
This is one of the few API functions that requires the Win64
compile constant:
#If VBA7 Then
#If Win64 Then
Private
Declare PtrSafe
Function SetWindowLongPtr Lib "USER32"
Alias "SetWindowLongPtrA" (ByVal
hWnd As LongPtr,
ByVal nIndex As
Long, ByVal
dwNewLong As LongPtr)
As LongPtr
#Else
Private
Declare Function
SetWindowLongPtr Lib "USER32"
Alias "SetWindowLongA" (ByVal
hWnd As LongPtr,
ByVal nIndex As
Long, ByVal dwNewLong
As LongPtr) As
LongPtr
#End If
#Else
Private Declare
Function SetWindowLong
Lib "USER32" Alias "SetWindowLongA"
(ByVal hWnd As
Long, ByVal nIndex
As Long,
ByVal dwNewLong
As Long) As Long
#End If
|
SetWindowPos |
#If VBA7 Then
Private Declare
PtrSafe Function SetWindowPos _
Lib
"user32" (ByVal hwnd
As LongPtr, ByVal
hWndInsertAfter As LongPtr, _
ByVal
X As Long,
ByVal Y As
Long, ByVal
cx As Long,
_
ByVal
cy As Long,
ByVal wFlags As
Long) As
Long
#Else
Private Declare
Function SetWindowPos _
Lib
"user32" (ByVal hwnd
As Long,
_
ByVal
hWndInsertAfter As
Long, _
ByVal
X As Long,
ByVal Y As
Long, _
ByVal
cx As Long,
_
ByVal
cy As Long,
_
ByVal
wFlags As Long)
As Long
#End If
|
SHBrowseForFolder |
#If VBA7 Then
Private Type
BROWSEINFO
hOwner As LongPtr
pidlRoot As
LongPtr
pszDisplayName As
String
lpszTitle As
String
ulFlags As
Long
lpfn As LongPtr
lParam As LongPtr
iImage As
Long
End Type
Private Declare
PtrSafe Function SHBrowseForFolder
Lib "shell32.dll" Alias "SHBrowseForFolderA"
_
(lpBrowseInfo As
BROWSEINFO) As LongPtr
#Else
Private Type
BROWSEINFO
hOwner As
Long
pidlRoot As
Long
pszDisplayName As
String
lpszTitle As
String
ulFlags As
Long
lpfn As
Long
lParam As
Long
iImage As
Long
End Type
Private Declare
Function SHBrowseForFolder
Lib "shell32.dll" Alias "SHBrowseForFolderA"
_
(lpBrowseInfo As
BROWSEINFO) As
Long
#End If
Private Const
BIF_RETURNONLYFSDIRS = &H1
|
ShellExecute |
Private Declare
Function ShellExecute
Lib "shell32.dll" Alias "ShellExecuteA"
( _
ByVal hwnd
As Long, ByVal
lpOperation As
String, ByVal lpFile
As String,
_
ByVal lpParameters
As String,
ByVal lpDirectory
As String,
ByVal nShowCmd
As Long)
As Long
Private Declare PtrSafe
Function ShellExecute
Lib "shell32.dll" Alias "ShellExecuteA"
( _
ByVal hwnd
As LongPtr, ByVal
lpOperation As
String, ByVal lpFile
As String,
_
ByVal lpParameters
As String,
ByVal lpDirectory
As String,
ByVal nShowCmd
As Long)
As LongPtr
|
SHFileOperation |
#If VBA7 Then
Type SHFILEOPSTRUCT
hWnd As LongPtr
wFunc As Long
pFrom As
String
pTo As
String
fFlags As
Integer
fAborted As
Boolean
hNameMaps As
Longptr
sProgress As
String
End Type
Declare PtrSafe
Function SHFileOperation Lib "shell32.dll"
Alias "SHFileOperationA" _
(lpFileOp As SHFILEOPSTRUCT)
As LongPtr
#Else
Type SHFILEOPSTRUCT
hWnd As
Long
wFunc As
Long
pFrom As
String
pTo As
String
fFlags As
Integer
fAborted As
Boolean
hNameMaps As
Long
sProgress As
String
End Type
Declare Function
SHFileOperation Lib "shell32.dll"
Alias "SHFileOperationA" _
(lpFileOp As SHFILEOPSTRUCT)
As Long
#End If
|
SHGetPathFromIDList |
Private Declare
Function SHGetPathFromIDList
Lib "shell32.dll" Alias "SHGetPathFromIDListA"
_
(ByVal pidl
As Long,
ByVal pszPath As
String) As
Boolean
Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll"
Alias "SHGetPathFromIDListA" _
(ByVal pidl As LongPtr, ByVal pszPath
As String) As Boolean
|
SHGetSpecialFolderLocation |
#If VBA7 Then Private Declare PtrSafe Function SHGetSpecialFolderLocation Lib _ "shell32.dll" (ByVal hwndOwner As LongPtr, ByVal nFolder As Long, _ pidl As ITEMIDLIST) As LongPtr Private Type SHITEMID cb As LongPtr abID As Byte End Type #Else Private Declare Function SHGetSpecialFolderLocation Lib _ "shell32.dll" (ByVal hwndOwner As Long, ByVal nFolder As Long, _ pidl As ITEMIDLIST) As Long Private Type SHITEMID cb As Long abID As Byte End Type #End If Private Type ITEMIDLIST mkid As SHITEMID End Type
|
timeGetTime |
Private Declare
Function timeGetTime
Lib "winmm.dll" ()
As Long
Private Declare PtrSafe
Function timeGetTime
Lib "winmm.dll" ()
As Long
|
URLDownloadToFile |
#If VBA7 Then
Private Declare
PtrSafe Function URLDownloadToFile
Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal
pCaller As Long,
_
ByVal
szURL As String,
ByVal szFileName
As String,
_
ByVal
dwReserved As Long,
ByVal lpfnCB As
Long) As
Long
#Else
Private Declare
Function URLDownloadToFile
Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal
pCaller As Long,
_
ByVal
szURL As String,
ByVal szFileName
As String,
_
ByVal
dwReserved As Long,
ByVal lpfnCB As
Long) As
Long
#End If
|
Which Longs should become LongPtr?
It's actually pretty easy to determine what requires LongPtr and
what can stay as Long. The only things that require LongPtr are function
arguments or return values that represent addresses in memory. This is because
a 64-bit OS has a memory space that is too large to hold in a Long data
type variable. Arguments or return values that represent data will still
be declared Long even in 64-bit.
The SendMessage API is a good example because it uses both types:
32-bit:
Public Declare
Function SendMessageA Lib "user32"
(ByVal hWnd As
Long, ByVal wMsg
As Long, _
ByVal wParam As
Long, lParam As
Any) As Long
64 bit:
Public Declare PtrSafe
Function SendMessageA Lib "user32"
(ByVal hWnd As LongPtr,
ByVal wMsg As
Long, _
ByVal wParam As
LongPtr, lParam As
Any) As LongPtr
The first argument -hWnd- is a window handle, which is an address in
memory. The return value is a pointer to a function, which is also an address
in memory. Both of these must be declared LongPtr in 64-bit VBA. The argument
wMsg is used to pass data, so can be Long in both 32-bit and 64-bit.
How to determine what is a memory address and what is data? You just
have to read
the MSDN documentation for the API functions (the C++ version) and it
will tell you. Anything called a handle, pointer, brush or any other object
type will require a LongPtr in 64-bit. Anything that is strictly data can
stay as Long.
Conditional compiling
If your code needs to run on both 32 bit and 64 bit Excel, then another
thing to do is add conditional compilation to your VBA.
Microsoft devised two compile constants to handle this:
VBA7: True if you're using Office 2010, False for older versions
WIN64: True if your Office installation is 64 bit, false for 32 bit.
Since the 64 bit declarations also work on 32 bit Office 2010, all you
have to test for is VBA7:
#If VBA7 Then
Private Declare
PtrSafe Function GetDeviceCaps
Lib "gdi32" (ByVal
hDC As LongPtr, ByVal
nIndex As Long)
As Long
#Else
Private Declare
Function GetDeviceCaps
Lib "gdi32" (ByVal hDC
As Long,
ByVal nIndex As
Long) As
Long
#End If
And then in the routine where this function is put to use:
#If VBA7 Then
Dim hDC As
LongPtr
#Else
Dim hDC As
Long
#End If
Dim lDotsPerInch As
Long
'Get the user's DPI setting
lDotsPerInch = GetDeviceCaps(hDC, LOGPIXELSX)
Other API functions
Have a function declaration which is not on this list? I invite you to
send me your (working and tested!!!) declarations so I can add them here.
I also welcome comments and suggestions on improvements!
Sorry for the truncations into 3 messages
George
Comment by: Jan Karel Pieterse (8/8/2013 9:03:19 PM)
Hi George,
Thanks!!
Comment by: Jan Karel Pieterse (8/8/2013 9:04:11 PM)
Hi George,
The best way is to find womeone with 64 bit Excel to test this.
Comment by: Daniel Isoje (12/29/2013 8:33:10 PM)
Your post makes it all easy for me now. Before now the 32/64bit issues have been troubling my mind as an access developer.
Many thanks.
Comment by: Erwin Kalvelagen (3/19/2014 4:54:16 PM)
Just as a warning: I believe the file Win32API_PtrSafe.TXT contains some errors wrt Excel 64 bit. I got a few "Microsoft Excel has stopped working errors". Most are related to strings.
Here are some details:
http://social.msdn.microsoft.com/Forums/office/en-US/9ad49156-0d29-4c0c-ae30-8e7c11ccd8cf/win32apiptrsafetxt-better-version-available?forum=exceldev
Comment by: Thomas Dette (7/30/2014 10:44:41 AM)
Hi,
do you have a "64bit translation" for following APIs
Declare Function SleepEx Lib "kernel32" (ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
Declare Function MoveFileEx Lib "kernel32" Alias "MoveFileExA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal dwFlags As Long) As Long
Declare Function sndPlaySound Lib "winmm.dll" snd dPlaySoundA" ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Declare Function WritePrivateProfileString& Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, _
ByVal lplFileName As String)
Declare Function GetPrivateProfileString& Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String)
Using ACCESS 2010 64bit.
Thanks for helping.
Thomas.
Comment by: Frank Barsnick (9/1/2014 1:37:24 PM)
Hi,
do you have a "64bit translation" for following APIs for reading an writing INI-files:
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, lpKeyName As Any, lpString As Any, ByVal lplFileName As String) As Integer
Private Declare Function DeletePrivateProfileSection Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal Section As String, ByVal NoKey As Long, ByVal NoSetting As Long, ByVal FileName As String) As Long
Thx for your help,
Frank
Comment by: Jan Karel Pieterse (9/1/2014 2:29:45 PM)
Hi Frank,
Sure:
Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Declare PtrSafe Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
I was unable to find the Delete one though!
Comment by: Alexander (9/29/2014 12:32:47 PM)
Error in declaration SHBrowseForFolder. To 64-bit returned type must be LongPtr:
Private Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" Alias "SHBrowseForFolderA" _
(lpBrowseInfo As BROWSEINFO) As LongPtr
Comment by: Jan Karel Pieterse (9/29/2014 1:09:12 PM)
Hi Alexander,
Thanks for pointing that out!
I have edited the page accordingly.
Comment by: LHEN (10/20/2014 10:20:12 AM)
Hi,
do you have a "64bit translation" for following APIs?
Public Declare Function WSAGetLastError Lib "WSOCK32.DLL" () As Long
'Returns the socket error
Public Declare Function WSAStartup Lib "WSOCK32.DLL" _
(ByVal wVersionRequired As Long, lpWSADATA As WSADATA) As Long
'Initialize sockets
Public Declare Function WSACleanup Lib "WSOCK32.DLL" () As Long
'Clean up sockets
Public Declare Function gethostname Lib "WSOCK32.DLL" _
(ByVal szHost As String, ByVal dwHostLen As Long) As Long
'Get Host Name
Public Declare Function gethostbyname Lib "WSOCK32.DLL" _
(ByVal szHost As String) As Long
Many thanks :)
Comment by: Jan Karel Pieterse (10/20/2014 10:26:56 AM)
Hi LHEN,
I'm sorry, but I don't.
Best to search MSDN for the functions and try to translate them yourself.
Comment by: Dave (11/14/2014 4:35:26 AM)
Nice Work Jan!
Comment by: Nigel Heffernan (11/14/2014 4:41:48 PM)
OpenProcess and GetExitCodeProcess would be useful: both are required for the widely-used ShellAndWait() function.
Note that they are quite tricky: while the handles and pointers are clearly LongPtr in the 64-bit environment, it's not clear whether the Process ID and the exit codes are Long or LongLong integers.
Comment by: Jan Karel Pieterse (11/17/2014 9:46:08 AM)
Hi Nigel,
Added!
Comment by: Zak (11/19/2014 11:08:33 AM)
Hi,
Hi to All,
Can anyone help me regarding my problem?
This is the scenario.
I have a .mdb file generated using Access 2010.
I tried to open the file using Access 2013.
After some modifications in the connections, I have a problem.
I have a browse button that when I click, resulted to this error.
Run-time Error '452'
Can't find DLL entry point 59 in msaccess.exe
When I debug, I think this portion have problem.
Declare PtrSafe Sub ms_accSplitPath Lib "msaccess.exe" Alias "#59" _
(ByVal strPath As String, ByVal strDrive As String, _
ByVal strDir As String, ByVal strFName As String, ByVal strExt As String)
*I just added the PtrSafe for 64-bit.
I will surely appreciate all your feedbacks.
Thank you very much.
Comment by: Dan (11/27/2014 1:18:44 PM)
Hi,
I need to make my code available to 32-Bit & 64-Bit Excel users, with both VBA7 and earlier verisons.
Can I not just use the
#if VBA7
statement to replace all Long with LongPtr for VBA7 environments? Surely this will just evaluate to long in 32-bit and longlong in 64-bit?
I'm failing to see how this could be detrimental. Why should I be only converting certain Longs to LongPtr?
Any guidance is appreciated.
Comment by: Jan Karel Pieterse (11/27/2014 2:31:29 PM)
Hi Dan,
To be honest, I'm not entirely sure what to answer here. My gut feeling says that the arguments you pass to a Win API need to be of the right type. I am not convinced LongPtr would be equally good as Long when the argument is supposed to be a Long. My gut feeling also whispers to me that this is the type of thing that lets vulnerabilities creep into software, but perhaps I'm paranoid :-) .
Comment by: Nigel Heffernan (1/21/2015 6:10:05 PM)
Hi Jan -
Thanks for the code for OpenProcess and GetExitCodeProcess.
I notice that you're not using LongLong anywhere in these declarations: do you have examples of Win64 API functions that do require them?
This isn't a matter of idle curiosity: other VBA Gurus are peppering their API declarations with LongLong and I think that they are occasionally wrong - but I think they are safer doing that than taking the risk of receiving a LongLong resource identifier or parameter into a Long integer, and passing the truncated result into another API call. Windows might throw an exception that VBA can handle as an error; it might crash Excel; or it might truncate the value silently and perform some arcane API function on the wrong resource.
Also, there are environments where LongPtr is available, but LongLong isn't.
This means that GetWindowLong isn't the only API declaration that needs three separate segments of conditional compilation; take a look at this, and consider what it means if the only place I can put a breakpoint is
'lParam = 6432'
Public Sub TestEnv()
#If VBA7 And Win64 Then
' 64 bit Excel under 64-bit windows
' We can use LongPtr and LongLong
Dim hWnd As LongPtr
Dim lParam As LongLong
lParam = 6464
#ElseIf VBA7 Then
' 64 bit Excel in all environments
' We can use LongPtr
Dim hWnd As LongPtr
Dim lParam As Long
lParam = 6432
#Else
' 32 bit Excel
' Any length you like, as long as it's Long
Dim hWnd As Long
Dim lParam As Long
lParam = 32
#End If
End Sub
I think we've all underestimated the complexity of the task we face in upgrading VBA code to 64-bit.
Comment by: Nigel Heffernan (1/21/2015 7:41:16 PM)
Dan,
You need to do some reading on Pointers, and why 'PtrSafe' matters. Google for 'Dangling Pointer' and see what you get.
What follows is my own understanding, in the language we use as VBA developers; and I am well aware that it contains oversimplifications that push it beyond mere errors and into the logical abyss that philosophers refer to as 'Not Even Wrong'.
A Pointer is the memory address of a resource - maybe the address of the Long integer you're using right now; maybe the address of an object which needs to be in memory when you need it, or a window handle; or, maybe, the address of a function that an API Timer has been told to call in sixty seconds' time.
When that address is incorrect, or when the resource at that address isn't what you expected, things can go badly wrong; so Microsoft have introduced new functions labelled 'Pointer-Safe', which use a special type of integer called 'LongPtr' for memory addresses; and a compiler that reads 'PtrSafe' and 'LongPtr' will create runtime code with new, improved, error-tolerant logic to manage these pointers and the resources in the memory addresses they point to.
You can still store addresses in a LongLong integer: a pointer is just a number. But the compiler won't do that new, improved pointer management on any old integer: you need to declare it as 'LongPtr'.
I do not know what will happen if you declare an everyday integer as a LongPtr, and use it in your code as (say) a loop counter.
My best guess is that things will run very slowly - every time the integer is changed, there will be a series of uneccessary checks to see if there's a memory address with a pointer already using 'your' number - and I would guess that an error-handler (or a complicated redirection and reallocation routine) will be called whenever your integer-declared-as-LngPtr is changed to a value that represents a pointer to memory that's already in use.
Let me know how your application works when you try that.
Comment by: John (3/19/2015 10:38:51 PM)
Hello, I have a problem with system tray icon. Icon cannot show and after minimized nothing happened. Do you know how to update vba code to win7 64bit?
Best regards
Comment by: Jan Karel Pieterse (3/20/2015 1:42:45 PM)
Hi John,
What code?
Comment by: Randy (4/28/2015 5:58:08 AM)
How do you get VBA to recognize the VBA7 constant? I'm running Office 2010 64-bit Excel. I declared a DLL function as follows:
[VB code below]
#IF VBA7 then
Declare PtrSafe Function ...
#ELSE
Declare Function ...
#END IF
The compiler flags the statement after the #ELSE as incorrect and won't compile.
Comment by: Jan Karel Pieterse (4/28/2015 8:39:36 AM)
Hi Randy,
The VBA7 compile constant should be recognized "out of the box". When precisely do you get the compile error?
Comment by: Randy (4/28/2015 8:45:19 PM)
Here's an example
#If VBA7 Then
Declare PtrSafe Function Foo Lib "Mylib" () As Double
#Else
Declare Function Foo lib "Mylib" () as Double
#End If
I can't move past the declaration following the #Else. A message box pops up saying "Compile error: The code in this project must be updated for use on 64-bit systems. Please review and update Declare statements and then mark them with the PtrSafe Attribute."
Comment by: Jan Karel Pieterse (4/29/2015 7:40:28 AM)
Hi Randy,
You can igonre those messages as far as I know (though you should not be getting them). You can avoid these silly compile error messages during editing by turning them off in the Editor options:
Tools, Options, uncheck "Auto syntax check".
Comment by: wareko (5/9/2015 4:02:32 AM)
Hi, I have a question.
In the above API functios list, there are two declarations for each function.
For example,
GetWindow has two declarations.
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
My question is,
Which constant VBA7 or WIn64 I should use?
For example of the two declarations below, which declaration is good?
I am confusing...
'Declaration using VBA7
#If VBA7 Then
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
#Else
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
#End If
'Declaration using Win64
#If Win64 Then
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
#Else
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
#End If
Comment by: Jan Karel Pieterse (5/9/2015 11:45:20 AM)
Hi Wareko,
VBA7 suffices in almost all cases. In case there is an exception it is mentioned in the sample code above.
Comment by: wareko (5/9/2015 12:29:43 PM)
Thank you for your quick reply!
Comment by: Frank (5/28/2015 2:11:31 PM)
Hi,
I'm certainly out of my element here, and I hope you can help. I'm using Excel 2010, and I was trying to create a macro whereby a user would click a link, and it would pass the product number to a Windows Explorer search function. I found the code below online that opens the search dialogue box.
It worked to open the search dialogue window, but it wasn't quite what I was looking for, so I removed the code and module. However, the code is still there somewhere, because when I try to step through any other module, the search dialogue window pops back up, and I can't get rid of it.
I'm on a network, and when I undocked my computer and went home last night and worked, all was fine. But when I came back to work today and redocked the computer, the issue was back.
Can you give me an idea of what I've done and how to fix it, please? Thank you!
=====================================
Option Explicit
'API declaration for the windows "Search Results" dialog
Private Declare Function ShellSearch& Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long)
Private Const SW_SHOWNORMAL = 1
Sub ShowWindowsSearchDialog_API()
' Specified drive to Search
Const szSDrive As String = "C:\"
ShellSearch 0, "find", szSDrive, "", "", SW_SHOWNORMAL
End Sub
Comment by: Jan Karel Pieterse (5/28/2015 2:57:31 PM)
Hi Frank,
Probably the code is in a file that loads when you start Excel. You should be able to locate the code by looking at all open projects in the Project explorer of the VBA editor and doing a find on each of them?
Comment by: Frank (5/28/2015 3:35:52 PM)
Hi Jan,
Thank you for getting back to me, and so quickly! Part of my conundrum is that there are NO files open. The only thing visible in the Project Explorer is the Personal.xlsb, and I've made sure that even that is empty (including Sheet1 and ThisWorkbook).
And why would this be happening when my computer is docked to the network, but when I undock it and take it home, everything is fine?
Thank you very much for considering my issue - it's VERY frustrating.
Frank
Comment by: Jan Karel Pieterse (5/28/2015 4:06:34 PM)
Hi Frank,
Does it also do this when you open Excel in safe mode (press and hold control key during Excel's startup)?
Comment by: Frank (5/28/2015 10:12:56 PM)
Hi again Jan,
I'm really at a loss for what happened, but I ended up restarting my computer this afternoon for an IT update, and when it booted back up, all was well with Excel. I had completely shut down my computer yesterday when I undocked, and I was glad it was ok when I got home. And I shut down again before coming back into work and redocking. And I was very surprised to see the issue had returned after redocking and booting back up. So I'm again surprised that it went away after restarting the computer this afternoon.
In the end, I'm glad things are back to normal, but I'd like to know what caused that.
Again, thank you very much for taking the time and interest in trying to help me resolve this issue.
Best regards,
Frank
Comment by: Alan Elston (6/23/2015 12:14:59 AM)
Hi,
. I have only basic VBA Knowledge.
. I have a code that is working for me in 32 Bit Vista XL 2010
. The code does not work in an identical system but XL 2007
. Initially the problem appears to be these lines, which error in XL 2007 but not XL 2010
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare PtrSafe Function CloseClipboard Lib "User32" () As Long
Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long
Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
.
. Sorry I cannot give more detail but my knowledge of VBA is limited.
. Is there any obvious reason for my problem?
. Thanks
Alan
Comment by: Jan Karel Pieterse (6/23/2015 7:35:14 AM)
Hi Alan,
The quick and dirty way to make this work on Excel 2007 is this:
#If VBA7 Then
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare PtrSafe Function CloseClipboard Lib "User32" () As Long
Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long
Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
#Else
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare Function CloseClipboard Lib "User32" () As Long
Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare Function EmptyClipboard Lib "User32" () As Long
Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
#End If
I haven't tried whether these are correct for 64 bit Office however!
Comment by: Alan Elston (6/23/2015 12:52:48 PM)
Hi.
. Many thanks Jan Karel Pieterse. With your Mod the code works for me now in both XL 2007 and XL 2010. I was googling similar things but was way out of my depth to apply them. Thanks for giving me the final full solution. I note that in XL 2007 the first Declare PtrSafe lines still come up Red, indicating error, but the code works , by virtue , I think of the # which somehow works so that that code is done prior to the compiling.
. I cannot check if the code works in 64 bit. But I highly expect it as the original author has the original code working in 64 bit:
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-thread.html
Comment by: Alan Elston (6/23/2015 12:57:22 PM)
. FYI. Jan, I have posted your modified code version and referenced you.
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-thread-2.html
…..and
Comment by: Alan Elston (6/23/2015 12:58:11 PM)
…..and here
http://www.excelforum.com/the-water-cooler/1068075-just-testing-img-cannot-do-it-in-test-forum-as-img-is-off-there-no-reply-needed-2.html#post4110298
Hope that is OK.
Alan.
Comment by: Alan Elston (6/23/2015 5:06:35 PM)
Hi
. Very sorry to mess up your site with my many replies here.
. Hope you catch them all and can edit them before you include them in your site:
- I was keen to acknowledge your help..
. The administrator has deleted the Posts where I acknowledged your help
. Hopefully they are still acknowledged here
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-forum-thread.html
Comment by: Alan Elston (6/23/2015 5:07:11 PM)
......and here:
http://www.excelforum.com/the-water-cooler/1068075-just-testing-img-cannot-do-it-in-test-forum-as-img-is-off-there-no-reply-needed-2.html#post4110298
. Sorry for any confusion. Thanks again for the help
. Alan
Comment by: Tawn (8/6/2015 8:10:14 PM)
I've downloaded the Microsoft Office Code Compatibility inspector add-in. I have MC Office Pro Plus 2010. The directions for use say to add the Developer Tab. I don't see the tab at File>Options>Customize Ribbon>Popular Commands>Main Tab.
I found one MVP that states there is not a Developer Tab for Access 2010.
Does the program need to be installed differently?
I have to get IT out to change installation and it would be helpful to know what I need to be able to see the Developer tab.
Thank you,
Tawn
Comment by: Jan Karel Pieterse (8/7/2015 2:20:54 PM)
Hi Tawn,
I have googled for a bit, but probably found the same information you already found.
AFAIK, all you need to do to check for 64 bit compliance is:
1. search your code for windows API declarations (those all start with the keyword "Declare", so they are easily found using a project-wide Find in the VBA editor)
2. Check whether or not you have used any external activeX controls in your project, because those may be unavailable in 64 bit (e.g. from the Common Controls library comclt.ocx). Mostly these should be shown in your VBA projects list of references.
Comment by: les (12/17/2015 7:19:49 PM)
I have a 32 bit version of Excel but have a client that has a 64 bit version. Where do I put the code to use the 64 bit if needed
Comment by: Jan Karel Pieterse (12/18/2015 11:52:08 AM)
Hi Les,
Does your code have any API calls (Declare statements)?
If not, chances are quite good that your file works on 64 bit without any changes.
Comment by: Vladimir Nazarov (2/9/2016 9:24:48 PM)
Dear Mr. Jan Karel Pieterse,
Could you please help me which Long becomes PtrLong in the following Type code in VBA7? Many thanks in advance.
Private Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
Flags As Long
time As Long
dwExtraInfo As Long
End Type
Comment by: Jan Karel Pieterse (2/10/2016 7:27:11 AM)
Hi Vladimir,
Which API funtion are you using?
Comment by: Jan Karel Pieterse (2/10/2016 7:28:54 AM)
Hi Vladimir,
I expect:
Private Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
Flags As Long
time As Long
dwExtraInfo As LongPtr
End Type
Comment by: Vladimir Nazarov (2/10/2016 2:07:28 PM)
Dear Mr. Jan Karl Pieterse,
I have just found a very interesting text document containing a lot of API declarations in VBA7 format however without an older version of VBA (295 pages of A4 format):
http://www.cadsharp.com/docs/Win32API_PtrSafe.txt
' ----------------------------------------------------------
'
'Win32API_PtrSafe.TXT -- Declare statements for
'Visual Basic for Applications and Microsoft Office 2010
Comment by: Jan Karel Pieterse (2/10/2016 2:28:49 PM)
Hi Vladimir,
Isn't that the same file as the one I refer to near the top of this article? (links section)
Comment by: Vladimir Nazarov (2/10/2016 3:38:20 PM)
Dear Mr. Jan Karel Pieterse,
Could you recommend any websites / links to convert old Excel VBA code into the code for VBA7 for the following API declarations and corresponding Type statements?
Can MAPI32.DLL used for 64-bit Excel or another DLL should be used instead and which one and how to change the code?
============================================================
Declare Function MAPILogon Lib "MAPI32.DLL" (ByVal UIParam&, ByVal User$, ByVal Password$, ByVal flags&, ByVal Reserved&, Session&) As Long
Declare Function MAPILogoff Lib "MAPI32.DLL" (ByVal Session&, ByVal UIParam&, ByVal flags&, ByVal Reserved&) As Long
Declare Function RAWMAPISendMail Lib "MAPI32.DLL" Alias "MAPISendMail" (ByVal Session&, ByVal UIParam&, Message As RAWMAPIMessage, ByVal flags&, ByVal Reserved&) As Long
Comment by: Jan Karel Pieterse (2/10/2016 4:02:28 PM)
Hi Vladimir,
It seems my page is one of the few that actually addresses this I'm afraid. And if a function is not in the winAPI.txt, then all you can do is try to find its definition on MSDN and then figure out what are the longptr's
Comment by: Elek (2/16/2016 4:30:21 PM)
Hi,
do you have a "64bit translation" for following APIs?
Public Function SetFileDateTime(FileName As String, _
FileDateTime As Double, WhichDateToChange As FileDateToProcess, _
Optional NoGMTConvert As Boolean = False) As Boolean
Thanks,
Elek
Comment by: Jan Karel Pieterse (2/16/2016 5:44:24 PM)
Hi elek,
I don't think that function is an API function so no 64 bit translation is needed. API functions are always declared using the "Declare" keyword. Any functuion NOT using that keyword is NOT a Windows API function and does not need 64 bit changes.
Comment by: Vladimir Nazarov (2/25/2016 4:52:28 PM)
Dear Mr. Jan K. Pieterse,
How to make the following function LowLevelKeyboardProc to work both in VBA6 and in VBA7?
In VBA6 it looks like follows and it works OK for Excel VBA6:
Public Function LowLevelKeyboardProc(ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
In VBA7 it this function should looks like shown below:
Public Function LowLevelKeyboardProc(ByVal nCode As LongPtr, _
ByVal wParam As LongPtr, _
ByVal lParam As LongPtr) As LongPtr
If I remove both Long and LongPtr as shown below hoping to make it work with both Excel VBA6 and Excel VBA7, then Excel VBA6 crashes.
In VBA6 it looks like follows:
Public Function LowLevelKeyboardProc(ByVal nCode, _
ByVal wParam, _
ByVal lParam) As Long
Please note, that all API functions have been declared properly using #If VBA7 Then … #Else … #End If construction.
Thanks in advance for your help.
Vladimir Nazarov
Comment by: Jan Karel Pieterse (2/26/2016 2:26:37 PM)
Hi Vladimir,
Can you please show the relevant declaration including the conditional compile stuff and the relevant pieces in your routine?
Comment by: Ramavatar (3/11/2016 7:47:17 AM)
Thanks for information shared but i wanted to know which references lib to be selected in excel vba for handling windowsfind api. or similar kind.
Comment by: Jan Karel Pieterse (3/11/2016 10:26:35 AM)
Hi Ramavatar,
Do you mean the FindWindow API? You can simply look it up in the table on this page. Windows API's do not need references, they only need the declare statement.
Comment by: Lorin Rowe (3/18/2016 9:30:22 PM)
in 32 bit I called:
Set tdConnection = CreateObject("tdapiole80.tdconnection")
how should I reference "CreateObject" in a 64bit world? This is a 32 bit DLL.
Comment by: Jan Karel Pieterse (3/20/2016 7:03:52 PM)
Hi Lorin,
I strongly suspect you simply cannot call a 32 bit dll form 64 bit VBA.
Comment by: Chris (3/20/2016 11:49:24 PM)
Having some trouble with hooking a window proc in Access on 64-bit Office 2016, Windows 10. Still VBA 7, and I have 64-bit declarations, but every time I latch the window proc below, Access crashes after a few messages.
Thoughts?
#If VBA7 Then
Public Function sDragDropAttach(ByVal hwnd As LongPtr, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As LongPtr
#Else
Public Function sDragDropAttach(ByVal hwnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
#End If
Dim lngRet As Long, strTmp As String, intLen As Integer
Dim lngCount As Long, i As Long, strOut As String
Const cMAX_SIZE = 255
On Error Resume Next
If Msg = WM_DROPFILES Then
strTmp = String(255, vbNullChar)
lngCount = DragQueryFile(wParam, _
&HFFFFFFFF, _
StrPtr(strTmp), _
Len(strTmp))
For i = 0 To lngCount - 1
strTmp = String(cMAX_SIZE, vbNullChar)
intLen = DragQueryFile(wParam, _
i, _
StrPtr(strTmp), _
cMAX_SIZE)
strOut = strOut & left(StrConv(strTmp, vbUnicode), intLen) & "|"
Next i
Call DragFinish(wParam)
'I do my file processing here
Else
lngRet = CallWindowProc(ByVal lpPrevWndProc, _
ByVal hwnd, _
ByVal Msg, _
ByVal wParam, _
ByVal lParam)
End If
End Function
Comment by: Jan Karel Pieterse (3/21/2016 7:11:43 AM)
Hi Chris,
I haven't used that function before, so I'm just making wild stabs here...
If you are creating hooks from API functions into your VBA code, are you properly releasing those hooks?
Are you sure there are no errors in your code, the on error resume next hides them.
Comment by: hilmi (6/2/2016 5:09:41 AM)
i'm still not understand how to solve it. beginner user. should we copy all and save it in module?
Comment by: Jan Karel Pieterse (6/7/2016 1:43:34 PM)
Hi Hilmi,
This is by far not something for a beginner user I'm afraid. I think it is best if you seek help from a more experienced VBA developer for this task.
Comment by: M Simms (6/23/2016 11:26:05 AM)
This is from the Microsoft MSDN portal:
Existing 32-bit ActiveX controls, both third-party and Microsoft-supplied, are not compatible with the 64-bit version of Office 2010. For ActiveX controls and COM objects, there are three possible solutions:
If you have the source code, you can generate a 64-bit version yourself,
You can contact the vendor for an updated version,
You can search for an alternative solution.
Comment by: Jan Karel Pieterse (6/23/2016 12:27:30 PM)
Hi M,
Yes correct. Another alternative is to build your own ActiveX-like control (if it is to be used on a userform) like this one:
www.jkp-ads.com/articles/treeview.asp
Comment by: M Simms (6/25/2016 3:14:15 PM)
Can ALL "Long" references both parameters as well as return values be converted to "LongPtr"....or are there exceptions ?
This assumes Office 2011, 2013, and 2016.
Comment by: M Simms (6/25/2016 3:29:53 PM)
Is the conversion below correct ?
I am worried about when to keep it Long vs. convert to LongPtr.
I take it that all handles and pointers should convert to LongPtr, correct ? Thanks for your help !!
--------------------------------------------------------
Private Declare Ptrsafe Function FtpCommand Lib "wininet.dll" Alias "FtpCommandA" _
(ByVal hConnect As LongPtr, _
ByVal fExpectResponse As Boolean, _
ByVal dwFlags As Long, _
ByVal lpszCommand As String, _
dwContext As LongPtr, phFtpCommand As LongPtr) As Boolean
' From the API documentation:
'BOOL FtpCommand(
' _In_ HINTERNET hConnect,
' _In_ BOOL fExpectResponse,
' _In_ DWORD dwFlags,
' _In_ LPCTSTR lpszCommand,
' _In_ DWORD_PTR dwContext,
' _Out_ HINTERNET *phFtpCommand
');
Comment by: Jan Karel Pieterse (6/27/2016 9:43:02 AM)
Hi M Simmons,
No, you cannot simply replace all Longs woth LongPtrs, that will cause problems.
Have a look at the API viewer built by Dennis Walentin:
http://www.rondebruin.nl/win/dennis/index.htm
Comment by: Jan Karel Pieterse (6/27/2016 9:45:33 AM)
Hi M Simms,
The FtpCommand declaration looks correct to me. Best to test it thoroughly on both 32 and 64 bit Office systems.
Comment by: M Simms (6/28/2016 7:52:29 PM)
Oh wow, that API Viewer looks terrific !!!
Does it also handle those "other" libraries like the FTP library ?
Comment by: gfmgin (8/22/2016 4:22:35 AM)
I presume this would also helpful for me have less knowledge on MS Office compatibility in programming MS Access from 32bit to 64.
Thank U Very Much!
Comment by: Peter Straton (8/24/2016 12:13:38 AM)
Shouldn't the last argument to the 64-bit declaration for GetWindow, wCmd, be a Long rather than a LongPtr since it is a numeric bit-code, consistent between both 32-bit and 64-bit Office, not a "pointer"?
Comment by: Jan Karel Pieterse (8/24/2016 9:18:14 AM)
Hi Peter,
You're right and I've corrected the declaration. Thanks!
Comment by: Mick Webb (9/6/2016 6:16:37 PM)
I assume that any wrappers where the result was Long but could now be either Long or LongPtr will have to have their return changed to Variant.
Comment by: Jan Karel Pieterse (9/7/2016 8:48:52 AM)
Hi Mick,
I don't really know to be honest. Do you have any specific function in mind?
Comment by: Mick Webb (9/7/2016 1:18:22 PM)
Hi,
For instance I have the FindWindow api in a wrapper to give me the handle of a MS UserForm.
Comment by: Jan Karel Pieterse (9/7/2016 4:47:46 PM)
Hi Mick,
In such a case (e.g. when you're returning a value from a function), wrap the function header in a conditional compilation statement:
#IF VBA7 Then
Function ReturnSomeValue() As LongPtr
#Else
Function ReturnSomeValue() As Long
#End If
'Code here which either assigns a Long or a LongPtr:
ReturnSomeValue = FindWindow(...)
End Function
Comment by: Mick Webb (9/9/2016 6:22:47 PM)
Simples - thank you
Mick
Comment by: Marcos Ferreira (10/10/2016 7:20:49 PM)
Esta lÃnea de da error en vba power point 64 bits
Private Declare Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Cómo deberÃa corregir para usar el comando sleep en Power Point?
Comment by: Jan Karel Pieterse (10/11/2016 7:05:54 AM)
Buenos dias Marcos,
Yo no hablo Espanol, pero:
Private PtrSafe Declare Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Comment by: atr (11/4/2016 8:10:18 AM)
Hello.
I have a question.
Why do you use the "LongPtr" in "ByVal nBufferLength As longptr"?
In the "Long" is it bad?
Declare PtrSafe Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As longptr, _
ByVal lpbuffer As String) As Long
Comment by: Jan Karel Pieterse (11/14/2016 4:32:30 PM)
Hi atr,
I must admit I don't know!
Comment by: Ramakrishnan S (11/29/2016 9:04:15 PM)
I have a 64 bit machine & have my VBscript (.vbs) that is for mouse automation and mouse click events.
I am using sendkeys to get a specific cursor position, but unable to click at that location.
Let me know how to use the API calls on 64 bit?
Thanks
Ram.S
Comment by: Jan Karel Pieterse (11/30/2016 1:42:48 PM)
Hi Ram,
You haven't mentioned which API functions you are using?
Comment by: Alan Elston (11/30/2016 4:09:05 PM)
Hi Jan Karel Pieterse
Is it possible to get a URL Link to a particular Comment placed here?
I ask as I find it useful to referrence some of your answers here
Thanks
Alan
Comment by: Jan Karel Pieterse (11/30/2016 6:10:43 PM)
Hi Alan,
That is actually a great idea! It will take me some time though, too much things going on right now.
Comment by: Alan Elston (11/30/2016 6:21:30 PM)
Thanks ! :)
Alan
Comment by: Brett Bourg (11/30/2016 6:22:45 PM)
Thank you for this page! It keeps helping me!
Comment by: Ram S (11/30/2016 7:54:00 PM)
Hi Jan Karel,
Greetings!. Thanks for asking the question.
As of now i just have the Win32 APIs. Am researching to see if there are mouse APIs related to getCursorPos and setCursorPos and click at that position om Win 64.
Thanks
Ram.S
Comment by: Alan Elston (12/1/2016 3:08:21 PM)
The new Comment direct URL links are working great, thanks again
Alan
Comment by: Jan Karel Pieterse (12/6/2016 10:09:12 AM)
Hi Alan,
Please post your current declarations.
Comment by: loquat (12/29/2016 1:48:46 PM)
how to use CallWindowProc in Win6 x64 office 32?
Comment by: Jan Karel Pieterse (12/30/2016 3:06:48 PM)
Hi loquat,
I suggest you to do a google search for that API adding VBA to the search words.
Comment by: Richard Bates (3/1/2017 9:24:42 AM)
'****************** N.B. I had to change the PtrSafe ReportEvent as it doesn't work at all ******************
Public Declare PtrSafe Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As LongPtr, _
ByVal wType As Integer, ByVal wCategory As Integer, ByVal dwEventID As Long, ByVal lpUserSid As Any, _
ByVal wNumStrings As Integer, ByVal dwDataSize As Long, plpStrings As LongPtr, lpRawData As Any) As Long
'Public Declare PtrSafe Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As LongPtr, _
ByVal wType As Long, ByVal wCategory As Long, ByVal dwEventID As Long, lpUserSid As Any, _
ByVal wNumStrings As Long, ByVal dwDataSize As Long, ByVal lpStrings As LongPtr, lpRawData As Any) As Long
'******************* N.B. This old code will work but it isn't PtrSafe **************************************
'Declare Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As Long, _
ByVal wType As Integer, ByVal wCategory As Integer, ByVal dwEventID As Long, ByVal lpUserSid As Any, _
ByVal wNumStrings As Integer, ByVal dwDataSize As Long, plpStrings As Long, lpRawData As Any) As Boolean
'************************************************************************************************************
Comment by: Jan Karel Pieterse (3/1/2017 10:04:22 AM)
Hi Richard,
Thanks for those!
Comment by: Bill (3/2/2017 8:15:29 PM)
I'm having a problem with code to hide access behind forms. I'm in Access 2013 on Windows 7 64-bit. The code seems to work for others in different forums, but mine can't fine the function apiShowWindow even though I changed to ptrsafe. It compiles, so the syntax is right, but burps at execution. You clearly understand this stuff, but I'm out of my area of expertise - do I need to add some reference in the VBA window? Thanks in advance for any help/ideas you can share.
Option Compare Database
Option Explicit
Global Const SW_HIDE = 0
Global Const SW_SHOWNORMAL = 1
Global Const SW_SHOWMINIMIZED = 2
Global Const SW_SHOWMAXIMIZED = 3
Private Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Function fSetAccessWindow(nCmdShow As Long)
Dim loX As Long
Dim loForm As Form
On Error Resume Next
Set loForm = Screen.ActiveForm
If Err <> 0 Then
loX = apiShowWindow(hWndAccessApp, nCmdShow)
Err.Clear
End If
If nCmdShow = SW_SHOWMINIMIZED And loForm.Modal = True Then
MsgBox "Cannot minimize Access with " _
& (loForm.Caption + " ") _
& "form on screen"
ElseIf nCmdShow = SW_HIDE And loForm.PopUp <> True Then
MsgBox "Cannot hide Access with " _
& (loForm.Caption + " ") _
& "form on screen"
Else
loX = apiShowWindow(hWndAccessApp, nCmdShow)
End If
fSetAccessWindow = (loX <> 0)
End Function
Comment by: Jan Karel Pieterse (3/3/2017 11:17:51 AM)
Hi Bill,
Try whether this declaration works:
Private Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Comment by: jay (3/16/2017 11:09:11 PM)
Just noticed, That in the List SendMessage wParam is LonpPtr.
Luckly I read "Which Longs should become LongPtr?"
and noticed this error.
Great site thanks and thanks to microsoft for all the new work.
Comment by: Charltsing (5/31/2017 5:57:47 PM)
I developed a free tool for automatic conversion of windows api in vbe. (office,autocad,etc)
http://www.cnblogs.com/Charltsing/p/SmartIndenter64.html
this vbe addins support windows API convert (Declare <--> PtrSafe),the number of supported api functions is about 1550.
thank you for your test!
Charltsing@gmail.com
Comment by: Luis Cardenas (7/3/2017 2:51:30 AM)
I'm having a problem with code to get a ciphered string from a C++ .dll I'm in Excel 2016 on Windows 10 64-bit. The code seems to work for strings no longer than 16 characters, because VB receives the result string as a LongPointer. Thanks in advance for any help/ideas you can share:
Option Explicit
Private Declare PtrSafe Function EncryptDecrypt Lib "F:\XLS\SegCrypt64.dll" (ByVal fEncrypt As Boolean, ByVal lpszInBuffer As String, ByRef lpszOutBuffer As LongPtr, ByRef dwOutBufferLen As Long) As Boolean
Function EncryptXLS(ByVal fEncrypt As Boolean, ByVal lpszInBuffer As String, ByRef lpszOutBuffer As LongPtr, ByRef dwOutBufferLen As Long) As Boolean
EncryptXLS = EncryptDecrypt(fEncrypt, lpszInBuffer, lpszOutBuffer, dwOutBufferLen)
End Function
Sub TestDll()
Dim Result As Variant ' Result
Dim StrIn As String 'String to Cipher
Dim strOut As LongPtr 'Ciphered String
Dim lOut As Long 'Lenght of StrCr
StrIn = "1234567890123456"
lOut = Len(StrIn)
strOut = StrPtr(String(lOut, " "))
Result = EncryptXLS(1, StrIn, strOut, lOut)
Result = Trim(CStr(strOut))
MsgBox (Hex(Result))
End Sub
Comment by: Jan Karel Pieterse (7/3/2017 10:32:30 AM)
Hi Luis,
This is a problem related to how C++ handles strings and how VBA handles strings and how to ensure you get the information accross between them. I googled a bit and found this article on stacj exchange. Hope it helps:
https://stackoverflow.com/questions/39404028/passing-strings-from-vba-to-c-dll
Comment by: J. W. Raper (9/27/2017 11:40:05 PM)
I am a novice trying to learn Excel VBA; you have personally helped me before and this web page continues that help. Above is the statement WIN64: True if your Office installation is 64 bit, false for 32 bit. I am confused because everywhere I look the compiler constant Win64 has little or nothing to do with the active office version, it simply indicates whether or not the office installation platform environment is 64-bit compatible. It would assist me if an Excel VBA professional would help me understand. Thank you in advance for your assistance.
Comment by: Jan Karel Pieterse (9/28/2017 7:36:02 AM)
Hi JW,
I agree the WIN64 compile constant is confusing, it should have read OFF64 if you ask me. This little routine returns TRUE *only* if your Office innstallation is 64 bit:
Function AmI64()
#If Win64 Then
AmI64 = True
#End If
End Function
Comment by: Chris B (10/19/2017 5:20:54 PM)
Thanks for the excellent documentation.
In your example for GetOpenFileName you have
#If VBA7 Then
...
Public Type OPENFILENAME
...
lCustData As Long
But the Microsoft documentation in file "Win32API_PtrSafe.TXT" has
Type OPENFILENAME
lCustData As LongPtr
Comment by: Jan Karel Pieterse (10/19/2017 5:44:09 PM)
Hi Chris,
Thanks!
Well spotted and I have corrected the error now.
Comment by: Martin L (11/2/2017 6:18:28 AM)
Working and tested function that could be added:
#If VBA7 Then
Public Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
Public Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
#End If
Comment by: Jan Karel Pieterse (11/2/2017 10:33:06 AM)
Thank you Martin, I have added it to the list.
Comment by: Manuel (12/19/2017 12:29:05 PM)
sConnect = "ODBC;UID=ADM124;PWD=ADM124;DATABASE="
If Base_Abierta = False Then
Set GdbCurrentDB = OpenDatabase("adm124", False, False, sConnect)
Error: Run-time error '429'
ActiveX component can't créate object.
How to solve this problem or error?
atte.
Manuel Araya Peña
Comment by: Jan Karel Pieterse (12/19/2017 1:01:25 PM)
Hi Araya,
In what application are you programming? MSAccess?
Comment by: Manuel (12/19/2017 1:04:39 PM)
No, with ODBD connection to Oracle.
atte.
Map
Comment by: Jan Karel Pieterse (12/19/2017 2:06:23 PM)
Hi Manuel,
I suggest you ask your question at www.eileenslounge.com
Comment by: Roy (12/26/2017 8:39:58 AM)
Hi, i cant seem to fix my Occupancy calculator. it works fine on office 2010, but its not working on office 2013. i already declared it safe but cant make it work. Appreciate your help.
below is the VBA code under module 1. let me know if you need the actual file that im having trouble with.
------------------------------------
Option Explicit
#If Win64 Then
Private Declare PtrSafe Function Erlcf Lib "erl32.dll" Alias "_Erlcf@16" _
(ByRef hours As Double, ByRef hold As Double, ByRef fract As Double, slsec As Double) As Double
#Else
Private Declare Function Erlcf Lib "erl32.dll" Alias "_Erlcf@16" _
(ByRef hours As Double, ByRef hold As Double, ByRef fract As Double, slsec As Double) As Double
#End If
Comment by: Jan Karel Pieterse (12/27/2017 11:27:42 AM)
Hi Roy,
Are you using 64 bit Office?
Is this dll a third-party dll by any chance? I cannot find any reference to it when I Google for it. If so, get hold of its maker, ask if there is a 64 bit version.
Comment by: Roy (12/27/2017 4:10:18 PM)
Hi there!
Thanks for your reply.
Yes it is 64bit Ms Excel. And yes, its a third party Dll file.
Comment by: Jan Karel Pieterse (12/28/2017 12:21:16 PM)
Hi Roy,
In that case you will need to find a 64 bit version of that dll. 32 bit dll's cannot be accessed by a 64 bit Office installation.
ALternatively, uninstall 64 bit Office and install the 32 bit version (the dafault).
Comment by: Roy (12/28/2017 2:16:33 PM)
Thanks for your response. I appreciate it.
Comment by: Andrija Vrcan (1/8/2018 8:50:28 PM)
Which way i can open folder using Shell API in 64 bit win,similar to:
Shell "C:\WINDOWS\EXPLORER.EXE " & FolderPath, vbNormalNoFocus
Thank you in advance.
Comment by: Jan Karel Pieterse (1/9/2018 8:09:15 AM)
Hi Andrija,
No need for a Windows API, there is a built-in method for it:
Application.FileDialog:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-filedialog-property-excel
Comment by: Andrija Vrcan (1/9/2018 10:04:31 AM)
Thank you Jan, but I don't need 'select' folder to be display, but only display specified folder. Cheers
Comment by: Jan Karel Pieterse (1/9/2018 10:53:17 AM)
Hi Andrija,
Apologies, I misunderstood!
What is wrong with the Shell method you already showed?
Comment by: Andrija Vrcan (1/9/2018 11:05:53 AM)
Shell "C:\WINDOWS\EXPLORER.EXE " & FolderPath, vbNormalNoFocus
works only in 32 bit win.
Comment by: Jan Karel Pieterse (1/9/2018 12:50:47 PM)
Hi Andrijja,
The code works just fine on my 64 bit Excel 2010.
Comment by: Andrija Vrcan (1/10/2018 9:38:39 AM)
Thank you Jan! The code did not work for my mistake (I accidentally commented part of the previous code).
Comment by: Chuck Minarik (1/19/2018 1:20:33 PM)
Thanks! This is just what I needed after converting from Office 32 to Office 64.
Comment by: Martin L (2/7/2018 11:05:38 PM)
I've seen the function SetWindowPos a lot in some forum posts that don't always use the appropriate declaration method,so I thought it would be good to add it here. I've made the adjustment myself and and tested the version below on my computer.
#If VBA7 Then
Private Declare PtrSafe Function SetWindowPos Lib "user32" ( _
ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
#Else
Private Declare Function SetWindowPos Lib "user32" ( _
ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
#End If
Comment by: Jan Karel Pieterse (2/8/2018 6:49:41 AM)
Hi Martin,
Thanks, I've added it to the list!
Comment by: Lorne (3/3/2018 2:14:55 PM)
Thanks for an valuable reference resource.
Why is the SendMessage function referred to by the alias of SEndMessageA? Also, the same example declaration at he foot of this page declares the wParam as Long instead of LongPtr. The Declaration returns LongPtr but the MS Win32API_PtrSafe.Txt states it is a Long. The same text file states that the GetClassName declaration for nMaxCount should be a Long, Not LongPtr.
Comment by: Jan Karel Pieterse (3/5/2018 10:24:24 AM)
Hi Lorne,
Good catch, I have updated the page to match the declaration in the txt file.
Comment by: Martin L (3/22/2018 6:08:48 AM)
I'm afraid that Lorne's comment was not completely right regarding SendMessage. I double checked in Win32API_PtrSafe.Txt and the return value for SendMessage actually requires LongPtr.
However, the comment was right regarding wParam which means that the following sentence: "The arguments wMsg and wParam are used to pass data, so they can be Long in both 32-bit and 64-bit."
should exclude the mention of wParam.
Comment by: Jan Karel Pieterse (3/22/2018 8:12:55 AM)
Hi Martin,
I have changed the declaration, thanks!
Comment by: Vishal kirve (4/9/2018 1:08:09 PM)
I want click on open button of notification bar of ie11 using vba code
Comment by: Jan Karel Pieterse (4/9/2018 4:36:39 PM)
Hi Vishal,
If you know the URL of the download, perhaps you can use the URLDownloadTofile function?
Comment by: Arjun (6/1/2018 8:33:40 PM)
Hi All,
i am missing something here
can anyone please edit the below 32 bit code for 64 bit excel
Option Explicit
Private Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As LongPtr, _
ByVal dx As Long, _
ByVal dy As Long, _
ByVal cButtons As Long, _
ByVal dwExtraInfo As Long)
Private Const MOUSEEVENTF_MOVE = &H1 ' mouse move
Private Const MOUSEEVENTF_LEFTDOWN = &H2 ' left button down
Private Const MOUSEEVENTF_LEFTUP = &H4 ' left button up
Private Const MOUSEEVENTF_RIGHTDOWN = &H8 ' right button down
Private Const MOUSEEVENTF_RIGHTUP = &H10 ' right button up
Private Const MOUSEEVENTF_MIDDLEDOWN = &H20 ' middle button down
Private Const MOUSEEVENTF_MIDDLEUP = &H40 ' middle button up
Private Const MOUSEEVENTF_WHEEL = &H800 ' wheel button rolled
Private Const MOUSEEVENTF_ABSOLUTE = &H8000 ' absolute move
Private Type POINTAPI
X As Long
Y As Long
End Type
Sub Click()
Dim pt As POINTAPI
Dim X As Long
Dim Y As Long
'(0,0) = top left
'(65535,65535) = bottom right
X = 29000 / 2
Y = 29000 / 2
LeftClick X, Y
End Sub
Sub LeftClick(X As Long, Y As Long)
'Move mouse
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE, X, Y, 0, 0
'Press left click
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
'Release left click
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
End Sub
Comment by: Jan Karel Pieterse (6/8/2018 7:40:30 PM)
Hi Arjun,
I have added it to the list.
Comment by: Jan Karel Pieterse (7/3/2018 2:34:40 PM)
Hi Giancarlo,
Thanks. But the txt file which I refer to at the start of this article says:
' Provided for reference only. Please use the LongPtr versions instead.
Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
Comment by: Jamie (8/22/2018 4:12:40 PM)
This is a great page! The declaration for GetWindowLong has two errors as it's shown as GetWindowLongPtr in two places. Here are a few more:
Public Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As Long
Public Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpFn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
Public Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Public Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Public Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Comment by: Jan Karel Pieterse (8/23/2018 2:50:29 PM)
Hi Jamie,
Thanks. What you posted, do you think those are the correct declarations?
Comment by: 123hemanth.singh@gmail.com (9/14/2018 10:56:34 PM)
Public Declare PtrSafe Function Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As LongPtr)
Not able to run this module.
Comment by: Jan Karel Pieterse (9/17/2018 10:40:21 AM)
Hi Hemanth (?),
When do you get this error?
Comment by: Tony Matyas (10/23/2018 1:25:19 PM)
Just a hint to avoid possible confusion after corrected code line: In the section "Which Longs should become LongPtr?" (after the declaration list block)
you corrected the SendMessageA argument's wParam type to LongPtr due to comments, but left the 3rd line in the following paragraph unchanged:
"The arguments wMsg and wParam (!) are used to pass data, so they can be Long in both (!) 32-bit and 64-bit."
Comment by: Jan Karel Pieterse (10/23/2018 5:18:30 PM)
Hi Tony,
Corrected, thanks!
Comment by: Tony Matyas (10/23/2018 7:42:50 PM)
ad) 1. GetWindowLong: Suppose the last #Else statement (AFTER WIN64/Win32 differentiation), i.e. referring to >VBA6< should be
Private Declare Function GetWindowLong Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
as IMO the GetWindowLongPtr replacement has been introduced later for Office 2010 and higher.
2. Similarly the last SetWindowLong declaration referring to elder Office Versions:
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Comment by: Jan Karel Pieterse (10/24/2018 9:42:21 AM)
Hi Tony,
Corrected, thanks!
Comment by: Joe (10/29/2018 7:13:00 AM)
Thanks to the information on this page, I've had some success in getting a personal application working in a mix of 32/64 worlds. The Windows API calls are all working...
I'm still stuck though: I have a third party 32bit DLL which just contain math and file functions.
On my Win7(x64) with Excel 2010 (32bit) it all works as it should. On a Win10(x64) with Excel 2016 (64bit) even using Public Declare PtrSafe... I get cannot find entry point, or sometimes a DLL not found error!
#If VBA7 Then
Private Declare PtrSafe Function LearningRate Lib "crunch.dll" (ByVal nIndex As Long, ByVal nWeight As Long, ByVal nFocus as Long) As Double
#Else
Private Declare Function LearningRate Lib "crunch.dll" (ByVal nIndex As Long, ByVal nWeight As Long, ByVal nFocus as Long) As Double
#End If
I have copies of the .dll file in both C:\Windows\System32 and C:\Windows\SysWOW64 although I'm not sure if the file needs to be in both locations? (My understanding is that System32 is (confusingly) for the 64bit DLLs and SysWOW64 is where the 32bit DLLs are kept?)
Can I call the functions from a "simple" 32bit DLL from 64bit VBA?
Any help would really be appreciated.
Joe.
Comment by: Jan Karel Pieterse (10/29/2018 11:10:27 AM)
Hi Joe,
In theory you cannot call 32 bit dll's from 64 bit VBA. But I seem to recall there is a convoluted win API work-around for it. Unfortunately I was not able to locate the demo file I thought I had on my system somewhere :-(
Comment by: A K (11/9/2018 3:17:12 AM)
Thank you for the great compilation. However, please note that most of the 64 bit declarations in the table are incorrect. Most of the declarations only need PtrSafe added to them. Only when actual pointers are being passed as an argument, they will need to be converted from Long to LongPtr or other pointer type. Otherwise, ByRef Long types (eventhough they are defined as pointers in the function documentation) still need to be declared as Long, not LongPtr. Also, Long returned values remain Long, and should not be converted to LongPtr. If you have access to 64 bit Office, please test these declarations and update accordingly, since apparently they have not been tested. I have tested the above information in this comment and they are correct.
Comment by: Jan Karel Pieterse (11/9/2018 11:30:00 AM)
Hi A K,
Most of these have been tested. Many of them come directly from the mentioned documentation by Microsoft.
I'm afraid I must disagree with your comment that most of them are wrong, I think they are correct. If any of these actually fail on 64 bit Office I'd like to know.
Have a question, comment or suggestion? Then please use this form.
If your question is not directly related to this web page, but rather a more
general "How do I do this" Excel question, then I advise you to ask
your question here: www.eileenslounge.com.
Comments
All comments about this page:
Comment by: Alexander Wolff (1/28/2010 12:01:43 PM)
- PtrSafe before "Function"
- LongPtr instead of "Long" (in some cases)
IsCharAlphaNumericA: "#Else" is probably not intended to be there?
Comment by: Jan Karel Pieterse (1/29/2010 2:40:08 AM)
Thanks for spotting the anomalies. Care to tell me which Long's must become LongPtr's?
Comment by: Ron Anderson (5/3/2010 5:13:21 PM)
Comment by: Jan Karel Pieterse (5/4/2010 12:36:23 AM)
Unfortunately, I have never used that application before, so I am not in the position to advise. I would suggest to contact the manufacturer about your problem.
Comment by: Anders Hauge (5/20/2010 10:35:46 AM)
Notice that the new file is called Win32API_PtrSafe.TXT and by default is installed to: C:\Office 2010 Developer Resources\
Comment by: Jan Karel Pieterse (5/21/2010 1:37:45 AM)
Comment by: Yuhong Bao (6/6/2010 12:23:09 AM)
"Private Declare PtrSafe Function GetWindowLongptr Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr"
Wrong, sorry. I think the best bet here is to use Win64 instead of VBA7 and use Alias "GetWindowLongPtrA" and Alias "SetWindowLongPtrA". That is how it is defined in the headers.
Comment by: Jan Karel Pieterse (6/6/2010 11:09:30 PM)
Thanks. Could you perhaps show the proper declarations in full?
Comment by: Yuhong Bao (6/6/2010 11:14:06 PM)
Private Declare PtrSafe Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Note that this Declare should be conditialized on Win64 instead of VB7, because Get/SetWindowLongPtr do not exist as an export on 32-bit Windows.
Comment by: Jan Karel Pieterse (6/7/2010 12:21:24 AM)
Thanks!
Comment by: Yuhong Bao (6/7/2010 1:15:58 PM)
Private Declare PtrSafe Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Comment by: Clarence (7/14/2010 8:43:57 AM)
Comment by: Jan Karel Pieterse (7/14/2010 10:58:42 AM)
No, but you will need code like the following:
#If VBA7 Then
Declare PtrSafe Function GetKeyState Lib "USER32" (ByVal vKey As Long) As Integer
#Else
Declare Function GetKeyState Lib "USER32" (ByVal vKey As Long) As Integer
#End If
Comment by: Villable (8/16/2010 10:53:06 AM)
Why?
How can i do faster my macros at 64 bits?.
Thanks
Comment by: Jan Karel Pieterse (8/16/2010 11:16:35 AM)
Depends on the code. Could you post some of it?
Comment by: Villable (8/16/2010 3:38:09 PM)
----------------
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Union(Target, Range("L5")).Address = _Range("L5").Address Then Call Calendario
End Sub
---------------
Private Sub Calendario()
ActiveSheet.Unprotect ("BCG")
f = Cells(1, 1) 'f=fila de comienzo
ff = Cells(1, 2) 'ff=fila final
m = Range("L5").Value 'm = mes
If ff > f Then Range("A" & f & ":A" & ff).EntireRow.Delete shift:=xlUp 'delete existing report
'New report
For o = Hoja3.Cells(1, 1) To Hoja3.Cells(1, 2)
Range("A2:A3").EntireRow.Copy'copy line
Rows(f).EntireRow.Insert shift:=xlDown 'insert line
Range("A" & f & ":A" & f + 1).EntireRow.Hidden = False 'show line
Cells(f, 1) = Hoja3.Cells(o, 1)
Cells(f, 2) = Hoja3.Cells(o, 2)
Hoja2.Range("AP3").Value = Hoja3.Cells(o,1)
f = f + 1
p = Hoja2.Cells(1, 1)
ff = Hoja2.Cells(1, 2) - 25
While p < ff
If Hoja2.Cells(p - 1 + m * 2, 42).Value > 0 Then
Rows(4).EntireRow.Copy
Rows(f).EntireRow.Insert shift:=xlDown
Rows(f).EntireRow.Hidden = False
Cells(f, 1) = Hoja3.Cells(o, 1)
Cells(f, 2) = Hoja2.Cells(p, 1).Value
Cells(f, 3) = (p - 5) / 26
Cells(f, 4) = Hoja2.Cells(p + m * 2, 42)
Cells(f, 6) = Hoja2.Cells(p - 1 + m * 2, 42) / Hoja2.Cells(p - 1 + m * 2, 36) * 100
f = f + 1
End If
p = p + 26
Wend
f = f + 1
Cells(f, 1).Select
Next
FIN:
Cells(Cells(1, 1), 1).Select
ActiveSheet.Protect ("BCG")
Beep
End Sub
----------------
Thanks
Comment by: Jan Karel Pieterse (8/16/2010 11:12:21 PM)
I see no obvious reason for the slowness of your code on 64 bit. But you may benefit from turning off screenupdating and calculation when the code starts:
Application.Calculation = xlCalculationManual
'Your code goes here
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Comment by: Villable (8/17/2010 1:01:53 AM)
Variable 'o' goes from 1 to 20 and variable 'p' goes from 1 to 42. So in 64 bits it takes, at least, AN HOUR while in 32 bits it takes 15 SECONDS!!!
I don't know which is the difference. I think is a bug of Office 2010 64bits, and i'm thinking about install 32 bits to get that problems off.
Thank you anyway.
Comment by: Doug Drada (10/11/2010 7:46:38 AM)
Comment by: Jan Karel Pieterse (10/11/2010 7:58:19 AM)
Please post them!
Can't you combine them into one post?
If unsure, please go ahead and send me an email (see bottom of page).
Comment by: Boomer57 (11/26/2010 4:17:06 PM)
Great site!
Since I'm cutting and pasting this code into VBA7, wrapping each api call with the:
#If VBA7 Then
.... 'New 64-bit declarations here...
#Else
.... 'Legacy 32-bit declarations here...
#End If
would be appreciated.
Thank you!!!
Comment by: Excelo (12/11/2010 12:01:34 PM)
Comment by: Tomas (12/15/2010 11:45:56 AM)
As I'am no expert in this matter i feel the need to ask for help on this matter.
I cant get these Api declarations to work with a 64bit office version. The 32bit declarations work fine...
thanks in advance
Tomas
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As Any) As LongPtr
#Else
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long
#End If
Comment by: Jan Karel Pieterse (12/16/2010 1:22:18 AM)
The type IntPtr does not exist (second declare statement in your code)
Comment by: Tomas (12/16/2010 12:15:34 PM)
Comment by: Satyendra (2/3/2011 8:04:12 AM)
Can you help me, to place LongPtr insted of Long in delarations. I am posting all my declarations in 2 or 3 posts. Because here I can't post more then 2000 chars in one post
Public Declare PtrSafe Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequired&, lpWSADATA As WSADATA) As Long
Public Declare PtrSafe Function WSACleanup Lib "wsock32.dll" () As Long
Public Declare PtrSafe Function gethostbyname Lib "wsock32.dll" (ByVal host_name As String) As Long
Public Declare PtrSafe Function gethostname Lib "wsock32.dll" (ByVal host_name As String, ByVal namelen As Integer) As Integer
Public Declare PtrSafe Function setsockopt Lib "wsock32.dll" (ByVal S As Long, ByVal level As Long, ByVal optname As Long, optval As Any, ByVal optlen As Long) As Long
Public Declare PtrSafe Function w_socket Lib "wsock32.dll" Alias "socket" (ByVal lngAf As Long, ByVal lngType As Long, ByVal lngProtocol As Long) As Long
Public Declare PtrSafe Function w_closesocket Lib "wsock32.dll" Alias "closesocket" (ByVal socketHandle As Long) As Long
Public Declare PtrSafe Function w_bind Lib "wsock32.dll" Alias "bind" (ByVal SOCKET As Long, Name As SOCKADDR_IN, ByVal namelen As Long) As Long
Public Declare PtrSafe Function w_connect Lib "wsock32.dll" Alias "connect" (ByVal SOCKET As Long, Name As SOCKADDR_IN, ByVal namelen As Long) As Long
Public Declare PtrSafe Function w_send Lib "wsock32.dll" Alias "send" (ByVal SOCKET As Long, buf As Any, ByVal length As Long, ByVal Flags As Long) As Long
Public Declare PtrSafe Function w_sendTo Lib "wsock32.dll" Alias "sendto" (ByVal SOCKET As Long, buf As Any, ByVal length As Long, ByVal Flags As Long, remoteAddr As SOCKADDR_IN, ByVal remoteAddrSize As Long) As Long
Public Declare PtrSafe Function w_recv Lib "wsock32.dll" Alias "recv" (ByVal SOCKET As Long, buf As Any, ByVal length As Long, ByVal Flags As Long) As Long
Comment by: Jan Karel Pieterse (2/3/2011 11:38:52 AM)
I'm sorry I can't help you with that on short notice, I'm way too busy to do this for you.
I suggest you to find the information on each of the functions you mention on the Microsoft MSDN site:
http://msdn.microsoft.com/en-us/library/aa383749(v=vs.85).aspx
Like I mentioned above:
Anything called a handle, pointer, brush or any other object type will require a LongPtr in 64-bit. Anything that is strictly data can stay as Long.
Comment by: Satyendra (2/4/2011 1:24:48 AM)
Thanks for your quick response. I tried to find those functions in your given MSDN site. But I didn't find any one of them. Can you help me sort this issue or suggest some good material where I can get all these function syntaxes.
Satyendra
Comment by: Jan Karel Pieterse (2/4/2011 3:28:51 AM)
I think you'll find your information here:
http://msdn.microsoft.com/en-us/library/ms741394(VS.85).aspx
Comment by: Satyendra (2/7/2011 10:14:42 AM)
I modified all the declarations, except the select statement. Can you please help to modify it.
Public Declare PtrSafe Function w_select Lib "wsock32.dll" Alias "select" (ByVal nfds As Long, readFds As fd_set, writeFds As fd_set, exceptFds As fd_set, timeout As timeval) As Long
Satyendra
Comment by: Maria (4/4/2011 11:40:45 AM)
I still get compile errors on the 32 bit declares. What am I missing?
I am using Excel 64 bit (14.0.5128.5000 64 bit) and Windows 7 Professional (64 bit).
Comment by: Jan Karel Pieterse (4/4/2011 11:23:49 PM)
Can you post your code and indicate what line gets highlighted when the compile error is shown?
Comment by: Maria (4/7/2011 9:08:45 AM)
---------------------------------------------
#If VBA7 Then
Private Type LASTINPUTINFO
cbSize As LongPtr
dwTime As LongPtr
End Type
Private Declare PtrSafe Sub GetLastInputInfo Lib "USER32" (ByRef plii As LASTINPUTINFO)
#Else
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type
'>>>>>>> The next line is the line that will not compile <<<<<<<<<<<<<
Private Declare Sub GetLastInputInfo Lib "USER32" (ByRef plii As LASTINPUTINFO)
#End If
Comment by: Pablo (4/7/2011 4:36:54 PM)
Comment by: Jan Karel Pieterse (4/8/2011 2:39:40 AM)
Odd, as those line should never be reached in 64 bit Excel and they do not give a compile error on my 32 bit Excel 2010. Do you happen to have any references indicated as missing?
Comment by: Maria (4/8/2011 6:08:08 AM)
The following references are checked:
- Visual Basic For Applications
- Microsoft Excel 14.0 Object Library
- OLE Automation
- Microsoft Office 14.0 Object Library
I quickly scrolled through the entire reference list and did not see anything marked "Missing".
Comment by: Maria (4/9/2011 10:07:17 AM)
32 bit declares. I guess one of the libraries was corrupted. Thank
you for your time.
Comment by: Jan Karel Pieterse (4/9/2011 10:08:39 AM)
Thanks for letting me know, great you could solve your problem.
NB: in the references list, the checked ones are always at the top and those are also the only ones that might be marked "MISSING", so there is no need to scroll down.
Comment by: Ulrik (5/11/2011 10:30:56 PM)
Win32API_PtrSafe.txt contains the following:
32-bit (x86) and 64-bit (x64) compatible Declare statements for the Windows API functions that were included in the original Win32API.txt file.
Global constant declarations for the constants that the provided Declare statements use.
Type declarations for the user-defined types (structures) that the provided Declare statements use.
http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=035b72a5-eef9-4baf-8dbc-63fbd2dd982b&displaylang=en
Comment by: Jan Karel Pieterse (5/12/2011 12:56:41 AM)
Thanks for the link!
NB: what isn't mentioned is that the executable unzips the information to this folder on your hard drive:
C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe
Comment by: Gregory Morse (6/8/2011 2:25:19 AM)
typedef UINT_PTR WPARAM;
#if defined(_WIN64)
typedef unsigned __int64 UINT_PTR;
#else
typedef unsigned int UINT_PTR;
#endif
Comment by: Jan Karel Pieterse (6/8/2011 7:54:53 AM)
Thanks!
Maybe you're right, I'll have to check.
Comment by: Karen (6/29/2011 10:24:36 AM)
Comment by: Jan Karel Pieterse (6/30/2011 12:19:11 AM)
I've included the function, see top of the table on this page.
Comment by: Martin Orlicky (7/20/2011 8:21:45 AM)
Concrete, these two commands don't work:
1. Set mymenu = Application.CommandBars.Add(Name:="Test_Check_Toolbar", Position:=msoBarBottom, Temporary:=True)
2. Function APR_calc(RIV As Double, Payment_Frequency As Integer, term As Integer, grace_period As Integer, first_pmt As Double, weekly_pmt As Double, final_pmt As Double)
May you please help somehow? Thanks, Martin
Comment by: Jan Karel Pieterse (7/22/2011 7:32:49 AM)
Unfortunately, you cannot use 32 bit controls in 64 bit Office and the Office Web controls are strictly 32 bit.
So you will have to revert to a different method entirely.
If you want to be sure an Excel application works on both 32 and 64 bit, use only the built-in Office controls.
I'm a bit surprised the 1st command does not work, but I strongly suspect this is due to the missing reference.
Comment by: Rx_ (9/30/2011 8:35:48 AM)
My client uses Citrix to distribut my MS Access application that uses Windows API declare statements.
The article describes Office 2007 32/64 bit. And most users are probably running from Windows 7. Can you please exapand on a situation for migrating to Windows Server 2008 R2 and the 32 Bit of Office 2010? Is the PrtSafe required for this or could there be other factors?
Moving a working application over to the new server this week, the API functions fail.
New server: Windows Server 2008 R2 Office 2010 32 Bit
The exact same Access code is still working fine on the Windows Server 2003 using Office 2007.
Best Regards
Rx
Tesla 3D, Denver
Comment by: Jan Karel Pieterse (10/2/2011 11:46:11 PM)
As long as your users are on 32 bit Office your API declarations should work unchanged.
Comment by: Rx_ (10/3/2011 8:02:05 AM)
On a Windows 7 (64 bit) with Office 2010, the error message that the DLL must be updated with PrtSafe is required (as we all expected.
Back at the customer site, the same copy was run on a new Windows 7 Enterprise (32 bit) with Office 2010. It still fails. Setting the MS Access 2010 exe running as administrator in Compatibility Mode for XP sp 3 - it still fails.
Another site recommend checking the Err.LastDllError at various points in the code. And, suggested that there are some DLL for Windows 7 that may have to be upgraded.
Rx Tesla 3D, Denver
Comment by: Jan Karel Pieterse (10/4/2011 4:32:45 AM)
The files I tried work on any Office version since Office 97 up to and including 2010.
Are you SURE this isn't a 64 bit version of Excel?
Comment by: Ger (10/12/2011 12:52:57 PM)
My own scenario is: Office 2007 (32 bit), Office 2010 (32 bit) and Office 2010 (64 bit). Code and declarations need to work on all of them.
I cant just use #if VBA7 then use LongLong and LngPtr declarations, because if I do this it will fail to compile on Office 2010 32 bit with a "User Defined Type Not defined" and highlighting the line that contains LongLong
Granted, the compiler statement works fine on Office 2010 64 bit.
The #Else part of the conditional statement catches the compiler for Office 2007 32 bit and there arent any issues there.
But to get declarations to work correct across the three platforms, I believe I need to use the win64 constant, as per the MS 2010 Help file:
' Conditional Compilation Example
#If Vba7 Then
' Code is running in the VBA7 editor.
#If Win64 Then
' Code is running in 64-bit development environment.
#Else
' Code is not running in 64-bit development environment.
#End If
#Else
' Code is not running in the VBA7 editor.
#End If
It makes the declarations awfully long!!!!
Of course, I could be doing something wrong too. :-)
Appreciate the feedback. I can post my current declarations if you wish to see them to cover all 3 platforms (GetActiveWindow, ChooseColorDlg).
Ger
Comment by: Jan Karel Pieterse (10/12/2011 11:48:43 PM)
Thanks for the comments. All declarations shown here should work on those versions, but I guess there may be situations where the win64 compile constant is needed. If you have an example, please post it here and I will include it in the article text!
Comment by: Ger Plante (10/13/2011 2:39:19 AM)
Let me know if you need me to email it to a different address.
Best Regards
Ger
Comment by: Jan Karel Pieterse (10/13/2011 4:29:07 AM)
Email received and replied-to, thanks.
Comment by: Jochen Wezel (10/20/2011 2:40:04 AM)
Option Explicit
Option Compare Database
Public Enum OfficePlatformVersion
Office64 = 2
Office32 = 1
End Enum
Public Function DetectOfficeVbaVersion() As Integer
#If VBA10 Then
DetectOfficeVbaVersion = 10
#ElseIf VBA9 Then
DetectOfficeVbaVersion = 9
#ElseIf VBA8 Then
DetectOfficeVbaVersion = 8
#ElseIf VBA7 Then
DetectOfficeVbaVersion = 7
#ElseIf VBA6 Then
DetectOfficeVbaVersion = 6
#ElseIf VBA5 Then
DetectOfficeVbaVersion = 5
#ElseIf VBA4 Then
DetectOfficeVbaVersion = 4
#ElseIf VBA3 Then
DetectOfficeVbaVersion = 3
#ElseIf VBA2 Then
DetectOfficeVbaVersion = 2
#ElseIf VBA1 Then
DetectOfficeVbaVersion = 1
#Else
DetectOfficeVbaVersion = 0
#End If
End Function
Public Function DetectOfficePlatformVersion() As OfficePlatformVersion
#If Win64 Then
DetectOfficePlatformVersion = OfficePlatformVersion.Office64
#Else
DetectOfficePlatformVersion = OfficePlatformVersion.Office32
#End If
End Function
Comment by: Yvette (10/24/2011 11:20:58 AM)
Please also email the code you created for working with Office 2007 (32 bit), Office 2010 (32 bit) and Office 2010 (64 bit). I have the exact same scenario
Comment by: Rx_ (10/24/2011 11:39:14 AM)
The last DLL error is 87
It It consistantlly works on XP Access 2007 but not on Windows 7 Access 2010.
Comment by: BERNARDO FIAUX (10/25/2011 5:48:55 PM)
Declare Function impliedBS Lib "c:\dll\option.dll" (ByVal flag As Double, ByVal prazo As Double, ByVal spot As Double, ByVal strike As Double, ByVal taxa As Double, ByVal mercado As Double, ByVal dividend As Double) As double
i tried to add the ptrsafe, like this:
Declare PtrSafe Function impliedBS Lib "c:\dll\option.dll" (ByVal flag As Double, ByVal prazo As Double, ByVal spot As Double, ByVal strike As Double, ByVal taxa As Double, ByVal mercado As Double, ByVal dividend As Double) As Long
but the function is still not working, im wondering why...any idea?
tks
Comment by: Jan Karel Pieterse (10/26/2011 2:59:52 AM)
I advised Ger to replace all LongLong's with LongPtr. Have not heard from him whether that was sufficient.
Comment by: Jan Karel Pieterse (10/26/2011 3:01:46 AM)
I'm sorry, but I don't appear to have that dll, so it is not possible for me to answer your question!
NB: if you are on Office 64 bit and the dll is a 32 bit dll, then it will never work.
Comment by: NEX-5 (11/11/2011 6:56:26 PM)
Comment by: @Alex (11/20/2011 10:57:47 AM)
@Alex
Comment by: enzo (11/21/2011 4:16:47 AM)
here a sample already modified for 64 bit but crash al line:
CC.lpCustColors = StrConv(aCustomColors, vbUnicode)
(Version 32 bit works properly)
*** ERROR: Runtime 13 Conversion type error
#If VBA7 Then
Dim lReturn As LongLong
Dim aCustomColors(0 To 16 * 4 - 1) As Long
Dim i As Integer
Dim lpCC As LongPtr
For i = LBound(aCustomColors) To UBound(aCustomColors)
aCustomColors(i) = 0
Next i
lpCC = StrConv(aCustomColors, vbUnicode)
Dim CC As CHOOSECOLOR
CC.lStructSize = CLng(Len(CC))
CC.hWndOwner = Application.hwnd
CC.hInstance = CLng(0)
CC.lpCustColors = StrConv(aCustomColors, vbUnicode)
CC.flags = CLng(0)
lReturn = ChooseColor(CC)
If lReturn <> 0 Then
Me.Caption = "RGB Value User Chose: "& str$(CC.rgbResult)
Me.idColore = CC.rgbResult
Else
MsgBox "No color selected"
End If
#Else
Dim CC As CHOOSECOLOR
Dim lReturn As Long
Dim aCustomColors(0 To 16 * 4 - 1) As Byte
Dim i As Integer
For i = LBound(aCustomColors) To UBound(aCustomColors)
aCustomColors(i) = 0
Next i
CC.lStructSize = Len(CC)
CC.hWndOwner = Me.hwnd
CC.hInstance = 0
CC.lpCustColors = StrConv(aCustomColors, vbUnicode)
CC.flags = 0
lReturn = ChooseColor(CC)
If lReturn <> 0 Then
Me.Caption = "RGB Value User Chose: " & str$(CC.rgbResult)
Me.idColore = CC.rgbResult
Else
MsgBox "No color selected"
End If
#End If
Comment by: Jan Karel Pieterse (11/21/2011 4:56:46 AM)
Why are you declaring aCustomColors as a Long in the VBA7 case? I'd expect both declares should be of type Byte.
Since I see no differences in the VBA7 case or the Else pare, the entire conditional compilation is not needed?
Comment by: ENZO (11/21/2011 8:35:22 AM)
You are right I've changed type to Long for #VA7
The difference is in function and TYPE CHOOSECOLOR declarations (not wrote above)
here are the two different declarations:
if #Vba7 then
Type CHOOSECOLOR
lStructSize As Long
hWndOwner As LongPtr
hInstance As LongPtr
rgbResult As Long
lpCustColors As LongPtr
flags As Long
lCustData As LongPtr
lpfnHook As LongPtr
lpTemplateName As String
End Type
Declare PtrSafe Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR) As Long
#else
Type CHOOSECOLOR
lStructSize As Long
hWndOwner As Long
hInstance As Long
rgbResult As Long
lpCustColors As Long
flags As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Declare Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR) As Long
#end if
Comment by: Jan Karel Pieterse (11/21/2011 10:16:53 AM)
I still think the aCustomeColors array should remain an array of type Byte.
Comment by: enzo (11/21/2011 11:33:06 AM)
CC.lpCustColors = StrConv(aCustomColors, vbUnicode)
Color dialog box don't appears
Comment by: Jan Karel Pieterse (11/21/2011 10:21:44 PM)
Comment by: enzo (12/9/2011 3:49:36 AM)
' 32 BIT VERSION works properly (under 32 bit):
Option Compare Database
Option Explicit
Declare Function ChooseColor Lib "comdlg32.dll" _
Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR_TYPE) _
As Long
Type CHOOSECOLOR_TYPE
lStructSize As Long
hwnd As Long
hInstance As Long
rgbResult As Long
lpCustColors As String
Flags As Long
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
' ===============================================
Sub TestGetColor()
Dim c
c = GetColor()
If c > 0 Then
MsgBox "SELECTED COLOR: " & c
Else
MsgBox "NO COLOR SELECTED"
End If
End Sub
Function GetColor()
Dim CustomColors() As Byte ' dynamic (resizable) array holds the RGB values
Dim cc As CHOOSECOLOR_TYPE ' structure to pass/receive information
Dim getC As Long ' return value of function
Dim rVal As Long ' return value of function
ReDim CustomColors(0 To 16 * 4 - 1) As Byte ' resize the array
Dim i As Integer ' counter variable
For i = LBound(CustomColors) To UBound(CustomColors)
CustomColors(i) = 0 ' set all custom color choices to black (RGB = 0,0,0)
Next i
cc.hwnd = Application.hWndAccessApp
cc.lpCustColors = StrConv(CustomColors, vbUnicode) ' convert custom color array
cc.Flags = &H80
cc.lStructSize = Len(cc) ' the size of the structure
getC = ChooseColor(cc) ' open the dialog box
If getC <> 0 Then ' if the user successfully chose a color
CustomColors = StrConv(cc.lpCustColors, vbFromUnicode) ' save custom colors
rVal = cc.rgbResult
Else
rVal = -1
End If
GetColor = rVal
End Function
Comment by: Jan Karel Pieterse (12/9/2011 5:18:43 AM)
Thanks.
Comment by: Ali (2/27/2012 5:57:23 AM)
thanks for the solution but could you please take me through it step by step as I am an amateur in VB. My whole office is struggling with the 32bit-64bit compatibility issue.
Regards,
Ali
Comment by: Jan Karel Pieterse (3/5/2012 5:14:12 AM)
If your whole Office needs help with this, perhaps it is a better idea if you get in touch so we can arrange to start a project on this? (see my email address at the bottom of the screen)
Comment by: Macarius (3/22/2012 11:29:37 PM)
Running Windows 7 x64, Office 2007 (32-bit, I believe).
CopyMemory API crashes Excel. Need this ASAP for work. Would most appreciate your thoughts/solutions.
Respectfully,
Macarius
Comment by: Jan Karel Pieterse (3/23/2012 3:58:42 AM)
Look at this page:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366535(v=vs.85).aspx
It tells us the first two arguments are pointers, so they need to be changes to LongPtr for 64 bit.
Comment by: Theo Vroom (5/5/2012 9:19:35 AM)
I am developping in 32 bit Office 2003 and a number of users run 32 bit office. We now have the first Windows 7 64 bit users and I installed Office 2010 64 bit.
How can I (maybe with a conditional compiler constant, but at least office 2003 does not have eg vba7 or 64bit) continue to develop in 32 bit office, also for use in 64 bit office.
I cannot upgrade to 64 bit myself now.
The easy solution, I believe, would be to install 32 bit office on w7 64 bit, but I like the challenge
Comment by: Jan Karel Pieterse (5/6/2012 11:11:43 AM)
I expect all code that works on 32 bit Office 2010 also to work on 64 bit, except for API declarations. Also, 32 bit ActiveX controls that are not part of Office will not work.
I'd install 32 bit Office and have a virtual machine with 64 bit Office for testing purposes.
Comment by: Natalie (5/31/2012 7:49:56 PM)
Do
PreviousValue=[a1]
CurrentValue = ComPortInput
PreviousValue = CurrentValue
[a1]=PreviousValue
Loop
If you can, please respond with email, thank you.
Comment by: Jan Karel Pieterse (6/1/2012 10:41:51 AM)
Can you try to explain what you are trying to achieve? Where would that value you want to store come from?
Perhaps this page gives you some ideas:
http://www.jkp-ads.com/Articles/DistributeMacro08.asp
Comment by: Natalie (6/1/2012 2:29:21 PM)
Do
PreviousData=[a1]
CurrentData=ComPortInput
DeltaData=CurrentData-PreviousData
PreviousData=CurrentData
[a1]=PreviousData
Loop
I would like to be able to store the PreviousData without having to go to the worksheet cell A1 (or any cell). The data coming in (CurrentData) is from the serial RS232 CommPort. I would like to be able to do this, store the data, perhaps 3,4 times back, i.e.: PreviousData4 without having to store and retrieve from the worksheet. Again, thanks.
Comment by: Jan Karel Pieterse (6/1/2012 2:50:14 PM)
I think I understand now.
Declare your variable at the top of the module:
Dim PreviousValue As Variant 'Or another appropiate type
'All Subs and functions follow below
Comment by: Natalie (6/1/2012 3:10:40 PM)
Comment by: Jan Karel Pieterse (6/1/2012 7:15:14 PM)
Comment by: Natalie (6/2/2012 5:37:35 PM)
Dim Eacc As Integer
Sub RunIt()
DoEvents
RunNow = Now + TimeSerial(0, 0, 1)
Application.OnTime RunNow, "RunIt", , True
HDG = [a1]
Eacc = Eacc + HDG
[b1] = Eacc
DoEvents
End Sub
Comment by: David McIntosh (6/4/2012 4:33:21 PM)
Comment by: Jan Karel Pieterse (6/4/2012 6:15:37 PM)
Well spotted, thank you!
Page updated.
Comment by: David I. McIntosh (6/4/2012 7:32:37 PM)
Comment by: David I. McIntosh (6/4/2012 7:35:34 PM)
http://www.microsoft.com/en-us/download/details.aspx?id=9970
Comment by: David I. McIntosh (6/4/2012 8:54:56 PM)
Thus, the declaration for SendMessage in 64bit should be
Public Declare PtrSafe Function SendMessageA Lib "user32"(ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
and note that is is in fact what is in the Microsoft doc. (SendMessage was, unfortunately, the worst function to pick as an example!!!)
Comment by: Jan Karel Pieterse (6/5/2012 8:44:26 AM)
Thanks for looking through the article and spotting the errors (it is easy to miss an item to convert from Long to LongPtr -or not-), much appreciated!
Comment by: Yves BENOIT (6/14/2012 1:54:53 AM)
is there a way to play sounds in 64 bits VBA, now that the 32 bits calls to Playsound and others are obsolete?
Thank you
Yves
Comment by: Jan Karel Pieterse (6/14/2012 8:19:07 AM)
Does it work if you declare the function like this:
Lib "winmm.dll" _
Alias "sndPlaySoundA" ( _
ByVal lpszSoundName As String, _
ByVal uFlags As Long) As Long
Comment by: Banana (6/28/2012 12:14:22 AM)
http://www.utteraccess.com/wiki/index.php/Category:API
Comment by: Jan Karel Pieterse (6/28/2012 11:08:22 AM)
Thanks!
Comment by: Peter van Loosbroek (6/28/2012 2:40:42 PM)
I used the GetOpenFileName methode in 32 bit verions of MS Office. Working well. Now I converted to 64 bit and use it in MS Office 64 bit, but the dialog box won't open. I don't know what I am doing wrong. I've rearched the web but can't solve the problem. Please can you help me? I would be very greatfull!
Thanks, Peter (Netherlands)
Public Declare PtrSafe Function GetOpenFileName Lib "comdlg32.dll" Alias _
"GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
Public Type OPENFILENAME
lStructSize As Long
hwndOwner As LongPtr '
hInstance As LongPtr '
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As LongPtr '
lpTemplateName As String
End Type
Public Function TestGetFile(strTitle As String) As String
Dim OpenFile As OPENFILENAME
Dim lReturn As LongPtr
Dim sFilter As String
OpenFile.lStructSize = Len(OpenFile)
OpenFile.hwndOwner = 0
OpenFile.lpstrFile = String(257, 0)
OpenFile.nMaxFile = Len(OpenFile.lpstrFile) - 1
OpenFile.lpstrFileTitle = OpenFile.lpstrFile
OpenFile.nMaxFileTitle = OpenFile.nMaxFile
OpenFile.lpstrInitialDir = "C:\"
OpenFile.lpstrTitle = strTitle
OpenFile.flags = 0
lReturn = GetOpenFileName(OpenFile)
If lReturn = 0 Then
TestGetFile = ""
Else
TestGetFile = Trim(Left(OpenFile.lpstrFile, InStr(1, OpenFile.lpstrFile, vbNullChar) - 1))
End If
End Function
Comment by: Jan Karel Pieterse (6/29/2012 11:39:35 AM)
Just curious: why are you using the API function to start with, there's an Application.GetOpenFileName available too?
Comment by: Peter van Loosbroek (6/29/2012 12:02:47 PM)
The code I used in a standard module in MS Access. In a 32 bit version it works well (of course without using PtrSafe and LongPtr). The function TestGetFile returns the filename. You can test is in the debug window.
I also learned that the VB function Len (in TestGetFile) should be LenB in a 64 bit version.
I hope you can help me (and more people because everyon can use this function).
Regards, Peter, The Netherlands
Comment by: Jan Karel Pieterse (6/29/2012 2:47:51 PM)
Odd that it does not work. I have no idea why though. Perhaps looking through the MSDN documentation fo the function gives you pointers?
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646927(v=vs.85).aspx
Comment by: Jon Peltier (7/3/2012 6:28:57 PM)
#If VBA7 And Win64 Then
Comment by: Jan Karel Pieterse (7/3/2012 9:47:56 PM)
True, but as far as I know, in almost all cases the VBA7 test suffices, unless there are specific reasons to test for bitness.
Comment by: technolust (7/11/2012 9:35:30 PM)
Comment by: Sisyphus (8/21/2012 8:21:11 PM)
http://www.microsoft.com/en-us/download/details.aspx?id=9970
The site acts like it were supply an executable file. However, if you acceded to all requests, all you get are 3 very useful documents.
Comment by: MK (9/21/2012 11:11:50 AM)
Comment by: Dharmendra (10/8/2012 6:54:16 PM)
We have Excel spredsheet with VBA code to get data from user to our system using CyberLynx approach. Here are lines that declare the said object..
Dim cyberlynxobj
Set cyberlynxobj = New CyberLynx
It is working just fine on Windows 32 or Window 64 with Office 32 bit version but we have new team using Window 64 and Office 64bit getting following error in the above line as:
"License information for this omponent not found. You do not have an appropriate license to use this functionality in the design environment"
Any suggestion/help? Thanks in advance.
Comment by: Jan Karel Pieterse (10/9/2012 10:24:50 AM)
This means that the Cyberlynx system you refer to is not a 64 bit system and cannot be called from 64 bit Excel.
You must contact the vendor and ask if they have a 64 bit COM enabled version of the system that can be called from Excel VBA.
Comment by: Gyula (11/5/2012 3:08:52 AM)
or do I need to use something like:
Thanks a lot!
Comment by: Jan Karel PIeterse (11/5/2012 8:44:32 AM)
I suggest you just try!
VBA seems to allow it, but I don't know if it'll work in the code at runtime?
Comment by: Peter Sierek (12/4/2012 5:15:03 AM)
maybe I will not get an answer from you. I want to query in Excel VBA, which has bit version of the computer. How does this line are for 64-bit?
Declare Function InternetGetConnectedState Lib "wininet.dll" (ByRef K As Long, ByVal Rola As Long) As Long
In the hope of getting an answer, I remain, with
friendly greetings
Peter Sierek
Comment by: Jan Karel Pieterse (12/4/2012 8:51:01 AM)
The bitness of windows can be detected like so (taken from http://www.freevbcode.com/ShowCode.asp?ID=9043 and adjusted to cater for 64 bit Office):
Part 1, declarations:
#If VBA7 Then
Private Declare Function GetProcAddress Lib "kernel32" _
(ByVal hModule As LongPtr, _
ByVal lpProcName As String) As LongPtr
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleA" _
(ByVal lpModuleName As String) As LongPtr
Private Declare Function GetCurrentProcess Lib "kernel32" _
() As LongPtr
Private Declare Function IsWow64Process Lib "kernel32" _
(ByVal hProc As LongPtr, _
bWow64Process As Boolean) As Long
#Else
Private Declare Function GetProcAddress Lib "kernel32" _
(ByVal hModule As Long, _
ByVal lpProcName As String) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
Alias "GetModuleHandleA" _
(ByVal lpModuleName As String) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" _
() As Long
Private Declare Function IsWow64Process Lib "kernel32" _
(ByVal hProc As Long, _
bWow64Process As Boolean) As Long
#End If
Comment by: Jan Karel Pieterse (12/4/2012 8:51:29 AM)
Part 2, Function:
Dim handle As Long, bolFunc As Boolean
' Assume initially that this is not a Wow64 process
bolFunc = False
' Now check to see if IsWow64Process function exists
handle = GetProcAddress(GetModuleHandle("kernel32"), _
"IsWow64Process")
If handle > 0 Then ' IsWow64Process function exists
' Now use the function to determine if
' we are running under Wow64
IsWow64Process GetCurrentProcess(), bolFunc
End If
Is64bit = bolFunc
End Function
Comment by: dave (12/29/2012 6:58:35 AM)
below is the link to the webpage extension i want to use that requires my excel file to request the appropriate license key through an API from each end user's computer to prevent unauthorized distribution of the file. how do i do this and how do i connect to this api??????
http://wcdocs.woothemes.com/user-guide/extensions/software-add-on/
thanks for your help!
PS. please keep in mind that my file has no macros and what i am trying to protect is the formulas i have built and the data interface i have designed to collect and analyze the data each user would be generating. i built a 40mb file with nothing but formulas and tables, etc....
Comment by: Jan Karel Pieterse (12/29/2012 4:51:33 PM)
"Connecting" to this API will require VBA programming.
Unfortunately, the content of Excel workbooks is poorly protected. Anyone can get quick access to your model by running just one simple macro that removes all passwords.
The only way might be to create an on-line version of your model, but that likely requires:
1. An Office 365 subscription (not sure if that suffices)
2. A (possibly drastic) redesign of your model to make it work on-line using the Excel web app.
Comment by: Patrick Headley (1/31/2013 7:39:40 PM)
Comment by: Jan Karel Pieterse (2/1/2013 3:08:15 PM)
What code does your Excel fail on?
Comment by: fabrice CONSTANS (2/4/2013 4:42:04 PM)
I have a heterogeneous Park: windows xp, vista, 7 and 8 in 32 or 64 bit Excel 2003 to 2010 in 32 or 64 bit.
What should i use as a compile-time directive? Win64 and vba7, both?
Should I deliver for 2003 to 2007 and 2010 32/64 versions?
My code is :
#If Win64 Then
Private Type structHH_FTS_QUERY
cbStruct As Long
fUniCodeStrings As Long
pszSearchQuery As String
iProximity As Long
fStemmedSearch As Long
fTitleOnly As Long
fExecute As Long
pszWindow As String
End Type
Private Declare PtrSafe Function HtmlHelp Lib "hhctrl.ocx" Alias "HtmlHelpA" _
(ByVal hwndCaller As LongPtr, _
ByVal pszFile As String, _
ByVal uCommand As HH_COMMAND, _
dwData As Any) As LongPtr
#Else
Private Type structHH_FTS_QUERY
cbStruct As Long
fUniCodeStrings As Long
pszSearchQuery As String
iProximity As Long
fStemmedSearch As Long
fTitleOnly As Long
fExecute As Long
pszWindow As String
End Type
Private Declare Function HtmlHelp Lib "hhctrl.ocx" Alias "HtmlHelpA" _
(ByVal hwndCaller As Long, _
ByVal pszFile As String, _
ByVal uCommand As HH_COMMAND, _
dwData As Any) As Long
#End If
Public Sub Show(NewFile As String, Optional WindowPane As String, Optional ContextID)
Dim Fichier As String
Fichier = NewFile
...
#If Win64 Then
Call HtmlHelp(0, Fichier, HH_HELP_CONTEXT, ByVal CLng(ContextID))
#Else
Call HtmlHelp(0, Fichier, HH_HELP_CONTEXT, ByVal CLngLng(ContextID))
#End If
End If
End Sub
Thank you.
Fabrice CONSTANS MVP
Comment by: Jan Karel Pieterse (2/5/2013 5:37:43 PM)
As far as I know, VBA7 suffices UNLESS there is a specific API which behaves different on a Win64 machine then on a Win32 machine (e.g. is in a different dll or has a difference in arguments). The ones listed here seem to work just fine with just VBA7.
Comment by: Mireille DOUGUET (3/11/2013 12:13:09 PM)
I am from France, and your article was very usefull for me.
But I did'nt success in declaring the function GetPrivateProfileString in my vba code (access 2010 module under Windows Server 2008)...
I couldn't declare the return value to LongPtr because it made a program crash.
When declaring it to Long, with the key PtrSafe, then I could have the return value (the number of characters read)
But I could'nt retrieve the string read...
Here is my code (not crashing, but not working...) :
Thank you for your feedback.
Best regards
M. DOUGUET
'Read
Private Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As String, _
ByVal lpDefault As String, _
ByVal lpReturnedString As String, _
ByVal nSize As Long, _
ByVal lpFileName As String) As Long
Function Startup()
...
Dim iResult As LongPtr
iResult = GetPrivateProfileString("ETAT", "NOM_ETAT", "", sParamNomEtat, 255, "D:\BTIA_CONF\LanceAccess.INI")
....
Comment by: Jan Karel Pieterse (3/11/2013 3:32:52 PM)
The reason is that the GetPrivateProfileString function returns a Long, not a LongPtr.
So your Dim statement must indeed declare as Long:
Comment by: Zac (3/12/2013 4:03:28 PM)
I had used the PtrSafe expression below yesterday with great results, but today it no longer works... I am trying to get an calculation box to work. It is labeled as Text227. Yesterday when I used the PtrSafe expression I placed it on the very top line, for example Option PtrSafe Compare Database.
Any ideas?
Thank you for your help!
Option Compare Database
Option Explicit
' Copyright Lebans Holdings 1999 Ltd.
' Color only the Active/Current TAB and
' not the background of the Tab control
' Var of type Tab class
Private TB As clsTabsCurrentPage
' Temp var for the Class
Dim blRet As Boolean
Dim lngRet As Long
Private Sub Form_Load()
DoCmd.MoveSize 0, 0, 6650, 5200
' Create an instance of our FormatByCriteria class
Set TB = New clsTabsCurrentPage
' You MUST set the CriteriaControl prop
' Set the first TAB Page as the current page
Me.TabCtl.Value = 0
TB.TabControl = Me.TabCtl
' You MUST set the BackGround control
' used to display the current pages background color
TB.BGControl = Me.RecBG
' Parent Form
TB.TabForm = Me
' Set the desired Rotation amount
' For this class it should remain at Zero as
' the class only renders the Text when it is colored.
TB.RotateDegree = 0
' Create the Tabs
' For this sample we only want the Current TAB itself colored
' not the background of the TAB control.
TB.ColorTabsOnly = True
TB.MakeTabsCurrentPage Me.TabCtl.Value
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set TB = Nothing
End Sub
Private Sub Text227_BeforeUpdate(Cancel As Integer)
End Sub
Comment by: Jan Karel Pieterse (3/12/2013 4:27:47 PM)
I see no API declarations in the code you posted?
Comment by: Mireille DOUGUET (3/13/2013 11:27:19 AM)
But the problem is that I can retrieve the number of bytes, ok, but I can't retrieve the string that the GetPrivateProfileString must return to me...
Perhaps the definition of the lpReturnedString parameter, or the way it is passed to the function...
Best regards
M. DOUGUET
Comment by: Jan Karel Pieterse (3/13/2013 4:32:29 PM)
According to the microsoft documentation, this is the correct 64 bit declaration:
Comment by: ChanthornLaiy (4/1/2013 6:06:13 PM)
Comment by: Neil Rogers (4/18/2013 2:45:15 AM)
Comment by: Jan Karel Pieterse (4/18/2013 1:27:51 PM)
You're right of course.
I started building this list and adding Functions as I happen to have the need form them in tools that require porting to 64 bit Office.
As it happens I have not encountered the need to add Sub declarations yet.
As soon as I encounter one (or if you send me some) I'll add them.
Comment by: mic (5/10/2013 4:51:54 PM)
Comment by: Jan Karel Pieterse (5/10/2013 5:17:41 PM)
Basically, as long as you use the method shown here, you should be fine for older Office versions.
Of course you will have to test your code on all Office versions that it will be used.
Comment by: wwwilli (5/15/2013 12:10:26 PM)
Comment by: Jan Karel Pieterse (5/15/2013 12:44:34 PM)
That is a very concise question :-). Care to elaborate a bit?
Comment by: wwwilli (5/15/2013 1:05:59 PM)
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long _
, ByVal lParam As Long) As Long
?
Comment by: Jan Karel Pieterse (5/15/2013 1:55:54 PM)
The correct 64 bit declaration is:
Comment by: wwwilli (5/17/2013 9:17:04 PM)
And bedankt for the whole list.
Comment by: Swap (5/24/2013 2:35:56 PM)
I have written code in vba to open regisry and get handel of some application, it is working fine on XP, office2003 but on windows7(64 bit), office 2010(32bit not sure) code is not working for, RegOpenKeyEx command. Here is the code.
Please help.
Public Declare Function RegCloseKey Lib "ADVAPI32" (ByVal hKey&) As Long
Public Declare Function RegOpenKeyEx Lib "ADVAPI32" Alias "RegOpenKeyExA" (ByVal hKey&, ByVal lpSubKey$, ByVal ulOptions&, ByVal samDesired&, phkResult&) As Long
Public Declare Function RegQueryValueEx Lib "ADVAPI32" Alias "RegQueryValueExA" (ByVal hKey&, ByVal lpValueName$, ByVal lpReserved&, ByVal lpType&, ByVal lpData$, lpcbData&) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Const HKEY_CLASSES_ROOT As Long = &H80000000
Public Const HKEY_CURRENT_USER As Long = &H80000001
Public Const HKEY_LOCAL_MACHINE As Long = &H80000002
Public Const HKEY_USERS As Long = &H80000003
Public Const ERROR_SUCCESS As Long = &H0
Global Const SYNCHRONIZE As Long = &H100000
Global Const INFINITE As Long = &HFFFFFFFF
'define
Public Const MAX_PATH As Long = 260
Public Const FILE_TYPE_XLS As Long = 0
Public Const FILE_TYPE_CSV As Long = 1
Sub check()
Ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\XYZ_App", 0, 1, hKey)
Ret = RegQueryValueEx(hKey, "InstallPath", 0, 0, RegValue, MAX_PATH)
End sub
Comment by: Jan Karel Pieterse (5/24/2013 2:51:57 PM)
Can you perhaps give a more complete example with variable content in place that does work on XP/2003 and returns a proper value? Otherwise this is a bit hard to test.
Comment by: Anon (6/12/2013 5:00:47 AM)
Private Declare Function SendDlgItemMessage _
Lib "user32" Alias "SendDlgItemMessageA" ( _
ByVal hDlg As Long, _
ByVal nIDDlgItem As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) _
As Long
Comment by: Jan Karel Pieterse (6/12/2013 8:05:38 AM)
From the download link shown at the top of this article:
http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=035b72a5-eef9-4baf-8dbc-63fbd2dd982b&displaylang=en
Comment by: Anon (6/13/2013 5:09:23 AM)
I tried the MS download but I get a "no result" when searching for this function in VBA help after installing?
I am now looking for URLDownloadToFile. I can not find that by searching the help either.
Comment by: Jan Karel Pieterse (6/13/2013 8:47:56 AM)
It is not obvious, but the API declarations are in the txt file.
Comment by: Emiel Nijhuis (6/20/2013 9:31:15 PM)
When looking for 64 bit API calls to manipulate the clipboard I came across this sample:
https://korpling.german.hu-berlin.de/p/projects/excelfalkoplugin/repository/revisions/321/entry/Components/mdlApi.bas
I tested the sample and it functions without error.
It is a 'translation' of the following MSDN example:
http://msdn.microsoft.com/en-us/library/office/ff192913.aspx
Might be useful for your list,
Regards,
Emiel Nijhuis
Comment by: Jan Karel Pieterse (6/21/2013 12:01:24 PM)
Thanks!
Comment by: Mathys Walma (7/23/2013 1:04:30 AM)
Declare PtrSafe Function SetupComm Lib "kernel32" Alias "SetupComm" (ByVal hFile As Long, ByVal dwInQueue As Long, ByVal dwOutQueue As Long) As Long
hFile is LongPtr in a lot of other functions.
Comment by: George Marcovits (8/3/2013 9:20:22 AM)
ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long
Public TimerID As Long
Public TimerSeconds As Single
Sub StartTimer30T()
Windows("Test.xls").Activate
Sheets("First").Select
Application.Run "Test.xls!AtTheStart"
TimerSeconds = 30
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
Sub EndTimer30T()
On Error Resume Next
Sheets("First").Select
Range("A1").Select
KillTimer 0&, TimerID
End Sub
I am planning to use them on a computer with Windows 7 and Office 2013 all 64 bit. Will the above codes work and if not any directions on what to change will be highly appreciated.
Thank you very much in advance,
George
Comment by: George Marcovits (8/3/2013 9:24:22 AM)
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Const GWL_STYLE = (-16)
Private Const WS_CAPTION = &HC00000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_SYSMENU = &H80000
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Enum ESetWindowPosStyles
SWP_SHOWWINDOW = &H40
SWP_HIDEWINDOW = &H80
SWP_FRAMECHANGED = &H20
SWP_NOACTIVATE = &H10
SWP_NOCOPYBITS = &H100
SWP_NOMOVE = &H2
SWP_NOOWNERZORDER = &H200
SWP_NOREDRAW = &H8
SWP_NOREPOSITION = SWP_NOOWNERZORDER
SWP_NOSIZE = &H1
SWP_NOZORDER = &H4
SWP_DRAWFRAME = SWP_FRAMECHANGED
HWND_NOTOPMOST = -2
End Enum
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Comment by: George Marcovits (8/3/2013 9:24:53 AM)
Dim lStyle As Long
Dim tRect As RECT
Dim sWndTitle As String
Dim xlhnd
sWndTitle = "Microsoft Excel - " & ActiveWindow.Caption
xlhnd = FindWindow(vbNullString, sWndTitle)
GetWindowRect xlhnd, tRect
If Not bShow Then
lStyle = GetWindowLong(xlhnd, GWL_STYLE)
lStyle = lStyle And Not WS_SYSMENU
lStyle = lStyle And Not WS_MAXIMIZEBOX
lStyle = lStyle And Not WS_MINIMIZEBOX
lStyle = lStyle And Not WS_CAPTION
Else
lStyle = GetWindowLong(xlhnd, GWL_STYLE)
lStyle = lStyle Or WS_SYSMENU
lStyle = lStyle Or WS_MAXIMIZEBOX
lStyle = lStyle Or WS_MINIMIZEBOX
lStyle = lStyle Or WS_CAPTION
End If
SetWindowLong xlhnd, GWL_STYLE, lStyle
SetWindowPos xlhnd, 0, tRect.Left, tRect.Top, tRect.Right - tRect.Left, tRect.Bottom - tRect.Top, SWP_NOREPOSITION Or SWP_NOZORDER Or SWP_FRAMECHANGED
End Sub