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

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

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

Анализ проблемы: Реквизит формы против Реквизита объекта

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

Проанализируем исходный код из примера:


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

В данном фрагменте Реквизит01 является реквизитом именно формы. Когда мы выполняем команду Форма.Реквизит01 = "Проверка", значение записывается в память открытой формы. Однако при вызове НовЭл.Записать() система сохраняет данные самого справочника, в структуре которого этого поля нет. Как только выполнение процедуры завершается и форма закрывается (или если она вообще не выводилась на экран), значение Реквизит01 бесследно исчезает.

Решение 1: Преобразование в реквизит объекта

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


&НаСервере
Функция СоздатьЭлемент()
    НовЭл = Справочники.ТестовыйСправочник.СоздатьЭлемент();
    НовЭл.Наименование = "НовыйЭлемент";
    НовЭл.Реквизит01 = "Проверка"; // Теперь это реквизит объекта
    НовЭл.Записать();
    Возврат НовЭл.Ссылка;
КонецФункции

Теперь значение физически записывается в таблицу базы данных. При открытии формы система автоматически считает это значение из объекта и отобразит его пользователю.

Решение 2: Использование механизмов БСП (Дополнительные сведения)

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

Выясним, как это работает: 1. Мы создаем запись в регистре сведений, где измерением выступает Ссылка на наш элемент, а ресурсом — наше значение. 2. В форме справочника, в обработчике ПриЧтенииНаСервере, мы прописываем код, который считывает данные из регистра и помещает их в РеквизитФормы. 3. Таким образом, для пользователя это выглядит как обычное поле справочника, хотя данные "прилетают" извне.

Решение 3: Массовое заполнение без открытия форм

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

Рассмотрим правильный алгоритм массовой обработки через объектную технику:


&НаСервере
Процедура ЗаполнитьРеквизитыМассово()
    Выборка = Справочники.ТестовыйСправочник.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Получаем объект для редактирования
        ОбъектСправочника = Выборка.ПолучитьОбъект();
        
        // Устанавливаем значение (если это реквизит объекта)
        ОбъектСправочника.Реквизит01 = "Значение заполнено обработкой";
        
        // Обязательно записываем изменения
        Попытка
            ОбъектСправочника.Записать();
        Исключение
            Сообщить("Не удалось записать элемент: " + ОбъектСправочника.Ссылка);
        КонецПопытки;
    КонецЦикла;
КонецПроцедуры

Как передать данные в форму при открытии?

Если ваша задача — передать данные в форму "на лету", чтобы пользователь их увидел, но не обязательно сохранял в базу сразу, используйте структуру параметров. Разберем этот метод подробнее.

При открытии формы можно передать параметр ЗначенияЗаполнения. Рассмотрим пример:


&НаКлиенте
Процедура ОткрытьИЗаполнить()
    ПараметрыЗаполнения = Новый Структура;
    ПараметрыЗаполнения.Вставить("Реквизит01", "Временное значение");
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗначенияЗаполнения", ПараметрыЗаполнения);
    
    ОткрытьФорму("Справочник.ТестовыйСправочник.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры

В модуле формы (на сервере) необходимо обработать эти параметры в процедуре ПриСозданииНаСервере:


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

Подведем итоги

Для успешного решения задач по заполнению данных в 1С необходимо четко следовать правилам:

  1. Реквизиты формы — для временных вычислений и интерфейсных задач. Они не живут дольше сеанса работы с формой.
  2. Реквизиты объекта — для хранения информации, которая должна быть записана в базу данных.
  3. Массовая обработка — выполняется строго через ПолучитьОбъект() и Записать() в цикле, без использования методов ПолучитьФорму().
  4. Событие ПриЧтенииНаСервере — лучший способ заполнить визуальные реквизиты формы данными из связанных таблиц или регистров при каждом открытии существующего элемента.

Помните, что команда Записать() у объекта справочника сохраняет только те данные, которые описаны в метаданных этого справочника в дереве конфигурации. Все "искусственные" дополнения формы при этом игнорируются.

← На главную