之前寫的類存在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
}

C#、VSTO讀取Excel類的更多相关文章

  1. PHPExcel讀取excel數據

    require_once 'PHPExcel.php'; $PHPReader = new PHPExcel_Reader_Excel2007(); $filePath = 'wjyl.xlsx'; ...

  2. POI 讀取EXCEL

    /*** 獲取單元格數值* * @param cell* @return*/private String getCellValue(Cell cell) {String cellValue = &qu ...

  3. Android Training精要(五)讀取Bitmap對象實際的尺寸和類型

    讀取Bitmap對象實際的尺寸和類型 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecode ...

  4. 【WIN10】程序內文件讀取與保存

    DEMO下載:http://yunpan.cn/cFHIZNmAy4ZtH  访问密码 cf79 1.讀取與保存文件 Assets一般被認為是保存用戶文件數據的地方.同時,微軟還支持用戶自己創建文件夾 ...

  5. 讓 SourceTree 讀取自定的 SSH key

    我目前都在 Mac 底下開發,用 Git 來管理我的程式碼,比較一番之後決定用 SourceTree 來做為 Git client.SourceTree 是一款 Mac 底下的版本控制系統 clien ...

  6. MailSystem.NET Gmail IMAP讀取信件

    程式的主流程為: 開啟SSL連線,逐一讀取收信匣中的信件,將信件內文HTML及附檔逐一存檔後,再將信件移至垃圾桶. 程式碼如下,補充說明我寫在註解裡,請參考: static void Main(str ...

  7. 如何使用VSTO自动将Excel中的图表复制到Word

    如何使用VSTO自动将Excel中的图表复制到Word 原文地址:https://code.msdn.microsoft.com/How-to-copy-Chart-in-Excel-a29f9029 ...

  8. asp.net C#取Excel 合并单元格内容

    asp教程.net c#取excel 合并单元格内容读取excel数据,填充dataset// 连接字符串 string xlspath = server.mappath("~/www.11 ...

  9. 設定 gpio 為 讀取用途,需注意的參數

    Schematic 解說 上面的 線路圖, R1 R2 只能有一個被接上, R3 R4 只能有一個被接上, 是使用 gpio 讀取 電壓 判斷為0 或是 1 這時的 gpio 設定,其中一個參數需設為 ...

随机推荐

  1. MySQL三个列组成唯一值查询_开源中国问题练习_20161026

    问题地址:https://www.oschina.net/question/2923955_2202674 按 service_collect_day分类以后,按 app_id,node_id,ser ...

  2. kettle及数据库导数_20160920

    一.kettle是什么. Kettle是一款国外开源的ETL( Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载 ...

  3. [转]addEventListener的第三个参数

    如果要把HTML元素的事件与某个函数绑定起来,可以有下面三种方法,以最常见的“点击”事件为例. 方法一: 直接在对应的HTML元素标签上绑定函数 ? 1 <button id='submit'  ...

  4. C++ ADO连接

    #include "stdafx.h" #include <iostream> #include <iomanip> #include "wind ...

  5. orcale用户名的创建及权限设置

    oracle数据库的权限系统分为系统权限与对象权限.系统权限( database system privilege )可以让用户执行特定的命令集.例如,create table权限允许用户创建表,gr ...

  6. 响应式web设计,html5和css3实战(@author Ben Fraim)

    重定向 //请求重定向简化写法 response.sendRedirect("/day09/adv.html"); 转发 request.getRequestDispatcher( ...

  7. UVa 714 Copying books 贪心+二分 最大值最小化

    题目大意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相 ...

  8. java-并发-进程和线程

    浏览以下内容前,请点击并阅读 声明 软件的并发是指同时做多件事情,java平台一开始就支持并发编程,java编程语言以及类库含有对并发最基本的支持,从5.0版本开始,java平台开始包含一些高并发的A ...

  9. 【239】◀▶IEW-Unit04

    Unit 4 Youth Issues: Computer Use 1 Model1题目及范文分析 Some teenagers spend a lot of time playing compute ...

  10. hadoop学习笔记之-hbase完全分布模…

    安装环境: OS: Oracle linux 5.6 JDK: jdk1.6.0_18 Hadoop: hadoop-0.20.2 Hbase: hbase-0.90.5 安装准备: 1. Jdk环境 ...