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

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

При разработке бизнес-логики в 1С регулярно возникает задача анализа данных в объекте ТаблицаЗначений. Одной из распространенных задач является сравнение строк между собой по колонкам с временными интервалами, такими как ДатаНачала и ДатаКонца. Рассмотрим подробно, как правильно организовать перебор и проверку строк, какие особенности платформы 1С следует учитывать и какие алгоритмы подходят для решения данной задачи.

Базовый перебор строк в цикле

Если требуется проанализировать каждую строку таблицы значений и проверить соответствие даты заданному условию или значению, используется стандартный цикл Для Каждого. Проанализируем простой пример кода:


Для Каждого СтрокаТЗ Из ТаблицаЗначений Цикл
    Если СтрокаТЗ.ДатаНачала <= ТекущаяДата() Тогда
        // Выполняем необходимую обработку строки
        СтрокаТЗ.Обработана = Истина;
    КонецЕсли;
КонецЦикла;

Этот способ отлично подходит, когда нужно сравнить значение каждой строки с внешним параметром или константой.

Сравнение строк таблицы между собой и проверка пересечения интервалов

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

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

  1. Отсортируем таблицу значений по возрастанию даты начала с помощью метода Сортировать(). Это позволит упорядочить временные отрезки.
  2. Организуем внешний цикл по индексам от 0 до Количество() - 2.
  3. Организуем внутренний цикл по индексам от ИндексВнешнего + 1 до Количество() - 1. Такое построение исключает сравнение строки с самой собой и повторные проверки уже обработанных пар.
  4. Проверим пересечение дат с помощью условий.

Посмотрим на пример реализации данного подхода в коде:


// Шаг 1. Сортировка таблицы по дате начала
ТаблицаЗначений.Сортировать("ДатаНачала Возр");

ВсегоСтрок = ТаблицаЗначений.Количество();

// Шаг 2 и 3. Перебор пар строк по индексам
Для Индекс1 = 0 По ВсегоСтрок - 2 Цикл
    Строка1 = ТаблицаЗначений[Индекс1];
    
    Для Индекс2 = Индекс1 + 1 По ВсегоСтрок - 1 Цикл
        Строка2 = ТаблицаЗначений[Индекс2];
        
        // Учитываем возможные пустые даты окончания (бесконечный период)
        ДатаКонца1 = ?(ЗначениеЗаполнено(Строка1.ДатаКонца), Строка1.ДатаКонца, Дата('39991231'));
        ДатаКонца2 = ?(ЗначениеЗаполнено(Строка2.ДатаКонца), Строка2.ДатаКонца, Дата('39991231'));
        
        // Шаг 4. Проверка пересечения интервалов
        Если (Строка1.ДатаНачала <= ДатаКонца2) И (ДатаКонца1 >= Строка2.ДатаНачала) Тогда
            // Обнаружено пересечение периодов
            Сообщить("Период в строке " + Индекс1 + " пересекается с периодом в строке " + Индекс2);
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Использование запроса для анализа таблицы значений

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

Рассмотрим пример кода для обработки таблицы значений через запрос:


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

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

Важные особенности и ограничения платформы 1С

Выясним ключевые нюансы, о которых необходимо помнить при работе с объектом ТаблицаЗначений:

  1. Контекст исполнения: Объект ТаблицаЗначений доступен на сервере, в толстом клиенте и во внешнем соединении. На тонком клиенте и веб-клиенте вместо него используется ДанныеФормыКоллекция.
  2. Типизация колонок для запросов: При передаче ТаблицаЗначений в запрос в качестве параметра для каждой колонки таблицы должно быть обязательно задано строгое ОписаниеТипов. Если колонки созданы без явного указания типов (например, типа Дата), платформа выдаст ошибку при выполнении запроса.
  3. Ограничения метода НайтиСтроки(): Встроенный метод НайтиСтроки() выполняет поиск исключительно по точечному совпадению (равенству) значений. Проверить вхождение даты в диапазон или пересечение интервалов с помощью этого метода нельзя.
  4. Обработка незаполненных дат: Пустая дата в 1С соответствует значению '00010101'. В логике интервалов незаполненная ДатаКонца обычно трактуется как неограниченный период. Если не обрабатывать пустое значение отдельно, система сочтет пустую дату наименьшим возможным значением, что приведет к ошибкам в логике.
← На главную