Как найти документ в 1С, если известен только фрагмент его номера

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

В процессе интеграции систем или загрузки данных из внешних файлов (например, Excel) часто возникает ситуация, когда в источнике номер заказа указан в упрощенном виде (например, "1222"), а в базе 1С он хранится с префиксами и лидирующими нулями (например, "СФНД-001222"). В этой статье мы подробно разберем, как программно найти ссылку на документ в таких условиях, проанализируем различные подходы и выберем наиболее оптимальный с точки зрения производительности.

Решение 1: Использование оператора ПОДОБНО в запросе

Самый простой и очевидный способ найти документ по части строки — использовать оператор ПОДОБНО в языке запросов 1С. Однако, как мы видим из обсуждения, часто возникают ошибки при его использовании. Разберем типичный пример. Если мы напишем условие ГДЕ Заказ.Номер ПОДОБНО &НомерДок и передадим в параметр значение "1222", запрос не вернет результат, так как он ищет полное совпадение. Для подбора записей по неполным данным также подойдёт обработка для поиска объектов по подстроке и схожести реквизитов.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ЗаказПокупателя.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ЗаказПокупателя КАК ЗаказПокупателя
    |ГДЕ
    |	ЗаказПокупателя.Номер ПОДОБНО ""%"" + &НомерИзФайла";

Запрос.УстановитьПараметр("НомерИзФайла", "1222");
РезультатЗапроса = Запрос.Выполнить();

Важный нюанс: Поиск с процентом в начале строки (%1222) делает невозможным использование индексов базы данных. Система будет вынуждена выполнить полное сканирование таблицы (Full Table Scan). Если в вашей базе сотни тысяч или миллионы документов, такой запрос будет работать крайне медленно. Рассмотрим, как можно ускорить этот процесс.

Решение 2: Программное формирование полного номера

Чтобы поиск работал быстро, желательно использовать точное соответствие, которое задействует индекс по полю Номер. Для этого нам нужно преобразовать "1222" в формат 1С, добавив префикс и недостающие нули. Выясним причину, почему номера выглядят именно так: в 1С длина номера фиксирована, и она дополняется нулями до нужной длины.

Если мы заранее знаем возможные префиксы (например, "СФНД-" и "ФНД-"), мы можем подготовить список всех возможных вариантов номера. Разберем по шагам, как это сделать:

  1. Определяем длину номера в конфигурации (например, 11 символов).
  2. Дополняем числовую часть нулями слева до нужной длины, учитывая длину префикса.
  3. Используем метод НайтиПоНомеру() или запрос с условием В.

Посмотрим на пример кода с использованием функций БСП (Библиотеки стандартных подсистем):


// Предположим, номер из файла "1222", а длина номера в базе 11
ЧисловаяЧасть = "1222";
НужнаяДлина = 11;
Префиксы = Новый Массив;
Префиксы.Добавить("СФНД-");
Префиксы.Добавить("ФНД-");

ВариантыНомеров = Новый Массив;
Для Каждого Префикс Из Префиксы Цикл
    // Дополняем нулями до нужной длины за вычетом длины префикса
    ДлинаНулей = НужнаяДлина - СтрДлина(Префикс);
    ПолныйНомер = Префикс + ПрефиксацияОбъектовКлиентСервер.ДополнитьСтрокуНулями(ЧисловаяЧасть, ДлинаНулей);
    ВариантыНомеров.Добавить(ПолныйНомер);
КонецЦикла;

// Теперь ищем запросом по индексированному полю
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Документ.ЗаказПокупателя ГДЕ Номер В (&ВариантыНомеров)";
Запрос.УстановитьПараметр("ВариантыНомеров", ВариантыНомеров);

Решение 3: Использование метода НайтиПоНомеру()

Если нам не нужен запрос (например, мы обрабатываем одну строку), можно воспользоваться встроенным методом менеджера документа НайтиПоНомеру(). Рассмотрим этот вариант:


ДатаПоиска = ТекущаяДата(); // Желательно знать хотя бы год
СсылкаНаДокумент = Документы.ЗаказПокупателя.НайтиПоНомеру(СформированныйНомер, ДатаПоиска);
Если НЕ СсылкаНаДокумент.Пустая() Тогда
    // Документ найден
КонецЕсли;

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

Решение 4: Оптимизация через Регистр Сведений

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

Этот регистр может называться "СоответствиеНомеров" и содержать следующие измерения:

Мы можем настроить подписку на событие ПриЗаписи для нужных документов, которая будет записывать в этот регистр "чистый" номер. Тогда поиск превратится в мгновенное обращение к регистру по проиндексированному полю ЧистыйНомер. Это самый надежный способ для высоконагруженных систем.

Решение 5: Полнотекстовый поиск

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


СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок("1222", 1);
СписокПоиска.ОбластьПоиска.Добавить(Метаданные.Документы.ЗаказПокупателя);
СписокПоиска.ПерваяПорция();
Если СписокПоиска.Количество() > 0 Тогда
    Результат = СписокПоиска[0].Значение; // Это и будет наша ссылка
КонецЕсли;

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

Подведем итоги

Для разовых задач на небольших базах вполне подойдет оператор ПОДОБНО с использованием символа %. Если же вы работаете в крупной компании с большим объемом данных, мы рекомендуем либо программно восстанавливать префиксы для точного поиска, либо внедрять вспомогательный регистр сведений. Также всегда учитывайте периодичность нумерации: старайтесь ограничивать поиск по дате, чтобы не получить ссылку на старый заказ с тем же номером.

← На главную