Как заполнить реквизиты таблицы значений на форме данными выбранного элемента справочника?

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

В процессе разработки на платформе 1С:Предприятие 8.3 (особенно на управляемых формах) программисты часто сталкиваются с задачей: пользователь выбирает элемент справочника в одной из колонок таблицы значений, и система должна автоматически «подтянуть» связанные данные в соседние колонки. Например, при выборе номенклатуры должны заполниться цена, единица измерения или артикул.

В этой статье мы подробно разберем, как правильно организовать передачу данных между клиентом и сервером, какие методы платформы использовать для оптимизации и как избежать типичных ошибок, связанных с контекстом формы.

Постановка задачи и анализ ограничений

Представим ситуацию: на управляемой форме есть реквизит типа ТаблицаЗначений. В первой колонке (например, «Товар») выбирается ссылка на справочник. Нам нужно заполнить остальные колонки («Цена», «ЕдИзм») сразу после выбора. Основная сложность заключается в том, что:

  1. На клиенте мы видим только ссылку. Мы не можем обратиться через точку к реквизитам объекта (например, Товар.Артикул), так как это вызовет неявное обращение к серверу, что недопустимо в тонком клиенте или веб-клиенте.
  2. На сервере (в контекстных вызовах) доступна вся форма, но чрезмерная передача контекста (всей таблицы значений) замедляет работу интерфейса.
  3. Идентификация строки: методы работы с текущей строкой на клиенте и сервере различаются, и важно не перепутать индекс строки с ее уникальным идентификатором.

Рассмотрим несколько эффективных способов решения этой задачи.

Вариант 1. Визуальное отображение через «Путь к данным» (без программирования)

Если ваша задача — просто показать данные справочника в таблице, не сохраняя их физически в реквизитах таблицы значений (например, артикул, который всегда фиксирован), можно воспользоваться механизмом путей к данным.

Разберем этот метод по шагам:

  1. Добавьте в таблицу на форме новую колонку (поле ввода или поле надписи).
  2. В свойстве ПутьКДанным укажите путь через точку от основной колонки. Например: Элементы.Таблица1.ТекущиеДанные.Номенклатура.Артикул.

Платформа 1С самостоятельно обеспечит получение этих данных с сервера и их отображение. Важно помнить: эти данные будут доступны только для чтения, и они не хранятся в самой таблице значений. Если вам нужно изменять эти данные или сохранять их независимо от справочника, этот метод не подойдет.

Вариант 2. Программное заполнение через серверный вызов без контекста

Это наиболее правильный и производительный метод с точки зрения архитектуры управляемого приложения. Мы минимизируем объем передаваемых данных, отправляя на сервер только ссылку, а обратно — структуру с нужными значениями.

Рассмотрим пример реализации в обработчике события ПриИзменении колонки таблицы:


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

&НаСервереБезКонтекста
Функция ПолучитьДанныеТовараНаСервере(СсылкаТовар)
    
    Результат = Новый Структура("Цена, ЕдиницаИзмерения");
    
    // Используем запрос для максимальной производительности
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Номенклатура.Цена КАК Цена,
        |   Номенклатура.ЕдиницаХранения КАК ЕдиницаИзмерения
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |   Номенклатура.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", СсылкаТовар);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        ЗаполнитьЗначенияСвойств(Результат, Выборка);
    КонецЕсли;
    
    Возврат Результат;
    
КонецФункции

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

Вариант 3. Заполнение на сервере с использованием идентификатора строки

Иногда логика заполнения настолько сложна (например, требуется пересчет итогов по всей таблице или обращение к другим реквизитам формы), что приходится использовать контекстный вызов &НаСервере. В этом случае крайне важно правильно найти строку, которую мы редактируем.

Выясним причину, по которой нельзя использовать «номер строки»: при сортировке или фильтрации индекс строки в визуальном элементе может не совпадать с индексом в коллекции данных. Правильный путь — использование идентификатора.


&НаКлиенте
Процедура Таблица1ТоварПриИзменении(Элемент)
    
    // Получаем уникальный идентификатор текущей строки
    ИдентификаторСтроки = Элементы.Таблица1.ТекущаяСтрока;
    
    Если ИдентификаторСтроки <> Неопределено Тогда
        ЗаполнитьСтрокуНаСервере(ИдентификаторСтроки);
    КонецЕсли;
    
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьСтрокуНаСервере(ИдентификаторСтроки)
    
    // Находим строку в данных формы по идентификатору
    СтрокаТЗ = Объект.Таблица1.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если СтрокаТЗ <> Неопределено Тогда
        // Здесь можно обращаться к реквизитам справочника через точку (внутри сервера)
        // Но лучше использовать запрос для оптимизации
        СтрокаТЗ.Цена = СтрокаТЗ.Товар.ОсновнаяЦена;
        СтрокаТЗ.ЕдиницаИзмерения = СтрокаТЗ.Товар.ЕдиницаИзмерения;
        
        // Пример дополнительной логики:
        СтрокаТЗ.Сумма = СтрокаТЗ.Количество * СтрокаТЗ.Цена;
    КонецЕсли;
    
КонецПроцедуры

Рекомендации по оптимизации

При реализации подобных механизмов стоит придерживаться следующих правил:

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

Таким образом, выбор метода зависит от ваших целей: для простого показа данных используйте Путь к данным, для полноценного заполнения — внеконтекстный серверный вызов со структурой, а для сложной бизнес-логики — контекстный серверный вызов с поиском строки по идентификатору.

← На главную