Erratum :
J’étais fatigué (retour de TechDays ??) quand j’ai écrit cet article car il y a une solution beaucoup plus simple (que je connaissais en plus). Je n’ai pas voulu écouter la petite voix dans ma tête qui me disait « abruti, abruti » quand j’ai cité la fonction Previous. Bref, la solution est :
=RunningValue(Fields!SubTotal.Value, Sum, Nothing)
Mais je vous invite à lire la solution proposée ci-dessous car elle est utile pour de aggrégats un peu custom (et puis pour dire que je n’ai pas gratté pour rien).
Article Original
Dans cet article nous allons voir comment faire une somme cumulée dans un rapport. Le principe est simple, j’ai des ventes dans le temps et pour chaque date, je veux le cumul depuis la première date.
Reporting Services n’offre pas cette fonctionnalité en natif mais nous allons mettre en place les élements pour le suporter. Sans vouloir gâcher la surprise, je peux déjà vous annoncer que l’on va passer par du code .NET ajouté au rapport.
Pour commencer, voyons ce que nous offre Reporting Services comme fonction en rapport avec notre besoin. Il y a la fonction Previous qui permet de récupérer des données dans la ligne précédente. Cependant, cela ne marche plus à partir de la 3eme ligne car la fonction ne remonte pas plus haut.
L’idée pour résoudre cette problématique est d’utiliser une variable qui va tenir le cumul depuis la première ligne. A chaque ligne, on ajoute la valeur en cours. Pour garder une variable, on doit passer par le code .NET.
Pour ce faire on passe par la fenêtre de propriétés du rapport, dans l’onglet Code.
Oubliez le confort de l’Intellisense, vous n’êtes pas dans Visual Studio, l’éditeur ressemble plutôt à Notepad. En espérant que Reporting Services 2008 apporte des améliorations dans ce sens (comme pour Integration Services). En plus, vous êtes limité uniquement à VB.NET comme langage.
Quant au code en lui-même il est assez simple. On garde un variable Shared (static) et on fournit une petite fonction pour mettre à jour et retourner le cumul. Ici j’ai choisi le type Decimal car je souhaite retourner une somme d’argent. Rien de plus simple :
Shared cumul As Decimal = 0.0
Public Shared Function GetCumulativeSum(ByVal currentValue As Decimal) As Decimal
cumul += currentValue
Return cumul
End Function
Reste à utiliser ce code dans le rapport. Pour cela, on utilise une Expression dans un élément de notre DataRegion :
=Code!GetCumulativeSum(Fields!SalesAmount.Value)
Un des problèmes est que l’on ne peut pas utiliser cette technique de cumul à différents endroits. En effet, on ne repart jamais à zéro. Plutôt que de tenter de réinitialiser le cumul dans la première ligne d’une DataRegion, on préfèrera l’utilisation d’un dictionnaire dans le Custom Code. Voici le code utilisant un dictionnaire :
Shared cumuls As System.Collections.Generic.Dictionary(Of String, Decimal) = _
New System.Collections.Generic.Dictionary(Of String, Decimal)
Public Shared Function GetCumulativeSum(ByVal currentValue As Decimal, ByVal sumKey As String) As Decimal
If Not cumuls.ContainsKey(sumKey) Then
cumuls.Add(sumKey, 0.0)
End If
cumuls.Item(sumKey) += currentValue
Return cumuls.Item(sumKey)
End Function
Dans le rapport, on utilisera l’expression suivante :
=Code!GetCumulativeSum(Fields!SalesAmount.Value, "salesInChart")
...
=Code!GetCumulativeSum(Fields!TaxAmount.Value, "taxInMatrix")
Note : pour faire du C#, il faudra coder la fonction dans une assembly et la référencer dans le rapport.