Как исправить ошибки "Недостаточно фактических параметров" и "Переменная не определена" при групповой печати УПД в 1С?

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

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

Анализируем исходный код и выявляем проблему

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

В модуле формы документа «_Распределение» присутствуют следующие ключевые фрагменты:


&НаСервере
Функция ПечатьНаСервере () Экспорт
    // ... формирование МассивНаправлений, МассивРаспределений, МассивРеализаций, МассивСФ ...

    ТабДокумент = Новый ТабличныйДокумент;
    // ... настройка ТабДокумент ...

    Если ПечатьУПД Тогда
        // Здесь происходит первый проблемный вызов
        ТабДокУПД = Документы.Распределение.СформироватьНесколькоУПД(МассивСФ, МассивНаправлений);
        ТабДокумент.Вывести(ТабДокУПД);
    КонецЕсли;
    Возврат ТабДокумент;
КонецФункции

И в модуле менеджера документа «_Распределение» определена функция, которую мы пытаемся вызвать:


Функция СформироватьНесколькоУПД(МассивОбъектов, МассивНаправлений = "ВСЕ", ДанныеДляПечати, ОбъектыПечати) Экспорт
    ТабличныйДокумент = Новый ТабличныйДокумент;
    // ... настройка ТабличныйДокумент ...

    Для каждого Ссылка из МассивОбъектов Цикл
        // Внутренний вызов типовой функции печати УПД
        ТабДокументОбъекта = Обработки.ПечатьОбщихФорм.ЗаполнитьТабличныйДокументУПД(ТабличныйДокумент,ДанныеДляПечати,ОбъектыПечати);
        // ... объединение табличных документов ...
        ТабличныйДокумент.Вывести(ТабДокументОбъекта);
    КонецЦикла;
    Возврат ТабличныйДокумент;
КонецФункции

Мы видим, что функция СформироватьНесколькоУПД объявлена с четырьмя параметрами: МассивОбъектов, МассивНаправлений, ДанныеДляПечати и ОбъектыПечати. При этом, параметр МассивНаправлений имеет значение по умолчанию "ВСЕ", что делает его необязательным при вызове, если мы передадим остальные параметры в правильном порядке.

Причина ошибки "Недостаточно фактических параметров"

Первая ошибка, с которой мы сталкиваемся, – "Недостаточно фактических параметров". Она возникает, когда функция вызывается с меньшим количеством аргументов, чем было указано в её определении. Давайте посмотрим на определение функции СформироватьНесколькоУПД еще раз:


Функция СформироватьНесколькоУПД(МассивОбъектов, МассивНаправлений = "ВСЕ", ДанныеДляПечати, ОбъектыПечати) Экспорт

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


ТабДокУПД = Документы.Распределение.СформироватьНесколькоУПД(МассивСФ, МассивНаправлений);

В этом вызове передаются только два параметра: МассивСФ и МассивНаправлений. Соответственно, для параметров ДанныеДляПечати и ОбъектыПечати не были переданы значения, что и приводит к ошибке "Недостаточно фактических параметров". 1С не знает, какие значения ей подставить для этих обязательных параметров.

Для устранения этой ошибки нам необходимо передать все обязательные параметры при вызове функции. Если мы не планируем использовать эти параметры для каких-либо специфических настроек в данный момент, мы можем передать пустые, но корректные по типу значения, например, пустую структуру для ДанныеДляПечати и пустой массив для ОбъектыПечати. Тем не менее, как мы увидим далее, для корректной работы БСП эти параметры несут важное смысловое значение.

Причина ошибки "Переменная не определена"

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

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

Назначение параметров ДанныеДляПечати и ОбъектыПечати в БСП

Мы используем функции печати, которые, судя по названиям, относятся к Библиотеке стандартных подсистем (БСП) – Обработки.ПечатьОбщихФорм.ЗаполнитьТабличныйДокументУПД. В БСП существует унифицированный механизм печати, который предполагает передачу определённого набора параметров для формирования печатных форм. Давайте разберем их назначение:

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

Для решения проблемы "Переменная не определена" нам нужно объявить и инициализировать эти переменные в функции ПечатьНаСервере до того, как они будут использованы в вызове СформироватьНесколькоУПД.

Итоговое решение: корректировка функции ПечатьНаСервере

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

