Как распечатать форму ТОРГ-12 из документа РеализацияТоваровУслуг в 1С:УТ 11.5 без его проведения?

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

Коллеги, сегодня мы с вами разберем крайне актуальную для пользователей 1С:Управление торговлей (УТ) 11.5 проблему, связанную с печатью формы ТОРГ-12 для документа РеализацияТоваровУслуг, который не был проведен. Эта задача может показаться простой на первый взгляд, но имеет свои нюансы, поскольку стандартный механизм 1С не предполагает формирование этой формы без зафиксированных движений документа. Мы рассмотрим, почему возникает эта проблема, проанализируем начальные попытки решения и предложим несколько эффективных подходов, включая программную модификацию через расширения и создание внешних печатных форм.

Понимание корневой причины: табличная часть "ВидыЗапасов"

Прежде чем перейти к решениям, давайте выясним, почему возникает данная проблема. В 1С:УТ 11.5, как и в других современных конфигурациях, печатная форма ТОРГ-12 не собирает данные напрямую из табличной части Товары документа РеализацияТоваровУслуг. Вместо этого, для формирования значительной части информации, такой как номера ГТД, конкретные характеристики партий или специфические аналитики запасов, форма обращается к табличной части ВидыЗапасов. Это является ключевым моментом, о котором часто забывают при диагностике.

Табличная часть ВидыЗапасов заполняется и актуализируется только в момент проведения документа. Ее назначение – агрегировать и детализировать информацию о товарах с учетом всех необходимых аналитик для оперативного и бухгалтерского учета. При отмене проведения документа данные из этой табличной части, как правило, очищаются. Таким образом, если документ РеализацияТоваровУслуг не проведен, табличная часть ВидыЗапасов остается пустой или содержит неактуальную информацию, что неизбежно приводит к тому, что печатная форма ТОРГ-12 будет пустой в разделе товаров или недоступной, даже если табличная часть Товары заполнена.

Начальные попытки и их ограничения

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


// Изменяем параметр команды печати для ТОРГ-12
// КомандаПечати.ПроверкаПроведенияПередПечатью = Истина; // Исходная строка
КомандаПечати.ПроверкаПроведенияПередПечатью = Ложь; // Измененная строка

Данное изменение действительно убирает системное окно с требованием провести документ перед печатью. Однако, как мы уже выяснили, это не решает проблему отсутствия данных. Вместо этого, мы можем столкнуться с сообщениями типа "Печатная форма недоступна" или "В документе Реализация товаров и услуг №Док от ДатаВремя отсутствуют товары. Печать ТОРГ-12 не требуется", если в табличной части Товары отсутствуют услуги (которые иногда могут выводиться). Если же услуги присутствуют, то в ТОРГ-12 будут выведены только они, а товары так и останутся невидимыми, поскольку их детализация зависит от ВидыЗапасов.

Еще одна попытка может заключаться в удалении или изменении строки в процедуре ПередЗаписью модуля объекта документа РеализацияТоваровУслуг, которая связана с заполнением идентификаторов документа, включая ВидыЗапасов. Например, строка могла выглядеть так:


#Удаление
ОбщегоНазначенияУТ.ЗаполнитьИдентификаторыДокумента(ЭтотОбъект, "Товары,ВидыЗапасов");
#КонецУдаления

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

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

Программное решение: временное заполнение "ВидовЗапасов" в расширении

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

Мы будем действовать через расширение конфигурации, чтобы не затрагивать типовой код. Основная идея заключается в следующем: когда пользователь пытается распечатать ТОРГ-12 для непроведенного документа, мы:

  1. Перехватываем команду печати.
  2. Временно обеспечиваем заполнение табличной части ВидыЗапасов для текущего документа.
  3. Вызываем стандартную процедуру печати ТОРГ-12, которая теперь сможет получить нужные данные.
  4. После формирования печатной формы очищаем табличную часть ВидыЗапасов.
  5. Сохраняем документ в исходном непроведенном состоянии.

Разберем это по шагам:

1. Создание расширения и подписка на команду печати

Сначала создадим расширение и добавим в него документ РеализацияТоваровУслуг для модификации. Нам потребуется изменить поведение команды печати. В 1С:УТ 11.5 команды печати обычно регистрируются и управляются через механизм БСП. Мы можем перехватить команду печати, используя подписки на события или модифицируя модули расширения.

