При разработке отчетов и обработок в платформе 1С:Предприятие 7.7 часто используется периодическая группировка запроса по месяцам (например, Группировка Месяц Все ВошедшиеВЗапрос;). Однако разработчики регулярно сталкиваются с проблемой: при прямом обращении к переменной группировки через точку (Запрос.Месяц) возвращается строковое представление периода (например, "Январь 17" или "Март 2017"), а не значение с типом Дата.
Если попытаться применить стандартную функцию преобразования НачМесяца(Запрос.Месяц), платформа возвращает пустую дату (' . . '), так как функция ожидает на вход значение типа Дата, а не строку. Это создает сложности при последующей сортировке данных или их передаче в таблицу значений (ТЗ), поскольку текстовые названия месяцев сортируются по алфавиту, а не в хронологическом порядке.
Проанализируем причины такого поведения платформы и подробно разберем штатные способы получения корректной даты начала месяца при работе с выборкой запроса.
В механизме встроенного языка запросов 1С 7.7 при обращении к периодической группировке через свойство объекта (Запрос.<ИмяГруппировки>) возвращается отформатированная строка, предназначенная для вывода в печатную форму отчета. Сама дата начала расчетного интервала хранится внутри контекста выборки, но доступ к ней осуществляется через специализированные методы объекта Запрос.
Рассмотрим основные способы получения даты первого числа месяца.
Наиболее универсальным и рекомендуемым решением при обходе группировок запроса является использование встроенного метода Запрос.НачалоПериода(). Внутри цикла обхода интервальной группировки этот метод возвращает дату начала текущего периода (для группировки по месяцам — первое число месяца со временем 00:00:00).
Разберем пример кода с обходом выборки, проверкой условий и заполнением таблицы значений:
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("ДатаМесяца", "Дата");
ТЗ.НоваяКолонка("Сумма", "Число", 15, 2);
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|Период С ВыбНачПериода По ВыбКонПериода;
|Сумма = Регистр.Продажи.Сумма;
|Функция СуммаИтог = Сумма(Сумма);
|Группировка Месяц Все ВошедшиеВЗапрос;
|//}}ЗАПРОС
";
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Пока Запрос.Группировка("Месяц") = 1 Цикл
ДатаНачала = Запрос.НачалоПериода();
// Пример фильтрации строк по условию
Если Запрос.СуммаИтог > 0 Тогда
ТЗ.НоваяСтрока();
ТЗ.ДатаМесяца = ДатаНачала;
ТЗ.Сумма = Запрос.СуммаИтог;
КонецЕсли;
КонецЦикла;
// Сортировка таблицы значений по реальной дате
ТЗ.Сортировать("ДатаМесяца+");
КонецЕсли;
Если для логики алгоритма требуется также дата конца месяца, можно применить парный метод Запрос.КонецПериода(), который возвращает дату последнего дня текущего интервала группировки (28, 29, 30 или 31 число соответствующего месяца).
Еще один штатный метод получения типизированного значения — вызов Запрос.ЗначениеГруппировки(...). В качестве параметра можно передать строковое имя группировки или её порядковый номер в запросе.
В отличие от обращения через точку (Запрос.Месяц), метод Запрос.ЗначениеГруппировки("Месяц") для встроенных периодических группировок (День, Неделя, Декада, Месяц, Квартал, Год) возвращает истинное значение типа Дата, соответствующее началу интервала.
Посмотрим на пример использования:
Пока Запрос.Группировка(1) = 1 Цикл
ДатаМесяца = Запрос.ЗначениеГруппировки(1);
// ДатаМесяца имеет тип Дата, корректно передается в ТЗ
ТЗ.НоваяСтрока();
ТЗ.Дата = ДатаМесяца;
ТЗ.Сумма = Запрос.СуммаИтог;
КонецЦикла;
Если требуется получить таблицу значений с результатами запроса, можно использовать метод Запрос.Выгрузить(ТаблицаЗначений, ...). При прямой выгрузке встроенный механизм платформы 1С 7.7 автоматически формирует колонки с правильными типами данных: в колонку группировки Месяц помещается именно дата начала периода (тип Дата), а не строка.
Разберем по шагам, как выгрузить данные и отфильтровать ненужные строки:
Запрос.Выгрузить(ТЗ, 1, 0).Посмотрим на пример реализации:
ТЗ = СоздатьОбъект("ТаблицаЗначений");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
// Выгружаем данные группировок верхнего уровня в ТЗ
Запрос.Выгрузить(ТЗ, 1, 0);
// Удаляем строки, не удовлетворяющие условию, обходом с конца таблицы
Для Сч = -ТЗ.КоличествоСтрок() По -1 Цикл
НомерСтроки = -Сч;
Если ТЗ.ПолучитьЗначение(НомерСтроки, "СуммаИтог") <= 0 Тогда
ТЗ.УдалитьСтроку(НомерСтроки);
КонецЕсли;
КонецЦикла;
// Колонка "Месяц" в ТЗ содержит даты, сортировка выполняется корректно
ТЗ.Сортировать("Месяц+");
КонецЕсли;
Для корректной работы с датами при группировке запроса по месяцам в 1С 7.7 следует избегать прямого чтения свойства Запрос.Месяц для получения даты. Используйте метод Запрос.НачалоПериода() или Запрос.ЗначениеГруппировки("Месяц") при ручном обходе выборки, либо штатную выгрузку Запрос.Выгрузить(ТЗ) при пакетной обработке данных.