.NET Excel导出方法及其常见问题详解

摘要:.NET Excel导出方法及其常见问题详解。html

1、Excel导出的实现方法java

  在.net 程序开发中,对于Excel文件的导出咱们一共有三种导出方式:安全

  1. 利用文件输出流进行读写操做

    这种方式的导出方法是比较简单就能够实现的,咱们其实是针对相似于html中table表格的输出服务器

    a.针对想要的Excel合并样式写一个table标签代码app

       

 1 <table border="1">
 2     <thead>
 3         <tr>
 4             <th style="background-color:yellow" colspan="7" align="center">物料汇总单</th>
 5         </tr>
 6         <tr>
 7             <th style="background-color:yellow">物料码</th>
 8             <th style="background-color:yellow">物料名称</th>
 9             <th style="background-color:yellow">型号</th>
10             <th style="background-color:yellow">单位</th>
11             <th style="background-color:yellow">数量</th>
12             <th style="background-color:yellow">备注</th>
13             <th style="background-color:yellow">排序</th>
14         </tr>
15     </thead>
16     <tbody>
17         <tr>
18             <th>{0}</th>
19             <th>{0}</th>
20             <th>{0}</th>
21             <th>{0}</th>
22             <th>{0}</th>
23             <th>{0}</th>
24             <th>{0}</th>
25         </tr>
26     </tbody>
27 </table>

    table的border属性能够控制展示为Excel文件时是否显示网格线,通常若是不设置为border="1"时,导出的文件是不会生成网格线的,实际上table的各类属性和样式最终在生成为Excel文件时,都大体会以相同的格式展示出来,也就是说咱们只要设计好table的样式就行,不用考虑其它的问题了。测试

    而对于表头中的颜色设置:网站

1        <tr>
2             <th style="background-color:yellow">物料码</th>
3             <th style="background-color:yellow">物料名称</th>
4             <th style="background-color:yellow">型号</th>
5             <th style="background-color:yellow">单位</th>
6             <th style="background-color:yellow">数量</th>
7             <th style="background-color:yellow">备注</th>
8             <th style="background-color:yellow">排序</th>
9         </tr>    

    有很多人会疑惑:为何不在<tr>设置background-color不是更方便?this

1        <tr style="background-color:yellow">
2             <th>物料码</th>
3             <th>物料名称</th>
4             <th>型号</th>
5             <th>单位</th>
6             <th>数量</th>
7             <th>备注</th>
8             <th>排序</th>
9         </tr>

    这样作的确省了很多事,可是这样作当转化为Excel文件时效果就不是很相同了。spa

    咱们理想中的效果:.net

    

    但实际上会展现为:

    

    转化为Excel文件时并未在固定的列数设置背景颜色,而是整行都被设置为黄色。针对其余的细节咱们能够慢慢的去尝试,去调整。

    此时咱们先要针对现有的table标签进行数据填充:

 1             ber.Append("<table border=\"1\">");
 2             ber.Append("<thead>");
 3             ber.Append("<tr><th  style=\"background-color:yellow\" colspan=\"7\" align=\"center\">物料汇总单</th></tr>");
 4 
 5             ber.Append("<tr>");
 6 
 7             ber.Append("<th style=\"background-color:yellow\">物料码</th>");
 8             ber.Append("<th style=\"background-color:yellow\">物料名称</th>");
 9             ber.Append("<th style=\"background-color:yellow\">型号</th>");
