Буфер обмена#

В разделе описан буфер обмена как системный механизм операционных систем, а также особенности работы с буфером обмена в системе Global ERP.

Общее описание буфера обмена#

Буфер обмена — это системный механизм передачи данных между приложениями. Он используется при копировании и вставке и позволяет передавать не только текст, но и изображения, файлы и структурированные данные.

Где хранится буфер обмена#

  • В Windows буфер обмена представляет собой централизованное хранилище в оперативной памяти системы. Данные копируются в буфер и сохраняются независимо от приложения-источника. При вставке, например по Ctrl+V, активное приложение запрашивает данные из буфера в нужном формате.

  • В Linux буфер обмена работает как механизм передачи данных между приложениями. Фактически данные хранит приложение-владелец, а не сама система. При вставке активное приложение запрашивает данные у владельца буфера, и тот передает их по запросу. Если приложение-владелец закрывается, данные из буфера могут быть потеряны.

В каком виде хранятся данные#

В Windows данные хранятся как набор форматов CF_*. Например:

  • CF_UNICODETEXT — текст;

  • CF_BITMAP — изображение;

  • CF_HDROP — список файлов.

Одни и те же данные могут одновременно присутствовать в нескольких форматах.

В Linux для представления данных используются MIME-типы. Наиболее распространенные варианты:

  • text/plain;

  • text/html;

  • image/png.

Работа с буфером обмена в системе#

В системе Global ERP используются три сценария работы с буфером обмена:

  • программная запись текста в буфер обмена через метод writeToClipboard;

  • программное чтение текста из буфера обмена через метод readFromClipboard;

  • вставка данных в таблицы и выборки через onClipboardPaste.

Примечание

Копирование и вставка файлов через буфер обмена в системе сейчас недоступны. Возможность находится в процессе разработки.

Запись текста в буфер обмена#

Перед вставкой текстовые или табличные данные должны быть помещены в буфер обмена. Пользователь может сделать это вручную, например через Ctrl+C, а прикладная логика может программно записать текст с помощью метода writeToClipboard.

Метод writeToClipboard используется, когда прикладной логике нужно поместить текст в буфер обмена. После этого пользователь может вставить этот текст в таблицу, выборку или другое приложение через Ctrl+V или команду Вставить.

Метод работает только с текстовым содержимым буфера обмена. Он не записывает файлы, изображения и табличные данные в виде event.file. Для записи текста браузер должен разрешить сайту с прикладным проектом доступ к буферу обмена.

Процесс программной записи выглядит следующим образом:

  1. Прикладная логика вызывает метод writeToClipboard и передает текст для записи.

  2. Браузер проверяет, разрешено ли сайту записывать данные в буфер обмена.

  3. Если разрешение есть, браузер передает текст в системный буфер обмена.

  4. Текст становится доступен для последующей вставки через Ctrl+V или команду Вставить.

Если разрешение на запись отсутствует, текст не будет записан, а сообщение об ошибке будет выведено в логи браузера.

Чтение текста из буфера обмена#

Для программного получения текста из буфера обмена в системе доступен метод readFromClipboard. Метод используется, когда прикладной логике нужно получить текст без пользовательской вставки в грид или выборку через onClipboardPaste.

readFromClipboard работает только с текстовым содержимым буфера обмена. Метод не обрабатывает файлы, изображения и табличную вставку через event.file. Для чтения текста браузер должен разрешить сайту с прикладным проектом доступ к буферу обмена.

Процесс чтения выглядит следующим образом:

  1. Прикладная логика вызывает метод readFromClipboard.

  2. Браузер проверяет, разрешено ли сайту читать данные из буфера обмена.

  3. Если разрешение есть, браузер запрашивает текстовое содержимое буфера обмена.

  4. Операционная система или приложение-владелец буфера возвращает текст.

  5. Полученный текст передается в прикладную логику.

