如何在C#中将API响应转换为Excel报告
如何在C#中将API响应转换为Excel报告
在当今数据驱动的世界中,企业在数据交换中严重依赖REST API。然而,许多利益相关者更倾向于以Excel格式消费这些数据,以便进行分析和报告。本指南演示了如何构建一个完整的C#应用程序,该应用程序:
- 连接到REST API
- 检索JSON响应数据
- 将数据转换为专业格式的Excel报告
- 添加图表和表格的可视化
商业价值
该解决方案通过以下方式提供了显著的价值:
- 自动化手动数据提取和报告创建过程
- 通过消除手动复制来确保数据准确性
- 提供一致的报告格式
- 实现定时报告生成
分步实施指南
第1步:创建新的C#应用程序
首先创建一个新的控制台应用程序:
dotnet new console -n ApiToExcelReporter
cd ApiToExcelReporter
第2步:安装所需的包
添加必要的NuGet包:
dotnet add package Aspose.Cells
dotnet add package Newtonsoft.Json
dotnet add package RestSharp
第3步:实现REST API客户端
创建一个用于API通信的服务:
using RestSharp;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
public class ApiService
{
private readonly RestClient _client;
public ApiService(string baseUrl)
{
_client = new RestClient(baseUrl);
}
public async Task<T> GetApiDataAsync<T>(string endpoint, string apiKey = null)
{
var request = new RestRequest(endpoint, Method.Get);
// 如果需要,添加身份验证
if (!string.IsNullOrEmpty(apiKey))
{
request.AddHeader("Authorization", $"Bearer {apiKey}");
}
var response = await _client.ExecuteAsync(request);
if (response.IsSuccessful)
{
return JsonConvert.DeserializeObject<T>(response.Content);
}
throw new Exception($"API调用失败: {response.ErrorMessage}");
}
}
第4步:处理JSON响应数据
添加一个类来处理JSON数据:
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
public class DataProcessor
{
public List<Dictionary<string, object>> FlattenJsonData(string jsonData)
{
var results = new List<Dictionary<string, object>>();
JToken token = JToken.Parse(jsonData);
// 处理不同的JSON结构
if (token is JArray array)
{
foreach (var item in array)
{
results.Add(FlattenObject(item));
}
}
else if (token is JObject obj)
{
// 处理嵌套数据如 {"data": [{...}, {...}]}
var dataToken = obj["data"] as JArray;
if (dataToken != null)
{
foreach (var item in dataToken)
{
results.Add(FlattenObject(item));
}
}
else
{
results.Add(FlattenObject(obj));
}
}
return results;
}
private Dictionary<string, object> FlattenObject(JToken token)
{
var result = new Dictionary<string, object>();
FillDictionary(result, token, "");
return result;
}
private void FillDictionary(Dictionary<string, object> dict, JToken token, string prefix)
{
switch (token.Type)
{
case JTokenType.Object:
foreach (var prop in token.Children<JProperty>())
{
FillDictionary(dict, prop.Value,
string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}");
}
break;
case JTokenType.Array:
int index = 0;
foreach (var item in token.Children())
{
FillDictionary(dict, item, $"{prefix}[{index}]");
index++;
}
break;
default:
dict[prefix] = ((JValue)token).Value;
break;
}
}
}
第5步:使用Aspose.Cells转换为Excel
实现Excel转换:
using Aspose.Cells;
using Aspose.Cells.Utility;
using System;
using System.Collections.Generic;
using System.IO;
public class ExcelReportGenerator
{
public void GenerateReport(string jsonData, string outputPath)
{
// 创建一个新的工作簿
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// 配置JSON布局选项
JsonLayoutOptions options = new JsonLayoutOptions
{
ArrayAsTable = true,
ConvertNumericOrDate = true,
IgnoreNull = true
};
// 使标题加粗
options.TitleStyle = new CellsFactory().CreateStyle();
options.TitleStyle.Font.IsBold = true;
// 导入JSON数据
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
// 自动调整列宽
sheet.AutoFitColumns();
// 保存工作簿
workbook.Save(outputPath);
}
public void GenerateReportFromObjects(List<Dictionary<string, object>> data, string outputPath)
{
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// 如果有数据则添加标题
if (data.Count > 0)
{
int col = 0;
foreach (var key in data[0].Keys)
{
// 添加带样式的标题
Cell cell = sheet.Cells[0, col];
cell.PutValue(key);
Style style = cell.GetStyle();
style.Font.IsBold = true;
cell.SetStyle(style);
col++;
}
// 添加数据行
for (int row = 0; row < data.Count; row++)
{
col = 0;
foreach (var value in data[row].Values)
{
sheet.Cells[row + 1, col].PutValue(value);
col++;
}
}
}
// 格式化为表格
if (data.Count > 0)
{
int lastRow = data.Count;
int lastCol = data[0].Count - 1;
var tableRange = sheet.Cells.CreateRange(0, 0, lastRow + 1, lastCol + 1);
sheet.ListObjects.Add(tableRange, "DataTable");
}
// 自动调整列宽
sheet.AutoFitColumns();
// 保存工作簿
workbook.Save(outputPath);
}
}
第6步:添加专业格式
使用专业样式增强Excel输出:
public void ApplyProfessionalFormatting(Workbook workbook)
{
Worksheet sheet = workbook.Worksheets[0];
// 创建标题样式
Style titleStyle = workbook.CreateStyle();
titleStyle.Font.Size = 14;
titleStyle.Font.IsBold = true;
titleStyle.HorizontalAlignment = TextAlignmentType.Center;
// 为报告添加标题
sheet.Cells.Merge(0, 0, 1, sheet.Cells.MaxColumn + 1);
Cell titleCell = sheet.Cells[0, 0];
titleCell.PutValue("API数据报告 - " + DateTime.Now.ToString("yyyy-MM-dd"));
titleCell.SetStyle(titleStyle);
// 在标题后插入空行
sheet.Cells.InsertRow(1);
// 为数据应用交替行颜色
Style evenRowStyle = workbook.CreateStyle();
evenRowStyle.ForegroundColor = Color.FromArgb(240, 240, 240);
evenRowStyle.Pattern = BackgroundType.Solid;
int dataStartRow = 3; // 考虑到标题和空行
int lastRow = sheet.Cells.MaxRow;
for (int row = dataStartRow; row <= lastRow; row += 2)
{
for (int col = 0; col <= sheet.Cells.MaxColumn; col++)
{
sheet.Cells[row, col].SetStyle(evenRowStyle);
}
}
// 添加页眉和页脚
sheet.PageSetup.SetHeader(1, "&\"Arial,Bold\"&14API报告");
sheet.PageSetup.SetFooter(1, "第 &P 页,共 &N 页");
// 设置打印选项
sheet.PageSetup.Orientation = PageOrientationType.Landscape;
sheet.PageSetup.FitToPagesWide = 1;
sheet.PageSetup.TopMargin = 0.5;
sheet.PageSetup.LeftMargin = 0.5;
sheet.PageSetup.RightMargin = 0.5;
sheet.PageSetup.BottomMargin = 0.5;
}
第7步:添加数据可视化
使用图表增强报告:
public void AddChartVisualization(Workbook workbook, int dataColumn)
{
Worksheet sheet = workbook.Worksheets[0];
Worksheet chartSheet = workbook.Worksheets.Add("图表分析");
// 获取数据范围(跳过标题行)
int lastRow = sheet.Cells.MaxRow;
int nameColumn = 0; // 假设第一列包含名称/类别
// 添加图表
int chartIndex = chartSheet.Charts.Add(ChartType.Column, 2, 2, 20, 10);
Chart chart = chartSheet.Charts[chartIndex];
// 设置图表的数据范围
chart.NSeries.Add($"Sheet1!B2:B{lastRow + 1}", true);
chart.NSeries.CategoryData = $"Sheet1!A2:A{lastRow + 1}";
// 设置图表标题和其他属性
chart.Title.Text = "数据分析";
chart.Legend.Position = LegendPositionType.Bottom;
// 其他图表自定义
chart.NSeries[0].Area.ForegroundColor = Color.FromArgb(79, 129, 189);
chart.PlotArea.Area.ForegroundColor = Color.White;
// 添加数据标签
chart.NSeries[0].DataLabels.IsValueShown = true;
chart.NSeries[0].DataLabels.Position = DataLabelPositionType.OutsideEnd;
}
第8步:将所有内容整合在一起
创建一个主程序,将所有内容连接起来:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
try
{
// 配置API端点
string baseUrl = "https://api.example.com";
string endpoint = "/data/endpoint";
string apiKey = "your-api-key"; // 如果需要
// 连接到API并获取数据
Console.WriteLine("连接到API...");
var apiService = new ApiService(baseUrl);
var jsonData = await apiService.GetApiDataAsync<string>(endpoint, apiKey);
Console.WriteLine("数据成功检索");
// 生成Excel报告
Console.WriteLine("生成Excel报告...");
var reportGenerator = new ExcelReportGenerator();
// 选项1:直接从JSON转换为Excel
string outputPath = "ApiReport_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
reportGenerator.GenerateReport(jsonData, outputPath);
// 选项2:处理JSON并创建增强报告
// var processor = new DataProcessor();
// var processedData = processor.FlattenJsonData(jsonData);
// reportGenerator.GenerateReportFromObjects(processedData, outputPath);
Console.WriteLine($"报告已保存至 {outputPath}");
}
catch (Exception ex)
{
Console.WriteLine($"错误: {ex.Message}");
}
}
}
处理不同的API响应结构
REST API以各种格式返回数据。以下是如何处理常见结构:
1. 对象数组
[
{ "id": 1, "name": "产品A", "price": 29.99 },
{ "id": 2, "name": "产品B", "price": 49.99 }
]
对于此结构,使用:
JsonLayoutOptions options = new JsonLayoutOptions();
options.ArrayAsTable = true;
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
2. 包含数据数组的嵌套对象
{
"status": "success",
"data": [
{ "id": 1, "name": "产品A", "price": 29.99 },
{ "id": 2, "name": "产品B", "price": 49.99 }
]
}
使用DataProcessor类提取“data”数组,或:
// 使用Newtonsoft.Json解析
JObject jsonObj = JObject.Parse(jsonData);
JArray dataArray = (JArray)jsonObj["data"];
// 转换为字符串并导入
string dataArrayJson = dataArray.ToString();
JsonUtility.ImportData(dataArrayJson, sheet.Cells, 0, 0, options);
3. 嵌套数组和对象
{
"categories": [
{
"name": "电子产品",
"products": [
{ "id": 1, "name": "笔记本电脑", "price": 999.99 },
{ "id": 2, "name": "手机", "price": 699.99 }
]
},
{
"name": "书籍",
"products": [
{ "id": 3, "name": "小说", "price": 14.99 }
]
}
]
}
对于复杂结构,创建多个工作表:
// 解析JSON
JObject root = JObject.Parse(jsonData);
JArray categories = (JArray)root["categories"];
// 为每个类别创建一个工作表
foreach (var category in categories)
{
string categoryName = category["name"].ToString();
Worksheet sheet = workbook.Worksheets.Add(categoryName);
// 获取并导入产品数组
JArray products = (JArray)category["products"];
JsonUtility.ImportData(products.ToString(), sheet.Cells, 0, 0, options);
}
将其提升到一个新水平:定时报告
要自动化报告生成,添加调度功能:
// 安装任务调度程序包
// dotnet add package TaskScheduler
using Microsoft.Win32.TaskScheduler;
public void ScheduleDailyReportGeneration(string appPath)
{
using (TaskService ts = new TaskService())
{
// 创建一个新任务
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "每日API数据报告生成";
// 创建一个每天早上7点触发的触发器
td.Triggers.Add(new DailyTrigger { StartBoundary = DateTime.Today.AddHours(7) });
// 创建一个将运行应用程序的操作
td.Actions.Add(new ExecAction(appPath));
// 在根文件夹中注册任务
ts.RootFolder.RegisterTaskDefinition("DailyApiReport", td);
}
}
需要考虑的高级功能
- 电子邮件交付 - 自动通过电子邮件发送报告
- 多API集成 - 合并来自多个API的数据
- 基于模板的报告 - 使用Excel模板以保持一致的品牌形象
- 仪表板创建 - 生成交互式Excel仪表板
- 错误跟踪和报告 - 记录问题并报告成功/失败
通过遵循本指南,您已经创建了一个强大的C#应用程序,自动化了检索API数据并将其转换为专业的Excel报告的过程——节省时间,确保准确性,并提供商业价值。