Почему не сохраняются данные в новой табличной части документа в 1С:УПП и как это исправить

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

При доработке типовых конфигураций, таких как 1С:Управление производственным предприятием (УПП), программисты часто сталкиваются с неприятной ситуацией: в стандартный документ добавляется новая табличная часть, программно заполняется, но после вызова метода Записать() данные из этой таблицы бесследно исчезают. При этом стандартные табличные части (например, Товары) сохраняются корректно.

В этой статье мы подробно разберем, почему так происходит, изучим внутренние механизмы УПП и научимся находить «виновника» очистки данных с помощью отладчика.

Анализируем ситуацию: почему данные пропадают?

Рассмотрим типичный сценарий. Вы добавили в документ (например, «Реализация товаров и услуг») табличную часть Отклонения. В коде обработки заполнения вы обращаетесь к объекту и добавляете строки:


НоваяСтрока = Объект.Отклонения.Добавить();
НоваяСтрока.Номенклатура = ВыбраннаяНоменклатура;
НоваяСтрока.Количество = 10;

// В отладчике на этом этапе Объект.Отклонения содержит данные
Объект.Записать(РежимЗаписиДокумента.Запись);
// После этой строки Объект.Отклонения становится пустым

Проблема заключается в том, что УПП — это конфигурация с очень жесткой архитектурой. В модулях объектов типовых документов прописано огромное количество проверок и процедур автоматического заполнения, которые срабатывают в событии ПередЗаписью. Если ваша новая табличная часть не «зарегистрирована» в этих внутренних механизмах, система может посчитать её лишней или временной и просто очистить перед тем, как данные попадут в базу данных.

Причина №1: Глобальная очистка в событии ПередЗаписью

Проанализируем программный код модуля документа. В большинстве документов УПП процедура ПередЗаписью содержит вызовы общих процедур из модулей ОбщегоНазначения, ЗаполнениеДокументов или РаботаСДиалогами.

Выясним причину: в типовых решениях часто реализован механизм «санитарной» обработки. Система проходит циклом по всем табличным частям, которые она «знает» (которые прописаны в программном коде как обязательные), а остальные либо игнорирует, либо принудительно обнуляет, чтобы избежать хранения неконсистентных данных. Особенно часто это встречается в процедурах типа ЗаполнитьТабличныеЧасти() или СброситьДанныеТабличныхЧастей().

Причина №2: Использование структуры ДополнительныеСвойства

В УПП при записи документа активно используется структура ДополнительныеСвойства. Если документ записывается из формы, в эту структуру могут передаваться флаги, управляющие перезаполнением таблиц. При программной записи из обработки (как в нашем примере) эти флаги могут отсутствовать, что заставляет систему выполнять «полную очистку и перезаполнение» по умолчанию. Если ваша ТЧ не включена в алгоритм перезаполнения, она останется пустой.

Как найти место очистки: используем трассировку

Чтобы не гадать, в какой из сотен процедур пропадают данные, воспользуемся механизмом отладки. Проделаем следующие шаги:

  1. Откроем модуль объекта документа, в который была добавлена ТЧ.
  2. Найдем процедуру ПередЗаписью.
  3. Установим точку останова в самом начале этой процедуры.
  4. Запустим выполнение кода. Когда выполнение остановится, откройте окно «Табло» (Shift+F9).
  5. Добавьте в табло выражение ЭтотОбъект.МояТабличнаяЧасть.Количество().
  6. Используйте клавишу F8 (шагнуть в), чтобы заходить в каждую вызываемую процедуру.
  7. Следите за значением в табло. Как только количество строк станет равным 0 — вы нашли процедуру-виновника.

Совет: Если процедур слишком много, можно поставить точку останова с условием. Нажмите правой кнопкой мыши на точку останова, выберите «Условие» и напишите: ЭтотОбъект.МояТабличнаяЧасть.Количество() = 0. Это позволит «поймать» момент сразу после очистки.

Варианты решения проблемы

После того как мы выяснили, где именно очищаются данные, рассмотрим способы исправления ситуации:

Способ 1: Модификация типового кода (если допустимо)

Если вы нашли процедуру, которая очищает таблицы (например, цикл по метаданным или жесткий список ТЧ), вам нужно добавить имя своей табличной части в список исключений. Посмотрим на пример логики, которую можно встретить в УПП:


// Пример того, как может выглядеть очистка в типовом коде
Для Каждого ТЧ Из Метаданные().ТабличныеЧасти Цикл
    Если ТЧ.Имя <> "Товары" И ТЧ.Имя <> "ВозвратнаяТара" Тогда
        ЭтотОбъект[ТЧ.Имя].Очистить(); // Вот здесь пропадают ваши данные!
    КонецЕсли;
КонецЦикла;

В этом случае необходимо добавить проверку вашей ТЧ: И ТЧ.Имя <> "Отклонения".

Способ 2: Запись через подписки на события

Иногда проще не менять логику ПередЗаписью, а использовать подписку на событие ПриЗаписи. Однако помните, что на этапе ПриЗаписи данные уже улетают в БД. Если ТЧ очистилась перед записью, то в ПриЗаписи восстанавливать её будет поздно. Поэтому основной упор всегда делаем на анализ ПередЗаписью.

Способ 3: Проверка механизмов обмена (РИБ)

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

Заключение

Проблема «исчезающих» табличных частей в УПП почти всегда кроется в типовых механизмах очистки, заложенных в модуль объекта. Тщательная трассировка события ПередЗаписью с контролем количества строк в ТЧ позволяет быстро локализовать проблему и внести необходимые правки в исключения типовых процедур заполнения.

← На главную