グループ化されたForward Pathレポート

このトピックでは、スクリプトで定義されたカテゴリ(特定のプラットフォームへの展開への適合性など)またはアプリケーションが属するAppDNAアプリケーショングループによってアプリケーションをグループ化するために使用できる高度なForward Path機能の概要を説明します。アプリケーション値をグループ・レベルで集計できます (たとえば、各グループの小計を作成する場合)。また、レポート・レベルで合計を作成できます。つまり、たとえば、アプリケーショングループが部署を表す場合、アプリケーションを部署別にグループ化し、各部署の小計を表示するForward Pathレポートを作成できます。

概要

次の図は、Windows 7およびApp-VレポートのRAGステータスに基づいてアプリケーションをグループ化した、Forward Pathレポートのスニペットを示しています。グループごとに、修復の総コストと、グループ内のアプリケーションの数が表示されます。各グループを展開して、内部のアプリケーションを表示できます。上部の集計行には、レポート全体の合計が表示されます。

Forward Pathレポート・イメージ

次の例で、このレポートを生成した Forward Path シナリオを構築します。例をできるだけシンプルにするために、アプリケーションごとにハードコードされた修復コストを使用します。実際の環境では、アプリケーションの複雑さと必要な修復に基づいて計算できます。このようにコストを計算する例については、「Forward PathシナリオでのEffort Calculator変数の使用」を参照してください。

シナリオ関数

グループ化されたForward Pathレポートのシナリオは、通常、次の標準Forward Path機能を実装します。

  • Initialize() -スクリプトの開始時にこの関数が1回自動的に呼び出されます。通常、この関数は変数を初期化します。
  • ForwardPath() — これは、すべてのForward Pathのシナリオで実装する必要がある標準関数です。AppDNAは、レポートの実行時に選択されたアプリケーションごとに、この関数を1回呼び出します。グループ化されたForward Pathレポートでは、この関数により、アプリケーションが配置されるカテゴリ(レポート・グループ)が作成されます。レポートグループは、コード内のロジックによって作成することも、アプリケーションがすでに属しているアプリケーション・グループに基づいて作成することもできます。
  • ProcessGroups() -ForwardPath() 関数によって生成されたレポートグループごとに、この関数を1回呼び出します。この関数は、グループ・レベルのレポート・カラムとそれに含まれる値を定義します。
  • GetGroupColumnSummary() - ProcessGroups() 関数で定義された列ごとに、この関数が1回呼び出されます。通常、この関数はレポートレベルの合計を定義します。
  • OnProcessingComplete() — これはオプションの関数で、残りの処理がすべて完了した後にAppDNAが1回呼び出します。この機能を使用すると、レポートが表示される前に最終処理を実行できます。

次の図は、レポートの実行時にAppDNAがどのように関数を呼び出すかを示しています。この図の後には、各高度な機能の仕様と、上記の「概要」セクションに示したレポートを作成する例が示されています。

高度な機能

注:このトピックの一部の例では、長い行を 2 行以上に分割するためにアンダースコア (_) 表記を使用しています。これは、サンプルコードスニペットが PDF に含まれているときに正しくレンダリングされるためです。この表記の詳細については、 MSDN ライブラリを参照してください。

Initialize()

シナリオで指定されている場合、AppDNAはスクリプトの開始時にInitialize() 関数を1回自動的に呼び出します。Initialize() 関数には、次のシグネチャが必要です。

Public Overrides Sub Initialize()
   ' Enter your code here.
End Sub

この例では、Initialize() 関数を使用して、アプリケーション値を格納するために使用する変数を初期化し、グループレベルで集約できるようにします。しかし、まず、シナリオ全体で使用する変数を宣言する必要があります。これらの変数は複数の関数で使用するため、次のようにスクリプトの冒頭(Initialize () 関数の前)に定義します。

' Declare a Dictionary variable to store the remediation
' costs for each application in the group.
Private Dim costs As Dictionary(Of String, List(Of Integer)) _
   = New Dictionary(Of String, List(Of Integer))

' Declare string variables that store the names of the
' report groups.
Private Dim win7group As String = "Windows 7"
Private Dim appvgroup As String = "App-V"
Private Dim othergroup As String = "Retire"

この例では、コストと呼ばれる辞書変数を宣言しています。この標準.NET クラスのドキュメントについては、MSDN ライブラリを参照してください。辞書変数は、キーと値のコレクションを格納することができます。この例では、キーは文字列(レポートグループ名を格納するために使用する)で、値は整数のリストです(レポートグループ内のすべてのアプリケーションの修復コストを格納するために使用します)。List クラスのドキュメントについては、MSDN ライブラリを参照してください。

