将子工作项值汇总到父示例报表

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

汇总支持显示工作项的计数或故事点、剩余工时或其他子项的自定义域的总和。 本文提供了有关如何为包含子工作项的 Epics、Features 或 User Stories 生成表格汇总报表的几个示例。 下图显示了为其父功能汇总的故事点示例。

功能汇总矩阵报表的屏幕截图。

有关汇总和显示汇总的选项的详细信息,请参阅 Azure Boards 中的显示汇总进度或总计。

注意

本文假设你阅读 了使用 OData 查询 的示例报表概述,并基本了解 Power BI。

先决条件

  • Access:至少是具有基本访问权限的项目的成员。
  • 权限: 默认情况下,项目成员有权查询 Analytics 和创建视图。
  • 有关服务和功能启用和常规数据跟踪活动的其他先决条件的详细信息,请参阅 访问 Analytics 的权限和先决条件。

示例查询

以下查询返回 WorkItems 实体集中的数据,以支持生成汇总矩阵报表。

注意

若要确定用于筛选或报表的可用属性,请参阅Azure Boards元数据参考。 可以使用 提供的 EntitySetNavigationPropertyBinding Path 值下EntityType的任何Property值筛选查询或返回属性。 每个对应 EntitySet 一个 EntityType。 有关每个值的数据类型的详细信息,请查看为相应 EntityType值提供的元数据。

汇总故事点到基于区域路径的子用户情景的功能

将以下 Power BI 查询直接复制并粘贴到 “获取数据>空白查询” 窗口中。 有关详细信息,请参阅 使用 OData 查询的示例报告概述。

let
    Source = OData.Feed("https://analytics.dev.azure.com/{organization}/{project}/_odata/v3.0-preview/WorkItems?"
            &"$filter=WorkItemType eq 'Feature'"
            &" and State ne 'Cut'"
            &" and startswith(Area/AreaPath,'{areapath}')"
            &" and Descendants/any()"    
        &"& $select=WorkItemId,Title,WorkItemType,State,AreaSK"
        &"& $expand=AssignedTo($select=UserName),Iteration($select=IterationPath),Area($select=AreaPath),"        
            &"Descendants("
                &"$apply=filter(WorkItemType eq 'User Story')"
                &"/aggregate($count as CountOfUserStories, StoryPoints with sum as TotalStoryPoints)"
            &")", 
        null, [Implementation="2.0",OmitValues = ODataOmitValues.Nulls,ODataVersion = 4])  
in
    Source

替换字符串和查询明细

将以下字符串替换为值。 不要在替换中包含括号 {} 。 例如,如果组织名称为“Fabrikam”,请将 替换为 {organization}Fabrikam,而不是 {Fabrikam}

  • {organization} - 组织名称
  • {project} - 对于跨项目查询,团队项目名称或完全省略“/{project}”
  • {areapath} - 区域路径。 示例格式: Project\Level1\Level2

查询明细

下表描述了查询的每个部分。

查询部件

描述

$filter=WorkItemType eq 'Feature'

返回功能。

and State ne 'Cut'

省略已关闭的 bug。

and startswith(Area/AreaPath,'{areapath}')

