Почему не записываются измерения в регистр накопления при проведении документа?

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

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

Анализ проблемы: почему данные «пропадают»

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

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

Когда мы выполняем команду:

Движение.Материал = ТекСтрокаТабличнаяЧасть1.Материал;

Происходит попытка записать текст (тип Строка) в поле, которое ожидает уникальный идентификатор объекта (тип Ссылка). Платформа 1С не выдает ошибку принудительно, она просто не может сопоставить текст со ссылкой и записывает в регистр пустое значение данного типа. Именно поэтому мы видим пустые поля в консоли запросов или списке движений.

Решение №1: Приведение типов в конфигураторе (рекомендуемое)

Самый правильный и надежный способ — это обеспечить идентичность типов данных еще на уровне метаданных. Выясним, как это сделать по шагам:

  1. Откроем конфигуратор и найдем наш документ.
  2. Перейдем на закладку Данные и развернем список колонок нужной табличной части.
  3. Для колонок Материал и ДрагМеталл нажмем кнопку выбора типа (три точки).
  4. Вместо типа Строка выберем соответствующий ссылочный тип (например, СправочникСсылка.Материалы).
  5. Аналогичную проверку проведем для регистра накопления. Убедимся, что измерения регистра имеют точно такой же ссылочный тип.

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

Решение №2: Программный поиск ссылки по строке

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


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

Важное замечание: Поиск по наименованию считается "плохим тоном" в профессиональной разработке, так как в справочнике могут быть дубли или опечатки. Всегда старайтесь использовать первый способ (ссылочные типы в ТЧ).

Проверка ресурсов и реквизитов регистра

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

Как использовать отладчик для диагностики

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

  1. Установим точку останова внутри цикла в процедуре ОбработкаПроведения.
  2. Запустим документ на проведение.
  3. Когда выполнение прервется, выделим выражение ТекСтрока.Материал, нажмем правую кнопку мыши и выберем Вычислить выражение.
  4. Обратим внимание на колонку Тип. Если там написано Строка, а в конфигураторе у регистра стоит СправочникСсылка... — мы нашли причину.
  5. Для проверки типа измерения регистра вычислим выражение ТипЗнч(Движение.Материал). Это покажет нам ожидаемый платформой тип данных.

Таким образом, для стабильной работы системы всегда контролируйте соответствие типов данных в цепочке "Документ -> Регистр -> Отчет". Это избавит вас от проблем с пустыми значениями и некорректными итогами в регистрах накопления.

← На главную