Если разрешение на чтение отсутствует, текст не будет прочитан, а сообщение об ошибке будет выведено в логи браузера.

Вставка данных из буфера обмена#

Вставка данных из буфера обмена используется, когда пользователь вручную вставляет данные в интерфейсе системы, например через Ctrl+V или команду Вставить. Вставка может использоваться для передачи текстовых и табличных данных, например текста из Excel.

Перед вставкой данные уже должны находиться в буфере обмена. На этапе вставки система не наполняет буфер, а запрашивает уже размещенное в нем содержимое и передает его на сервер для обработки.

На сервере обрабатывается само событие вставки, поэтому способ его вызова не имеет значения: через Ctrl+V, команду Вставить в меню приложения или команду вставки браузера.

Процесс вставки выглядит следующим образом:

  1. Пользователь инициирует событие вставки в интерфейсе системы.

  2. Активное приложение запрашивает данные из буфера обмена в одном из поддерживаемых форматов.

  3. Операционная система или приложение-владелец буфера возвращает данные.

  4. Клиентская часть системы передает полученные данные на сервер.

  5. На сервере данные преобразуются во временный файл event.file.

  6. После этого вызывается метод onClipboardPaste, в который передается объект события PasteEvent.

Для корректной работы вставка должна выполняться в контексте редактируемой ячейки или выделенного фрейма, в котором доступна вставка. Если такой контекст отсутствует, вставка не произойдет и обработчик onClipboardPaste вызван не будет.

Если пользователь копирует диапазон ячеек, например из Excel, данные передаются как табличный набор строк и колонок. При дальнейшей обработке система разбирает их построчно и поколоночно, используя символы перевода строки и табуляции как разделители.

Если среди ячеек, в которые выполняется вставка, есть нередактируемые, сервер прерывает операцию и выводит сообщение об ошибке: «Невозможно вставить значения: среди выделенных ячеек есть нередактируемые».

Дальнейшая обработка вставленных данных#

После завершения onClipboardPaste прикладная логика работает не напрямую с содержимым буфера обмена, а с временным файлом event.file, который был сформирован на сервере на основе переданных данных.

Дальнейшая обработка выполняется системно. Система определяет, нужно ли создавать новые записи или обновлять существующие.

Если выделенных записей нет или данные не с чем сопоставить, система проходит по всем строкам, полученным при вставке из буфера обмена, и создает новые объекты.

Если в выборке есть выделенные записи, система обновляет существующие объекты значениями из соответствующих строк.

Для разбора строк используется системная обработка данных в формате TSV (Tab-Separated Values, значения, разделенные табуляцией). TSV — это текстовый табличный формат, в котором каждая строка представляет запись, а столбцы разделяются символом табуляции \t.

Система разбирает строки и распределяет значения по атрибутам.

Алгоритм работы:

  1. Получает список характеристик варианта, отсортированный по nOrder.

  2. Разбивает строку по символу табуляции \t.

  3. Проходит по колонкам.

  4. Для каждой колонки находит соответствующий атрибут по индексу.

  5. Если значение не пустое, устанавливает его через API.

При установке значения учитывается тип данных:

  • для даты при типе idDate значение преобразуется заменой / на . с последующей конвертацией в дату;

  • для мультисправочника и интервала значение разбивается по ;.

Для оптимизации производительности коммит сессии может выполняться пакетно.

Примеры обработки вставленных данных#

Пример 1. Вставка диапазона из Excel

Пользователь копирует диапазон:

A1    B1    C1
A2    B2    C2

В систему данные передаются в виде TSV (Tab-Separated Values, значения, разделенные табуляцией):

A1\tB1\tC1
A2\tB2\tC2

Система разбивает данные на строки и колонки и сопоставляет их с атрибутами.

Пример 2. Вставка одного значения

Пользователь копирует одно значение:

TestValue

Если выбрана одна запись и значение не содержит табуляции, используется стандартная вставка super.onClipboardPaste.

