VBA操作剪切板
VBA操作剪切板
一,利用MsForms.DataObject操作
1,什么是DataObject对象
传输操作中使用的格式化文本数据的保留区域。 还保留 DataObject 中存储的文本块所对应的 格式 的列表
DataObject 可包括一段针对剪贴板文本格式的文本和一段针对每种其他文本格式(如自定义格式和用户定义的格式)的文本。
DataObject 与剪贴板不同。 DataObject 支持涉及剪贴板和文本的拖放操作的命令。 在启动涉及剪贴板的操作(如 GetText)或拖放操作时,该操作中涉及的数据将移动到 DataObject。
DataObject 的工作方式与剪贴板类似。 如果您将文本字符串复制到 DataObject,则 DataObject 将存储文本字符串。 如果您将同一格式的第二个字符串复制到 DataObject,则 DataObject 将弃用第一个文本字符串并存储第二个字符串的副本。 它将存储一段指定格式的文本并保留最近操作中的文本。
2,用vba操作剪切板注意
不要打开剪切板,同时只能一个操作,否则强制退出
3,声明方式
-
前期绑定
勾选–>
Micorosoft Forms 2.0 Object LIbrary
-
后期绑定
CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
4,文本写入剪切板
Sub test()
Dim jq As New MSForms.DataObject
Dim ss As String
ss = "测试文本" '文本变量
jq.SetText ss '赋值给DataObject
jq.PutInClipboard '写入剪切板
End Sub
5,读取剪切板文本
Sub test2()
Dim jq As New MSForms.DataObject
Dim ss As String
jq.GetFromClipboard '读取剪切板
ss = jq.GetText '调用方法得到文本
Debug.Print ss
End Sub
二,利用API操作剪切板
1,用到得API函数
-
OpenClipboard
函数:作用是打开剪贴板声明及引用:
Declare Function OpenClipboard Lib "user32" Alias "OpenClipboard" (ByVal hwnd As Long) As Long
如果调用成功,它会返回一个非0值;如果失败,则返回0;
如果有其他窗口已经打开剪贴板,这个函数会调用失败。
如果函数调用成功,一定要记得使用
CloseClipboard
函数关闭它。 -
GetClipboardData
函数:作用是读取剪贴板里面的数据声明及引用:
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
如果调用成功,返回剪贴板中以指定格式存放的剪贴板对象的句柄;
如果调用失败,返回Null;
在使用
GetClipboardData
之前,必须先成功调用OpenClipboard
常用得几个常量
-
Public Const CF_TEXT = 1
-
Public Const CF_BITMAP = 2
-
Public Const CF_METAFILEPICT = 3
-
Public Const CF_SYLK = 4
-
-
CopyMemory
函数将一定字节长度的数据从内存中的一个位置(源)复制到另一个位置(目的地)声明及引用:
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
这个函数需要三个参数:
-
Destination
:目的地的第一个字节的内存地址(指针) -
Source
: 源的第一个字节的内存地址(指针) -
Length
: 要复制的数据的长度
-
-
GlobalLock
函数锁定一个全局内存对象并返回它所占用内存块的第一个字节的内存地址(指针)声明及引用:
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
-
GlobalSize
函数返回给定内存对象的字节长度声明及引用:
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
-
GlobalUnlock
函数将可移动(GMEM_MOVEABLE)内存对象的锁计数器数值-1,对于固定位置(GMEM_FIXED)的内存对象,这个函数不起作用简单说这个函数就是解锁内存指针和上面锁定对应
用到上面GlobalAlloc函数得到参数来解锁
声明及引用:
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
-
CloseClipboard
函数关闭剪贴板声明及引用:
Declare Function CloseClipboard Lib "user32"() As Long
-
EmptyClipboard
函数清空剪切板声明及引用:
Declare Function EmptyClipboard Lib "user32" () As Long
-
GlobalAlloc分配可移动的全局内存
声明及引用:
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
wFlags 参数给个常量:`Const GHND = &H42`
-
lstrcpy复制字符串到该全局内存
声明及引用:
Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
lpString1 是要复制得内存指针地址,用`GlobalLock`得到
2,写入剪切板
'处理64位和32位Office
#If VBA7 And Win64 Then
Private Declare PtrSafe Function GlobalUnlock 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 GlobalAlloc Lib "kernel32" (ByVal wFlags As LongPtr, _
ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As LongPtr
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _
ByVal lpString2 As Any) As LongPtr
Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As LongPtr, _
ByVal hMem As LongPtr) As LongPtr
#Else
Private Declare Function GlobalUnlock Lib "kernel32" (ByValhMem As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMemAs Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByValwFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () AsLong
Private Declare Function OpenClipboard Lib "user32" (ByValhwnd As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () AsLong
Private Declare Function lstrcpy Lib "kernel32" (ByVallpString1 As Any, _
ByVal lpString2 As Any) As Long
Private Declare FunctionSetClipboardData Lib "user32" (ByVal wFormat _
As Long, ByVal hMem As Long) As Long
#End If
Const GHND = &H42
Const CF_TEXT = 1
Const MAXSIZE = 4096
'复制文本到剪贴板的API函数
'来源:www.msdn.microsoft.com/en-us/library/office/ff192913.aspx
Function ClipBoard_SetData(MyString As String)
Dim hGlobalMemory As LongPtr, lpGlobalMemory As LongPtr
Dim hClipMemory As LongPtr, X As LongPtr
'分配可移动的全局内存
hGlobalMemory = GlobalAlloc(GHND, Len(MyString) + 20)
'锁定该块以获取该内存的远指针
lpGlobalMemory = GlobalLock(hGlobalMemory)
'复制字符串到该全局内存
lpGlobalMemory = lstrcpy(lpGlobalMemory, MyString)
'解锁该内存
If GlobalUnlock(hGlobalMemory) <> 0 Then
MsgBox "不能解锁内存位置. 复制中止."
GoTo OutOfHere2
End If
'打开剪贴板复制数据.
If OpenClipboard(0&) = 0 Then
MsgBox "不能打开剪贴板. 复制中止."
Exit Function
End If
'清空剪贴板
X = EmptyClipboard()
'复制数据到剪贴板
hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory)
OutOfHere2:
If CloseClipboard() = 0 Then
MsgBox "不能关闭剪贴板."
End If
End Function
Sub CopyTextToClipboard()
Dim strText As String
strText = "这里使用VBA复制文本到剪贴板!"
'放置文本到剪贴板
ClipBoard_SetData strText
End Sub
3,读取
代码
'来源:https://zhuanlan.zhihu.com/p/214106380
#If VBA7 And Win64 Then
Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
#Else
Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
#End If
Private Const CF_TEXT = 1
Sub mynzB()
#If VBA7 And Win64 Then
Dim hMem As LongPtr
Dim lpData As LongPtr
Dim nClipSize As LongPtr
#Else
Dim hMem As Long
Dim lpData As Long
Dim nClipSize As Long
#End If
Dim bytClipData() As Byte
Dim sClipString As String
'Sheets("sheet1").Select
Range("A1:A3").Copy
If OpenClipboard(ByVal 0&) Then '如果OpenClipboard函数返回非0值,说明成功打开剪贴板
hMem = GetClipboardData(CF_TEXT) '获取剪贴板中以文本格式存在的内存对象的句柄
'如果剪贴板中对应的格式不存在,此时的hMem会是0(Null)
'这里用CBool把它转换成Boolean类型加以判断
If CBool(hMem) Then
lpData = GlobalLock(hMem) '获取内存对象第一个字节的内存地址
nClipSize = GlobalSize(hMem) '获取内存对象的字节长度
'修改缓冲字节数组的长度,确保能够容纳内存对象的全部数据
ReDim bytClipData(1 To CLng(nClipSize))
'复制内存对象的数据到字节数组中,注意Byval的用法
CopyMemory bytClipData(1), ByVal lpData, nClipSize
sClipString = StrConv(bytClipData, vbUnicode) '将字节转化成字符串
MsgBox "当前剪贴板内的文本是:" & vbCrLf & sClipString '将结果显示给用户
Else
MsgBox "当前剪贴板内没有文本"
End If
CloseClipboard '记住关闭,否则下次用报错
End If
End Sub
4, 提取剪贴板所有数据格式的代码
#If VBA7 And Win64 Then
Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
'这是获得剪切板格式用到得额外得api函数
Declare PtrSafe Function EnumClipboardFormats Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As LongPtr, ByVal lpString As String, ByVal nMaxCount As LongPtr) As LongPtr
#Else
Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function EnumClipboardFormats Lib "user32" (ByValwFormat As Long) As Long
Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
#End If
Private Const CF_TEXT = 1 '文本常量
Private Const CF_BITMAP = 2 'Bitmap对象
Private Const CF_METAFILEPICT = 3 'Metafile Picture格式
Private Const CF_SYLK = 4 '微软符号连接格式(Microsoft Symbolic Link Format)
Private Const CF_DIF = 5 'Software Arts' Data Interchange Format.
Private Const CF_TIFF = 6 '标签图像文件格式(TIFF)
Private Const CF_OEMTEXT = 7 '包含OEM字符集的文本格式
Private Const CF_DIB = 8 '设备无关位图(DIB)格式,前面是一个BITMAPINFO结构,后面是图像像素位
Private Const CF_PALETTE = 9 '调色板对象格式,当程序向剪贴板中放入一幅使用调色板的位图时,它需要同时将调色板也放入剪贴板
Private Const CF_PENDATA = 10 '手写笔数据
Private Const CF_RIFF = 11 '比标准CF_WAVE所能代表的音频格式更加复杂的音频格式
Private Const CF_WAVE = 12 '标准音频格式(如11kHz或22kHz脉冲编码调制)的数据
Private Const CF_UNICODETEXT = 13 'Unicode文本格式
Private Const CF_ENHMETAFILE = 14 '增强图元文件格式
Private Const CF_HDROP = 15 '文件名列表
Private Const CF_LOCALE = 16 '与剪贴板内文本相关的区域选项的ID
Private Const CF_MAX = 17
Dim lFormat As LongPtr
Sub mynzC()
Dim i
Sheets("SHEET2").Select
Cells().ClearContents
Sheets("SHEET4").Select
Cells(2, 1).Copy
Sheets("SHEET2").Select
If OpenClipboard(ByVal 0&) Then
lFormat = EnumClipboardFormats(0)
If lFormat <> 0 Then
i = 1
Cells(i, 1) = "格式代码"
Cells(i, 2) = "格式名称"
i = i + 1
Do While lFormat <> 0
Cells(i, 1) = lFormat
Cells(i, 2) = GetFormatName(lFormat)
i = i + 1
lFormat = EnumClipboardFormats(lFormat)
Loop
End If
CloseClipboard
End If
End Sub
Public Function GetFormatName(ByVal lFormat As LongPtr) As String
Select Case lFormat
Case 1
GetFormatName = "CF_Text"
Case 2
GetFormatName = "CF_Bitmap"
Case 3
GetFormatName = "CF_MetaFilePict"
Case 4
GetFormatName = "CF_SYLK"
Case 5
GetFormatName = "CF_Dif"
Case 6
GetFormatName = "CF_Tiff"
Case 7
GetFormatName = "CF_OEMText"
Case 8
GetFormatName = "CF_DIB"
Case 9
GetFormatName = "CF_Pallette"
Case 10
GetFormatName = "CF_PenData"
Case 11
GetFormatName = "CF_Riff"
Case 12
GetFormatName = "CF_Wave"
Case 13
GetFormatName = "CF_UnicodeText"
Case 14
GetFormatName = "CF_EnhMetaFile"
Case 15
GetFormatName = "CF_HDrop"
Case 16
GetFormatName = "CF_Locale"
Case 17
GetFormatName = "CF_Max"
Case Else:
'以下是非标准部分
Dim sBuffer As String
sBuffer = String(100, Chr(0))
GetClipboardFormatName lFormat, sBuffer, 100
GetFormatName = Trim(sBuffer)
End Select
End Function
Sub mynzD()
CloseClipboard
End Sub
api弄得比较乱
5,整理一个上面用得全部api
#If VBA7 And Win64 Then
Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Declare PtrSafe Function GetClipboardData Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _
Source As Any, ByVal Length As LongPtr)
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
'这是获得剪切板格式用到得额外得api函数
Declare PtrSafe Function EnumClipboardFormats Lib "user32" (ByVal wFormat As LongPtr) As LongPtr
Declare PtrSafe Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" _
(ByVal wFormat As LongPtr, ByVal lpString As String, ByVal nMaxCount As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As LongPtr, _
ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As LongPtr
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _
ByVal lpString2 As Any) As LongPtr
Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As LongPtr, _
ByVal hMem As LongPtr) As LongPtr
#Else
Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Declare Function CloseClipboard Lib "user32" () As Long
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function EnumClipboardFormats Lib "user32" (ByValwFormat As Long) As Long
Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () AsLong
Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _
ByVal lpString2 As Any) As Long
Private Declare FunctionSetClipboardData Lib "user32" (ByVal wFormat _
As Long, ByVal hMem As Long) As Long
#End If
Private Const CF_TEXT = 1 '文本常量
Private Const CF_BITMAP = 2 'Bitmap对象
Private Const CF_METAFILEPICT = 3 'Metafile Picture格式
Private Const CF_SYLK = 4 '微软符号连接格式(Microsoft Symbolic Link Format)
Private Const CF_DIF = 5 'Software Arts' Data Interchange Format.
Private Const CF_TIFF = 6 '标签图像文件格式(TIFF)
Private Const CF_OEMTEXT = 7 '包含OEM字符集的文本格式
Private Const CF_DIB = 8 '设备无关位图(DIB)格式,前面是一个BITMAPINFO结构,后面是图像像素位
Private Const CF_PALETTE = 9 '调色板对象格式,当程序向剪贴板中放入一幅使用调色板的位图时,它需要同时将调色板也放入剪贴板
Private Const CF_PENDATA = 10 '手写笔数据
Private Const CF_RIFF = 11 '比标准CF_WAVE所能代表的音频格式更加复杂的音频格式
Private Const CF_WAVE = 12 '标准音频格式(如11kHz或22kHz脉冲编码调制)的数据
Private Const CF_UNICODETEXT = 13 'Unicode文本格式
Private Const CF_ENHMETAFILE = 14 '增强图元文件格式
Private Const CF_HDROP = 15 '文件名列表
Private Const CF_LOCALE = 16 '与剪贴板内文本相关的区域选项的ID
Private Const CF_MAX = 17
Const GHND = &H42
Const MAXSIZE = 4096
再比较常用得比如从剪切板导出图片
从剪切板读取图片到控件等,大同小异