Как получить штрихкод из регистра сведений при изменении номенклатуры в документе?

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

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

Рассмотрим реальную ситуацию: есть документ с табличной частью "Товары". При изменении номенклатуры в строке нужно получить её штрихкод из независимого непериодического регистра сведений и подставить в соответствующую колонку. Вся логика получения штрихкода уже написана в экспортной функции в модуле менеджера этого регистра. Вопрос — как правильно вызвать эту функцию из формы документа и какой параметр ей передать?

Анализ исходной ситуации и типичные ошибки

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


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

    Запрос.УстановитьПараметр("Ссылка", Ссылка);
    Результат = Запрос.Выполнить();

    Если Результат.Пустой() Тогда
        Возврат Неопределено;
    Иначе
        Выборка = Результат.Выбрать();
        Если Выборка.Следующий() Тогда
            Возврат Выборка.Штрихкод;
        КонецЕсли;
    КонецЕсли;
КонецФункции

Эта функция ожидает на вход параметр Ссылка, который является ссылкой на измерение регистра ЕдиницаУчета (в данном случае это номенклатура).

Попытка вызова этой функции из формы документа была следующей:


Функция ВыгрузитьШтрихкод()
    Штрихкод = РегистрыСведений.цбкШтрихкоды.ПолучитьШтрихкод(Объект.Ссылка);
    ШтрихкодУсловие = ?(Штрихкод = Неопределено, "Штрихкод не предусмотрен", Штрихкод);
    Возврат ШтрихкодУсловие;
КонецФункции

Здесь допущено две ключевые ошибки:

  1. Неверный контекст вызова. Обращение к серверным объектам, таким как РегистрыСведений, напрямую из клиентского кода невозможно. Управляемые формы работают в клиент-серверной архитектуре. Клиент (интерфейс пользователя) не имеет прямого доступа к базе данных. Любые операции с данными должны выполняться на сервере. Для этого код на форме нужно разделять директивами компиляции &НаКлиенте и &НаСервере.
  2. Неверный параметр. В функцию передается Объект.Ссылка. Это ссылка на сам документ, а не на номенклатуру, которая была изменена в строке табличной части. Функция в модуле менеджера ожидает получить ссылку на номенклатуру, чтобы найти по ней штрихкод.

Правильная реализация: клиент-серверный вызов

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

Шаг 1. Создаем обработчик события на клиенте

Сначала нужно создать обработчик события ПриИзменении для поля "Номенклатура" в табличной части "Товары". Этот код будет выполняться на клиенте.

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


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

    // Проверяем, что номенклатура выбрана
    Если ЗначениеЗаполнено(ТекущаяСтрока.Номенклатура) Тогда
        // Вызываем серверную функцию и передаем в нее ссылку на выбранную номенклатуру
        // Результат вызова сразу присваиваем полю "ШтрихКод" в этой же строке
        ТекущаяСтрока.ШтрихКод = ПолучитьШтрихКодНаСервере(ТекущаяСтрока.Номенклатура);
    Иначе
        // Очищаем штрихкод, если номенклатуру очистили
        ТекущаяСтрока.ШтрихКод = "";
    КонецЕсли;
КонецПроцедуры

Важные моменты:

Шаг 2. Создаем серверную функцию-"обертку"

Теперь создадим в модуле формы функцию, которая будет выполняться на сервере. Она будет служить "мостом" между клиентом и модулем менеджера регистра. Назовем ее ПолучитьШтрихКодНаСервере.


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

Проанализируем этот код:

Шаг 3. Итог и общая схема работы

Давайте соберем все воедино и посмотрим на полную картину взаимодействия:

  1. Пользователь в табличной части документа выбирает номенклатуру.
  2. Срабатывает клиентская процедура ТоварыНоменклатураПриИзменении.
  3. Она получает ссылку на выбранную номенклатуру из текущей строки.
  4. Вызывается серверная функция ПолучитьШтрихКодНаСервере, и ей в качестве параметра передается эта ссылка.
  5. Выполнение "переходит" на сервер. Функция ПолучитьШтрихКодНаСервере вызывает экспортную функцию ПолучитьШтрихкод из модуля менеджера регистра сведений.
  6. Функция из модуля менеджера выполняет запрос к базе данных, находит штрихкод и возвращает его.
  7. Результат возвращается в серверную "обертку", а оттуда — обратно на клиент, в исходную процедуру ТоварыНоменклатураПриИзменении.
  8. Полученное значение присваивается реквизиту ШтрихКод текущей строки табличной части, и пользователь видит результат на форме.

Этот подход является стандартным и правильным для реализации подобной логики в управляемых формах 1С. Он четко разделяет код, выполняющийся на клиенте, от кода, работающего с базой данных на сервере, обеспечивая производительность и корректность работы приложения.

← На главную