logo
small logo
  • Produkty
  • Zamów
  • Wsparcie techniczne
  • Articles
  • Customer panel Wsparcie techniczne
    • en
    • pt
    • es
    • de
    • pl
    • JP
    • ZH
  • Glówna strona
  • /
  • Articles
  • /
  • Jak posortować macierz według wskaźnika
  • Jak wybrać najwyższe wartości w macierzy?

    22 kwietnia 2021

    Artykuł jest aktualny do wersji 2022.1. FastReport .NET posiada świetne narzędzie do wyświetlania danych w postaci

    read more
  • Jak wykonać sortowanie od końca do końca podobnych macierzy na kilku stronach w FastReport .NET

    22 września 2021

    Załóżmy, że mamy zadanie: posortować macierz na pierwszej stronie w odpowiedniej kolejności. Możesz również potrzebować

    read more
  • Tworzenie złożonego raportu z kilkoma macierzami w FastReport .NET

    16 czerwca 2021

    Dzisiaj przyjrzymy się złożonemu raportowi z podejściem pasmowym, które zazwyczaj jest wykorzystywane w FastReport. Na

    read more
  • Jak filtrować zbudowaną matrycę

    23 czerwca 2021

    W FastReport obiekt Matrix pozwala nam na filtrowanie danych. Jest to jedna z najbardziej popularnych

    read more
  • Nowe właściwości i porównanie obiektów Matrix i AdvancedMatrix

    23 marca 2022

    Niedawno w FastReport.NET został zaimplementowany obiekt AdvancedMatrix. W tym artykule przyjrzymy się strukturze nowej

    read more

Jak posortować macierz według wskaźnika

30 czerwca 2021

Sortowanie danych jest bardzo ważnym narzędziem analitycznym, które pozwala szybko ocenić dynamikę wzrostu lub spadku, a także uszeregować dane tak, aby były przyjazne dla czytelnika. Macierz w obecnej wersji FastReport .NET umożliwia sortowanie tylko miar. Na przykład, budujesz raport, który wyświetla statystyki sprzedaży pracowników według roku. Macierz ma pogrupowane dane według roku i miesiąca. Potrzebujemy posortować je w ramach każdej grupy - rok. Standardowe narzędzia sortowania pozwolą Ci posortować nazwy pracowników, lata, miesiące, ale nie dane. Szczególnie jeśli chcemy posortować po konkretnej kolumnie.

Wybór kolejności sortowania dla wymiaru Nazwa

Aby posortować według konkretnej kolumny skonstruowanej macierzy (np. dla konkretnego pracownika), będziesz musiał użyć skryptu raportu. Dwa sposoby sortowania skonstruowanej macierzy to przesuwanie wierszy lub komórek.

Na pierwsze rzut oka wygląda, że przeniesienie wierszy na raz będzie dobrym rozwiązaniem, ponieważ sortowanie oznacza zmianę kolejności wyświetlania całego wiersza, a nie konkretnej komórki. W rzeczywistości, będzie to najbardziej poprawna decyzja, ale nie zawsze.

Przyjrzymy się przypadkowi, w którym przenoszenie wierszy nie będzie działać. Jeśli twoja macierz ma grupy z podgrupami w wymiarach, wtedy będziesz miał problemy z przeniesieniem pierwszego wiersza w grupie. Ten wiersz ma nazwę grupy w pierwszej komórce. Kolejne wiersze z grupy mają pustą wartość w pierwszej komórce. Ponieważ możesz zmienić kolejność wyświetlania pierwszego wiersza w grupie podczas sortowania, błąd pojawi się, gdy na jego miejsce przyjdzie wiersz z pustym nagłówkiem grupy.

Aby uniknąć takich błędów, będziesz musiał posortować komórki w odpowiedniej kolumnie. Oznacza to, że najpierw sortujesz wybraną kolumnę, a następnie, używając zestawu indeksów komórek, sortujesz wszystkie inne kolumny w macierzy według tej kolumny. Oczywiście, ta metoda jest znacznie bardziej czasochłonna.

Przyjrzyjmy się obu przypadkom na przykładzie. Pierwszym z nich jest sortowanie wierszy macierzy poprzez usuwanie i wstawianie wierszy do wynikowej macierzy.

Przyjrzyjmy się macierzy źródłowej, którą musimy posortować:

Macierz źródłowa

Ten zrzut ekranu pokazuje prostą macierz, która nie posiada grup z podgrupami. Przenoszenie wierszy jest idealne w tym przypadku. W rzeczywistości najpierw usuniemy wymagane wiersze, a następnie wstawimy je we właściwej kolejności. Zostanie to zrobione za pomocą skryptu raportu.

Załóżmy, że chcemy posortować macierz według kolumny dla roku 2011. Musimy określić liczbę porządkową tej kolumny i uzyskać dane dla wszystkich jej komórek, z wyjątkiem wynikowej Razem.

