C#、VSTO讀取Excel類
2024-08-27 22:42:24
之前寫的類存在Excel進程不能結束的Bug,重寫ExcelReader類,類實例清理時Excel進程自動結束。
class ExcelReader
{
// Excel Object
public Application app;
public Workbooks wbs;
public Workbook wb;
public Worksheet ws;
public Range rng; private bool disposed = false; public ExcelReader()
{
// New Excel Application
app = new Application
{
Visible = false,
DisplayAlerts = false
};
} /// <summary>
/// 關閉對象
/// </summary>
public void Close()
{
Dispose();
} /// <summary>
/// 清理對象
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
} /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
// Excel Application Quit
app.Quit(); // Finally, Release app.
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
app = null; disposed = true;
}
} #region Worksheet Operation
/// <summary>
/// 從工作表讀取數據到 DataTable
/// </summary>
/// <param name="fileName">文件</param>
/// <param name="sheet">工作表名</param>
/// <returns>DataTable</returns>
public DataTable GetDataTableFromSheet(string fileName, string sheet, int rows, int cols)
{
// Create Table
DataTable dt = new DataTable(); // Get Excel's WorkBooks. Attention: Don't use .Net cascade, ex.: app.Workbooks.Add()
// Every variable Must set to reference, then Release it one by one.
// If not, Can't quit Excel Process.
wbs = app.Workbooks; // Get WorkBook
wb = wbs.Open(fileName); // Get WorkSheet
ws = wb.Sheets[sheet]; // Columns & Rows Count
//int colCount = ws.UsedRange.CurrentRegion.Columns.Count;
//int rowCount = ws.UsedRange.CurrentRegion.Rows.Count; // Get worksheet's used range
//rng = ws.UsedRange;
rng = ws.Range[ws.Range["A1"], ws.Range[GetColumnName(cols)+rows]];
dt = GetDataTableFromRange(rng, rows, cols); // Relase Range, Set to null. (variable reference that COM Object's Count is 0)
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(rng);
rng = null; // Release WorkSheet
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ws);
ws = null; // Release WorkBook
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wb);
wb = null; // Release WorkBooks
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wbs);
wbs = null; return dt;
}
#endregion #region Range Operation
/// <summary>
/// 從單元格範圍讀取數據到 DataTable
/// </summary>
/// <param name="range">單元格範圍</param>
/// <returns>DataTable</returns>
private DataTable GetDataTableFromRange(Range range, int rows, int cols)
{
DataTable dataTable = new DataTable(); // First Row Range
Range titleRange = range.Rows[]; // Columns Count
//int colCount = titleRange.CurrentRegion.Columns.Count; // Title Row has Empty Cell Or Replication, Use Excel Column Header.
if (titleRange.Cells.Cast<Range>().Any(s => s.Value2 == null)
|| titleRange.Cells.Cast<Range>().GroupBy(s => s.Value2).Count() != titleRange.Cells.Count
|| titleRange.CurrentRegion.Columns.Count != cols)
{
for (int i = ; i <= cols; i++)
{
dataTable.Columns.Add(GetColumnName(i), typeof(string));
}
}
else
dataTable = GetTableStructureFromTitleRange(range); // Release Range Object
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(titleRange);
titleRange = null; // Insert Data To DataTable Wtih Range Value
object[,] arr = range.Value;
for (int i = ; i < arr.GetLength(); i++)
{
DataRow dr = dataTable.NewRow();
for (int j = ; j < arr.GetLength(); j++)
{
if (arr[i + , j + ] != null)
dr[j] = arr[i + , j + ];
else
dr[j] = "";
} dataTable.Rows.Add(dr);
} return dataTable;
} /// <summary>
/// 生成表頭。如果首行表頭規範,則採用首行表頭,否則用Excel表頭代替
/// </summary>
/// <param name="titleRow">首行範圍</param>
/// <param name="isAllString">全部採用字符串格式</param>
/// <returns>DataTable</returns>
private DataTable GetTableStructureFromTitleRange(Range titleRow, bool isAllString = true)
{
DataTable dataTable = new System.Data.DataTable();
foreach (Range cell in titleRow.Cells)
{
if (isAllString)
dataTable.Columns.Add(cell.Value2, typeof(string));
else
dataTable.Columns.Add(cell.Value2, typeof(object));
}
return dataTable;
}
#endregion #region Column Operation
/// <summary>
/// 使用 Excel 標頭的方式生成字母列頭
/// </summary>
/// <param name="index">索引號</param>
/// <returns>字母列頭</returns>
public string GetColumnName(int index)
{
var dividend = index;
var columnName = string.Empty; while (dividend > )
{
var modulo = (dividend - ) % ;
columnName = Convert.ToChar( + modulo) + columnName;
dividend = (dividend - modulo) / ;
} return columnName;
}
#endregion
}
最新文章
- Unity3d游戏场景优化杂谈(2)
- 使用Plsql将Excel数据导入Oracle数据库
- linux shell中的&;&; || 和()
- 【Mood-8】IT男!五更天!
- 第27章 项目8:使用XML-RPC进行文件共享
- Cocos2d-x ios 下http请求的另一种实现
- pecl/mongo is already installed
- Windowsclient开发简单介绍(四)
- 一个想法照进现实-《IT连》创业项目:聊聊IT连App是如何思考解决IT人员单身问题的
- Linux学习_012_Centos 6.8 安装 Netcat
- django 2.接口之工作原理
- 工作随笔—Java容器基础知识分享(持有对象)
- pymysql的使用
- VMware下安装Ubuntu18.04时vmware tools安装问题
- ospf精确宣告地址
- 深浅copy和字符串细节方法
- 查看Android内存的8中方法
- 对不队——Alpha冲刺
- 笔记 jquery 的一个bug解决方法积累
- FIS3常用配置
热门文章
- 1053 Path of Equal Weight (30)(30 分)
- 【Lintcode】062.Search in Rotated Sorted Array
- 【LeetCode】047. Permutations II
- Visual Studio 编译后去掉只读属性
- cocos2dx 获取精灵的高亮效果
- 绝对路径VS相对路径
- [hdu2874]Connections between cities(LCA+并查集)
- 常用的Elasticseaerch检索技巧汇总
- C#—反射(反射类型、方法、构造函数、属性、实现可配置可扩展、数据库访问类反射封装)
- Jmeter获取登录的token