Cách Chuyển Đổi Phản Hồi API Thành Báo Cáo Excel Trong C#
Trong thế giới ngày nay, nơi dữ liệu được điều khiển, các doanh nghiệp phụ thuộc rất nhiều vào REST APIs để trao đổi dữ liệu. Tuy nhiên, nhiều bên liên quan thích tiêu thụ dữ liệu này dưới định dạng Excel để phân tích và báo cáo. Hướng dẫn này minh họa cách xây dựng một ứng dụng C# hoàn chỉnh mà:
- Kết nối với REST APIs
- Lấy dữ liệu phản hồi JSON
- Chuyển đổi dữ liệu thành các báo cáo Excel được định dạng chuyên nghiệp
- Thêm hình ảnh hóa với biểu đồ và bảng
Giá trị doanh nghiệp
Giải pháp này mang lại giá trị đáng kể bằng cách:
- Tự động hóa quy trình trích xuất dữ liệu thủ công và tạo báo cáo
- Đảm bảo độ chính xác của dữ liệu bằng cách loại bỏ việc sao chép thủ công
- Cung cấp định dạng báo cáo nhất quán
- Cho phép tạo báo cáo theo lịch trình
Hướng dẫn thực hiện từng bước
Bước 1: Tạo một ứng dụng C# mới
Bắt đầu bằng cách tạo một ứng dụng console mới:
dotnet new console -n ApiToExcelReporter
cd ApiToExcelReporter
Bước 2: Cài đặt các gói cần thiết
Thêm các gói NuGet cần thiết:
dotnet add package Aspose.Cells
dotnet add package Newtonsoft.Json
dotnet add package RestSharp
Bước 3: Triển khai Client REST API
Tạo một dịch vụ để giao tiếp với 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);
// Thêm xác thực nếu cần
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($"Cuộc gọi API không thành công: {response.ErrorMessage}");
}
}
Bước 4: Xử lý dữ liệu phản hồi JSON
Thêm một lớp để xử lý dữ liệu 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);
// Xử lý các cấu trúc JSON khác nhau
if (token is JArray array)
{
foreach (var item in array)
{
results.Add(FlattenObject(item));
}
}
else if (token is JObject obj)
{
// Đối với dữ liệu lồng nhau như {"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;
}
}
}
Bước 5: Chuyển đổi sang Excel với Aspose.Cells
Triển khai việc chuyển đổi 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)
{
// Tạo một workbook mới
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// Cấu hình tùy chọn bố cục JSON
JsonLayoutOptions options = new JsonLayoutOptions
{
ArrayAsTable = true,
ConvertNumericOrDate = true,
IgnoreNull = true
};
// Đặt tiêu đề in đậm
options.TitleStyle = new CellsFactory().CreateStyle();
options.TitleStyle.Font.IsBold = true;
// Nhập dữ liệu JSON
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
// Tự động điều chỉnh cột
sheet.AutoFitColumns();
// Lưu workbook
workbook.Save(outputPath);
}
public void GenerateReportFromObjects(List<Dictionary<string, object>> data, string outputPath)
{
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
// Thêm tiêu đề nếu có dữ liệu
if (data.Count > 0)
{
int col = 0;
foreach (var key in data[0].Keys)
{
// Thêm tiêu đề với kiểu dáng
Cell cell = sheet.Cells[0, col];
cell.PutValue(key);
Style style = cell.GetStyle();
style.Font.IsBold = true;
cell.SetStyle(style);
col++;
}
// Thêm các hàng dữ liệu
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++;
}
}
}
// Định dạng như một bảng
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");
}
// Tự động điều chỉnh cột
sheet.AutoFitColumns();
// Lưu workbook
workbook.Save(outputPath);
}
}
Bước 6: Thêm định dạng chuyên nghiệp
Nâng cao đầu ra Excel với kiểu dáng chuyên nghiệp:
public void ApplyProfessionalFormatting(Workbook workbook)
{
Worksheet sheet = workbook.Worksheets[0];
// Tạo một kiểu dáng cho tiêu đề
Style titleStyle = workbook.CreateStyle();
titleStyle.Font.Size = 14;
titleStyle.Font.IsBold = true;
titleStyle.HorizontalAlignment = TextAlignmentType.Center;
// Thêm tiêu đề cho báo cáo
sheet.Cells.Merge(0, 0, 1, sheet.Cells.MaxColumn + 1);
Cell titleCell = sheet.Cells[0, 0];
titleCell.PutValue("Báo cáo dữ liệu API - " + DateTime.Now.ToString("yyyy-MM-dd"));
titleCell.SetStyle(titleStyle);
// Chèn một hàng trống sau tiêu đề
sheet.Cells.InsertRow(1);
// Áp dụng màu hàng xen kẽ cho dữ liệu
Style evenRowStyle = workbook.CreateStyle();
evenRowStyle.ForegroundColor = Color.FromArgb(240, 240, 240);
evenRowStyle.Pattern = BackgroundType.Solid;
int dataStartRow = 3; // Tính đến tiêu đề và hàng trống
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);
}
}
// Thêm tiêu đề và chân trang
sheet.PageSetup.SetHeader(1, "&\"Arial,Bold\"&14Báo cáo API");
sheet.PageSetup.SetFooter(1, "Trang &P của &N");
// Đặt tùy chọn in
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;
}
Bước 7: Thêm hình ảnh hóa dữ liệu
Nâng cao báo cáo với các biểu đồ:
public void AddChartVisualization(Workbook workbook, int dataColumn)
{
Worksheet sheet = workbook.Worksheets[0];
Worksheet chartSheet = workbook.Worksheets.Add("Phân tích Biểu đồ");
// Lấy phạm vi dữ liệu (bỏ qua hàng tiêu đề)
int lastRow = sheet.Cells.MaxRow;
int nameColumn = 0; // Giả sử cột đầu tiên có tên/danh mục
// Thêm một biểu đồ
int chartIndex = chartSheet.Charts.Add(ChartType.Column, 2, 2, 20, 10);
Chart chart = chartSheet.Charts[chartIndex];
// Đặt phạm vi dữ liệu cho biểu đồ
chart.NSeries.Add($"Sheet1!B2:B{lastRow + 1}", true);
chart.NSeries.CategoryData = $"Sheet1!A2:A{lastRow + 1}";
// Đặt tiêu đề biểu đồ và các thuộc tính khác
chart.Title.Text = "Phân tích Dữ liệu";
chart.Legend.Position = LegendPositionType.Bottom;
// Tùy chỉnh biểu đồ bổ sung
chart.NSeries[0].Area.ForegroundColor = Color.FromArgb(79, 129, 189);
chart.PlotArea.Area.ForegroundColor = Color.White;
// Thêm nhãn dữ liệu
chart.NSeries[0].DataLabels.IsValueShown = true;
chart.NSeries[0].DataLabels.Position = DataLabelPositionType.OutsideEnd;
}
Bước 8: Kết hợp mọi thứ lại với nhau
Tạo chương trình chính kết nối mọi thứ lại với nhau:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
try
{
// Cấu hình điểm cuối API
string baseUrl = "https://api.example.com";
string endpoint = "/data/endpoint";
string apiKey = "your-api-key"; // Nếu cần
// Kết nối với API và lấy dữ liệu
Console.WriteLine("Kết nối với API...");
var apiService = new ApiService(baseUrl);
var jsonData = await apiService.GetApiDataAsync<string>(endpoint, apiKey);
Console.WriteLine("Dữ liệu đã được lấy thành công");
// Tạo báo cáo Excel
Console.WriteLine("Đang tạo báo cáo Excel...");
var reportGenerator = new ExcelReportGenerator();
// Tùy chọn 1: Chuyển đổi JSON trực tiếp sang Excel
string outputPath = "ApiReport_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
reportGenerator.GenerateReport(jsonData, outputPath);
// Tùy chọn 2: Xử lý JSON và tạo báo cáo nâng cao
// var processor = new DataProcessor();
// var processedData = processor.FlattenJsonData(jsonData);
// reportGenerator.GenerateReportFromObjects(processedData, outputPath);
Console.WriteLine($"Báo cáo đã được lưu tại {outputPath}");
}
catch (Exception ex)
{
Console.WriteLine($"Lỗi: {ex.Message}");
}
}
}
Xử lý các cấu trúc phản hồi API khác nhau
REST APIs trả về dữ liệu dưới nhiều định dạng khác nhau. Dưới đây là cách xử lý các cấu trúc phổ biến:
1. Mảng đối tượng
[
{ "id": 1, "name": "Sản phẩm A", "price": 29.99 },
{ "id": 2, "name": "Sản phẩm B", "price": 49.99 }
]
Đối với cấu trúc này, hãy sử dụng:
JsonLayoutOptions options = new JsonLayoutOptions();
options.ArrayAsTable = true;
JsonUtility.ImportData(jsonData, sheet.Cells, 0, 0, options);
2. Đối tượng lồng nhau với mảng dữ liệu
{
"status": "success",
"data": [
{ "id": 1, "name": "Sản phẩm A", "price": 29.99 },
{ "id": 2, "name": "Sản phẩm B", "price": 49.99 }
]
}
Sử dụng lớp DataProcessor để trích xuất mảng “data”, hoặc:
// Phân tích với Newtonsoft.Json
JObject jsonObj = JObject.Parse(jsonData);
JArray dataArray = (JArray)jsonObj["data"];
// Chuyển đổi thành chuỗi và nhập
string dataArrayJson = dataArray.ToString();
JsonUtility.ImportData(dataArrayJson, sheet.Cells, 0, 0, options);
3. Mảng và đối tượng lồng nhau
{
"categories": [
{
"name": "Điện tử",
"products": [
{ "id": 1, "name": "Laptop", "price": 999.99 },
{ "id": 2, "name": "Điện thoại", "price": 699.99 }
]
},
{
"name": "Sách",
"products": [
{ "id": 3, "name": "Tiểu thuyết", "price": 14.99 }
]
}
]
}
Đối với các cấu trúc phức tạp, hãy tạo nhiều worksheet:
// Phân tích JSON
JObject root = JObject.Parse(jsonData);
JArray categories = (JArray)root["categories"];
// Tạo một worksheet cho mỗi danh mục
foreach (var category in categories)
{
string categoryName = category["name"].ToString();
Worksheet sheet = workbook.Worksheets.Add(categoryName);
// Lấy và nhập mảng sản phẩm
JArray products = (JArray)category["products"];
JsonUtility.ImportData(products.ToString(), sheet.Cells, 0, 0, options);
}
Đưa nó lên một tầm cao mới: Báo cáo theo lịch trình
Để tự động hóa việc tạo báo cáo, hãy thêm khả năng lập lịch:
// Cài đặt gói Task Scheduler
// dotnet add package TaskScheduler
using Microsoft.Win32.TaskScheduler;
public void ScheduleDailyReportGeneration(string appPath)
{
using (TaskService ts = new TaskService())
{
// Tạo một tác vụ mới
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Description = "Tạo báo cáo dữ liệu API hàng ngày";
// Tạo một kích hoạt sẽ xảy ra hàng ngày vào lúc 7 giờ sáng
td.Triggers.Add(new DailyTrigger { StartBoundary = DateTime.Today.AddHours(7) });
// Tạo một hành động sẽ chạy ứng dụng
td.Actions.Add(new ExecAction(appPath));
// Đăng ký tác vụ trong thư mục gốc
ts.RootFolder.RegisterTaskDefinition("DailyApiReport", td);
}
}
Các tính năng nâng cao cần xem xét
- Gửi email - Tự động gửi báo cáo qua email
- Tích hợp đa API - Kết hợp dữ liệu từ nhiều API
- Báo cáo dựa trên mẫu - Sử dụng các mẫu Excel để giữ thương hiệu nhất quán
- Tạo bảng điều khiển - Tạo bảng điều khiển Excel tương tác
- Theo dõi và báo cáo lỗi - Ghi lại các vấn đề và báo cáo về thành công/thất bại
Bằng cách làm theo hướng dẫn này, bạn đã tạo ra một ứng dụng C# mạnh mẽ tự động hóa quy trình lấy dữ liệu API và chuyển đổi nó thành các báo cáo Excel chuyên nghiệp—tiết kiệm thời gian, đảm bảo độ chính xác và mang lại giá trị cho doanh nghiệp.