Как вывести строку по максимальному числовому значению даты из текста

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

В практике разработки на платформе 1С часто возникает ситуация, когда технические данные (например, сроки поставки) хранятся или передаются в виде текстовых строк, таких как «Поставка 28.01.19». Трудность заключается в том, что стандартная сортировка или поиск максимума для строк работает по алфавитному принципу, а не по календарному. В данной статье мы подробно разберем, как эффективно извлечь дату из текста и найти максимальное значение для вывода в отчет или форму заказа.

Метод 1: Программный парсинг строки и поиск максимума в цикле

Если данные уже получены в виде массива строк или таблицы значений, нам необходимо перебрать их, преобразовать каждую строку в тип Дата и сравнить с текущим максимальным значением. Рассмотрим пример кода, который решает эту задачу. Предположим, у нас есть массив строк с датами в формате «ДД.ММ.ГГ».

Разберем алгоритм пошагово:

  1. Создаем переменную для хранения максимальной даты и инициализируем ее пустой датой.
  2. В цикле извлекаем подстроку, содержащую числовые значения.
  3. Используем конструктор Дата(Год, Месяц, День) для формирования полноценного объекта даты.
  4. Сравниваем полученную дату с максимальной с помощью функции Макс().

МассивЗначений = Новый Массив;
МассивЗначений.Добавить("Поставка 28.01.19");
МассивЗначений.Добавить("Поставка 30.01.19");
МассивЗначений.Добавить("Поставка 29.01.19");

МаксимальнаяДата = Дата(1, 1, 1); // Инициализация пустой датой

Для Каждого Элемент Из МассивЗначений Цикл
    // Отсекаем префикс "Поставка ", который занимает 9 символов (включая пробел)
    ДатаСтрока = Сред(Элемент, 10); 
    
    // Формируем дату. Внимание: учитываем, что год указан в формате "гг"
    // Для корректности добавляем "20" перед годом
    Год   = "20" + Прав(ДатаСтрока, 2);
    Месяц = Сред(ДатаСтрока, 4, 2);
    День  = Лев(ДатаСтрока, 2);
    
    Попытка
        ТекущаяДатаПоставки = Дата(Год, Месяц, День);
        МаксимальнаяДата = Макс(МаксимальнаяДата, ТекущаяДатаПоставки);
    Исключение
        // Обработка некорректных строк, например, если дата указана как "?"
        Продолжить;
    КонецПопытки;
КонецЦикла;

// В переменной МаксимальнаяДата теперь хранится 30.01.2019

Важный нюанс: использование функций Лев(), Прав() и Сред() жестко привязывает код к позиции символов. Если формат строки изменится (например, вместо «19» будет «2019»), код может отработать неверно. Для более надежной работы рекомендуется использовать функцию СтрЗаменить(), чтобы удалить текст «Поставка » и оставить только дату.

Метод 2: Изменение архитектуры функции (возврат объекта Даты)

Проанализируем ситуацию: зачем преобразовывать текст обратно в дату, если можно изначально возвращать дату из функции? Это самый правильный подход с точки зрения производительности и чистоты кода. Вместо того чтобы формировать строку «Поставка 28.01.19» внутри функции общего модуля, разделим данные на представление и значение.

Рассмотрим, как можно модифицировать функцию ОпределитьСрокПоставки:


Функция ОпределитьСрокПоставки(ДокументЗаказ, КодСтроки) Экспорт
    ТаблицаСрокПоставки = ПолучитьИзВременногоХранилища(ОбновитьСрокиПоставки(ДокументЗаказ));
    СтрокаТовара = ТаблицаСрокПоставки.Найти(КодСтроки, "КодСтроки");
    
    // Вместо строки возвращаем чистую дату из реквизита
    Если СтрокаТовара <> Неопределено Тогда
        Возврат СтрокаТовара.ДатаПоступления; 
    КонецЕсли;
    
    Возврат Дата(1, 1, 1);
КонецФункции

Теперь, имея чистую дату, мы можем легко использовать ее в Системе компоновки данных (СКД) или при сортировке таблицы значений. Если пользователю все же нужно видеть текст «Поставка...», мы добавим его на этапе оформления отчета (через условное оформление или выражение представления), не ломая логику вычислений.

Метод 3: Использование Системы компоновки данных (СКД)

Если задача стоит в рамках формирования отчета, оптимальным решением будет использование ресурсов СКД. Выясним, как настроить автоматический поиск максимальной даты для всего заказа, если у каждой номенклатурной позиции свой срок.

  1. Вычисляемое поле: Создадим поле, в котором вызывается ваша функция получения даты. Назовем его ДатаПоставкиЧислом.
  2. Вкладка «Ресурсы»: Добавим поле ДатаПоставкиЧислом в ресурсы. В колонке «Выражение» выберем функцию Максимум(ДатаПоставкиЧислом).
  3. Рассчитывать по: Укажем, что этот максимум нужно рассчитывать в разрезе ЗаказКлиента.
  4. Выражение представления: Для того чтобы в отчете красиво выводилось «Поставка 30.01.19», в поле «Выражение представления» для нашего ресурса пропишем: "Поставка " + Формат(ДатаПоставкиЧислом, "ДФ=дд.ММ.гг").

Таким образом, система на уровне запросов и временных таблиц сама найдет самую позднюю дату среди всех строк заказа, а пользователь увидит привычный текстовый формат. Это исключает необходимость писать сложные циклы обхода строк вручную.

Метод 4: Оптимизация поиска через временные таблицы в запросе

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

Предположим, данные о сроках хранятся в регистре или табличной части. Мы можем использовать агрегатную функцию МАКСИМУМ непосредственно в SQL-запросе:


ВЫБРАТЬ
    ЗаказКлиентаТовары.Ссылка КАК Заказ,
    МАКСИМУМ(ЗаказКлиентаТовары.ДатаПоступления) КАК МаксимальныйСрок
ПОМЕСТИТЬ ВТ_МаксимальныеСроки
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГРУППИРОВАТЬ ПО
    ЗаказКлиентаТовары.Ссылка;

Этот метод работает на уровне СУБД, что в десятки раз быстрее, чем обработка каждой строки кодом 1С. После выполнения такого запроса мы получаем готовую таблицу, где для каждого заказа указана одна, самая поздняя дата поставки.

Обработка исключений и пустых значений

При работе с датами важно помнить о «пустых» значениях. В исходном коде автора упоминается использование знака вопроса "?" для неопределенных дат. При поиске максимума это может привести к ошибкам или игнорированию данных.

Рекомендация: Всегда заменяйте неопределенные или пустые даты на Дата(1, 1, 1) перед сравнением. В этом случае любая заполненная дата будет «больше» пустой, и функция Макс() отработает корректно. Если же вы используете строки, то строка со знаком вопроса при алфавитной сортировке может оказаться выше или ниже дат, что исказит итоговый статус заказа.

Подводя итог, можно сказать, что наиболее эффективным решением является разделение данных: хранение и обработка в формате Дата, и преобразование в формат «Поставка + Дата» только в момент вывода на экран пользователю.

← На главную