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

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

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

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

Анализ ошибки: Данные против Элементов управления

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


Процедура ПриОткрытии()
    ЭлементыФормы.ВидЦены = Справочники.ВидЦен.Закупочная;
    ЭлементыФормы.Склад = Справочники.Склады.НайтиПоНаименованию("Склад запчастей");
КонецПроцедуры

Платформа незамедлительно возвращает ошибку: «{Документ.ПриходнаяНакладная.Форма.ФормаДокумента.Форма(32)}: Поле объекта недоступно для записи (ВидЦены)». Почему так происходит?

Дело в том, что в архитектуре 1С реализовано четкое разделение между данными объекта и элементами отображения этих данных на форме:

  1. Данные (Реквизиты) — это то, где физически хранится информация в базе данных или в оперативной памяти (например, реквизиты ЭтотОбъект.ВидЦены или ЭтотОбъект.Склад).
  2. Элементы формы — это лишь визуальные элементы управления (поля ввода, флажки, таблицы), расположенные на экране для удобства пользователя. Они связаны с данными через специальное свойство связи (в обычных формах — «Данные», в управляемых — «ПутьКДанным»).

Попытка напрямую присвоить значение элементу коллекции ЭлементыФормы ошибочна, так как сам элемент управления заблокирован для прямой перезаписи ссылки. Записывать новые значения необходимо непосредственно в источник данных — то есть в реквизиты объекта.

Решение 1. Правильное заполнение в Обычных формах

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

Чтобы избежать затирания исторических данных в старых документах, мы должны обязательно добавить проверку на то, является ли наш объект новым. Для этого в обычных формах используется метод ЭтоНовый(). Проанализируем правильный вариант кода:


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

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

Решение 2. Современный стандарт — Управляемые формы (1С 8.3)

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

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


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

Решение 3. Использование события «ОбработкаЗаполнения» (Рекомендация фирмы 1С)

Размещение логики заполнения в модуле формы (будь то обычная или управляемая форма) имеет один глобальный недостаток: этот код сработает только при интерактивном создании документа пользователем через интерфейс.

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

Чтобы избежать этой проблемы, бизнес-логику заполнения по умолчанию следует переносить в Модуль объекта в специализированный обработчик ОбработкаЗаполнения. Этот метод вызывается платформой всегда при инициализации нового объекта, независимо от способа его создания.

Рассмотрим пример кода в модуле объекта документа:


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

Такой подход гарантирует целостность ваших данных в системе при любых интеграциях и автоматических обменах.

Решение 4. Заполнение полей без программирования

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

  1. Откройте конфигуратор и найдите нужный документ.
  2. Перейдите на вкладку «Реквизиты» и откройте палитру свойств целевого реквизита (например, ВидЦены).
  3. Найдите свойство «Значение для заполнения».
  4. Нажмите на кнопку выбора и укажите конкретный элемент справочника (например, предопределенный элемент «Закупочная» или значение перечисления).

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

Критика жесткого кодирования (Хардкода)

Обратите внимание на строку кода: Справочники.Склады.НайтиПоНаименованию("Склад запчастей"). Использование текстового поиска по наименованию в коде считается грубой ошибкой разработки (антипаттерном) по нескольким причинам:

Как сделать правильно?

Во-первых, если элемент справочника является ключевым для логики системы, сделайте его предопределенным в конфигураторе. Тогда вы сможете обращаться к нему напрямую по имени: Справочники.Склады.СкладЗапчастей.

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

← На главную