Dodajmy teraz zdarzenie ModifyResult dla obiektu macierzy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class ReportScript
 {
 // the key of the pair is the value in the cell of the matrix, the value of the pair is the y-coordinate of the cell
 // the dictionary will be sorted by cell value in this way
 private SortedDictionary<double, int> numbers = new SortedDictionary<double, int>();
 
 private void Matrix1_ModifyResult(object sender, EventArgs e)
 {
 int x = 1;
 int y = 2;
 
 // let's collect the values of the cells in the column for 2011, we will sort by it
 for ( ; y < Matrix1.ResultTable.RowCount - 1; y++)
 {
 object val = Matrix1.ResultTable.GetCellData(x, y).Value;
 double dval = 0.0;
 if (val != null)
 { 
 // here it is important to know the types of values or to check them
 // the cell format is Currency in this example, so we first convert it to a string
 // the default cell format is string
 Double.TryParse(val.ToString(), out dval);
 numbers.Add(dval, y);
 }
 // we add a pair with a value of 0.0 to the dictionary if there is an empty string in the cell
 // as a result, empty strings will be taken into account when sorting and will go first
 else
 {
 numbers.Add(dval, y);
 }
 }
 
 // copy the rows of the matrix into the backing array
 // then we will take the necessary rows from it and insert into the matrix
 object[] originalRows = Matrix1.ResultTable.Rows.ToArray();
 
 int i = 2; // the number of the row where we will start deleting rows in the matrix
 // now we delete the second row in the matrix as many times as there are rows to be sorted
 // we keep deleting the second row, because all rows will move up one position after deleting it
 for (int j = 0; j < numbers.Count; j++)
 {
 Matrix1.ResultTable.Rows.RemoveAt(i);
 }
 
 i = 2; 
 // now we just add all the rows in order according to the sorted list
 foreach (int v in numbers.Values)
 {
 int rowNum = v;
 Matrix1.ResultTable.Rows.Insert(i, originalRows[rowNum] as TableRow);
 i++;
 }
 }
 }

W rzeczywistości idea metody polega na odczytaniu wartości komórek i ich indeksów z żądanej kolumny i zapisaniu ich do posortowanego słownika. Możemy ułożyć wiersze w żądanej kolejności za pomocą indeksów komórek i odpowiednio wierszy. W tym celu najpierw kopiujemy wiersze do listy tymczasowej. Następnie usuwamy wszystkie wiersze i wstawiamy je zgodnie z indeksami w posortowanym słowniku komórek. Do wstawienia wykorzystujemy wiersze macierzy zapisane na liście tymczasowej.

W efekcie otrzymujemy macierz posortowaną według kolumny z 2011 roku:

Macierz posortowana według kolumny 2011

To jest najprostszy przykład jak sortować macierz poprzez tablicę jednowymiarową. Teraz wyobraźmy sobie, że mamy grupy dla pomiarów po lewej stronie i będziemy sortować w obrębie każdej grupy. Jak zauważono wcześniej, sortowanie wierszy nie jest opcją w tym przypadku. Przyjrzyjmy się jak posortować komórki.

Odwróćmy macierz z poprzedniego przykładu:

Macierz odwrócona

