Приветствуем вас! Сегодня мы рассмотрим актуальную и часто встречающуюся задачу в разработке отчетов на платформе 1С: вывод нескольких дат, относящихся к одной сущности, в одну текстовую строку. Например, когда нам необходимо показать все даты оплат по одному заказу или все даты событий по конкретному объекту в одной ячейке отчета. На первый взгляд задача может показаться нетривиальной, но платформа 1С предоставляет нам несколько мощных инструментов для ее решения, зависящих от того, где именно мы планируем выполнять обработку данных – в Системе Компоновки Данных (СКД), непосредственно в языке запросов или уже на стороне программного кода. Давайте вместе разберем каждый из подходов и выясним, какой из них будет наиболее эффективным в той или иной ситуации.
Если вы формируете отчеты с помощью Системы Компоновки Данных, то у нас есть наиболее элегантное и рекомендованное решение. Мы будем использовать мощные агрегатные функции СКД – Массив и СоединитьСтроки.
Для начала нам потребуется создать новое вычисляемое поле в схеме компоновки данных. Именно в нем мы и будем формировать нашу строку с датами.
Массив:
Функция Массив (в англоязычной версии Array) позволяет нам собрать значения из детальных записей по определенному полю или выражению в коллекцию (массив). Представьте, что у нас есть несколько строк данных, и каждая строка содержит дату. Мы хотим собрать все эти даты в один список для каждой группы.
Важный момент: прежде чем передавать дату в массив, ее необходимо преобразовать в строковый формат. Для этого используем функцию Формат() с подходящей форматной строкой. Это позволит нам контролировать внешний вид даты в итоговой строке (например, "ДД.ММ.ГГГГ").
СоединитьСтроки:
Полученный массив строк с датами мы затем передаем функции СоединитьСтроки (в англоязычной версии JoinStrings). Эта функция объединяет все элементы массива в одну строку, используя заданный нами разделитель. В качестве разделителя вы можете выбрать запятую, пробел, перевод строки или любой другой символ, который подходит для вашего отчета.
Давайте посмотрим на пример выражения, которое мы можем указать для вычисляемого поля в СКД:
СоединитьСтроки(Массив(Формат(ПолеСДатой, "ДФ=dd.MM.yyyy")), ", ")
Здесь:
ПолеСДатой – это поле вашего набора данных, содержащее дату, которую вы хотите вывести."ДФ=dd.MM.yyyy" – это форматная строка для функции Формат(), которая преобразует дату в строку вида "день.месяц.год". Вы можете настроить ее под свои нужды.", " – это разделитель, который будет использоваться между датами в итоговой строке.Таким образом, мы сначала форматируем каждую дату в строку, затем собираем эти строки в массив, а после объединяем массив в одну строку через заданный разделитель. Это решение является наиболее гибким и производительным для отчетов на СКД.
Теоретически можно создать вычисляемое поле, где с помощью выражений мы бы пытались конкатенировать даты. Однако для сценариев, когда нужно собрать множество дат из разных строк в одну, этот метод становится крайне неудобным и сложным в реализации, поскольку не предоставляет прямой агрегации "строка в строку".
Для полей отчета на вкладке "Наборы данных" в схеме компоновки данных можно настроить "Выражение представления". Это позволяет определить, как будет отображаться поле. Однако, это скорее инструмент для форматирования одного значения, чем для агрегации нескольких значений из разных строк в одно.
Теперь перейдем к языку запросов 1С. Здесь ситуация несколько отличается.
Основная проблема: В стандартном языке запросов 1С отсутствует прямая агрегатная функция, аналогичная STRING_AGG в SQL, которая позволяла бы собрать значения из нескольких строк в одну строку внутри самого запроса.
Если нам нужно объединить даты, которые уже находятся в одной строке результата запроса (например, когда у сущности есть несколько полей типа "Дата", и нам нужно их объединить), то мы можем использовать оператор конкатенации строк +. Даты при этом необходимо предварительно преобразовать в строковый тип с помощью функции ВЫРАЗИТЬ(Дата КАК СТРОКА) или Формат().
ВЫБРАТЬ
Документ.Номер,
ВЫРАЗИТЬ(Документ.Дата КАК СТРОКА) + " / " + ВЫРАЗИТЬ(Документ.ДатаПроведения КАК СТРОКА) КАК ДатыДокумента
ИЗ
Документ.РеализацияТоваровУслуг КАК Документ
Этот метод подходит только для объединения значений, которые уже доступны в одной строке запроса. Он не решает задачу сбора дат из разных строк.
Для более сложных сценариев, когда нам нужно собрать даты из нескольких строк в одну, приходится прибегать к обходным путям. Обычно это включает в себя:
Поэтому, если есть возможность, мы рекомендуем переносить логику формирования строки с датами на уровень СКД (как было описано выше) или на уровень программного кода, если речь идет о программном формировании отчета или обработке данных.
Наконец, рассмотрим ситуацию, когда данные уже получены из запроса или СКД, например, в виде объекта ТаблицаЗначений, и нам необходимо программно сформировать итоговую строку.
Этот подход наиболее гибок, поскольку мы можем использовать все возможности языка 1С. Мы будем обходить полученные данные в цикле и вручную формировать нужную строку.
Сначала мы получаем данные, содержащие даты, которые нужно объединить. Это может быть результат запроса, выгруженный в ТаблицаЗначений, или данные, полученные из СКД.
Массив и функции СтрСоединить:
Мы можем создать временный объект Массив, добавлять в него строковые представления каждой даты, а затем объединить их с помощью функции СтрСоединить.
Перед добавлением даты в массив, обязательно преобразуйте ее в нужный строковый формат с помощью функции Формат().
Давайте посмотрим на пример программного кода:
// Предположим, у нас есть ТаблицаЗначений "РезультатЗапроса"
// с колонкой "ДатаСобытия" и колонкой "ИдентификаторГруппы",
// по которой нужно объединять даты.
// Создадим структуру для хранения дат по группам
ДатыПоГруппам = Новый Соответствие;
Для Каждого СтрокаТЗ Из РезультатЗапроса Цикл
ИдентификаторГруппы = СтрокаТЗ.ИдентификаторГруппы;
ДатаСобытия = СтрокаТЗ.ДатаСобытия;
Если Не ДатыПоГруппам.Содержит(ИдентификаторГруппы) Тогда
ДатыПоГруппам.Вставить(ИдентификаторГруппы, Новый Массив);
КонецЕсли;
Если ДатаСобытия <> Неопределено Тогда
// Добавляем отформатированную дату в массив для текущей группы
ДатыПоГруппам.Получить(ИдентификаторГруппы).Добавить(Формат(ДатаСобытия, "ДФ=dd.MM.yyyy"));
КонецЕсли;
КонецЦикла;
// Теперь пройдемся по собранным данным и сформируем итоговые строки
Для Каждого ЭлементСоответствия Из ДатыПоГруппам Цикл
ИдентификаторГруппы = ЭлементСоответствия.Ключ;
МассивДатДляГруппы = ЭлементСоответствия.Значение;
Если МассивДатДляГруппы.Количество() > 0 Тогда
СтрокаСДатами = СтрСоединить(МассивДатДляГруппы, ", ");
Иначе
СтрокаСДатами = "Даты отсутствуют";
КонецЕсли;
Сообщить("Для группы " + ИдентификаторГруппы + ": " + СтрокаСДатами);
// Здесь вы можете использовать СтрокаСДатами для вывода в отчет,
// добавления в другую ТаблицуЗначений и т.д.
КонецЦикла;
Этот подход позволяет нам полностью контролировать процесс формирования строки, добавлять различные условия, форматирование и логику.
Если вы используете типовые конфигурации или разработки на базе БСП, обратите внимание на функции общего назначения, которые могут быть полезны для работы со строками и датами. Например, в общих модулях БСП могут быть функции, которые упрощают форматирование дат или манипуляции со строками, что может сократить ваш код.
Мы с вами подробно рассмотрели основные подходы к выводу нескольких дат в одну строку в отчетах 1С.
Массив и СоединитьСтроки в вычисляемых полях. Это решение обеспечивает высокую производительность и гибкость.Формат(), Массив и СтрСоединить().Надеемся, что это подробное руководство поможет вам успешно решать задачи по формированию отчетов и обработке данных в 1С!
← К списку