Как настроить перетаскивание строк между табличными полями на обычных формах в 1С?

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

При разработке интерфейсов на обычных формах 1С часто возникает задача реализовать механизм перетаскивания строк (Drag-and-Drop) из одной таблицы в другую. Однако после включения свойств элементов управления РазрешитьНачалоПеретаскивания у таблицы-источника и РазрешитьПеретаскивание у таблицы-приемника разработчики нередко сталкиваются с тем, что курсор мыши при наведении показывает знак запрета («стоянка запрещена»), а события вставки не срабатывают. Разберем по шагам, как устроен механизм перетаскивания в платформе 1С, почему возникает блокировка и как правильно реализовать перенос данных программно.

Схема возникновения событий перетаскивания

Чтобы понять, в какой момент платформа запрещает действие, проанализируем стандартный жизненный цикл перетаскивания в 1С:

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

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

Рассмотрим основные причины, из-за которых платформа блокирует перетаскивание между двумя табличными полями:

  1. Не отключена стандартная обработка событий в приемнике. По умолчанию платформа 1С считает допустимым перетаскивание только внутри одной и той же таблицы (для интерактивного изменения порядка строк). При попытке бросить строку в другую таблицу стандартный механизм распознает несовместимость типов и принудительно запрещает действие. Чтобы переопределить это поведение, в событиях ПроверкаПеретаскивания и Перетаскивание необходимо явно указывать СтандартнаяОбработка = Ложь;.
  2. Несоответствие типов действий. Если в источнике по умолчанию разрешено только ДействиеПеретаскивания.Копирование, а в проверке приемника жестко задано ДействиеПеретаскивания.Перемещение, платформа отобразит запрет. В обработчике источника следует явно разрешить нужные действия или использовать комбинацию флагов.
  3. Блокировка редактирования таблицы. Если у табличного поля-приемника или у формы включено свойство ТолькоПросмотр = Истина, либо выключена Доступность, перетаскивание будет заблокировано на уровне интерфейса.

Пошаговая программная реализация Drag-and-Drop

Разберем пример реализации переноса строк между двумя табличными полями обработки (ТабличноеПолеИсточник и ТабличноеПолеПриемник).

Шаг 1. Настройка свойств элементов управления

В конфигураторе для ТабличноеПолеИсточник устанавливаем свойство РазрешитьНачалоПеретаскивания в значение Истина. Для ТабличноеПолеПриемник включаем свойство РазрешитьПеретаскивание в значение Истина.

Шаг 2. Обработка начала перетаскивания в источнике

В модуле формы создадим обработчик события НачалоПеретаскивания для исходной таблицы. Передадим структуру переносимых данных и разрешим перемещение:


Процедура ТабличноеПолеИсточникНачалоПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
    
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Недоступно;
        Возврат;
    КонецЕсли;
    
    // Формируем структуру с данными переносимой строки
    ДанныеСтроки = Новый Структура;
    ДанныеСтроки.Вставить("Номенклатура", ТекущиеДанные.Номенклатура);
    ДанныеСтроки.Вставить("Количество",   ТекущиеДанные.Количество);
    ДанныеСтроки.Вставить("Цена",         ТекущиеДанные.Цена);
    
    // Передаем значение и разрешаем перемещение и копирование
    ПараметрыПеретаскивания.Значение = ДанныеСтроки;
    ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение | ДействиеПеретаскивания.Копирование;
    
КонецПроцедуры

Шаг 3. Проверка перетаскивания в таблице-приемнике

Создадим обработчик события ПроверкаПеретаскивания для целевого табличного поля. Отключим стандартную обработку, проверим тип данных и сообщим платформе о готовности принять строку:


Процедура ТабличноеПолеПриемникПроверкаПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    
    СтандартнаяОбработка = Ложь;
    
    // Проверяем, что переносится ожидаемая структура данных
    Если ТипЗнч(ПараметрыПеретаскивания.Значение) = Тип("Структура") Тогда
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение;
    Иначе
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Недоступно;
    КонецЕсли;
    
КонецПроцедуры

Шаг 4. Обработка вставки данных в приемнике

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


Процедура ТабличноеПолеПриемникПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
    
    СтандартнаяОбработка = Ложь;
    
    Если ТипЗнч(ПараметрыПеретаскивания.Значение) = Тип("Структура") Тогда
        ДанныеСтроки = ПараметрыПеретаскивания.Значение;
        
        НоваяСтрока = ЭтотОбъект.ТабличнаяЧастьПриемник.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ДанныеСтроки);
        
        // Устанавливаем действие, чтобы источник знал о завершении перемещения
        ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение;
    КонецЕсли;
    
КонецПроцедуры

Шаг 5. Удаление строки из источника (при необходимости перемещения)

Если требуется физически удалить строку из первой таблицы после успешного переноса, используем событие ОкончаниеПеретаскивания в таблице-источнике:


Процедура ТабличноеПолеИсточникОкончаниеПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
    
    Если ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение Тогда
        ТекущиеДанные = Элемент.ТекущиеДанные;
        Если ТекущиеДанные <> Неопределено Тогда
            ЭтотОбъект.ТабличнаяЧастьИсточник.Удалить(ТекущиеДанные);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Особенности отображения иерархии в дереве значений

Если в процессе разработки вы сталкиваетесь с тем, что табличное поле типа ДеревоЗначений отображает только строки верхнего уровня и не показывает вложенные узлы, обратите внимание на следующие нюансы:

  1. Свойство колонки ОтображатьИерархию: у ведущей колонки дерева (как правило, первой) обязательно должен стоять признак ОтображатьИерархию. Без этого флажка пиктограммы раскрытия («плюсики») не отображаются, и дерево визуально выглядит как плоская таблица.
  2. Программное раскрытие узлов: при заполнении дерева строки по умолчанию создаются свернутыми. Чтобы показать подчиненные элементы, используйте метод: ЭлементыФормы.ТабличноеПолеДерево.Развернуть(СтрокаДерева, Истина);
  3. Сбой метаданных колонок в конфигураторе: при изменении типа табличного поля с ТаблицаЗначений на ДеревоЗначений конфигуратор не всегда автоматически перестраивает свойства существующих колонок. В такой ситуации помогает пересоздание колонок через контекстное меню элемента либо создание нового элемента управления с нуля.

Таким образом, ключевым условием корректной работы Drag-and-Drop между таблицами на обычных формах является полное переопределение стандартной обработки через СтандартнаяОбработка = Ложь; во всех целевых обработчиках и согласование допустимых действий между источником и приемником.

← На главную