10             ber.Append("<th style=\"background-color:yellow\">单位</th>");
11             ber.Append("<th style=\"background-color:yellow\">数量</th>");
12             ber.Append("<th style=\"background-color:yellow\">备注</th>");
13             ber.Append("<th style=\"background-color:yellow\">排序</th>");
14 
15             ber.Append("</tr>");
16             ber.Append("</thead>");
17 
18             ber.Append("<tbody>");
19             foreach (ExcelTMaterial item in all_models)
20             {
21                 ber.Append("<tr>");
22                 ber.AppendFormat("<th>{0}</th>", item.mt_code);
23                 ber.AppendFormat("<th>{0}</th>", item.mt_name);
24                 ber.AppendFormat("<th>{0}</th>", item.mt_model);
25                 ber.AppendFormat("<th>{0}</th>", item.mt_unit);
26                 ber.AppendFormat("<th>{0}</th>", item.count);
27                 ber.AppendFormat("<th>{0}</th>", item.mt_remake);
28                 ber.AppendFormat("<th>{0}</th>", item.mt_sort);
29                 ber.Append("</tr>");
30             }
31 
32 
33             ber.Append("</tbody>");
34             ber.Append("</table>");     

      咱们将数据填充完毕之后得到到的将是字符串文本,而后咱们则经过如下方法导出Excel文件

      1)通用输出流方法

        /// <summary>
        /// 输入HTTP头,而后把指定的流输出到指定的文件名,而后指定文件类型
        /// </summary>
        /// <param name="OutType">输出类型</param>
        /// <param name="FileName">文件名称</param>
        /// <param name="ExcelContent">内容</param>
        public void ExportToExcel(string OutType, string FileName, string dataSource)
        {
            lock (this)
            {
                System.Web.HttpContext.Current.Response.Charset = "UTF-8";
                System.Web.HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
                System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8).ToString());
                System.Web.HttpContext.Current.Response.ContentType = OutType;
                System.IO.StringWriter tw = new System.IO.StringWriter();
                System.Web.HttpContext.Current.Response.Output.Write(dataSource);
                System.Web.HttpContext.Current.Response.Flush();
                System.Web.HttpContext.Current.Response.End();
            }
        }

      2)调用方法获取Excel文件下载

1             string data =GetMySourceStr();
2             ExportToExcel("application/ms-excel", "导出Excel文件.xls", data);    

        这里要注意参数:

         string OutType:application/ms-excel输出方式;

        string FileName:指定文件的名称+.xls,后缀咱们最好不要更改,默认.xls便可;

        string dataSource:拼接好的数据源字符串;

       此时总体下来咱们即可以完成简单的Excel表格导出功能了。

       注:在某种特殊状况下,文档数据会存在丢失现象,如:文件传送给他人计算机,为避免这种状况只能采起导出后将内容Copy到新建的Excel文件中,所以此方法不推荐使用!(2019-01-28注)

 

 

    二、第三方插件进行Excel导出

      网上推荐使用:NPOI导出。如下是百度百科的介绍:

        NPOI是指构建在POI 3.x版本之上的一个程序,NPOI能够在没有安装Office的状况下对Word或Excel文档进行读写操做。
        POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。

      能够看出NPOI的优点在于独立性,不依赖于Office去完成一系列操做,针对Java和C#均可以使用;其官方网址:NPOI官方网站,因为暂时还未采用第三方插件进行导出,暂不对此进行介绍。而对于B\S端我我的更推荐使用此方法,由于它的一些基本操做以及相关的依赖,NPOI对于格式和生成的速度都是有必定优点的。

    (2019-01-28新增)

     去年中旬开始,针对业务调整,发现微软提供的microsoft.office.interop.excel.dll使用上虽然很方便,可是对于部署上真是一言难尽,好比以前的服务器帐号注销、速度等问题,所以后续调整便采用NPOI。

      对于NPOI的使用十分的简单且方便

     1)咱们须要安装或引用NPOI依赖包

      

     2)建立Book、Sheet、Row、Cell,NPOI在建立这些对象上很直观明了,操做起来和写文章同样

