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