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