65.9K
CodeProject 正在变化。 阅读更多。
Home

通用 DataGridView 导出到 Excel (带主题和格式)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (6投票s)

2009 年 10 月 30 日

CPOL

3分钟阅读

viewsIcon

67329

downloadIcon

4695

一篇关于将任何 datagridview 内容导出到 Excel 文件,并带有主题和格式化或 *.CSV (无主题) 的文章

引言

这是我对带主题和格式化的通用 DataGridView 导出到 Excel 的第二次也是最后一次更新。

总而言之,它的重点是创建一个支持一些格式化的动态和通用的导出解决方案。

我增加了 4 个额外的的主题,一些额外的条件和对齐功能。 我还添加了直接导出到 Excel 的功能,没有中间的 CSV。 我将只关注新的内容。
修复了用于 CSV 导出的非欧盟/美国文化的的问题。 现在它在 CSVToExcel() 方法中使用 System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator 代替 ","。 还修复了具体的数字格式 rrr.NumberFormat = "#,##0.00 [$€-407]";,使用更通用的 rrr.NumberFormat = String.Format("#,##0.00 [$€]");
对于这些精彩的观察,你要感谢 Mike.
现在,它有 4 个新主题,总共有八个

  • 蓝天 - 旧
  • 经典灰 - 旧
  • 绿是好的 - 旧
  • 可爱紫 - 旧 (从 SweetViolet 重命名)
  • 甜粉色 - 新
  • 红衣女郎 - 新
  • 橙色 - 新
  • 深蓝色 - 新

添加了一个额外的条件 -> TEXT,这对于同时包含数字和文本/字符串数据的列很有用。 还添加了一个新的 Enum Align。

  • 4 种货币格式(欧元和美元,带 2 位和 4 位小数)
  • 2 种百分比(默认情况下为 2 位和 4 位小数)
  • 3 个数字条件(带 2、3 或 4 位小数)
  • 2 个日期时间条件(一个采用 mm/dd/yy 格式,另一个采用 dd/mm/yy 格式)
  • 文本格式
  • 4 个(实际上是 3 个)对齐条件(左对齐、右对齐、居中对齐和默认的无对齐)

为了运行该应用程序,您需要从 COM 选项卡添加对 Microsoft Excel 11.0 或 12.0 对象库的引用。 警告:在 12.0 (2007) 版本中,颜色有所不同,因此输出可能不是您想要的。 您需要先进行测试。

特别感谢 PeterMoon将 DataSet 快速导出到 Excel 文章中的想法。

Using the Code

使用代码非常简单。 导出实用程序有三个类:主类 GenericFormattedExcel2003Export 和辅助类 ColumnConditionColumnRowConditon。 该实用程序还具有 4 个 enums:ConditionThemeThemeColors

下面给出了这三个 enums

public enum Condition
{
    None,			//default(no condition)
    Numeric,		//2 digits
    Numeric3,		//3 digits
    Numeric4,		//4 digits
    Percentage,		//2 digits
    Percentage4,	//4 digits
    CurrencyEuro,	//2 digits
    CurrencyEuro4,	//4 digits
    CurrencyDollar,	//2 digits
    CurrencyDollar4,//4 digits
    DateTime,		//dd/mm/yyyy
    USDateTime,		//mm/dd/yyy
    Text
}

public enum Theme
{
    BlueSky,
    ClassicGray,
    GreenIsGood,
    NiceViolet,
    DarkBlue,//new
    SweetPink,//new
    LadyInRed,//new
    OrangeWorks,//new
    CSV//no theme and a lot faster *.CSV export
}

public enum ThemeColors
{
    //first row FontColor is WHITE for all the themes
    FirstRowFontColor = 2,
    //the BlueSkyColors
    BlueSkyFirstRowInteriorColor = 11,
    BlueSkyInteriorColor = 37,
    BlueSkyFontColor = 11,
    //the ClassicGrayColors
    ClassicGrayFirstRowInteriorColor = 48,
    ClassicGrayInteriorColor = 15,
    ClasicGaryFontColor = 56,
    //the GreenIsGoodColors
    GreenIsGoodFirstRowInteriorColor = 50,
    GreenIsGoodInteriorColor = 35,
    GreenIsGoodFontColor = 10,
    //the SweetViolet/PinkColors for the ladies:)
    NiceVioletFirstRowInteriorColor = 13,
    NiceVioletInteriorColor = 39,
    NiceVioletFontColor = 13,
    //the OrangwWorks colors
    OrangeWorksFirstRowInterior = 46,
    OrangeWorksFont = 53,
    OrangeWorksInterior = 40,
    //the SweetPink colors
    SweetPinkFirstRowInterior = 7,
    SweetPinkFont = 13,
    SweetPinkInterior = 38,
    //the LadyInRed colors
    LadyInRedFirstRow = 3,
    LadyInRedFont = 3,
    LadyInRedInterior = 38,
    //the DarkBlue colors
    DarkBlueFirstRow = 55,
    DarkBlueFont = 11,
    DarkBlueInterior = 47
} 

