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": "Product A", "price": 29.99 },
{ "id": 2, "name": "Product 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": "Product A", "price": 29.99 },
{ "id": 2, "name": "Product 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": "Electronics",
"products": [
{ "id": 1, "name": "Laptop", "price": 999.99 },
{ "id": 2, "name": "Phone", "price": 699.99 }
]
},
{
"name": "Books",
"products": [
{ "id": 3, "name": "Novel", "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 대시보드 생성
- 오류 추적 및 보고 - 문제를 기록하고 성공/실패에 대해 보고
이 가이드를 따르면 API 데이터를 검색하고 전문 Excel 보고서로 변환하는 강력한 C# 애플리케이션을 생성하게 됩니다. 시간 절약, 정확성 보장 및 비즈니스 가치를 제공합니다.