如何跨TFS/Azure DevOps集合创建工作项查询并通过API导出至Excel等格式
跨TFS/ADO集合工作项查询及导出实现方案
核心思路
- 基于现有程序化创建工作项的开发基础,仅需要新增「跨集合工作项拉取」+「格式转换」两个模块的逻辑即可,可直接复用原有鉴权逻辑,开发量极低
- 不依赖平台自带导出功能,直接通过官方原生API拉取数据后自行转换为目标格式,适配性更强,同时支持TFS本地部署版本和Azure DevOps云端版本
API说明
- 跨集合查询使用官方标准WIQL(工作项查询语言)接口,单批次最多可拉取20000条工作项,可覆盖绝大多数业务场景
- 鉴权使用PAT(个人访问令牌)即可,仅需给令牌分配工作项读取权限,无需更高权限配置
可直接适配的代码示例(C#版,导出到Excel)
仅需要修改配置块的内容即可完成适配:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.TeamFoundation.WorkItemTracking.WebApi; using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models; using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Services.WebApi; using OfficeOpenXml; // 可按需替换为NPOI等其他Excel处理库 class WorkItemExporter { static void Main(string[] args) { // -------------------------- 仅需修改以下配置即可适配 -------------------------- string orgUrl = "https://dev.azure.com/你的组织名/"; // 本地TFS填集合根地址即可 string pat = "你的个人访问令牌PAT"; string wiqlQuery = "SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo] FROM WorkItems WHERE [System.AreaPath] UNDER '你的项目路径'"; string exportPath = @"C:\导出的工作项列表.xlsx"; // ----------------------------------------------------------------------------- // 建立服务连接 VssConnection connection = new VssConnection(new Uri(orgUrl), new VssBasicCredential(string.Empty, pat)); WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); // 执行WIQL查询获取工作项ID列表 Wiql queryObj = new Wiql() { Query = wiqlQuery }; var workItemIdList = witClient.QueryByWiqlAsync(queryObj).Result.WorkItems.Select(wi => wi.Id).ToList(); // 分批拉取工作项详情(单批最多拉200条,可根据服务器性能调整) List<WorkItem> workItemList = new List<WorkItem>(); for (int i = 0; i < workItemIdList.Count; i += 200) { var batchIds = workItemIdList.Skip(i).Take(200).ToList(); workItemList.AddRange(witClient.GetWorkItemsAsync(batchIds, expand: WorkItemExpand.All).Result); } // 导出到Excel ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // 非商用场景直接声明即可 using (var package = new ExcelPackage(new FileInfo(exportPath))) { var sheet = package.Workbook.Worksheets.Add("工作项列表"); // 写入表头 sheet.Cells[1, 1].Value = "工作项ID"; sheet.Cells[1, 2].Value = "标题"; sheet.Cells[1, 3].Value = "状态"; sheet.Cells[1, 4].Value = "负责人"; // 写入业务数据 for (int row = 0; row < workItemList.Count; row++) { var currentWi = workItemList[row]; sheet.Cells[row + 2, 1].Value = currentWi.Id; sheet.Cells[row + 2, 2].Value = currentWi.Fields["System.Title"].ToString(); sheet.Cells[row + 2, 3].Value = currentWi.Fields.ContainsKey("System.State") ? currentWi.Fields["System.State"].ToString() : ""; sheet.Cells[row + 2, 4].Value = currentWi.Fields.ContainsKey("System.AssignedTo") ? currentWi.Fields["System.AssignedTo"].ToString() : ""; } package.Save(); } Console.WriteLine($"导出完成,共导出{workItemList.Count}条工作项"); } }
其他格式导出说明
- 导出到Word:替换Excel导出模块为DocX等Word处理库,将拉取到的工作项数据按行写入Word表格即可
- 导出到Outlook:调用Outlook COM组件,把工作项数据拼接为HTML格式作为邮件正文,或者将导出的Excel/Word文件作为附件插入邮件即可
注意事项
- 可按需修改WIQL语句和后续写入逻辑的字段Key,适配自定义工作项字段的导出需求
- 跨集合查询时只需要调整orgUrl为对应集合的根地址,核心逻辑不需要修改
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

