В практике разработки на платформе 1С часто возникает ситуация, когда технические данные (например, сроки поставки) хранятся или передаются в виде текстовых строк, таких как «Поставка 28.01.19». Трудность заключается в том, что стандартная сортировка или поиск максимума для строк работает по алфавитному принципу, а не по календарному. В данной статье мы подробно разберем, как эффективно извлечь дату из текста и найти максимальное значение для вывода в отчет или форму заказа.
Если данные уже получены в виде массива строк или таблицы значений, нам необходимо перебрать их, преобразовать каждую строку в тип Дата и сравнить с текущим максимальным значением. Рассмотрим пример кода, который решает эту задачу. Предположим, у нас есть массив строк с датами в формате «ДД.ММ.ГГ».
Разберем алгоритм пошагово:
Дата(Год, Месяц, День) для формирования полноценного объекта даты.Макс().
МассивЗначений = Новый Массив;
МассивЗначений.Добавить("Поставка 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»), код может отработать неверно. Для более надежной работы рекомендуется использовать функцию СтрЗаменить(), чтобы удалить текст «Поставка » и оставить только дату.
Проанализируем ситуацию: зачем преобразовывать текст обратно в дату, если можно изначально возвращать дату из функции? Это самый правильный подход с точки зрения производительности и чистоты кода. Вместо того чтобы формировать строку «Поставка 28.01.19» внутри функции общего модуля, разделим данные на представление и значение.
Рассмотрим, как можно модифицировать функцию ОпределитьСрокПоставки:
Функция ОпределитьСрокПоставки(ДокументЗаказ, КодСтроки) Экспорт
ТаблицаСрокПоставки = ПолучитьИзВременногоХранилища(ОбновитьСрокиПоставки(ДокументЗаказ));
СтрокаТовара = ТаблицаСрокПоставки.Найти(КодСтроки, "КодСтроки");
// Вместо строки возвращаем чистую дату из реквизита
Если СтрокаТовара <> Неопределено Тогда
Возврат СтрокаТовара.ДатаПоступления;
КонецЕсли;
Возврат Дата(1, 1, 1);
КонецФункции
Теперь, имея чистую дату, мы можем легко использовать ее в Системе компоновки данных (СКД) или при сортировке таблицы значений. Если пользователю все же нужно видеть текст «Поставка...», мы добавим его на этапе оформления отчета (через условное оформление или выражение представления), не ломая логику вычислений.
Если задача стоит в рамках формирования отчета, оптимальным решением будет использование ресурсов СКД. Выясним, как настроить автоматический поиск максимальной даты для всего заказа, если у каждой номенклатурной позиции свой срок.
ДатаПоставкиЧислом.ДатаПоставкиЧислом в ресурсы. В колонке «Выражение» выберем функцию Максимум(ДатаПоставкиЧислом).ЗаказКлиента."Поставка " + Формат(ДатаПоставкиЧислом, "ДФ=дд.ММ.гг").Таким образом, система на уровне запросов и временных таблиц сама найдет самую позднюю дату среди всех строк заказа, а пользователь увидит привычный текстовый формат. Это исключает необходимость писать сложные циклы обхода строк вручную.
Рассмотрим более продвинутый вариант. Если данных много, обращение к функции общего модуля из каждой строки отчета (через вычисляемые поля) может существенно замедлить формирование документа. В этом случае проанализируем возможность перенести логику в текст запроса.
Предположим, данные о сроках хранятся в регистре или табличной части. Мы можем использовать агрегатную функцию МАКСИМУМ непосредственно в SQL-запросе:
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК Заказ,
МАКСИМУМ(ЗаказКлиентаТовары.ДатаПоступления) КАК МаксимальныйСрок
ПОМЕСТИТЬ ВТ_МаксимальныеСроки
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГРУППИРОВАТЬ ПО
ЗаказКлиентаТовары.Ссылка;
Этот метод работает на уровне СУБД, что в десятки раз быстрее, чем обработка каждой строки кодом 1С. После выполнения такого запроса мы получаем готовую таблицу, где для каждого заказа указана одна, самая поздняя дата поставки.
При работе с датами важно помнить о «пустых» значениях. В исходном коде автора упоминается использование знака вопроса "?" для неопределенных дат. При поиске максимума это может привести к ошибкам или игнорированию данных.
Рекомендация: Всегда заменяйте неопределенные или пустые даты на Дата(1, 1, 1) перед сравнением. В этом случае любая заполненная дата будет «больше» пустой, и функция Макс() отработает корректно. Если же вы используете строки, то строка со знаком вопроса при алфавитной сортировке может оказаться выше или ниже дат, что исказит итоговый статус заказа.
Подводя итог, можно сказать, что наиболее эффективным решением является разделение данных: хранение и обработка в формате Дата, и преобразование в формат «Поставка + Дата» только в момент вывода на экран пользователю.