Как перехватить нажатия Ctrl+C и Ctrl+V в окне табличного документа 1С для своей обработки вставки?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с табличным документом в 1С часто вызывает у пользователей ассоциации с Excel. Они ожидают привычного поведения: скопировал область, вставил, и все работает. Однако стандартный механизм вставки в 1С (Ctrl+V) копирует не только значения, но и форматирование (рамки, шрифты, цвета), что часто разрушает макет отчета или печатной формы. Более того, иногда требуется валидировать вставляемые данные или вставлять только значения в защищенные области.

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

Почему не работает стандартное событие «ПриВставкеИзБуфераОбмена»?

Первое, что приходит в голову разработчику — использовать штатное событие управляемой формы или табличного документа. Давайте проанализируем ситуацию с событием ПриВставкеИзБуфераОбмена.

Согласно документации и опыту сообщества, это событие действительно существует. Однако, как верно замечено в обсуждении, оно имеет существенное ограничение:

Событие срабатывает только при вставке специфических объектов, таких как картинки или файлы.

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

Стратегия 1: Перехват через Команду формы (Рекомендуемый способ для Windows)

Самый эффективный способ перехватить нажатие клавиш без использования внешних компонент (Native API) — это использование приоритета команд формы (в некоторых случаях может потребоваться программное изменение форм).

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

Шаг 1. Создание команды

В редакторе формы перейдем на вкладку «Команды». Создадим новую команду, назовем ее, например, ВставитьИзБуфераСпециальная. В свойствах этой команды найдем поле Сочетание клавиш и установим там Ctrl+V.

Шаг 2. Получение данных из буфера обмена

Здесь кроется главная сложность: перехватить нажатие мы смогли, но 1С не передает содержимое буфера в обработчик команды автоматически. Нам нужно извлечь его самостоятельно.

Для операционных систем Windows (клиентское приложение) мы можем использовать COM-объект htmlfile. Это позволяет обратиться к системному буферу обмена через механизм Internet Explorer, который есть в системе. В более сложных сценариях можно даже реализовать свой COM объект на Python.

Рассмотрим пример кода обработчика команды:


