كيفية تحويل استجابات API إلى تقارير Excel في C#

كيفية تحويل استجابات API إلى تقارير Excel في C#

في عالم اليوم المدفوع بالبيانات، تعتمد الشركات بشكل كبير على واجهات برمجة التطبيقات REST لتبادل البيانات. ومع ذلك، يفضل العديد من أصحاب المصلحة استهلاك هذه البيانات في تنسيق Excel للتحليل والتقارير. يوضح هذا الدليل كيفية بناء تطبيق C# كامل يقوم بما يلي:

  1. الاتصال بواجهات برمجة التطبيقات REST
  2. استرجاع بيانات استجابة JSON
  3. تحويل البيانات إلى تقارير Excel بتنسيق احترافي
  4. إضافة التصور باستخدام الرسوم البيانية والجداول

القيمة التجارية

تقدم هذه الحلول قيمة كبيرة من خلال:

  • أتمتة عمليات استخراج البيانات اليدوية وإنشاء التقارير
  • ضمان دقة البيانات من خلال القضاء على النسخ اليدوي
  • توفير تنسيق تقارير متسق
  • تمكين إنشاء تقارير مجدولة

دليل التنفيذ خطوة بخطوة

الخطوة 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

قم بإنشاء خدمة للتواصل مع واجهة برمجة التطبيقات:

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: التحويل إلى Excel باستخدام Aspose.Cells

قم بتنفيذ تحويل 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\"&14تقرير API");
    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"; // إذا لزم الأمر
            
            // الاتصال بواجهة برمجة التطبيقات والحصول على البيانات
            Console.WriteLine("الاتصال بواجهة برمجة التطبيقات...");
            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 البيانات بتنسيقات متنوعة. إليك كيفية التعامل مع الهياكل الشائعة:

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);
    }
}

ميزات متقدمة يجب مراعاتها

  1. تسليم البريد الإلكتروني - إرسال التقارير تلقائيًا عبر البريد الإلكتروني
  2. تكامل متعدد API - دمج البيانات من واجهات برمجة تطبيقات متعددة
  3. تقارير قائمة على القوالب - استخدام قوالب Excel لتحقيق علامة تجارية متسقة
  4. إنشاء لوحات معلومات - توليد لوحات معلومات تفاعلية في Excel
  5. تتبع الأخطاء والتقارير - تسجيل المشكلات والتقارير عن النجاح/الفشل

من خلال اتباع هذا الدليل، أنشأت تطبيق C# قويًا يقوم بأتمتة عملية استرجاع بيانات API وتحويلها إلى تقارير Excel احترافية - مما يوفر الوقت، ويضمن الدقة، ويقدم قيمة تجارية.

 عربي