NPOI指南

《NPOI指南》目录(草稿)

2014年4月9日没有评论

预计页数:250-350页

出版社:待定

 

初级篇

1. 什么是NPOI

1.1 NPOI发展历史

1.2 NPOI团队介绍

1.3 主流Excel读写库比较

1.4 NPOI的未来

2. NPOI操作Excel 2003/2007文件

2.1 架构

2.1.1 NPOI接口介绍

2.1.2 理解HSSF和XSSF的关系

2.1.3 文件的读和写实现上的区别与难点

2.2 文件生成篇

2.2.1 创建空文件

2.2.2 创建单元格和内容

2.2.3 设置边框和纹理

2.2.4 创建单元格批注

2.2.5 设置单元格高级样式(字体、划线等)

2.2.6 合并单元格

2.2.7 设置固定行宽和列高

2.2.8 使用Excel公式

2.2.9 插入图片

2.3 文件读取篇

2.3.1 遍历Excel行列

2.3.2 提取图片

2.3.3 获得公式的计算结果

2.4 高级技巧

2.4.1 设置页眉和页脚

2.4.2 打印设置

2.4.3 复制行和列

2.4.4 复制表格

2.4.5 自动识别Excel 2003及2007格式

2.4.6 把.NET日期格式转换成Excel日期格式

3. NPOI操作Word 2007文件

3.1 创建空文件

3.2 Paragraph和Run

3.3 设置Paragraph和Run的样式

3.4 创建表格

中级篇

4. NPOI综合技巧

5.1 Excel 2007实现点状图

5.2 单元格坐标与行列索引转换

5.3 用Toxy实现Excel转DataSet及DataTable

5.4 NPOI.CSS的使用

5. 项目实践及需求分析

3.1 生成某公司销售业绩表

3.2 生成学校课程表

3.3 生成淘宝产品表

3.4 生成食品饮料用成分表

6. NPOI中使用的设计模式

6.1 工厂模式

6.2 适配器模式

6.3 访问者模式

6.4 依赖注入

高级篇

7 搭建NPOI开发环境

7.1 基本环境设置

7.2 NPOI源代码结构说明

7.3 如何成为NPOI开发者

7.4 实用工具


8.  Office文件格式解析

8.1 ActiveX文档格式

8.1.1 COM复合文档接口

8.1.2 Office文件格式内部结构

8.1.3 Thumb.db

8.2 Excel与BIFF

8.2.1 BIFF简介

8.2.2 BIFF基本结构

8.2.3 BIFF中的记录(Record)

8.3 Word与FIB

8.4 OpenXml格式

8.4.1 OpenXML简介

8.4.2 基本结构

8.4.3 OpenXML在Excel格式中的应用

8.5 Office文件格式的未来

9. Office文件格式实例分析

9.1 Excel BIFF实例分析

9.1.1 Excel文本记录

9.1.2 Excel单元格样式

9.1.3 单元格相关BIFF记录解析

9.1.4

9.2 Excel OpenXML

9.2.1 单元格数据的存储

9.2.2 基本样式的实现

9.2.3

分类:未分类标签:

4.2 基于POIXMLDocument创建自定义属性

2014年4月28日没有评论

作者:Tony Qu

在Office 97-2003的文件格式里面中,我们是用SummaryInformation和DocumentSummaryInformation来设置自定义属性的。但OpenXml格式使用了完全不同的极致。

NPOI中,管理OpenXml格式的核心类叫做POIXmlDocument,这和POIFSFileSystem是非常类似的,担负着文件系统管理的职责。而POIXmlDocument.GetProperties则是我们需要关注的重点,它返回的POIXMLProperties实例就是我们需要的自定义属性。

由于XSSFWorkbook和XWPFDocument都继承自POIXmlDocument,所以你真正需要调用的是XSSFWorkbook.GetProperties()和XWPFDocument.GetProperties()。

以下代码是用来设置Custom1自定义属性的:

1
2
if (!workbook.GetProperties().CustomProperties.Contains("Custom1"))
    workbook.GetProperties().CustomProperties.AddProperty("Custom1", "NPOI Demo");

为了防止重复添加同名自定义属性,一定要记得判断它是否已存在。要注意,此操作必须在workbook.Write()之前调用。

分类:未分类标签:

NPOI 2.0.5性能究竟提升了多少

2014年4月10日没有评论

作者:Tony Qu

