.NET Excel导出方法及其常见问题详解
摘要:.NET Excel导出方法及其常见问题详解。
一、Excel导出的实现方法
在.net 程序开发中,对于Excel文件的导出我们一共有三种导出方式:
- 利用文件输出流进行读写操作
这种方式的导出方法是比较简单就可以实现的,我们实际上是针对类似于html中table表格的输出
a.针对想要的Excel合并样式写一个table标签代码
<table border="1">
<thead>
<tr>
<th style="background-color:yellow" colspan="7" align="center">物料汇总单</th>
</tr>
<tr>
<th style="background-color:yellow">物料码</th>
<th style="background-color:yellow">物料名称</th>
<th style="background-color:yellow">型号</th>
<th style="background-color:yellow">单位</th>
<th style="background-color:yellow">数量</th>
<th style="background-color:yellow">备注</th>
<th style="background-color:yellow">排序</th>
</tr>
</thead>
<tbody>
<tr>
<th>{0}</th>
<th>{0}</th>
<th>{0}</th>
<th>{0}</th>
<th>{0}</th>
<th>{0}</th>
<th>{0}</th>
</tr>
</tbody>
</table>
table的border属性可以控制展现为Excel文件时是否显示网格线,一般如果不设置为border="1"时,导出的文件是不会生成网格线的,实际上table的各种属性和样式最终在生成为Excel文件时,都大致会以相同的格式展现出来,也就是说我们只要设计好table的样式就行,不用考虑其它的问题了。
而对于表头中的颜色设置:
<tr>
<th style="background-color:yellow">物料码</th>
<th style="background-color:yellow">物料名称</th>
<th style="background-color:yellow">型号</th>
<th style="background-color:yellow">单位</th>
<th style="background-color:yellow">数量</th>
<th style="background-color:yellow">备注</th>
<th style="background-color:yellow">排序</th>
</tr>
有不少人会疑惑:为什么不在<tr>设置background-color不是更方便?
<tr style="background-color:yellow">
<th>物料码</th>
<th>物料名称</th>
<th>型号</th>
<th>单位</th>
<th>数量</th>
<th>备注</th>
<th>排序</th>
</tr>
这样做的确省了不少事,但是这样做当转化为Excel文件时效果就不是很相同了。
我们理想中的效果:
但实际上会展示为:
转化为Excel文件时并未在固定的列数设置背景颜色,而是整行都被设置为黄色。针对其他的细节我们可以慢慢的去尝试,去调整。
此时我们先要针对现有的table标签进行数据填充:
ber.Append("<table border=\"1\">");
ber.Append("<thead>");
ber.Append("<tr><th style=\"background-color:yellow\" colspan=\"7\" align=\"center\">物料汇总单</th></tr>"); ber.Append("<tr>"); ber.Append("<th style=\"background-color:yellow\">物料码</th>");
ber.Append("<th style=\"background-color:yellow\">物料名称</th>");
ber.Append("<th style=\"background-color:yellow\">型号</th>");
ber.Append("<th style=\"background-color:yellow\">单位</th>");
ber.Append("<th style=\"background-color:yellow\">数量</th>");
ber.Append("<th style=\"background-color:yellow\">备注</th>");
ber.Append("<th style=\"background-color:yellow\">排序</th>"); ber.Append("</tr>");
ber.Append("</thead>"); ber.Append("<tbody>");
foreach (ExcelTMaterial item in all_models)
{
ber.Append("<tr>");
ber.AppendFormat("<th>{0}</th>", item.mt_code);
ber.AppendFormat("<th>{0}</th>", item.mt_name);
ber.AppendFormat("<th>{0}</th>", item.mt_model);
ber.AppendFormat("<th>{0}</th>", item.mt_unit);
ber.AppendFormat("<th>{0}</th>", item.count);
ber.AppendFormat("<th>{0}</th>", item.mt_remake);
ber.AppendFormat("<th>{0}</th>", item.mt_sort);
ber.Append("</tr>");
} ber.Append("</tbody>");
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文件下载
string data =GetMySourceStr();
ExportToExcel("application/ms-excel", "导出Excel文件.xls", data);
这里要注意参数:
string OutType:application/ms-excel输出方式;
string FileName:指定文件的名称+.xls,后缀我们最好不要更改,默认.xls即可;
string dataSource:拼接好的数据源字符串;
此时整体下来我们便可以完成简单的Excel表格导出功能了。
注:在某种特殊情况下,文档数据会存在丢失现象,如:文件传送给他人计算机,为避免这种情况只能采取导出后将内容Copy到新建的Excel文件中,因此此方法不推荐使用!(2019-01-28注)
2、第三方插件进行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 = ;
//创建首行
IRow row0 = sheet.CreateRow(rowIndex++);
//创建单元格
ICell cell0 = row0.CreateCell();
//设置单元格内容
cell0.SetCellValue("测试首行"); //创建多行
for (int i = ; i < ; i++)
{
var row = sheet.CreateRow(rowIndex++); //连写创建单元格并设置单元格内容 (一般这样写更好点)
row.CreateCell().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 = ; index < ; index++)
{
ISheet sheet = book.CreateSheet($"工作簿{(index + 1)}"); //行下标记录
int rowIndex = ;
//创建首行
IRow row0 = sheet.CreateRow(rowIndex++);
//创建单元格
ICell cell0 = row0.CreateCell();
//设置单元格内容
cell0.SetCellValue("测试首行"); //创建多行
for (int i = ; i < ; i++)
{
var row = sheet.CreateRow(rowIndex++); //连写创建单元格并设置单元格内容 (一般这样写更好点)
row.CreateCell().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做核心功能业务。
3、微软提供的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即可。
再编写以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Excel;
using System.Drawing;
using System.IO; namespace OutExcel
{
public class Utility
{
public static void ExcelOut()
{ ApplicationClass app = new ApplicationClass(); /*针对Excel 对象及工作簿单元格操作*/
Workbook workbook_1 = (Workbook)app.Workbooks.Add(true);//添加workbook
Worksheet worksheet_1 = (Worksheet)workbook_1.Worksheets[];//选择第一个,即默认的工作簿
Range sheet_cells = worksheet_1.Cells;//工作簿单元格 string[] columns = new string[] { "系统", "设备信息", "类别", "代码", "名称", "型号", "单位", "数量", "备注" };//列数
int row = ;//默认行数
Range rg = sheet_cells.Range[app.Cells[row, ], app.Cells[row, columns.Length]];//选择光标-----选择第一行 1 到10列
rg.Merge(false);//合并单元格
rg.Value2 = "内容";//设置选中单元格内容
row++;//下移一行 for (int index = ; index < columns.Length; index++)
{
sheet_cells[row, index + ] = columns[index];//设置列标题内容
} rg = sheet_cells.Range[app.Cells[, ], app.Cells[row, columns.Length]];//选择标题头 /*针对选中单元格样式设置*/
rg.Borders.LineStyle = XlLineStyle.xlContinuous;
rg.HorizontalAlignment = XlHAlign.xlHAlignCenter;
rg.VerticalAlignment = XlHAlign.xlHAlignCenter;
rg.Interior.Color = Color.Yellow; string path_ = AppDomain.CurrentDomain.BaseDirectory.ToString()+ "excel导出.xlsx";
if (File.Exists(path_))
{
File.Delete(path_);
}
try
{
workbook_1.SaveAs(path_, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, XlSaveAsAccessMode.xlNoChange, , false, Type.Missing, Type.Missing, Type.Missing); }
catch (Exception ex)
{
path_ = null;
}
finally
{
workbook_1.Close(true, path_, Type.Missing);
workbook_1 = null;
}
}
}
}
以上代码只是参考示例基础操作,你可以使用过程中对常用方法进行封装。
C\S端再调用此方法时会在Debug目录下生成:
B\S生成则在根目录下,我们可以指定自己存放的路径。
生成结果:
此时针对Microsoft.Office.Interop.Excel.dll操作基本完成,而针对它的操作方法可以查阅相关文档即可实现。对于B\S调用出现的问题可以参考下面的方法解决。
二、提示的错误信息
1、导出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
.NET Excel导出方法及其常见问题详解的更多相关文章
- cloudemanager安装时出现8475 MainThread agent ERROR Heartbeating to 192.168.30.1:7182 failed问题解决方法(图文详解)
不多说,直接上干货! 问题详情 解决这个问题简单的,是因为有进程占用了.比如 # ps aux | grep super root ? Ss : : /opt/cm-/lib64/cmf/agen ...
- cloudemanager安装时出现failed to receive heartbeat from agent问题解决方法(图文详解)
不多说,直接上干货! 安装cdh5到最后报如下错误: 安装失败,无法接受agent发出的检测信号. 确保主机名称正确 确保端口7182可在cloudera manager server上访问(检查防火 ...
- Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量
Python进阶----线程基础,开启线程的方式(类和函数),线程VS进程,线程的方法,守护线程,详解互斥锁,递归锁,信号量 一丶线程的理论知识 什么是线程: 1.线程是一堆指令,是操作系统调度 ...
- C#类、对象、方法和属性详解
C#类.对象.方法和属性详解 一.相关概念: 1.对象:现实世界中的实体(世间万物皆对象) 2.类:具有相似属性和方法的对象的集合 3.面向对象程序设计的特点:封装 继承 多态 4.对象的三要素:属性 ...
- 封装excel导出方法
封装读取excel内容方法 /** * 获取Excel内容 * @param type $filename * @return type */ public function getExcelCont ...
- $.ajax()方法所有参数详解;$.get(),$.post(),$.getJSON(),$.ajax()详解
[一]$.ajax()所有参数详解 url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注 ...
- java集合的方法及使用详解
一.java集合的分类及相互之间的关系 Collection接口:向下提供了List和Set两个子接口 |------List接口:存储有序的,存储元素可以重复 |------ArrayList(主要 ...
- Oracle sqlldr导入导出txt数据文件详解
一.sqlldr导入txt 1.预备 a).txt文件 这里要保存成无签名的UTF-8 b).oracle建表 2.编写控制文件input_test.ctl LOAD DATA CHARACTERSE ...
- creo2.0安装方法和图文详解教程
Creo2.0是由PTC公司2012年8月底推出的全新CAD设计软件包,整合了PTC公司的三个软件Pro/Engineer的参数化技术.CoCreate的直接建模技术和ProductView的三维可视 ...
随机推荐
- GBK和UTF8的区别
GBK的文字编码是双字节来表示的,即不论中.英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1. UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中 ...
- python pip升级失败
接上篇,使用命令:python -m pip install --upgrade pip 发现pip升级时报错,无法升级 解决方法: 1.使用如下命令,查看具体失败原因: pip install -- ...
- Maven01——简介、安装配置、入门程序、项目构建和依赖管理
1 Maven的简介 1.1 什么是maven 是apache下的一个开源项目,是纯java开发,并且只是用来管理java项目的 Svn eclipse maven量级 1.2 Maven好处 同 ...
- BootKit病毒——“异鬼Ⅱ”的前世今生
七月底,一种名为"异鬼Ⅱ"的木马在全网大肆传播.一个多月过去了,风声渐渐平息,之前本来准备专门就这个木马写一篇博客的,结果拖到现在,幸好时间隔得还不算太久.闲话不多说,回到正题. ...
- Java基础学习 —— 线程
线程: 多线程的好处:解决了在一个进程中同时执行多个任务代码的问题. 自定义线程的创建方式: 1.自定一个类继承thread类,重写thread的run方法 吧自定义线程的任务代码写在run方法内,创 ...
- poj 3013 SPFA
首先看题看的很懵.. 然后这题直接没想用Djstra做 TLE了.看discuss,Dijstra要用堆优化,也可以用SPFA做. 这里在网上找了这两种做法的区别,点多稠密图用Dij,以为它是操作点的 ...
- PS小实验-去除水印
PS小实验-去除水印 水印是一些品牌商覆盖在图片或视频上的一个商标logo或小文本,比如大家最讨厌的百度logo,作者本人也是比较讨厌水印的,让好端端的一张图片变得美中不足. 个人觉得用photosh ...
- 【★】微信之于QQ的市场哲学
2016年的移动app下载排行榜出炉后,我们惊奇发现,前十名中有6个应用软件来自腾讯公司.而前两名毋庸置疑是远远碾压第三名的微信与qq.这让我们看到社交app的重要性的同时也回到了那个原始的问题:腾讯 ...
- Java Collections 源码分析
Java Collections API源码分析 侯捷老师剖析了不少Framework,如MFC,STL等.侯老师有句名言: 源码面前,了无秘密 这句话还在知乎引起广泛讨论. 我对教授程序设计的一点想 ...
- 201521123113《Java程序设计》第7周学习总结
1. 本周学习总结 2. 书面作业 Q1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 contains源代码: public boolean contains( ...