При разработке алгоритмов сопоставления данных разработчики часто сталкиваются с ситуацией, когда явный поиск по строковому литералу (например, "456") отрабатывает корректно, а при передаче значения из переменной или строки таблицы метод НайтиПоРеквизиту возвращает пустую ссылку. При этом попытка преобразовать значение через функцию Строка() может неожиданно возвращать пустую строку. Разберем по шагам, с чем связано такое поведение платформы 1С, как локализовать ошибку и как выстроить надежный поиск данных.
Первое, на что необходимо обратить внимание при внезапном получении пустых значений, — соответствие имен переменных. В исходном коде разработчик может непреднамеренно опечататься в похожих идентификаторах, например, обращаться к СтрокиТД.ФинАгент вместо СтрокиТЗ.ФинАгент. В нестрогой модели типизации или при отсутствии проверки метаданных платформой это приводит к обращению к неинициализированному свойству или другой коллекции.
Рассмотрим, как быстро локализовать проблему с помощью базовых инструментов отладки:
ТипЗнч() для исследуемого поля. Если свойство не существует или не заполнено, тип будет Неопределено:
// Проверим реальный тип значения перед поиском
Сообщить("Тип значения: " + Строка(ТипЗнч(СтрокиТЗ.ФинАгент)));
Сообщить("Фактическое значение: """ + Строка(СтрокиТЗ.ФинАгент) + """");
Выясним причину, почему конструкция Строка(Значение) может возвращать пустое значение, даже если переменная кажется заполненной:
Строка() возвращает строковое представление объекта (по умолчанию — значение реквизита Наименование). Если у элемента не заполнено наименование, результатом будет пустая строка.ОбработкаПолученияПредставления или ОбработкаПолученияПолейПредставления, платформа вычисляет представление по заложенному в них алгоритму. При определенных условиях этот алгоритм может возвращать пустую строку.Если имена переменных проверены, но метод НайтиПоРеквизиту всё равно не возвращает результат, проанализируем формат самих строковых данных:
"456" не равна строке "456 ". Для успешного поиска искомое значение необходимо дополнять пробелами либо изменить тип реквизита на строку переменной длины.СокрЛП удаляет только обычные пробелы (код 32). В таком случае очистку строки выполняем явно:
ЗначениеОчищенное = СтрЗаменить(СтрокиТЗ.ФинАгент, Символы.НПП, "");
ЗначениеОчищенное = СокрЛП(ЗначениеОчищенное);
"000000456"). Поиск значения "456" в этом случае не найдет объект. Приведем значение к нужному формату перед поиском:
ЧисловойКод = Число(ЗначениеОчищенное);
ИскомыйНомер = Формат(ЧисловойКод, "ЧЦ=9; ЧВН=");
Метод НайтиПоРеквизиту удобен для единичных операций, однако имеет существенные архитектурные ограничения, о которых важно помнить:
ХранилищеЗначения и реквизитами табличных частей.Вызов метода НайтиПоРеквизиту внутри цикла по строкам таблицы значений порождает критический антипаттерн — «запрос в цикле». Посмотрим на правильный подход к сопоставлению данных, когда вся таблица передается в один запрос:
// Подготовим таблицу с типизированной колонкой поиска
ТаблицаПоиска = Новый ТаблицаЗначений;
ТаблицаПоиска.Колонки.Добавить("ТабельныйНомер", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(20)));
Для Каждого СтрТЗ Из СтрокиТЗ Цикл
НоваяСтрока = ТаблицаПоиска.Добавить();
НоваяСтрока.ТабельныйНомер = СокрЛП(СтрТЗ.ФинАгент);
КонецЦикла;
// Выполним поиск за одно обращение к СУБД
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таб.ТабельныйНомер КАК ТабельныйНомер
|ПОМЕСТИТЬ ВТ_ИсходныеДанные
|ИЗ
| &ТаблицаПоиска КАК Таб
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ.ТабельныйНомер КАК ИсходныйНомер,
| Сотрудники.Ссылка КАК Сотрудник
|ИЗ
| ВТ_ИсходныеДанные КАК ВТ
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
| ПО ВТ.ТабельныйНомер = Сотрудники.ТабельныйНомер";
Запрос.УстановитьПараметр("ТаблицаПоиска", ТаблицаПоиска);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Такой подход полностью исключает проблемы единичных обращений к базе данных, обеспечивает максимальное быстродействие и гарантирует корректность сопоставления строковых типов.