2019独角兽企业重金招聘Python工程师标准>>>
最近老系统开发,vs2008开发环境的,用到一个EXCEL的读取和存入操作。本来一开始是用网络上下载的类来实现,而且网站上一大堆,但是发现很多都不是很好,而且解释不清楚,所以自己小结了一下,写了一个.net4.0的类:
开发环境:VS2010 .net4.0
操作系统:win 7
条件:加载Microsoft.Office.Interop.Excel动态库
先上代码:
///
/// 标题:Excel文件助手类
/// 描述:1.读取指定条件的Excel信息到内存中
/// 2.将内存中的信息导出到Excel文件中
/// 3.消除Excel文件中的空白记录
/// 作者:孙继鹏
/// 日期:2013-7-26
///
public static class ExcelHelper
{
#region Field
///
/// 读取Excel的连接字符串
///
///
/// Provider代表连接驱动4.0版本
/// Data Source代表Excel的路径
/// Extended Properties代表连接Excel的版本,对于Excel 97以上版本都用Excel 8.0
/// HDR代表默认Excel第一行是否列名,Yse代表是可以直接读取,No反之
/// IMEX代表
///
private const string strFormat = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = {0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
#endregion
#region Method
///
/// 把指定的DataTable里的空白行去除,返回一个没有空白行的DataTable
///
/// 原始的DataTable
/// 没有空白行的DataTable
public static DataTable DataTableEmptyRowsFilter(DataTable dataTable)
{
DataTable newDataTable = null;
if (dataTable.Rows.Count != 0)
{
newDataTable = dataTable.Clone();
foreach (DataRow dr in dataTable.Rows)
{
if (dr[0].ToString() != string.Empty)
{
newDataTable.ImportRow(dr);
}
}
}
return newDataTable;
}
///
/// 读取Excel文件内指定sheet页的数据到DataSet
///
/// Excel文件完整路径
/// 读取的表格数据
/// sheet名称
/// dataTable名称
/// 操作错误信息,若为空则执行成功
public static string TryRead(string strFilePath, out DataTable dataTable, string strSheetName = "Sheet1", string strNewSheetName = "ExcelInfo")
{
string errormsg = string.Empty;
if (!string.IsNullOrEmpty(strFilePath) && File.Exists(strFilePath))
{
string strConn = string.Format(strFormat, strFilePath);
string strSQL = string.Format("SELECT * FROM [{0}$]", strSheetName);
try
{
using (OleDbDataAdapter ExcelDA = new OleDbDataAdapter(strSQL, strConn))
{
DataSet ExcelDS = new DataSet();
ExcelDA.Fill(ExcelDS, strNewSheetName);
dataTable = DataTableEmptyRowsFilter(ExcelDS.Tables[0]);
}
}
catch (Exception err)
{
errormsg=err.Message;
dataTable = null;
}
}
else
{
errormsg="The file path of the file does not exist";
dataTable = null;
}
return errormsg;
}
///
/// 将DataTable写入指定路径Excel文件
///
///
/// 采用将导出的数据保存到数组,然后一次过导出,以提高速度
/// excelSheet.Merge(Missing.Value); 合并
/// excelSheet.Font.Bold=true; 设置粗体
/// excelSheet.Font.Size=12;设置字体大小
/// excelSheet.HorizontalAlignment=Excel.XlHAlign.xlHAlignCenter;水平对齐设置
/// excelSheet.VerticalAlignment=Excel.XlVAlign.xlVAlignCenter;垂直对齐设置
/// excelSheet.FormulaR1C1=公式; 公式设置
/// excelSheet.ColumnWidth=20; 设置列宽
/// excelSheet.RowHeight=20; 设置行高
///
/// 数据表
/// 导出路径文件夹路径
/// Excel内容开始列,默认为1,第一列为标题
/// Excel内容开始行,默认为1,第一行为标题
public static string DataTableToExcel(DataTable dTable, string strFiledirectPath,int startRow=1, int startCol=1)
{
string errorMsg = string.Empty;
if (dTable == null ||startRow <= 0 || startCol <=0)
{
errorMsg = "DataTable is null";
}
var excel = new Excel.Application();
var excelBook = excel.Workbooks.Add(Type.Missing);
var excelSheet = (Excel.Worksheet)excelBook.ActiveSheet;
var rowCount = dTable.Rows.Count;
var colCount = dTable.Columns.Count;
//二维数组定义是多一个标题行
var dataArray = new object[rowCount + 1, colCount];
for (var j = 0; j < colCount; j++)
{
//导出字段标题
dataArray[0, j] = dTable.Columns[j].Caption;
//根据各列的数据类型设置Excel的格式。
switch (dTable.Columns[j].DataType.ToString())
{
case "System.String":
excelSheet.get_Range(excelSheet.Cells[startRow, startCol + j] as Excel.Range,excelSheet.Cells[rowCount + startRow, startCol + j] as Excel.Range).
NumberFormatLocal = "@";
break;
case "System.DateTime":
excelSheet.get_Range(excelSheet.Cells[startRow, startCol + j] as Excel.Range,excelSheet.Cells[rowCount + startRow, startCol + j] as Excel.Range).
NumberFormatLocal = "yyyy-MM-dd HH:mm:ss";
break;
//可以根据自己的需要扩展。
default:
excelSheet.get_Range(excelSheet.Cells[startRow, startCol + j] as Excel.Range,excelSheet.Cells[rowCount + startRow, startCol + j] as Excel.Range).
NumberFormatLocal= "G/通用格式";
break;
}
for (int i = 0; i < rowCount; i++)
{
dataArray[i + 1, j] = dTable.Rows[i][j];
}
}
//写入Excel Sheet
excelSheet.get_Range(excel.Cells[startRow, startCol] as Excel.Range,excel.Cells[rowCount + startRow, colCount + startCol - 1] as Excel.Range).Value2= dataArray;
//设置列头为粗体字
excelSheet.get_Range(excel.Cells[1, 1] as Excel.Range,excel.Cells[1, colCount] as Excel.Range).Font.Bold = true;
//设置列头底色为灰色
excelSheet.get_Range(excel.Cells[1, 1] as Excel.Range,excel.Cells[1, colCount] as Excel.Range).Interior.ColorIndex = 15;
//设置内容的字体大小为9
excelSheet.get_Range(excel.Cells[2, 1] as Excel.Range,excel.Cells[rowCount + startRow, colCount + startCol - 1] as Excel.Range).Font.Size = 9;
//设置Sheet的名称
excelSheet.Name = dTable.TableName;
//保存文档
try
{
strFiledirectPath = Path.Combine(strFiledirectPath, dTable.TableName + ".xls");
excelBook.Saved = true;
excelBook.SaveCopyAs(strFiledirectPath);
}
catch (Exception ex)
{
errorMsg = ex.Message;
}
finally
{
excel.Quit();
GC.Collect();
}
return errorMsg;
}
#endregion
}
这里面要注意的几个特别的问题:
1.就是Excel的连接字符串,里面的参数必须注意,在注释中都有解释
2.就是在网上很多代码都是老的VS2008,.net2.0 ,当到VS2010中可能就会出现一些问题,比如:
VS2010的.NET4.0下调用Excel对象出现错误:“object”未包含“get_Range”;
eg:
错误代码:excelSheet.get_Range(excelSheet.Cells[startRow, startCol + j] ,excelSheet.Cells[rowCount + startRow, startCol + j]).
NumberFormatLocal = "@";
修正代码:
excelSheet.get_Range(excelSheet.Cells[startRow, startCol + j] as Excel.Range,excelSheet.Cells[rowCount + startRow, startCol + j] as Excel.Range).
NumberFormatLocal = "@";
原因:就是
get_Range()内的参数类型必须统一,貌似原来的就可以,但是VS2010至少就必须类型转换为
Excel.Range,否则编译不会出错,运行时会出错