首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 操作 Excel 建立圖表完整教學:從資料來源到 Chart 物件模型

     編輯:關於C語言

前言

透過 Microsoft.Office.Interop.Excel 以 C# 程式化建立 Excel 圖表,需理解 Excel 物件模型:Application → Workbook → Worksheet → ChartObjects → Chart → SeriesCollection。本文示範完整流程:寫入資料、建立圖表、設定類型、資料來源、標題、圖例、座標軸、資料標籤、輸出圖片。

必要條件

  • 已安裝 Microsoft Excel (或啟用 Office 線上版)
  • 專案參考 Microsoft.Office.Interop.Excel (NuGet: Microsoft.Office.Interop.Excel)
  • 目標平台 x64 (對應 64 位元 Excel) 或勾選 Prefer 32-bit

完整建立圖表範例

using Excel = Microsoft.Office.Interop.Excel;

public class ExcelChartBuilder
{
    public void CreateSalesChart(string outputXlsx, string outputChartImage = null)
    {
        Excel.Application excel = null;
        Excel.Workbook wb = null;
        Excel.Worksheet ws = null;

        try
        {
            excel = new Excel.Application
            {
                Visible = false,
                DisplayAlerts = false,
                ScreenUpdating = false
            };

            wb = excel.Workbooks.Add();
            ws = (Excel.Worksheet)wb.ActiveSheet;
            ws.Name = "銷售報表";

            // 1. 寫入標題列
            string[] headers = { "月份", "產品A", "產品B", "產品C" };
            for (int c = 0; c < headers.Length; c++)
                ws.Cells[1, c + 1] = headers[c];

            // 2. 寫入資料 (範例 12 筆)
            var data = new object[,]
            {
                { "1月", 120, 95, 80 },
                { "2月", 135, 110, 85 },
                { "3月", 150, 105, 90 },
                { "4月", 165, 120, 95 },
                { "5月", 180, 130, 100 },
                { "6月", 200, 145, 110 },
                { "7月", 220, 160, 120 },
                { "8月", 210, 155, 115 },
                { "9月", 195, 140, 105 },
                { "10月", 180, 130, 100 },
                { "11月", 160, 115, 90 },
                { "12月", 140, 100, 80 }
            };
            ws.Range["A2", "D13"].Value2 = data;

            // 3. 設定儲存格格式
            ws.Range["A1", "D1"].Font.Bold = true;
            ws.Range["A1", "D1"].Interior.Color = ColorTranslator.ToOle(Color.LightBlue);
            ws.Columns.AutoFit();

            // 4. 建立圖表
            Excel.ChartObjects chartObjs = (Excel.ChartObjects)ws.ChartObjects(Type.Missing);
            Excel.ChartObject chartObj = chartObjs.Add(Left: 100, Top: 50, Width: 600, Height: 400);
            Excel.Chart chart = chartObj.Chart;

            // 5. 設定圖表類型:群組長條圖
            chart.ChartType = Excel.XlChartType.xlColumnClustered;

            // 6. 設定資料來源 (包含標題列,依欄為系列)
            Excel.Range sourceRange = ws.Range["A1", "D13"];
            chart.SetSourceData(sourceRange, Excel.XlRowCol.xlColumns);

            // 7. 圖表美化
            chart.HasTitle = true;
            chart.ChartTitle.Text = "2024 年月度產品銷售比較";
            chart.ChartTitle.Font.Size = 14;
            chart.ChartTitle.Font.Bold = true;

            chart.HasLegend = true;
            chart.Legend.Position = Excel.XlLegendPosition.xlLegendPositionBottom;
            chart.Legend.Font.Size = 10;

            // 座標軸
            Excel.Axis categoryAxis = (Excel.Axis)chart.Axes(Excel.XlAxisType.xlCategory);
            categoryAxis.HasTitle = true;
            categoryAxis.AxisTitle.Text = "月份";
            categoryAxis.TickLabels.Font.Size = 9;

            Excel.Axis valueAxis = (Excel.Axis)chart.Axes(Excel.XlAxisType.xlValue);
            valueAxis.HasTitle = true;
            valueAxis.AxisTitle.Text = "銷售額 (千元)";
            valueAxis.MajorGridlines.Format.Line.ForeColor.RGB = ColorTranslator.ToOle(Color.LightGray);

            // 資料標籤 (顯示數值)
            foreach (Excel.Series series in chart.SeriesCollection())
            {
                series.HasDataLabels = true;
                series.DataLabels().Font.Size = 8;
                series.DataLabels().NumberFormat = "#,##0";
            }

            // 8. (選擇性) 另存圖表為圖片
            if (!string.IsNullOrEmpty(outputChartImage))
            {
                chart.Export(outputChartImage, "PNG");
            }

            // 9. 儲存活頁簿
            wb.SaveAs(outputXlsx, Excel.XlFileFormat.xlOpenXMLWorkbook);
        }
        finally
        {
            // 10. 釋放 COM 物件 (逆序)
            ReleaseCom(ws);
            if (wb != null) { wb.Close(false); ReleaseCom(wb); }
            if (excel != null) { excel.Quit(); ReleaseCom(excel); }
            GC.Collect(); GC.WaitForPendingFinalizers();
        }
    }

