Методы для группировки данных по полю,полям в Таблице Значений на примере универсального метода списания по партиям, а также отбора строк в ТЗ по произвольному условию. Для 8.x и 7.7

01.10.15

Разработка - Универсальные функции

Я очень часто использую группировку данных по полю и  полям, как в восьмерке, так и в семерке. Это аналог запроса Итоги, но там строится дерево, а в большинстве случаев нужны "плоские данные". Да и делать запрос в большинстве случаев более накладный процесс, чем работа с ТЗ.
  Все достоинства такого подхода приведены на примере метода универсального списания по париям, а так же отбора строк в ТЗ по произвольному условию.
Для 7.7 еще отчеты сравнения двух ТЗ. Работая с различными базами для упрощения сравнения номенклатуры, или как аналог джойнов(join), сделал сравнение двух таблиц значений по нескольким полям. Пока группировки полей должны быть уникальны.
Часто приходится искать дубли, для универсального поиска есть ДублиВТзПоПолю и пример в Тест.ert.

Скачать файлы

Наименование Файл Версия Размер
ErtОбщегоНазначения.zip
.zip 65,86Kb
4
.zip 65,86Kb 4 Скачать
///================ Группировка Данных ===============================================
Функция ПолучитьМассивСтрок(Тз,нач,кон)
    Массив= новый Массив(Кон-Нач+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");

//Рез=НайтиПоУсловию(тз,"Модуль.ФункцияСравнения(Стр,Список)",МассивСтруктур,ЭтотОбъект);

//То есть в модуле обработки должна быть функция
//  Функция ФункцияСравнения(стр,МассивСтруктур) Экспорт

Функция НайтиПоУсловию(Тз,Условие,Список="",Модуль="") Экспорт
Массив = новый массив;
 Для каждого Стр из Тз Цикл
   Если Вычислить(Условие) Тогда
     массив.Добавить(стр)
   КонецЕсли
 КонецЦикла;
возврат Тз.Скопировать(массив)
КонецФункции



Группировка данных

См. также

Библиотека процедур и функций для технологической платформы "1С: Предприятие 7.7"

Универсальные функции Платформа 1С v7.7 Россия Абонемент ($m)

В библиотеку собраны различные функции по работе с документами, журналами, типами данных, строками, датой и временем, таблицами значений, Excel, файлами, XML, JSON, Http-сервисами, SMTP серверами и т.п.

1 стартмани

22.12.2023    634    8    user706545_kseg1971    0    

4

1С 7.7 и новый 1С:Контрагент

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Россия Бесплатно (free)

Получение реквизитов контрагентов из 1С:Контрагент для старых конфигураций под 1с 7.7.

25.04.2022    1802    zhenyat    7    

6

Печать таблицы значений в 1С 7.7 при отладке

Универсальные функции Платформа 1С v7.7 Россия Бесплатно (free)

Функция выводит таблицу значений в табличный документ. (v7.7) Особенно полезно при отладке. Не нужно вносить изменения в код, вызываем функцию как вычисляемое выражение при останове. Если таблица обрабатывается в несколько этапов, можно вывести её после каждого и визуально проследить эволюцию.

30.06.2021    4371    Zoltan_Black    11    

2

Работа с журналом регистрации. Выходим за границы платформы

Журнал регистрации Бесплатно (free)

Работа с журналом регистрации нестандартными средствами. А также немного про использование платформы .NET в экосистеме 1С.

12.05.2020    18394    Infostart    32    

91

Установка принтера по умолчанию для 1С 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

Установка принтера по умолчанию в 1С 7.7. Обработка может быть полезна в том случае, когда нужно установить принтер по умолчанию, а доступа к рабочему столу нет (например, терминальный режим без рабочего стола или remoteApp)

1 стартмани

13.02.2019    13260    4    alsen    3    

3

Формирование строки json в 1С: 7.7

Универсальные функции Платформа 1С v7.7 Конфигурации 1cv7 1С:Комплексная 7.7 Абонемент ($m)

Предлагается набор функций 1с 7.7 для формирования строки json стандартными средствами.

1 стартмани

10.12.2018    10046    malovandrey    1    

17
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. CheBurator 3119 19.10.22 23:07 Сейчас в теме
Есть ощущение что для 77 с использованием ИТЗ все получится гораздо проще и быстрее
2. Serginio 938 20.10.22 12:19 Сейчас в теме
(1) Ну ИТЗ то не родной для семерки! А так да согласен.
Без 1С++ очень тяжело
3. CheBurator 3119 20.10.22 12:49 Сейчас в теме
(2) таки да, но сильно сомневаюсь, что у тех кто до сих пор сидит на клюшках - в конфиге нет формекса и 1С++ ;-)
4. Serginio 938 20.10.22 13:10 Сейчас в теме
(3) Это точно. Хотя лет 5 уже 1С не занимаюсь, а уж семеркой однозначно!
Оставьте свое сообщение