Часто при разработке на платформе 1С возникает задача: создать внешнюю обработку заполнения табличной части (ТЧ), которая будет ориентироваться на ту ячейку, в которой находился курсор пользователя до нажатия кнопки заполнения. Проанализируем ситуацию: пользователь выделил конкретное поле, нажал кнопку, и мы хотим скопировать значение из этой ячейки во все остальные строки этой же колонки. Разберем по шагам, как получить доступ к этим данным в обычных и управляемых формах, а также рассмотрим подводные камни программного заполнения.
В обычных формах при использовании стандартного механизма внешних обработок заполнения ТЧ используется экспортная процедура Инициализировать. В нее передается параметр ТабличноеПоле (или ТабличноеПолеОбъекта), который содержит ссылку на элемент управления формы.
Выясним причину, почему отладчик иногда не показывает внутренности этого объекта: пока форма не открыта и контекст не передан полностью, свойства могут быть недоступны. Однако мы точно знаем, что у этого элемента есть нужные нам свойства. Чтобы получить значения текущей строки и колонки, используются следующие конструкции:
ТабличноеПолеОбъекта.ТекущиеДанные — возвращает структуру с данными текущей выделенной строки.ТабличноеПолеОбъекта.ТекущаяКолонка.Имя — возвращает строковое представление имени колонки, в которой стоит курсор.Посмотрим на пример простейшего кода, который берет значение из выделенной ячейки и заполняет им всю колонку в табличной части:
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
// Получаем значение из ячейки, где стоял курсор
нЗначение = ТабличноеПолеОбъекта.ТекущиеДанные[ТабличноеПолеОбъекта.ТекущаяКолонка.Имя];
// Заполняем все строки в столбце ТЧ полученным значением
Для Каждого нСтрока Из Объект[ИмяТабличнойЧасти] Цикл
нСтрока[ТабличноеПолеОбъекта.ТекущаяКолонка.Имя] = нЗначение;
КонецЦикла;
КонецПроцедуры
Рассмотрим подробнее уязвимость приведенного выше базового кода. Если пользователь запустит обработку в пустой табличной части (где нет ни одной строки) или фокус вообще не установлен на элемент таблицы, свойство ТабличноеПолеОбъекта.ТекущиеДанные вернет значение Неопределено. Попытка получить данные по индексу колонки из значения Неопределено приведет к критической ошибке.
Чтобы избежать аварийного завершения работы обработки, добавим проверку наличия текущих данных:
Если ТабличноеПолеОбъекта.ТекущиеДанные = Неопределено Тогда
Сообщить("Не выбрана строка для получения значения!");
Возврат;
КонецЕсли;
При массовом заполнении данных всегда есть риск того, что пользователь нажал кнопку случайно и испортил существующие данные во всей колонке. Хорошей практикой является запрос подтверждения.
Используем метод ВвестиЗначение, который выведет пользователю диалоговое окно с предложением подтвердить или скорректировать заполняемое значение. Посмотрим на доработанный пример:
Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
Если ТабличноеПолеОбъекта.ТекущиеДанные = Неопределено Тогда
Сообщить("Не выбрана строка для получения значения!");
Возврат;
КонецЕсли;
ИмяКолонки = ТабличноеПолеОбъекта.ТекущаяКолонка.Имя;
нЗначение = ТабличноеПолеОбъекта.ТекущиеДанные[ИмяКолонки];
ОписаниеТипаЗначения = ТипЗнч(нЗначение);
// Запрашиваем подтверждение у пользователя
Если ВвестиЗначение(нЗначение, "Укажите значение для заполнения колонки:", ОписаниеТипаЗначения) Тогда
Для Каждого нСтрока Из Объект[ИмяТабличнойЧасти] Цикл
нСтрока[ИмяКолонки] = нЗначение;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Проанализируем еще одну важную деталь. При программном заполнении значений через прямое присвоение (например, нСтрока[ИмяКолонки] = нЗначение;) стандартные события элементов управления формы не отрабатывают. Событие ПриИзменении для колонки не будет вызвано.
Что это значит на практике? Если в документе есть логика пересчета (например, при изменении количества должна автоматически пересчитываться сумма строки), то при использовании внешней обработки суммы останутся старыми. Вам необходимо самостоятельно прописывать вызов нужных процедур или дублировать логику пересчета внутри цикла обработки.
Рассмотрим, как обстоят дела в Управляемых формах (УФ). Для них конструкция получения текущего элемента выглядит иначе:
// Получение имени колонки в УФ на клиенте:
ИмяТекущейКолонки = Элементы.ИмяТаблицыФормы.ТекущийЭлемент.Имя;
Однако в современных конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) для внешних обработок заполнения процедура Инициализировать больше не используется. Вместо этого применяется функция СведенияОВнешнейОбработке, а само выполнение происходит в серверной процедуре ВыполнитьКоманду.
Поскольку процедура ВыполнитьКоманду выполняется на сервере, у нас нет прямого доступа к клиентским элементам формы (Элементы) и мы не знаем, на какой ячейке стоял курсор. Чтобы реализовать подобный функционал в УФ, потребуется вносить изменения в код самой конфигурации, передавая данные о текущей колонке с клиента на сервер при вызове команды обработки. Описанный выше универсальный и простой механизм работает "из коробки" только для Обычных форм.