СКД. Сортировка

Программирование - Практика программирования

сортировка СКД

27
Показана реализация сортировки по двойному щелчку на заголовке колонки отчета и отображение направления сортировки в заголовках колонок.

Приведенный ниже программный код предназначен для выполнения в контексте тонкого клиента. Проверка работоспособности проведена на платформе: 8.3.11.2867.

 

1. Визуализация направления сортировки в заголовке колонки.

 

Ищем поля порядка на всю глубину вложенности группировок отчета.  Здесь  _Структура - структура настроек отчета.

&НаСервере
procedure ПолучитьНаправлениеСортировки(_Структура,_sps)
  _Коллекция=_Структура.Порядок.Элементы;
  if _Коллекция.Количество()>0 then
    ПолучитьНаправлениеЭлемента(_Коллекция,_sps);
    if _Структура.Структура.Количество()>0 then
      for each _эл in _Структура.Структура do
          ПолучитьНаправлениеСортировки(_эл,_sps);
      enddo;
    endif;
  endif;
endprocedure

Запоминаем направление сортировки для каждого найденного поля. Элементы автопорядка пропускаем.

&НаСервере 
procedure ПолучитьНаправлениеЭлемента(_Элементы,_sps)
  for each _эл in _Элементы do
    if ТипЗнч(_эл) <> Тип("АвтоЭлементПорядкаКомпоновкиДанных") then
      x=string(_эл.Поле);
      v=0;
      if _эл.ТипУпорядочивания=НаправлениеСортировкиКомпоновкиДанных.Убыв then
        v=1;
      endif;    
      _sps.Вставить(x,v);
    endif;  
  enddo;
endprocedure

И наконец, вызывающая  процедура. По заголовку поля ищем заголовок колонки отчета, и в зависимости от направления сортировки вставляем соответствующую пиктограмму в заголовок колонки. Нулевой индекс, в структуре настроек указывает на то, что в нашем отчете только одна область вывода данных. Если в отчет выводятся несколько наборов данных в разные области, то для каждой области должен быть указан соответствующий индекс.

&НаСервере
procedure ОтобразитьНаправленияСортировки()
  //Отображает направление в заголовках колонок
  Настройки=Отчет.КомпоновщикНастроек.ПолучитьНастройки();  
  sps=new Структура();
  ПолучитьНаправлениеСортировки(Настройки.Структура[0],sps);
  for each x in sps do
    fld=x.Ключ;
    srt=x.Значение;
    _Поле=Отчет.КомпоновщикНастроек.Настройки.ДоступныеПоляПорядка.НайтиПоле(new ПолеКомпоновкиДанных(fld));
    if not _Поле=undefined then
      cap=_Поле.Заголовок;
      Область=Результат.НайтиТекст(cap,,,true,true);
      if not Область=undefined then
        if srt=0 then
          Область.Картинка=БиблиотекаКартинок.СтрелкаВверх;
        else  
          Область.Картинка=БиблиотекаКартинок.СтрелкаВниз;
        endif;
        Область.РазмерКартинки=РазмерКартинки.РеальныйРазмер;
        Область.ПоложениеТекстаОтносительноКартинки=ПоложениеТекстаОтносительноКартинки.Сверху;
      endif;
    endif;
  enddo;
endprocedure

2. Сортировка по  заголовку колонки.

 

Единственным событием, к которому можно привязать сортировку является событие  "Выбор" - событие, возникающее при двойном щелчке на ячейку или рисованный объект в режиме "только просмотр".

&НаКлиенте
Процедура РезультатВыбор(Элемент, Область, СтандартнаяОбработка)
  //Двойной щелчок на активной области
  Текст=Область.Текст;
  if УстановитьПолеСортировки(Текст) then
    ОтобразитьНаправленияСортировки();
  endif;
КонецПроцедуры

По заголовку колонки получаем имя выбранного поля, и запускаем процедуру поиска в структуре настроек отчета.

