Excel 2013 64비트 VBA: 클립보드 API가 작동하지 않음
이전에는 Excel VBA에서 Windows API 호출을 사용하여 클립보드에 텍스트를 설정할 수 있었습니다.하지만 64비트 Office 2013으로 업그레이드한 이후로는 그럴 수 없습니다.아래는 오류가 발생하지 않는 일부 코드이지만 클립보드에 텍스트를 설정하지 않고 있습니다.누가 테스트하고 문제 해결하는 것을 도와줄 수 있습니까?
아래 코드를 VBA의 코드 모듈에 붙여넣은 후, 다음을 입력하여 바로 창에서 테스트할 수 있습니다.Clipboard_SetData("Copy this to the clipboard.")
클립보드에 텍스트를 설정하면 다른 응용프로그램에 붙여넣을 수 있습니다.
Windows 8을 사용하고 있기 때문에 Microsoft Forms 또는 Data Object를 사용하여 클립보드를 조작할 수 없습니다.Windows 8에서는 제대로 작동하지 않습니다.)
업데이트 및 편집: Jason Kurtz의 아래 답변 덕분에 아래 코드가 수정되어 64비트 Excel에서 제대로 작동합니다.만약 당신이 이것이 유용하다고 생각한다면, 그의 대답에 투표해 주십시오.
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
좋아요, 이제 알겠어요...
코드 버전에서 이 행을 변경해야 합니다.
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As String, ByVal lpString2 As String) As LongPtr
대상:
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr
코드를 그대로 통과하면 lstrcopy가 호출될 때 lpGlobalMemory의 값이 변경되는 것을 볼 수 있습니다.유형이 임의로 변경되면 값은 동일하게 유지됩니다.
Windows 7(윈도우 7)에서 작동합니다.그것이 당신에게 효과가 있기를 바랍니다!
다른 사람들을 위해 완전한 코드를 게시하고 있습니다.32비트 버전의 Excel 2007, 2010, 2013, 2016 및 64비트 Excel 2013 테스트 및 작업 모두 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
이 질문은 이제 끝났지만 아키텍처와 독립적으로 작동하는 훨씬 간단한 접근 방식을 선호합니다.그리고 클립보드를 읽고 쓸 수 있는 단일 기능의 접근 방식을 좋아합니다.
Function Clipboard(Optional StoreText As String) As String
'PURPOSE: Read/Write to Clipboard
'Source: ExcelHero.com (Daniel Ferry)
Dim x As Variant
'Store as variant for 64-bit VBA support
x = StoreText
'Create HTMLFile Object
With CreateObject("htmlfile")
With .parentWindow.clipboardData
Select Case True
Case Len(StoreText)
'Write to the clipboard
.setData "text", x
Case Else
'Read from the clipboard (no variable passed through)
Clipboard = .GetData("text")
End Select
End With
End With
End Function
코드는 다음과 같이 정확히 사용합니다.
http://msdn.microsoft.com/en-us/library/office/ff192913.aspx
모든 API 선언에 대해 선언 뒤에 PtrSafe를 삽입하는 것을 제외합니다.
코드는 모듈 자체에 있어야 합니다.
다음과 같이:
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
언급URL : https://stackoverflow.com/questions/18668928/excel-2013-64-bit-vba-clipboard-api-doesnt-work
'programing' 카테고리의 다른 글
Git 오류: "올바른 액세스 권한이 있고 리포지토리가 있는지 확인하십시오." (0) | 2023.05.12 |
---|---|
Apache POI를 사용하여 MS Excel 파일 형식 결정 (0) | 2023.05.12 |
서비스 패브릭 애플리케이션의 버전을 지정하고 분리하는 방법은 무엇입니까? (0) | 2023.05.12 |
Linux에서만 AWS RDS용 mysqdump "flush tables" 오류가 발생했습니다. (0) | 2023.05.12 |
문자열을 VB의 Enum 값으로 구문 분석합니다.그물 (0) | 2023.05.12 |