Excel 2013 64-bit VBA: Clipboard API doesn't work
OK, I got it now...
You need to change this line in your version of the code:
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As String, ByVal lpString2 As String) As LongPtr
To this:
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr
If you step through the code as you had it, you will see that the value of lpGlobalMemory changes when lstrcopy is called. When the types are changed to Any, the value stays the same.
Works for me on windows 7. Hope it works for you!
Posting complete code for others. Tested and working on 32 Bit Versions of Excel 2007, 2010, 2013, 2016and 64 Bit Excel 2013All running on Windows 10
'http://stackoverflow.com/questions/14738330/office-2013-excel-putinclipboard-is-differentOption Explicit#If VBA7 Then Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr Declare PtrSafe Function CloseClipboard Lib "User32" () As Long Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As LongPtr) As LongPtr Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr#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 IfPublic Const GHND = &H42Public Const CF_TEXT = 1Public Const MAXSIZE = 4096Function ClipBoard_SetData(MyString As String) #If VBA7 Then Dim hGlobalMemory As LongPtr, lpGlobalMemory As LongPtr, hClipMemory As LongPtr #Else Dim hGlobalMemory As Long, lpGlobalMemory As Long, hClipMemory As Long #End If Dim x As Long ' Allocate moveable global memory. '------------------------------------------- hGlobalMemory = GlobalAlloc(GHND, Len(MyString) + 1) ' Lock the block to get a far pointer ' to this memory. lpGlobalMemory = GlobalLock(hGlobalMemory) ' Copy the string to this global memory. lpGlobalMemory = lstrcpy(lpGlobalMemory, MyString) ' Unlock the memory. If GlobalUnlock(hGlobalMemory) <> 0 Then MsgBox "Could not unlock memory location. Copy aborted. Please contact 14Fathoms." GoTo OutOfHere2 End If ' Open the Clipboard to copy data to. If OpenClipboard(0&) = 0 Then MsgBox "Could not open the Clipboard. Copy aborted. Please contact 14Fathoms." Exit Function End If ' Clear the Clipboard. x = EmptyClipboard() ' Copy the data to the Clipboard. hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory)OutOfHere2: If CloseClipboard() = 0 Then MsgBox "Could not close Clipboard. Please contact 14Fathoms." End IfEnd FunctionSub TestCOPYPASTE() Call ClipBoard_SetData("Hello World " & now()) 'Open notepad or in the immediate window and hit control-vEnd Sub
Use the code exactly as shown here:
http://msdn.microsoft.com/en-us/library/office/ff192913.aspx
except insert PtrSafe after Declare for all the API declarations.
The code should be in a module by itself.
Like this:
Option ExplicitDeclare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) _ As LongDeclare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) _ As LongDeclare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _ ByVal dwBytes As Long) As LongDeclare PtrSafe Function CloseClipboard Lib "User32" () As LongDeclare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) _ As LongDeclare PtrSafe Function EmptyClipboard Lib "User32" () As LongDeclare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _ ByVal lpString2 As Any) As LongDeclare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat _ As Long, ByVal hMem As Long) As LongPublic Const GHND = &H42Public Const CF_TEXT = 1Public Const MAXSIZE = 4096Function ClipBoard_SetData(MyString As String) Dim hGlobalMemory As Long, lpGlobalMemory As Long Dim hClipMemory As Long, X As Long ' Allocate moveable global memory. '------------------------------------------- hGlobalMemory = GlobalAlloc(GHND, Len(MyString) + 1) ' Lock the block to get a far pointer ' to this memory. lpGlobalMemory = GlobalLock(hGlobalMemory) ' Copy the string to this global memory. lpGlobalMemory = lstrcpy(lpGlobalMemory, MyString) ' Unlock the memory. If GlobalUnlock(hGlobalMemory) <> 0 Then MsgBox "Could not unlock memory location. Copy aborted." GoTo OutOfHere2 End If ' Open the Clipboard to copy data to. If OpenClipboard(0&) = 0 Then MsgBox "Could not open the Clipboard. Copy aborted." Exit Function End If ' Clear the Clipboard. X = EmptyClipboard() ' Copy the data to the Clipboard. hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory)OutOfHere2: If CloseClipboard() = 0 Then MsgBox "Could not close Clipboard." End If End Function