Как подобрать ссылку на документ 1С по его текстовому представлению из Excel

Программист 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Часто в практике разработчика 1С возникает ситуация, когда пользователи предоставляют данные в формате Excel, где вместо прямых ссылок на объекты содержатся лишь их текстовые представления, например: "Заказ клиента 1111111 от 15.01.2021 23:59:59". Наша задача — корректно преобразовать эту строку в полноценную ссылку на документ в базе данных 1С для дальнейшей обработки. Рассмотрим подробно, как это сделать, разберем возможные "подводные камни" и выберем наиболее эффективные методы.

Способ 1. Ручной парсинг строки и поиск по номеру и дате

Если мы имеем дело со стандартным представлением документа, строка состоит из трех ключевых частей: типа документа, его номера и даты. Разберем алгоритм, при котором мы программно "разрезаем" строку на составляющие.

Для начала проанализируем структуру строки. Мы знаем, что дата обычно находится в конце и имеет фиксированную длину (19 символов для формата "ДД.ММ.ГГГГ ЧЧ:ММ:СС"). Рассмотрим пример кода, который позволяет извлечь данные:


Представление = "Заказ клиента 1111111 от 15.01.2021 23:59:59";
// Извлекаем дату из последних 19 символов
СтрокаДаты = Прав(Представление, 19);
ДатаДокумента = Дата(СтрЗаменить(СтрокаДаты, ".", "")); // Приводим к типу Дата

// Отсекаем дату и слово " от ", чтобы найти номер
ОстатокСтроки = Лев(Представление, СтрДлина(Представление) - 22); 
ЧастиСтроки = СтрРазделить(ОстатокСтроки, " ");
НомерДокумента = ЧастиСтроки[ЧастиСтроки.ВГраница()]; // Номер обычно последнее слово перед "от"

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


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

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

Метод ручного разбиения строки может "сломаться", если формат номера изменится или в названии документа появятся лишние пробелы. Более надежным способом является использование регулярных выражений. Начиная с версии платформы 8.3.23, регулярные выражения доступны "из коробки", но для более старых версий можно использовать COMОбъект("VBScript.RegExp").

Рассмотрим, как с помощью паттерна выделить номер и дату. Паттерн (.*)\s(.+)\sот\s(\d{2}.\d{2}.\d{4}.*) позволит нам гибко разобрать строку, где:

  1. Первая группа — это название вида документа.
  2. Вторая группа — номер документа.
  3. Третья группа — дата.

Проанализируем пример функции для платформы 8.3.23+:


Результат = СтрНайтиПоРегулярномуВыражению(СтрокаИзExcel, "(\d+)\sот\s(\d{2}.\d{2}.\d{4})");
// Это позволит быстро вычленить нужные подстроки даже в нестандартных текстах.

Способ 3. Оптимизация поиска через временные таблицы

Одной из главных ошибок при загрузке данных из Excel является выполнение поиска ссылки в цикле. Если в файле 10 000 строк, система выполнит 10 000 отдельных запросов к базе данных, что крайне медленно. Выясним, как сделать это правильно с помощью запроса.

Рациональнее всего сначала загрузить все данные из Excel в ТаблицуЗначений, подготовить в ней колонки "Номер" и "Дата", а затем передать эту таблицу в запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ВТ_ДанныеExcel.Номер КАК Номер,
    |   ВТ_ДанныеExcel.Дата КАК Дата
    |ПОМЕСТИТЬ ВТ_Excel
    |ИЗ
    |   &ТЗ_Excel КАК ВТ_ДанныеExcel
    |;
    |ВЫБРАТЬ
    |   Заказ.Ссылка,
    |   ВТ_Excel.Номер
    |ИЗ
    |   ВТ_Excel КАК ВТ_Excel
    |   ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК Заказ
    |   ПО ВТ_Excel.Номер = Заказ.Номер
    |   И ВТ_Excel.Дата = Заказ.Дата";

Запрос.УстановитьПараметр("ТЗ_Excel", ВашаТаблицаЗначений);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

Этот подход позволяет найти все ссылки одним обращением к серверу БД, что ускоряет загрузку в десятки раз.

Способ 4. Использование уникальных идентификаторов (GUID)

Проанализируем ситуацию: если вы сами формируете отчет, который пользователи потом редактируют в Excel, всегда добавляйте скрытую колонку с Уникальным Идентификатором (GUID). Это исключит любые проблемы с поиском.

В Excel это будет выглядеть как строка вида "550e8400-e29b-41d4-a716-446655440000". При загрузке нам не нужно ничего парсить и искать по номеру:


// Превращаем строку GUID обратно в ссылку
Идентификатор = Новый УникальныйИдентификатор(СтрокаИзExcel);
Ссылка = Документы.ЗаказКлиента.ПолучитьСсылку(Идентификатор);

Важный момент: метод ПолучитьСсылку не обращается к базе данных. Он создает ссылку "в памяти". Чтобы проверить, существует ли такой документ на самом деле, используйте Ссылка.ПолучитьОбъект() = Неопределено или проверьте наличие ссылки в запросе.

Типичные проблемы и их решение

  1. Лидирующие нули: Excel часто преобразует номер "0000123" в число "123". Перед поиском в 1С обязательно дополняйте номер нулями до нужной длины с помощью функции ОбщегоНазначения.ДополнитьСтрокуЛП() (если используете БСП) или просто кодом:
    
    Пока СтрДлина(НомерИзExcel) < 11 Цикл 
        НомерИзExcel = "0" + НомерИзExcel; 
    КонецЦикла;
    
  2. Префиксы: В разных узлах распределенной базы могут быть свои префиксы. Поиск по НайтиПоНомеру учитывает префиксы автоматически, а вот в запросе при соединении таблиц нужно быть внимательным и сопоставлять номера в том виде, в котором они хранятся в БД.
  3. Дубли номеров: Если в Excel указана дата документа, но не указано время, а документов за этот день несколько — поиск может вернуть не тот объект. Всегда старайтесь выгружать и загружать полное время документа.

Подводя итог, скажем: если есть возможность повлиять на формат выгрузки — используйте GUID. Если данные уже даны в виде строки "Представление" — используйте парсинг через СтрРазделить или регулярные выражения, но обязательно выполняйте итоговое сопоставление через запрос с временной таблицей для обеспечения высокой скорости работы системы.

← На главную