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