В практике разработки на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда необходимо программно создать элемент справочника и заполнить определенные поля. Однако начинающие разработчики нередко сталкиваются с проблемой: код отрабатывает без ошибок, но при открытии созданного элемента данные в нужных полях отсутствуют. Разберем детально, почему это происходит и как правильно организовать заполнение данных.
Рассмотрим ситуацию, описанную в теме. Разработчик пытается создать элемент справочника ТестовыйСправочник и заполнить поле Реквизит01, обращаясь напрямую к форме. Главная ошибка здесь заключается в непонимании жизненного цикла данных. В системе 1С существует жесткое разделение между данными объекта (которые хранятся в таблицах базы данных SQL) и реквизитами формы (которые существуют только в оперативной памяти в момент работы пользователя с конкретным окном).
Проанализируем исходный код из примера:
&НаКлиенте
Процедура вып(Команда)
НовЭл = СоздатьЭлемент(); // Создаем элемент в базе
ПараметрыФормы = Новый Структура("Ключ", НовЭл.Ссылка);
Форма = ПолучитьФорму("Справочник.ТестовыйСправочник.Форма.ФормаЭлемента", ПараметрыФормы);
Форма.Реквизит01 = "Проверка"; // Пытаемся заполнить реквизит формы
НовЭл.Записать(); // Записываем объект снова
КонецПроцедуры
В данном фрагменте Реквизит01 является реквизитом именно формы. Когда мы выполняем команду Форма.Реквизит01 = "Проверка", значение записывается в память открытой формы. Однако при вызове НовЭл.Записать() система сохраняет данные самого справочника, в структуре которого этого поля нет. Как только выполнение процедуры завершается и форма закрывается (или если она вообще не выводилась на экран), значение Реквизит01 бесследно исчезает.
Если данные в поле Реквизит01 должны сохраняться навсегда и быть доступны при каждом открытии элемента, самым правильным и простым решением будет добавление этого реквизита в структуру самого справочника в конфигураторе. Проанализируем, как изменится код в этом случае:
&НаСервере
Функция СоздатьЭлемент()
НовЭл = Справочники.ТестовыйСправочник.СоздатьЭлемент();
НовЭл.Наименование = "НовыйЭлемент";
НовЭл.Реквизит01 = "Проверка"; // Теперь это реквизит объекта
НовЭл.Записать();
Возврат НовЭл.Ссылка;
КонецФункции
Теперь значение физически записывается в таблицу базы данных. При открытии формы система автоматически считает это значение из объекта и отобразит его пользователю.
Бывают ситуации, когда изменять структуру справочника (добавлять реквизиты) нельзя — например, если конфигурация находится на поддержке или это запрещено архитектурными правилами проекта. В таких случаях для хранения данных, которые не являются частью типового объекта, используют Регистры сведений или механизм Дополнительных реквизитов и сведений (из состава Библиотеки Стандартных Подсистем — БСП).
Выясним, как это работает:
1. Мы создаем запись в регистре сведений, где измерением выступает Ссылка на наш элемент, а ресурсом — наше значение.
2. В форме справочника, в обработчике ПриЧтенииНаСервере, мы прописываем код, который считывает данные из регистра и помещает их в РеквизитФормы.
3. Таким образом, для пользователя это выглядит как обычное поле справочника, хотя данные "прилетают" извне.
В теме упоминается задача заполнить реквизит для 1000 элементов. Проанализируем критическую ошибку: никогда не используйте получение формы для массового изменения данных. Открытие формы — это ресурсозатратная операция, требующая инициализации интерфейса, вызова серверных событий компоновки и передачи контекста. Для 1000 элементов это приведет к значительным задержкам.
Рассмотрим правильный алгоритм массовой обработки через объектную технику:
&НаСервере
Процедура ЗаполнитьРеквизитыМассово()
Выборка = Справочники.ТестовыйСправочник.Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем объект для редактирования
ОбъектСправочника = Выборка.ПолучитьОбъект();
// Устанавливаем значение (если это реквизит объекта)
ОбъектСправочника.Реквизит01 = "Значение заполнено обработкой";
// Обязательно записываем изменения
Попытка
ОбъектСправочника.Записать();
Исключение
Сообщить("Не удалось записать элемент: " + ОбъектСправочника.Ссылка);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если ваша задача — передать данные в форму "на лету", чтобы пользователь их увидел, но не обязательно сохранял в базу сразу, используйте структуру параметров. Разберем этот метод подробнее.
При открытии формы можно передать параметр ЗначенияЗаполнения. Рассмотрим пример:
&НаКлиенте
Процедура ОткрытьИЗаполнить()
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("Реквизит01", "Временное значение");
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ПараметрыЗаполнения);
ОткрытьФорму("Справочник.ТестовыйСправочник.ФормаОбъекта", ПараметрыФормы);
КонецПроцедуры
В модуле формы (на сервере) необходимо обработать эти параметры в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ЗначенияЗаполнения") Тогда
ЭтаФорма.Реквизит01 = Параметры.ЗначенияЗаполнения.Реквизит01;
КонецЕсли;
КонецПроцедуры
Для успешного решения задач по заполнению данных в 1С необходимо четко следовать правилам:
ПолучитьОбъект() и Записать() в цикле, без использования методов ПолучитьФорму().Помните, что команда Записать() у объекта справочника сохраняет только те данные, которые описаны в метаданных этого справочника в дереве конфигурации. Все "искусственные" дополнения формы при этом игнорируются.