35eba0114efd4ccccff770ad6494bc7470fe2529
Guides/LayeredSubtotaling.md
| ... | ... | @@ -45,7 +45,12 @@ public class CustomAdHocConfig : FileSystemAdHocConfig |
| 45 | 45 | |
| 46 | 46 | public override string PerformCustomRendering(string initialHtml) |
| 47 | 47 | { |
| 48 | - return myLayeredSubtotaling.PerformCustomRendering(initialHtml); |
|
| 48 | + string outputHtml = myLayeredSubtotaling.PerformCustomRendering(initialHtml); |
|
| 49 | + |
|
| 50 | + //Uncomment the following lines if you need to manually clean things up after processing |
|
| 51 | + //LayeredSubtotaling.CleanUpDeltas(); |
|
| 52 | + //myLayeredSubtotaling.ResetStep(); |
|
| 53 | + return outputHtml; |
|
| 49 | 54 | } |
| 50 | 55 | } |
| 51 | 56 | |
| ... | ... | @@ -56,12 +61,20 @@ public class LayeredSubtotaling |
| 56 | 61 | { |
| 57 | 62 | public bool hasSubtotals = false; |
| 58 | 63 | static Dictionary<string, List<object>> deltas = new Dictionary<string, List<object>>(); |
| 59 | - bool firstPass = true; |
|
| 60 | - VisualGroupStyle targetVGStyle; |
|
| 64 | + VisualGroupStyle _targetVGStyle; |
|
| 65 | + ReportSetRenderingStep currentStep; |
|
| 66 | + |
|
| 67 | + enum ReportSetRenderingStep |
|
| 68 | + { |
|
| 69 | + ReportTableStep = 0, |
|
| 70 | + FullCountStep = 1, |
|
| 71 | + TotalsStep = 2 |
|
| 72 | + } |
|
| 61 | 73 | |
| 62 | 74 | public LayeredSubtotaling(VisualGroupStyle targetVGStyle) |
| 63 | 75 | { |
| 64 | 76 | _targetVGStyle = targetVGStyle; |
| 77 | + currentStep = ReportSetRenderingStep.ReportTableStep; |
|
| 65 | 78 | } |
| 66 | 79 | |
| 67 | 80 | /// <summary> |
| ... | ... | @@ -69,7 +82,11 @@ public class LayeredSubtotaling |
| 69 | 82 | /// </summary> |
| 70 | 83 | public void DoSubtotalingForVG(System.Data.DataSet ds, string reportPart) |
| 71 | 84 | { |
| 72 | - if (firstPass && !String.IsNullOrEmpty(reportPart)) |
|
| 85 | + //Nothing to do. This isn't a report data set |
|
| 86 | + if (String.IsNullOrEmpty(reportPart)) |
|
| 87 | + return; |
|
| 88 | + //We only want to do the main processing when we have the actual data |
|
| 89 | + if (currentStep == ReportSetRenderingStep.ReportTableStep) |
|
| 73 | 90 | { |
| 74 | 91 | string header, where; |
| 75 | 92 | List<object> dataColumns = new List<object>(); |
| ... | ... | @@ -139,11 +156,12 @@ public class LayeredSubtotaling |
| 139 | 156 | } |
| 140 | 157 | } |
| 141 | 158 | |
| 142 | - // If subtotaling is enabled, toggle first pass so the subtotal loop does wipe out custom totals. |
|
| 159 | + // If subtotaling Is enabled, there are three times during report execution when ProcessDataSet is called, otherwise it is called twice |
|
| 160 | + // We can cycle through the enum values to ensure every execution works properly |
|
| 143 | 161 | if (hasSubtotals) |
| 144 | - { |
|
| 145 | - firstPass = !firstPass; |
|
| 146 | - } |
|
| 162 | + currentStep = (ReportSetRenderingStep)(((int)(currentStep + 1)) % 3); |
|
| 163 | + else |
|
| 164 | + currentStep = (ReportSetRenderingStep)(((int)(currentStep + 1)) % 2); |
|
| 147 | 165 | } |
| 148 | 166 | |
| 149 | 167 | /// <summary> |
| ... | ... | @@ -233,6 +251,22 @@ public class LayeredSubtotaling |
| 233 | 251 | } |
| 234 | 252 | |
| 235 | 253 | /// <summary> |
| 254 | + /// If we need to, we can clear out the deltas manually to free up memory |
|
| 255 | + /// </summary> |
|
| 256 | + public static void CleanUpDeltas() |
|
| 257 | + { |
|
| 258 | + deltas.Clear(); |
|
| 259 | + } |
|
| 260 | + |
|
| 261 | + /// <summary> |
|
| 262 | + /// Just in case something misfires, we can reset the rendering step manually |
|
| 263 | + /// </summary> |
|
| 264 | + public void ResetStep() |
|
| 265 | + { |
|
| 266 | + currentStep = ReportSetRenderingStep.ReportTableStep; |
|
| 267 | + } |
|
| 268 | + |
|
| 269 | + /// <summary> |
|
| 236 | 270 | /// PrintFinalDeltas is called to in the case of level 1 delta changes. It makes sure all deltas get printed out, |
| 237 | 271 | /// not just the level 1. |
| 238 | 272 | /// </summary> |
| ... | ... | @@ -314,7 +348,12 @@ Public Class CustomAdHocConfig |
| 314 | 348 | End Sub |
| 315 | 349 | |
| 316 | 350 | Public Overrides Function PerformCustomRendering(initialHtml As String) As String |
| 317 | - Return myLayeredSubtotaling.PerformCustomRendering(initialHtml) |
|
| 351 | + Dim outputHtml = myLayeredSubtotaling.PerformCustomRendering(initialHtml) |
|
| 352 | + |
|
| 353 | + 'Uncomment the following lines if you need to manually clean things up after processing |
|
| 354 | + 'LayeredSubtotaling.CleanUpDeltas() |
|
| 355 | + 'myLayeredSubtotaling.ResetStep() |
|
| 356 | + Return outputHtml |
|
| 318 | 357 | End Function |
| 319 | 358 | End Class |
| 320 | 359 | |
| ... | ... | @@ -324,18 +363,30 @@ End Class |
| 324 | 363 | Public Class LayeredSubtotaling |
| 325 | 364 | Public hasSubtotals As Boolean = False |
| 326 | 365 | Shared deltas As New Dictionary(Of String, List(Of Object))() |
| 327 | - Dim firstPass As Boolean = True |
|
| 328 | 366 | Dim _targetVGStyle As VisualGroupStyle |
| 367 | + Dim currentStep As ReportSetRenderingStep |
|
| 368 | + |
|
| 369 | + Enum ReportSetRenderingStep |
|
| 370 | + ReportTableStep = 0 |
|
| 371 | + FullCountStep = 1 |
|
| 372 | + TotalsStep = 2 |
|
| 373 | + End Enum |
|
| 329 | 374 | |
| 330 | 375 | Sub New(targetVGStyle As VisualGroupStyle) |
| 331 | 376 | _targetVGStyle = targetVGStyle |
| 377 | + currentStep = ReportSetRenderingStep.ReportTableStep |
|
| 332 | 378 | End Sub |
| 333 | 379 | |
| 334 | 380 | ' <summary> |
| 335 | 381 | ' Overrides base version to support custom totaling of various deltas in the report. |
| 336 | 382 | ' </summary> |
| 337 | 383 | Public Sub DoSubtotalingForVG(ds As DataSet, reportPart As String) |
| 338 | - If firstPass AndAlso Not String.IsNullOrEmpty(reportPart) Then |
|
| 384 | + ' Nothing to do. This isn't a report data set |
|
| 385 | + If String.IsNullOrEmpty(reportPart) Then |
|
| 386 | + Return |
|
| 387 | + End If |
|
| 388 | + ' We only want to do the main processing when we have the actual data |
|
| 389 | + If currentStep = ReportSetRenderingStep.ReportTableStep Then |
|
| 339 | 390 | Dim header, where As String |
| 340 | 391 | Dim dataColumns As New List(Of Object)() |
| 341 | 392 | Dim dataHeaders As New Dictionary(Of String, String)() |
| ... | ... | @@ -359,14 +410,15 @@ Public Class LayeredSubtotaling |
| 359 | 410 | 'Otherwise, add the item, separated by a comma. |
| 360 | 411 | header += ", " & row(column).ToString() |
| 361 | 412 | where += " AND [" & column.ToString() & "] = '" & row(column) & "'" |
| 413 | + End If |
|
| 362 | 414 | |
| 363 | - 'If the header Is already in the list, ignore it And move on. |
|
| 364 | - If (Not dataHeaders.ContainsKey(header)) Then |
|
| 365 | - dataHeaders.Add(header, where) |
|
| 366 | - End If |
|
| 415 | + 'If the header Is already in the list, ignore it And move on. |
|
| 416 | + If (Not dataHeaders.ContainsKey(header)) Then |
|
| 417 | + dataHeaders.Add(header, where) |
|
| 367 | 418 | End If |
| 368 | - 'Otherwise this Is a data column And add it to that data structure. |
|
| 419 | + |
|
| 369 | 420 | ElseIf Not dataColumns.Contains(column) AndAlso row(column).GetType() IsNot GetType(DBNull) Then |
| 421 | + 'Otherwise this Is a data column And add it to that data structure. |
|
| 370 | 422 | dataColumns.Add(column) |
| 371 | 423 | End If |
| 372 | 424 | Next |
| ... | ... | @@ -389,9 +441,12 @@ Public Class LayeredSubtotaling |
| 389 | 441 | Next |
| 390 | 442 | End If |
| 391 | 443 | End If |
| 392 | - ' If subtotaling Is enabled, toggle first pass so the subtotal loop does wipe out custom totals. |
|
| 444 | + ' If subtotaling Is enabled, there are three times during report execution when ProcessDataSet is called, otherwise it is called twice |
|
| 445 | + ' We can cycle through the enum values to ensure every execution works properly |
|
| 393 | 446 | If hasSubtotals Then |
| 394 | - firstPass = Not firstPass |
|
| 447 | + currentStep = DirectCast((currentStep + 1) Mod 3, ReportSetRenderingStep) |
|
| 448 | + Else |
|
| 449 | + currentStep = DirectCast((currentStep + 1) Mod 2, ReportSetRenderingStep) |
|
| 395 | 450 | End If |
| 396 | 451 | End Sub |
| 397 | 452 | |
| ... | ... | @@ -470,6 +525,20 @@ Public Class LayeredSubtotaling |
| 470 | 525 | End Function |
| 471 | 526 | |
| 472 | 527 | ' <summary> |
| 528 | + ' If we need to, we can clear out the deltas manually to free up memory |
|
| 529 | + ' </summary> |
|
| 530 | + Public Shared Sub CleanUpDeltas() |
|
| 531 | + deltas.Clear() |
|
| 532 | + End Sub |
|
| 533 | + |
|
| 534 | + ' <summary> |
|
| 535 | + ' Just in case something misfires, we can reset the rendering step manually |
|
| 536 | + ' </summary> |
|
| 537 | + Public Sub ResetStep() |
|
| 538 | + currentStep = ReportSetRenderingStep.ReportTableStep |
|
| 539 | + End Sub |
|
| 540 | + |
|
| 541 | + ' <summary> |
|
| 473 | 542 | ' PrintFinalDeltas Is called to in the case of level 1 delta changes. It makes sure all deltas get printed out, |
| 474 | 543 | ' Not just the level 1. |
| 475 | 544 | ' </summary> |