Как правильно записать значение из перечисления в реквизит справочника при сохранении формы в 1С?

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

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

Анализ проблемы: почему данные не сохраняются

Проанализируем базовый пример кода, с которым возникла проблема при записи элемента справочника Абоненты:


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

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

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

Правильное решение: присвоение значения реквизиту объекта

Для того чтобы значение из перечисления сохранилось в базе данных, необходимо обращаться непосредственно к реквизиту реквизитного объекта СправочникОбъект (в обычных формах) или Объект (в управляемых формах).

Разберем по шагам правильное присвоение значений перечисления:


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

Критическая ошибка: обращение к перечислению по индексу

В процессе поиска решения иногда обращаются к элементам перечисления по их порядковому номеру (индексу):


// ОПАСНЫЙ КОД!
СправочникОбъект.СтатусДоговораНаТО = Перечисления.СтатусДоговораНаТО[0];

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

  1. Ненадежность структуры: Порядок элементов перечисления задается в дереве конфигурации. Если другой разработчик добавит новое значение перечисления в середину списка или поменяет элементы местами, индекс [0] начнет указывать на совершенно другое значение.
  2. Сложность отладки: Код теряет читаемость. По номеру индекса невозможно понять, какой именно статус устанавливается договору.

Правило: Всегда обращайтесь к значениям перечислений через прямые имя-идентификаторы: Перечисления.ИмяПеречисления.ИмяЗначения.

Важные архитектурные нюансы

При проектировании логики автоматической установки статусов на основе даты обратите внимание на следующие особенности:

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