    private void ReleaseCom(object obj)
    {
        if (obj != null)
        {
            try { Marshal.ReleaseComObject(obj); } catch { }
        }
    }
}

關鍵物件模型說明

物件用途常用屬性/方法
ChartObjects工作表上的圖表容器集合Add(Left, Top, Width, Height)
ChartObject單一圖表容器 (可移動/調整大小).Chart 取得實際 Chart 物件
Chart圖表核心ChartType, SetSourceData, SeriesCollection(), Export
SeriesCollection資料系列集合.Item(index), .NewSeries()
Series單一資料系列.Name, .Values, .XValues, .HasDataLabels
Axes座標軸集合AxisTitle, .MajorGridlines, .MinimumScale

常見圖表類型常數

// 柱狀/長條
xlColumnClustered = 51      // 群組長條圖
xlColumnStacked = 52        // 堆疊長條圖
xlColumnStacked100 = 53     // 100% 堆疊長條圖
xlBarClustered = 57         // 群組橫條圖

// 折線
xlLine = 4                  // 折線圖
xlLineMarkers = 65          // 帶標記折線圖
xlLineStacked = 63          // 堆疊折線圖

// 圓餅
xlPie = 5                   // 圓餅圖
xlPieExploded = 69          // 分離圓餅圖
xlDoughnut = -4120          // 環狀圖

// 散佈/氣泡
xlXYScatter = -4169         // 散佈圖
xlBubble = 15               // 氣泡圖

// 組合圖需手動建立多個 Series 並設定 ChartType

資料來源範圍設定細節


// 方式 1: SetSourceData (最簡單)
chart.SetSourceData(ws.Range["A1:D13"], Excel.XlRowCol.xlColumns); // 欄為系列

// 方式 2: 手動加入 Series (彈性最高)
Excel.Series seriesA = chart.SeriesCollection().NewSeries();
seriesA.Name = "=Sheet1!$B$1";
seriesA.Values = "=Sheet1!$B$2:$B$13";
seriesA.XValues = "=Sheet1!$A$2:$A$13";
seriesA.ChartType = Excel.XlChartType.xlColumnClustered;

// 方式 3: 多區域非連續範圍
Excel.Range multiRange = excel.Union(ws.Range["A1:A13"], ws.Range["C1:C13"]);
chart.SetSourceData(multiRange, Excel.XlRowCol.xlColumns);

進階:組合圖表 (長條 + 折線雙 Y 軸)


// 假設已有 chart 與資料
Excel.Series seriesLine = chart.SeriesCollection().NewSeries();
seriesLine.Name = "=Sheet1!$E$1"; // 達成率
seriesLine.Values = "=Sheet1!$E$2:$E$13";
seriesLine.ChartType = Excel.XlChartType.xlLineMarkers;
seriesLine.AxisGroup = Excel.XlAxisGroup.xlSecondary; // 指派給次要 Y 軸

// 顯示次要 Y 軸
Excel.Axis secAxis = (Excel.Axis)chart.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlSecondary);
secAxis.HasTitle = true;
secAxis.AxisTitle.Text = "達成率 (%)";
secAxis.MaximumScale = 1.2;
secAxis.MinimumScale = 0;
secAxis.TickLabels.NumberFormat = "0%";

效能與記憶體最佳實務

  • 批次寫入:使用 Range.Value2 = object[,] 一次寫入二維陣列,避免逐 Cell 呼叫 COM。
  • 關閉 UI 更新:excel.ScreenUpdating = false; excel.DisplayAlerts = false;
  • 及時釋放 COM:Marshal.ReleaseComObject 逆序釋放,GC.Collect() 強制回收 RCW。
  • 避免迴圈存取:for (int i=1; i<=n; i++) ws.Cells[i,1] = ... 極慢,改用陣列或 Range.Resize。

無 Excel 環境替代方案

套件支援圖表特點
EPPlus (商業授權)完整支援純 .NET、無 Office 相依、效能極佳
ClosedXML (MIT)基本支援API 簡潔、開源、社群活躍
NPOI (Apache 2.0)支援 (較複雜)Java POI 移植、支援 .xls/.xlsx
Syncfusion XlsIO (商業)企業級完整功能最全、含轉 PDF/圖片

建議:伺服器端/容器化部署請改用 EPPlus/ClosedXML,避免安裝 Office 與 COM 相容性問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved