惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
F
Full Disclosure
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
Engineering at Meta
Engineering at Meta
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Threatpost
I
Intezer
V2EX - 技术
V2EX - 技术
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The Hacker News
The Hacker News
小众软件
小众软件
Google DeepMind News
Google DeepMind News
T
Tailwind CSS Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
N
News | PayPal Newsroom
MyScale Blog
MyScale Blog
AI
AI
Vercel News
Vercel News
Spread Privacy
Spread Privacy
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
G
GRAHAM CLULEY
Help Net Security
Help Net Security
Hacker News: Ask HN
Hacker News: Ask HN
Google DeepMind News
Google DeepMind News
MongoDB | Blog
MongoDB | Blog
L
LINUX DO - 热门话题
U
Unit 42
L
LangChain Blog
Recent Announcements
Recent Announcements

博客园 - liufei

阿里云服务器访问不了外网 MySQL修改root密码的多种方法 为需要远程登录的用户赋予权限: C#生成电子印章源码 ASP.NET的优点 Android上传 apk格式文件下载 Could not load file or assembly 'System.Core, Version=2.0.5.0 和autofac冲突的问题 1130 - Host '' is not allowerd to connect to this MySQL server, HTTP 错误 500.21 - Internal Server Error 解决方案 . 修改SQL Service数据库排序规则 MSSQL获取昨天,本周,本月。。。 MySQL Packets larger than max_allowed_packet are not allowed 骗子手机 15311888578 北京高德豪门网络科技有限公司 面试题 JetBrains ReSharper 8.2 Build 8.2.0.2160 && StyleCop win7开启特定端口 jquery关于select框的取值和赋值 asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes”
asp.net Mvc Npoi 导出导入 excel
liufei · 2014-12-22 · via 博客园 - liufei

因近期项目遇到所以记录一下:

首先导出Excel :

首先引用NPOI包

http://pan.baidu.com/s/1i3Fosux

(Action一定要用FileResult)

前台直接写就可实现:

1、  @Html.ActionLink("点击导出名册", "ExportStu2")

下面说一下导出:

首先说一些前台吧,mvc上传注意必须加 new { enctype = "multipart/form-data" }:

<td>
                       2、@using(@Html.BeginForm("ImportStu", "ProSchool", FormMethod.Post, new { enctype = "multipart/form-data" }))
                        {
                        <text>选择上传文件:(工作表名为“Sheet1”,“电脑号”在A1单元格。)</text>
                        <input name="file" type="file" id="file" />
                        <input type="submit" name="Upload" value="批量导入第一批电脑派位名册" />
                        }
                    </td>

后台实现:只传路径得出DataTable:

补充一个类

得到DataTable后,就想怎么操作就怎么操作了

2011-11-18 22:24 by 囧月, 28284 阅读, 

尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文。

曾使用过的方法

  1. 直接导出html,修改后缀名为.xls,这个方法有点像骗人的把戏,而且不能再导入
  2. 使用Jet OLEDB引擎来进行导入导出,完全使用sql语句来进行操作,缺点能控制的东西非常有限,比如格式就难以控制
  3. 使用Office COM组件进行导入导出,对环境依赖性太强(如“检索 COM 类工厂…”错误);且需要通过打开Excel.exe进程进行操作;虽然可以通过关闭工作表以及Marshal.ReleaseComObject方法来释放资源,但依然避免不了性能差。

关于NPOI

NPOIPOI项目的.NET版本,是由@Tony Qu(http://tonyqus.cnblogs.com/)等大侠基于POI开发的,可以从http://npoi.codeplex.com/下载到它的最新版本。它不使用Office COM组件(Microsoft.Office.Interop.XXX.dll),不需要安装Microsoft Office,支持对Office 97-2003的文件格式,功能比较强大。更详细的说明请看作者的博客或官方网站。

它的以下一些特性让我相当喜欢:

  1. 支持对标准的Excel读写
  2. 支持对流(Stream)的读写 (而Jet OLEDB和Office COM都只能针对文件)
  3. 支持大部分Office COM组件的常用功能
  4. 性能优异 (相对于前面的方法)
  5. 使用简单,易上手

使用NPOI

本文使用的是它当前的最新版本1.2.4,此版本的程序集缩减至2个:NPOI.dllIonic.Zip.dll,直接引用到项目中即可。

对于我们开发者使用的对象主要位于NPOI.HSSF.UserModel空间下,主要有HSSFWorkbookHSSFSheetHSSFRowHSSFCell,对应的接口为位于NPOI.SS.UserModel空间下的IWorkbookISheetIRowICell,分别对应Excel文件、工作表、行、列。

简单演示一下创建一个Workbook对象,添加一个工作表,在工作表中添加一行一列:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

using NPOI.HSSF.UserModel;

using NPOI.SS.UserModel;

public class NPOIWrite

{

    void CreateSheet()

    {

        IWorkbook workbook = new HSSFWorkbook();

        ISheet sheet = workbook.CreateSheet("Sheet1");

        IRow row = sheet.CreateRow(0);

        ICell cell = row.CreateCell(0);

        cell.SetCellValue("test");

    }

}

相应的读取代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

using System.IO;

using NPOI.HSSF.UserModel;

using NPOI.SS.UserModel;

public class NPOIRead

{

    void GetSheet(Stream stream)

    {

        IWorkbook workbook = new HSSFWorkbook(stream);

        ISheet sheet = workbook.GetSheetAt(0);

        IRow row = sheet.GetRow(0);

        ICell cell = row.GetCell(0);

        string value = cell.ToString();

    }

}

使用NPOI导出

从DataTable读取内容来创建Workbook对象:

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

34

35

36

37

38

39

public static MemoryStream RenderToExcel(DataTable table)

{

    MemoryStream ms = new MemoryStream();

    using (table)

    {

        using (IWorkbook workbook = new HSSFWorkbook())

        {

            using (ISheet sheet = workbook.CreateSheet())

            {

                IRow headerRow = sheet.CreateRow(0);

                foreach (DataColumn column in table.Columns)

                    headerRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);

                int rowIndex = 1;

                foreach (DataRow row in table.Rows)

                {

                    IRow dataRow = sheet.CreateRow(rowIndex);

                    foreach (DataColumn column in table.Columns)

                    {

                        dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());

                    }

                    rowIndex++;

                }

                workbook.Write(ms);

                ms.Flush();

                ms.Position = 0;

            }

        }

    }

    return ms;

}

