Почему метод Найти() для массива в 1С не работает в условии и что он возвращает на самом деле

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

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

Разбираем возвращаемое значение метода Найти()

Главная причина, по которой код типа Если Не Массив.Найти(Значение) Тогда не работает, заключается в непонимании типа данных, который возвращает функция. В отличие от многих других языков программирования, где метод поиска может возвращать Истина или Ложь, в 1С метод Найти() возвращает:

  1. Индекс элемента (тип Число), если значение найдено. Индексация начинается с 0.
  2. Неопределено, если значение в массиве не обнаружено.

Когда мы пишем оператор Не перед вызовом функции, 1С пытается привести результат (число или Неопределено) к типу Булево. Поскольку автоматическое преобразование числа или Неопределено в логическое значение в 1С не предусмотрено, программа выдает ошибку «Преобразование значения к типу Булево не может быть выполнено».

Проанализируем правильный подход к написанию условия. Чтобы проверить, существует ли элемент в массиве, мы должны явно сравнить результат с Неопределено:


// Правильная проверка: элемент НЕ найден
Если ОрганизацияДляФизическихЛиц.Найти(Объект.Организация) = Неопределено Тогда
    Сообщить("Организация не найдена в списке");
КонецЕсли;

// Правильная проверка: элемент НАЙДЕН
Если ОрганизацияДляФизическихЛиц.Найти(Объект.Организация) <> Неопределено Тогда
    Сообщить("Организация присутствует в массиве");
КонецЕсли;

Ловушка нулевого индекса

Рассмотрим ситуацию, которую часто называют «странным поведением»: поиск работает для всех элементов, кроме первого. Если искомый объект находится в массиве на первой позиции, метод Найти() вернет 0. В логике некоторых языков (например, C++ или Python) 0 может интерпретироваться как Ложь, но в 1С 0 — это просто числовое значение индекса. Если вы попытаетесь использовать его в сокращенном условии, это приведет к ошибке или неверной логике исполнения. Только сравнение с Неопределено гарантирует корректность работы во всех случаях.

Проблема соответствия типов данных

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

  1. Ссылка против Объекта: Если в массиве хранятся ссылки (СправочникСсылка.Организации), а вы пытаетесь найти объект (полученный через ПолучитьОбъект()), поиск всегда будет возвращать Неопределено.
  2. Код против Ссылки: Часто разработчики ошибочно пытаются найти строковый код организации в массиве, где лежат сами ссылки на элементы справочника. Чтобы поиск сработал, типы должны совпадать.
  3. Строки и числа: Строка "123" не равна числу 123. При заполнении массива из внешних источников (Excel, текстовые файлы) важно следить за типизацией.

Посмотрим на пример, когда поиск должен идти по наименованию, если в массиве хранятся строки:


// Если в массиве хранятся названия организаций (строки)
Если ОрганизацияДляФизическихЛиц.Найти(Объект.Организация.Наименование) <> Неопределено Тогда
    // Логика обработки
КонецЕсли;

Массив и ФиксированныйМассив

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


ОбычныйМассив = Новый Массив(ФиксированныйМассивДанных);
ОбычныйМассив.Добавить(НоваяОрганизация);
Индекс = ОбычныйМассив.Найти(ИскомоеЗначение);

Что делать, если нужно найти несколько вхождений?

Метод Найти() возвращает индекс только первого найденного элемента. Если в вашем массиве могут быть дубли и вам нужно обработать их все, использование массива становится неэффективным. В этом случае проанализируем ситуацию и сменим структуру данных на ТаблицаЗначений.

Разберем по шагам, как выполнить поиск в таблице значений:


// Создаем таблицу вместо массива для расширенного поиска
ТаблицаОрганизаций = Новый ТаблицаЗначений;
ТаблицаОрганизаций.Колонки.Добавить("Организация");

// Допустим, таблица уже заполнена данными...

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

// Получаем массив всех подходящих строк
НайденныеСтроки = ТаблицаОрганизаций.НайтиСтроки(ПараметрыОтбора);

Если НайденныеСтроки.Количество() > 0 Тогда
    Для Каждого Стр Из НайденныеСтроки Цикл
        // Обработка каждого найденного элемента
    КонецЦикла;
КонецЕсли;

Особенности сравнения ссылок (GUID)

Иногда возникает ситуация: визуально в отладчике мы видим две одинаковые организации, но Найти() возвращает Неопределено. Это происходит потому, что 1С сравнивает ссылки по их внутреннему уникальному идентификатору (GUID). Если в базе есть «дубли» (элементы с одинаковым наименованием, но созданные по-разному), ссылки будут разными. При работе в распределенных информационных базах (РИБ) также важно следить, чтобы ссылки были синхронизированы, иначе поиск в массиве по ссылке, пришедшей из другого узла, может не дать результата.

Рекомендации по отладке

Если поиск не работает, выполните следующие действия в режиме отладки:

Использование этих простых правил и понимание того, что Найти() возвращает индекс или Неопределено, позволит вам писать надежный и отказоустойчивый код в 1С.

← На главную