由于NPOI 2.0 beta 2中95%的序列化不再使用XmlSerializer,在经过实验后发现,性能提升差不多是10-20倍的。当然干掉XmlSerializer的原因是多方面的,首先XmlSerializer有很多限制,NPOI的基础库NPOI.OpenXmlFormats无法预先生成XmlSerializer的assembly(这是微软官方提供的性能优化方法),生成器直接报错说有冲突,具体冲突我忘了,反正n多冲突,所以这条路走不通;再加上XmlSerializer对于一些场景的支持不够到位,比如Xml对象的继承,接口的支持等,导致生成的open xml文件其实就是坏的,然后Excel或Word直接报xxx.xml损坏,是否修复;最后自然是性能和内存消耗,使用XmlSerilizer时由于要临时编译生成代码,内存消耗非常可怕,即使有assembly缓存,很多时候第一次都挺不过去,所以直接报OutOfMemory异常,我已经接到多个用户反馈(国内国外都有)。

我们那数字说话,先来看来自于某国外NPOI用户的反馈。借此来说明性能究竟有多少提升

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Program
{
    static void Main(string[] args)
    {
        IWorkbook workbook = new XSSFWorkbook();
        ICell cell;
        ISheet sheet = workbook.CreateSheet("StressTest");
        int i = 0;
        int rowLimit = 100000;
        DateTime originalTime = DateTime.Now;
 
        System.Console.WriteLine("Start time: " + originalTime);
 
        for (i = 0; i <= rowLimit; i++)
        {
            cell = sheet.CreateRow(i).CreateCell(0);
            //sheet.SetActiveCell(i, 0);
            cell.SetCellValue("ZOMG PLEASE SURVIVE THIS STRESS TEST");
 
            if(i % 10000 == 0)
            {
                System.Console.WriteLine("[" + (DateTime.Now - originalTime) + "]" + " " + i + " rows written");
            }
        }
 
        FileStream sw = File.Create("test.xlsx");
        workbook.Write(sw);
        sw.Close();
 
        //prompt user so we do not close the window with our data <img src="http://tonyqus.sinaapp.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley">
        System.Console.Read();
    }
}

 

NPOI 2.0.1 (beta)的运行结果如下

Start time: 5/14/2013 5:05:39 PM

[00:00:00.0170017] 0 rows written

[00:00:02.7792779] 10000 rows written

[00:00:11.1951194] 20000 rows written

[00:00:27.7817779] 30000 rows written

[00:00:53.5283523] 40000 rows written

[00:01:30.1910182] 50000 rows written

[00:02:16.2836270] 60000 rows written

[00:03:14.6894670] 70000 rows written

[00:04:21.9641938] 80000 rows written

[00:05:38.7868753] 90000 rows written

[00:07:05.4055363] 100000 rows written

可以看到,写100,000行需要7分钟。

NPOI 2.0.5 (beta2)的运行结果如下

Start time: 2013/11/24 21:47:55

[00:00:00.0439453] 0 rows written

[00:00:00.1054687] 10000 rows written

[00:00:00.1826171] 20000 rows written

[00:00:00.2646484] 30000 rows written

[00:00:00.3271484] 40000 rows written

[00:00:00.4130859] 50000 rows written

[00:00:00.4892578] 60000 rows written

[00:00:00.5498046] 70000 rows written

[00:00:00.6513671] 80000 rows written

[00:00:00.7246093] 90000 rows written

[00:00:00.8037109] 100000 rows written

可以看到,2.0.5即使写入100,000行,都在1秒以内。

我们再来看另外一个例子,也是国外某NPOI提供的反馈。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Program
{
    static void Main(string[] args)
    {
        IWorkbook workbook = new XSSFWorkbook();
        ISheet sheet1 = workbook.CreateSheet("Sheet1");
        sheet1.CreateRow(0).CreateCell(0).SetCellValue("This is a Sample");
        int x = 1;
 
        Debug.WriteLine("Start at " + DateTime.Now.ToString());
        for (int i = 1; i <= 30000; i++)
        {
            IRow row = sheet1.CreateRow(i);
            for (int j = 0; j < 15; j++)
            {
                row.CreateCell(j).SetCellValue(x++);
            }
        }
        Debug.WriteLine("End at " + DateTime.Now.ToString());
 
        FileStream sw = File.Create("test.xls");
        workbook.Write(sw);
        sw.Close();
    }
}

 

NPOI 2.0.1(beta)的运行结果

3w行:25秒

7w行:4分钟

30w行:80分钟

用那位网友的话来说,真的是几何级数级增长。

NPOI 2.0.5(beta 2)的运行结果

3w行:2秒

7w行:5秒

30w行:37秒

看结果大家就懂了,其他不多说了。目前NPOI 2.0.5的内存依然有点高,以刚才30w行为例,峰值大概在1.3G内存左右,NPOI 2.0正式版中将对内存进行优化。