辞書だけでなく、我々は我々が作成する3つのレポートグループの名前を格納するために3つの文字列変数を宣言しました。

これで、Initialize() 関数を実装する準備が整いました。ここにあります:

Public Overrides Sub Initialize()
   costs.Add(win7group, New List(Of Integer))
   costs.Add(appvgroup, New List(Of Integer))
   costs.Add(othergroup, New List(Of Integer))
End Sub

この例では、3 つのレポートグループのそれぞれについて、コストディクショナリ変数に項目を追加するだけです。私たちは、レポートグループの名前を格納するために以前に宣言した3つの文字列変数を使用して項目キーを指定しました。

ForwardPath()

ForwardPath() 関数は、すべてのForward Pathのシナリオで実装する必要がある標準関数です。ForwardPath() 関数には、次のシグネチャが必要です。

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output
      ' Enter your code here.
End Function

この例では、アプリケーションを3つのレポートグループに分けます。Windows 7 RAGステータスが緑色のアプリケーションを「Windows 7」レポートグループに追加し、App-V RAGステータスが緑色のアプリケーションを「App-V」レポートグループに追加し、残りのアプリケーションを追加します。を「除・売却」レポートグループに追加します。アプリケーションごとに、ランダムなハードコードされた番号をディクショナリに追加して、アプリケーションの修復にかかるコストを表します。

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output

   Dim result As New Output()

   ' Is the application green for Windows 7?
   If (currentApplication.Modules.Windows7.RAG = RAG.Green) _
     Then
      result.Outcome = "Windows 7 OK"
      result.RAG = RAG.Green
      result.Cost = 33

      ' Add the application to the "Windows 7" group.
      result.ReportGroups.Add(win7group)

      ' Add the remediation cost to the dictionary variable.
      costs.Item(win7group).Add(33)
   Else

      ' Is the application green for App-V?
      If (currentApplication.Modules.AppV.RAG = RAG.Green) Then
         result.Outcome = "App-V OK"
         result.RAG = RAG.Green
         result.Cost = 170

         ' Add the application to the "App-V" group.
         result.ReportGroups.Add(appvgroup)

         ' Add the remediation cost to the dictionary variable.
         costs.Item(appvgroup).Add(170)
      Else

         ' The application is not green for Windows 7 or App-V.
         result.Outcome = "Not suitable for migration."
         result.RAG = RAG.Red
         result.Cost = 713

         ' Add the application to the "Retire" group.
         result.ReportGroups.Add(othergroup)

         ' Add the replacement cost to the dictionary variable.
         costs.Item(othergroup).Add(713)
      End If
   End If

   result.Display.SourcePath.Visible = false

   ForwardPath = result

End Function

我々は使用していることに注意してください… その後… Windows 7およびApp-VレポートのRAGステータスに基づいて、アプリケーションを3つのレポートグループに分けるためのステートメントです。レポートグループは、アプリケーションが属するアプリケーショングループに基づいて作成することができます。このトピックの後の例で、その方法を説明します。

注:同じアプリケーションを複数のグループに追加することは可能です。これを行うと、レポートを実行すると、アプリケーションが追加された各グループの下にアプリケーションが表示され、その値が各グループの合計に集計されます。これにより、アプリケーションの値がレポートの合計に複数回加算される可能性があります。報告書によっては、誤解を招く恐れがあります。意図しない限り、アプリケーションが複数のグループに追加されないようにするのは、スクリプトの作成者です。

ProcessGroups()

シナリオで指定されている場合、ForwardPath() 関数によって生成された各レポートグループに対してProcessGroups() 関数が呼び出されます。通常、ProcessGroups() 関数を使用して、Forward Pathレポートのグループ・レベルで表示される列を定義します。

ProcessGroups() 関数には、次のシグネチャが必要です。

Public Overrides Sub ProcessGroup(group As _
   ForwardPathReportGroup)
      ' Enter your code here.
End Sub

ForwardPathReportGroup オブジェクトがこの関数に渡されることに注意してください。これは、現在のレポートグループを表します。このプロパティには、グループの名前を格納する Name と、文字列のディクショナリである CustomColumns という 2 つのプロパティがあります。文字列 CustomColumns プロパティを使用して、グループレベルで表示される列の名前と列に含まれる列を指定します。

次に例を示します。

