Как массово распечатать акты сверки без создания лишних документов в 1С:Бухгалтерия 3.0 и преобразовать строковый формат даты в тип Дата

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

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

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

---

Групповая печать актов сверки «в памяти» без создания документов в ИБ

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

Гораздо более изящное решение — формировать объект документа в оперативной памяти, заполнять его по данным регистров бухгалтерии, передавать этот незаписанный объект в печатную форму и выводить результат в единый ТабличныйДокумент для отправки на принтер. Давайте разберем этот процесс по шагам.

Шаг 1. Инициализация и заполнение объекта «в памяти»

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


// Функция создает виртуальный документ "Акт сверки" и заполняет его данными расчетов
Функция СформироватьВиртуальныйАктСверки(Организация, Контрагент, НачалоПериода, КонецПериода) Экспорт
    
    // Создаем объект документа в оперативной памяти (в базу он пока не записан, Ссылка пустая)
    НовыйАкт = Документы.АктСверкиРасчетовСКонтрагентом.СоздатьДокумент();
    
    // Заполняем ключевые реквизиты шапки
    НовыйАкт.Дата = ТекущаяДата();
    НовыйАкт.Организация = Организация;
    НовыйАкт.Контрагент = Контрагент;
    НовыйАкт.ДатаНачала = НачалоПериода;
    НовыйАкт.ДатаОкончания = КонецПериода;
    НовыйАкт.ВалютаДокумента = Справочники.Валюты.НайтиПоКоду("643"); // Рубли РФ
    
    // Заполняем счета учета расчетов по умолчанию (60, 62, 76 и т.д.)
    // Используем стандартный метод конфигурации БП 3.0
    Документы.AктСверкиРасчетовСКонтрагентом.ЗаполнитьСчетаУчетаПоУмолчанию(НовыйАкт);
    
    // Вызываем типовые процедуры заполнения табличных частей документа по регистрам
    // Внимание: данные методы обращаются к базе данных за движениями, но сам объект не записывают!
    НовыйАкт.ЗаполнитьПоДаннымОрганизации();
    НовыйАкт.ЗаполнитьПоДаннымКонтрагента();
    
    Возврат НовыйАкт;
    
КонецФункции

Шаг 2. Обход ограничений подсистемы печати БСП

Стандартный механизм печати в библиотеке стандартных подсистем (БСП) жестко завязан на передачу массива ссылок (МассивСсылок). Поскольку наш документ существует только в памяти и не имеет ссылки (свойство Ссылка возвращает ПустаяСсылка()), передать его в стандартные экспортные методы печати напрямую не получится — программа выдаст ошибку.

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


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

Объединив этот код в цикл по выбранным контрагентам, мы сможем вывести все сформированные акты сверки в один общий табличный документ (используя метод ВывестиВертикальнуюОбластьТабличногоДокумента() или просто разделяя акты разрывом страницы через ВывестиГоризонтальныйРазделительСтраниц()), после чего отправить его на печать одной кнопкой.

---

Преобразование строкового формата даты «ММММ_гггг» обратно в тип Дата

Вторая техническая проблема, затронутая на форуме, касается обратного преобразования строки формата месяца и года в системный тип данных Дата. Такое форматирование часто используется для наглядного именования колонок во временных таблицах или отчетах, например: "Январь_2026".

Платформа 1С не имеет встроенных интеллектуальных средств для разбора локализованных текстовых названий месяцев. Стандартная функция Дата() не сможет распознать строку вида "Январь_2026" и вызовет исключение времени выполнения. Чтобы решить эту задачу, нам потребуется написать собственную парсер-функцию.

Рассмотрим готовую функцию, которая разбирает подобную строку на составляющие, сопоставляет русскоязычное название месяца с его порядковым номером и конструирует валидную дату на первое число этого месяца:


// Функция преобразует строку вида "Январь_2026" в объект Дата (01.01.2026 00:00:00)
Функция ПолучитьДатуИзФорматаММММ_гггг(Знач СтрокаДаты) Экспорт
    
    // Разделяем входящую строку по символу подчеркивания
    ЧастиСтроки = СтрРазделить(СтрокаДаты, "_");
    
    // Если разделитель не найден или формат нарушен, возвращаем пустую дату
    Если ЧастиСтроки.Количество() < 2 Тогда
        Возврат Дата(1, 1, 1);
    КонецЕсли;
    
    // Извлекаем название месяца и год, избавляясь от лишних пробелов
    ИмяМесяца = НРег(СокрЛП(ЧастиСтроки[0]));
    СтрокаГода = СокрЛП(ЧастиСтроки[1]);
    
    // Приводим год к числовому типу
    Попытка
        Год = Число(СтрокаГода);
    Исключение
        Возврат Дата(1, 1, 1); // Возвращаем пустую дату в случае ошибки приведения типа
    КонецПопытки;
    
    // Создаем соответствие русскоязычных названий месяцев их порядковым номерам
    СоответствиеМесяцев = Новый Соответствие;
    СоответствиеМесяцев.Вставить("январь", 1);
    СоответствиеМесяцев.Вставить("февраль", 2);
    СоответствиеМесяцев.Вставить("март", 3);
    СоответствиеМесяцев.Вставить("апрель", 4);
    СоответствиеМесяцев.Вставить("май", 5);
    СоответствиеМесяцев.Вставить("июнь", 6);
    СоответствиеМесяцев.Вставить("июль", 7);
    СоответствиеМесяцев.Вставить("август", 8);
    СоответствиеМесяцев.Вставить("сентябрь", 9);
    СоответствиеМесяцев.Вставить("октябрь", 10);
    СоответствиеМесяцев.Вставить("ноябрь", 11);
    СоответствиеМесяцев.Вставить("декабрь", 12);
    
    // Получаем номер месяца из соответствия
    НомерМесяца = СоответствиеМесяцев.Получить(ИмяМесяца);
    
    // Если название месяца написано некорректно или не найдено в списке
    Если НомерМесяца = Неопределено Тогда
        Возврат Дата(1, 1, 1);
    КонецЕсли;
    
    // Формируем результирующую дату на первое число месяца
    Попытка
        РезультатДата = Дата(Год, НомерМесяца, 1);
    Исключение
        РезультатДата = Дата(1, 1, 1);
    КонецПопытки;
    
    Возврат РезультатДата;
    
КонецФункции

Проанализируем ключевые моменты этой функции:

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

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

← На главную