C#调用NPOI组件读取excel表格数据转为datatable写入word表格中并向word中插入图片/文字/书签 获得书签列表
调用word的com组件将400条数据导入word表格中耗时10分钟简直不能忍受,使用NPOI组件耗时4秒钟.但是NPOI中替换书签内容的功能不知道是不支持还是没找到.
辅助类 Excel表格数据与DataTable互转:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using NPOI.SS.UserModel;
- using NPOI.XSSF.UserModel;
- using NPOI.HSSF.UserModel;
- using System.IO;
- using System.Data;
- namespace Utils
- {
- //http://www.cnblogs.com/luxiaoxun/p/3374992.html
- public class ExcelDataTableConverter : IDisposable
- {
- private string fileName = null; //文件名
- private IWorkbook workbook = null;
- private FileStream fs = null;
- private bool disposed;
- public ExcelDataTableConverter(string fileName)
- {
- this.fileName = fileName;
- disposed = false;
- }
- /// <summary>
- /// 将DataTable数据导入到excel中
- /// </summary>
- /// <param name="data">要导入的数据</param>
- /// <param name="isColumnWritten">DataTable的列名是否要导入</param>
- /// <param name="sheetName">要导入的excel的sheet的名称</param>
- /// <returns>导入数据行数(包含列名那一行)</returns>
- public int DataTableToExcel(DataTable data, string sheetName, bool isColumnWritten)
- {
- int i = 0;
- int j = 0;
- int count = 0;
- ISheet sheet = null;
- fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
- if (fileName.IndexOf(".xlsx") > 0) // 2007版本
- workbook = new XSSFWorkbook();
- else if (fileName.IndexOf(".xls") > 0) // 2003版本
- workbook = new HSSFWorkbook();
- try
- {
- if (workbook != null)
- {
- sheet = workbook.CreateSheet(sheetName);
- }
- else
- {
- return -1;
- }
- if (isColumnWritten == true) //写入DataTable的列名
- {
- IRow row = sheet.CreateRow(0);
- for (j = 0; j < data.Columns.Count; ++j)
- {
- row.CreateCell(j).SetCellValue(data.Columns[j].ColumnName);
- }
- count = 1;
- }
- else
- {
- count = 0;
- }
- for (i = 0; i < data.Rows.Count; ++i)
- {
- IRow row = sheet.CreateRow(count);
- for (j = 0; j < data.Columns.Count; ++j)
- {
- row.CreateCell(j).SetCellValue(data.Rows[i][j].ToString());
- }
- ++count;
- }
- workbook.Write(fs); //写入到excel
- return count;
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception: " + ex.Message);
- return -1;
- }
- }
- /// <summary>
- /// 将excel中的数据导入到DataTable中
- /// </summary>
- /// <param name="sheetName">excel工作薄sheet的名称</param>
- /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>
- /// <returns>返回的DataTable</returns>
- public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn)
- {
- ISheet sheet = null;
- DataTable data = new DataTable();
- int startRow = 0;
- try
- {
- fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
- if (fileName.IndexOf(".xlsx") > 0) // 2007版本
- workbook = new XSSFWorkbook(fs);
- else if (fileName.IndexOf(".xls") > 0) // 2003版本
- workbook = new HSSFWorkbook(fs);
- if (sheetName != null)
- {
- sheet = workbook.GetSheet(sheetName);
- if (sheet == null) //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet
- {
- sheet = workbook.GetSheetAt(0);
- }
- }
- else
- {
- sheet = workbook.GetSheetAt(0);
- }
- if (sheet != null)
- {
- IRow firstRow = sheet.GetRow(0);
- int cellCount = firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数
- if (isFirstRowColumn)
- {
- for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
- {
- ICell cell = firstRow.GetCell(i);
- if (cell != null)
- {
- string cellValue = cell.StringCellValue;
- if (cellValue != null)
- {
- DataColumn column = new DataColumn(cellValue);
- data.Columns.Add(column);
- }
- }
- }
- startRow = sheet.FirstRowNum + 1;
- }
- else
- {
- startRow = sheet.FirstRowNum;
- }
- //最后一列的标号
- int rowCount = sheet.LastRowNum;
- for (int i = startRow; i <= rowCount; ++i)
- {
- IRow row = sheet.GetRow(i);
- if (row == null) continue; //没有数据的行默认是null
- DataRow dataRow = data.NewRow();
- for (int j = row.FirstCellNum; j < cellCount; ++j)
- {
- if (row.GetCell(j) != null) //同理,没有数据的单元格都默认是null
- {
- //dataRow[j] = row.GetCell(j).ToString(); //19890603会显示成MIDB(C2,7,6)
- dataRow[j] = row.GetCell(j).StringCellValue;
- }
- }
- data.Rows.Add(dataRow);
- }
- }
- return data;
- }
- catch (Exception ex)
- {
- Console.WriteLine("Exception: " + ex.Message);
- return null;
- }
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (!this.disposed)
- {
- if (disposing)
- {
- if (fs != null)
- fs.Close();
- }
- fs = null;
- disposed = true;
- }
- }
- }
- }
调用:
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using NPOI.XWPF.UserModel;
- using NPOI.OpenXmlFormats.Wordprocessing;
- using System.IO;
- namespace WordNPOI
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- XWPFDocument doc = new XWPFDocument();
- private void Form1_Load(object sender, EventArgs e)
- {
- }
- private void button1_Click(object sender, EventArgs e)
- {
- Utils.ExcelDataTableConverter edc = new Utils.ExcelDataTableConverter("60岁以上人员.xlsx");
- DataTable dt = edc.ExcelToDataTable("sheet1", true);
- int rowCount = dt.Rows.Count;
- int columnCount = dt.Columns.Count;
- //创建段落对象
- XWPFParagraph p1 = doc.CreateParagraph();
- //创建run对象
- //本节提到的所有样式都是基于XWPFRun的,
- //你可以把XWPFRun理解成一小段文字的描述对象,
- //这也是Word文档的特征,即文本描述性文档。
- //来自Tony Qu http://tonyqus.sinaapp.com/archives/609
- XWPFRun r1 = p1.CreateRun();
- r1.SetBold(true);
- r1.SetText("数据导出demo");
- r1.SetBold(true);
- r1.FontFamily = "宋体";
- r1.FontSize = 26;
- //r1.SetFontFamily("Arial");//设置雅黑字体
- //创建表格对象,行 列
- XWPFTable table = doc.CreateTable(rowCount + 1, columnCount);
- //添加列头
- for (int i = 0; i < columnCount; i++)
- {
- var ctt = table.GetRow(0).GetCell(i).GetCTTc();
- var tcPr = ctt.AddNewTcPr();
- tcPr.tcW = new CT_TblWidth();
- tcPr.tcW.w = "6000";//单元格宽 单位是EMU,1英寸= 914400 EMU http://bbs.csdn.net/topics/390906055
- tcPr.tcW.type = ST_TblWidth.dxa;
- //table.SetColumnWidth(i, 5500); //无效果 特定数字5500又太大 貌似要设置为n*256
- //设置单元格字体 样式 http://www.tuicool.com/articles/JFZzUj
- var p = table.GetRow(0).GetCell(i).AddParagraph();
- XWPFRun r = p.CreateRun();
- r.FontFamily = "宋体";
- r.FontSize = 10;
- r.SetBold(true);
- r.SetText(dt.Columns[i].ColumnName);
- }
- for (int i = 1; i < rowCount; i++)
- {
- for (int j = 0; j < columnCount; j++)
- {
- string tem = dt.Rows[i][j].ToString();
- table.GetRow(i).GetCell(j).SetText(dt.Rows[i][j].ToString());
- }
- }
- //插入图片
- var gfs = new FileStream("1.png", FileMode.Open, FileAccess.Read);
- var gp = doc.CreateParagraph();
- gp.Alignment = ParagraphAlignment.CENTER; //居中
- var gr = gp.CreateRun();
- gr.AddPicture(gfs, (int)PictureType.JPEG, "1.png", 1000000, 1000000); //1000000 差不多100像素多一点
- gfs.Close();
- var gp1 = doc.CreateParagraph();
- gp1.CreateRun().SetText("The End");
- //bookmark书签
- var items = doc.Paragraphs[0].Document.BodyElements;
- //CT_Bookmark b = new CT_Bookmark();
- //CT_Bookmark ctBookmark = doc.Paragraphs[0].GetBookmarkStartArray(0);
- //foreach (CT_Bookmark bookmark in doc.Paragraphs[0].GetCTP().GetBookmarkStartList()) //网上的代码,发现找不到这个方法
- //{
- // Assert.AreEqual("poi", bookmark.name);
- //}
- //书签0开始
- int m_bookId = 0;//同一段内有多个书签,需要不同的Id,不同段的书签Id可以相同
- CT_P m_p = doc.Document.body.AddNewP();
- m_p.AddNewPPr().AddNewJc().val = ST_Jc.both;
- m_p.AddNewPPr().AddNewSpacing().line = "400";//固定行距20磅
- m_p.AddNewPPr().AddNewSpacing().lineRule = ST_LineSpacingRule.exact;
- m_p.Items = new System.Collections.ArrayList();
- CT_Bookmark m_ctbook1 = new CT_Bookmark();
- m_bookId = m_p.Items.Count;
- m_ctbook1.id = m_bookId.ToString(); //"0";
- m_ctbook1.name = "NPOI1";//书签名,超链接用
- m_p.Items.Add(m_ctbook1);
- m_p.ItemsElementName = new List<ParagraphItemsChoiceType>();
- m_p.ItemsElementName.Add(ParagraphItemsChoiceType.bookmarkStart);
- m_p.AddNewR().AddNewT().Value = "1、NPOI介绍";
- //书签0结束
- m_ctbook1 = new CT_Bookmark();
- m_ctbook1.id = m_bookId.ToString();//"0";
- m_p.Items.Add(m_ctbook1);
- m_p.ItemsElementName.Add(ParagraphItemsChoiceType.bookmarkEnd);
- //获得书签
- int pcount = doc.Document.body.ItemsElementName.Count();
- List<CT_Bookmark> bkList = new List<CT_Bookmark>();
- for (int i = 0; i < pcount; i++)
- {
- var ctp = doc.Document.body.GetPArray(i);
- if (ctp!=null)
- {
- var tempBookMarkList = ctp.GetBookmarkStartList();
- bkList.AddRange(tempBookMarkList);
- }
- }
- foreach (var bookMark in bkList)
- {//替换书签内容?????????????????找不到示例代码还是不支持此功能?
- bookMark.colFirst = "1";
- bookMark.colLast = "2";
- bookMark.displacedByCustomXmlSpecified = true;
- MessageBox.Show(bookMark.name);
- }
- //保存文件到磁盘
- FileStream out1 = new FileStream("simpleTable.docx", FileMode.OpenOrCreate);
- doc.Write(out1);
- out1.Close();
- MessageBox.Show("done");
- }
- }
- }
关于宽高设置:
http://www.oschina.net/code/snippet_222150_9780
- 在Excel中,单元格的宽度其实就是列的宽度,因为Excel假设这一列的单元格的宽度肯定一致。所以要设置单元格的宽度,我们就得从列的宽度下手,HSSFSheet有个方法叫SetColumnWidth,共有两个参数:一个是列的索引(从0开始),一个是宽度。
- 现在假设你要设置B列的宽度,就可以用下面的代码:
- HSSFWorkbook hssfworkbook = new HSSFWorkbook();
- HSSFSheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
- sheet1.SetColumnWidth(1, 100 * 256);
- 这里你会发现一个有趣的现象,SetColumnWidth的第二个参数要乘以256,这是怎么回事呢?其实,这个参数的单位是1/256个字符宽度,也就是说,这里是把B列的宽度设置为了100个字符。
- 刚才说的是如何设置,那如何去读取一个列的宽度呢?直接用GetColumnWidth方法,这个方法只有一个参数,那就是列的索引号。如下所示:
- int col1width = sheet1.GetColumnWidth(1);
- 说完宽度,我们来说高度,在Excel中,每一行的高度也是要求一致的,所以设置单元格的高度,其实就是设置行的高度,所以相关的属性也应该在HSSFRow上,它就是HSSFRow.Height和HeightInPoints,这两个属性的区别在于HeightInPoints的单位是点,而Height的单位是1/20个点,所以Height的值永远是HeightInPoints的20倍。
- 要设置第一行的高度,可以用如下代码:
- sheet1.CreateRow(0).Height = 200*20;
- 或者
- sheet1.CreateRow(0).HeightInPoints = 200;
- 如果要获得某一行的行高,可以直接拿HSSFRow.Height属性的返回值。
- 你可能觉得一行一行设置行高或者一列一列设置列宽很麻烦,那你可以考虑使用HSSFSheet.DefaultColumnWidth、HSSFSheet.DefaultRowHeight和HSSFSheet.DefaultRowHeightInPoints属性。
- 一旦设置了这些属性,如果某一行或者某一列没有设置宽度,就会使用默认宽度或高度。代码如下:
- sheet1.DefaultColumnWidth=100*256;
- sheet1.DefaultRowHeight=30*20;
版权声明:本文为博主原创文章,未经博主允许不得转载。
C#调用NPOI组件读取excel表格数据转为datatable写入word表格中并向word中插入图片/文字/书签 获得书签列表的更多相关文章
- C#调用NPOI组件导出Excel表格
把一个List集合的数据导出到Excel表格中 public static string RenderToExcel<T>(List<T> datas) { MemoryStr ...
- 利用PHPExcel读取Excel的数据和导出数据到Excel
PHPExcel是一个PHP类库,用来帮助我们简单.高效实现从Excel读取Excel的数据和导出数据到Excel.也是我们日常开发中,经常会遇到的使用场景.比如有个客户信息表,要批量导出发给同事,我 ...
- phpexcel如何读取excel的数据和如何导出数据到excel
phpexcel如何读取excel的数据和如何导出数据到excel 一.总结 一句话总结:去官网看参考手册和api,或者找中文的博客或者参考手册 1.phpexcel插件如何下载? 其实这些插件不仅可 ...
- 利用NPOI组件产Excel完整操作
最终还是要使用NPOi了.刚开始做的是用com组件,发现如果本机不按照excel就不能使用,后来把其中一支改为了用Itextsharp产生pdf,但是还有几支批次要产生Excel,只能改用NPOI了. ...
- 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据
1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...
- 上传读取Excel文件数据
/// <summary> /// 上传读取Excel文件数据 /// 来自http://www.cnblogs.com/cielwater /// </summary> // ...
- js循环读取json数据,将读取到的数据用js写成表格
①js循环读取json数据的方式: var data=[{"uid":"2688","uname":"*江苏省南菁高级中学 022 ...
- java后台读取excel模板数据
/** * 读取EXCEL模板数据 * * @param excelFilePath excel文件路径 * @param dataRowNum 开始读取数据的行数 * @param keyRowNu ...
- python读取excel所有数据(cmd界面)
python读取excel所有数据(cmd界面) cmd界面显示excel数据 代码 import xlrd import os from prettytable import PrettyTable ...
随机推荐
- Java Native Interface Specification—Contents
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html 1. Introduction Java Nati ...
- INSTALL MYSQL IN MAC
安装好MYSQL后,在System References中找到MYSQL,启动它. 启动之后在终端中输入添加MySQL路径的命令,把MYSQL路径添加到PATH中: PATH="$PATH& ...
- 浅谈html5网页内嵌视频
更好的阅读体验:浅谈html5网页内嵌视频 如今在这个特殊的时代下:flash将死未死,微软和IE的历史问题,html5标准未定,苹果和谷歌的闭源和开源之争,移动互联网的大势所趋,浏览器各自为战... ...
- iOS 基础复习
silverlight知识点:linqToSQL.视图.存储过程.索引.触发器 数据结构:数组.栈.队列.链表.属.图. 排序算法:插入.选择.交换(冒泡).归并 网络开发:HTTP短连接.socke ...
- Hadoop 2.4.1 设置问题小结【原创】
先丢点问题小结到这里,免得忘记,有空再弄个详细教程玩,网上的教程要不就是旧版的,要不就是没说到点子上,随便搞搞也能碰上结果是对的时候,但是知其然而不知其所以然,没意思啊.解决问题的方法有很多种,总得找 ...
- Onmouseover被调用多次
当一个容器,如div,不包含元素时.Onmouseover只执行一次,正常.当这个div包含其他子元素的时候,这个事件就被执行了多次,今天遇到了这个问题,特此记录下,解决方案. 这个是由于onmous ...
- 无线路由器WDS 桥接设置方法
假设现在有a b c三台路由器,现在我们把b作为中心路由器,基本的配置之后使其能正常无线上网. 然后: 无线路由器A设置: 1.修改LAN口IP地址.在网络参数-LAN口设置中,修改IP地址和B路由器 ...
- Why is processing a sorted array faster than an unsorted array?
这是我在逛 Stack Overflow 时遇见的一个高分问题:Why is processing a sorted array faster than an unsorted array?,我觉得这 ...
- Unit Of Work--工作单元(二)
回顾 上一篇我们根据工作单元的原理基于ADO.NET进行了简单的实现,但是当项目需求发生变化的时候,比如需要引入ORM框架又要兼容当前ADO.NET实现的方式时,先前的实现就无法满足这个需求了. 话就 ...
- iis错误记录
1:iis错误 解决方法: 输入C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis -i 这里由于我的是默认在Administ ...