首先要说一下自己写的一个帮助类ExcelHelper。可以用两种方式访问Excel文件,一种是以Excel的Com组件的形式,一种是最简单的把Excel看作是数据库。其实很多的内容网上都已经有了,但都比较分散,都只提到了一种或两种,没有统一到一起。代码如下:

using System;
using System.IO;
using System.Collections;
using System.Text;

using System.Data;
using System.Data.OleDb;

namespace com.urp.command.FileFrameWork.Helper
{
    /** <summary>
    /// Class1 的摘要说明。
    /// </summary>
    public class ExcelHelper
    {
        private readonly string readConn = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source={0};"
            +"Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'";

        private readonly string writeConn = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source={0};"
            +"Extended Properties='Excel 8.0;HDR=YES;'"; 
        
        private OleDbConnection _conn = null;
        private OleDbCommand _command = null;
        private OleDbDataAdapter _adapter = null;
        private OleDbCommandBuilder _builder = null;

        private Excel.Application _application =  null;
        private Excel._Workbook _workBook = null;
        private Excel._Worksheet _workSheet = null;
        private Excel.Range _range =  null;

        private int _columnCount;
        private int _rowCount;

        private object _missingValue = System.Reflection.Missing.Value;

        public ExcelHelper(string path)
        {
            readConn = String.Format(readConn, path);
            writeConn = String.Format(writeConn, path);
        }

        public ExcelHelper()
        {
            
        }

        ComExcel#region ComExcel
        public int UsedColumnCount
        {
            get 
            {
                if(_columnCount == 0)
                    _columnCount = _workSheet.UsedRange.Columns.Count;
                return _columnCount;
            }
        }

        public int UsedRowCount
        {
            get
            {
                if(_rowCount == 0)
                    _rowCount =  _workSheet.UsedRange.Rows.Count;
                return _rowCount;
            }
        }

        //打开一个Excel线程
        public void OpenWorkBook(string path)
        {
            try
            {
                _application = new Excel.ApplicationClass();
                _application.Visible = false;
                _workBook = _application.Workbooks.Open(path, 0, true, 5, "", "", false, 
                    Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        //新建一个Excel线程
        public void NewWorkBook()
        {
            _application = new Excel.ApplicationClass();
            _application.Visible = false;
            _workBook = (Excel._Workbook)(_application.Workbooks.Add(_missingValue));
        }
 

        //根据名字获取sheet
        public bool OpenWorkSheet(string sheetName)
        {
            _workSheet = (Excel._Worksheet)_workBook.Worksheets.get_Item(sheetName);
            if(_workSheet != null)
                return true;
            return false;
        }

        //默认获得第一个sheet
        public bool OpenWorkSheet(int sheetIndex)
        {
            _workSheet = (Excel._Worksheet)_workBook.Worksheets.get_Item(sheetIndex + 1);
            if(_workSheet != null)
                return true;
            return false;
        }

        //保存
        public void SaveSheet(string path)
        {
            _workBook.SaveAs(path, _missingValue, _missingValue, _missingValue, _missingValue,
                _missingValue, Excel.XlSaveAsAccessMode.xlNoChange, _missingValue, _missingValue,
                _missingValue, _missingValue, _missingValue);
        }

        //保存并关闭
        public void CloseSaveSheet(string path)
        {
//            Remove(path);
            this.SaveSheet(path);
            this.CloseSheet();
        }

        //关闭
        public void CloseSheet()
        {
            if(_workBook != null)
                _workBook.Close(false, _missingValue, _missingValue);
            if(_application != null)
                _application.Quit();

            if(_range != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(_range);
                _range = null;
            }
            if(_workSheet != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(_workSheet);
                _workSheet = null;
            }
            if(_workBook != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(_workBook);
                _workBook = null;
            }
            if(_application != null)
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(_application);            
                _application = null;
            }            

            GC.Collect();            
        }

        CellByCell#region CellByCell
        public object GetCellByCell(int rowIndex, int columnIndex)
        {
            _range = _workSheet.get_Range(CellStr(rowIndex, columnIndex), _missingValue);
            return _range.Value2;
        }

        public void SetCellByCell(int rowIndex, int columnIndex, object value)
        {
            _range = _workSheet.get_Range(CellStr(rowIndex, columnIndex), _missingValue);
            _range.set_Value(_missingValue, value);
        }

        
        //自动将行数加一
        private string CellStr(int rowIndex, int columnIndex)
        {
            return (char)(65 + columnIndex) + (++rowIndex).ToString();
        }
        #endregion

        range#region range
        public Array GetByRangeArray2(int rowStart, int columnStart, int rowEnd, int columnEnd)
        {
            _range = _workSheet.get_Range(CellStr(rowStart, columnStart), CellStr(rowEnd, columnEnd));
            return (Array)_range.Value2;
        }

        public void SetByRangeArray2(int rowStart, int columnStart, int rowEnd, int columnEnd, Array values)
        {
            _range = _workSheet.get_Range(CellStr(rowStart, columnStart), CellStr(rowEnd, columnEnd));
            _range.Value2 =  values;
        }
        #endregion

        #endregion

        ADO.Net#region ADO.Net
        //以非导入的方式打开连接
        public void OpenReadConnection()
        {
            _conn = new OleDbConnection(readConn);
            _conn.Open();  
        }

        //以非导入的方式打开连接
        public void OpenWriteConnection()
        {
            _conn = new OleDbConnection(writeConn);
            _conn.Open(); 
        }

        //在excel中先建一个sheet并写入列名
        public void NewTable(DataTable dataTable)
        {
            StringBuilder columnNames = new StringBuilder("Create Table ");
            columnNames.Append("sheet1(");
            foreach(DataColumn column in dataTable.Columns)
            {
                columnNames.Append(column.ColumnName);
                columnNames.Append(" varchar, ");
            }
            columnNames.Replace(", ", ")", columnNames.Length - 2 , 2);

            Command.CommandText = columnNames.ToString();
            Command.ExecuteNonQuery();
        }

        //关闭连接
        public void CloseConnection()
        {
            if(_conn != null)
                _conn.Close();
            _conn = null;
            _command = null;
            _adapter = null;
            _builder = null;
        }

        DataReader#region DataReader
        public IDataReader GetByDataReader()
        {
            Command.CommandText = "Select * From [sheet1$]";
            return Command.ExecuteReader();
        }

        public IDataReader GetByDataReader(int rowStart, int columnStart, int rowEnd, int columnEnd)
        {
            string range = CellStr(rowStart, columnStart) + ":" + CellStr(rowEnd, columnEnd);
            Command.CommandText = "Select * From [sheet1$" + range + "]";
            return Command.ExecuteReader();
        }
        #endregion

        DataTable#region DataTable
        public DataTable GetByDataTable()
        {
            Command.CommandText = "select * from [sheet1$]";

            DataTable dt = new DataTable();
            Builder = new OleDbCommandBuilder(Adapter);
            Adapter.Fill(dt);
            return dt; 
        }

        public void SetByDataTable(DataTable dataTable)
        {
            try
            {
                Command.CommandText = "select * from [sheet1$]";

                DataTable dt = new DataTable("sheet1");
                Builder = new OleDbCommandBuilder(Adapter);
                Adapter.Fill(dt);
                Adapter.InsertCommand = Builder.GetInsertCommand();
                Adapter.Update(dataTable);
                dt = null;
            }
            catch(OleDbException ex)
            {
                throw ex;
            }
        }

        private OleDbCommand Command
        {
            get
            {
                if(_command == null)
                {
                    _command = new OleDbCommand();
                    _command.Connection = _conn;
                }
                return _command;
            }
        }

        private OleDbDataAdapter Adapter
        {
            get
            {
                if(_adapter == null)
                {
                    _adapter = new OleDbDataAdapter();
                    _adapter.SelectCommand = Command;
                }
                return _adapter;
            }
        }

        private OleDbCommandBuilder Builder
        {
            get
            {
                return _builder;
            }
            set
            {
                _builder = value;
                _builder.QuotePrefix="[";     //获取insert语句中保留字符(起始位置)
                _builder.QuoteSuffix="]"; //获取insert语句中保留字符(结束位置) 
            }
        }
        #endregion
        #endregion
    }
}

如果把Excel看作数据库,那么要注意连接字符串:

private readonly string readConn = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source={0};"

+"Extended Properties='Excel 8.0;HDR=YES;IMEX=1;'";

HDR=YES 表示将sheet的第一行作为列名,所以我们默认excel的首行是列名。

IMEX=1 表示大致的意思是使用导入的模式,把数字也作为字符串来操作。

有一点很重要。IMEX=1,是一种导入的模式,所以首先这个文件要存在,如果不存在会报错:“Microsoft Jet 数据库引擎找不到对象'…\Customer.xls'。请确定对象是否存在,并正确地写出它的名称和路径”,而且这样写了以后就算文件是存在的,还有一个问题是不能对文件更新的,会提示“不能修改表 'sheet1' 的设计。它在只读数据库中”等错误,甚至还有提示权限的问题。

字符串的问题解决了以后,剩下的就是象数据库一样来操作了。如读excel只需要然后返回一个DataTable,其实这里应该可以返回后可以关闭连接,但是因为把数据库的打开已经提出去了做了一个单独的方法,所以把关闭也放到了外面,由导入,结束后再调用关闭的函数,而且这样做在形式上也和导出保持了一致。到目前位置还没发现这样做的问题。

public DataTable GetByDataTable()

{

Command.CommandText = "select * from [sheet1$]";

DataTable dt = new DataTable();

Builder = new OleDbCommandBuilder(Adapter);

Adapter.Fill(dt);

return dt;

}

至于导出,我们希望也是用DataTable来完成,网上有很多是一行一行插入的,想必在性能上肯定不如用Iadapter的方法Update来的快吧。而且单独写Insert方法的话还要处理参数的问题,要写插入语句,形式上烦了好多。所以我们利用DataTable的自动更新,用OleDbCommandBuilder来产生InserCommand。但是利用这种方法的问题是要求先要有表结构,所以我们要有一个产生表结构的方法,来写入列名,然后用一个select来填充一个空的table,同时来生成InsertCommand,然后更新的时候却是更新我们传入的dataTable,代码如下:

public void SetByDataTable(DataTable dataTable)

{

Command.CommandText = "select * from [sheet1$]";

DataTable dt = new DataTable("sheet1");

Builder = new OleDbCommandBuilder(Adapter);

Adapter.Fill(dt);

Adapter.InsertCommand = Builder.GetInsertCommand();

Adapter.Update(dataTable);

dt = null;

}

如何产生新的sheet的代码如下,这里还有一个问题,excel文件还不存在,怎么可以新建sheet了呢,是否还需要新建excel呢?我们的回答是不需要,当你的连接字符串里没有IMEX=1的,连接的同时如果没有文件,会自动新建,这一点省了好多。然后只要用“create table 表名(列名 类型)”,类型全部用varchar安全又简单。

public void NewTable(DataTable dataTable)

{

StringBuilder columnNames = new StringBuilder("Create Table ");

columnNames.Append("sheet1(");

foreach(DataColumn column in dataTable.Columns)

{

columnNames.Append(column.ColumnName);

columnNames.Append(" varchar, ");

}

columnNames.Replace(", ", ")", columnNames.Length - 2 , 2);

Command.CommandText = columnNames.ToString();

Command.ExecuteNonQuery();

}

ExcelHelper中还有返回IdataReader对象的方法,本来以为要用来写入列名的,发现后来已经用不到了。至于用Com的方法来访问就复杂了好多了。其实用这种方法来访问,灵活性会大好多,字体,格式,等等都可以操作。具体的例子网上也后好多,可以看一下这篇的文章http://support.microsoft.com/default.aspx?scid=kb;zh-cn;306023

这里我只说一下我自己的考虑,使用“自动化功能将数据数组传输到工作表上的区域”,我采用的是这片文章的第二中方法,至于格式之类的都不错处理,因为毕竟不是做报表,只是导入导出而已。用COM的方法访问excel最关键是是Range做为访问对象,这个Range可以是一个Cell,可以是一行,一列,也可以是一个sheet,所以如果我们能一次就把sheet读入内存,然后再来处理,避免反复的读文件,提高性能,事实证明确实是这样,在某些情况下,甚至超过了ADO.Net来访问的性能。文章中有行代码就是我采用这种方法的关键,“m_objRange.Value = objData;”这个objData是一个2维的数组,我们平时用的比较多的是object[], object[,]这种形式的数组,其实数组的类是Array,为了访问和转化的方便,我采用了Array的形式,不熟的朋友可以去查一下,里面有很多方法我们需要用到,在这里就不具体介绍了。代码如下,都是用Array来作为参数和返回值的。

public Array GetByRangeArray2(int rowStart, int columnStart, int rowEnd, int columnEnd)

{

_range = _workSheet.get_Range(CellStr(rowStart, columnStart), CellStr(rowEnd, columnEnd));

return (Array)_range.Value2;

}

public void SetByRangeArray2(int rowStart, int columnStart, int rowEnd, int columnEnd, Array values)

{

_range = _workSheet.get_Range(CellStr(rowStart, columnStart), CellStr(rowEnd, columnEnd));

_range.Value2 =  values;

}

还有我们注意到“m_objRange = m_objSheet.get_Range("A1", "C1");”返回Range的方法里的参数可以看出来,表示范围的方法是用一个“列行”组成的字符串。由于我们习惯用index来定位数组况且Array也只能用数字来定位,所以还必须有一个方法,来完成数字到字母的转化。Excel的首行是第一行,为了使用的习惯,改为由0行作为首行。
         private string CellStr(int rowIndex, int columnIndex)

{

return (char)(65 + columnIndex) + (++rowIndex).ToString();

}

还有一些关于sheet的打开关闭保存等问题就不一一解释了,朋友们一看代码就可以明白了。写完了ExcelHelper我们已经可以用程序来快速的访问excel了。如果用ADO.net的方法,只需要操作返回的DataTable,而如果用Com的方法,也只需要访问返回的Array就可以了。但是现在又有另一个问题产生了。

从DataTable可以获得列信息,那Array呢,怎么样获得呢,Array又是如何的一个结构,如何来操作呢。

这里我们又写了, 一个辅助的类ArrayCollection。构造函数直接传入两个Array,一个是列信息,一个是行信息,通过ArrayCollection,来将Array转化为List,方便访问,在形式上努力做到和DataTable统一。

这样子以后对于Excel的两种访问方式都写完了,以后还要做一个性能方面的比较,来证实我的想法的正确性,剩下的就是要对返回的数据进行处理了,这个下次在分析了。因为我读取和写入文件都只访问一次文件,而最花时间的地方就在这,所以,如果要加做进度条的话可能就无法实现了,这个问题以后在做考虑吧。

转载于:https://www.cnblogs.com/lxinxuan/archive/2006/11/02/547452.html

关于ASP.Net的导入导出的[转]相关推荐

  1. ASP.NET Core 导入导出Excel xlsx 文件

    ASP.NET Core 使用EPPlus.Core导入导出Excel xlsx 文件,EPPlus.Core支持Excel 2007/2010 xlsx文件导入导出,可以运行在Windows, Li ...

  2. ASP.NET 开源导入导出库Magicodes.IE Docker中使用

    更新历史 2019.02.13 [Nuget]版本更新到2.0.2 [导入]修复单列导入的Bug,单元测试"OneColumnImporter_Test".问题见(https:// ...

  3. ASP.NET 开源导入导出库Magicodes.IE 导出Pdf教程

    基础教程之导出Pdf收据 说明 本教程主要说明如何使用Magicodes.IE.Pdf完成Pdf收据导出 要点 导出PDF数据 自定义PDF模板 导出单据 如何批量导出单据 导出特性 PdfExpor ...

  4. asp.net Excel导入导出

    1.Excel数据导入到数据库中: //该方法实现从Excel中导出数据到DataSet中,其中filepath为Excel文件的绝对路径,sheetname为表示那个Excel表:         ...

  5. npoi的mvc怎么ajax导出,asp.net mvc利用NPOI导入导出Excel解决方法

    asp.net mvc利用NPOI导入导出Excel 导出Excel 2003没有问题,导出Excel2007老是出现无法访问已关闭的流,请帮忙解决,或是哪位有mvc导入导出excel的工具类能提供, ...

  6. mvc npoi导出excel ajax,ASP.Net MVC利用NPOI导入导出Excel

    因近期项目遇到所以记录一下: 首先导出Excel: 首先引用NPOI包 http://pan.baidu.com/s/1i3Fosux (Action一定要用FileResult) /// /// 批 ...

  7. 【飞秋】ASP.NET 之 常用类、方法的超级总结,并包含动态的EXCEL导入导出功能,奉上类库源码

    最近闲了,花点几天时间将项目中常用的一些类.方法做了一下总结,希望对大家有用. 实用类:UtilityClass 包含如下方法 判断对象是否为空或NULL,如果是空或NULL返回true,否则返回fa ...

  8. ASP .Net C# ---Excel导入导出方法

    导入导出的方法以及引用,可以自行创建一个帮助类 using System; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using NPOI ...

  9. Magicodes.IE之导入导出筛选器

    总体设计 Magicodes.IE是一个导入导出通用库,支持Dto导入导出以及动态导出,支持Excel.Word.Pdf.Csv和Html.在本篇教程,笔者将讲述如何使用Magicodes.IE的导入 ...

最新文章

  1. [tool] AI视频翻译 解决英文视频字幕问题(类似youtube自动生成字幕)
  2. STL二级配置器allocate的解析
  3. Kubernetes面试题超详细总结
  4. 《大数据分析原理与实践》——习题
  5. perl数组硬引用_Perl个人总结
  6. 软测第二周作业WordCount
  7. JAVA知识基础(一):数据类型
  8. Opencv--addWeighted()
  9. 基于OpenCV实现图像平移
  10. 湖北网络安全的产业机遇在哪里
  11. log4j日志输出配置
  12. Friendster,linkedin,orkut,liring对SNS的求索
  13. 怎么给word文档注音_怎么为整篇word文字添加拼音标注
  14. MediaType介绍
  15. Ubuntu软件包升级失败的终极修复方法
  16. 物质模拟器4.0版 改了bug,爆炸时也可移动
  17. 怎样用html设置文档格式,Dreamweaver使用CSS样式表设置网页文本格式
  18. Http协议和Python调试过程
  19. 纹理 Texture
  20. 继承 多态 抽象类 接口

热门文章

  1. shiro.ini实现授权
  2. leetcode C++ 2. 两数相加 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数
  3. 不同地图坐标系的坐标转换
  4. freeRtos学习笔(2)任务管理
  5. mktime函数实现获取当前系统时间
  6. 【C language】函数指针
  7. CTFshow 反序列化 web269
  8. CTFshow 反序列化 web261
  9. MATLAB常用命令(窗口命令、标点符号特殊功能和帮助命令)
  10. orth--将矩阵正交规范化