Tworzymy również obsługę zdarzenia ModifyResult dla macierzy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
public class ReportScript
 {
 
 public class DescendingComparer<T>: IComparer<T> where T : IComparable<T>
 {
 public int Compare(T x, T y)
 {
 return y.CompareTo(x); 
 }
 }
 
 // the key of the pair is the value in the cell of the matrix, the value of the pair is the y-coordinate of the cell
 // the dictionary will be sorted by cell value in this way
 private SortedList<int, double> numbers = new SortedList<int, double>();
 
 private void Matrix1_ModifyResult(object sender, EventArgs e)
 {
 int x = 3;
 int y = 2;
 
 Dictionary<int, double> cellsMonth = new Dictionary<int, double>();
 Dictionary<int, double> cellsFirst = new Dictionary<int, double>();
 Dictionary<int, double> cellsSecond = new Dictionary<int, double>();
 Dictionary<int, double> cellsThird = new Dictionary<int, double>();
 Dictionary<int, double> cellsFourth = new Dictionary<int, double>();
 Dictionary<int, double> cellsTotal = new Dictionary<int, double>();
 List<List<int>> allCells = new List<List<int>>();
 
 bool other = false;
 int z = 2;
 double val2 = 0.0;
 
 var val3 = 0.0;
 
 string message = "";
 
 List<string> years = new List<string>();
 
 for (int j=0; j<Matrix1.ResultTable.RowCount; j++)
 {
 var column = Matrix1.ResultTable.Columns[0] as TableColumn;
 try
 {
 years.Add(Matrix1.ResultTable.GetCellData(0,j).Value.ToString());
 }
 catch (Exception)
 {}
 } 
 
 //We do the cycle for each year 
 foreach (var year in years)
 {
 total = false;
 // We get the cell values for each year for a given column
 while (!total)
 {
 // We exclude Total being in the list of sorted values
 if (Matrix1.ResultTable.GetCellData(1,z).Text!="Total")
 {
 //Column of months
 var value = Matrix1.ResultTable.GetCellData(1,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsMonth.Add(z,val3);
 }
 else
 cellsMonth.Add(z, 0.0);
 
 //Column for first employee
 value = Matrix1.ResultTable.GetCellData(2,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsFirst.Add(z,val3);
 }
 else
 cellsFirst.Add(z, 0.0);
 
 //Column for the second employee
 value = Matrix1.ResultTable.GetCellData(3,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsSecond.Add(z,val3);
 }
 else
 cellsSecond.Add(z, 0.0);
 
 //Column for the third employee
 value = Matrix1.ResultTable.GetCellData(5,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsFourth.Add(z,val3);
 }
 else
 cellsFourth.Add(z, 0.0);
 
 //Sort column. It will serve as a sorting reference for other columns
 value = Matrix1.ResultTable.GetCellData(4,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsThird.Add(z,val3);
 }
 else
 cellsThird.Add(z, 0.0);
 
 //Column for the fifth employee
 value = Matrix1.ResultTable.GetCellData(6,z).Value;
 if (value!=null)
 {
 Double.TryParse(value.ToString(),out val3);
 cellsTotal.Add(z,val3);
 }
 else
 cellsTotal.Add(z, 0.0);
 }
 else
 {
 total = true;
 } 
 z++;
 } 
 
 //Let’s sort the cellsThird by the list, which is the column for the third employee
 var keys = cellsThird.OrderByDescending(i=>i.Value).Select(key => key.Key).ToList();
 
 //We set a new value for the cells in all strings in the required columns according to the order in the sorted dictionary for the third column
 int k = 0;
 foreach(var key in keys)
 {
 Matrix1.ResultTable.GetCellData(1, cellsThird.Keys.ElementAt(k)).Text = cellsMonth[key].ToString();
 Matrix1.ResultTable.GetCellData(2, cellsThird.Keys.ElementAt(k)).Text = cellsFirst[key].ToString();
 Matrix1.ResultTable.GetCellData(3, cellsThird.Keys.ElementAt(k)).Text = cellsSecond[key].ToString();
 Matrix1.ResultTable.GetCellData(4, cellsThird.Keys.ElementAt(k)).Text = cellsThird[key].ToString();
 Matrix1.ResultTable.GetCellData(5, cellsThird.Keys.ElementAt(k)).Text = cellsFourth[key].ToString();
 Matrix1.ResultTable.GetCellData(6, cellsThird.Keys.ElementAt(k)).Text = cellsTotal[key].ToString();
 k++;
 }
 cellsThird.Clear();
 }
 }
 }

 

Istnieją dwie zasadnicze różnice w stosunku do poprzedniej metody - sortujemy za pomocą zastępowania, a nie usuwania/insertowania, oraz sortujemy po każdej kolumnie osobno.

Z komentarzy w kodzie powinno być jasne, co i gdzie należy zrobić. Ale mimo to, zerknijmy szybko:

1) Po pierwsze, otrzymujemy wartości grup wymiarów, aby wiedzieć, ile zestawów sortujących potrzebujemy. Kolejność sortowania jest inna dla każdej grupy.

2) Następnie pobieramy dane dla wszystkich kolumn potrzebnych do sortowania. To znaczy dla wszystkich kolumn, z wyjątkiem pierwszej, która zawiera nazwy grup wymiarów.

3) Następnie wybieramy zestaw wartości wymaganych do sortowania i sortujemy go.

4) Można ułożyć komórki we wszystkich posortowanych kolumnach zgodnie z kolejnością tych indeksów, korzystając z wynikowego słownika, gdzie kluczem jest indeks komórki.

Wynikiem jest matryca posortowana dla Nancy Davolio:

Matryca posortowana według kolumn dla pracownika Nancy Davolio

W ten sposób można sortować macierz według dowolnej kolumny danych. Co więcej, można dokonać niestandardowego sortowania nie tylko w porządku malejącym lub rosnącym. Dodatkowo możesz wyłączyć z sortowania określone wiersze (sumaryczne lub obliczeniowe) ustawiając je w indywidualnej kolejności.

about product pobierz zamów
avatar
Dmitriy Fedyashov
Technical Writer
Fast Reports Team: Dmitriy Fedyashov - Technical Writer at Fast Reports
.NET FastReport Matrix

Add comment
logo
  • 800-985-8986 (English, US)
  • +4930568373928 (German)
  • +55 19 98147-8148 (Portuguese)
  • info@fast-report.com
  • 901 N Pitt Str #325 Alexandria VA 22314
  • Zamów
  • Pobierz
  • Dokumentacja
  • Opinie użytkowników
  • Jak odinstalować nasze produkty
  • Ticket system
  • FAQ
  • Tutorial Video
  • Forum
  • Articles
  • Our News
  • Prasa o nas
  • Partnerzy
  • Kontakty

© 1998-2022 by Fast Reports Inc.

  • Poufność