分类:未分类标签:

NPOI 2教程 – 读取Word 2007文件

2013年12月11日没有评论

作者: Tony Qu

 

要学习如何读取Word,还要从Word的基本结构说起。

Word的文件格式doc/docx是一种文本描述性格式,其主体是文本,其他的都是描述该文本的属性,这就和英语中的定语和补语差不多。

 

在此之前,我要先给大家复习下Word的文档结构,通常呢Word文档结构可以分为段落和表格(当然也会有页眉页脚,但这不是重点),而一个表格里面可以包含行和列,有行列自然会有单元格(这个NPOI用户应该非常熟悉,和Excel的概念是一模一样的),每个单元格里面又会包含段落。而每个段落里面可以包含很多个Run。下面的程序就是读取Word中所有段落(不包括表格中的段落)的遍历方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using (FileStream stream = File.OpenRead(filepath))
{
    XWPFDocument doc = new XWPFDocument(stream);
    foreach (var para in doc.Paragraphs)
    {
        string text = para.ParagraphText; //获得文本
        ...
        var runs = para.Runs;
        string styleid = para.Style;
 
        for (int i = 0; i < runs.Count; i++)
        {
             var run = runs[i];
             text = run.ToString(); //获得run的文本
            ...
        }
    }
}

 

这里有一句话用到了Paragraph.Style,这个是每个段落被设置的样式名称,样式分为嵌入式样式和引用样式两种,嵌入式样式是直接写在document.xml里面的样式,而引用样式是引用styles.xml里面的样式。这里的styles.xml很像web中的css文件。

如果要抽取表格中的文本,可以用下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var tables = doc.Tables;
 
foreach (var table in tables)    //遍历表格
{
 
    foreach (var row in table.Rows)    //遍历行
    {
        var c0= row.GetCell(0);        //获得单元格0
        foreach (var para in c0.Paragraphs)
        {
       string text = para.ParagraphText;
            //处理段落
            ...
        }
    }
}

上面这段代码是我在项目中用到的,它是获得Word中所有在第0个单元格的段落的文本。

分类:NPOIXWPF标签:

NPOI 2教程 – 2.3.2 公式重新计算开关

2013年12月1日没有评论

作者:Tony Qu

Excel其实带了一个选项,叫做是否进行自动计算。默认是自动的,所以每次打开Excel时,你会发现所有的计算值都会自动更新,或者你更改某个单元格,计算结果也会自动更新。

image

但其实这个选项是可以控制的。在NPOI中,这个属性叫做XSSFSheet.ForceFormulaRecalculation。

打开该选项的话,代码为

sheet1.ForceFormulaRecalculation = true; (这是默认值,通常不需要设置)

如果关闭的话,代码为

sheet1.ForceFormulaRecalculation = false;

分类:未分类标签:

NPOI 2教程 – 2.3.1 在单元格中创建Excel公式

2013年12月1日没有评论

作者:Tony Qu

从这节开始,我们将开始学习Excel高级一点的功能–公式。为某个单元格指定公式后,单元格中的类容将根据公式计算得出,如图:  
formula_common01 
图中设置的是一个基本表达式”1+2*3”,单元格A1中将显示此表达式计算的结果”7”,如图所示。对应的C#生成代码也很简单,如下:

1
2
3
4
5
6
7
ISheet sheet1 = hssfworkbook.CreateSheet("Sheet1");
IRow row1=sheet1.CreateRow(0);
ICell cel1 = row1.CreateCell(0);
ICell cel2 = row1.CreateCell(1);
ICell cel3 = row1.CreateCell(2);
cel1.SetCellFormula("1+2*3");
cel2.SetCellValue(5);

同样,NPOI也支持单元格引用类型的公式设置,如下图中的C1=A1*B1。

formula_common02

对应的公式设置代码为:

cel3.SetCellFormula("A1*B1");

注意:这里不需要加等于号,和Excel里使用时略有不同。

 

当然你也可以用Excel函数,如SUM

代码如下:

cel3.SetCellFormula("SUM(A1:A2)");

分类:未分类标签:

NPOI 1.2.5教程 2.5.2 重命名工作表

2013年11月12日没有评论

作者:Jnz

在Excel中,当你双击工作表名称之后,工作表名称将变为可编辑状态,输入新工作表名称,点击保存,即可完成对工作表名称的修改,那么在NPOI中我们怎么实现重命名工作表呢,就可以用下面的 方法:

workbook.SetSheetName(0, "001");