如果看不惯DataTable,那么DataReader也行:

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

34

35

36

37

38

39

40

41

public static MemoryStream RenderToExcel(IDataReader reader)

{

    MemoryStream ms = new MemoryStream();

    using (reader)

    {

        using (IWorkbook workbook = new HSSFWorkbook())

        {

            using (ISheet sheet = workbook.CreateSheet())

            {

                IRow headerRow = sheet.CreateRow(0);

                int cellCount = reader.FieldCount;

                for (int i = 0; i < cellCount; i++)

                {

                    headerRow.CreateCell(i).SetCellValue(reader.GetName(i));

                }

                int rowIndex = 1;

                while (reader.Read())

                {

                    IRow dataRow = sheet.CreateRow(rowIndex);

                    for (int i = 0; i < cellCount; i++)

                    {

                        dataRow.CreateCell(i).SetCellValue(reader[i].ToString());

                    }

                    rowIndex++;

                }

                workbook.Write(ms);

                ms.Flush();

                ms.Position = 0;

            }

        }

    }

    return ms;

}

以上代码把创建的Workbook对象保存到流中,可以通过以下方法输出到浏览器,或是保存到硬盘中:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

static void SaveToFile(MemoryStream ms, string fileName)

{

    using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))

    {

        byte[] data = ms.ToArray();

        fs.Write(data, 0, data.Length);

        fs.Flush();

        data = null;

    }

}

static void RenderToBrowser(MemoryStream ms, HttpContext context, string fileName)

{

    if (context.Request.Browser.Browser == "IE")

        fileName = HttpUtility.UrlEncode(fileName);

    context.Response.AddHeader("Content-Disposition", "attachment;fileName=" + fileName);

    context.Response.BinaryWrite(ms.ToArray());

}

使用NPOI导入

需要注意的是,sheet.LastRowNum = sheet.PhysicalNumberOfRows - 1,这里可能存在BUG:当没有数据或只有一行数据时sheet.LastRowNum为0,PhysicalNumberOfRows 表现正常

这里读取流中的Excel来创建Workbook对象,并转换成DataTable:

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

34

35

36

37

38

39

40

41

42

43

static DataTable RenderFromExcel(Stream excelFileStream)

{

    using (excelFileStream)

    {

        using (IWorkbook workbook = new HSSFWorkbook(excelFileStream))

        {

            using (ISheet sheet = workbook.GetSheetAt(0))

            {

                DataTable table = new DataTable();

                IRow headerRow = sheet.GetRow(0);

                int cellCount = headerRow.LastCellNum;

                int rowCount = sheet.LastRowNum;

                for (int i = headerRow.FirstCellNum; i < cellCount; i++)

                {

                    DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);

                    table.Columns.Add(column);

                }

                for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++)

                {

                    IRow row = sheet.GetRow(i);

                    DataRow dataRow = table.NewRow();

                    if (row != null)

                    {

                        for (int j = row.FirstCellNum; j < cellCount; j++)

                        {

                            if (row.GetCell(j) != null)

                                dataRow[j] = GetCellValue(row.GetCell(j));

                        }

                    }

                    table.Rows.Add(dataRow);

                }

                return table;

            }

        }

    }

}

或者是直接生成SQL语句来插入到数据库:

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

34

35

36

37

38

39

40

41

42

public static int RenderToDb(Stream excelFileStream, string insertSql, DBAction dbAction)

{

    int rowAffected = 0;

    using (excelFileStream)

    {

        using (IWorkbook workbook = new HSSFWorkbook(excelFileStream))

        {

            using (ISheet sheet = workbook.GetSheetAt(0))

            {

                StringBuilder builder = new StringBuilder();

                IRow headerRow = sheet.GetRow(0);

                int cellCount = headerRow.LastCellNum;

                int rowCount = sheet.LastRowNum;

                for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++)

                {

                    IRow row = sheet.GetRow(i);

                    if (row != null)

                    {

                        builder.Append(insertSql);

                        builder.Append(" values (");

                        for (int j = row.FirstCellNum; j < cellCount; j++)

                        {

                            builder.AppendFormat("'{0}',", GetCellValue(row.GetCell(j)).Replace("'", "''"));

                        }

                        builder.Length = builder.Length - 1;

                        builder.Append(");");

                    }

                    if ((i % 50 == 0 || i == rowCount) && builder.Length > 0)

                    {

                        rowAffected += dbAction(builder.ToString());

                        builder.Length = 0;

                    }

                }

            }

        }

    }

    return rowAffected;

}

这里的Excel可能没有数据,所以可以加一个方法来检测:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public static bool HasData(Stream excelFileStream)

{

    using (excelFileStream)

    {

        using (IWorkbook workbook = new HSSFWorkbook(excelFileStream))

        {

            if (workbook.NumberOfSheets > 0)

            {

                using (ISheet sheet = workbook.GetSheetAt(0))

                {

                    return sheet.PhysicalNumberOfRows > 0;

                }

            }

        }

    }

    return false;

}

结尾

好吧,不说啥了,放代码:点击下载