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