Параметры СКД 1С бывают двух видов. Жёсткие (обязательные) записаны в запросе как &Параметр и требуют значения, иначе отчёт не сформируется. Мягкие (необязательные) стоят внутри фигурных скобок расширения языка запросов {...}: если значение не задано, система компоновки просто не добавит условие в итоговый запрос. Всё остальное, что связано с параметрами, — их свойства на вкладке «Параметры», выражения, вывод на форму и установка из кода — надстройки над этими двумя механизмами.

Ниже я собрал то, чем пользуюсь сам при разработке отчётов на СКД: от синтаксиса запроса до программного расчёта параметров перед компоновкой. Примеры на условном справочнике «Автомобили» и типовых регистрах, имена легко заменить на свои.

Где параметры живут в запросе СКД

Параметр в запросе — это имя с амперсандом. Его можно поставить почти куда угодно: в список полей, в условие ГДЕ, в выражение ВЫБОР, в параметры виртуальной таблицы.

Запрос 1С
ВЫБРАТЬ
	&ДатаОтчета КАК ДатаОтчета,
	Автомобили.Ссылка КАК Автомобиль,
	ВЫБОР
		КОГДА Автомобили.ДатаОкончанияОСАГО < &ДатаОтчета
			ТОГДА "Полис ОСАГО просрочен"
		ИНАЧЕ ""
	КОНЕЦ КАК Предупреждение
ИЗ
	Справочник.Автомобили КАК Автомобили
ГДЕ
	Автомобили.ПометкаУдаления = &ПоказыватьУдаленные

Все такие параметры СКД автоматически переносит на вкладку «Параметры» схемы. Они жёсткие: если значения нет, при формировании будет ошибка. Это правильно для параметров, без которых результат бессмысленен (дата отчёта, организация в регламентном отчёте), и неудобно для фильтров, которые пользователь может не заполнять.

Небольшая деталь конструктора запроса: на вкладке «Условия» без флажка «Произвольное» в правой части пишется имя параметра без & — конструктор сам считает это параметром.

Необязательные параметры СКД: фигурные скобки

Расширение языка запросов для СКД — это блоки в фигурных скобках, которые обрабатывает только система компоновки. Обычный объект Запрос их не понимает. Для параметров важны три места.

Блок {ГДЕ}

Ставится после обычного ГДЕ или вместо него, в любом запросе пакета, подзапросе или части объединения.

Запрос 1С
ВЫБРАТЬ
	Автомобили.Ссылка КАК Ссылка,
	Автомобили.Марка КАК Марка,
	Автомобили.ГосНомер КАК ГосНомер
{ВЫБРАТЬ
	Ссылка КАК Автомобиль,
	Марка.*,
	ГосНомер}
ИЗ
	Справочник.Автомобили КАК Автомобили
ГДЕ
	НЕ Автомобили.ПометкаУдаления
{ГДЕ
	Автомобили.Марка.* КАК МаркаОтбор,
	Автомобили.ГосНомер,
	(Автомобили.Предопределенный = &ТолькоПредопределенные)}

Условие (Автомобили.Предопределенный = &ТолькоПредопределенные) попадёт в запрос, только если пользователь задал значение параметра. Поэтому такие параметры и называют мягкими. Конструкция .* открывает для отбора реквизиты ссылочного поля, а КАК задаёт псевдоним, чтобы поле не смешивалось с одноимённым полем выборки.

Зачем это нужно, если есть обычные отборы в настройках? Отбор из пользовательских настроек СКД применяет ко всему набору данных. Если в пакете два запроса, например продажи по выбранной номенклатуре и общая сумма продаж для сравнения, отбор по номенклатуре испортит второй. Блок {ГДЕ} в нужном запросе даёт точечное условие.

Ловушка с МЕЖДУ

Выражение с двумя параметрами в одном условии работает не так, как ожидают:

Запрос 1С
{ГДЕ
	(Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода)}

Оба параметра заданы — отбор за период. Оба пустые — условие выбрасывается, выборка за всё время. Задан только один — ошибка формирования. Лечится разбиением на два независимых условия:

Запрос 1С
{ГДЕ
	(Реализация.Дата >= &НачалоПериода),
	(Реализация.Дата <= &КонецПериода)}

Правило общее: в одном мягком условии — один параметр.

Параметры виртуальных таблиц

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

Запрос 1С
ВЫБРАТЬ
	Взаиморасчеты.Сотрудник,
	Взаиморасчеты.СуммаПриход,
	Взаиморасчеты.СуммаРасход
ИЗ
	РегистрНакопления.ВзаиморасчетыССотрудниками.Обороты(
			{&НачалоПериода},
			{&КонецПериода},
			,
			{Сотрудник.*,
			Подразделение.* КАК ПодразделениеОтбор}) КАК Взаиморасчеты