在一个小测试应用程序中使用代码。 首先,我们需要向 datagridview 添加一些数据。 对于此任务,我创建了一个名为 SomethingReallyReallyUseless 的虚拟示例类。

Sample Image - maximum width is 600 pixels
//a dummy class to load some data into the gridview
public class SomethingReallyReallyUseless
{
    private string name;
    private double sum = 0.00d;
    private double performance = 0.00d;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public double Sum
    {
        get { return sum; }
        set { sum = value; }
    }

    public double Performance
    {
        get { return performance; }
        set { performance = value; }
    }
}

ColumnConditions

public class ColumnConditions
{
    private int column = 0;
    private Conditon condition = Conditon.None;
    private Align align = Align.None;

    public int Column
    {
        get { return column; }
        set { column = value; }
    }

    public Conditon Cond
    {
        get { return condition; }
        set { condition = value; }
    }

    public Align Alignment
    {
        get { return align; }
        set { align = value; }
    }
}

使用 DarkBlue 主题以及列和行额外的条件。 首先,我们必须创建条件,然后将它们传递给 GenericFormattedExcel2003Export

private void button1_Click(object sender, EventArgs e)
{
    string mode = rCsv.Checked ? "CSV" : "XLS";
    List<MyExcelExport.ColumnConditions> conds =
        new List<MyExcelExport.ColumnConditions>();
    MyExcelExport.ColumnConditions curr = null;

    //create the column conditions

    //no need to specify alignment
    //only if you wish/needed. It defaults to MyExcelExport.Align.None
    curr = new MyExcelExport.ColumnConditions();
    curr.Column = 2;
    curr.Cond = MyExcelExport.Conditon.CurrencyEuro;
    conds.Add(curr);

    //specify Alignment
    curr = new MyExcelExport.ColumnConditions();
    curr.Column = 3;
    curr.Cond = MyExcelExport.Conditon.Percentage;
    curr.Alignment = MyExcelExport.Align.Right;
    conds.Add(curr);

    List<MyExcelExport.ColumnRowConditon> rowConds = 
			new List<MyExcelExport.ColumnRowConditon>();
    MyExcelExport.ColumnRowConditon row = new MyExcelExport.ColumnRowConditon();
    row.Column = 1;
    row.ConditionValue = "Total";
    rowConds.Add(row);

    try
    {
        MyExcelExport.GenericFormattedExcel2003Export gExp =
            new MyExcelExport.GenericFormattedExcel2003Export(mode, dataGridView1,
                MyExcelExport.Theme.DarkBlue, conds, rowConds, null);
    }
    catch (COMException ex)
    {
        MessageBox.Show(ex.Message);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

使用 DarkBlue 主题,无额外条件。

private void button1_Click(object sender, EventArgs e)
{
    string mode = rCsv.Checked ? "CSV" : "XLS";
    try
    {
        MyExcelExport.GenericFormattedExcel2003Export gExp =
            new MyExcelExport.GenericFormattedExcel2003Export(dataGridView1,
                MyExcelExport.Theme.BlueSky, conds, rowConds);
    }
    catch (COMException ex)
    {
        MessageBox.Show(ex.Message);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

最后,使用 PeterMoon 的想法,从 GenericFormattedExcel2003Export 类中导出到 Blue Sky 主题的更新后的代码示例

//this is PeterMoon's idea-> to use Range.Value2 property 
//and paste a bi dimensional array of objects/datas
//creates the two dimensional object[,] from the datagridview
private object[,] CreateTwoDimensionalObject()
{
    object[,] datas = new object[dgv.Rows.Count + 1, dgv.Rows[0].Cells.Count];

    //add the first row(the column headers) to the array
    for (int col = 0; col < dgv.Columns.Count; col++)
    {
        datas[0, col] = dgv.Columns[col].HeaderText;
    }

    //copy the actual datas
    for (int col = 0; col < dgv.Rows[0].Cells.Count; col++)
    {
        for (int row = 0; row < dgv.Rows.Count; row++)
        {
            datas[row + 1, col] = dgv.Rows[row].Cells[col].Value.ToString();
        }
    }

    return datas;
}

//exports in the blue sky theme
private void BlueSky()
{
    try
    {
        object[,] datas = CreateTwoDimensionalObject();

        object None = Type.Missing;

        Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
        app.Visible = true;

        Excel.Workbook wk = app.Workbooks.Add(None);
        Excel.Worksheet ws = (Excel.Worksheet)wk.ActiveSheet;

        Excel.Range upperLeft = (Excel.Range)ws.Cells[1, 1];
        Excel.Range rightLimit = upperLeft.get_Offset(0, dgv.Columns.Count - 1);
        Excel.Range bottomRight = rightLimit.get_Offset(dgv.Rows.Count, 0);
        Excel.Range wholeThing = ws.get_Range(upperLeft, bottomRight);
        wholeThing.Value2 = datas;
        //set the font color
        wholeThing.Font.ColorIndex = ThemeColors.BlueSkyFontColor;
        //create the borders
        wholeThing.Borders.Weight = Excel.XlBorderWeight.xlThin;
        wholeThing.Borders.LineStyle = Excel.XlLineStyle.xlContinuous;
        wholeThing.Borders.ColorIndex = Excel.XlColorIndex.xlColorIndexAutomatic;

        //format first row
        upperLeft.EntireRow.Font.Bold = true;
        upperLeft.EntireRow.Font.Italic = true;
        upperLeft.EntireRow.Font.ColorIndex = ThemeColors.FirstRowFontColor;
        ws.get_Range(upperLeft, rightLimit).Interior.ColorIndex = 
				ThemeColors.BlueSkyFirstRowInteriorColor;

        Excel.Range r;
        //set the auto fit for each column
        for (int i = 1; i <= dgv.Rows[0].Cells.Count; i++)
        {
            r = (Excel.Range)ws.Cells[1, i];
            r.EntireColumn.AutoFit();
        }

        //color the 3rd row
        r = (Excel.Range)ws.Cells[3, 1];
        rightLimit = r.get_End(Microsoft.Office.Interop.Excel.XlDirection.xlToRight);
        ws.get_Range(r, rightLimit).Interior.ColorIndex = 
					ThemeColors.BlueSkyInteriorColor;

        //get the second and third row
        r = (Excel.Range)ws.Cells[2, 1];
        bottomRight = r.get_Offset(1, 0);
        bottomRight = bottomRight.get_End
			(Microsoft.Office.Interop.Excel.XlDirection.xlToRight);
        //copy the range
        ws.get_Range(r, bottomRight).Copy(None);

        //get the whole range
        r = (Excel.Range)ws.Cells[4, 1];
        bottomRight = r.get_End(Microsoft.Office.Interop.Excel.XlDirection.xlToRight);
        bottomRight = bottomRight.get_End
			(Microsoft.Office.Interop.Excel.XlDirection.xlDown);
        wholeThing = ws.get_Range(r, bottomRight);
        //now paste special -> formats
        wholeThing.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteFormats,
          	Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.
		xlPasteSpecialOperationNone, false, false);

        //apply column formatting, if any
        ApplyColumnFormats(ws);
        //apply rowcolumn(Bold row) formatting, if any
        if ((this.rowConds != null) && (this.rowConds.Count > 0))
        {
            Excel.Range rrr = null;
            //pass each datagridview row only once
            foreach (DataGridViewRow dgvItem in dgv.Rows)
            {
                foreach (var rowCon in rowConds)
                {
                    if (dgvItem.Cells[rowCon.Column - 1].Value.ToString().Equals
							(rowCon.ConditionValue))
                    {
                        rrr = (Excel.Range)ws.Cells[dgvItem.Cells[0].RowIndex + 2, 
				dgvItem.Cells[rowCon.Column - 1].ColumnIndex + 1];
                        rrr.EntireRow.Font.Bold = true;
                    }
                }
            }
        }
        //select cell A1
        upperLeft.Select();
    }
    catch (COMException ex)
    {
        throw ex;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

关注点

写这篇文章很愉快。 我将停止修改/添加文章的功能。 我可以添加大量新功能,但这不是本文的目的。 您可以修改并添加您自己的额外条件/格式化/或其他任何内容。 希望它能帮助到某人。 BRB 带来 2007 (Excel) 的额外酷炫主题/颜色和其他东西。

历史

  • 2009 年 10 月 30 日:这是第二次也是最后一次更新。

祝您编码愉快

© . All rights reserved.