Для начала, мы можем воспользоваться механизмом, описанным в сообщении 10, для изменения режима записи команды печати, чтобы она не требовала проведения. Это делается через обработчик события ПриСозданииНаСервереПосле формы документа, где мы получаем таблицу команд и изменяем их свойства:


// В расширении, в модуле формы документа РеализацияТоваровУслуг (например, в обработчике ПриСозданииНаСервереПосле)
&НаСервере
Процедура ут_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

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

КонецПроцедуры

Этот код позволяет нам вызывать команду печати для непроведенного документа, но, как мы помним, он не решает проблему отсутствия данных в ТОРГ-12. Для этого нам нужна более глубокая модификация.

2. Выполнение операции, заполняющей "ВидыЗапасов"

Самая сложная часть — это программно заполнить ВидыЗапасов. В типовой конфигурации это происходит во время записи или проведения документа. Вспомним строку ОбщегоНазначенияУТ.ЗаполнитьИдентификаторыДокумента(ЭтотОбъект, "Товары,ВидыЗапасов");, которую мы упоминали ранее. Эта процедура или ее аналоги вызываются в модулях объекта документа.

В рамках расширения мы можем переопределить обработчик ПередЗаписью документа РеализацияТоваровУслуг, чтобы он заполнял ВидыЗапасов даже при простом сохранении (РежимЗаписиДокумента.Запись), а не только при проведении. Для этого нам потребуется создать вспомогательную процедуру в расширении и вызвать ее из измененного обработчика.

Модификация процедуры ПередЗаписью документа РеализацияТоваровУслуг через расширение:

  1. Создадим в расширении новый общий модуль (например, РеализацияТоваровУслуг_Расширение_Сервер) и в нем функцию, которая будет безопасно заполнять ВидыЗапасов.
  2. В модуле объекта РеализацияТоваровУслуг нашего расширения добавим обработчик ПередЗаписью.

// В модуле объекта документа РеализацияТоваровУслуг_Расширение
// Переопределяем процедуру ПередЗаписью
&После("ПередЗаписью")
Процедура РеализацияТоваровУслуг_ПередЗаписьюПосле(Отказ, РежимЗаписи, РежимПроведения)

    // Добавляем условие, которое позволит заполнять ВидыЗапасов
    // при обычной записи, если есть специальный флаг (например, для печати)
    // Это позволит стандартным механизмам УТ заполнить ВидыЗапасов
    // без фактического проведения документа в регистры.

    // Временный флаг, который мы будем устанавливать перед вызовом печати
    Если ДополнительныеСвойства.Свойство("ПечатьБезПроведения") И ДополнительныеСвойства.ПечатьБезПроведения Тогда
        // Запускаем заполнение идентификаторов, которое включает ВидыЗапасов
        // Важно убедиться, что ОбщегоНазначенияУТ доступен в контексте расширения
        // И что его вызов не приведет к нежелательным сайд-эффектам
        ОбщегоНазначенияУТ.ЗаполнитьИдентификаторыДокумента(ЭтотОбъект, "Товары,ВидыЗапасов");
    КонецЕсли;

КонецПроцедуры

Примечание: Чтобы ОбщегоНазначенияУТ.ЗаполнитьИдентификаторыДокумента был доступен, возможно, потребуется добавить его в расширение с флагом "Вызов сервера" или "Модификация", в зависимости от контекста вызова.

3. Обработка команды печати для временного заполнения и очистки

Теперь, когда мы имеем механизм для заполнения ВидовЗапасов при записи (если установлен специальный флаг), нам нужно перехватить команду печати и реализовать следующую логику:


// В модуле команды печати или в общем модуле расширения,
// который обрабатывает команды печати (например, ОбработкаПодключаемыхКоманд_Расширение)

