zoukankan      html  css  js  c++  java
  • C# WinForm导出Excel

    概述

    在.NET应用中,导出Excel是很常见的需求,在我维护的一个应用中就遇到到了这样的需求,需要每月定时从不同的Server的不同数据库中获取Excel报表,手动生成实在是非常蛋疼。导出Excel报表大致有以下三种方式:Office PIA,文件流和NPOI开源库,本文只介绍前两种方式。

    Office PIA

    .NET开发人员首选的方法,通过COM组件调用Office软件本身来实现文件的创建和读写,但是数据量较大的时候异常缓慢;如下代码所示已经做了优化,将一个二维对象数组赋值到一个单元格区域中(下面的代码中只能用于导出列数不多于26列的数据导出):

    public static void ExportToExcel(DataSet dataSet, string outputPath)
    {
        Excel.ApplicationClass excel = new Excel.ApplicationClass();
        Excel.Workbook workbook = excel.Workbooks.Add(Type.Missing);
        int sheetIndex = 0;
        foreach (System.Data.DataTable dt in dataSet.Tables)
        {
            object[,] data = new object[dt.Rows.Count + 1, dt.Columns.Count];
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                data[0, j] = dt.Columns[j].ColumnName;
            }
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    data[i + 1, j] = dt.Rows[i][j];
                }
            }
            string finalColLetter = string.Empty;
    
            string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int colCharsetLen = colCharset.Length;
            if (dt.Columns.Count > colCharsetLen)
            {
                finalColLetter = colCharset.Substring(
                    (dt.Columns.Count - 1) / colCharsetLen - 1, 1);
            }
            finalColLetter += colCharset.Substring(
                    (dt.Columns.Count - 1) % colCharsetLen, 1);
            
            Excel.Worksheet sheet = (Excel.Worksheet)workbook.Sheets.Add(
                workbook.Sheets.get_Item(++sheetIndex),
                Type.Missing, 1, Excel.XlSheetType.xlWorksheet);
            sheet.Name = dt.TableName;
            string range = string.Format("A1:{0}{1}", finalColLetter, dt.Rows.Count + 1);
            sheet.get_Range(range, Type.Missing).Value2 = data;
            ((Excel.Range)sheet.Rows[1, Type.Missing]).Font.Bold = true;
        }
        workbook.SaveAs(outputPath, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        workbook.Close(true, Type.Missing, Type.Missing);
        workbook = null;
        excel.Quit();
        KillSpecialExcel(excel);
        excel = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
    
    [DllImport("user32.dll", SetLastError = true)]
    static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);
    
    static void KillSpecialExcel(Excel.Application app)
    {
        try
        {
            if (app != null)
            {
                int processId;
                GetWindowThreadProcessId(new IntPtr(app.Hwnd), out processId);
                System.Diagnostics.Process.GetProcessById(processId).Kill();
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    文件流

    这种方法的效率明显高于第一种,而且也不需要安装Office,但是导出的xls文件并不符合Excel的格式标准,在打开生成的xls文件时会提示:The file you are trying to open is in a different format that specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file.

    public static void ExportToExcel(System.Data.DataSet ds, string path)
    {
        StreamWriter sw = null;
        try
        {
            long totalCount = ds.Tables[0].Rows.Count;
            sw = new StreamWriter(path, false, Encoding.Unicode);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
            {
                sb.Append(ds.Tables[0].Columns[i].ColumnName + "\t");
            }
            sb.Append(Environment.NewLine);
            for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                for (int j = 0; j < ds.Tables[0].Columns.Count; j++)
                {
                    sb.Append(ds.Tables[0].Rows[i][j].ToString() + "\t");
                }
                sb.Append(Environment.NewLine);
            }
            sw.Write(sb.ToString());
            sw.Flush();
        }
        catch (IOException ioe)
        {
            throw ioe;
        }
        finally
        {
            if (sw != null)
            {
                sw.Close();
            }
        }
    }
    作者:LukyW
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>
    cvWaitKey 如果 cvNamedWindow就不会起作用
    Java 并发基础
    简化Getter 与 Setter 的插件 Lombok
    20、状态模式
    mybatis-generator 覆盖新增XML
    Jvm 虚拟机
    18、备忘录设计模式
    16、 观察者设计模式
    08、仲载者 -中间者模式
  • 原文地址:https://www.cnblogs.com/lukyw/p/3007422.html
Copyright © 2011-2022 走看看