Как программно изменить записи регистра накопления в 1С:Предприятие 8

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

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

Основы работы с движениями регистра

Для начала проанализируем ситуацию: записи в регистрах накопления в 1С всегда жестко привязаны к документу-регистратору. Мы не можем просто так взять и изменить одну строку регистра, как в таблице Excel. Любое изменение должно происходить через объект НаборЗаписей. Рассмотрим пошагово, как это реализовать.

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

  1. Создаем объект НаборЗаписей для конкретного регистра.
  2. Устанавливаем фильтр (отбор) по Регистратору. Это обязательное условие для регистров накопления.
  3. Читаем существующие записи из базы данных в память.
  4. Производим необходимые изменения в коллекции записей.
  5. Записываем измененный набор обратно в базу данных.

Разбор практического примера: Массовое изменение реквизита

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


// 1. Сначала найдем все регистраторы, по которым есть пустые значения
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ТоварыОрганизаций.Регистратор КАК Регистратор
    |ИЗ
    |   РегистрНакопления.ТоварыОрганизаций КАК ТоварыОрганизаций
    |ГДЕ
    |   ТоварыОрганизаций.Качество = &ПустоеКачество
    |СГРУППИРОВАТЬ ПО
    |   ТоварыОрганизаций.Регистратор";

Запрос.УстановитьПараметр("ПустоеКачество", Справочники.Качество.ПустаяСсылка());
РезультатЗапроса = Запрос.Выполнить().Выбрать();

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

Проблема «задвоения» записей и ее решение

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

Метод Записать(Замещать) принимает булев параметр. Если мы передаем Истина, 1С сначала удаляет из регистра все записи, соответствующие установленному отбору (в нашем случае — по регистратору), а затем записывает новые данные из набора. Если же передать Ложь, система просто добавит записи из набора к тем, что уже есть в базе. Важно всегда использовать Записать(Истина) при редактировании существующих движений, чтобы избежать дублей.

Оптимизация через выгрузку в Таблицу Значений

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


Набор = РегистрыНакопления.НДФЛРасчетыСБюджетом.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(ВыбранныйДокумент);
Набор.Прочитать();

// Выгружаем в ТЗ для быстрой обработки
ТаблицаДвижений = Набор.Выгрузить();

// Массово заполняем колонку
ТаблицаДвижений.ЗаполнитьЗначения(НовоеПодразделение, "Подразделение");

// Загружаем обратно в набор и сохраняем
Набор.Загрузить(ТаблицаДвижений);
Набор.Записать(Истина);

Риски перепроведения и флаг «Ручная корректировка»

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

Чтобы этого избежать, в типовых конфигурациях (БП 3.0, ЗУП 3.1) предусмотрен механизм «Ручной корректировки». Рассмотрим, как его задействовать:

  1. У документа, движения которого мы правим, должен быть реквизит РучнаяКорректировка (тип Булево).
  2. Перед записью набора записей регистра мы должны установить этот флаг в значение Истина у самого документа-регистратора.
  3. Если флаг установлен, стандартный код проведения документа обычно пропускает очистку и запись движений, сохраняя ваши изменения нетронутыми.

Работа с блокировками данных

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


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыОрганизаций");
ЭлементБлокировки.УстановитьПараметр("Регистратор", РегистраторСсылка);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

Блокировка.Заблокировать();
// Далее следует код чтения, изменения и записи набора...

Итоги и рекомендации

Мы рассмотрели основные способы программного изменения реквизитов записей регистра накопления. Подведем итоги:

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

← На главную