Как настроить отбор в СКД, если в отчете смешиваются ссылки на номенклатуру и строковые данные из внешних источников

Программист 1С v8.3 (Управляемые формы)
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто возникают ситуации, когда отчет должен объединять данные из информационной базы и внешних систем (Excel, SQL-базы, API сторонних сервисов). Типичная проблема: в колонке «Номенклатура» мы хотим видеть полноценную ссылку, если товар найден в справочнике, и просто текстовое название, если записи в базе нет. Однако, как только пользователь устанавливает стандартный отбор по номенклатуре, все «строковые» записи исчезают из результата. Рассмотрим, почему это происходит и как правильно реализовать такую задачу в Системе компоновки данных (СКД).

Почему стандартный отбор СКД «скрывает» данные?

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

Разберем основные стратегии решения этой проблемы, от простой настройки типов до программного управления компоновкой.

Решение 1: Настройка составного типа данных в схеме

Первым делом нам необходимо «объяснить» системе компоновки, что в поле могут находиться данные разных типов. Выясним, как это сделать в конфигураторе:

  1. Откроем схему компоновки данных и перейдем на закладку Наборы данных.
  2. Найдем наше поле Номенклатура.
  3. В колонке Тип значения нажмем на кнопку выбора и установим флажки напротив нужного справочника и типа Строка.
  4. Укажите квалификаторы строки (длину), чтобы система корректно выделяла память под данные.

Это позволит избежать ошибок приведения типов, однако не решит проблему полностью, если пользователь выбирает ссылку в отборе, а в данных пришла строка с тем же названием. Для СКД ссылка на «Товар 1» и строка «Товар 1» — это разные сущности.

Решение 2: Программная трансляция отбора через параметры

Этот метод считается наиболее надежным. Идея заключается в том, чтобы скрыть стандартное поле отбора от пользователя и предоставить ему виртуальное поле или параметр, который мы обработаем в коде. Рассмотрим этот процесс по шагам.

Шаг 1. Настройка параметров в СКД

Добавим параметр ВыбраннаяНоменклатура с типом СправочникСсылка.Номенклатура. Сделаем его доступным для пользователя в настройках. При этом само поле Номенклатура из набора данных исключим из доступных полей для отбора (установим флажок «Ограничение поля»).

Шаг 2. Создание вспомогательного параметра для связи

В запросе или настройках набора данных добавим скрытый параметр СписокАртикулов (тип Массив или СписокЗначений). Именно по этому параметру мы будем фильтровать данные, получаемые из внешнего источника.

Шаг 3. Обработка в модуле объекта отчета

Используем предопределенную процедуру ПриКомпоновкеРезультата. Выясним, как программно передать артикулы выбранной номенклатуры в скрытый параметр:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	// Получаем настройки пользователя
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	
	// Извлекаем значение выбранной номенклатуры из параметров
	ПараметрНоменклатура = Настройки.ПараметрыДанных.Элементы.Найти("ВыбраннаяНоменклатура");
	
	Если ПараметрНоменклатура <> Неопределено И ПараметрНоменклатура.Использование Тогда
		
		ВыбраннаяСсылка = ПараметрНоменклатура.Значение;
		СписокАртикулов = Новый Массив;
		
		// Если выбрана группа, получаем артикулы всех вложенных элементов
		// Если выбран конкретный элемент - только его артикул
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	Номенклатура.Артикул КАК Артикул
			|ИЗ
			|	Справочник.Номенклатура КАК Номенклатура
			|ГДЕ
			|	Номенклатура.Ссылка В ИЕРАРХИИ(&Ссылка)";
		
		Запрос.УстановитьПараметр("Ссылка", ВыбраннаяСсылка);
		РезультатЗапроса = Запрос.Выполнить();
		СписокАртикулов = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Артикул");
		
		// Устанавливаем параметр для фильтрации внешней таблицы или запроса
		ПараметрСписок = Настройки.ПараметрыДанных.Элементы.Найти("СписокАртикулов");
		Если ПараметрСписок <> Неопределено Тогда
			ПараметрСписок.Значение = СписокАртикулов;
			ПараметрСписок.Использование = Истина;
		КонецЕсли;
		
	КонецЕсли;

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

Решение 3: Использование «Виртуального поля» для отбора

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

  1. Номенклатура — поле для вывода (составной тип: Ссылка + Строка).
  2. НоменклатураДляОтбора — виртуальное поле (тип: Ссылка), которое мы заполняем в Таблице Значений (внешнем источнике) только для тех строк, где номенклатура была успешно найдена в базе.

Если в строке данных из внешнего источника нет соответствия в справочнике 1С, поле НоменклатураДляОтбора остается пустым (NULL или Неопределено). Пользователь настраивает отбор по второму полю. Однако здесь есть тонкость: если пользователь захочет отобрать «Все пустые», он увидит и те позиции, которых нет в справочнике.

Важные рекомендации по работе с внешними данными

Разберем несколько критических моментов, которые часто игнорируют начинающие разработчики:

1. Очистка строковых идентификаторов

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

2. Уникальность артикулов

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

3. Фиксированные настройки

Если вы пытаетесь программно отключить отбор и это «не работает», проанализируйте объект КомпоновщикНастроек.ФиксированныеНастройки. Иногда разработчики устанавливают отборы именно там, и они имеют приоритет над пользовательскими настройками. Чтобы программно подавить стандартное поведение СКД, нужно работать с иерархией настроек осознанно.

Заключение

Мы рассмотрели, что основная причина исчезновения строк при отборах в СКД — это несоответствие типов данных. Наиболее профессиональным решением является создание пользовательского интерфейса через параметры и последующая программная обработка этих параметров в модуле отчета. Это гарантирует, что отчет будет работать предсказуемо независимо от того, насколько сложная логика сопоставления внешних и внутренних данных заложена в бизнес-логику задачи.

← На главную