Как в 1С 8.3 программно перебрать все проводки в документе «Операция (бухгалтерский учет)»?

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

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

Почему стандартный обход коллекции «Движения» может не работать?

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


док = Документы.ОперацияБух.НайтиПоНомеру("0А00-001376", Дата("20161231"));
Для Каждого Строка из док.Движения.Хозрасчетный Цикл
    // Код обработки
КонецЦикла;

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

Способ №1: Использование коллекции «Движения» через объект документа

Если вам нужно прочитать или изменить проводки конкретного документа, и у вас уже есть его объект, этот способ будет наиболее интуитивным. Для быстрой генерации шаблонов кода используйте консоль кода + ИИ-помощник (GigaChat). Рассмотрим правильный алгоритм действий:

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

Посмотрим на пример кода:


ДокСсылка = Документы.ОперацияБух.НайтиПоНомеру("001", ТекущаяДата());
ДокОбъект = ДокСсылка.ПолучитьОбъект();

// Обращаемся к коллекции движений регистра Хозрасчетный
ДвиженияХозрасчетный = ДокОбъект.Движения.Хозрасчетный;

// КРИТИЧЕСКИ ВАЖНО: читаем данные из БД
ДвиженияХозрасчетный.Прочитать();

Для Каждого Запись из ДвиженияХозрасчетный Цикл
    Если Запись.Сумма > 1000 Тогда
        // Выполняем действия с проводкой
        Сообщить("Счет Дт: " + Запись.СчетДт + " Сумма: " + Запись.Сумма);
    КонецЕсли;
КонецЦикла;

Важный нюанс: если вы планируете изменять проводки этим способом, не забудьте установить флаг ДвиженияХозрасчетный.Записывать = Истина; перед сохранением объекта документа.

Способ №2: Использование Набора Записей (рекомендуемый для записи)

Использование НабораЗаписей — это более универсальный и «чистый» способ работы с регистрами. Он позволяет работать с данными, не загружая в память весь объект документа, что удобно, когда требуется массовое включение / отключение активности бухгалтерских проводок документа.

Рассмотрим по шагам, как работать с набором записей:


// Создаем набор записей регистра бухгалтерии
Проводки = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();

// Устанавливаем отбор по регистратору (нашему документу)
Проводки.Отбор.Регистратор.Установить(ДокСсылка);

// Читаем проводки из базы
Проводки.Прочитать();

Для Каждого Пров из Проводки Цикл
    // Пример: установка субконто для 91 счета
    Если Пров.СчетКт.Код = "91.01" Тогда
        // Используем типовой механизм для установки субконто
        БухгалтерскийУчет.УстановитьСубконто(Пров.СчетКт, Пров.СубконтоКт, "ПрочиеДоходыИРасходы", ЗначениеСубконто);
    КонецЕсли;
КонецЦикла;

// Записываем изменения обратно в базу данных
Проводки.Записать(ИСТИНА);

Обратите внимание на метод Записать(ИСТИНА). Параметр Истина означает, что мы полностью замещаем существующие записи в базе данных теми, что подготовили в памяти. Подобную логику реализует интерактивный обработчик объектов для массовых изменений.

Способ №3: Запрос к физической таблице (самый быстрый для чтения)

Если ваша задача — только проанализировать данные без их изменения (особенно если нужно обработать сотни или тысячи документов), использование объектов или наборов записей в цикле будет крайне медленным. В этом случае мы рекомендуем использовать Запрос.

Проанализируем, к какой таблице лучше обращаться. Часто разработчики выбирают таблицу ДвиженияССубконто, однако она является виртуальной и достаточно тяжелой для системы. Если вам нужны базовые поля проводки и значения субконто, лучше обращаться к физической таблице РегистрБухгалтерии.Хозрасчетный.

Пример эффективного запроса:


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

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

Пока Выборка.Следующий() Цикл
    // Быстрая обработка данных
КонецЦикла;

Почему важно проверять поле «Активность»? В документе «Операция» пользователь может вручную выключить активность конкретных проводок (снять флажок «Использование»). Если вы не добавите условие Активность = Истина, ваш код обработает даже те записи, которые не влияют на баланс и отчетность.

Тонкости работы с субконто

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

Пров.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты] = НужныйКонтрагент;

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

Подведем итоги

Выясним, какой метод выбрать в зависимости от ситуации:

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

← На главную