Если параметр периода не задан, виртуальная таблица считается без ограничения с этой стороны. Если автозаполнение полей включено, а периоды не вписаны явно, СКД сама создаст параметры НачалоПериода и КонецПериода на вкладке «Параметры».

Можно совместить жёсткий и мягкий параметр: Обороты(&НачалоПоУмолчанию {&НачалоПериода}, ...). Если пользователь задал НачалоПериода, используется оно, иначе берётся жёсткий &НачалоПоУмолчанию.

Вкладка «Параметры» схемы: что означает каждое свойство

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

СвойствоЧто делаетГде пригодится
ИмяИдентификатор, по нему обращаемся из запроса, выражений и кодаВсегда
ЗаголовокПодпись для пользователяПонятные названия на форме
ТипТип значения, в том числе квалификаторыДата без времени, длина строки, разрядность числа
Доступные значенияОграниченный список выбораФиксированный набор вариантов
Доступен список значенийРазрешает передать списокОтбор по нескольким складам
ЗначениеЗначение по умолчаниюТиповые даты, флаги
ВыражениеЗначение вычисляетсяПроизводные параметры
Включать в доступные поляПараметр виден как поле в настройкахВывод параметра в шапку отчёта
Ограничение доступностиПользователь не меняет параметрСлужебные и вычисляемые параметры
Запрещать незаполненные значенияПустое значение вызывает ошибкуОбязательная организация
Использование«Авто» или «Всегда»Параметры, которые всегда участвуют в расчёте

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

Выражения в параметрах

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

Запрос 1С
НачалоПериода(&ДатаНачала, "День")

Типичный приём для удобного выбора периода: пользователь видит одно поле с типом СтандартныйПериод, а запрос работает с двумя датами.

  1. Создайте параметр Период с типом «Стандартный период», без ограничения доступности.
  2. Создайте ПериодНачало и ПериодОкончание с типом «Дата», включите им «Ограничение доступности».
  3. В выражении ПериодНачало напишите &Период.ДатаНачала, в ПериодОкончание — &Период.ДатаОкончания.
  4. В запросе используйте &ПериодНачало и &ПериодОкончание.

Дата начала стандартного периода приходит с временем 00:00:00, дата окончания — с 23:59:59, поэтому дополнительно обрезать время в запросе не нужно. Если же вы оставляете два параметра типа «Дата» без времени, в запросе оборачивайте их в НАЧАЛОПЕРИОДА(..., ДЕНЬ) и КОНЕЦПЕРИОДА(..., ДЕНЬ), иначе последний день периода потеряется.

Как вывести параметр СКД пользователю

Чтобы параметр появился в отчёте, его нужно включить в пользовательские настройки варианта:

  1. Откройте вкладку «Настройки» схемы, в нижней части — закладку «Параметры».
  2. Отметьте параметр и задайте значение по умолчанию для варианта.
  3. Откройте свойства элемента пользовательских настроек и включите «Включать в пользовательские настройки».
  4. Режим редактирования: «Быстрый доступ» — поле прямо на форме отчёта; «Обычный» — только в окне «Настройки...».
  5. В «Представлении» можно переопределить подпись, которую увидит пользователь.

Флажок «Отображать недоступные параметры» в варианте полезен, когда у разных вариантов отчёта должен быть разный набор параметров.

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

Установка параметров СКД программно

Простой случай — задать значение из формы отчёта перед формированием:

1С
&НаСервере
Процедура УстановитьОрганизациюПоУмолчаниюНаСервере(Организация)

	ПараметрыДанных = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных;
	ПараметрыДанных.УстановитьЗначениеПараметра("Организация", Организация);

КонецПроцедуры

УстановитьЗначениеПараметра сам включает использование параметра. Но если параметр выведен в пользовательские настройки, значение оттуда перекроет то, что вы записали в Настройки. В этом случае меняйте пользовательскую настройку:

1С
&НаСервере
Процедура УстановитьПользовательскийПараметр(ИмяПараметра, Значение)

	Для Каждого ЭлементНастройки Из Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
		Если ТипЗнч(ЭлементНастройки) = Тип("ЗначениеПараметраНастроекКомпоновкиДанных")
			И Строка(ЭлементНастройки.Параметр) = ИмяПараметра Тогда
			ЭлементНастройки.Значение = Значение;
			ЭлементНастройки.Использование = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;

КонецПроцедуры

