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.