Разработка в среде 1С с использованием механизма расширений — удобный и безопасный способ модификации типовых конфигураций. Однако у начинающих разработчиков часто возникают сложности, связанные с пониманием контекста выполнения кода и структуры хранения данных. Рассмотрим классическую проблему: в табличную часть документа через расширение добавляется новая колонка, данные из которой должны записываться в регистр сведений при проведении. На практике разработчик сталкивается с тем, что при записи или проведении документа введённые числовые значения просто исчезают из колонки на форме, а в регистр сведений ничего не записывается.
В этой статье мы подробно разберем причины возникновения этой проблемы и по шагам реализуем корректный алгоритм сохранения данных из расширения в базу данных.
Для начала проанализируем ситуацию и поймем, почему введенные пользователем данные бесследно исчезают. Здесь кроются две принципиальные ошибки в проектировании решения.
Ошибка 1. Колонка добавлена как реквизит формы, а не реквизит объекта.
Когда мы добавляем колонку в таблицу на форме через редактор формы в расширении, очень легко ошибиться и создать обычный Реквизит формы (переменную, которая живет только в памяти открытого окна на клиенте). Если колонка на форме не связана с реальным реквизитом табличной части документа в базе данных, то при любой серверной операции (например, при записи объекта или при проведении) платформа выполняет цикл чтения-записи. Объект заново перечитывается из базы данных, форма обновляет свои данные, и всё, что было введено во «временную» колонку формы, безвозвратно затирается, так как системе просто неоткуда считать эти данные на сервере.
Ошибка 2. Попытка работы с расширенными данными в основной конфигурации.
Разработчик пытается использовать стандартный конструктор движений в основной конфигурации для заполнения регистра сведений данными из расширения. Это в корне неверно. Основная конфигурация ничего не знает о тех реквизитах и объектах, которые созданы внутри расширения. Если вы напишете обращение к расширенному реквизиту в модуле основной конфигурации, программа либо выдаст ошибку компиляции на этапе сохранения, либо проигнорирует это свойство в процессе выполнения (в зависимости от настроек строгости компиляции и режима совместимости).
---
Чтобы решить задачу корректно, нам нужно выполнить три основных этапа: правильно привязать данные на форме к объекту базы данных в расширении, заимствовать регистр сведений и переписать логику проведения документа с использованием модуля объекта расширения. Разберем каждый шаг подробно.
Данные должны сохраняться в базе данных вместе с документом. Для этого расширим структуру метаданных документа:
Товары), кликнем по ней правой кнопкой мыши и выберем Добавить -> Реквизит табличной части.сКод (или КодПодразделения) и укажем тип данных — Число.Теперь платформа знает, что у табличной части документа в базе данных физически появилось новое поле для хранения информации.
Теперь свяжем визуальный элемент формы с физическим реквизитом объекта базы данных:
Объект.Товары. Внутри нее появится наш новый реквизит сКод.сКод мышкой в таблицу элементов формы.Объект.Товары.сКод.Важно: Если ранее вы добавляли колонку вручную просто как элемент формы, удалите её и добавьте заново перетаскиванием реквизита объекта, чтобы избежать путаницы с путями к данным.
Поскольку мы будем писать код проведения в контексте расширения, расширение должно иметь доступ к регистру сведений, куда будут записываться данные:
сКод).Поскольку мы не должны изменять программный код основной конфигурации (чтобы сохранить возможность беспрепятственного обновления), мы воспользуемся механизмом перехвата событий. Мы расширим стандартную процедуру ОбработкаПроведения.
&После, чтобы наш код выполнялся сразу после того, как отработает стандартное проведение из основной конфигурации.Проанализируем и напишем следующий программный код в модуле объекта расширения:
&После("ОбработкаПроведения")
Процедура Расш_ОбработкаПроведения(Отказ, РежимПроведения)
// Если при проведении в основной конфигурации возникли ошибки,
// прерываем выполнение и не пишем свои движения.
Если Отказ Тогда
Возврат;
КонецЕсли;
// Включаем флаг записи для коллекции движений нашего регистра
Движения.сКод.Записывать = Истина;
// Обходим строки табличной части документа
Для Каждого ТекСтрокаТовары Из Товары Цикл
// Создаем новую запись в наборе записей регистра сведений
Движение = Движения.сКод.Добавить();
// Заполняем ключевые поля (Период, Измерения и Ресурсы)
Движение.Период = Дата;
Движение.Контрагент = Контрагент;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
// Записываем числовое значение из нашей добавленной колонки
Движение.Код = ТекСтрокаТовары.сКод;
КонецЦикла;
КонецПроцедуры
Разберем подробнее, почему эта схема работает идеально:
Движения автоматически доступна в модуле объекта документа, и нам не нужно вручную создавать менеджеры записи регистра сведений.сКод теперь гарантированно заполнен, так как данные были предварительно записаны в табличную часть документа в базу данных при сохранении формы перед проведением.При работе с расширениями всегда помните золотое правило: данные формы не равны данным объекта. Любая колонка, которую вы хотите использовать в проведении, отчетах или бизнес-логике, должна быть добавлена как полноценный реквизит заимствованного объекта (документа, справочника) внутри расширения. Старайтесь полностью избегать изменений в модулях основной конфигурации, реализуя всю сопутствующую бизнес-логику в модулях расширения с помощью перехватчиков &Перед, &После или &Вместо.