返回特定区域路径下的工作项,替换 Area/AreaPath eq '{areapath}' 特定区域路径处的返回项。 若要按团队名称进行筛选,请使用 filter 语句 Teams/any(x:x/TeamName eq '{teamname})'

and Descendants/any()

包括所有功能,甚至不包含用户情景的功能。 替换为“any(d:d/WorkItemType eq 'User Story')”以省略没有子用户情景的功能。

&$select=WorkItemId, Title, WorkItemType, State

选择要返回的字段。

&$expand=AssignedTo($select=UserName), Iteration($select=IterationPath), Area($select=AreaPath),

选择可展开的属性字段AssignedTo,, IterationArea

Descendants(

展开子 Descendants 句。

$apply=filter(WorkItemType eq 'User Story')

筛选后代以仅包含用户情景(省略任务和 bug)。

/aggregate($count as CountOfUserStories, StoryPoints with sum as TotalStoryPoints)

对于与筛选器子句匹配的所有后代,请对它们进行计数,并对属性求和 StoryPoints

)

关闭 Descendants()

汇总故事点到基于 Teams 的子用户情景的功能

以下查询演示如何按团队名称而不是区域路径生成汇总报告筛选。

将以下 Power BI 查询直接复制并粘贴到 “获取数据>空白查询” 窗口中。 有关详细信息,请参阅 使用 OData 查询的示例报告概述。

let
    Source = OData.Feed("https://analytics.dev.azure.com/{organization}/{project}/_odata/v3.0-preview/WorkItems?"
            &"$filter=WorkItemType eq 'Feature'"
            &" and State ne 'Cut'"
            &" and (Teams/any(x:x/TeamName eq '{teamname}) or Teams/any(x:x/TeamName eq '{teamname}) or Teams/any(x:x/TeamName eq '{teamname})"
            &" and Descendants/any()"    
        &"& $select=WorkItemId,Title,WorkItemType,State,AreaSK"
        &"& $expand=AssignedTo($select=UserName),Iteration($select=IterationPath),Area($select=AreaPath),"        
            &"Descendants("
                &"$apply=filter(WorkItemType eq 'User Story')"
                &"/aggregate($count as CountOfUserStories, StoryPoints with sum as TotalStoryPoints)"
            &")", 
        null, [Implementation="2.0",OmitValues = ODataOmitValues.Nulls,ODataVersion = 4])  
in
    Source

汇总故事点到史诗

可以使用以下查询将故事点汇总到 Epics。

将以下 Power BI 查询直接复制并粘贴到 “获取数据>空白查询” 窗口中。 有关详细信息,请参阅 使用 OData 查询的示例报告概述。

let
    Source = OData.Feed("https://analytics.dev.azure.com/{organization}/{project}/_odata/v3.0-preview/WorkItems?"
            &"$filter=WorkItemType eq 'Epic'"
            &" and State ne 'Cut'"
            &" and startswith(Area/AreaPath,'{areapath}')"
            &" and Descendants/any(d:d/WorkItemType eq 'User Story')"    
        &"& $select=WorkItemId,Title,WorkItemType,State,AreaSK"
        &"& $expand=AssignedTo($select=UserName),Iteration($select=IterationPath),Area($select=AreaPath),"        
            &"Descendants("
                &"$apply=filter(WorkItemType eq 'User Story')"
                &"/aggregate(StoryPoints with sum as TotalStoryPoints)"
            &")", 
        null, [Implementation="2.0",OmitValues = ODataOmitValues.Nulls,ODataVersion = 4])  
in
    Source

将剩余工时和已完成工时汇总到用户情景

以下查询演示如何汇总 分配给层次结构中用户情景的子任务剩余工时已完成工 时。 这些查询假定任务分配为指定 区域路径中用户情景的子级。

将以下 Power BI 查询直接复制并粘贴到 “获取数据>空白查询” 窗口中。 有关详细信息,请参阅 使用 OData 查询的示例报告概述。

let
    Source = OData.Feed("https://analytics.dev.azure.com/{organization}/{project}/_odata/v3.0-preview/WorkItems?"
            &"$filter=WorkItemType eq 'User Story'"
            &" and State ne 'Removed'"
            &" and startswith(Area/AreaPath,'{areapath}')"
            &" and Descendants/any()"    
        &"& $select=WorkItemId,Title,WorkItemType,State,AreaSK"
        &"& $expand=AssignedTo($select=UserName),Iteration($select=IterationPath),Area($select=AreaPath),"        
            &"Descendants("
                &"$apply=filter(WorkItemType eq 'Task')"
                &"/aggregate(RemainingWork with sum as TotalRemainingWork, CompletedWork with sum as TotalCompletedWork)"
            &")", 
        null, [Implementation="2.0",OmitValues = ODataOmitValues.Nulls,ODataVersion = 4])  
in
    Source

将 Bug 计数汇总到功能

以下查询演示如何汇总分配给功能的 Bug 计数。 这些查询假定 Bug 定义为指定 区域路径中特征的子级。

将以下 Power BI 查询直接复制并粘贴到 “获取数据>空白查询” 窗口中。 有关详细信息,请参阅 使用 OData 查询的示例报告概述。

let
    Source = OData.Feed("https://analytics.dev.azure.com/{organization}/{project}/_odata/v3.0-preview/WorkItems?"
            &"$filter=WorkItemType eq 'Feature'"
            &" and State ne 'Removed'"
            &" and startswith(Area/AreaPath,'{areapath}')"
            &" and Descendants/any()"    
        &"& $select=WorkItemId,Title,WorkItemType,State,AreaSK"
        &"& $expand=AssignedTo($select=UserName),Iteration($select=IterationPath),Area($select=AreaPath),"        
            &"Descendants("
                &"$apply=filter(WorkItemType eq 'Bug')"
                &"/aggregate($count as CountOfBugs)"
            &")", 
        null, [Implementation="2.0",OmitValues = ODataOmitValues.Nulls,ODataVersion = 4])  
in
    Source

(可选) 重命名查询

可以将默认查询标签 Query1 重命名为更有意义的标签。 只需在 “查询设置” 窗格中输入新名称。

Power BI 查询菜单选项的屏幕截图,重命名查询。

在 Power BI 中展开列

&$expand=AssignedTo($select=UserName), Iteration($select=IterationPath), Area($select=AreaPath) 句返回包含多个字段的记录。 在创建报表之前,需要展开记录以将其平展到特定字段。 在此实例中,需要展开以下记录:

  • AssignedTo
  • AreaPath
  • IterationPath

若要了解如何操作,请参阅 转换分析数据以生成 Power BI 报表

(可选)重命名字段

展开列后,可能需要重命名一个或多个字段。 例如,可以将列 AreaPath 重命名为 Area Path。 若要了解如何操作,请参阅 “重命名列字段”。

替换汇总字段中的 null 值

如果工作项没有任何子项,则汇总值可能为 null。 例如,如果功能没有任何子用户情景, 则 Descendants.CountOfUserStories 为“null”。

为便于报告,请按照以下步骤将所有 null 替换为零。

  1. 单击列标题选择列。
  2. 选择“转换”菜单。
  3. 选择“ 替换值”。 此时会显示“ 替换值 ”对话框。
  4. 在值中 输入“null”以查找
  5. 在“替换为”中输入“0”。
  6. 选择 “确定”

对所有汇总列重复。

关闭查询并应用更改

完成所有数据转换后,从“开始”菜单中选择“关闭和应用”以保存查询并返回到 Power BI 中的“报表”选项卡。

Power Query 编辑器“关闭并应用”选项的屏幕截图。

创建表报表

  1. 在 Power BI 中,选择可视化效果下的“表”报表。

    汇总表报表的 Power BI 可视化效果和字段选择的屏幕截图。

  2. 按指示的顺序将以下字段添加到 “列 ”:

    • WorkItemI,选择 “不汇总 ”以显示 ID(如果需要)
    • WorkItemType
    • Title
    • State
    • Count of User Stories
    • Total Story Points

显示示例报表。

示例功能汇总矩阵报表的屏幕截图。