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

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

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

Разбор событийной модели формы

Прежде чем переходить к написанию кода, проанализируем, в какой момент система должна выполнить действие. В 1С работа с интерфейсом строится на событиях. Нам необходимо, чтобы действие произошло сразу после того, как пользователь выбрал товар в конкретной строке. Для этого идеально подходит обработчик события ПриИзменении. Это событие возникает в тот момент, когда значение в поле выбора было изменено и подтверждено пользователем.

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

Работа с текущей строкой через ТекущиеДанные

Одной из главных проблем новичков является обращение к данным таблицы. Часто пытаются обращаться к реквизитам документа напрямую, что приводит к ошибкам, так как в таблице может быть множество строк. Выясним причину: программа должна точно знать, в какую именно строку «положить» цену. Для этого мы используем конструкцию Элементы.Товары.ТекущиеДанные.

ТекущиеДанные — это объект, который содержит данные именно той строки, в которой сейчас находится курсор пользователя или где происходит редактирование. Обращаясь к этому объекту, мы получаем доступ ко всем колонкам этой строки: Товар, Цена, Количество, Сумма.

Программная реализация подстановки цены

Рассмотрим пример кода, который решает задачу переноса цены. Предположим, что в справочнике Товары у нас есть реквизит Цена, и в документе в табличной части Товары тоже есть реквизит Цена. Посмотрим на логику:


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

Решение проблемы одинаковых имен реквизитов

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

Автоматический пересчет суммы

Чтобы автоматизация была полной, нам необходимо реализовать пересчет суммы при изменении любого из параметров: цены или количества. Проанализируем ситуацию: логика пересчета одинакова для обоих случаев. Поэтому правильным подходом будет вынесение этой логики в отдельную процедуру. Это позволит избежать дублирования кода.


&НаКлиенте
Процедура РассчитатьСуммуСтроки(СтрокаТаблицы)
    
    // Сумма = Цена * Количество
    СтрокаТаблицы.Сумма = СтрокаТаблицы.Цена * СтрокаТаблицы.Количество;
    
КонецПроцедуры

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

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

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

Рассмотрим подробнее архитектуру управляемого приложения. При работе в режиме «Тонкий клиент» прямое обращение через точку к реквизитам справочника (как в примере СтрокаТаблицы.Товар.Цена) может работать медленно или быть недоступным в зависимости от настроек платформы. Профессиональным подходом считается получение данных на стороне сервера.

Если простая подстановка не срабатывает, разберем более надежный способ с использованием серверной функции:


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

&НаСервереБезКонтекста
Функция ПолучитьЦенуТовараНаСервере(СсылкаНаТовар)
    // Возвращаем значение реквизита "Цена" из справочника "Товары"
    Возврат СсылкаНаТовар.Цена;
КонецФункции

Использование директивы &НаСервереБезКонтекста позволяет максимально быстро получить данные, не передавая всю форму на сервер, что значительно ускоряет работу программы.

Типичные ошибки, которых стоит избегать

В процессе реализации начинающие разработчики часто сталкиваются со следующими проблемами:

  1. Отсутствие проверки на заполнение: Если пользователь выберет товар, а потом очистит поле, программа попытается обратиться к цене пустого объекта и вызовет ошибку. Всегда используйте ЗначениеЗаполнено().
  2. Написание кода в модуле объекта: Обработчики событий формы должны располагаться только в модуле формы. Модуль объекта используется для проверки данных перед записью в базу, а не для интерактивного изменения полей на экране.
  3. Забытая команда «Обновить»: В некоторых случаях после программного изменения реквизитов требуется визуально обновить форму, хотя при использовании ТекущиеДанные в управляемых формах это обычно происходит автоматически.

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

Подводя итог, можно сказать, что связка события ПриИзменении, объекта ТекущиеДанные и серверной функции для получения реквизитов — это стандарт «золотого сечения» при разработке интерфейсов в 1С. Реализовав эту логику один раз, вы сможете применять её для любых типов документов, будь то заказы, накладные или акты выполненных работ.

← На главную