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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Торговля и дистрибуция
← К списку

Мы часто сталкиваемся с ситуацией, когда, создав новый реквизит программно на форме, обнаруживаем, что введенные в него данные не сохраняются в базе данных. Эта проблема возникает из-за фундаментального различия между реквизитами формы и реквизитами объекта метаданных. Давайте вместе разберемся в этой особенности платформы 1С:Предприятие и найдем эффективные решения. Выясним причину, по которой это происходит. Платформа 1С:Предприятие имеет четкое разделение между структурой данных, хранящихся в базе данных, и данными, которые отображаются и обрабатываются на форме. * Реквизиты объекта метаданных (например, справочника, документа или регистра сведений) — это поля, которые являются частью структуры объекта, определенной в конфигураторе. Именно они хранятся в базе данных. Главное правило: их нельзя создать программно в режиме "1С:Предприятие". Изменение структуры метаданных требует обновления конфигурации. * Реквизиты формы — это временные данные, которые существуют только в контексте открытой формы. Они используются для отображения информации, промежуточных расчетов, ввода данных пользователем или для управления поведением формы. Реквизиты формы можно создавать программно, но они не связаны напрямую с базой данных и не сохраняются автоматически при закрытии формы. Итак, когда мы программно добавляем реквизит на форму, мы создаем именно реквизит формы, а не реквизит объекта метаданных. Отсюда и возникает проблема несохранения данных. Теперь рассмотрим, как мы можем решить эту задачу.

Решение 1: Корректная привязка элемента формы к существующему реквизиту объекта

Рассмотрим подробнее ситуацию, когда реквизит, в который мы хотим сохранить данные, уже существует в объекте метаданных (например, в регистре сведений ШтрихкодыНоменклатуры уже есть реквизит ЕдиницаУпаковки). Часто проблема заключается в некорректном пути к данным, указанном для элемента формы. Когда вы добавляете элемент на форму, важно правильно указать, с каким реквизитом он связан. Если вы создали реквизит формы и пытаетесь напрямую связать его с элементом, то данные будут храниться только в этом реквизите формы. Для сохранения в базу данных элемент формы должен быть связан с реквизитом объекта, который является источником данных формы. Разберем по шагам, как это работает:

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

Посмотрим на пример. Если у вас есть регистр сведений ШтрихкодыНоменклатуры и в нем уже есть реквизит ЕдиницаУпаковки, а на форме регистр представлен основным реквизитом Запись, то правильный путь к данным для элемента формы будет следующим:


// Пример программного создания элемента формы и привязки к существующему реквизиту объекта
// Предполагаем, что на форме уже есть основной реквизит "Запись" типа "ЗаписьРегистраСведений.ШтрихкодыНоменклатуры"
// И в метаданных регистра "ШтрихкодыНоменклатуры" есть реквизит "ЕдиницаУпаковки"

// Создаем новый элемент формы типа "ПолеВвода"
НовыйЭлемент = Элементы.Добавить("ПолеЕдиницаУпаковки", Тип("ПолеФормы"), Элементы.ГруппаФормы);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.Заголовок = "Единица упаковки";

// Важно: Путь к данным указываем на реквизит основного объекта формы
// "Запись" - это имя основного реквизита формы, представляющего запись регистра
// "ЕдиницаУпаковки" - это имя существующего реквизита регистра сведений
НовыйЭлемент.ПутьКДанным = "Запись.ЕдиницаУпаковки";

// Если нужно программно установить значение (например, при инициализации формы)
Запись.ЕдиницаУпаковки = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("Штука");