类及接口 说明
NPOI.HSSF.UserModel.HSSFWorkbook 建立Excek文件对象
NPOI.SS.UserModel.ISheet Excel中的工做簿
NPOI.SS.UserModel.IRow Excel工做部中的行
NPOI.SS.UserModel.ICell Excel工做部中的单元格

       对于建立Excel文件及简单填充数据很简单(简单的测试方法,Copy便可使用):

       

        public void G()
        {
            //建立Excel文件的对象
            HSSFWorkbook book = new HSSFWorkbook();
            //添加一个sheet
            ISheet sheet = book.CreateSheet($"工做簿1");

            //行下标记录
            int rowIndex = 0;
            //建立首行
            IRow row0 = sheet.CreateRow(rowIndex++);
            //建立单元格
            ICell cell0 = row0.CreateCell(0);
            //设置单元格内容
            cell0.SetCellValue("测试首行");

            //建立多行
            for (int i = 0; i < 10; i++)
            {
                var row = sheet.CreateRow(rowIndex++);

                //连写建立单元格并设置单元格内容 (通常这样写更好点)
                row.CreateCell(0).SetCellValue("A"+i.ToString());
            }
            
           using (FileStream st = new FileStream(AppDomain.CurrentDomain.BaseDirectory+ "test.xls", FileMode.OpenOrCreate))
            {
                book.Write(st);
            }
        }

     打开生成的文件以下图:

    2)多工做簿实现

      咱们只须要简单改一改就能够实现,Book是固定惟一的,此时咱们针对Sheet动态实现便可,通常多是手动去建立,咱们使用简单循环实现一下吧

      

        public void G()
        {
            //建立Excel文件的对象
            HSSFWorkbook book = new HSSFWorkbook();
            //添加一个sheet
            for (int index = 0; index < 3; index++)
            {
                ISheet sheet = book.CreateSheet($"工做簿{(index + 1)}");

                //行下标记录
                int rowIndex = 0;
                //建立首行
                IRow row0 = sheet.CreateRow(rowIndex++);
                //建立单元格
                ICell cell0 = row0.CreateCell(0);
                //设置单元格内容
                cell0.SetCellValue("测试首行");

                //建立多行
                for (int i = 0; i < 10; i++)
                {
                    var row = sheet.CreateRow(rowIndex++);

                    //连写建立单元格并设置单元格内容 (通常这样写更好点)
                    row.CreateCell(0).SetCellValue("A" + i.ToString());
                }
            }
            
           using (FileStream st = new FileStream(AppDomain.CurrentDomain.BaseDirectory+ "test.xls", FileMode.OpenOrCreate))
            {
                book.Write(st);
            }
        }

      

    从以上能够看出,NPOI对于Excel导出非常实用,对于NPOI其余功能暂时还没使用到,所以不作评价。

     注:由于工做中开始使用Java作服务,而Java提供了更为的Excel、Word、Pdf等文件的处理,所以后续考虑吧文件处理交给java服务程序去完成,.Net作核心功能业务。

 

 

 

     三、微软提供的microsoft.office.interop.excel.dll

    microsoft.office.interop.excel.dll是针对COM+的包装,它便于在托管代码中使用,依赖本地安装的Office软件。若是本地未安装Office则此方法不适合操做Excel以及其余相关如:

 

    这些都是微软其Office产品提供的插件,惟一的缺点则是依赖性,咱们在本地开发须要安装Office,部署在服务器也是须要安装Office,在B\S端的响应速度不是太好。

    1)DLL引用

      Microsoft.Office.Interop.Excel.dll、Microsoft.Office.core.dll

    2)引用方式

      Microsoft.Office.Interop.Excel.dll:

      

 

      经过NuGet包管理器进行安装,要与本地Office版本相对应。

      Microsoft.Office.core.dll:

      

 

      经过项目的右键>添加引用>COM>类型库 --查找-->Microsoft Office 15.0 Object Library(此处针对Office2013,其它版本能够查找相应的Microsoft Office xx.0 Object Library)。

      3)使用方法

      a.引入命名空间

        咱们能够直接引入一下命名空间:

             using Microsoft.Office.Interop.Excel;

 

         也能够这样引入:

              using OfcExcel = Microsoft.Office.Interop.Excel;

 

         这样作主要是针对较长方法的简写。

      b.方法的实现

      

 

      咱们首先建立一个ApplicationClass对象,可是发现彷佛提示了一个错误,第一次使用的时候发现代码并没用什么问题,后来查阅了一些文档和教程咱们只须要作一下操做即可以解决:

        在引用中找到Microsoft.Office.Interop.Excel查看属性->嵌入互操做类型由True改成False便可。

      

      再编写如下代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using Microsoft.Office.Interop.Excel;
 7 using System.Drawing;
 8 using System.IO;
 9 