这里的workbook是IWorkbook类型的,SetSheetName所需要的参数是Sheet的编号(Int),新的工作表名称,一般来说默认情况下,在没有删除过Sheet的情况下,Sheet1的编号为0。

分类:ExcelHSSFXSSF标签:

NPOI 1.2.5教程 2.5.1 设置默认工作表(已更新)

2013年11月2日没有评论

在Excel中,当你点击左边工作表名称之后,点击保存,Excel会自动记住当前的活动工作表,即默认工作表,所以如果你想打开Excel生成的xls或者xlsx文件的时候,此时显示的将会是默认的工作表,即是你所右键点击的那张,那么在NPOI中我们怎么实现设置默认工作表呢,就可以用下面的方法:

workbook.SetActiveSheet();
 

SetActiveSheet所需要的参数是Sheet的编号(Int),一般来说默认情况下,在没有删除过Sheet的情况下,Sheet1的编号为0,所以当我们需要设置某张表为excel默认工作表的时候,只需要知道该表的编号即可。

分类:NPOI标签:

NPOI 2教程 – 3.4 在Word中创建表格

2013年10月27日没有评论

作者:Tony Qu

Word中的表格和Excel中的完全不同,虽然我们可以把Excel的表格贴到Word中,但其实贴这个过程中是做了复杂的转换的。其实Word的表格是单独实现的,和Excel的表格没有直接关系。

在NPOI中,我们可以用XWPFTable直接操作Word中的表格。

XWPFTable也有Row和Cell的概念(表格都有这概念,呵呵),我们可以用table.GetRow()获得行,用GetCell获得行中的单元格,如下:

1
2
3
4
XWPFDocument doc = new XWPFDocument();
 
XWPFTable table = doc.CreateTable(3, 3);
table.GetRow(1).GetCell(1).SetText("EXAMPLE OF TABLE");

这里我们创建了一个3×3的表格,我们获得表格的第二行第二列,同时把内容设置为EXAMPLE OF TABLE。

设置文本有几种方法,我们这里用的是最简单的方法,即直接用文本,但这种方法不利于设置复杂样式。如果有样式,可以考虑用XWPFParagraph,也就是说把某个单元格的内容直接设置为一个XWPFParagraph实例,如下所示:

1
2
3
4
5
6
7
8
9
XWPFRun r1 = p1.CreateRun();
r1.SetBold(true);
r1.SetText("The quick brown fox1");
r1.SetBold(true);
r1.SetFontFamily("Courier");
r1.SetUnderline(UnderlinePatterns.DotDotDash);
r1.SetTextPosition(100);
 
table.GetRow(0).GetCell(0).SetParagraph(p1);

 

这里我们把第一行第一列的内容设置为一个段落。

 

最后为了撑开第三列,我们再设置一个文本。

table.GetRow(2).GetCell(2).SetText("only text");

image

上面是该表格的最终效果。

分类:未分类标签:

NPOI 2教程 – 3.2 在Word中设置样式

2013年10月27日没有评论

作者:Tony Qu

本节将介绍如何设置Word中的文本样式,如字体大小、粗体、字体、删除线等。

 

要记住,本节提到的所有样式都是基于XWPFRun的,你可以把XWPFRun理解成一小段文字的描述对象,这也是Word文档的特征,即文本描述性文档。

所以我们先初始化一个XWPFRun。

1
2
3
4
5
XWPFDocument doc = new XWPFDocument();
 
XWPFParagraph p1 = doc.CreateParagraph();
XWPFRun r1 = p1.CreateRun();
r1.SetText("The quick brown fox");

a. 设置字体和字号

r1.SetFontFamily("Courier");

r1.SetFontSize(20);

上面的例子我们把字体设置成了Courier, 字号是20。

b. 斜体

r1.SetItalic(true);

c. 粗体

r1.SetBold(true);

d. 删除线

r1.SetStrike(true);

image

e. 段落对齐

这是Word中的常用术语,但这个属性是直接设置在段落对象上,而非XWPFRun上。

p1.SetAlignment(ParagraphAlignment.BOTH);

这句话相当于Word段落设置中的对齐方式设置

image

这里的ParagraphAlignment有很多种枚举值,如下:

1
2
3
4
5
6
7
8
public enum ParagraphAlignment
{
    LEFT, //左对齐
    CENTER, //居中
    RIGHT,    //右对齐
    BOTH,    //两端对齐
    DISTRIBUTE,    //分散对齐
}

最后别忘了把文档保存。


阅读更多
个人分类: C#
想对作者说点什么? 我来说一句

NPOI API帮助文档

2014年09月24日 4.2MB 下载

没有更多推荐了,返回首页

不良信息举报

NPOI指南

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