Обратите внимание на строку НовыйЭлемент.ПутьКДанным = "Запись.ЕдиницаУпаковки";. Именно здесь мы указываем системе, что данные, вводимые в это поле, должны записываться в реквизит ЕдиницаУпаковки объекта, представленного реквизитом формы Запись. Это и было "косяком", о котором упомянула автор в сообщении 19.

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

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

  1. Дополнительные реквизиты:
    • Предназначены для хранения свойств, которые всегда присущи объекту и являются его неотъемлемой частью.
    • Данные дополнительных реквизитов хранятся непосредственно в таблице самого объекта, к которому они относятся.
    • Пример: Если для номенклатуры нам нужно добавить поле "Цвет" или "Материал", которое всегда будет у каждой позиции.
  2. Дополнительные сведения:
    • Подходят для хранения характеристик или свойств, которые могут быть необязательными, иметь множественные значения или описывать объект в различных контекстах.
    • Данные дополнительных сведений хранятся в отдельном регистре сведений, связанном с объектом.
    • Пример: Для той же номенклатуры могут быть "Сертификаты" (несколько для одной позиции) или "Особенности эксплуатации".

Как включить и использовать этот механизм:

  1. Убедитесь, что в вашей конфигурации используется Библиотека стандартных подсистем (БСП).
  2. Включите функциональность "Дополнительные реквизиты и сведения" в разделе "Администрирование – Общие настройки" (или аналогичном, в зависимости от конфигурации).
  3. После включения вы сможете добавлять новые реквизиты и сведения для нужных объектов через пользовательский интерфейс. Эти реквизиты автоматически появятся на соответствующих формах объектов и будут сохраняться в базе данных.

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

Решение 3: Программное сохранение данных из реквизита формы в существующий реквизит объекта

Если по каким-то причинам механизм "Дополнительные реквизиты и сведения" не подходит, или вам нужно временно использовать реквизит формы, а затем вручную сохранить его значение в *уже существующий* реквизит объекта метаданных, мы можем сделать это программно. В этом случае мы создаем реквизит формы, работаем с ним, а затем, в нужный момент (например, при записи объекта), считываем его значение и записываем в соответствующий реквизит основного объекта. Посмотрим на пример:


// Предположим, у нас есть реквизит формы "МойВременныйРеквизит" строкового типа
// и существующий реквизит объекта "Запись.Комментарий" (где "Запись" - основной реквизит формы)

// 1. Создание реквизита формы (если его еще нет)
Если Не Свойство("МойВременныйРеквизит") Тогда
    МассивТипов = Новый Массив;
    МассивТипов.Добавить(Тип("Строка"));
    ДобавитьРеквизит("МойВременныйРеквизит", Новый ОписаниеТипов(МассивТипов), "ЗаголовокМоегоРеквизита");
КонецЕсли;

// 2. Создание элемента формы для отображения этого реквизита
// (Этот шаг аналогичен тому, что мы делали в Решении 1, но ПутьКДанным ведет к реквизиту формы)
Если Элементы.Найти("ПолеМойВременныйРеквизит") = Неопределено Тогда
    НовыйЭлемент = Элементы.Добавить("ПолеМойВременныйРеквизит", Тип("ПолеФормы"), Элементы.ГруппаФормы);
    НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
    НовыйЭлемент.Заголовок = "Мой временный реквизит";
    НовыйЭлемент.ПутьКДанным = "МойВременныйРеквизит"; // Привязываем к реквизиту формы
КонецЕсли;

// 3. Программное сохранение значения реквизита формы в реквизит объекта
// Этот код выполняется, например, в обработчике события "ПередЗаписью" или "ПриЗаписи"
// основного объекта формы (например, ЗаписьРегистраСведений)
// Здесь "Запись" - это основной реквизит формы, представляющий объект регистра.

// Устанавливаем значение реквизита объекта из реквизита формы
Запись.Комментарий = МойВременныйРеквизит;

// Теперь при записи объекта "Запись" в базу данных, значение из "МойВременныйРеквизит"
// будет сохранено в реквизит регистра "Комментарий".

Таким образом, мы видим, что ключом к решению проблемы сохранения данных является понимание различий между реквизитами формы и реквизитами объекта метаданных. Всегда стремитесь использовать стандартные механизмы платформы, такие как "Дополнительные реквизиты и сведения", для гибкого расширения функциональности без изменения конфигурации. Если же требуется ручное управление, обеспечьте правильную привязку элементов формы или явное программное копирование данных из реквизитов формы в реквизиты объекта перед его сохранением.

← К списку