Я собираюсь поделиться двумя решениями:
Во-первых, быстрое и грязное решение:
- Создание многострочного текстового поля
- Вставить к этому
- Разобрать результат
Обратите внимание, что при вставке текста он вставляется в файл TSV (значения, разделенные табуляцией). Это может вызвать проблемы, если у вас есть значения, которые не могут быть представлены в формате TSV.
Во-вторых, слишком сложный ответ буфера обмена WinAPI. Я рекомендую первый ответ для начинающих пользователей, так как его гораздо проще понять, второй в основном полезен для опытных пользователей
Во-первых, нам нужны объявления для многих функций буфера обмена, функций обработки глобальной памяти и строковых функций. Мои объявления несовместимы с VBA6, но должны быть совместимы с 64-разрядными:
'Global mem functions
Public Declare PtrSafe Function GlobalSize Lib "Kernel32" (ByVal hMem As LongPtr) As LongPtr
Public Declare PtrSafe Function GlobalLock Lib "Kernel32" (ByVal hMem As LongPtr) As LongPtr
Public Declare PtrSafe Function GlobalUnlock Lib "Kernel32" (ByVal hMem As LongPtr) As Boolean
'Clipboard functions
Public Declare PtrSafe Function GetClipboardData Lib "User32" (ByVal uFormat As Long) As LongPtr
Public Declare PtrSafe Function GetClipboardFormatNameW Lib "User32" (ByVal format As Long, ByVal lpszFormatName As LongPtr, ByVal cchMaxCount As Long) As Long
Public Declare PtrSafe Function OpenClipboard Lib "User32" (Optional ByVal hWndNewOwner As LongPtr) As Boolean
Public Declare PtrSafe Function CloseClipboard Lib "User32" () As Boolean
Public Declare PtrSafe Function EnumClipboardFormats Lib "User32" (ByVal format As Long) As Long
Public Declare PtrSafe Function CountClipboardFormats Lib "User32" () As Long
'String functions
Public Declare PtrSafe Function lstrcpyA Lib "Kernel32" (ByVal lpString1 As LongPtr, ByVal lpString2 As LongPtr) As LongPtr
Затем мы получим электронную таблицу XML из буфера обмена, выполнив 2 шага:
Public Function GetClipboardSpreadsheetFormat() As Long
'Requires clipboard to be open, doesn't close it, returns 0 if not exists
Dim format As Long
Dim b As String
Dim l As Long
For l = 1 To CountClipboardFormats
b = String(100, vbNullChar) 'Initialize string buffer
format = EnumClipboardFormats(format) 'Get next format
GetClipboardFormatNameW format, StrPtr(b), 100 'Copy name to buffer
If Left(b, 15) = "XML Spreadsheet" Then
GetClipboardSpreadsheetFormat = format
Exit Function
End If
Next
End Function
Public Function GetClipboardSpreadsheetXML() As String
OpenClipboard 'Open (lock) the clipboard
Dim format As Long
format = GetClipboardSpreadsheetFormat
If format = 0 Then
Debug.Print "Spreadsheet data not available, display message here"
GoTo ExitHandler
End If
Dim hMem As LongPtr
hMem = GetClipboardData(format) 'Get handle to clipboard data
Dim memSize As LongPtr
memSize = GlobalSize(hMem) 'Get memory size
Dim buf() As Byte
Redim buf(0 To memSize - 1) 'Initialize buffer to hold XML
Dim memPtr As Long
memPtr = GlobalLock(hmem) 'Lock memory, get pointer to address
lstrcpyA VarPtr(buf(0)), memPtr 'Copy memory to buffer
GetClipboardSpreadsheetXML = StrConv(buf, vbUnicode) 'Convert ASCII string to unicode, return as result
ExitHandler:
If memPtr <> 0 Then GlobalUnlock (hMem) 'If memory pointer has been acquired, unlock global
CloseClipboard 'Close and unlock clipboard
End Function
Поскольку вы намереваетесь преобразовать электронную таблицу в XML, вы можете получить XML-таблицу, вызвав GetClipboardSpreadsheetXML
, а затем использовать XSLT для преобразования ее в нужный формат.
Для источников данных, отличных от Excel, вы можете использовать Формат HTML вместо XML Spreadsheet для извлечения HTML, если он доступен, а в противном случае вы можете использовать 1 (CF_TEXT
) как ваш формат, а не перебирать все возможные форматы для извлечения простого текста из буфера обмена.
Подробнее об API буфера обмена можно узнать на Документах Microsoft