10 namespace OutExcel
11 {
12     public class Utility
13     {
14         public static void ExcelOut()
15         {
16 
17             ApplicationClass app = new ApplicationClass();
18 
19             /*针对Excel 对象及工做簿单元格操做*/
20             Workbook workbook_1 = (Workbook)app.Workbooks.Add(true);//添加workbook
21             Worksheet worksheet_1 = (Worksheet)workbook_1.Worksheets[1];//选择第一个,即默认的工做簿
22             Range sheet_cells = worksheet_1.Cells;//工做簿单元格
23 
24             string[] columns = new string[] { "系统", "设备信息", "类别", "代码", "名称", "型号", "单位", "数量", "备注" };//列数
25             int row = 1;//默认行数
26             Range rg = sheet_cells.Range[app.Cells[row, 1], app.Cells[row, columns.Length]];//选择光标-----选择第一行 1 到10列
27             rg.Merge(false);//合并单元格
28             rg.Value2 = "内容";//设置选中单元格内容
29             row++;//下移一行
30          
31           
32             for (int index = 0; index < columns.Length; index++)
33             {
34                 sheet_cells[row, index + 1] = columns[index];//设置列标题内容
35             }
36 
37             rg = sheet_cells.Range[app.Cells[1, 1], app.Cells[row, columns.Length]];//选择标题头
38             
39             /*针对选中单元格样式设置*/
40             rg.Borders.LineStyle = XlLineStyle.xlContinuous;
41             rg.HorizontalAlignment = XlHAlign.xlHAlignCenter;
42             rg.VerticalAlignment = XlHAlign.xlHAlignCenter;
43             rg.Interior.Color = Color.Yellow;
44 
45             string path_ = AppDomain.CurrentDomain.BaseDirectory.ToString()+ "excel导出.xlsx";
46             if (File.Exists(path_))
47             {
48                 File.Delete(path_);
49             }
50             try
51             {
52                 workbook_1.SaveAs(path_, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, XlSaveAsAccessMode.xlNoChange, 1, false, Type.Missing, Type.Missing, Type.Missing); 53 54 } 55 catch (Exception ex) 56 { 57 path_ = null; 58 } 59 finally 60 { 61 workbook_1.Close(true, path_, Type.Missing); 62 workbook_1 = null; 63 } 64 } 65 } 66 }

 

       以上代码只是参考示例基础操做,你可使用过程当中对经常使用方法进行封装。

      C\S端再调用此方法时会在Debug目录下生成:

      

        B\S生成则在根目录下,咱们能够指定本身存放的路径。

      生成结果:

        

       此时针对Microsoft.Office.Interop.Excel.dll操做基本完成,而针对它的操做方法能够查阅相关文档便可实现。对于B\S调用出现的问题能够参考下面的方法解决。

2、提示的错误信息

  一、导出Excel提示信息错误

检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败,缘由是出现如下错误: 8000401a 由于配置标识不正确,系统没法开始服务器进程。请检查用户名和密码。 (异常来自 HRESULT:0x8000401A)。

 

  1)问题表现

    服务器断开链接,导出功能报错即以上错误。服务器登录,导出正常。

  2)分析

    帐号的登录与断开,表现为帐户所属权限问题。

  3)解决过程

    参照着网上的一些教程总结,得出一下方法:

      a.设置DCOM

        win+r键,输入:dcomcnfg.exe 调出=》组件服务

        选择 组件服务>计算机>个人电脑>DCOM 配置 --查找-->Microsoft Excel Application

        右键>属性>安全,设置以下

        标识设置:

        若是此时仍是报错,则能够考虑设置 标识 下列用户 即指定一个用户:

         保存配置在关闭,断开服务器链接,导出Excel不在报8000401A错误。

    问题0x8000401A 参考文献:http://blog.csdn.net/caobingyi/article/details/5175281

相关文章
相关标签/搜索