&НаКлиенте
Процедура ВставитьИзБуфераСпециальная(Команда)
    
    // Пытаемся получить текст из буфера обмена
    ТекстБуфера = "";
    Попытка
        // Создаем легковесный COM-объект для доступа к буферу
        HTMLОбертка = Новый COMОбъект("htmlfile");
        // Получаем текст. Метод getData("Text") вернет содержимое буфера
        ТекстБуфера = HTMLОбертка.parentWindow.clipboardData.getData("Text");
    Исключение
        Сообщить("Не удалось прочитать буфер обмена: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    Если ЗначениеЗаполнено(ТекстБуфера) Тогда
        ОбработатьВставкуТекста(ТекстБуфера);
    КонецЕсли;

КонецПроцедуры

Шаг 3. Парсинг и вставка данных

Данные из Excel или другой таблицы приходят в буфер обмена в виде текста, где строки разделены символом переноса строки (Символы.ПС), а колонки — знаком табуляции (Символы.Таб).

Разберем алгоритм обработки такой строки:


&НаКлиенте
Процедура ОбработатьВставкуТекста(Знач ТекстВставки)
    
    // Определяем текущую активную область, куда пользователь хочет вставить данные
    ТекущаяОбласть = Элементы.ТабличныйДокумент.ТекущаяОбласть;
    Если ТекущаяОбласть.ТипОбласти <> ТипОбластиЯчеекТабличногоДокумента.Прямоугольник Тогда
        Возврат; // Вставка возможна только в ячейки
    КонецЕсли;
    
    Верх = ТекущаяОбласть.Верх;
    Лево = ТекущаяОбласть.Лево;
    
    // Разбиваем текст на строки
    МассивСтрок = СтрРазделить(ТекстВставки, Символы.ПС, Ложь);
    
    Для ИндексСтр = 0 По МассивСтрок.Количество() - 1 Цикл
        
        ТекущаяСтрокаТекста = МассивСтрок[ИндексСтр];
        // Разбиваем строку на колонки по табуляции
        МассивКолонок = СтрРазделить(ТекущаяСтрокаТекста, Символы.Таб, Ложь);
        
        Для ИндексКол = 0 По МассивКолонок.Количество() - 1 Цикл
            
            ЗначениеЯчейки = МассивКолонок[ИндексКол];
            
            // Вычисляем координаты целевой ячейки
            ЦелеваяСтрока = Верх + ИндексСтр;
            ЦелеваяКолонка = Лево + ИндексКол;
            
            // Получаем область одной ячейки
            ОбластьПриемник = Элементы.ТабличныйДокумент.Область(ЦелеваяСтрока, ЦелеваяКолонка, ЦелеваяСтрока, ЦелеваяКолонка);
            
            // Вставляем ТОЛЬКО ЗНАЧЕНИЕ, не трогая форматирование
            // Здесь можно добавить проверки: число ли это, входит ли в допустимый диапазон и т.д.
            ОбластьПриемник.Текст = ЗначениеЯчейки; 
            // Или ОбластьПриемник.Значение = ..., если нужно типизированное значение
            
        КонецЦикла;
        
    КонецЦикла;

КонецПроцедуры

Важное примечание: Данный метод через htmlfile работает только в тонком клиенте под Windows. Для веб-клиента потребуется иной подход.

Стратегия 2: Использование HTML-поля (Кроссплатформенный подход)

Если мы хотим, чтобы решение работало не только в Windows или если политики безопасности блокируют COM-объекты, можно использовать "мостик" через поле HTML-документа.

  1. Добавляем на форму реквизит типа Строка с видом Поле HTML документа. Делаем его невидимым (или минимального размера), но он должен присутствовать в DOM-дереве формы.
  2. В макет HTML-документа внедряем JavaScript, который умеет работать с navigator.clipboard.readText() (современный стандарт) или через создание скрытого textarea.
  3. При нажатии нашей команды (Ctrl+V) мы вызываем функцию JavaScript в этом поле, которая читает буфер и возвращает результат в 1С через событие нажатия скрытой кнопки или изменение контекста.

Это более сложный путь, требующий знания JavaScript, но он наиболее надежен для веб-клиента.

Стратегия 3: Пост-обработка (Событие «ПриИзмененииСодержимогоОбласти»)

Если перехватить нажатие клавиш не удается (например, из-за специфики RDP или ограничений прав), можно пойти другим путем: позволить 1С вставить данные "как есть", а затем мгновенно исправить результат.

Используем событие табличного документа ПриИзмененииСодержимогоОбласти.

Проблема: Когда это событие срабатывает, форматирование уже может быть испорчено (вставка с рамками из Excel). В 1С программно нет функции "Отменить" (Undo) для возврата форматирования.

Решение: Хранить эталон.

  1. Иметь скрытый макет или структуру данных, где хранится "правильное" форматирование для редактируемых ячеек.
  2. В событии ПриИзмененииСодержимогоОбласти:
    • Считываем новые значения, которые вставил пользователь.
    • Очищаем область или восстанавливаем форматирование из эталона (шрифт, цвет, границы).
    • Записываем значения обратно.

Пример логики:


&НаКлиенте
Процедура ТабличныйДокументПриИзмененииСодержимогоОбласти(Элемент, Область)
    
    // Внимание: событие может зациклиться, если мы будем менять данные внутри него.
    // Нужен флаг блокировки.
    Если БлокировкаСобытия Тогда Возврат; КонецЕсли;
    
    БлокировкаСобытия = Истина;
    
    // Анализируем вставленные данные
    // Если видим, что сбилось форматирование (например, появились рамки),
    // применяем стиль "по умолчанию" для этой области.
    
    // Пример упрощенный: просто сбрасываем рамку
    Область.ГраницаСверху = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.НетЛинии);
    // ... и так далее для других свойств
    
    БлокировкаСобытия = Ложь;

КонецПроцедуры

Резюме и рекомендации

Для реализации задачи "Вставить только значения" в табличный документ 1С:

  1. Создайте Команду формы и назначьте ей сочетание Ctrl+V. Это заблокирует стандартную вставку.
  2. В обработчике команды используйте COMОбъект("htmlfile") (для Windows) для получения чистого текста из буфера.
  3. Распарсите полученный текст (разделяя по Символы.ПС и Символы.Таб) и программно заполните свойства Текст или Значение ячеек, не затрагивая их оформление.
  4. Для защиты от Ctrl+C (копирования) аналогично создайте команду с этим сочетанием и оставьте ее пустой или реализуйте свою логику копирования в буфер через тот же COM-объект (метод setData).

Этот подход позволяет гибко управлять процессом, проверять данные перед вставкой (например, запрещать вставку текста в числовые поля) и сохранять красивый внешний вид ваших таблиц.

← На главную