При программном заполнении документов и обработке входящих данных разработчики часто сталкиваются с ситуацией, когда методы поиска элементов справочника возвращают пустую ссылку (Справочники.Кассы.ПустаяСсылка()), хотя визуально кажется, что поиск выполняется по существующим данным. Разберем по шагам основные причины такого поведения и способы их устранения, а также рассмотрим сопутствующую задачу парсинга числовых значений из текста.
Самая распространенная ошибка при вызове метода НайтиПоРеквизиту — передача значения, тип которого не совпадает с типом реквизита в метаданных конфигурации. В платформе 1С поиск по реквизиту строго типизирован: если реквизит имеет тип Строка, а в метод передается Число, поиск гарантированно вернет пустую ссылку.
Проанализируем ситуацию на примере поиска кассы по номеру карты:
// Ошибочный вариант: реквизит "Карта" имеет тип Строка, но передано Число
дО.Касса = Справочники.Кассы.НайтиПоРеквизиту("Карта", 7275);
// Корректный вариант: явное преобразование числа в строку
КасЧ = 7275;
КасСтр = Формат(КасЧ, "ЧГ=0");
дО.Касса = Справочники.Кассы.НайтиПоРеквизиту("Карта", КасСтр);
Параметр "ЧГ=0" в функции Формат обязателен, чтобы исключить автоматическую группировку разрядов пробелами (например, превращение числа 7275 в строку "7 275").
Попытка найти элемент по коду через НайтиПоРеквизиту("Код", ...) часто приводит к ошибкам. Для стандартного реквизита Код платформа предоставляет специализированный метод НайтиПоКоду.
Рассмотрим особенности поиска по коду:
"000000038"). Передача числа 38 или короткой строки "38" не найдет нужный элемент.ЧВН= или передаем строку точной длины.Посмотрим на пример правильного вызова метода:
// Поиск по числовому или точно совпадающему строковому коду
дО.Касса = Справочники.Кассы.НайтиПоКоду("000000038");
// Если справочник подчинен другому объекту (например, Организации), указываем владельца
дО.Касса = Справочники.Кассы.НайтиПоКоду("000000038", , дО.Организация);
Выясним причину, почему поиск по реквизиту может работать некорректно в подчиненных справочниках или при больших объемах данных:
Кассы чаще всего подчинен справочнику Организации. Метод НайтиПоРеквизиту принимает третьим параметром владельца: НайтиПоРеквизиту("Карта", КасСтр, , дО.Организация). Если владелец не указан, поиск может вернуть элемент чужой организации или завершиться неудачей.НайтиПоРеквизиту быстро отрабатывает только по реквизитам с установленным свойством «Индексировать». Если реквизит не проиндексирован, надежнее и производительнее использовать объект Запрос.При разборе входящих писем и сообщений часто требуется извлечь сумму, представленную в международном формате (например, "Vhodyaschiy platezh. Summa 2,222.00 RUB. Otpravitel/////"). Рассмотрим несколько способов ее получения.
Если формат строки строго фиксирован, выделим подстроку с числом, удалим разделители групп (запятые) и преобразуем полученную строку с точкой в число без учета локальных настроек Windows:
ИсходныйТекст = "Vhodyaschiy platezh. Summa 2,222.00 RUB. Otpravitel";
// Находим границы суммы по маркерам
ПозНачала = СтрНайти(ИсходныйТекст, "Summa ") + СтрДлина("Summa ");
ПозКонца = СтрНайти(ИсходныйТекст, " RUB", , ПозНачала);
Если ПозНачала > 0 И ПозКонца > ПозНачала Тогда
СтрокаСуммы = Сред(ИсходныйТекст, ПозНачала, ПозКонца - ПозНачала);
// Удаляем запятые (разделители тысяч)
СтрокаСуммы = СтрЗаменить(СтрокаСуммы, ",", "");
// Преобразуем строку вида "2222.00" в число через XML-тип
СуммаЧислом = XMLЗначение(Тип("Число"), СтрокаСуммы);
КонецЕсли;
В современных версиях платформы (начиная с 8.3.23) доступен встроенный объект РегулярноеВыражение, который позволяет безопасно извлечь числовой шаблон независимо от окружающего текста:
РегВыр = Новый РегулярноеВыражение("\d[\d,]*\.\d{2}");
РезультатПоиска = РегВыр.НайтиПервый(ИсходныйТекст);
Если РезультатПоиска <> Неопределено Тогда
СтрокаСуммы = СтрЗаменить(РезультатПоиска.Значение, ",", "");
СуммаЧислом = XMLЗначение(Тип("Число"), СтрокаСуммы);
КонецЕсли;
Такой подход обеспечивает устойчивость алгоритма к изменению разрядности сумм и вариациям текста сообщения.