&НаСервере
function УстановитьПолеСортировки(txt)
  //Ищет поле сортировки по заголовку колонки
  Настройки=Отчет.КомпоновщикНастроек.ПолучитьНастройки();
  ДоступныеПоля=Настройки.Порядок.ДоступныеПоляПорядка.Элементы;
  for each д in ДоступныеПоля do
    if д.Заголовок=txt then
      НайтиПолеВИерархии(д.Поле,Настройки.Структура[0]);
      ОбновитьОтчет(Настройки);
      return true;
    endif;
  enddo;
  return false;
endfunction

Сначала проверяем на совпадение нашего поля с полями группировок. Если совпадение найдено, удаляем у найденного поля элемент автопорядка, если он есть.  Если в полях группировок наше поле не найдено, то это означает, что это поле является ресурсом и для него будет создано новое поле порядка.

&НаСервере
procedure НайтиПолеВИерархии(fld,_Структура)
  //Ищет  в группировках поле, выбранное пользователем 
  ПолеГрупп=_Структура.ПоляГруппировки.Элементы;
  for each п in ПолеГрупп do
    if п.Поле=fld then
      _Коллекция=_Структура.Порядок.Элементы;
      ПроверкаПоляАвтоПорядка(_Коллекция);
       НайтиПолеПорядка(fld,_Коллекция);
      return;
    endif;
  enddo;
  //Поле не найдено, спускаемся ниже
  if _Структура.Структура.Количество()>0 then
    for each _эл in _Структура.Структура do
      НайтиПолеВИерархии(fld,_эл);
    enddo;
  else
    //Это ресурс
    _Коллекция=_Структура.Порядок.Элементы;
    ПроверкаПоляАвтоПорядка(_Коллекция);
    НайтиПолеПорядка(fld,_Коллекция)
  endif;
endprocedure

Удаление элементов автопорядка.

procedure ПроверкаПоляАвтоПорядка(_Коллекция)
  //Если элемент автопорядка - удаляем
  if _Коллекция.Количество()>0 then
    for each _эл in _Коллекция do
      if ТипЗнч(_эл) = Тип("АвтоЭлементПорядкаКомпоновкиДанных") then
        _Коллекция.Удалить(_эл);
      endif;
    enddo;
  endif;
endprocedure

После того, как мы определились, по какому полю будет выполнена сортировка, проверим наличие полей порядка у нашего поля. Тут возможны три варианта. Первый - поля порядка есть в структуре отчета. В этом случае меняем порядок сортировки на обратный. Второй вариант - выбрано другое поле сортировки. Например, в отчете присутствует группировка по полю "Товар", у данной группировки есть два ресурса "Количество" и "Сумма". В настройках отчета указано, что сортировка по группировке "Товар" должна выполняться по ресурсу "Количество". Если в сформированном отчете пользователь щелкнул на колонке "Количество" то у группировки "Товар" и данного ресурса сортировка изменится на обратную (первый вариант), если была выбрана колонка "Сумма", то предыдущая сортировка удаляется, и устанавливается сортировка по полю "Сумма" (второй вариант).  И наконец третий вариант, у выбранной колонки нет полей порядка, в этом случае создаем новую сортировку.

&НаСервере
procedure НайтиПолеПорядка(fld,_Коллекция)
  //Проверка наличия поля порядка для fld
  if _Коллекция.Количество()>0 then
    for each _эл in _Коллекция do
      _ПолеПорядка=_эл.Поле;
      if _ПолеПорядка=fld then
        ИзменитьПорядокСортировки(_эл);
        return;
      endif;
    enddo;
    //Выбрано другое поле, очищаем коллекцию существующей сортировки и добавляем новое поле
    _Коллекция.Очистить();
    НовоеПолеПорядка(fld,_Коллекция)
  else
    //Коллекция пустая (нет полей сортировки), добавляем новое поле
    НовоеПолеПорядка(fld,_Коллекция)
  endif;
