При разработке печатных форм в 1С часто возникает необходимость отсортировать табличные данные, особенно если эти данные получаются из запросов с использованием группировок. Разберем ситуацию, когда требуется упорядочить область «Строки» по колонке, содержащей представление номенклатуры, например, НоменклатураПредставление, но стандартные методы сортировки через УПОРЯДОЧИТЬ ПО не дают ожидаемого результата. Мы выясним, почему так происходит, и предложим эффективные решения.
Предположим, у нас есть запрос, который формирует данные для сборочного листа, и мы хотим, чтобы список номенклатуры внутри каждой группировки (например, по складу) был отсортирован по алфавиту наименования. Однако, несмотря на добавление УПОРЯДОЧИТЬ ПО НоменклатураПредставление в запрос, порядок вывода в печатной форме остается непредсказуемым.
Основная причина такого поведения кроется во взаимодействии между секциями запроса УПОРЯДОЧИТЬ ПО и ИТОГИ ПО, а также методом обхода результата запроса в коде 1С. Когда мы используем Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) для итерации по результатам запроса, порядок, в котором выбираются эти группировки, строго определяется порядком полей, указанных в секции ИТОГИ ПО вашего запроса.
Секция УПОРЯДОЧИТЬ ПО в запросе определяет порядок детальных записей, которые затем используются для расчета итогов и формирования группировок. Однако при обходе результатов запроса методом Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) приоритет в определении порядка группировок имеет секция ИТОГИ ПО. Если в секции ИТОГИ ПО указана Номенклатура (то есть ссылка на элемент справочника), то система будет группировать и обходить результаты по самой ссылке, а не по ее представлению (строковому значению). Это означает, что даже если НоменклатураПредставление есть в УПОРЯДОЧИТЬ ПО, это не повлияет на порядок группировок, которые определяются вышестоящими уровнями в ИТОГИ ПО.
Для диагностики этой проблемы всегда рекомендуется выполнить запрос в консоли запросов. Если в консоли вы видите, что данные в группировках уже идут вперемешку, это однозначно указывает на проблему в структуре самого запроса, а не в коде, формирующем печатную форму.
Давайте рассмотрим структуру предоставленного запроса и итераций по нему. Наш запрос содержит несколько временных таблиц и финальную выборку. Особое внимание уделим последней секции:
|ВЫБРАТЬ
| ...
|ИЗ
| Состав КАК Состав
| ЛЕВОЕ СОЕДИНЕНИЕ СвойстваТовара КАК СвойстваТовара
| ПО Состав.Номенклатура = СвойстваТовара.Номенклатура
| И Состав.ЕдИзм = СвойстваТовара.ЕдИзм
| ЛЕВОЕ СОЕДИНЕНИЕ Реквизиты КАК Реквизиты
| ПО Состав.РасходнаяНакладная = Реквизиты.РасходнаяНакладная
|
|УПОРЯДОЧИТЬ ПО
| Номенклатура,
| Контрагент,
| АдресДоставки,
| ТорговаяТочка,
| СкладР,
| НомерСклада,
| ТорговаяМарка,
| МаршрутныйЛист,
| РасходнаяНакладная
|ИТОГИ
| МАКСИМУМ(Договор),
| МАКСИМУМ(Служебный),
| МАКСИМУМ(НоменклатураПредставление),
| МАКСИМУМ(Номер),
| МАКСИМУМ(Дата),
| МАКСИМУМ(Склад),
| МАКСИМУМ(НомерР),
| МАКСИМУМ(ДатаР),
| МАКСИМУМ(Экспедитор),
| МАКСИМУМ(Водитель),
| СУММА(Количество),
| СУММА(Сумма),
| МАКСИМУМ(Артикул),
| МАКСИМУМ(ШтрихКод),
| СУММА(Объем),
| СУММА(ВесБрутто),
| СУММА(КоличествоУп)
|ПО
| МаршрутныйЛист,
| Контрагент,
| АдресДоставки,
| ТорговаяТочка,
| СкладР,
| НомерСклада,
| Номенклатура,
| РасходнаяНакладная
В коде формирования печатной формы мы видим следующие итерации, которые соответствуют уровням группировки в секции ИТОГИ ПО:
ВыборкаМаршрутныйЛист = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО МаршрутныйЛист)ВыборкаКонтрагент = ВыборкаМаршрутныйЛист.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО Контрагент)ВыборкаАдрес = ВыборкаКонтрагент.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО АдресДоставки)ВыборкаТорговаяТочка = ВыборкаАдрес.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО ТорговаяТочка)ВыборкаСкладР = ВыборкаТорговаяТочка.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО СкладР)ВыборкаНомерСклада = ВыборкаСкладР.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО НомерСклада)ВыборкаНоменклатура = ВыборкаНомерСклада.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); (соответствует ПО Номенклатура)Именно на седьмом уровне, где мы получаем ВыборкаНоменклатура, должна происходить сортировка по НоменклатураПредставление. Однако в секции ИТОГИ ПО на этом уровне указана просто Номенклатура. Это означает, что группировка и, соответственно, порядок обхода будет осуществляться по внутренней ссылке объекта Номенклатура, а не по ее строковому представлению. Строки будут отсортированы по уникальным идентификаторам номенклатуры, что визуально выглядит как хаотичный порядок.
Важным требованием является то, что сортировка по номеру склада (НомерСклада) должна оставаться нетронутой. Это означает, что изменения должны касаться только порядка внутри уже сгруппированных по складу данных.
Для того чтобы добиться желаемой сортировки по НоменклатураПредставление на уровне группировки номенклатуры, нам необходимо внести изменения в секцию ИТОГИ ПО запроса.
ИТОГИ ПОЧтобы обеспечить сортировку группировок по НоменклатураПредставление, мы должны включить это поле в секцию ИТОГИ ПО на соответствующем уровне иерархии, то есть после НомерСклада. У нас есть два основных варианта:
Вариант 1 (Рекомендуемый, если группировка по представлению приемлема): Заменяем Номенклатура на НоменклатураПредставление.
Этот вариант подходит, если нам достаточно группировать и сортировать номенклатуру только по ее представлению. То есть, если две разные номенклатуры имеют одинаковое представление (что маловероятно, но возможно), они будут объединены в одну группу по представлению.
// Оригинально было:
// ПО МаршрутныйЛист, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, Номенклатура, РасходнаяНакладная
// Изменяем на:
ПО МаршрутныйЛист, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, НоменклатураПредставление, РасходнаяНакладная
После этой корректировки, итерация ВыборкаНоменклатура = ВыборкаНомерСклада.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); будет происходить по сгруппированным и отсортированным значениям НоменклатураПредставление, обеспечивая алфавитный порядок в печатной форме.
Вариант 2 (Если группировка по ссылке Номенклатура все еще необходима, но сортировка по представлению): Включаем НоменклатураПредставление перед Номенклатура.
Этот вариант более гибок. Он позволяет сначала выполнить сортировку по представлению номенклатуры, а затем, внутри этой сортировки, сохранить группировку по самой ссылке на номенклатуру. Это может быть полезно, если вы хотите иметь уникальные группы по ссылке на номенклатуру, но при этом гарантировать, что эти группы будут выстроены по их строковому представлению.
// Оригинально было:
// ПО МаршрутныйЛист, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, Номенклатура, РасходнаяНакладная
// Изменяем на:
ПО МаршрутныйЛист, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, НоменклатураПредставление, Номенклатура, РасходнаяНакладная
В этом случае, система сначала сгруппирует по НоменклатураПредставление, обеспечивая правильный порядок, а затем внутри каждой такой группы (если представления совпали) будет дополнительно группировать по Номенклатура. Это обеспечивает нужный порядок вывода, сохраняя при этом возможность различать номенклатуру по ссылке, даже если их представления совпадают.
Важно помнить, что порядок полей в секции ИТОГИ ПО определяет иерархию группировки и обхода. Чем раньше поле появляется в этой секции, тем выше его приоритет в иерархии. Мы добавляем НоменклатураПредставление на том уровне, где хотим применить сортировку, то есть после НомерСклада и перед РасходнаяНакладная.
УПОРЯДОЧИТЬ ПО (для полноты и детальной сортировки)Хотя основное влияние на порядок группировок оказывает секция ИТОГИ ПО, секция УПОРЯДОЧИТЬ ПО все еще важна для определения порядка детальных записей внутри самой нижней группировки, а также для обеспечения консистентности. Рекомендуем привести ее в соответствие с новой иерархией группировки.
// Оригинально было:
// УПОРЯДОЧИТЬ ПО Номенклатура, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, ТорговаяМарка, МаршрутныйЛист, РасходнаяНакладная
// Изменяем на:
УПОРЯДОЧИТЬ ПО МаршрутныйЛист, Контрагент, АдресДоставки, ТорговаяТочка, СкладР, НомерСклада, НоменклатураПредставление, Номенклатура, РасходнаяНакладная
В этом обновленном порядке, мы сохраняем логику группировки, добавляя НоменклатураПредставление и Номенклатура в правильном порядке. Это гарантирует, что даже если вы в будущем решите обходить детальные записи, они также будут упорядочены согласно нашим требованиям.
После внесения этих изменений в секцию ИТОГИ ПО и УПОРЯДОЧИТЬ ПО, критически важно выполнить модифицированный запрос в консоли запросов 1С. Откройте консоль запросов, вставьте измененный текст запроса, установите необходимые параметры (&ЭтоРеализация, &МассивОбъектов, &БрендНапитки) и выполните его. Убедитесь, что порядок группировок по НоменклатураПредставление стал корректным. Если в консоли порядок по-прежнему неверный, значит, проблема в логике запроса, и ее нужно решать на этом уровне, прежде чем переходить к коду формирования печатной формы.
В нашем запросе поле НоменклатураПредставление создается с помощью функции ПРЕДСТАВЛЕНИЕССЫЛКИ(РасходнаяНакладнаяСостав.Номенклатура). Убедитесь, что эта функция возвращает стабильное и ожидаемое строковое значение для сортировки. В большинстве случаев она работает корректно, используя наименование объекта. Однако, если для разных объектов генерируется одинаковое представление, это может привести к их объединению в одну группу при использовании Варианта 1.
Подводя итог, мы выяснили, что ключ к управлению порядком группировок при обходе результата запроса методом Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам) лежит в правильной настройке секции ИТОГИ ПО. Недостаточно просто добавить поле в УПОРЯДОЧИТЬ ПО; оно должно присутствовать в ИТОГИ ПО на том уровне, где мы хотим применить сортировку для группировки.