Вот как будет выглядеть исправленный код в модуле формы:


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

    Для Каждого СтрТЧ ИЗ МассивРаспределений Цикл
        Для Каждого СтрЗаказы ИЗ СтрТЧ.Заказы Цикл
             МассивРеализаций.Добавить(СтрЗаказы.Накладная);
             МассивСФ.Добавить(СтрЗаказы.СчетФактура);
        КонецЦикла;
    КонецЦикла;

    ТабДокумент = Новый ТабличныйДокумент;
    ТабДокумент.АвтоМасштаб = Истина;
    ТабДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Портрет;
    ТабДокумент.ОтображатьЗаголовки = Ложь;
    ТабДокумент.ОтображатьСетку = Ложь;
    ТабДокумент.Защита = Истина;

    Если ПечатьУПД Тогда
        // 1. Объявляем и инициализируем ДанныеДляПечати и ОбъектыПечати
        // Для ДанныеДляПечати создаем пустую структуру, если нет специфических параметров
        ДанныеДляПечати = Новый Структура();
        
        // Для ОбъектыПечати используем МассивСФ, так как это коллекция объектов, для которых формируется УПД
        ОбъектыПечати = МассивСФ; 

        // 2. Корректный вызов функции СформироватьНесколькоУПД со всеми обязательными параметрами
        // МассивСФ - это МассивОбъектов для СформироватьНесколькоУПД
        // МассивНаправлений - второй параметр
        // ДанныеДляПечати - третий параметр
        // ОбъектыПечати - четвертый параметр
        ТабДокУПД = Документы._Распределение.СформироватьНесколькоУПД(МассивСФ, МассивНаправлений, ДанныеДляПечати, ОбъектыПечати);
        ТабДокумент.Вывести(ТабДокУПД);
    КонецЕсли;

    Возврат ТабДокумент;
КонецФункции

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

  1. Мы объявили и инициализировали переменные ДанныеДляПечати и ОбъектыПечати перед их использованием. ДанныеДляПечати теперь является пустой структурой, что позволяет избежать ошибки, если никаких специфических настроек печати в данный момент не требуется. ОбъектыПечати теперь содержит МассивСФ, что является логичным, так как мы печатаем УПД именно на основании счетов-фактур.
  2. Мы передали все четыре параметра (МассивСФ, МассивНаправлений, ДанныеДляПечати, ОбъектыПечати) в функцию СформироватьНесколькоУПД, соблюдая порядок и количество, указанное в её определении.

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

Дополнительные рекомендации и анализ типовых механизмов печати

Для более глубокого понимания и избежания подобных ошибок в будущем, давайте рассмотрим несколько дополнительных аспектов:

  1. Использование отладчика

    Как верно было подмечено в сообщении 1 на форуме, отладчик является вашим лучшим другом. Он позволяет пошагово проверить значения переменных или сравнить объекты перед вызовом функции СформироватьНесколькоУПД, чтобы убедиться в корректности передаваемых данных, включая параметры ДанныеДляПечати и ОбъектыПечати.

    Для использования отладчика:

    1. Откройте конфигуратор.
    2. Найдите строку кода, где происходит вызов ТабДокУПД = Документы._Распределение.СформироватьНесколькоУПД(...).
    3. Нажмите F9 или установите точку останова, кликнув мышью на поле слева от номера строки.
    4. Запустите режим отладки (обычно Shift+F9 или через меню "Отладка").
    5. Выполните действия в пользовательском режиме (например, запуск фонового задания), которые приводят к вызову вашей функции печати.
    6. При достижении точки останова вы сможете пошагово выполнять код (F10 - шаг через, F11 - шаг в) и просматривать значения переменных на панели "Табло" или "Выражения".
  2. Взаимодействие с БСП (Библиотека стандартных подсистем)

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

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

    Когда вы видите, что функция БСП, например, Обработки.ПечатьОбщихФорм.ЗаполнитьТабличныйДокументУПД(), принимает параметры ДанныеДляПечати и ОбъектыПечати, это означает, что она, скорее всего, будет использовать эти параметры для:

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

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

  3. Организация кода для групповой печати

    Ваша общая структура для групповой печати, включающая использование ОбщаяФорма.ПечатьДокументов из БСП, является хорошей практикой. Это позволяет разделить логику интерфейса и бизнес-логику, используя типовой механизм печати БСП для вывода табличных документов.

    Помните, что данные, которые вы формируете на сервере (ТабДок), затем передаются на клиент для отображения и дальнейшей работы с типовой формой печати. Структура ЭлементКоллекцииДляПечати и КоллекцияПечатныхФорм предназначена именно для этого – унифицированной передачи печатных форм в общую форму печати БСП.

  4. Передача параметра МассивОбъектов в СформироватьНесколькоУПД

    В функции СформироватьНесколькоУПД вы используете МассивОбъектов для итерации по ссылкам на документы:

    
    Для каждого Ссылка из МассивОбъектов Цикл
        // ...
    КонецЦикла;
    

    В вашем случае, в ПечатьНаСервере вы корректно передаете МассивСФ как первый параметр (МассивОбъектов) в СформироватьНесколькоУПД. Это означает, что для каждой ссылки на счет-фактуру из МассивСФ будет выполняться внутренний цикл и вызываться ЗаполнитьТабличныйДокументУПД. Важно, чтобы МассивСФ действительно содержал ссылки, а не объекты, так как метод ПолучитьОбъект() может быть ресурсоёмким в циклах.

Корректное понимание и передача параметров — фундаментальный аспект программирования в 1С и других системах. Внимательный анализ сигнатур функций, использование отладчика и знание принципов работы БСП значительно упрощают разработку и устранение ошибок.

← На главную