Как исправить ошибку «Неверные параметры» при передаче Таблицы Значений в запрос и работе с Конструктором выходных форм в 1С

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

При работе со сложными отчетами в конфигурациях на обычных формах (например, в «1С:Управление производственным предприятием», ред. 1.3) разработчики часто сталкиваются с наследием старого кода. Одной из типичных проблем является попытка отредактировать запрос отчета с помощью встроенного инструмента «Конструктор выходных форм», после чего система выдает критическую ошибку вида: {(6,2)}: Неверные параметры "ИменаЗатрат" >&ИменаЗатрат КАК Т. В этой статье мы подробно разберем, почему возникает данная ошибка, как устроены механизмы передачи внешних таблиц в запрос и как правильно оптимизировать код и логику работы с конструкторами в платформе «1С:Предприятие».

Выясняем причину: почему «Конструктор выходных форм» выдает ошибку

Для того чтобы понять природу проблемы, проанализируем поведение платформы. Инструмент «Конструктор выходных форм» — это устаревший визуальный мастер (так называемая «некротехнология» времен платформ 8.0 и 8.1), предназначенный для первоначального проектирования простых отчетов на базе объекта ПостроительОтчета. Этот конструктор ориентирован исключительно на работу с простыми, однокомпонентными запросами, которые выбирают данные напрямую из физических таблиц базы данных (справочников, документов или регистров).

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

ВЫБРАТЬ Т.Затрата, Т.Имя ПОМЕСТИТЬ ИменаЗатрат ИЗ &ИменаЗатрат КАК Т ;

При попытке открыть такой запрос через «Конструктор выходных форм» происходит следующее:

  1. Парсер конструктора пытается статически проанализировать структуру запроса на этапе конфигуратора.
  2. В секции ИЗ он натыкается на параметр &ИменаЗатрат.
  3. Поскольку это динамический параметр (внешний источник данных, структура которого на этапе проектирования конструктору неизвестна), визуальный парсер не может определить состав полей и типы данных этой таблицы.
  4. Конструктор аварийно завершает работу, сообщая о неверных параметрах.

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

Решение проблемы: правильная работа с Конструктором запроса

Разберем по шагам, как нужно поступать в подобных ситуациях. Для редактирования запросов мы должны использовать исключительно стандартный «Конструктор запроса», который полностью поддерживает работу со всеми современными конструкциями языка запросов 1С.

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

  1. Откроем модуль формы или модуль объекта, где расположен текст запроса.
  2. Нажмем правой кнопкой мыши по тексту запроса и выберем пункт «Конструктор запроса...». В отличие от конструктора выходных форм, стандартный конструктор запроса успешно откроет этот текст.
  3. Чтобы конструктор запроса корректно «понимал» структуру нашей внешней таблицы ИменаЗатрат и позволял связывать ее поля с другими таблицами пакета в визуальном режиме, перейдем на вкладку «Дополнительно».
  4. В разделе «Описание временных таблиц» добавим новую таблицу с именем ИменаЗатрат.
  5. Вручную опишем ее колонки: Затрата (тип: Строка) и Имя (тип: Строка).
  6. Теперь платформа на этапе проектирования знает структуру нашей таблицы, и мы можем без проблем использовать ее при связывании таблиц на вкладке «Связи».

Как правильно подготовить и передать Таблицу Значений в параметр запроса

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

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


// 1. Создаем объект ТаблицаЗначений
ИменаЗатрат = Новый ТаблицаЗначений;

// 2. Создаем описание типов для колонок таблицы.
// Запрос должен четко знать типы полей, иначе возникнет ошибка выполнения!
КС = Новый КвалификаторыСтроки(150);
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Строка"));
ОписаниеТиповС = Новый ОписаниеТипов(МассивТипов, , КС);

// 3. Добавляем колонки с обязательным указанием типов данных
ИменаЗатрат.Колонки.Добавить("Затрата", ОписаниеТиповС);
ИменаЗатрат.Колонки.Добавить("Имя", ОписаниеТиповС);

// 4. Заполняем таблицу значений данными (например, из справочника Статьи Затрат)
Выборка = Справочники.СтатьиЗатрат.Выбрать();
Пока Выборка.Следующий() Цикл
    Если Выборка.ЭтоГруппа Тогда
        Продолжить;
    КонецЕсли;
    
    НоваяСтрока = ИменаЗатрат.Добавить();
    НоваяСтрока.Затрата = СокрЛП(Выборка.Наименование);
    
    // Выделяем имя затраты до скобки, если она присутствует в наименовании
    Поз = Найти(НоваяСтрока.Затрата, "(");
    Если Поз = 0 Тогда
        НоваяСтрока.Имя = НоваяСтрока.Затрата;
    Иначе
        НоваяСтрока.Имя = Лев(НоваяСтрока.Затрата, Поз - 1);
    КонецЕсли;