Процедура ВыполнитьКомандуПечатиТОРГ12БезПроведения(МассивОбъектов) Экспорт

    Для Каждого СсылкаДокумента Из МассивОбъектов Цикл

        ДокументОбъект = СсылкаДокумента.ПолучитьОбъект();

        Если ДокументОбъект = Неопределено Тогда
            Продолжить;
        КонецЕсли;

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

            // Устанавливаем флаг, чтобы в ПередЗаписью произошло заполнение ВидовЗапасов
            ДокументОбъект.ДополнительныеСвойства.Вставить("ПечатьБезПроведения", Истина);

            // Записываем документ без проведения, чтобы сработал наш модифицированный ПередЗаписью
            // и заполнилась ТЧ ВидыЗапасов
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

            // Теперь вызываем стандартную процедуру печати ТОРГ-12
            // Она будет работать с заполненными ВидамиЗапасов
            ПараметрыПечати = Новый Структура;
            // Здесь могут быть дополнительные параметры, например, ВыводитьУслуги
            // ПараметрыПечати.Вставить("ВыводитьУслуги", Истина);

            ПечатьМассива = Новый Массив;
            ПечатьМассива.Добавить(СсылкаДокумента);

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

            // Очищаем ВидыЗапасов после печати
            ДокументОбъект.ВидыЗапасов.Очистить();
            ДокументОбъект.ДополнительныеСвойства.Удалить("ПечатьБезПроведения"); // Удаляем флаг

            // Возвращаем документ в исходное состояние (или просто перезаписываем без ВидовЗапасов)
            // Это важно, чтобы документ оставался непроведенным и без "левых" данных в ВидахЗапасов
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

        Исключение
            Сообщить("Ошибка при печати ТОРГ-12 для документа " + СсылкаДокумента + ": " + ОписаниеОшибки());
            // Восстанавливаем документ в случае ошибки
            Если ИсходноеСостояниеДокумента <> Неопределено Тогда
                ИсходноеСостояниеДокумента.СкопироватьВ(ДокументОбъект);
                ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
            КонецЕсли;
        КонецПопытки;
    КонецЦикла;

КонецПроцедуры

Важные моменты:

Создание внешней печатной формы (ВПФ)

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

Преимущества ВПФ:

  1. Независимость: ВПФ не изменяет типовую конфигурацию, что упрощает обновления системы.
  2. Гибкость: Мы можем полностью переписать запросы и алгоритмы формирования данных для ТОРГ-12, чтобы они напрямую обращались к табличной части Товары документа РеализацияТоваровУслуг, минуя ВидыЗапасов.
  3. Специфичность: В ВПФ можно учесть любые специфические требования к данным, которые по каким-либо причинам не попадают в стандартную форму.

Для создания ВПФ нам потребуется:

  1. Скопировать типовой макет: Извлечь типовой макет ТОРГ-12 из конфигурации.
  2. Анализировать запросы: Изучить функцию ПолучитьДанныеДляПечатнойФормыТОРГ12 из общего модуля РеализацияТоваровУслугЛокализация. Мы увидим, какие временные таблицы используются и как они заполняются. Наша задача будет адаптировать эти запросы.
  3. Переписать запросы: Модифицировать запросы в ВПФ так, чтобы они брали информацию непосредственно из табличной части Товары документа РеализацияТоваровУслуг. При этом придется вручную рассчитывать некоторые параметры (например, вес, объем, количество мест, если они зависят от видов упаковок), которые в типовой форме могли браться из ВидовЗапасов или связанных регистров.
  4. Регистрация ВПФ: Зарегистрировать ВПФ в 1С через механизм Дополнительные отчеты и обработки, указав, что она заменяет стандартную команду печати ТОРГ-12 для документа РеализацияТоваровУслуг.

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

Простой обходной путь: проведение и распроведение документа

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

Несмотря на недостатки, это быстрое решение "здесь и сейчас", если требуется срочно распечатать один или несколько документов, а времени на разработку расширений или ВПФ нет. Однако для систематического использования мы настоятельно рекомендуем рассмотреть программные методы.

Мы с вами рассмотрели различные подходы к решению проблемы печати формы ТОРГ-12 из непроведенного документа РеализацияТоваровУслуг в 1С:УТ 11.5. Наиболее эффективными и устойчивыми решениями являются программное управление заполнением табличной части ВидыЗапасов через расширение или создание собственной внешней печатной формы, напрямую работающей с табличной частью Товары. Выбор конкретного метода будет зависеть от ваших ресурсов, требований к гибкости и допустимого уровня вмешательства в типовую конфигурацию.

← На главную