Пример 3. Преобразование типов

Пользователь вставляет строку:

01/12/2025    value1;value2

Система:

  • преобразует дату;

  • разбивает значения;

  • сохраняет данные в атрибуты.

Обработка вставки на примере Btk_Variant#

В примере показана обработка вставленных данных в выборке Btk_Variant.

Основная логика вставки запускается в методе onClipboardPaste. Это обработчик события вставки данных из буфера обмена, который доступен в AVI и может быть переопределен в логике выборки.

После завершения onClipboardPaste дальнейшая обработка выполняется системно: данные из временного файла event.file разбираются и передаются в логику создания или обновления записей.

Объект event: PasteEvent содержит:

  • event.file — временный файл, в который на сервере преобразованы данные из буфера обмена;

  • event.type — тип данных, то есть MIME-type.

При вставке обработка выполняется в таком порядке:

  1. Проверяется наличие файла: event.file != null.

  2. Из файла считываются все строки.

  3. Пустые строки отфильтровываются.

  4. Если данные есть, система запускает дальнейшую обработку вставленных данных.

override def onClipboardPaste(event: PasteEvent): Unit = {
  dialogs.withInfoForm("Идет загрузка объектов") {
    if (event.file != null) {
      val values = Files.readAllLines(event.file.toPath).asScala
      val convertedValues = values.filter(s => s.ns.isNotNullOrEmpty).toSeq

      if (convertedValues.nonEmpty) {
        if (selection.selectedRecordsCount() === 1 && !convertedValues.head.contains('\t')) {
          super.onClipboardPaste(event)
        } else {
          Btk_VariantObjLib().loadFromClipboard(convertedValues, getMasterId)
        }
      }
    }
  }
  selection.refresh()
}

Настройка вставки#

Настройка вставки относится только к сценарию пользовательской вставки данных в таблицы и выборки. Если текст был предварительно записан в буфер обмена методом writeToClipboard, его вставка в таблицу или выборку также обрабатывается через onClipboardPaste. Для программного чтения текста используется метод readFromClipboard.

Поддерживаемые форматы вставки#

Поддерживаются следующие типы:

  • text/plain (Plain Text) — обычный текст без форматирования;

  • application/xml и text/xml — XML-документы;

  • text/html — HTML-документы.

При вставке из Excel данные обычно передаются в формате text/plain как TSV (Tab-Separated Values, значения, разделенные табуляцией): строки разделяются переводом строки, а колонки — символом табуляции.

Настройка выборки#

При настройке выборки нужно указать, какие форматы данных система может принимать. Чаще всего используется обычный текст.

Поддержка вставки данных из буфера обмена настраивается на этапе разработки компонента выборки. Чтобы система корректно принимала данные, необходимо в методе onLoadMeta указать форматы (MIME-типы), которые данная выборка способна обработать.

Система проверяет список selection.clipboard.pasteMimeTypes при инициализации выборки и использует его для фильтрации данных при последующих операциях вставки.

Пример настройки выборки:

override def onLoadMeta(): Unit = {
  super.onLoadMeta()

  // Указываем поддерживаемые форматы буфера обмена
  // Приоритет обработки: слева направо
  selection.clipboard.pasteMimeTypes = Seq(MimeType.textPlain)
}

Ограничения при работе по HTTP#

При работе по HTTP доступ к буферу обмена зависит от адреса, по которому открыт сайт, и от правил конкретного браузера.

Если сайт открыт через публичный адрес, большинство браузеров блокируют возможность настройки разрешений на чтение и запись в буфер обмена. В этом случае методы readFromClipboard и writeToClipboard не смогут получить доступ к буферу обмена.

Если сайт открыт через localhost, большинство браузеров разрешают настройку доступа к чтению и записи в буфер обмена.

Примечание

Поведение зависит от спецификации и настроек используемого браузера.