При разработке и кастомизации управляемых форм в 1С:Предприятии программисты часто сталкиваются с ситуацией, когда стандартные события табличных частей ведут себя непредсказуемо. Типичный пример — событие ПриНачалеРедактирования для табличной части РасшифровкаПлатежа в документах «Списание с расчетного счета» и «Поступление на расчетный счет» в конфигурации «Бухгалтерия предприятия».
Разработчики замечают странное поведение: в одном документе («Поступление на РС») при копировании строки (по клавише F9) событие ПриНачалеРедактирования срабатывает стабильно, а в другом («Списание с РС») — игнорируется платформой, срабатывая только при обычном интерактивном редактировании существующей строки. Более того, данное поведение может меняться при обновлении платформы 1С:Предприятие (например, корректно работать на релизе 8.3.10.2580 и ломаться на 8.3.13.1513).
В этой статье мы подробно разберем, почему возникает данная проблема, и рассмотрим три надежных способа обхода этого поведения без необходимости изменять версию платформы 1С.
---
Для того чтобы понять, почему событие ведет себя по-разному в схожих документах, проанализируем внутренние механизмы платформы 1С:Предприятие 8.3:
ТолькоПросмотр = Истина), платформа считает, что редактировать нечего, и физически не инициирует событие ПриНачалеРедактирования. В «Списании с расчетного счета» состав и доступность колонок жестко управляются программным кодом формы в зависимости от выбранного вида операции. Если логика формы блокирует элементы, событие подавляется.ПриНачалеРедактирования «теряется».Попытка использовать стандартное событие ПередНачаломДобавления напрямую сталкивается со следующей сложностью: в этом обработчике новая строка еще физически не создана. Параметр НоваяСтрока в нем отсутствует, а свойство Элемент.ТекущиеДанные все еще указывает на строку-источник, с которой происходит копирование. Нам необходимы обходные пути.
---
Этот подход является наиболее надежным, так как мы полностью берем под контроль процесс копирования строки, отменяя стандартное поведение платформы. Этот метод гарантирует стабильную работу на любых релизах платформы 1С.
Разберем реализацию по шагам:
1. В свойствах таблицы управляемой формы находим событие ПередНачаломДобавления и создаем для него обработчик на клиенте.
2. Проверяем, если параметр Копирование равен Истина, мы взводим отказ от стандартного действия платформы (Отказ = Истина) и выполняем копирование программно.
Посмотрим на пример реализации кода:
&НаКлиенте
Процедура РасшифровкаПлатежаПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрыШаблона)
Если Копирование Тогда
// Отменяем стандартное копирование платформы
Отказ = Истина;
// Получаем исходную строку, которую пользователь пытается скопировать
ИсходнаяСтрока = Элемент.ТекущиеДанные;
Если ИсходнаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Программно добавляем новую строку в коллекцию ТЧ на клиенте
НоваяСтрока = Объект.РасшифровкаПлатежа.Добавить();
// Копируем значения всех свойств из исходной строки в новую
ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяСтрока);
// Выполняем действия, которые должны были произойти при начале редактирования новой строки.
// Например, очищаем уникальные идентификаторы или пересчитываем суммы.
ИнициализироватьНовуюСтрокуРасшифровки(НоваяСтрока);
// Активизируем только что созданную строку на форме
Элементы.РасшифровкаПлатежа.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецЕсли;
КонецПроцедуры
Для инициализации значений в новой строке создадим вспомогательную процедуру, в которой пропишем всю необходимую логику, которая ранее содержалась в ПриНачалеРедактирования:
&НаКлиенте
Процедура ИнициализироватьНовуюСтрокуРасшифровки(НоваяСтрока)
// Пример: при копировании строки нам нужно очистить сумму платежа или пересчитать ставку НДС
НоваяСтрока.СуммаПлатежа = 0;
// Здесь же вызываем любые экспортные процедуры общих модулей для расчета параметров строки
КонецПроцедуры
---
Если нам критически важно сохранить стандартный интерактивный механизм копирования платформы (например, чтобы отрабатывали системные триггеры СУБД или сложные внутренние механизмы формы), мы можем применить асинхронный вызов через обработчик ожидания.
Идея заключается в следующем: в момент копирования мы запоминаем этот факт в переменной модуля формы, а затем с минимальной задержкой в 0.1 секунды вызываем процедуру инициализации, когда строка уже физически создана платформой.
Проанализируем этот алгоритм на практике:
1. Объявим переменную в самом верху модуля управляемой формы:
&НаКлиенте
Перем ФлагКопированияСтроки;
2. Напишем код для события ПередНачаломДобавления:
&НаКлиенте
Процедура РасшифровкаПлатежаПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрыШаблона)
Если Копирование Тогда
// Устанавливаем флаг, сигнализирующий о процессе копирования
ФлагКопированияСтроки = Истина;
// Подключаем однократный обработчик ожидания с минимальным интервалом
ПодключитьОбработчикОжидания("Подключаемый_ПослеКопированияСтроки", 0.1, Истина);
КонецЕсли;
КонецПроцедуры
3. Опишем подключаемую процедуру, которая выполнится сразу после того, как платформа завершит создание строки и передаст управление интерфейсу:
&НаКлиенте
Процедура Подключаемый_ПослеКопированияСтроки()
Если ФлагКопированияСтроки = Истина Тогда
// Сбрасываем флаг, чтобы исключить повторные срабатывания
ФлагКопированияСтроки = Ложь;
// На данный момент строка уже создана и является текущей в таблице формы
ТекущиеДанные = Элементы.РасшифровкаПлатежа.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Вызываем логику обработки новой скопированной строки
ИнициализироватьНовуюСтрокуРасшифровки(ТекущиеДанные);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
---
Этот вариант подходит для конфигураций с высокой интерактивностью интерфейса, где обработчики ожидания могут вызывать нежелательные задержки или прерывать ввод пользователя.
Метод заключается в отслеживании момента, когда фокус формы перемещается на новую строку сразу после инициализации копирования. Как и в Варианте Б, мы используем переменную модуля формы для отслеживания состояния.
Реализуем данный метод по шагам:
1. В модуле формы объявляем переменную ФлагКопированияСтроки.
2. В обработчике события таблицы ПередНачаломДобавления взводим флаг:
&НаКлиенте
Процедура РасшифровкаПлатежаПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, ПараметрыШаблона)
Если Копирование Тогда
ФлагКопированияСтроки = Истина;
КонецЕсли;
КонецПроцедуры
3. В событии таблицы ПриАктивизацииСтроки перехватываем управление:
&НаКлиенте
Процедура РасшифровкаПлатежаПриАктивизацииСтроки(Элемент)
Если ФлагКопированияСтроки = Истина Тогда
ФлагКопированияСтроки = Ложь; // Сбрасываем состояние
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Строка скопирована и активизирована, выполняем ее инициализацию
ИнициализироватьНовуюСтрокуРасшифровки(ТекущиеДанные);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
---
Мы рассмотрели три эффективных метода решения проблемы, когда событие ПриНачалеРедактирования игнорируется платформой 1С при копировании строк табличной части.
Для большинства задач автоматизации в управляемых формах Вариант А (программное копирование) является наиболее предпочтительным. Он полностью прозрачен, не зависит от поведения платформы при работе с фокусом ввода и исключает любые задержки интерфейса, которые могут возникать при использовании обработчиков ожидания. Используйте этот метод, чтобы обеспечить стабильную и быструю работу ваших кастомных алгоритмов в документах движения денежных средств.