КонецЦикла;

// 5. Устанавливаем подготовленную таблицу значений в параметр запроса
Запрос.УстановитьПараметр("ИменаЗатрат", ИменаЗатрат);

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

Оптимизация кода: избавляемся от громоздких вложенных конструкций ВЫБОР

Проанализируем структуру исходного запроса из первого сообщения. Предыдущий программист использовал каскадную вложенность операторов ВЫБОР КОГДА ... ИНАЧЕ ВЫБОР КОГДА .... Такая запись существенно затрудняет чтение кода, увеличивает вероятность синтаксической ошибки (например, легко запутаться в количестве закрывающих операторов КОНЕЦ) и может негативно влиять на производительность парсера запросов.

Рассмотрим структуру исходного неоптимального фрагмента:


ВЫБОР КОГДА ХозрасчетныйОбороты.Счет.Родитель.Код = "02" ТОГДА 
    "6. Амортизация" 
ИНАЧЕ 
    ВЫБОР КОГДА ХозрасчетныйОбороты.Счет = &Счет70 ТОГДА 
        "8. Заработная плата" 
    ИНАЧЕ 
        ВЫБОР КОГДА ХозрасчетныйОбороты.КорСчет В (&МатЗатраты) ТОГДА 
            "1. Материальные затраты" 
        ИНАЧЕ 
            // И так далее...
        КОНЕЦ 
    КОНЕЦ 
КОНЕЦ

В языке запросов «1С» оператор ВЫБОР поддерживает плоскую структуру условий. Мы можем перечислить все условия последовательно через ключевое слово КОГДА внутри одной конструкции. Перепишем этот фрагмент в оптимизированном и легко читаемом виде:


ВЫБОР 
    КОГДА ХозрасчетныйОбороты.Счет.Родитель.Код = "02" ТОГДА "6. Амортизация" 
    КОГДА ХозрасчетныйОбороты.Счет = &Счет70 ТОГДА "8. Заработная плата" 
    КОГДА ХозрасчетныйОбороты.КорСчет В (&МатЗатраты) ТОГДА "1. Материальные затраты" 
    КОГДА ХозрасчетныйОбороты.КорСчет В (&Услуги) ТОГДА "2. Услуги" 
    КОГДА ХозрасчетныйОбороты.КорСчет В (&Кап) ТОГДА "3. Капитальные вложения" 
    КОГДА ХозрасчетныйОбороты.КорСчет В (&РасхБп) ТОГДА "4. Расходы будущих периодов" 
    КОГДА ХозрасчетныйОбороты.КорСчет В (&ЗаПрибыль) ТОГДА "5. Расходы за счет прибыли" 
    ИНАЧЕ "!!!!!" 
КОНЕЦ КАК Группа

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

Вывод документов в макет отчета

В сообщении №10 автор интересуется возможностью вывода документов-регистраторов непосредственно в макет этого отчета. Разберем, как это реализовать.

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

РегистрБухгалтерии.Хозрасчетный.Обороты(&ДН, &ДК, Месяц, ...)

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

  1. Изменить периодичность виртуальной таблицы оборотов на Регистратор:
    
    ИЗ РегистрБухгалтерии.Хозрасчетный.Обороты(&ДН, &ДК, Регистратор, Счет В ИЕРАРХИИ (&Счет60), , &УсловиеПоКлиенту, , ) КАК ХозрасчетныйОбороты
    
  2. Добавить поле ХозрасчетныйОбороты.Регистратор в список выбираемых полей первого пакета запроса (таблица тмп) и включить его в секцию СГРУППИРОВАТЬ ПО.
  3. Протащить поле Регистратор через все последующие временные таблицы пакета запроса (Ит, Итг, ИтоговаяТаблица) до самого последнего итогового запроса.
  4. В итоговом запросе добавить поле Регистратор в список полей выборки и в группировки ИТОГИ ... ПО (например, добавив уровень группировки по регистратору после детальной расшифровки).
  5. Вручную отредактировать макет отчета, добавив новую область для вывода строки документа, и прописать вывод этого параметра в коде формирования табличного документа формы.

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

← На главную