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

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

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

Анализ проблемы: ошибка использования метода Записать в цикле

Основная ошибка, которую допустил автор в исходном коде, заключается в вызове метода Записать() внутри цикла Для каждого... Из... КонецЦикла. Когда мы создаем набор записей через СоздатьНаборЗаписей() и вызываем его запись на каждом шаге цикла, происходит следующее: при каждой итерации система удаляет все существующие записи по данному отбору и записывает только ту одну запись, которая была добавлена в текущий момент. В итоге, после завершения цикла в регистре остается лишь последний обработанный элемент.

Важное правило: Метод Записать() следует вызывать один раз после того, как все необходимые записи были добавлены в набор. Это не только исправляет логическую ошибку, но и значительно ускоряет работу системы, так как обращение к серверу базы данных происходит однократно.

Решение 1: использование коллекции Движения

Современным стандартом разработки в 1С является использование встроенной коллекции Движения. Этот механизм позволяет платформе автоматически управлять процессом записи. Рассмотрим, как правильно реализовать проведение документа:


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

При использовании этого подхода нам не нужно вручную вызывать Записать(). Установка свойства Записывать = Истина говорит платформе, что по окончании процедуры нужно сохранить все накопленные в коллекции Движения данные.

Решение 2: явное указание параметров записи

Хотя многие поля при проведении документа заполняются автоматически, опытные разработчики рекомендуют придерживаться принципа «явного лучше, чем неявного». Это защищает от непредвиденных ошибок, особенно при сложной логике проведения.

  1. Регистратор: Если регистр подчинен регистратору, система сама свяжет записи с документом. Однако, явное указание Регистратор (если это поле выведено в измерение) делает код более читаемым и надежным при отладке.
  2. Активность: Явное присвоение Активность = Истина полезно в ситуациях, когда логика проведения документа может меняться (например, при отмене проведения или создании сторнирующих движений).
  3. Дата: Вместо обращения к ЭтотОбъект.Ссылка.Дата, которое вызывает лишнее чтение из базы данных, используйте переменную Дата, доступную в контексте модуля объекта.

Рекомендации по оптимизации и архитектуре

Чтобы код был профессиональным и эффективным, придерживайтесь следующих рекомендаций:

Минимизация запросов: Избегайте лишних обращений к базе данных внутри циклов. Использование Ссылка.Дата требует обращения к СУБД, тогда как Дата (текущая дата документа) берется из памяти объекта. Это небольшая, но важная деталь для производительности высоконагруженных систем.

Использование конструктора движений: Если вы сомневаетесь, как должен выглядеть код проведения, воспользуйтесь встроенным в конфигуратор Конструктором движений. Он генерирует структуру кода, соответствующую стандартам фирмы «1С», и помогает избежать типичных ошибок при работе с регистрами сведений, накоплениями или бухгалтерии.

Резюме: Никогда не размещайте метод Записать() внутри цикла обработки табличных частей. Накапливайте все изменения в памяти (в наборе записей или коллекции Движения) и выполняйте сохранение в БД единожды по завершении формирования движений. Это позволит сделать работу вашей программы быстрой, а логику проведения — прозрачной и предсказуемой.

← На главную