В процессе автоматизации работы пользователей в 1С часто возникает задача: минимизировать количество действий при оформлении документов. Типичный пример — автоматическое формирование и печать Счета-фактуры (СФ) сразу после печати Реализации товаров и услуг. В данной статье мы подробно разберем, как реализовать этот механизм, избежать дублирования документов в базе и исправить распространенные ошибки при обращении к макетам печатных форм.
При попытке вызвать процедуру печати напрямую из кода другого документа разработчики часто сталкиваются с ошибкой: «Значение не является значением объектного типа (ПолучитьОбласть)». Давайте проанализируем ситуацию, когда код выглядит следующим образом:
НовДокумент = Документы.СчетФактура.СоздатьДокумент();
НовДокумент.Заполнить(ЭтотОбъект.Ссылка);
НовДокумент.Записать(РежимЗаписиДокумента.Запись);
НовДокумент.Печать_УПД("УПД");
Ошибка возникает внутри метода Печать_УПД в строке, где происходит обращение к переменной Макет. Выясним причину: в типовых или самописных конфигурациях (например, «Далион») переменная Макет инициализируется через ЭтотОбъект.ПолучитьМакет(). Однако при программном создании объекта и немедленном вызове его методов контекст формы или специфические параметры инициализации могут быть не определены. Проанализируем состояние переменных через Отладчик: скорее всего, в момент вызова процедура не понимает, какой именно макет использовать, и переменная Макет имеет значение Неопределено.
Прежде чем переходить к печати, необходимо убедиться, что мы не создаем лишние документы. Создание новой СФ при каждой печати Реализации — это критическая ошибка, которая приведет к хаосу в бухгалтерском учете и Книге продаж. Проанализируем алгоритм проверки наличия существующего документа.
Перед вызовом СоздатьДокумент() мы должны выполнить поиск уже существующей ссылки. Сделаем это с помощью запроса:
Функция НайтиИлиСоздатьСчетФактуру(ДокументОснование)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СчетФактура.Ссылка КАК Ссылка
|ИЗ
| Документ.СчетФактура КАК СчетФактура
|ГДЕ
| СчетФактура.ДокументОснование = &Основание
| И НЕ СчетФактура.ПометкаУдаления";
Запрос.УстановитьПараметр("Основание", ДокументОснование);
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка.ПолучитьОбъект();
Иначе
НовСФ = Документы.СчетФактура.СоздатьДокумент();
НовСФ.Дата = ТекущаяДата();
НовСФ.Заполнить(ДокументОснование);
НовСФ.Записать(РежимЗаписиДокумента.Запись);
Возврат НовСФ;
КонецЕсли;
КонецФункции
Этот подход гарантирует, что если СФ уже была создана ранее, система просто найдет ее и подготовит к печати, а не создаст дубль.
Рассмотрим способы вывода печатной формы на экран или принтер. Если вы используете конфигурацию на обычных формах (как во многих версиях «Далион»), наиболее надежным способом будет не вызов экспортной процедуры модуля объекта, а использование менеджера документа или механизмов печати, заложенных в систему.
Если же вы решили использовать метод объекта, убедитесь, что все параметры переданы верно. Разберем пример вызова, который минимизирует ошибки контекста:
ОбъектСФ = НайтиИлиСоздатьСчетФактуру(ЭтотОбъект.Ссылка);
// Вместо вызова процедуры напрямую, попробуем сформировать ТабличныйДокумент
ТабДок = ОбъектСФ.Печать_УПД("УПД");
// Если метод возвращает ТабличныйДокумент, выводим его
Если ТабДок <> Неопределено Тогда
ТабДок.Показать("Печать Счета-фактуры");
КонецЕсли;
Важный момент: если процедура Печать_УПД внутри модуля объекта требует наличия макета, попробуйте передать макет явно или инициализировать его внутри процедуры, используя Документы.СчетФактура.ПолучитьМакет("ВашМакет") вместо ЭтотОбъект.ПолучитьМакет().
Чтобы пользователю не приходилось нажимать кнопку печати дважды, мы можем объединить накладную и счет-фактуру в одном окне просмотра. Проанализируем, как это сделать программно. Посмотрим на пример кода в модуле документа РеализацияТоваровУслуг:
Процедура ПечатьПакетаДокументов()
// 1. Формируем табличный документ реализации
ТабДокРеализация = ПечатьРеализации();
// 2. Ищем или создаем СФ, получаем ее печатную форму
ОбъектСФ = НайтиИлиСоздатьСчетФактуру(ЭтотОбъект.Ссылка);
ТабДокСФ = ОбъектСФ.Печать_УПД("УПД");
// 3. Объединяем документы
// Добавляем разрыв страницы между документами
ТабДокРеализация.ВывестиГоризонтальныйРазделительСтраниц();
ТабДокРеализация.Вывести(ТабДокСФ);
// 4. Показываем результат
ТабДокРеализация.Показать("Пакет документов: Реализация и СФ");
КонецПроцедуры
Использование метода Вывести() позволяет склеить два разных табличных документа в один. Это самый удобный вариант для «ленивых» пользователей, так как им достаточно нажать «Печать» один раз и отправить на принтер сразу весь пакет.
Выясним ситуацию с Универсальным передаточным документом (УПД). Современное законодательство позволяет использовать один документ вместо пары «Накладная + Счет-фактура». Если ваша конфигурация поддерживает УПД со статусом «1» (и как первичный документ, и как счет-фактура), то задача существенно упрощается.
В этом случае вам достаточно перенастроить стандартную кнопку печати так, чтобы она формировала УПД. Это исключит необходимость программного создания второго объекта (СФ) в базе данных, так как все данные для УПД будут браться напрямую из документа Реализация. Однако, если политика компании требует наличия отдельного номера счета-фактуры в реестре, то вариант с программным созданием документа СФ, описанный выше, остается приоритетным.
Рассмотрим еще один профессиональный подход: автоматическое создание СФ при проведении Реализации. Чтобы не изменять модуль самого документа, можно воспользоваться объектом Подписка на событие (например, ОбработкаПроведения).
ОбщийМодуль (если его нет).Источник (наш документ) и Отказ.НайтиИлиСоздатьСчетФактуру(Источник.Ссылка).ДокументОбъект.РеализацияТоваровУслуг, событие — ОбработкаПроведения, и выбираем нашу процедуру.Таким образом, счета-фактуры будут гарантированно создаваться в базе при каждом проведении реализации, и при нажатии кнопки печати вам останется только найти существующую ссылку и вывести ее форму, не беспокоясь о записи или заполнении данных.
Важное примечание: при автоматическом создании СФ всегда учитывайте время документа. Обычно СФ создается той же датой, но на несколько секунд позже реализации, чтобы соблюсти логическую последовательность цепочки документов в базе данных 1С.