Как настроить отбор строк таблицы значений по точному совпадению в управляемой форме 1С?

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

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

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

Разберем подробнее, почему так происходит, и рассмотрим проверенные способы организовать отбор по строгому соответствию значений.

В чем причина поиска по подстроке через свойство ОтборСтрок

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


ТекДанные = Элементы.СписокЗаказов.ТекущиеДанные;
Если ТекДанные = Неопределено Тогда 
	Элементы.СписокУпаковок.ОтборСтрок = Неопределено;
Иначе 
	Элементы.СписокУпаковок.ОтборСтрок = Новый ФиксированнаяСтруктура("НомерЗаказа", ТекДанные.НомерЗаказа);
КонецЕсли;

Если номер текущего заказа равен «1», то в подчиненной таблице отобразятся не только строки с номером «1», но и «10», «11», «21» и любые другие, где встречается единица.

Дело в архитектурном ограничении механизма ОтборСтрок на управляемых формах:

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

Выясним причину и рассмотрим несколько практических вариантов решения задачи.

Способ 1. Использование отбора по ссылке на документ

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

Посмотрим на пример кода в обработчике активизации строки:


ТекДанные = Элементы.СписокЗаказов.ТекущиеДанные;

Если ТекДанные = Неопределено Тогда 
	Элементы.СписокУпаковок.ОтборСтрок = Неопределено;
Иначе 
	ПараметрыОтбора = Новый Структура("СсылкаНаЗаказ", ТекДанные.СсылкаНаЗаказ);
	Элементы.СписокУпаковок.ОтборСтрок = Новый ФиксированнаяСтруктура(ПараметрыОтбора);
КонецЕсли;

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

Способ 2. Использование числового типа данных для номера

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

  1. В запросе или при программном заполнении таблицы преобразуем строковый номер в число (например, через функцию Число()).
  2. Устанавливаем тип колонки НомерЗаказа в реквизитах формы как Число.
  3. Передаем числовое значение в ФиксированнаяСтруктура:

Если ТекДанные <> Неопределено Тогда
	Элементы.СписокУпаковок.ОтборСтрок = Новый ФиксированнаяСтруктура("НомерЗаказа", Число(ТекДанные.НомерЗаказа));
КонецЕсли;

При таком подходе число 1 никогда не совпадет с числом 10 или 21.

Способ 3. Приведение строк к фиксированной длине или маскирование разделителями

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

  1. Форматирование с ведущими нулями до фиксированной длины: если строковый номер всегда дополняется нулями (например, "0000000001" и "0000000010"), строка "0000000001" физически не содержится внутри "0000000010", что исключает пересечения.
  2. Использование служебных обрамляющих символов: добавим в таблицы служебную колонку, в которую номер записывается в границах спецсимволов, например "#1#", "#10#". При установке отбора передаем значение "#1#". Поскольку подстрока "#1#" отсутствует внутри строки "#10#", платформа отобразит только требуемые строки.

Способ 4. Связывание через уникальный идентификатор (GUID)

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

Разберем по шагам:

  1. Добавим в обе таблицы строковую колонку КлючСвязи с длиной 36 символов.
  2. При формировании строк родительской таблицы генерируем ключ: Строка(Новый УникальныйИдентификатор).
  3. Тот же самый ключ прописываем во все подчиненные строки упаковок данного заказа.
  4. В интерфейсе устанавливаем отбор по этому ключу.

Поскольку GUID состоит из 36 символов и обладает абсолютной уникальностью, вероятность случайного совпадения подстрок сведена к нулю.

Способ 5. Отказ от свойства ОтборСтрок в пользу метода НайтиСтроки

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

В отличие от свойства формы ОтборСтрок, программный метод коллекции НайтиСтроки() для строковых полей выполняет поиск строго по точному совпадению.

Рассмотрим схему реализации:

  1. Храним полный список всех упаковок во временной невидимой таблице или реквизите формы (например, ВсеУпаковки).
  2. В видимой на форме таблице СписокУпаковок отображаем только отфильтрованный результат.
  3. В событии ПриАктивизацииСтроки очищаем отображаемую таблицу и копируем в нее строки, полученные методом НайтиСтроки().

Посмотрим на пример кода:


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

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

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

← На главную