Как реализовать автоматическую подстановку единицы измерения при выборе номенклатуры?

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

При разработке конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача автоматизации ввода данных. Одной из самых распространенных операций является автоматическое заполнение единицы измерения сразу после того, как пользователь выбрал товар (номенклатуру) в табличной части документа. Это не только ускоряет работу оператора, но и минимизирует риск возникновения ошибок учета.

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

Почему «Связи параметров выбора» не подходят для этой задачи?

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

Однако этот механизм не умеет подставлять значение в пустое поле самостоятельно. Для того чтобы значение «прилетело» в строку документа автоматически в момент выбора номенклатуры, необходимо использовать событийную модель встроенного языка.

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

Основной инструмент для решения нашей задачи — обработчик события ПриИзменении для поля Номенклатура в табличной части формы. Разберем по шагам, как это реализовать в управляемом приложении.

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

Рассмотрим пример кода, который является наиболее простым и эффективным для конфигураций, где единица измерения является реквизитом справочника номенклатуры:


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

    // Вызываем серверную функцию для получения базовой единицы
    ТекущаяСтрока.ЕдиницаИзмерения = ПолучитьБазовуюЕдиницуНаСервере(ТекущаяСтрока.Номенклатура);
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьБазовуюЕдиницуНаСервере(Знач ВыбраннаяНоменклатура)
    
    // Возвращаем реквизит напрямую через точку (простой способ)
    Возврат ВыбраннаяНоменклатура.БазоваяЕдиница;
    
КонецФункции

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

Использование запроса для получения данных

Если ваша конфигурация предполагает сложную логику (например, единица измерения зависит от подразделения, склада или вида операции), получение данных «через точку» может быть не самым лучшим вариантом. Проанализируем ситуацию, когда необходимо использовать объект Запрос. Это позволяет избежать неявного считывания всего объекта номенклатуры из базы данных, что полезно при работе в высоконагруженных системах.

Рассмотрим пример реализации функции с запросом:


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

Продвинутые методы оптимизации (БСП и пакетное получение данных)

В профессиональной разработке, особенно при использовании Библиотеки стандартных подсистем (БСП), принято получать не один реквизит, а сразу целый набор данных (цену, ставку НДС, единицу измерения), чтобы минимизировать количество серверных вызовов.

Проанализируем преимущества использования общих модулей БСП. Вместо написания своего запроса, мы можем использовать метод ОбщегоНазначения.ЗначенияРеквизитовОбъекта(). Это сделает код чище и профессиональнее:


&НаСервереБезКонтекста
Функция ПолучитьДанныеНоменклатуры(Номенклатура)
    // Используем стандартный механизм БСП для получения структуры реквизитов
    Возврат ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Номенклатура, "БазоваяЕдиница, СтавкаНДС, СтатьяРасходов");
КонецФункции

На клиенте мы просто разложим полученную структуру по полям строки табличной части:


&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
    СтрокаТЧ = Элементы.Товары.ТекущиеДанные;
    Данные = ПолучитьДанныеНоменклатуры(СтрокаТЧ.Номенклатура);
    
    СтрокаТЧ.ЕдиницаИзмерения = Данные.БазоваяЕдиница;
    СтрокаТЧ.СтавкаНДС = Данные.СтавкаНДС;
КонецПроцедуры

Важные нюансы и обработка исключений

Разберем несколько важных моментов, о которых часто забывают при реализации автоподстановки:

  1. Очистка полей: Всегда предусматривайте поведение системы при удалении значения из поля номенклатуры. Если пользователь стер товар, зависимые поля (единица, цена) также должны быть очищены или обнулены.
  2. Тип данных: Убедитесь, что реквизит БазоваяЕдиница в справочнике Номенклатура совпадает по типу с реквизитом ЕдиницаИзмерения в вашей табличной части. Обычно это ссылка на справочник ЕдиницыИзмерения или КлассификаторЕдиницИзмерения.
  3. Копирование строк: Проверьте, как ведет себя система при копировании строки табличной части (событие ПриКопировании). Иногда требуется пересчет данных или повторная проверка актуальности единиц.
  4. Упаковки: Если в вашей программе ведется учет в упаковках (например, в УТ 11 или ERP), логика может быть сложнее. Система должна проверять, используется ли индивидуальный набор упаковок, и подставлять либо единицу хранения, либо наиболее подходящую упаковку по умолчанию.

Выяснив причину, по которой Связи параметров выбора не подходят для заполнения, и рассмотрев пошагово программную реализацию, мы можем сделать вывод: наиболее надежным и гибким способом является использование клиент-серверного взаимодействия через событие ПриИзменении. Это позволяет не только подставить единицу измерения, но и реализовать любую другую логику заполнения документа «на лету».

← На главную