Как получить самую раннюю дату в табличной части документа 1С

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

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

В этой статье мы подробно разберем несколько эффективных способов решения данной задачи, проанализируем их плюсы и минусы, а также выясним, какой метод лучше выбрать в зависимости от объема данных.

Способ 1. Простой перебор строк табличной части

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

Рассмотрим пример кода для реализации в модуле документа или формы:


СамаяМеньшаяДата = '00010101'; // Инициализируем пустой датой

Для Каждого СтрокаТЧ Из Объект.Товары Цикл
    ТекущаяДата = СтрокаТЧ.ДатаОтгрузки;
    
    // Проверяем, заполнена ли дата в текущей строке
    Если ЗначениеЗаполнено(ТекущаяДата) Тогда
        // Если наша итоговая дата еще пустая или текущая меньше найденной ранее
        Если СамаяМеньшаяДата = '00010101' Или ТекущаяДата < СамаяМеньшаяДата Тогда
            СамаяМеньшаяДата = ТекущаяДата;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

// Теперь в переменной СамаяМеньшаяДата находится искомое значение

Важный нюанс: Обратите внимание на инициализацию. Если вы просто напишете СамаяМеньшаяДата = '29991231', вы можете столкнуться с проблемой, если все даты в ТЧ окажутся пустыми. Проверка через ЗначениеЗаполнено() позволяет гарантированно отсечь пустые значения 0001.01.01.

Способ 2. Выгрузка в таблицу значений и сортировка

Если нам нужно не просто найти минимум, а выполнить дополнительные манипуляции с данными, удобно использовать объект ТаблицаЗначений. Метод Выгрузить() позволяет мгновенно превратить строки табличной части в коллекцию, поддерживающую сортировку.

Разберем этот процесс по шагам:

  1. Выгружаем нужную нам колонку в таблицу значений.
  2. Сортируем таблицу по возрастанию.
  3. Находим первую строку, в которой дата не является пустой.

Пример программного кода:


// Шаг 1: Выгружаем данные
ТаблицаДат = Объект.ИмяВашейТЧ.Выгрузить( , "ИмяКолонкиДата");

// Шаг 2: Сортируем по возрастанию
ТаблицаДат.Сортировать("ИмяКолонкиДата Возр");

// Шаг 3: Ищем первую непустую дату
СамаяРанняяДата = '00010101';
Для Каждого Стр Из ТаблицаДат Цикл
    Если ЗначениеЗаполнено(Стр.ИмяКолонкиДата) Тогда
        СамаяРанняяДата = Стр.ИмяКолонкиДата;
        Прервать; // Выходим из цикла сразу после нахождения минимума
    КонецЕсли;
КонецЦикла;

Почему нельзя просто взять ТаблицаДат[0].ИмяКолонкиДата? Потому что при сортировке по возрастанию (Возр) пустые даты всегда окажутся в самом начале списка. Именно поэтому цикл после сортировки необходим для пропуска незаполненных значений.

Способ 3. Использование запроса к таблице значений

Этот метод считается наиболее профессиональным и эффективным, если в табличной части сотни или тысячи строк. Запросы в 1С работают крайне быстро, так как используют оптимизированные алгоритмы. Однако, поскольку данные еще не записаны в базу, мы не можем просто обратиться к таблице документа. Нам нужно передать таблицу значений в запрос как внешний источник.

Рассмотрим подробнее алгоритм реализации этого метода:


// 1. Подготавливаем таблицу значений
ТЗ = Объект.Список.Выгрузить(); 

// 2. Инициализируем запрос
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	МИНИМУМ(ВТ_Данные.ДатаСобытия) КАК МинДата
    |ИЗ
    |	&ТЗ КАК ВТ_Данные
    |ГДЕ
    |	ВТ_Данные.ДатаСобытия <> ДАТАВРЕМЯ(1, 1, 1)";

// 3. Передаем таблицу в запрос
Запрос.УстановитьПараметр("ТЗ", ТЗ);

// 4. Выполняем расчет
Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда
    МинимальнаяДата = Выборка.МинДата;
КонецЕсли;

Важные замечания по работе с запросом:

Сравнение методов и нюансы платформы

Проанализируем технические особенности методов, которые могут повлиять на ваш выбор:

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

Ограничение метода Итог(): У таблицы значений есть метод Итог("ИмяКолонки"). Часто начинающие разработчики пытаются применить его для дат. Помните: Итог работает только для числовых колонок. Попытка вызвать его для колонки с типом "Дата" приведет к ошибке выполнения.

Метод НайтиСтроки(): Если вам нужно найти строки с конкретной датой, этот метод незаменим. Однако для поиска именно минимального (неизвестного заранее) значения он не подходит напрямую.

Выводы: какой метод выбрать?

Выясним итоговые рекомендации для различных ситуаций:

  1. Если строк мало (до 100) и код на клиенте: Используйте простой перебор через Для Каждого. Это избавит от лишних серверных вызовов и создания тяжелых объектов типа Запрос.
  2. Если строк много (от 500) или код выполняется на сервере: Однозначно выбирайте Запрос к таблице значений. Агрегатные функции СУБД (или менеджера временных таблиц 1С) работают быстрее ручных циклов.
  3. Если пустые даты — норма: Всегда добавляйте условие ЗначениеЗаполнено() или проверку на ДАТАВРЕМЯ(1, 1, 1) в запросе. В противном случае ваш код будет всегда возвращать пустую дату как самую раннюю.

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

← На главную