Как правильно обратиться к движениям документа «Корректировка записей регистров» в 1С:УПП 1.3 и удалить нужные строки

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

При разработке обработок в «1С:Управление производственным предприятием 1.3» часто возникает необходимость программно отредактировать строки в документе Корректировка записей регистров. Начинающие разработчики часто пытаются найти привычную табличную часть с движениями, однако этот документ устроен иначе. В этой статье разберем особенности структуры документа, выясним причины распространенных ошибок при удалении строк и рассмотрим правильные алгоритмы работы с наборами записей.

Особенности структуры документа «Корректировка записей регистров»

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

Для доступа к этим данным используется коллекция Движения объекта документа.

Обращение к набору записей регистра

Проанализируем базовый порядок обращения к движениям конкретного регистра (например, регистра накопления НДСсАвансов):

  1. Получаем объект документа по ссылке через метод ПолучитьОбъект().
  2. Обращаемся к нужному регистру в коллекции Движения по его имени.
  3. Прочитываем текущие записи из базы данных с помощью метода Прочитать().
  4. Выполняем необходимую обработку строк.
  5. Записываем изменения в базу данных.

Посмотрим на базовый пример кода:


ДокументОбъект = СсылкаНаОбъект.ПолучитьОбъект();
НаборЗаписи = ДокументОбъект.Движения["НДСсАвансов"];

// Загружаем текущие движения документа из базы
НаборЗаписи.Прочитать();

// Выполняем действия с записями...

// Сохраняем движения
НаборЗаписи.Записать();

Анализ ошибок при удалении строк и сравнении ссылок

Часто при попытке профильтровать и удалить строки разработчики сталкиваются с ошибкой Недопустимое значение параметра (параметр номер '1') при вызове метода Удалить(). Выясним причину этой проблемы.

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

Также обратим внимание на сравнение ссылочных типов. Использование конструкции СокрЛП(Строка(Ссылка1)) = СокрЛП(Строка(Ссылка2)) является критической ошибкой. Приведение ссылок к строкам существенно снижает производительность и может давать ложные результаты из-за совпадения наименований разных объектов. Ссылки 1С следует сравнивать напрямую через оператор =.

Способ 1. Безопасное удаление с помощью массива и флага

Разберем по шагам правильный алгоритм обхода коллекций с использованием флага совпадения. Мы собираем только уникальные записи на удаление и затем удаляем их из коллекции.


ДокументОбъект = СсылкаНаОбъект.ПолучитьОбъект();
ДвиженияРегистра = ДокументОбъект.Движения["НДСсАвансов"];
ДвиженияРегистра.Прочитать();

МассивУдаляемых = Новый Массив;

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

// Удаляем собранные элементы
Для Каждого ЭлементНаУдаление Из МассивУдаляемых Цикл
    ДвиженияРегистра.Удалить(ЭлементНаУдаление);
КонецЦикла;

// Взводим флаг записи и сохраняем изменения
ДвиженияРегистра.Записывать = Истина;
ДокументОбъект.Записать();

Способ 2. Выгрузка в Таблицу Значений (рекомендуемый подход)

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

Посмотрим на реализацию этого способа:


ДокументОбъект = СсылкаНаОбъект.ПолучитьОбъект();
НаборДвижений = ДокументОбъект.Движения["НДСсАвансов"];
НаборДвижений.Прочитать();

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

// Добавляем временное служебное поле для отметки
ТЗДвижений.Колонки.Добавить("Удалить", Новый ОписаниеТипов("Булево"));

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

// Отбираем и удаляем помеченные строки
ПараметрыОтбора = Новый Структура("Удалить", Истина);
УдаляемыеСтроки = ТЗДвижений.НайтиСтроки(ПараметрыОтбора);

Для Каждого СтрокаДляУдаления Из УдаляемыеСтроки Цикл
    ТЗДвижений.Строки.Удалить(СтрокаДляУдаления);
КонецЦикла;

// Удаляем служебную колонку перед загрузкой
ТЗДвижений.Колонки.Удалить("Удалить");

// Очищаем набор и загружаем отфильтрованные данные
НаборДвижений.Очистить();
НаборДвижений.Загрузить(ТЗДвижений);
НаборДвижений.Записывать = Истина;

ДокументОбъект.Записать();

Важные рекомендации при работе в конфигурации УПП 1.3

  1. Явная установка флага записи: При изменении движений через объект документа рекомендуем перед вызовом ДокументОбъект.Записать() всегда явно указывать НаборДвижений.Записывать = Истина;.Это гарантирует, что платформа корректно сбросит изменения в базу данных.
  2. Очистка состава регистров документа: Если из регистра удаляются абсолютно все строки, необходимо проверить служебную табличную часть документа (список задействованных регистров). Если имя регистра останется в табличной части, на форме документа сохранится пустая закладка регистра.
← На главную