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