Как вывести несколько дат в одну строку в отчетах 1С?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← К списку

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

Решение в Системе Компоновки Данных (СКД)

Если вы формируете отчеты с помощью Системы Компоновки Данных, то у нас есть наиболее элегантное и рекомендованное решение. Мы будем использовать мощные агрегатные функции СКД – Массив и СоединитьСтроки.

  1. Создание вычисляемого поля:

    Для начала нам потребуется создать новое вычисляемое поле в схеме компоновки данных. Именно в нем мы и будем формировать нашу строку с датами.

  2. Использование функции Массив:

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

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

  3. Использование функции СоединитьСтроки:

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

Давайте посмотрим на пример выражения, которое мы можем указать для вычисляемого поля в СКД:


СоединитьСтроки(Массив(Формат(ПолеСДатой, "ДФ=dd.MM.yyyy")), ", ")

Здесь:

Таким образом, мы сначала форматируем каждую дату в строку, затем собираем эти строки в массив, а после объединяем массив в одну строку через заданный разделитель. Это решение является наиболее гибким и производительным для отчетов на СКД.

Другие подходы в СКД

Решение в языке запросов 1С

Теперь перейдем к языку запросов 1С. Здесь ситуация несколько отличается.

Основная проблема: В стандартном языке запросов 1С отсутствует прямая агрегатная функция, аналогичная STRING_AGG в SQL, которая позволяла бы собрать значения из нескольких строк в одну строку внутри самого запроса.

Конкатенация строк

Если нам нужно объединить даты, которые уже находятся в одной строке результата запроса (например, когда у сущности есть несколько полей типа "Дата", и нам нужно их объединить), то мы можем использовать оператор конкатенации строк +. Даты при этом необходимо предварительно преобразовать в строковый тип с помощью функции ВЫРАЗИТЬ(Дата КАК СТРОКА) или Формат().


ВЫБРАТЬ
    Документ.Номер,
    ВЫРАЗИТЬ(Документ.Дата КАК СТРОКА) + " / " + ВЫРАЗИТЬ(Документ.ДатаПроведения КАК СТРОКА) КАК ДатыДокумента
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ

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

Обходные пути с временными таблицами

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

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

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

Программное формирование строки в коде 1С

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

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

  1. Получение данных:

    Сначала мы получаем данные, содержащие даты, которые нужно объединить. Это может быть результат запроса, выгруженный в ТаблицаЗначений, или данные, полученные из СКД.

  2. Использование объекта Массив и функции СтрСоединить:

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

  3. Форматирование дат:

    Перед добавлением даты в массив, обязательно преобразуйте ее в нужный строковый формат с помощью функции Формат().

Давайте посмотрим на пример программного кода:


// Предположим, у нас есть ТаблицаЗначений "РезультатЗапроса"
// с колонкой "ДатаСобытия" и колонкой "ИдентификаторГруппы",
// по которой нужно объединять даты.

// Создадим структуру для хранения дат по группам
ДатыПоГруппам = Новый Соответствие;

Для Каждого СтрокаТЗ Из РезультатЗапроса Цикл
    ИдентификаторГруппы = СтрокаТЗ.ИдентификаторГруппы;
    ДатаСобытия        = СтрокаТЗ.ДатаСобытия;

    Если Не ДатыПоГруппам.Содержит(ИдентификаторГруппы) Тогда
        ДатыПоГруппам.Вставить(ИдентификаторГруппы, Новый Массив);
    КонецЕсли;

    Если ДатаСобытия <> Неопределено Тогда
        // Добавляем отформатированную дату в массив для текущей группы
        ДатыПоГруппам.Получить(ИдентификаторГруппы).Добавить(Формат(ДатаСобытия, "ДФ=dd.MM.yyyy"));
    КонецЕсли;
КонецЦикла;

// Теперь пройдемся по собранным данным и сформируем итоговые строки
Для Каждого ЭлементСоответствия Из ДатыПоГруппам Цикл
    ИдентификаторГруппы = ЭлементСоответствия.Ключ;
    МассивДатДляГруппы  = ЭлементСоответствия.Значение;

    Если МассивДатДляГруппы.Количество() > 0 Тогда
        СтрокаСДатами = СтрСоединить(МассивДатДляГруппы, ", ");
    Иначе
        СтрокаСДатами = "Даты отсутствуют";
    КонецЕсли;

    Сообщить("Для группы " + ИдентификаторГруппы + ": " + СтрокаСДатами);
    // Здесь вы можете использовать СтрокаСДатами для вывода в отчет,
    // добавления в другую ТаблицуЗначений и т.д.
КонецЦикла;

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

Функции Библиотеки Стандартных Подсистем (БСП)

Если вы используете типовые конфигурации или разработки на базе БСП, обратите внимание на функции общего назначения, которые могут быть полезны для работы со строками и датами. Например, в общих модулях БСП могут быть функции, которые упрощают форматирование дат или манипуляции со строками, что может сократить ваш код.

Заключение

Мы с вами подробно рассмотрели основные подходы к выводу нескольких дат в одну строку в отчетах 1С.

Надеемся, что это подробное руководство поможет вам успешно решать задачи по формированию отчетов и обработке данных в 1С!

← К списку