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