Public Overrides Sub ProcessGroup(group As _
   ForwardPathReportGroup)

   ' 1. Define a report group column to show the total
   ' cost for the applications in the group and format it
   ' as currency.
   group.Columns.Item("Cost").Value = _
      costs.Item(group.Name).Sum()
   group.Columns.Item("Cost").Format = "{0:C}"
   group.Columns.Item("Cost").Culture = "en-US"

   ' 2. Define a report group column to show the number of
   ' applications in the group.
   group.Columns.Item("Count").Value = _
      costs.Item(group.Name).Count

   ' 3. Define a report group column that has a link to
   ' further information.
   group.Columns.Item("Link").Value = _
   "<a target=""_blank"" href=""http://www.google.com"">More information</a>"

End Sub

3つの列を定義していることに注意してください。

  1. これにより、[Cost] 列が定義されます。この列には、各グループのアプリケーションの修復コストの合計が表示されます。総コストを取得するには、我々は、コスト辞書変数内のグループのために格納されているすべてのコスト値を集約するList.Sum() メソッドを使用しています。List クラスには、グループに格納されている平均、最小値、または最大値(たとえば)を取得するために使用できる他の集計関数があります。List クラスのドキュメントについては、MSDN ライブラリを参照してください。

    列の Format プロパティを {0: C}(値が通貨であることを指定)に設定していることに注意してください。また、Culture プロパティを en-US の値に設定して、通貨記号が米ドル記号であることを指定します。出力のフォーマットについては、Forward Pathレポートのソートと書式設定を参照してください。

  2. これにより、[Count] 列が定義され、各グループ内のアプリケーション数が表示されます。今回は、List.Count() メソッドを使用して、コストディクショナリ変数にグループのために格納されている(アプリケーションを表す)項目の数を取得します。

  3. これは、ハードコードされたハイパーリンクを定義する HTML コードを含む [リンク] 列を定義します。これは、列に HTML コードを含めることができることを示す過度に単純化された例です。

注:グループ名を示す列が自動的に生成されます。これは「グループ」列と呼ばれます。

GetGroupColumnSummary()

シナリオで指定されている場合、AppDNAは、ProcessGroups() 関数で定義された各列に対してGetGroupColumnSummary() 関数と、自動生成された「グループ」列(グループ名を格納する)に対して自動的にGetGroupColumnSummary() 関数が呼び出されます。GetGroupColumnSummary() 関数には、次のシグネチャが必要です。

Public Overrides Function GetGroupColumnSummary(groupColumnName _
   As String) As String
      ' Enter your code here.
End Function

列の名前が文字列として関数に渡され、関数が文字列を返すことに注意してください。文字列は、レポート集計行の対応する列に挿入されるテキストです。

レポートレベルの値を定義するには、GetGroupColumnSummary() 関数を使用します。たとえば、次のようになります。

Public Overrides Function GetGroupColumnSummary(groupColumnName _
   As String) As String

   If groupColumnName = "Group" Then

      ' Put the text "Total" in the automatically-generated
      ' "Group" column.
      GetGroupColumnSummary = "<b>Total</b>"

   Else If groupColumnName = "Cost" Then

      ' Declare a variable to store the total cost.
      Dim sum As Decimal = 0

      ' Iterate through the costs variable to get the total cost.
      For Each key As String In costs.Keys
         sum += costs.Item(key).Sum()
      Next

      ' Format the total as currency.
      GetGroupColumnSummary = _
         String.Format(New _
            System.Globalization.CultureInfo("en-US"), _
            "{0:C}", sum)

   Else If groupColumnName = "Count" Then

      ' Declare a variable to store the overall count.
      Dim count As Integer = 0

      ' Iterate through the costs variable to get the total
      ' count.
      For Each key As String In costs.Keys
         count += costs.Item(key).count()
      Next

      GetGroupColumnSummary = String.Format(count)

   Else

      ' Leave the "Link" column blank.
      GetGroupColumnSummary = ""

   End If

End Function

AppDNAは、ProcessGroups() 関数で定義したグループ列と、自動生成された「Group」列ごとに、この関数を1回呼び出します。したがって、我々は、If… その後… Else ステートメントを使用して、どのカラムが処理されているかをテストします。各列に対して何をしているかを見てみましょう。

  1. これは、自動生成された [グループ] 列です。 この列では、単に「Total」というテキストを生成します。 テキストが <b></b> タグで囲まれていることに注意してください。 これらは、テキストを太字で表示するように指定する標準の HTML タグです。 どの列でも任意の HTML コードを使用できます。

  2. これは [コスト] 列です。レポートの合計を取得するには、作業変数を宣言します。次に、グローバルコストディクショナリ変数のすべての項目を反復処理し、それらの合計値を作業変数に追加し、それを返します。

    戻り値は文字列です。私たちは、通貨としてコスト値をフォーマットするString.Format()メソッドを使用しており、我々は、米ドルの通貨記号を指定するためにCultureInfoクラスを使用しました。文字列のフォーマットについては、MSDN ライブラリを参照してください。

  3. カウント列については、我々は、レポートの合計値を生成するために、同様の技術を使用しました。

  4. 「リンク」列は空白のままです。

