This repository has been archived by the owner on Oct 2, 2023. It is now read-only.
/
Form1.vb
282 lines (251 loc) · 10.4 KB
/
Form1.vb
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports DevExpress.XtraPivotGrid
Imports System.Collections
Namespace WindowsFormsApplication15
Partial Public Class Form1
Inherits Form
Private yearValues_Renamed As List(Of Object)
Private pivotData As PivotData
Private sortInfo As SortInfo
Public Sub New()
InitializeComponent()
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'NwindDataSet.CustomerReports' table. You can move, or remove it, as needed.
Me.CustomerReportsTableAdapter.Fill(Me.NwindDataSet.CustomerReports)
Me.pivotData = FillPivotData()
End Sub
Private ReadOnly Property YearValues() As List(Of Object)
Get
If yearValues_Renamed Is Nothing Then
yearValues_Renamed = New List(Of Object)()
yearValues_Renamed.AddRange(fieldOrderDate.GetUniqueValues())
yearValues_Renamed.Sort()
End If
Return yearValues_Renamed
End Get
End Property
Private Sub pivotGridControl1_CustomCellValue(ByVal sender As Object, ByVal e As PivotCellValueEventArgs) Handles pivotGridControl1.CustomCellValue
If e.DataField Is fieldProductAmount1 AndAlso e.Value IsNot Nothing Then
Dim rowValues As New List(Of Object)()
For Each field As PivotGridField In e.GetRowFields()
rowValues.Add(UpdateValue(field, e.RowIndex, e))
Next field
Dim columnValues As New List(Of Object)()
For Each field As PivotGridField In e.GetColumnFields()
columnValues.Add(UpdateValue(field, e.ColumnIndex, e))
Next field
Dim previousValue As Decimal = Convert.ToDecimal(e.GetCellValue(columnValues.ToArray(), rowValues.ToArray(), fieldProductAmount))
Dim value As Decimal = Convert.ToDecimal(e.GetCellValue(fieldProductAmount))
If previousValue = 0D OrElse e.Value Is Nothing Then
e.Value = Nothing
Else
e.Value = (CDec(e.Value) / previousValue - 1)
End If
End If
End Sub
Private Sub pivotGridControl1_CustomFieldSort(ByVal sender As Object, ByVal e As PivotGridCustomFieldSortEventArgs) Handles pivotGridControl1.CustomFieldSort
If Me.pivotData Is Nothing OrElse sortInfo Is Nothing Then
e.Handled = False
Return
End If
Dim sortByColumnIndex As Integer = GetSortByColumnIndex(e)
Dim value1RowIndex As Integer = GetValueIndex(False, e.Value1, e.Field, Nothing)
Dim value2RowIndex As Integer = GetValueIndex(False, e.Value2, e.Field, Nothing)
If value1RowIndex < 0 OrElse value2RowIndex < 0 OrElse sortByColumnIndex < 0 Then
Return
End If
Dim cellValue1 As Object = pivotData.GetCellValue(sortByColumnIndex, value1RowIndex)
Dim cellValue2 As Object = pivotData.GetCellValue(sortByColumnIndex, value2RowIndex)
e.Handled = True
If Object.Equals(cellValue1, cellValue2) Then
e.Result = Comparer.Default.Compare(e.Value1, e.Value2)
Else
e.Result = Comparer.Default.Compare(cellValue1, cellValue2)
End If
Return
End Sub
Private Function UpdateValue(ByVal field As PivotGridField, ByVal index As Integer, ByVal e As PivotCellValueEventArgs) As Object
Dim value As Object = e.GetFieldValue(field, index)
If field Is fieldOrderDate Then
Dim currentPosition As Integer = YearValues.IndexOf(value)
If currentPosition > 0 Then
value = YearValues(currentPosition - 1)
Else
value = "0000"
End If
End If
Return value
End Function
Private Function FillPivotData() As PivotData
Dim columnCount As Integer = pivotGridControl1.Cells.ColumnCount, rowCount As Integer = pivotGridControl1.Cells.RowCount
Dim columnFields As List(Of PivotGridField) = pivotGridControl1.GetFieldsByArea(PivotArea.ColumnArea), rowFields As List(Of PivotGridField) = pivotGridControl1.GetFieldsByArea(PivotArea.RowArea)
Dim data As New PivotData(columnCount, rowCount, columnFields.Count, rowFields.Count)
FillFieldValues(True, columnCount, columnFields, data)
FillFieldValues(False, rowCount, rowFields, data)
For i As Integer = 0 To columnCount - 1
For j As Integer = 0 To rowCount - 1
Dim info As PivotCellEventArgs = pivotGridControl1.Cells.GetCellInfo(i, j)
If info IsNot Nothing Then
data.SetCellValue(i, j, info.Value)
End If
Next j
Next i
Return data
End Function
Private Sub FillFieldValues(ByVal isColumn As Boolean, ByVal count As Integer, ByVal fields As List(Of PivotGridField), ByVal data As PivotData)
For i As Integer = 0 To count - 1
Dim value As FieldValue = data.GetFieldValue(isColumn, i)
value.ValueType = pivotGridControl1.GetFieldValueType(isColumn, i)
value.DataField = pivotGridControl1.Cells.GetCellInfo(If(isColumn, i, 0),If(isColumn, 0, i)).DataField
For j As Integer = 0 To fields.Count - 1
value.SetValue(j, pivotGridControl1.GetFieldValue(fields(j), i), fields(j))
Next j
Next i
End Sub
Private Function GetSortByColumnIndex(ByVal e As PivotGridCustomFieldSortEventArgs) As Integer
If sortInfo.Conditions.Count = 0 Then
For i As Integer = pivotData.ColumnCount - 1 To 0 Step -1
Dim value As FieldValue = pivotData.GetFieldValue(True, i)
If value.ValueType = PivotGridValueType.GrandTotal AndAlso value.DataField Is sortInfo.DataField Then
Return i
End If
Next i
Else
For i As Integer = 0 To pivotData.ColumnCount - 1
Dim value As FieldValue = pivotData.GetFieldValue(True, i)
If IsValueFit(value, sortInfo.Conditions, sortInfo.DataField) Then
Return i
End If
Next i
End If
Return -1
End Function
Private Function GetValueIndex(ByVal isColumn As Boolean, ByVal value As Object, ByVal field As PivotGridField, ByVal dataField As PivotGridField) As Integer
Dim count As Integer = If(isColumn, pivotData.ColumnCount, pivotData.RowCount)
For i As Integer = 0 To count - 1
Dim fieldValue As FieldValue = pivotData.GetFieldValue(isColumn, i)
If Object.Equals(value, fieldValue(field)) AndAlso (dataField Is Nothing OrElse fieldValue.DataField Is dataField) Then
Return i
End If
Next i
Return -1
End Function
Private Function IsValueFit(ByVal value As FieldValue, ByVal conds As List(Of PivotGridFieldSortCondition), ByVal field As PivotGridFieldBase) As Boolean
For i As Integer = 0 To conds.Count - 1
Dim cond As PivotGridFieldSortCondition = conds(i)
If Not(Object.Equals(value(CType(cond.Field, PivotGridField)), cond.Value) AndAlso field Is TryCast(value.DataField, PivotGridFieldBase)) Then
Return False
End If
Next i
Return True
End Function
Private Sub pivotGridControl1_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs) Handles pivotGridControl1.MouseClick
Dim hi As PivotGridHitInfo = pivotGridControl1.CalcHitInfo(e.Location)
If hi.HitTest = PivotGridHitTest.Value AndAlso hi.ValueInfo.IsColumn Then
ApplySortByValue(hi.ValueInfo)
End If
End Sub
Private Sub ApplySortByValue(ByVal valueInfo As PivotFieldValueEventArgs)
If valueInfo.DataField IsNot valueInfo.Field Then
Return
End If
Dim sortInfo As New SortInfo()
sortInfo.DataField = valueInfo.DataField
Dim fields() As PivotGridField = valueInfo.GetHigherLevelFields()
For i As Integer = 0 To fields.Length - 1
sortInfo.Conditions.Add(New PivotGridFieldSortCondition(fields(i), valueInfo.GetFieldValue(fields(i), valueInfo.MinIndex)))
Next i
Me.sortInfo = sortInfo
pivotGridControl1.RefreshData()
End Sub
Private Sub pivotGridControl1_PopupMenuShowing(ByVal sender As Object, ByVal e As DevExpress.XtraPivotGrid.PopupMenuShowingEventArgs)
If e.MenuType = PivotGridMenuType.FieldValue Then
e.Allow = False
End If
End Sub
End Class
Friend Class PivotData
Private columns(), rows() As FieldValue
Private cells(,) As Object
Public Sub New(ByVal columnCount As Integer, ByVal rowCount As Integer, ByVal columnLevelCount As Integer, ByVal rowLevelCount As Integer)
Me.cells = New Object(columnCount - 1, rowCount - 1){}
InitFieldValues(Me.columns, columnCount, columnLevelCount)
InitFieldValues(Me.rows, rowCount, rowLevelCount)
End Sub
Public ReadOnly Property ColumnCount() As Integer
Get
Return Me.columns.Length
End Get
End Property
Public ReadOnly Property RowCount() As Integer
Get
Return Me.rows.Length
End Get
End Property
Private Sub InitFieldValues(ByRef values() As FieldValue, ByVal length As Integer, ByVal levelCount As Integer)
values = New FieldValue(length - 1){}
For i As Integer = 0 To length - 1
values(i) = New FieldValue(levelCount)
Next i
End Sub
Public Function GetCellValue(ByVal columnIndex As Integer, ByVal rowIndex As Integer) As Object
Return Me.cells(columnIndex, rowIndex)
End Function
Public Sub SetCellValue(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As Object)
Me.cells(columnIndex, rowIndex) = value
End Sub
Public Function GetFieldValue(ByVal isColumn As Boolean, ByVal index As Integer) As FieldValue
Dim array() As FieldValue = If(isColumn, Me.columns, Me.rows)
Return array(index)
End Function
End Class
Friend Class FieldValue
Private values() As Object
Private fields() As PivotGridField
Private cache As Dictionary(Of PivotGridField, Object)
Public Sub New(ByVal levelCount As Integer)
Me.values = New Object(levelCount - 1){}
Me.fields = New PivotGridField(levelCount - 1){}
Me.cache = New Dictionary(Of PivotGridField, Object)(levelCount)
End Sub
Default Public ReadOnly Property Item(ByVal index As Integer) As Object
Get
Return values(index)
End Get
End Property
Default Public ReadOnly Property Item(ByVal field As PivotGridField) As Object
Get
Dim res As Object
If cache.TryGetValue(field, res) Then
Return res
End If
Dim index As Integer = Array.IndexOf(Of PivotGridField)(fields, field)
If index < 0 Then
Return Nothing
End If
res = values(index)
cache.Add(field, res)
Return res
End Get
End Property
Public Sub SetValue(ByVal index As Integer, ByVal value As Object, ByVal field As PivotGridField)
Me.values(index) = value
Me.fields(index) = field
End Sub
Public ValueType As PivotGridValueType
Public DataField As PivotGridField
End Class
Friend Class SortInfo
Public DataField As PivotGridField
Public Conditions As New List(Of PivotGridFieldSortCondition)()
End Class
End Namespace