Почему метод НайтиПоРеквизиту возвращает пустую ссылку и как правильно искать элементы справочника в 1С

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

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

Причина 1. Несоответствие типов данных при поиске

Самая распространенная ошибка при вызове метода НайтиПоРеквизиту — передача значения, тип которого не совпадает с типом реквизита в метаданных конфигурации. В платформе 1С поиск по реквизиту строго типизирован: если реквизит имеет тип Строка, а в метод передается Число, поиск гарантированно вернет пустую ссылку.

Проанализируем ситуацию на примере поиска кассы по номеру карты:


// Ошибочный вариант: реквизит "Карта" имеет тип Строка, но передано Число
дО.Касса = Справочники.Кассы.НайтиПоРеквизиту("Карта", 7275);

// Корректный вариант: явное преобразование числа в строку
КасЧ = 7275;
КасСтр = Формат(КасЧ, "ЧГ=0");
дО.Касса = Справочники.Кассы.НайтиПоРеквизиту("Карта", КасСтр);

Параметр "ЧГ=0" в функции Формат обязателен, чтобы исключить автоматическую группировку разрядов пробелами (например, превращение числа 7275 в строку "7 275").

Причина 2. Ошибочный поиск по стандартному реквизиту Код

Попытка найти элемент по коду через НайтиПоРеквизиту("Код", ...) часто приводит к ошибкам. Для стандартного реквизита Код платформа предоставляет специализированный метод НайтиПоКоду.

Рассмотрим особенности поиска по коду:

  1. Тип и длина кода в метаданных. Если код имеет строковый тип с фиксированной длиной, он дополняется лидирующими нулями (например, "000000038"). Передача числа 38 или короткой строки "38" не найдет нужный элемент.
  2. Использование правильного метода. Для строкового кода с лидирующими нулями применяем форматную строку с параметром ЧВН= или передаем строку точной длины.

Посмотрим на пример правильного вызова метода:


// Поиск по числовому или точно совпадающему строковому коду
дО.Касса = Справочники.Кассы.НайтиПоКоду("000000038");

// Если справочник подчинен другому объекту (например, Организации), указываем владельца
дО.Касса = Справочники.Кассы.НайтиПоКоду("000000038", , дО.Организация);

Причина 3. Индексация реквизитов и подчиненность справочника

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

  1. Подчинение владельцу. Справочник Кассы чаще всего подчинен справочнику Организации. Метод НайтиПоРеквизиту принимает третьим параметром владельца: НайтиПоРеквизиту("Карта", КасСтр, , дО.Организация). Если владелец не указан, поиск может вернуть элемент чужой организации или завершиться неудачей.
  2. Индексирование. Метод НайтиПоРеквизиту быстро отрабатывает только по реквизитам с установленным свойством «Индексировать». Если реквизит не проиндексирован, надежнее и производительнее использовать объект Запрос.

Разбор текста: как извлечь сумму платежа из строки

При разборе входящих писем и сообщений часто требуется извлечь сумму, представленную в международном формате (например, "Vhodyaschiy platezh. Summa 2,222.00 RUB. Otpravitel/////"). Рассмотрим несколько способов ее получения.

Способ 1. Замена подстрок и использование XMLЗначение

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


ИсходныйТекст = "Vhodyaschiy platezh. Summa 2,222.00 RUB. Otpravitel";

// Находим границы суммы по маркерам
ПозНачала = СтрНайти(ИсходныйТекст, "Summa ") + СтрДлина("Summa ");
ПозКонца = СтрНайти(ИсходныйТекст, " RUB", , ПозНачала);

Если ПозНачала > 0 И ПозКонца > ПозНачала Тогда
    СтрокаСуммы = Сред(ИсходныйТекст, ПозНачала, ПозКонца - ПозНачала);
    
    // Удаляем запятые (разделители тысяч)
    СтрокаСуммы = СтрЗаменить(СтрокаСуммы, ",", "");
    
    // Преобразуем строку вида "2222.00" в число через XML-тип
    СуммаЧислом = XMLЗначение(Тип("Число"), СтрокаСуммы);
КонецЕсли;

Способ 2. Использование регулярных выражений

В современных версиях платформы (начиная с 8.3.23) доступен встроенный объект РегулярноеВыражение, который позволяет безопасно извлечь числовой шаблон независимо от окружающего текста:


РегВыр = Новый РегулярноеВыражение("\d[\d,]*\.\d{2}");
РезультатПоиска = РегВыр.НайтиПервый(ИсходныйТекст);

Если РезультатПоиска <> Неопределено Тогда
    СтрокаСуммы = СтрЗаменить(РезультатПоиска.Значение, ",", "");
    СуммаЧислом = XMLЗначение(Тип("Число"), СтрокаСуммы);
КонецЕсли;

Такой подход обеспечивает устойчивость алгоритма к изменению разрядности сумм и вариациям текста сообщения.

← На главную