Как правильно удалить или скорректировать лишние проводки в регистре бухгалтерии через расширение

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

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

Анализ ситуации: почему изменения в наборе записей могут не сохраняться

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

  1. Свойство «Записывать» у движений. В 1С у каждого набора записей в коллекции Движения документа есть флаг Записывать. Если в основном коде проведения документа (после выполнения вашего кода в расширении) этому флагу присваивается значение Ложь, то даже модифицированный вами набор не будет зафиксирован в базе данных.
  2. Перезапись набора в основном коде. Если вы используете аннотацию &Перед в расширении для модуля набора записей, ваш код выполняется до основного алгоритма. Если далее типовой механизм полностью очищает и заново заполняет коллекцию движений, ваши правки будут потеряны.
  3. Контекст вызова. Если документ перепроводится программно без фактического изменения данных, система может оптимизировать запись и не вызывать запись наборов, которые помечены как немодифицированные.

Для решения этих проблем рассмотрим несколько надежных подходов к модификации проводок.

Способ 1: Использование метода «Выгрузить» и «Загрузить»

Этот метод считается одним из самых безопасных и удобных для групповой обработки записей. Его суть заключается в том, что мы переводим данные из специализированного объекта НаборЗаписей в универсальный объект ТаблицаЗначений, где имеем полный арсенал инструментов для фильтрации.

Рассмотрим пошагово, как это реализовать:


// В обработчике ПередЗаписью набора записей регистра
ТаблицаДвижений = ЭтотОбъект.Выгрузить();

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

СтрокиДляУдаления = ТаблицаДвижений.НайтиСтроки(ПараметрыОтбора);

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

// Загружаем модифицированную таблицу обратно в набор
ЭтотОбъект.Загрузить(ТаблицаДвижений);

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

Способ 2: Удаление из набора записей с конца (обратный цикл)

Если вы предпочитаете работать напрямую с объектом НаборЗаписей без выгрузки в таблицу, важно помнить о правиле «обратного обхода». Если удалять записи в цикле от 0 до N, то после удаления 0-й записи бывшая 1-я станет 0-й, и цикл ее пропустит при следующем шаге.

Разберем пример корректного удаления:


КоличествоЗаписей = ЭтотОбъект.Количество();

// Идем от последней записи к первой
Для Индекс = 1 По КоличествоЗаписей Цикл
    ТекущаяЗапись = ЭтотОбъект[КоличествоЗаписей - Индекс];
    
    // Проверяем условие для удаления
    Если ТекущаяЗапись.Сумма = 0 Тогда 
        ЭтотОбъект.Удалить(ТекущаяЗапись);
    КонецЕсли;
КонецЦикла;

Также можно использовать вспомогательный массив. Сначала проанализируем ситуацию и соберем все объекты РегистрБухгалтерииЗапись.Хозрасчетный, подлежащие удалению, в массив, а затем вторым циклом пройдем по массиву и выполним метод ЭтотОбъект.Удалить(ЭлементМассива).

Способ 3: Модификация в модуле документа (ОбработкаПроведения)

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

Посмотрим на пример использования аннотации &После("ОбработкаПроведения"):


&После("ОбработкаПроведения")
Процедура ИмяРасш_ОбработкаПроведенияПосле(Отказ, РежимПроведения)
    
    // Обращаемся к конкретному регистру
    НаборХозрасчетный = ЭтотОбъект.Движения.Хозрасчетный;
    
    // Если нужно полностью очистить движения по регистру при определенных условиях
    Если НужноеУсловие Тогда
        НаборХозрасчетный.Очистить();
    КонецЕсли;
    
    // КРИТИЧЕСКИ ВАЖНО: Установить флаг записи в Истина, 
    // иначе изменения не попадут в базу!
    НаборХозрасчетный.Записывать = Истина;
    
КонецПроцедуры

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

Практические советы по работе с регистром «Хозрасчетный»

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

Например, в документе:

Движения.Хозрасчетный.ДополнительныеСвойства.Вставить("ПроверкаВыполнена", Истина);

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

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

← На главную