2013-09-07 17 views
12

Ero abituato a utilizzare le chiamate API di Windows in VBA di Excel per impostare il testo negli Appunti. Ma da quando ho aggiornato l'Office 2013 a 64 bit, non posso. Di seguito è riportato un codice che non presenta errori, ma non imposta alcun testo negli Appunti. Qualcuno può aiutarmi a testare e risolvere i problemi?Excel 2013 VBA a 64 bit: l'API degli Appunti non funziona

Dopo aver incollato il codice sottostante in un modulo di codice in VBA, è possibile verificarlo nelle finestre immediate digitando Clipboard_SetData("Copy this to the clipboard.") e si dovrebbe impostare quel testo negli Appunti e si sarà in grado di incollarlo in qualsiasi altra applicazione.

(sto usando Windows 8, quindi non posso utilizzare Forms Microsoft o l'oggetto dati per manipolare la clipboard Non funziona correttamente su Windows 8..)

UPDATE e EDIT: codice qui sotto è stato corretto e ora funziona correttamente in Excel 64 bit, grazie alla risposta di Jason Kurtz qui sotto. Se lo trovi utile, vota la sua risposta.

Option Explicit 

'Found 64-bit API declarations here: http://spreadsheet1.com/uploads/3/0/6/6/3066620/win32api_ptrsafe.txt 
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr 
Private Declare PtrSafe Function GlobalFree Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr 
Private Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr 
Private Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr 
Private Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As Long 
Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long 
Private Declare PtrSafe Function CloseClipboard Lib "user32"() As Long 
Private Declare PtrSafe Function EmptyClipboard Lib "user32"() As Long 
Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr 
Private Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As LongPtr 
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr 

Private Const GMEM_MOVEABLE = &H2 
Private Const GMEM_ZEROINIT = &H40 
Private Const GHND = (GMEM_MOVEABLE Or GMEM_ZEROINIT) 

Public Const CF_TEXT = 1 
Public Const MAXSIZE = 4096 

Sub ClipBoard_SetData(MyString As String) 
'32-bit code by Microsoft: http://msdn.microsoft.com/en-us/library/office/ff192913.aspx 
    Dim hGlobalMemory As LongPtr, lpGlobalMemory As LongPtr 
    Dim hClipMemory As LongPtr, 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." 
     'Debug.Print "GlobalFree returned: " & CStr(GlobalFree(hGlobalMemory)) 
     GoTo OutOfHere 
    End If 

    ' Open the Clipboard to copy data to. 
    If OpenClipboard(0&) = 0 Then 
     MsgBox "Could not open the Clipboard. Copy aborted." 
     Exit Sub 
    End If 

    ' Clear the Clipboard. 
    X = EmptyClipboard() 

    ' Copy the data to the Clipboard. 
    hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory) 

OutOfHere: 
    If CloseClipboard() = 0 Then 
     MsgBox "Could not close Clipboard." 
    End If 
End Sub 
+2

fa il 'SetClipboardData()' chiamata avere successo? In caso contrario, cosa significa "GetLastError()"? –

+0

Ho appena provato. Clipboard_SetData ("fjdkla; jfd") \ output Debug: \ hGlobalMemory è 287.253.201.176 \ lpGlobalMemory è 287.450.358.016 \ lpGlobalMemory è 287.362.598.488 \ hClipMemory è 287.253.201.176 \ LastDLLError è 0 \ Mi chiedo perché lstrcopy restituisce un indirizzo diverso da quello GlobalLock. Ho studiato la [pagina API di lstrcopy] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms647490 (v = vs.85) .aspx) e Microsoft ci avverte di non usarlo. Mi chiedo se è disabilitato da qualche tipo di funzionalità di sicurezza di Windows 8. Qualcuno sa come usare [StringCchCopy] (http://bit.ly/15N1jBR) in VBA? – Baodad

+1

Il file menzionato 'win32api_ptrsafe.txt 'può ora essere scaricato da' File della Guida di Office 2010: Win32API_PtrSafe con supporto a 64 bit '(http://www.microsoft.com/en-us/download/details.aspx?id=9970) –

risposta

9

OK, ho capito ora ...

è necessario modificare questa riga nella vostra versione del codice:

Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As String, ByVal lpString2 As String) As LongPtr 

a questo:

Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr 

Se si passa attraverso il come hai fatto, vedrai che il valore di lpGlobalMemory cambia quando viene chiamato lstrcopy. Quando i tipi vengono modificati su Qualsiasi, il valore rimane lo stesso.

Lavora per me su Windows 7. Spero che funzioni per te!

+0

Grazie, ha funzionato: e noto che stai usando un puntatore come tipo di ritorno, non un numero intero lungo: c'è il codice su altri siti che utilizzano Long o LongLong, che funzionerà bene finché non lo farà. –

0

Utilizzare il codice esattamente come mostrato qui:

http://msdn.microsoft.com/en-us/library/office/ff192913.aspx

tranne inserto PtrSafe dopo Dichiarare per tutte le dichiarazioni API.

Il codice deve essere in un modulo da solo.

Ti piace questa:

Option Explicit 

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 

Public Const GHND = &H42 
Public Const CF_TEXT = 1 
Public Const MAXSIZE = 4096 

Function 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 
+0

Questo codice non funziona in Excel 2013 a 64 bit. Le dichiarazioni API kernel32 non sono LongPtr. Errori in GlobalUnlock. Il mio codice nel corpo principale della domanda non ha errori e le API sono dichiarate per 64-bit. Ma grazie per aver provato. – Baodad

6

Pubblicazione di codice completo per gli altri. Testato e lavorando su versioni a 32 bit di Excel 2007, 2010, 2013, 2016 e 64 bit di Excel 2013 tutto in esecuzione su Windows 10

'http://stackoverflow.com/questions/14738330/office-2013-excel-putinclipboard-is-different 
Option 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 If 

Public Const GHND = &H42 
Public Const CF_TEXT = 1 
Public Const MAXSIZE = 4096 

Function 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 If 

End Function 
Sub TestCOPYPASTE() 
    Call ClipBoard_SetData("Hello World " & now()) 
    'Open notepad or in the immediate window and hit control-v 
End Sub 
Problemi correlati