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