Работа с буфером обмена в VBA Excel: копирование и вставка ячеек, копирование текста из переменной, очистка буфера обмена. Объект DataObject. Примеры.
Копирование и вставка ячеек
Копирование содержимого и форматов ячеек (диапазона) в буфер обмена осуществляется методом Range.Copy, а вставка – методом Worksheet.Paste:
‘Копирование одной ячейки в буфер обмена Range(«A10»).Copy Cells(10, 1).Copy ‘Копирование диапазона ячеек в буфер обмена Range(«B8:H12»).Copy Range(Cells(8, 2), Cells(12, 8)).Copy ‘Вставка ячейки (диапазона) из буфера обмена на рабочий лист ActiveSheet.Paste Range(«A20») ActiveSheet.Paste Cells(20, 1) |
При вставке диапазона ячеек из буфера обмена на рабочий лист достаточно указать верхнюю левую ячейку места (диапазона) вставки.
Для вставки из буфера обмена отдельных компонентов скопированных ячеек (значения, формулы, примечания и т.д.), а также применения к диапазону транспонирования или вычислений, используется метод Range.PasteSpecial (специальная вставка).
Буфер обмена и переменная
Передача текста между переменной и буфером обмена в VBA Excel осуществляется с помощью объекта DataObject. Стоит иметь в виду, что на некоторых компьютерах DataObject может некорректно работать при открытом окне проводника.
Объект DataObject
DataObject – это область временного хранения форматированных фрагментов текста, используемая в операциях переноса данных.
Подробнее об элементе DataObject вы можете прочитать на сайте разработчиков.
Методы объекта DataObject:
Метод | Описание |
---|---|
GetFromClipboard | Копирует данные из буфера обмена в DataObject |
GetText | Извлекает текстовую строку из объекта DataObject в указанном формате |
PutInClipboard | Перемещает данные из DataObject в буфер обмена |
SetText | Копирует текстовую строку в DataObject, используя указанный формат |
Копирование текста из переменной в буфер обмена
Sub Primer2() Dim s As String, myData As New DataObject s = «Копирование текста из переменной в буфер обмена» ‘Копируем текст из переменной в DataObject myData.SetText (s) ‘Перемещаем текст из DataObject в буфер обмена myData.PutInClipboard ‘Проверяем содержимое буфера обмена ActiveSheet.Paste Range(«A1») End Sub |
Копирование текста из буфера обмена в переменную
Sub Primer3() Dim s As String, myData As New DataObject Range(«A1») = «Копирование текста из буфера обмена в переменную» ‘Копируем данные из ячейки в буфер обмена Range(«A1»).Copy ‘Копируем данные из буфера обмена в DataObject myData.GetFromClipboard ‘Извлекаем текст из объекта DataObject и присваиваем переменной s s = myData.GetText ‘Проверяем содержимое переменной s MsgBox s End Sub |
Очистка буфера обмена
Специального метода для очистки буфера обмена в VBA Excel нет. Для решения этой задачи можно использовать выход из режима вырезания-копирования:
Application.CutCopyMode = False |
Следующий пример демонстрирует вставку скопированной ячейки "A1"
в ячейки "A2"
и "A3"
и отсутствие вставки в ячейки "A4"
и "A5"
после строки Application.CutCopyMode = False
:
Sub Primer4() Range(«A1») = «Очистка буфера обмена» Range(«A1»).Copy ActiveSheet.Paste Range(«A2») ActiveSheet.Paste Range(«A3») Application.CutCopyMode = False On Error Resume Next ActiveSheet.Paste Range(«A4») ActiveSheet.Paste Range(«A5») End Sub |
Оператор On Error Resume Next
необходим для обработки (пропуска) ошибки, возникающей при вставке из пустого буфера обмена.
Функции для работы с буфером обмена
В некоторых системах, начиная с Windows 8, метод DataObject.PutInClipboard не работает правильно: если открыт хотя бы один экземпляр Проводника (папка), в буфер обмена записываются два квадратика. Следующие функции должны решить эту проблему:
‘Функция записи текста в буфер обмена Function SetClipBoardText(ByVal Text As Variant) As Boolean SetClipBoardText = CreateObject(«htmlfile»).parentWindow.clipboardData.SetData(«Text», Text) End Function ‘Функция вставки текста из буфера обмена Function GetClipBoardText() As String On Error Resume Next GetClipBoardText = CreateObject(«htmlfile»).parentWindow.clipboardData.GetData(«Text») End Function ‘Функция очистки буфера обмена Function ClearClipBoardText() As Boolean ClearClipBoardText = CreateObject(«htmlfile»).parentWindow.clipboardData.clearData(«Text») End Function |
Пример использования функций для работы с буфером обмена:
Sub Primer() Dim s As String s = «Копирование текста из переменной в буфер обмена» ‘Копируем текст в буфер обмена SetClipBoardText (s) ‘Вставляем текс из буфера обмена в ячейку «A1» Range(«A1») = GetClipBoardText ‘Очищаем буфер обмена, если это необходимо ClearClipBoardText End Sub |
Update! Better Solution from ExcelHero
Excel MVP Daniel Ferry from ExcelHero graciously provided a much more eloquent solution than my original article over on the StackOverflow forum.
In the below solution, he is utilizing the Microsoft HTML Object Library to access the clipboard. This solution will work with 32-bit and 64-bit versions of Excel which has been a pain point for many proposed VBA solutions out there on the web. His VBA function also allows you to both read from the clipboard and write to the clipboard depending on if you pass through a variable. Check out this beautiful piece of code (and if you dare keep scrolling to see my original behemoth of a solution!).
Text To The Clipboard (original solution)
There may be instances where you create a macro that reads in text and sticks it in your computer’s clipboard so you can manually paste it somewhere else. The most prominent way to do this, is to use a DataObject variable from the Forms library (language).
You can reference this library by either going to your Visual Basic Editor’s tools menu and enabling the Microsoft Forms 2.0 Object Library reference or by simply adding a userform to your project (the userform doesn’t have to do anything, it’s very existence tells your project that the Forms library is needed).
Below is a very self-explanatory snippet of VBA code that will show you how to copy text straight into your computer’s clipboard.
Sub CopyTextToClipboard()
‘PURPOSE: Copy a given text to the clipboard (using DataObject)
‘SOURCE: www.TheSpreadsheetGuru.com
‘NOTES: Must enable Forms Library: Checkmark Tools > References > Microsoft Forms 2.0 Object Library
Dim obj As New DataObject
Dim txt As String
‘Put some text inside a string variable
txt = «This was copied to the clipboard using VBA!»
‘Make object’s text equal above string variable
obj.SetText txt
‘Place DataObject’s text into the Clipboard
obj.PutInClipboard
‘Notify User
MsgBox «There is now text copied to your clipboard!», vbInformation
End Sub
There’s An Excel Office Bug!
I initially started investigating how to copy text to the clipboard while running someone else’s code. This code worked perfectly on my work computer (using Windows 7/Excel 2007), however it kept copying just two question marks to the clipboard while executing the VBA code on my home computer (using Windows 8.1/Excel 2013). It took me forever to narrow down what was causing this to happen (the source code was very long) and of course, the problem ended up being a bug on the part of Microsoft!
Luckily, there were many others who were running into this very issue on the forums. Someone posted that they were actually able to troubleshoot this problem with a Microsoft support member a couple years ago (maybe in 2010) and that person determined it to be a bug. The support member pointed to a solution using a Windows API as a workaround (shown in the next section).
Copy To Clipboard With Windows API
Below is the API workaround suggested by Microsoft to get around the «SetText» bug. It has three parts: an API declaration section, a Function routine, and then I used a similar subroutine macro to place the desired text into the Clipboard.
UPDATE: I have modified the API declarations to work with both 64-bit and 32-bit versions of Microsoft Office
‘Handle 64-bit and 32-bit Office
#If VBA7 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» (ByVal hMem As Long) As Long
Private Declare Function GlobalLock Lib «kernel32» (ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib «kernel32» (ByVal wFlags As Long, _
ByVal dwBytes As Long) As Long
Private Declare Function CloseClipboard Lib «user32» () As Long
Private Declare Function OpenClipboard Lib «user32» (ByVal hwnd As Long) As Long
Private Declare Function EmptyClipboard Lib «user32» () As Long
Private Declare Function lstrcpy Lib «kernel32» (ByVal lpString1 As Any, _
ByVal lpString2 As Any) As Long
Private Declare Function SetClipboardData Lib «user32» (ByVal wFormat _
As Long, ByVal hMem As Long) As Long
#End If
Const GHND = &H42
Const CF_TEXT = 1
Const MAXSIZE = 4096
Function ClipBoard_SetData(MyString As String)
‘PURPOSE: API function to copy text to clipboard
‘SOURCE: www.msdn.microsoft.com/en-us/library/office/ff192913.aspx
#If VBA7 Then
Dim hGlobalMemory As LongPtr, lpGlobalMemory As LongPtr
Dim hClipMemory As LongPtr, x As LongPtr
#Else
Dim hGlobalMemory As Long, lpGlobalMemory As Long
Dim hClipMemory As Long, x As Long
#End If
‘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
Sub CopyTextToClipboard()
‘PURPOSE: Copy a given text to the clipboard (using Windows API)
‘SOURCE: www.TheSpreadsheetGuru.com
‘NOTES: Must have above API declaration and ClipBoard_SetData function in your code
Dim txt As String
‘Put some text inside a string variable
txt = «This was copied to the clipboard using VBA!»
‘Place text into the Clipboard
ClipBoard_SetData txt
‘Notify User
MsgBox «There is now text copied to your clipboard!», vbInformation
End Sub
About The Author
Hey there! I’m Chris and I run TheSpreadsheetGuru website in my spare time. By day, I’m actually a finance professional who relies on Microsoft Excel quite heavily in the corporate world. I love taking the things I learn in the “real world” and sharing them with everyone here on this site so that you too can become a spreadsheet guru at your company.
Through my years in the corporate world, I’ve been able to pick up on opportunities to make working with Excel better and have built a variety of Excel add-ins, from inserting tickmark symbols to automating copy/pasting from Excel to PowerPoint. If you’d like to keep up to date with the latest Excel news and directly get emailed the most meaningful Excel tips I’ve learned over the years, you can sign up for my free newsletters. I hope I was able to provide you with some value today and I hope to see you back here soon!
— Chris
Founder, TheSpreadsheetGuru.com
Функции для работы с буфером обмена
(очистка буфера обмена, запись в буфер обмена, чтение из буфера обмена)
ВНИМАНИЕ: для работы функций требуется установка ссылки на библиотеку Microsoft Forms 2.0 Object Library:
Public Sub SetClipboard(Obj As Variant) Dim MyDataObj As New DataObject MyDataObj.SetText Format(Obj) MyDataObj.PutInClipboard End Sub Public Sub SetTextIntoClipboard(ByVal txt As String) Dim MyDataObj As New DataObject MyDataObj.SetText txt MyDataObj.PutInClipboard End Sub Public Function GetClipboard() As Variant GetClipboard = "": On Error Resume Next Dim MyDataObj As New DataObject MyDataObj.GetFromClipboard: GetClipboard = MyDataObj.GetText() End Function Public Sub ClearClipboard() Dim MyDataObj As New DataObject MyDataObj.SetText "": MyDataObj.PutInClipboard End Sub
Аналогичная функция ClipboardText (чтение текста из буфера обмена), но не требующая подключения библиотеки:
Sub ПримерИспользования() txt = ClipboardText MsgBox txt, vbInformation, "Содержимое буфера обмена Windows" End Sub Function ClipboardText() ' чтение из буфера обмена With GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") .GetFromClipboard ClipboardText = .GetText End With End Function Sub SetClipboardText(ByVal txt$) ' запись в буфер обмена With GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") .SetText txt$ .PutInClipboard End With End Sub
- 68173 просмотра
Не получается применить макрос? Не удаётся изменить код под свои нужды?
Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.
The code given at the Microsoft site works in Excel too, even though it is under Access VBA. I tried it in Excel 365 on a 64 bit Windows 10.
Microsoft Site Link: https://learn.microsoft.com/en-us/office/vba/access/Concepts/Windows-API/send-information-to-the-clipboard
Copying here for answer completeness.
Option Explicit
Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Declare Function EmptyClipboard Lib "user32.dll" () As Long
Private Declare Function CloseClipboard Lib "user32.dll" () As Long
Private Declare Function IsClipboardFormatAvailable Lib "user32.dll" (ByVal wFormat As Long) As Long
Private Declare Function GetClipboardData Lib "user32.dll" (ByVal wFormat As Long) As Long
Private Declare Function SetClipboardData Lib "user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Public Sub SetClipboard(sUniText As String)
Dim iStrPtr As Long
Dim iLen As Long
Dim iLock As Long
Const GMEM_MOVEABLE As Long = &H2
Const GMEM_ZEROINIT As Long = &H40
Const CF_UNICODETEXT As Long = &HD
OpenClipboard 0&
EmptyClipboard
iLen = LenB(sUniText) + 2&
iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen)
iLock = GlobalLock(iStrPtr)
lstrcpy iLock, StrPtr(sUniText)
GlobalUnlock iStrPtr
SetClipboardData CF_UNICODETEXT, iStrPtr
CloseClipboard
End Sub
Public Function GetClipboard() As String
Dim iStrPtr As Long
Dim iLen As Long
Dim iLock As Long
Dim sUniText As String
Const CF_UNICODETEXT As Long = 13&
OpenClipboard 0&
If IsClipboardFormatAvailable(CF_UNICODETEXT) Then
iStrPtr = GetClipboardData(CF_UNICODETEXT)
If iStrPtr Then
iLock = GlobalLock(iStrPtr)
iLen = GlobalSize(iStrPtr)
sUniText = String$(iLen 2& - 1&, vbNullChar)
lstrcpy StrPtr(sUniText), iLock
GlobalUnlock iStrPtr
End If
GetClipboard = sUniText
End If
CloseClipboard
End Function
The above code can be called from a Custom Macro as follows:
Sub TestClipboard()
Dim Val1 As String: Val1 = "Hello Clipboard " & vbLf & "World!"
SetClipboard Val1
MsgBox GetClipboard
End Sub
To Show a button on a form, you can find a good example by a quick serach. To show a button in the Excel Custom Ribbon (One that shows only in the current Excel workbook) you can use CustomUI.
CustomUI links:
https://bettersolutions.com/vba/ribbon/custom-ui-editor.htm
https://learn.microsoft.com/en-us/office/open-xml/how-to-add-custom-ui-to-a-spreadsheet-document
imageMSO List with Icons (Used in CustomUI):
https://bert-toolkit.com/imagemso-list.html
Thanks.
Denis_pog Пользователь Сообщений: 39 |
#1 09.03.2014 08:36:54 Помогите написать макрос для копирования значений ячеек в буфер обмена (интересуют только значения, без форматирования и т.д.). Как с помощью макроса сделать кнопку «Копировать»? Нашел что то похожее
только вместо «строка текста», 1 , должны быть данные из определенных ячеек, именно данные а не формулы. Изменено: Denis_pog — 09.03.2014 20:12:30 |
||
gling Пользователь Сообщений: 4024 |
#2 09.03.2014 13:35:35 А макрорекордером не пробовали создать макрос?
Макросом кнопки не делают, макрос «вешают» на готовую кнопку. |
||
gling Пользователь Сообщений: 4024 |
#3 09.03.2014 14:00:28
Для того чтобы в буфере осталась информация необходимо в параметрах буфера обмена установить галочки либо автоматическое отображение буфера, либо сбор данных без отображения буфера. Только во втором случае при вставке данных буфер придется отобразить. А код для копирования диапазона А1:Е10 на Листе1 записан макрорекодером.
Изменено: gling — 09.03.2014 20:12:53 |
||||
Denis_pog Пользователь Сообщений: 39 |
|
Denis_pog Пользователь Сообщений: 39 |
#5 10.03.2014 04:29:12
за что отвечает данная строка? |
||
gling Пользователь Сообщений: 4024 |
#6 10.03.2014 09:29:03 Она убирает отмеченный диапазон копирования. Если её не написать то при случайном нажатии Ctrl+V будет вставляться этот диапазон в активную ячейку и далее. Если вместо этих двух строк написать
То диапазон сразу копируется без буфера обмена. Только надо знать куда. Я указал диапазон ниже начиная с А15. |
||
Denis_pog Пользователь Сообщений: 39 |
#7 10.03.2014 09:36:13
Спасибо, мне нужно копировать данные в другую программу, как я понял сделать можно, но через API для меня это пока сложновато. |
||
gling Пользователь Сообщений: 4024 |
#8 10.03.2014 09:42:54
Для меня тоже. |
||
Hugo Пользователь Сообщений: 23251 |
В другую программу можно копировать с помощью AutoIt — поищите форумы по этой программе. |
Denis_pog Пользователь Сообщений: 39 |
|
лишнюю тему решил не создавать т.к. у меня схожий вопрос и вроде то что мне нужно есть в сообщениях, тем не менее мне не удалось сделать макрос который копирует в буфер обмена значение (не формулу) текущей ячейки, для того чтобы потом вставить это значение в другой программе Изменено: Марьян Ковач — 26.03.2015 22:26:50 |
|
Максим Зеленский Пользователь Сообщений: 4646 Microsoft MVP |
#12 27.03.2015 12:15:57
F1 творит чудеса |
||
Nikki Пользователь Сообщений: 107 |
Что-то не работает, выдает Compile error: User-defined type not defined Изменено: Nikki — 27.03.2015 17:58:21 |
RAN Пользователь Сообщений: 7091 |
Добавьте форму в файл. Заработает. |
vlad7790 Пользователь Сообщений: 41 |
RAN, а вы не подскажите, какую форму вы имели ввиду? |
Yarosik Пользователь Сообщений: 4 |
Привет задача такая: процесс: в ячейку С3 вводятся данные измерения и нажимаем Enter, а в ячейке С5 появляются расчетные значения. Вот их и нужно автоматически копировать в буфер обмена. Изменено: Yarosik — 26.06.2019 15:39:15 |
Юрий М Модератор Сообщений: 60575 Контакты см. в профиле |
#17 26.06.2019 21:09:39 Скопируйте в модуль листа:
|
||
Yarosik Пользователь Сообщений: 4 |
#18 27.06.2019 13:23:05 Юрий М, Спасибо, работает как и задумывалось |