Сложный случай — параметр, который не выразить формулой. Пример из практики: отчёт сравнивает продажи двух недель. В понедельник сравниваются позапрошлая и прошлая неделя (текущая только началась), в остальные дни — прошлая и текущая. От дня недели зависят сразу четыре параметра, а пользователь ещё хочет сформировать отчёт «как будто вчера». Такие вещи я считаю в модуле объекта отчёта, в ПриКомпоновкеРезультата, с ручной компоновкой:

1С
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	// Получаем настройки с учетом пользовательских значений
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	РассчитатьГраницыНедель(Настройки);

	СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки, ДанныеРасшифровки);

	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

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

КонецПроцедуры

// Заполняет параметры НачалоПрошлойНедели, КонецПрошлойНедели,
// НачалоТекущейНедели, КонецТекущейНедели от параметра ДатаОтчета.
Процедура РассчитатьГраницыНедель(Настройки)

	СекундВНеделе = 7 * 86400;

	ДатаОтчета = ТекущаяДатаСеанса();
	ЗначениеДатыОтчета = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(
		Новый ПараметрКомпоновкиДанных("ДатаОтчета"));
	Если ЗначениеДатыОтчета <> Неопределено
		И ЗначениеДатыОтчета.Использование
		И ЗначениеЗаполнено(ЗначениеДатыОтчета.Значение) Тогда
		ДатаОтчета = ЗначениеДатыОтчета.Значение;
	КонецЕсли;

	// В понедельник текущая неделя еще пустая — сдвигаемся на неделю назад
	Если ДеньНедели(ДатаОтчета) = 1 Тогда
		ОпорнаяДата = ДатаОтчета - СекундВНеделе;
	Иначе
		ОпорнаяДата = ДатаОтчета;
	КонецЕсли;

	ПараметрыДанных = Настройки.ПараметрыДанных;
	ПараметрыДанных.УстановитьЗначениеПараметра("НачалоТекущейНедели", НачалоНедели(ОпорнаяДата));
	ПараметрыДанных.УстановитьЗначениеПараметра("КонецТекущейНедели", КонецНедели(ОпорнаяДата));
	ПараметрыДанных.УстановитьЗначениеПараметра("НачалоПрошлойНедели", НачалоНедели(ОпорнаяДата - СекундВНеделе));
	ПараметрыДанных.УстановитьЗначениеПараметра("КонецПрошлойНедели", КонецНедели(ОпорнаяДата - СекундВНеделе));

КонецПроцедуры

Четыре вычисляемых параметра в схеме я помечаю «Ограничение доступности», чтобы пользователь видел только ДатаОтчета. Расчёт на стороне объекта, а не формы, хорош тем, что отчёт одинаково работает при формировании из формы, из рассылки и из кода. В конфигурациях на БСП то же самое удобно делать в обработчике ПередЗагрузкойНастроекВКомпоновщик или ПриКомпоновкеРезультата модуля отчёта — смотрите, какие события подключены у конкретного варианта.

Типичные ошибки с параметрами СКД

  • «Не установлено значение параметра» при заполненном поле. Проверьте флажок использования (при «Авто») и не перекрывает ли пользовательская настройка значение варианта.
  • Мягкое условие с двумя параметрами. МЕЖДУ в {ГДЕ} падает, если заполнен один параметр. Разбивайте на два условия.
  • Отбор портит соседний запрос пакета. Пользовательский отбор действует на весь набор. Нужен локальный фильтр — используйте {ГДЕ} в конкретном запросе.
  • Потерянный последний день периода. Параметр типа «Дата» с составом «Дата» приходит как 00:00:00. Используйте КОНЕЦПЕРИОДА или стандартный период.
  • Параметр задан в коде, но не применился. Значение записано в Настройки, а выведенная пользовательская настройка его перекрыла. Меняйте ПользовательскиеНастройки или считайте параметр в ПриКомпоновкеРезультата.
  • Фигурные скобки в обычном запросе. Расширение языка запросов работает только внутри схемы компоновки. Тот же текст в Новый Запрос даст синтаксическую ошибку.
Если параметр должен быть обязательным — пишите его в запрос открыто и ставьте «Запрещать незаполненные значения». Если это фильтр «по желанию» — только фигурные скобки и одно условие на параметр.

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

Коротко

  • Жёсткий параметр — &Имя в запросе, без значения отчёт не строится. Мягкий — внутри {ГДЕ} или {&Имя} в параметрах виртуальной таблицы, без значения условие исчезает.
  • В одном мягком условии держите один параметр: МЕЖДУ разбивайте на >= и <=.
  • «Использование: Всегда» снимает требование флажка, «Ограничение доступности» прячет служебные параметры.
  • Производные параметры считайте выражением (&Период.ДатаНачала), а алгоритмические — в ПриКомпоновкеРезультата.
  • При установке из кода помните, что пользовательские настройки перекрывают настройки варианта.