声明:我是用Unity写的,以下代码在5.5.2中运行通过,unity都能过了,所以C#肯定没问题的…………..NPOI的dll在网上找找吧。。。
NPOI简介
http://blog.youkuaiyun.com/pan_junbiao/article/details/39717443
1.1 什么是NPOI
NPOI,顾名思义,就是POI的.NET版本。那POI又是什么呢?POI是一套用Java写成的库,能够帮助开发者在没有安装微软Office的情况下读写Office 97-2003的文件,支持的文件格式包括xls, doc, ppt等。在本文发布时,POI的最新版本是3.5 beta 6。
NPOI 1.x是基于POI 3.x版本开发的,与poi 3.2对应的版本是NPOI 1.2,目前最新发布的版本是1.2.1,在该版本中仅支持读写Excel文件和Drawing格式,其他文件格式将在以后的版本中得到支持。
1.2 版权说明
NPOI采用的是Apache 2.0许可证(poi也是采用这个许可证),这意味着它可以被用于任何商业或非商业项目,你不用担心因为使用它而必须开放你自己的源代码,所以它对于很多从事业务系统开发的公司来说绝对是很不错的选择。
当然作为一个开源许可证,肯定也是有一些义务的,例如如果你在系统中使用NPOI,你必须保留NPOI中的所有声明信息。对于源代码的任何修改,必须做出明确的标识。
完整的apache 2.0许可证请见http://www.phpx.com/man/Apache-2/license.html
1.3 相关资源
官方网站:http://npoi.codeplex.com/
POIFS Browser 1.2
下载地址:http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24305
1.4 团队介绍
Tony Qu来自于中国上海,是这个项目的发起人和开发人员,时区是GMT+8,2008年9月开始了NPOI的开发,负责NPOI所有底层库的开发、测试和bug修复。
个人blog地址为http://tonyqus.cnblogs.com/
HüseyinTüfekçilerli来自于土耳其的伊斯坦布尔,也是这个项目的开发人员,时区是GMT+2,2008年11月参与了NPOI的开发,主要负责POIFS Browser 1.0的开发工作。
个人blog地址为http://huseyint.com/
aTao.Xiang,来自中国,2009年8月开始参与该项目,主要参与了NPOI 1.2中文版的撰写工作和推广工作
个人blog地址为http://www.cnblogs.com/atao/
1.5 回顾与展望
目前POI版本中的HWPF(用于Word的读写库)还不是很稳定,并非正式发布版本,且负责HWPF的关键开发人员已经离开,所以NPOI可能考虑自己重新开发HWPF。另外,目前微软正在开发Open XML Format SDK,NPOI可能会放弃对ooxml的支持,当然这取决于用户的需求和Open XML Format SDK的稳定性和速度。从目前而言,NPOI有几大优势
第一,完全基于.NET 2.0,而非.NET 3.0/3.5。
第二,读写速度快(有个国外的兄弟回复说,他原来用ExcelPackage生成用了4-5个小时,现在只需要4-5分钟)
第三,稳定性好(相对于用Office OIA而言,毕竟那东西是基于Automation做的,在Server上跑个Automation的东西,想想都觉得可怕),跑过了将近1000个测试用例(来自于POI的testcase目录)
第四,API简单易用,当然这得感谢POI的设计师们
第五,完美支持Excel 2003格式(据说myxls无法正确读取xls模板,但NPOI可以),以后也许是所有Office 2003格式
希望NPOI把这些优势继续发扬下去,这样NPOI才会更有竞争力。
1.6 NPOI 1.2中各Assembly的作用
NPOI目前有好几个assembly,每个的作用各有不同,开发人员可以按需加载相应的assembly。在这里大概罗列一下:
NPOI.Util 基础辅助库
NPOI.POIFS OLE2格式读写库
NPOI.DDF Microsoft Drawing格式读写库
NPOI.SS Excel公式计算库
NPOI.HPSF OLE2的Summary Information和Document Summary Information属性读写库
NPOI.HSSF Excel BIFF格式读写库
使用NPOI写Excel——插入数据
public static void WriteExcel(List<MyRebar> list)
{
HSSFWorkbook workbook2003 = new HSSFWorkbook(); //新建工作簿
workbook2003.CreateSheet("Sheet1"); //新建1个Sheet工作表
HSSFSheet SheetOne = (HSSFSheet)workbook2003.GetSheet("Sheet1"); //获取名称为Sheet1的工作表
HSSFCell[] SheetCell;//单元格//先申明一些变量
CellRangeAddress range;//合并
IRow row; //行
//对工作表先添加行,下标从0开始
for (int k = 0; k < list.Count; k++)
{
row = SheetOne.CreateRow(k); //创建10行
row.HeightInPoints = 40;//设置单元格的高度
row = (HSSFRow)SheetOne.GetRow(k); //获取Sheet1工作表的首行
SheetCell = new HSSFCell[10]; //对每一行创建10个单元格
for (int i = 0; i < 10; i++)
{
SheetCell[i] = (HSSFCell)row.CreateCell(i); //为第一行创建10个单元格
}
SheetCell[0].SetCellValue(list[k].SerialNumber);//创建之后就可以赋值了
SheetCell[1].SetCellValue(list[k].CardNum);
SheetCell[2].SetCellValue(list[k].Name);
SheetCell[6].SetCellValue(list[k].Length);
SheetCell[7].SetCellValue(list[k].Quantity);
SheetCell[8].SetCellValue(list[k].Weight);
SheetCell[9].SetCellValue(list[k].Reamarks);
HSSFCellStyle fCellStyle = (HSSFCellStyle)workbook2003.CreateCellStyle();//创建单元格的一些格式
HSSFFont ffont = (HSSFFont)workbook2003.CreateFont();
ffont.FontHeight = 15 * 15;//字体的高度及宽度
ffont.FontName = "宋体";//字体
ffont.IsBold = true;//是否加粗
fCellStyle.FillBackgroundColor = HSSFColor.Red.Index;//改变背景颜色?没有效果,使用另一个插件时候是可以的
fCellStyle.SetFont(ffont);
SheetCell[0].CellStyle = fCellStyle;//给这个单元格添加刚刚写好的格式
range = new CellRangeAddress(k, k, 3, 5);//想要合并的范围(参数分别是单元格的左上角坐标(行X,列Y),右下角的坐标(行X,列Y))
SheetOne.AddMergedRegion(range);
SheetCell[0].CellStyle.Alignment = HorizontalAlignment.Center;//对齐方式,只能有一种?二种以上会覆盖之前的
SheetCell[0].CellStyle.VerticalAlignment = VerticalAlignment.Center;
}
index = PlayerPrefs.GetInt("KEY");//测试
index++;
PlayerPrefs.SetInt("KEY", index);
FileStream file2003 = new FileStream(@"E:\Excel2003" + index + ".xls", FileMode.Create);//创建一个文件
workbook2003.Write(file2003);
file2003.Close();
workbook2003.Close();//保存
Application.OpenURL(@"E:\Excel2003" + index + ".xls");//执行创建好的文件
}
插入图片
插这个图片真是累得要死,二张图片以上的时候还会覆盖 ,找了好久资料才找到,太多了。。。即便如此,这些参数也是试了好多次才知道是什么意思。。。很抱歉,实在记不清楚看得哪个大神写的帖子了
/// <summary>
/// 向excel添加一个图片
/// </summary>
/// <param name="workbook">excel</param>
/// <param name="sheet1">sheet</param>
/// <param name="pngPath">图片的名字,没有后缀</param>
/// <param name="x1">excel中图片的左上角的单元格行</param>
/// <param name="y1">excel中图片的右上角的单元格行</param>
/// <param name="x2">excel中图片的左下角的单元格列</param>
/// <param name="y2">excel中图片的右下角的单元格列</param>
public static void AddPicture(HSSFWorkbook workbook, HSSFSheet sheet1, string pngPath, int x1, int y1, int x2, int y2)
{
//将图片加入Workbook
byte[] bytes = File.ReadAllBytes(@"D:\Work001\Work001\Assets\Resources\Sprites2\" + pngPath + ".png");//读取图片转换为流
int pictureIdx1 = workbook.AddPicture(bytes, PictureType.JPEG);//图片的格式?好像没什么用,换了几种格式都是一样的
IDrawing patriarch = sheet1.CreateDrawingPatriarch(); //获取存在的Sheet,必须在AddPicture之后
HSSFClientAnchor anchor;
anchor = new HSSFClientAnchor(0, 0, 1023, 0, x1, y1, x2, y2);//插入图片
patriarch.CreatePicture(anchor, pictureIdx1);
}
完整代码
using System.Collections.Generic;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using System.IO;
using UnityEngine;
using NPOI.SS.Util;
using NPOI.HSSF.Util;
public class MakeExcel : MonoBehaviour
{
public static int index = 0;
/// <summary>
/// 向excel添加一个图片
/// </summary>
/// <param name="workbook">excel</param>
/// <param name="sheet1">sheet</param>
/// <param name="pngPath">图片的名字,没有后缀</param>
/// <param name="x1">excel中图片的左上角的单元格行</param>
/// <param name="y1">excel中图片的右上角的单元格行</param>
/// <param name="x2">excel中图片的左下角的单元格列</param>
/// <param name="y2">excel中图片的右下角的单元格列</param>
public static void AddPicture(HSSFWorkbook workbook, HSSFSheet sheet1, string pngPath, int x1, int y1, int x2, int y2)
{
//将图片加入Workbook
byte[] bytes = File.ReadAllBytes(@"D:\Work001\Work001\Assets\Resources\Sprites2\" + pngPath + ".png");//读取图片转换为流
int pictureIdx1 = workbook.AddPicture(bytes, PictureType.JPEG);//图片的格式?好像没什么用,换了几种格式都是一样的
IDrawing patriarch = sheet1.CreateDrawingPatriarch(); //获取存在的Sheet,必须在AddPicture之后
HSSFClientAnchor anchor;
anchor = new HSSFClientAnchor(0, 0, 1023, 0, x1, y1, x2, y2);//插入图片
patriarch.CreatePicture(anchor, pictureIdx1);
}
public static void WriteExcel(List<MyRebar> list)
{
HSSFWorkbook workbook2003 = new HSSFWorkbook(); //新建工作簿
workbook2003.CreateSheet("Sheet1"); //新建1个Sheet工作表
HSSFSheet SheetOne = (HSSFSheet)workbook2003.GetSheet("Sheet1"); //获取名称为Sheet1的工作表
HSSFCell[] SheetCell;//单元格//先申明一些变量
CellRangeAddress range;//合并
IRow row; //行
//对工作表先添加行,下标从0开始
for (int k = 0; k < list.Count; k++)
{
row = SheetOne.CreateRow(k); //创建10行
row.HeightInPoints = 40;//设置单元格的高度
row = (HSSFRow)SheetOne.GetRow(k); //获取Sheet1工作表的首行
SheetCell = new HSSFCell[10]; //对每一行创建10个单元格
for (int i = 0; i < 10; i++)
{
SheetCell[i] = (HSSFCell)row.CreateCell(i); //为第一行创建10个单元格
}
SheetCell[0].SetCellValue(list[k].SerialNumber);//创建之后就可以赋值了
SheetCell[1].SetCellValue(list[k].CardNum);
SheetCell[2].SetCellValue(list[k].Name);
SheetCell[6].SetCellValue(list[k].Length);
SheetCell[7].SetCellValue(list[k].Quantity);
SheetCell[8].SetCellValue(list[k].Weight);
SheetCell[9].SetCellValue(list[k].Reamarks);
HSSFCellStyle fCellStyle = (HSSFCellStyle)workbook2003.CreateCellStyle();//创建单元格的一些格式
HSSFFont ffont = (HSSFFont)workbook2003.CreateFont();
ffont.FontHeight = 15 * 15;//字体的高度及宽度
ffont.FontName = "宋体";//字体
ffont.IsBold = true;//是否加粗
fCellStyle.FillBackgroundColor = HSSFColor.Red.Index;//改变背景颜色?没有效果,使用另一个插件时候是可以的
fCellStyle.SetFont(ffont);
SheetCell[0].CellStyle = fCellStyle;//给这个单元格添加刚刚写好的格式
range = new CellRangeAddress(k, k, 3, 5);//想要合并的范围(参数分别是单元格的左上角坐标(行X,列Y),右下角的坐标(行X,列Y))
SheetOne.AddMergedRegion(range);
SheetCell[0].CellStyle.Alignment = HorizontalAlignment.Center;//对齐方式,只能有一种?二种以上会覆盖之前的
SheetCell[0].CellStyle.VerticalAlignment = VerticalAlignment.Center;
}
index = PlayerPrefs.GetInt("KEY");//测试
index++;
PlayerPrefs.SetInt("KEY", index);
FileStream file2003 = new FileStream(@"E:\Excel2003" + index + ".xls", FileMode.Create);//创建一个文件
workbook2003.Write(file2003);
file2003.Close();
workbook2003.Close();//保存
Application.OpenURL(@"E:\Excel2003" + index + ".xls");//执行创建好的文件
}
}
———————————-
精确设置列宽
* 参数只支持int所以还不是特别精确,,,NPOI生成Excel文件时,设置列宽只有一函数sheet.SetColumnWidth(),该函数有两个参数,第一个是行索引,第二个是行列宽。但是在实际使用过程中,设置的行列宽与产生的Excel文件行列宽不一致。经过实际测试,只需要加一个常量即可:*
sheet.SetColumnWidth(0, 16 * 256 + 200); // 200为常量,这样即可控制列宽为16
原文:
http://blog.youkuaiyun.com/echoshinian100/article/details/46764487
设置对齐方式
HSSFCellStyle fCellStyle;
HSSFFont ffont;
fCellStyle = (HSSFCellStyle)workbook2003.CreateCellStyle();
ffont = (HSSFFont)workbook2003.CreateFont();
ffont.FontHeight = 15 * 15;
ffont.FontName = "宋体";
ffont.Color = HSSFColor.Red.Index;
ffont.IsBold = fontIsBold;
fCellStyle.FillForegroundColor = 40;
fCellStyle.SetFont(ffont);
fCellStyle.Alignment = hori;
fCellStyle.VerticalAlignment = VerticalAlignment.Center;
SheetCell[index].CellStyle = fCellStyle;
边框线设置
fCellStyle.BorderBottom = BorderStyle.Thin;
fCellStyle.BorderLeft = BorderStyle.Thin;
fCellStyle.BorderRight = BorderStyle.Thin;
fCellStyle.BorderTop = BorderStyle.Thin;
参考:
http://bbs.youkuaiyun.com/topics/390960435?locationNum=8&fps=1
样式的枚举
注意
样式的数量是有限的,多了会超出限制,没必要每一个单元格都去createstyle 可以在循环外面 创建几种需要的样式出来 用的时候直接 cellstyle=你创建好的样式,样式创建的不要太多,使用一个变量循环赋值就可以了,否则会报空?忘记截图了
读取Excel并写入数据
上边都是直接创建的一个表,上边都写过读取也就没什么难度了
using System.Collections.Generic;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using System.IO;
using UnityEngine;
public class MakeExcel
{
public static void WriteExcel(string filePath)
{
IWorkbook book = null; //置空
FileStream fs = File.OpenRead(filePath);//打开表
book = new HSSFWorkbook(fs);//读取表
fs.Close();
ISheet sheet = book.GetSheetAt(0); //获取名称为第0个工作表
IRow row = sheet.GetRow(0); //读取当前行数据
for (int i = 0; i <= sheet.LastRowNum; i++) //LastRowNum 是当前表的总行数-1(注意)
{
row = sheet.GetRow(i); //读取当前行数据
if (row != null)
{
string s = "";
for (int j = 0; j < row.LastCellNum; j++)//LastCellNum 是当前行的总列数
{
//读取该行的第j列数据
string value = row.GetCell(j).ToString();
s += value;//对每一行的列的数据累加,得到一行的数据
}
Debug.Log(s);//一行的数据
}
}
}
}