• OpenXML: excel 插入BarChart图表


     

    Openxml format SDK 2.0 v2 的 how to 文章里提供了一个怎样插入 chart 图表的示例, 但这个 chart的数据是独立不是根据excel sheet 上data 动态生成的chart,因此, 我在此示例代码上做了一些改动,可以根据excel sheet 上的数据, 生成 chart 图片, 效果如图

    画图的逻辑结构为:

    WorksheetPart<-DrawingsPart<-ChartPart<-ChartSpace<-Chart<-PlotArea<-BarChart<-BarChartSeries

    Openxml 画excel 柱状图的数据存在在BarChartSeries, 一个BarChartSeries的实例代表一个颜色的柱子, 上图共有C1, C2两个BarChartSeries实例。

    BarChartSeries 又包含三个部门:CategoryAxisData(x轴坐标), SeriesText(类型的名字, 这个也可以通过数据源取,sdk是传的固定值), Values(值, 柱状图的y轴值)。

    Openxml的数据源对应的类型是DocumentFormat.OpenXml.Drawing.Charts.Formula, 如:new DocumentFormat.OpenXml.Drawing.Charts.Formula(”sheet1!$A$1:$C$4“), 这个是说取 sheet1的 A1 到C4的数据

    这样我们改造sdk的代码就是 变BarChartSeries的值参, 为Openxml 的 Formula数据源

    1. 生成x轴的数据源实例:        


      string formulaString = string.Format("{0}!${1}${2}:${3}${4}", sheetName, columnName, startx + 1, columnName, startx + rowCount -1);
                CategoryAxisData cad 
    = new CategoryAxisData();
                cad.StringReference 
    = new StringReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };

    2. 生成数据的数据源实例:


     formulaString = string.Format("{0}!${1}${2}:${3}${4}", sheetName, columnName, startx +1, columnName, startx + rowCount-1);
                    DocumentFormat.OpenXml.Drawing.Charts.Values v 
    = new DocumentFormat.OpenXml.Drawing.Charts.Values();
                    v.NumberReference 
    = new NumberReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };

    这个数据源取得数据需要把保证cell的datatype 是"Number";因此在写数据时要用如下方法

    Cell cell = InsertCellInWorksheet(name, Convert.ToUInt32(j + startx), worksheetPart);

                        cell.CellValue = new CellValue(index.ToString());
                        cell.DataType = new EnumValue<CellValues>(CellValues.Number);
                        worksheetPart.Worksheet.Save();

    3. 生成分类柱的名字:


    formulaString = string.Format("{0}!${1}${2}", sheetName, columnName, startx);
                    SeriesText st 
    = new SeriesText();
                    st.StringReference 
    = new StringReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };

    4. 生成柱状图的一个分类的实例:


        BarChartSeries barChartSeries = barChart.AppendChild<BarChartSeries>(new BarChartSeries(new Index() { Val = new UInt32Value(i) },
                        
    new Order() { Val = new UInt32Value(i) }, st, v));
                    
    if (sIndex == 1)
                        barChartSeries.AppendChild(cad);

    这里startx表示excel行索引, starty表示excel的列索引

    改造SDK how to 方法的完整代码:


      1 /// <summary>
      2    /// draw the 2D bar chart
      3    /// index start from 1
      4    /// </summary>
      5    /// <param name="startx">index start from 1 for row</param>
      6    /// <param name="starty">index start from 1 for column</param>
      7    /// <param name="columnCount"></param>
      8    /// <param name="rowCount"></param>

      9    public void InsertChartInSpreadsheet(int startx, int starty, int columnCount, int rowCount)
     10    {
     11        WorksheetPart worksheetPart = CurrentWorksheetPart;
     12
     13        SDK How to example code
     32
     33        string sheetName = GetCurrentSheetName();
     34        string columnName = GetColumnName(starty - 1);
     35        string formulaString = string.Format("{0}!${1}${2}:${3}${4}", sheetName, columnName, startx + 1, columnName, startx + rowCount - 1);
     36        CategoryAxisData cad = new CategoryAxisData();
     37        cad.StringReference = new StringReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };
     38
     39        uint i = 0;
     40        for (int sIndex = 1; sIndex < columnCount; sIndex++)
     41        {
     42            columnName = GetColumnName(starty + sIndex - 1);
     43            formulaString = string.Format("{0}!${1}${2}", sheetName, columnName, startx);
     44            SeriesText st = new SeriesText();
     45            st.StringReference = new StringReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };
     46
     47            formulaString = string.Format("{0}!${1}${2}:${3}${4}", sheetName, columnName, startx + 1, columnName, startx + rowCount - 1);
     48            DocumentFormat.OpenXml.Drawing.Charts.Values v = new DocumentFormat.OpenXml.Drawing.Charts.Values();
     49            v.NumberReference = new NumberReference() { Formula = new DocumentFormat.OpenXml.Drawing.Charts.Formula(formulaString) };
     50
     51            BarChartSeries barChartSeries = barChart.AppendChild<BarChartSeries>(new BarChartSeries(new Index() { Val = new UInt32Value(i) },
     52                new Order() { Val = new UInt32Value(i) }, st, v));
     53            if (sIndex == 1)
     54                barChartSeries.AppendChild(cad);
     55            i++;
     56        }

     57        SDK how to  example Code
    134    }

    获取当前sheet name的方法:


      private string GetCurrentSheetName()
        {
            
    string name = "";
            WorkbookPart workbookPart 
    = spreadSheet.WorkbookPart;
            
    string relationshipId = workbookPart.GetIdOfPart(CurrentWorksheetPart);
            Sheets sheets 
    = workbookPart.Workbook.GetFirstChild<Sheets>();
            
    foreach (Sheet item in sheets)
            {
                
    if (item.Id == relationshipId)
                {
                    name 
    = item.Name;
                    
    break;
                }
            }
            
    return name;
        }

    怎样生成excel 并写数据请参看 http://www.cnblogs.com/skyfei/archive/2009/06/12/Openxml.html 

  • 相关阅读:
    归并排序
    快速排序
    冒泡排序
    排序算法复杂度
    [LeetCode] 20. Valid Parentheses ☆(括号匹配问题)
    makefile编写helloworld
    shell的通俗理解
    PID三种参数的理解
    PID的原理
    PID控制温度
  • 原文地址:https://www.cnblogs.com/chuncn/p/1508002.html
Copyright © 2020-2023  润新知