endprocedure

Изменение направления сортировки.

&НаСервере
procedure ИзменитьПорядокСортировки(_Порядок)
  //Меняет порядок сортировки на обратный
  if _Порядок.ТипУпорядочивания=НаправлениеСортировкиКомпоновкиДанных.Возр then
    _Порядок.ТипУпорядочивания=НаправлениеСортировкиКомпоновкиДанных.Убыв;
  else
    _Порядок.ТипУпорядочивания=НаправлениеСортировкиКомпоновкиДанных.Возр;
  endif;
endprocedure

Добавление новой сортировки в коллекцию полей порядка.

&НаСервере
procedure НовоеПолеПорядка(fld,_Коллекция)
  //Вставляет новое поле сортировки в коллекцию злементов порядка
  НовыйПорядок=_Коллекция.Вставить(0,Тип("ЭлементПорядкаКомпоновкиДанных"));
  НовыйПорядок.Поле= fld;
  НовыйПорядок.Использование=Истина;
  НовыйПорядок.ТипУпорядочивания=НаправлениеСортировкиКомпоновкиДанных.Возр;  
endprocedure

Формируем отчет с новыми настройками сортировки.

&НаСервере
procedure ОбновитьОтчет(Настройки)
//Сформировать отчет с новыми настройками 
  Отчет.КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
  ЭтаФорма.СкомпоноватьРезультат(РежимКомпоновкиРезультата.Непосредственно);
endprocedure

 

Во вложении находится тестовый отчет с примерами сортировки трех типов отчетов: "Группировка", "Детальные записи" и "Таблица".

27

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

Наименование Файл Версия Размер
Сортировка
.erf 14,12Kb
03.12.18
4
.erf 14,12Kb 4 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. BigClock 04.12.18 16:09 Сейчас в теме
Зачем используются англоязычные ключевые слова вперемешку с переменными на русском?
borda4ev; Gang031; dabu-dabu; birkoffff123; zqzq; fr13; Craig; awk; frutty; jif; TreeDogNight; A_Max; +12 Ответить
2. slimper 190 04.12.18 16:38 Сейчас в теме
(1) Мне так удобнее
akimych; Gang031; acanta; nazirovramzil; +4 3 Ответить
4. Bassgood 821 05.12.18 14:42 Сейчас в теме
(2) А как же стандарты?
Реально глаза режет когда смотришь на текст, в котором перемешены два языка
birkoffff123; CSiER; awk; frutty; +4 Ответить
5. slimper 190 05.12.18 14:52 Сейчас в теме
(4) Это, наверно мое кривое восприятие. Мне трудно читать код, когда ключевые слова написаны кириллицей.
akimych; MSK_Step; user774630; +3 2 Ответить
6. awk 688 05.12.18 16:23 Сейчас в теме
(2) Если кто-то, будет в тестовом задании, такое делать, при трудоустройстве, то 100% пойдет мимо моей организации. Ну мне так удобней. Так же пойдет лесом человек неоправданно использующий "_" и однобуквенные переменные. Это если кто дошел из новичков до комментариев и решил, что код крутой.
dabu-dabu; birkoffff123; Junix; Serj1C; IgorS; +5 Ответить
7. slimper 190 05.12.18 16:53 Сейчас в теме
(6) К счастью или сожалению я не буду соискателем места в вашей компании. Представленный код не претендует на образец для подражания. Вам удобней отправлять лесом людей, не подходящих под ваши представления, a мне удобней
такое делать
the1; akimych; Gang031; Govorun39; MSK_Step; +5 1 Ответить
11. awk 688 05.12.18 18:13 Сейчас в теме
(7) У меня в компании люди код пишут для коллег и себя, а не для ЧСВ,
13. slimper 190 05.12.18 18:24 Сейчас в теме
(11)
а не для ЧСВ

Ошибочная оценка, не соответствующая реальности.
18. Поручик 4169 06.12.18 13:56 Сейчас в теме
(7) Удобно чесать ЧСВ и показывать "крутость". Сишные понты. Я бы тоже лесом отправил.
10. MSK_Step 18 05.12.18 18:00 Сейчас в теме
(6)в языках программирования мы также использовали "_" , только на 1с это как то считается плохим
12. awk 688 05.12.18 18:14 Сейчас в теме
(10) Префикс "_" в Си зарезервирован для служебных переменных.
3. DoctorRoza 05.12.18 13:39 Сейчас в теме
(1) Тут другое, если ты пишешь на православном ООП, то почему условный оператор написан не по канону!?
if (_ПолеПорядка=fld) then ....
:)
birkoffff123; frutty; +2 Ответить
8. Трактор 1169 05.12.18 17:31 Сейчас в теме
Ключевая строка оказалась в конце
Формируем отчет с новыми настройками сортировки.

А нужно ли его формировать? Любопытно, что быстрее будет работать. Формирование нового отчёта или перестановка строк в уже сформированном.
9. slimper 190 05.12.18 17:52 Сейчас в теме
(8) Если я правильно понял, вы предлагаете просто переставить строки в табличном документе "Результат". Этот вариант я не рассматривал.
14. zqzq 17 06.12.18 09:26 Сейчас в теме
Просто тогда нужно и всё остальное на английский переводить. И соблюдать стандарты по большим буквам и вообще названиям (без _).
&НаСервере
procedure НовоеПолеПорядка(fld,_Коллекция)
//...
НовыйПорядок=_Коллекция.Вставить(0,Тип("ЭлементПорядкаКомпоновкиДанных"));

превращается в
&AtServer
Procedure NewFieldOfOrder(fld, Collection)
//...
NewOrder = Collection.Insert(0, Type("DataCompositionOrderItem"));

... и получится неплохой индусский код...
neikist; rincewind; CSiER; awk; +4 Ответить
15. slimper 190 06.12.18 10:56 Сейчас в теме
(14) Попробую объяснить свой подход. Наверно в большинстве языков условный оператор это if, т.е. такое обозначение является мировым стандартом (может у китайцев по другому). В языке 1С объектная модель реализована на русском языке, поэтому названия объектов логично писать на этом языке, но для ключевых слов существует общий стандарт, который, для меня имеет приоритет над стандартом 1С. Если вы работаете в разных языковых средах, мне кажется проще, использовать ключевые слова из общего стандарта. Заглавные буквы - это должна делать сама среда разработки, как например в VS. Подчерки - здесь чтобы отличать переменные от системных объектов, при совпадении наименований.
16. buganov 49 06.12.18 12:50 Сейчас в теме
Работал как то с тру кодерами, которым нужно было написать обработку в 1С. Так у них вообще все было на английском, потому, что им так удобнее и привычнее. С такой точки зрения это оправдывает использование английского в 1С, но,

procedure ПроверкаПоляАвтоПорядка(_Коллекция)
  //Если элемент автопорядка - удаляем
  if _Коллекция.Количество()>0 then
    for each _эл in _Коллекция do


достойно премии всем известного сайта

В целом разработка интересна с точки зрения научного интереса, но, я думаю, многим проще и быстрее в настройках СКД задать свою сортировку.
19. slimper 190 06.12.18 16:08 Сейчас в теме
(16)
С такой точки зрения это оправдывает использование английского в 1С,

Нет, как справедливо отмечено в (14) это будет выглядеть довольно странно, почти также как писать русские слова латинскими буквами.

я думаю, многим проще и быстрее в настройках СКД задать свою сортировку.

Все еще проще. В СКД отчетах есть контекстное меню, где среди прочих присутствует команда "Упорядочить".
17. dabu-dabu 7 06.12.18 13:33 Сейчас в теме
Поиск ячейки по заголовку группировки - это здорово и просто, но совсем не универсально.
Оставьте свое сообщение