これにより、このトピックの冒頭に示した Forward Path レポートの生成に使用されたシナリオのコードの最後に表示されます。このトピックの後半では、アプリケーションがすでに属しているAppDNAアプリケーショングループに基づいてレポートグループを作成する方法を説明します。

OnProcessingComplete()

シナリオで指定されている場合、残りの処理がすべて完了すると、AppDNAはOnProcessingComplete() を自動的に1回呼び出します。この機能を使用すると、レポートが表示される前に最終処理を実行できます。

OnProcessingComplete() 関数には、次のシグネチャが必要です。

Public Overrides Sub OnProcessingComplete()
   ' Enter your code here.
End Sub

AppDNAアプリケーショングループによるグループ化

このセクションでは、すでに属しているアプリケーショングループに従ってアプリケーションをグループ化するシナリオを変更します。いずれかのアプリケーションがグループのメンバーでない場合は、[グループ解除] カテゴリに表示されます。

このシナリオでは、Application.Groups プロパティを使用して、アプリケーションがどのグループに属しているかを調べることができます。アプリケーションは複数のグループに属することができます。上記のように、すべてのグループをレポートに追加すると、アプリケーションが属する各グループの下にアプリケーションが表示されます。したがって、スクリプトの作成方法によっては、アプリケーションの修復コストをレポートの合計に複数回追加できる可能性があります。

これらの関数には、その動作を説明する詳細なコメントが含まれています。

Public Function ForwardPath(ByVal currentApplication _
   As Application) As Output

   Dim result As New Output()

   If (currentApplication.Modules.Windows7.RAG = RAG.Green) Then
      result.Outcome = "Windows 7 OK"
      result.RAG = RAG.Green
   Else
      ' If the RAG for Windows 7 is not green,
      ' check if it's green for App-V
      If (currentApplication.Modules.AppV.RAG = RAG.Green) Then
         result.Outcome = "App-V OK"
         result.RAG = RAG.Green
      Else
         result.Outcome = "Not suitable for migration."
         result.RAG = RAG.Red
      End If
    End If

   ' We're temporarily using a hard-coded cost.
   result.Cost = 713

   ' Iterate through the groups to which the application
   ' belongs.
   For Each group As String In currentApplication.Groups

      ' Add the application to the corresponding report group.
      result.ReportGroups.Add(group)

      ' Check whether the group has already been added to our
      ' global dictionary variable.
      If costs.ContainsKey(group) Then

         ' Add the application's cost to the global variable.
         costs.Item(group).Add(713)
      Else

         ' Add the group to the global variable and then
         ' add the application's cost.
         costs.Add(group, New List(Of Integer))
         costs.Item(group).Add(713)

      End If
   Next

   ForwardPath = result

End Function

Public Overrides Sub ProcessGroup(group As ForwardPathReportGroup)

   If costs.ContainsKey(group.Name) Then
      group.Columns.Item("Count").Value = _
         costs.Item(group.Name).Count
      group.Columns.Item("Cost").Value = _
         costs.Item(group.Name).Sum()
      group.Columns.Item("Cost").Format = "{0,-10:C}"
      group.Columns.Item("Cost").Culture = "en-US"
      group.Columns.Item("Link").Value = _
      "<a href=""http://www.google.com"">More information</a>"
   End If

End Sub

グループの表示を非表示にする

場合によっては、グループ化せずにグループ化されたレポートを表示することもできます。これを行うには、転送パスレポート設定.表示グループプロパティを使用します。シナリオにグループ処理コードを含めると、このプロパティは自動的に true に設定されます。ただし、シナリオで明示的に false に設定して、レポート内のグループの表示を非表示にすることができます。

設定オブジェクト (ForwardPathReportSettings 型の) は、シナリオ全体で使用できます。通常は、次のように Initialize() 関数でプロパティを設定します。

Settings.DisplayGroups = false

グループを再び表示するには、この行をコメントアウトします。