Как автоматически заполнить реквизит ИНН при выборе контрагента на обычной форме в 1С?

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

При начале работы с платформой 1С:Предприятие начинающие разработчики часто сталкиваются с трудностями при взаимодействии элементов интерфейса и базы данных. Типичный сценарий — необходимость автоматически заполнить текстовое поле на форме (например, ИНН) сразу после того, как пользователь выбрал элемент в другом поле (например, ссылку на элемент справочника Контрагенты). В этой статье мы подробно разберем, как правильно реализовать эту задачу на обычных (неуправляемых) формах, которые до сих пор активно используются во многих типовых решениях, таких как 1С:Бухгалтерия государственного учреждения 1.0 (БГУ 1.0), 1С:Управление производственным предприятием 1.3 (УПП) или 1С:Комплексная автоматизация 1.1.

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

Разбор типичных ошибок: Почему код «не работает»?

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

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

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

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

  1. Откроем форму документа или обработки в конфигураторе.
  2. Найдем на форме элемент управления (поле ввода), предназначенный для выбора контрагента. Назовем его Контрагент.
  3. Откроем палитру свойств этого элемента управления (нажатием правой кнопки мыши и выбором пункта «Свойства»).
  4. Убедимся, что в свойстве Данные указан соответствующий реквизит (например, ДокументОбъект.Контрагент или просто реквизит формы Контрагент).
  5. Прокрутим палитру свойств до самого низа, найдем событие ПриИзменении и нажмем на значок лупы рядом с ним.
  6. Платформа автоматически сгенерирует заготовку процедуры в Модуле формы. Именно внутри этой процедуры мы и будем писать логику заполнения ИНН.

Вариант 1. Простой способ заполнения (Прямое обращение через точку)

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

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


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

В этом примере параметр Элемент представляет собой само поле ввода формы, с которым взаимодействует пользователь. Свойство Элемент.Значение хранит ссылку на выбранный элемент справочника Контрагенты. Обращение Элемент.Значение.ИНН позволяет быстро получить нужное строковое значение.

Важное примечание: Переменная ИНН в левой части выражения — это реквизит нашего документа или формы. Если ваше поле ИНН на форме не связано с реквизитом напрямую, а является независимым элементом управления, то обращаться к нему следует через коллекцию ЭлементыФормы:


Процедура КонтрагентПриИзменении(Элемент)
    
    Если ЗначениеЗаполнено(Элемент.Значение) Тогда
        ЭлементыФормы.ИНН.Значение = Элемент.Значение.ИНН;
    Иначе
        ЭлементыФормы.ИНН.Значение = "";
    КонецЕсли;
    
КонецПроцедуры

Вариант 2. Профессиональный и оптимизированный способ (Использование БСП)

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

Когда мы пишем Элемент.Значение.ИНН, платформа 1С производит так называемый «неявный запрос» к базе данных. Чтобы прочитать всего лишь одну строчку ИНН, система считывает из СУБД в оперативную память весь объект контрагента целиком: его наименование, полное наименование, КПП, адреса, телефоны, банковские счета и даже табличные части, если они есть. В клиент-серверном режиме работы это приводит к передаче огромного объема избыточных данных по сети, замедляя работу интерфейса.

Для оптимизации производительности в современных конфигурациях (включая БГУ 1.0, БП 3.0 и др.) используется встроенная Библиотека стандартных подсистем (БСП). В ней есть специальный общий модуль ОбщегоНазначения, содержащий функцию быстрого получения конкретных реквизитов без чтения всего объекта. Перепишем наш обработчик с использованием БСП:


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

Этот подход выполняет легкий и точечный SQL-запрос к базе данных, выгружая исключительно поле ИНН. Использование метода ЗначениеРеквизитаОбъекта гарантирует высокую скорость работы формы даже при медленном интернет-соединении или при работе через веб-клиент.

Вариант 3. Использование явного запроса

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

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


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

Этот способ является наиболее низкоуровневым и производительным в отсутствие БСП, так как полностью контролирует процесс обращения к серверу базы данных.

Разбор ситуации: Если Контрагент и ИНН находятся в табличной части

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

Разберем, как правильно получить доступ к текущей строке табличной части на обычных формах:


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

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

Заключение и рекомендации

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

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

← На главную