Почему дополнительная внешняя печатная форма в 1С БСП печатает старые данные из ссылки и как это исправить?

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

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

В чем причина: архитектура клиент-серверного взаимодействия БСП

Для начала проанализируем, как БСП передает данные в печатную форму. Когда мы регистрируем стандартную ВПФ, в ее модуле объекта обязательна к реализации процедура Печать(). Обратите внимание на ее сигнатуру: в нее передается параметр МассивОбъектов. Этот массив содержит не сами объекты документов со всеми их экранными изменениями, а массив ссылок типа ДокументСсылка.

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

Как БСП решает эту проблему в штатном режиме? Перед тем как отправить команду на сервер, подсистема печати БСП на клиенте анализирует состояние формы. Она обращается к свойству управляемой формы Модифицированность:

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

Суть ошибки: если данные в документе были изменены программным путем (например, в коде формы через обработчик заполнения, при выборе связанных реквизитов или при интерактивном заполнении через стороннюю обработку), платформа 1С далеко не всегда автоматически взводит флаг модифицированности. Визуально данные на форме обновились, пользователь их видит, но для платформы свойство Модифицированность остается равным Ложь. БСП пропускает этап автозаписи, отправляет на сервер ссылку, и печатная форма берет неактуальные данные напрямую из СУБД.

---

Решение 1. Принудительная установка модифицированности (Решение автора темы)

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


&НаКлиенте
Процедура ПослеПрограммногоИзмененияДанных()
    
    // Ваш код изменения реквизитов, например:
    Объект.Комментарий = "Заполнено автоматически при выборе контрагента";
    
    // Принудительно сообщаем платформе, что форма изменена
    ЭтаФорма.Модифицированность = Истина;
    
КонецПроцедуры

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

---

Решение 2. Корректная настройка параметров команды печати при регистрации ВПФ

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

  1. Параметр НеВыполнятьЗаписьВФорме. По умолчанию данный параметр имеет значение Ложь. Это означает, что БСП обязана попытаться записать модифицированную форму. Если вы по ошибке установили его в значение Истина, автозапись выполняться не будет, даже если модифицированность установлена. Убедитесь, что этот параметр не блокирует запись.
  2. Параметр ПроверкаПроведенияПередПечатью. Если этот параметр установлен в значение Истина, БСП будет требовать, чтобы документ был не просто записан, а проведен. Для многих печатных форм проведение не требуется — достаточно простой записи. Установите данный параметр в значение Ложь, если вам нужна только запись изменений без проведения.

Рассмотрим пример правильной настройки команды в процедуре регистрации внешней печатной формы:


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

---

Решение 3. Печать «на лету» без записи в базу данных (Виртуальная печать)

Бывают ситуации, когда бизнес-логика требует распечатать измененные на экране данные вообще без их сохранения в базу данных. Например, менеджер рассчитывает предварительную стоимость заказа покупателю, хочет распечатать коммерческое предложение («черновик»), но не имеет права или не хочет сохранять этот тестовый документ в системе.

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

Проанализируем алгоритм реализации виртуальной печати:

  1. При регистрации команды печати указываем тип использования — вызов клиентского метода.
  2. В модуле управляемой формы внешней печатной формы создаем экспортную процедуру Печать(), которая будет выполняться на клиенте.
  3. Через свойство ВладелецФормы мы получаем доступ к контексту формы документа, с которой была вызвана печать. Мы можем напрямую прочитать любые экранные данные, включая незаписанные табличные части, не обращаясь к базе данных.
  4. Передаем эти данные (например, упаковав их в структуру или таблицу значений) на серверную часть нашей внешней обработки, где формируем ТабличныйДокумент.
  5. Возвращаем сформированный табличный документ на клиент и открываем его в стандартной форме просмотра печатных форм БСП.

Рассмотрим пример реализации клиентского метода во внешней обработке:


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

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

Выбирайте подходящий метод в зависимости от бизнес-требований вашей задачи: для стандартного сохранения используйте своевременный контроль свойства Модифицированность = Истина, а для сложной логики без записи — интерактивную печать через клиентские методы.

← На главную