Как найти и распознать дату в текстовой строке в 1С:Предприятии?

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

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

Способ 1. Использование регулярных выражений (COM-объект VBScript.RegExp)

Для гибкого поиска шаблона даты вида ДД.ММ.ГГГГ в произвольном тексте удобно использовать механизм регулярных выражений. В операционной системе Windows для этого традиционно применяется объект VBScript.RegExp.

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


Регуляр = Новый COMОбъект("VBScript.RegExp");
Регуляр.IgnoreCase = Истина; // Игнорировать регистр
Регуляр.Global = Истина;     // Поиск всех вхождений шаблона
Регуляр.Pattern = "\b\d{2}\.\d{2}\.\d{4}\b"; // Шаблон даты ДД.ММ.ГГГГ

// Исходная строка для анализа
СтрокаДляПоиска = Строка(СтрокаТабличнойЧасти.ХарактеристикаНоменклатуры);

Результаты = Регуляр.Execute(СтрокаДляПоиска);

Для Каждого Совпадение Из Результаты Цикл
    НайденнаяПодстрока = Совпадение.Value;
    Сообщить("Найдена дата в тексте: " + НайденнаяПодстрока);
    
    // Преобразуем найденную подстроку в тип Дата
    НашаДата = ПреобразоватьСтрокуДДММГГГГВДату(НайденнаяПодстрока);
    Сообщить("Тип 1С Дата: " + Строка(НашаДата));
КонецЦикла;

Разбор ошибки: «Ошибка при вызове метода контекста (Execute) по причине: Типы не совпадают (0)»

Выясним причину распространенной ошибки, возникающей при передаче значения в метод Execute. Метод Execute COM-объекта принимает исключительно строковые данные (тип BSTR). Если в метод передается реквизит составного типа, ссылка на элемент справочника (например, СправочникСсылка.ХарактеристикиНоменклатуры), значение Неопределено или NULL, платформа 1С вызывает исключение несовпадения типов.

Чтобы избежать ошибки, обязательно приводим анализируемое значение к строковому типу с помощью встроенной функции: Строка(ЗначениеРеквизита).

Способ 2. Преобразование строки «ДД.ММ.ГГГГ» в тип Дата

После того как дата выделена из текста в виде строки "10.10.2017", попытка выполнить вызов Дата("10.10.2017") приведет к фатальной ошибке: «Преобразование значения к типу Дата не может быть выполнено».

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

Преобразовать строку в дату можно несколькими надежными путями:

  1. Сборка канонической строки с помощью строковых функций:

    Разберем строку на составляющие (день, месяц, год) с помощью функций Лев(), Сред(), Прав() и объединим их в каноническую строку "ГГГГММДД":

    
    Функция ПреобразоватьСтрокуДДММГГГГВДату(СтрДата) Экспорт
        // Формат строки: "ДД.ММ.ГГГГ" (10 символов)
        Если СтрДлина(СтрДата) <> 10 Тогда
            Возврат '00010101';
        КонецЕсли;
        
        ДеньСтр  = Лев(СтрДата, 2);
        МесяцСтр = Сред(СтрДата, 4, 2);
        ГодСтр   = Сред(СтрДата, 7, 4);
        
        КаноническаяСтрока = ГодСтр + МесяцСтр + ДеньСтр;
        
        Попытка
            Возврат Дата(КаноническаяСтрока);
        Исключение
            // Перехват некорректных дат (например, 31.02.2023)
            Возврат '00010101';
        КонецПопытки;
    КонецФункции
    
  2. Использование конструктора даты с числовыми параметрами:

    Конструктор Дата(Год, Месяц, День) принимает числа. Выделим подстроки, преобразуем их к типу Число и передадим в конструктор:

    
    Попытка
        День  = Число(Лев(СтрДата, 2));
        Месяц = Число(Сред(СтрДата, 4, 2));
        Год   = Число(Сред(СтрДата, 7, 4));
        
        РезультатДата = Дата(Год, Месяц, День);
    Исключение
        РезультатДата = '00010101';
    КонецПопытки;
    
  3. Использование функции БСП (Библиотека стандартных подсистем):

    Если в конфигурации внедрена БСП, воспользуемся готовой библиотечной функцией, которая умеет безопасно преобразовывать строки формата ДД.ММ.ГГГГ:

    РезультатДата = СтроковыеФункцииКлиентСервер.СтрокаВДату(СтрДата);

Способ 3. Поиск даты без использования COM-объектов (чистый код 1С)

При работе на сервере под управлением Linux или в веб-клиенте вызов COMОбъект("VBScript.RegExp") завершится ошибкой, так как COM-технология доступна исключительно в среде Windows. В таких условиях задачу можно решить штатными строковыми функциями платформы 1С.

Рассмотрим алгоритм разбора строки по разделителям:


Функция НайтиДатуВТекстеБезCOM(ИсходныйТекст) Экспорт
    // Заменяем распространенные знаки препинания на пробелы для разделения слов
    ОчищеннаяСтрока = СтрЗаменить(ИсходныйТекст, ",", " ");
    ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, ";", " ");
    
    МассивСлов = СтрРазделить(ОчищеннаяСтрока, " ", Ложь);
    
    Для Каждого Слово Из МассивСлов Цикл
        Слово = СокрЛП(Слово);
        // Проверяем формат ДД.ММ.ГГГГ: длина ровно 10 символов и точки на 3 и 6 позициях
        Если СтрДлина(Слово) = 10 И Сред(Слово, 3, 1) = "." И Сред(Слово, 6, 1) = "." Тогда
            Попытка
                День  = Число(Лев(Слово, 2));
                Месяц = Число(Сред(Слово, 4, 2));
                Год   = Число(Сред(Слово, 7, 4));
                
                Если День >= 1 И День <= 31 И Месяц >= 1 И Месяц <= 12 И Год >= 1900 И Год <= 2099 Тогда
                    Возврат Дата(Год, Месяц, День);
                КонецЕсли;
            Исключение
                // Не является корректным числом или датой, продолжаем поиск
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
    
    Возврат '00010101';
КонецФункции

Важные рекомендации:

  1. Любое создание даты на основе внешних или введенных пользователем данных обязательно оборачиваем в конструкцию Попытка ... Исключение, так как некорректная календарная дата (например, 29 февраля невисокосного года) приводит к аварийной остановке выполнения модуля.
  2. Для кроссплатформенных конфигураций (сервер Linux, мобильные клиенты) следует отдавать предпочтение разбору строки через встроенные функции языка 1С без использования внешних COM-библиотек.
← На главную