Почему пропадают данные из добавленной в расширении колонки при записи документа и как правильно записать их в регистр сведений

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

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

В этой статье мы подробно разберем причины возникновения этой проблемы и по шагам реализуем корректный алгоритм сохранения данных из расширения в базу данных.

Выясняем причину: почему затираются данные на форме?

Для начала проанализируем ситуацию и поймем, почему введенные пользователем данные бесследно исчезают. Здесь кроются две принципиальные ошибки в проектировании решения.

Ошибка 1. Колонка добавлена как реквизит формы, а не реквизит объекта.
Когда мы добавляем колонку в таблицу на форме через редактор формы в расширении, очень легко ошибиться и создать обычный Реквизит формы (переменную, которая живет только в памяти открытого окна на клиенте). Если колонка на форме не связана с реальным реквизитом табличной части документа в базе данных, то при любой серверной операции (например, при записи объекта или при проведении) платформа выполняет цикл чтения-записи. Объект заново перечитывается из базы данных, форма обновляет свои данные, и всё, что было введено во «временную» колонку формы, безвозвратно затирается, так как системе просто неоткуда считать эти данные на сервере.

Ошибка 2. Попытка работы с расширенными данными в основной конфигурации.
Разработчик пытается использовать стандартный конструктор движений в основной конфигурации для заполнения регистра сведений данными из расширения. Это в корне неверно. Основная конфигурация ничего не знает о тех реквизитах и объектах, которые созданы внутри расширения. Если вы напишете обращение к расширенному реквизиту в модуле основной конфигурации, программа либо выдаст ошибку компиляции на этапе сохранения, либо проигнорирует это свойство в процессе выполнения (в зависимости от настроек строгости компиляции и режима совместимости).

---

Пошаговое руководство по правильной реализации задачи

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

Шаг 1. Создание реквизита табличной части в расширении

Данные должны сохраняться в базе данных вместе с документом. Для этого расширим структуру метаданных документа:

  1. Откроем дерево метаданных конфигурации-расширения.
  2. Найдем наш документ (он должен быть заимствован в расширение) и раскроем его ветку метаданных.
  3. Перейдем к табличной части (например, Товары), кликнем по ней правой кнопкой мыши и выберем Добавить -> Реквизит табличной части.
  4. Назовем новый реквизит сКод (или КодПодразделения) и укажем тип данных — Число.

Теперь платформа знает, что у табличной части документа в базе данных физически появилось новое поле для хранения информации.

Шаг 2. Привязка колонки формы к созданному реквизиту

Теперь свяжем визуальный элемент формы с физическим реквизитом объекта базы данных:

  1. Откроем форму документа, заимствованную в расширение.
  2. В окне элементов формы найдем нашу таблицу (например, таблицу «Товары»).
  3. В списке реквизитов формы (в правой части экрана) найдем ветку Объект.Товары. Внутри нее появится наш новый реквизит сКод.
  4. Перетащим этот реквизит сКод мышкой в таблицу элементов формы.
  5. Проверим свойства созданного элемента формы (колонки): в свойстве ПутьКДанным (DataPath) обязательно должно быть указано Объект.Товары.сКод.

Важно: Если ранее вы добавляли колонку вручную просто как элемент формы, удалите её и добавьте заново перетаскиванием реквизита объекта, чтобы избежать путаницы с путями к данным.

Шаг 3. Заимствование регистра сведений в расширение

Поскольку мы будем писать код проведения в контексте расширения, расширение должно иметь доступ к регистру сведений, куда будут записываться данные:

  1. В дереве основной конфигурации найдем созданный нами регистр сведений (например, сКод).
  2. Нажмем на него правой кнопкой мыши и выберем пункт Добавить в расширение.
  3. Убедимся, что все необходимые измерения и ресурсы этого регистра также перенеслись в расширение.

Шаг 4. Написание логики проведения в модуле объекта расширения

Поскольку мы не должны изменять программный код основной конфигурации (чтобы сохранить возможность беспрепятственного обновления), мы воспользуемся механизмом перехвата событий. Мы расширим стандартную процедуру ОбработкаПроведения.

  1. В дереве метаданных расширения найдем наш документ, нажмем правой кнопкой мыши и выберем Открыть модуль объекта.
  2. Используем аннотацию &После, чтобы наш код выполнялся сразу после того, как отработает стандартное проведение из основной конфигурации.

Проанализируем и напишем следующий программный код в модуле объекта расширения:


&После("ОбработкаПроведения")
Процедура Расш_ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Если при проведении в основной конфигурации возникли ошибки,
    // прерываем выполнение и не пишем свои движения.
    Если Отказ Тогда 
        Возврат;
    КонецЕсли;
    
    // Включаем флаг записи для коллекции движений нашего регистра
    Движения.сКод.Записывать = Истина;
    
    // Обходим строки табличной части документа
    Для Каждого ТекСтрокаТовары Из Товары Цикл
        
        // Создаем новую запись в наборе записей регистра сведений
        Движение = Движения.сКод.Добавить();
        
        // Заполняем ключевые поля (Период, Измерения и Ресурсы)
        Движение.Период = Дата;
        Движение.Контрагент = Контрагент;
        Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
        
        // Записываем числовое значение из нашей добавленной колонки
        Движение.Код = ТекСтрокаТовары.сКод; 
        
    КонецЦикла;
    
КонецПроцедуры

Разберем подробнее, почему эта схема работает идеально:

Резюме и правила хорошего тона при работе с расширениями

При работе с расширениями всегда помните золотое правило: данные формы не равны данным объекта. Любая колонка, которую вы хотите использовать в проведении, отчетах или бизнес-логике, должна быть добавлена как полноценный реквизит заимствованного объекта (документа, справочника) внутри расширения. Старайтесь полностью избегать изменений в модулях основной конфигурации, реализуя всю сопутствующую бизнес-логику в модулях расширения с помощью перехватчиков &Перед, &После или &Вместо.

← На главную