Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

Форум поддержки пользователей. LibreOffice, Apache OpenOffice, OpenOffice.org

30 Июнь 2022, 19:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости: Здесь можно поблагодарить участников форума Улыбка
 
   Начало   Помощь Поиск Войти Регистрация    задать вопрос  
Страниц: 1   Вниз
  Печать  
Автор Тема: Передача значения переменной в системный буфер обмена.  (Прочитано 587 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Ириминаге
Всем бобра!
Форумчанин
***
Offline Offline

Сообщений: 63


« Стартовое сообщение: 17 Июнь 2022, 11:56 »

В СУБД BASE, из таблицы должна извлекаться информация, обрабатываться и передаваться в системный буфер обмена.
Все примеры, найденные в интернете, предполагают использование Слушателя, а мне он не нужен совершенно. Как можно передать значение переменной в буфер обмена, без этого метода?
Записан

Он верил в Мир и Здравый Смысл,
В себя, в людей, в любовь, в науку!
Но кто-то Кафку положил,
В его протянутую руку...
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 104


« Ответ #1: 17 Июнь 2022, 17:54 »

Код:
REM  *****  BASIC  *****
Option Explicit

Global sTxtCString As String


Sub CopyToClipBoard(sText)
Dim oClip As Object
Dim oTrans As Object  'transferable object to set as new content

' Create SystemClipboard instance.
oClip = CreateUnoService( _
"com.sun.star.datatransfer.clipboard.SystemClipboard")
oTrans = createUnoListener("Tr_", _
"com.sun.star.datatransfer.XTransferable")

' Set data.
' NOTE: xClipboardOwner=NULL means that the caller
' is not interested in lost ownership notifications.
oClip.setContents(oTrans, Null)
sTxtCString = sText

'oClip.flushClipboard() 'does not work
End Sub

Function Tr_getTransferData( _
 aFlavor As com.sun.star.datatransfer.DataFlavor)
If (aFlavor.MimeType = "text/plain;charset=utf-16") Then
Tr_getTransferData() = sTxtCString
End If
End Function

Function Tr_getTransferDataFlavors()
Dim aFlavor As New com.sun.star.datatransfer.DataFlavor

aFlavor.MimeType = "text/plain;charset=utf-16"
aFlavor.HumanPresentableName = "Unicode-Text"
Tr_getTransferDataFlavors() = Array(aFlavor)
End Function

Function Tr_isDataFlavorSupported( _
 aFlavor As com.sun.star.datatransfer.DataFlavor) As Boolean
If aFlavor.MimeType = "text/plain;charset=utf-16" Then
Tr_isDataFlavorSupported = True
Else
Tr_isDataFlavorSupported = False
End If
End Function

Как можно передать значение переменной в буфер обмена, без этого метода?
Ctrl+C
« Последнее редактирование: 17 Июнь 2022, 17:56 от eeigor » Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
Ириминаге
Всем бобра!
Форумчанин
***
Offline Offline

Сообщений: 63


« Ответ #2: 17 Июнь 2022, 18:38 »

Именно это полотенце я в интернете и видел. И оно меня не устраивает, потому и задал вопрос. Контрол+с не подходит, потому как копируемое значение берется из переменной. В общем, нужно как в песне: "нажми на кнопку, получишь резултат, и твоя мечта осуществится, нажми на кнопку, ну что же ты не рад? Тебе больше не к чему стремиться!"
Записан

Он верил в Мир и Здравый Смысл,
В себя, в людей, в любовь, в науку!
Но кто-то Кафку положил,
В его протянутую руку...
eeigor
Опытный пользователь
***
Offline Offline

Пол: Мужской
Сообщений: 1 104


« Ответ #3: 17 Июнь 2022, 21:54 »

Поместите этот код в отдельный модуль "Clipboard" и забудьте о нем.
Используйте так:
    Call CopyToClipBoard ("Ваш текст или значение переменной")

Боюсь, ваша проблема надуманна. А со временем появится класс типа "Clipboard", который скроет всё то, что вы не хотите видеть...
« Последнее редактирование: 17 Июнь 2022, 22:01 от eeigor » Записан

Ubuntu 18.04 LTS • LibreOffice 7.3.2.2 Community
sokol92
Мастер
*****
Online Online

Пол: Мужской
Сообщений: 939


WWW
« Ответ #4: 18 Июнь 2022, 19:17 »

С моей точки зрения, приведенный в #1 пример очень полезен для обучения. Возможные вопросы для экспериментов в OC Windows (Linux, увы, пока не моя стихия):
1. Что делает каждый из макросов?

Вызываем функцию CopyToClipBoard с параметром, например, "english русский" и пробуем выполнить вставку из нового буфера обмена.
2. Непосредственно (выделяем ячейку и Shift+Insert) в ячейку Excel текст не добавляется (добавляется после перехода в режим редактирования с помощью F2). Почему? Если такой же текст скопировать в буфер обмена в текстовом редакторе (например, в Блокноте), то в ячейку Excel текст вставить можно.

В ячейку Calc текст, скопированный в буфер обмена с помощью CopyToClipBoard, вставляется непосредственно.
« Последнее редактирование: 18 Июнь 2022, 21:25 от sokol92 » Записан

Владимир.
mikekaganski
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 2 774


« Ответ #5: 19 Июнь 2022, 11:32 »

1. Что делает каждый из макросов?

CopyToClipBoard создаёт сервис SystemClipboard, а также особый объект Basic, реализующий интерфейс XTransferable. Это очень интересный трюк: использование createUnoListener не для создания слушателя, а для реализации произвольного интерфейса. Насколько я понимаю, эта возможность не документирована. Она основана на реализации функции, которая создаёт SbUnoObject, а также дополнительные интерфейсы, позволяющие использовать интроспекцию для разрешения и вызова произвольных методов реализуемого интерфейса. Естественно, требуется реализовать методы этого интерфейса - и вот тут работают три других функции: Tr_getTransferData, Tr_getTransferDataFlavors и Tr_isDataFlavorSupported.

Буфер обмена на любой современной платформе позволяет иметь одновременно несколько представлений скопированного содержимого: скажем, в виде простого текста, таблицы в разных форматах (HTML, RTF, каком-нибудь нативном), картинки в разных форматах, ... - и приложение, в которое производится вставка, сможет выбрать лучший из доступных форматов, подходящий именно для него (скажем, вставка таблицы в Paint, вероятно, выберет не то, что выберет вставка в Word). Для достижения этого приложение, из которого идёт копирование, должно предоставить все реализуемые им типы содержимого буфера - и это реализуется объектом Transferable, который имеет методы для перечисления доступных типов, а также для получения данных нужного типа.

Ну а здесь реализуется самый примитивный вариант: предоставляется только тип UTF-16. Это позволяет не усложнять реализацию, поскольку Basic вообще не имеет нормальных средств для управления кодировками текстовых данных.

2. Непосредственно ... в ячейку Excel текст не добавляется ... . Почему?

Похоже на баг (возможно, платформоспецифичный). После копирования системный буфер Windows содержит два типа данных: CF_UNICODETEXT с правильными данными (куда можно запихать и строку типа テストabcабв, которую ни в какой стандартной не-Unicode кодировке Windows не представишь), а также CF_TEXT. И вот она-то битая - содержит только нулевой завершающий байт (то есть фактически пустая).

Поскольку мы сами 8-битную кодировку не предоставляем, похоже, это внутренняя магия сервиса SystemClipboard, которая не умеет правильно создавать 8-битные данные из UTF-16, когда их не предоставляет Transferable.


* WriongClipboard.png (11.29 Кб, 699x366 - просмотрено 7 раз.)
Записан

С уважением,
Михаил Каганский
sokol92
Мастер
*****
Online Online

Пол: Мужской
Сообщений: 939


WWW
« Ответ #6: 19 Июнь 2022, 19:05 »

Провел эксперимент.
Oткрыл документ, добавил в документ макросы из #1,  вызвал функцию CopyToClipBoard с параметром "english русский", закрыл документ.

Теперь текст из буфера обмена благополучно вставляется непосредственно в ячейку Excel. Интересно...

Не вставляется (как и раньше) в редактор VBE (Excel), что, по-видимому связано с тем, что VBE "понятия не имеет" о юникоде (и хранит текст макросов в кодировке кодовой таблицы Windows по умолчанию).

Записан

Владимир.
mikekaganski
Гуру
*******
Offline Offline

Пол: Мужской
Расположение: Хабаровск -> Москва
Сообщений: 2 774


« Ответ #7: 19 Июнь 2022, 21:05 »

Хм. Отладка показывает, что это не CF_TEXT виноват, а ещё один вариант неочистки предыдущего значения результата функции. В соединении с наглым поведением Excel, который не спрашивает, какие форматы имеются в буфере, это приводит к тому, что в ответ на прямой запрос формата Biff8 Tr_getTransferData не назначает никакого результата, и там лежит предыдущее значение - которое оказывается строкой от предыдущего вызова (а он происходит сразу при вызове CopyToClipBoard, когда проверяется новое состояние кнопок вставки). То есть Excel на запрос данных в своём бинарном формате получает не отказ, а неверные данные, и выдаёт ошибку вставки.

Вот так оно работает:

Код:
Function Tr_getTransferData(aFlavor As com.sun.star.datatransfer.DataFlavor)
If (aFlavor.MimeType = "text/plain;charset=utf-16") Then
Tr_getTransferData() = sTxtCString
Else
   Tr_getTransferData = Empty
End If
End Function

tdf#149622
« Последнее редактирование: 19 Июнь 2022, 21:31 от mikekaganski » Записан

С уважением,
Михаил Каганский
sokol92
Мастер
*****
Online Online

Пол: Мужской
Сообщений: 939


WWW
« Ответ #8: 19 Июнь 2022, 21:33 »

Супер!!
Записан

Владимир.
Страниц: 1   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!