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