之前寫的類存在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. ASM认证与口令文件

    ASM认证 ORACLE ASM 实例没有数据字典,所以连接ASM 实例只能通过如下三种系统权限来进行连接: SYSASM,SYSDBA,SYSOPER. 可以通过如下三种模式来连接ASM 实例:1. ...

  2. VS中运行后控制台窗口一闪就没了

    使用VS2010后,用Ctrl+F5运行程序,结果控制台窗口一闪就没了,也没有出现”press any key to continue…” 或者“请按任意键继续”. 出现这种原因,主要是建立工程时选用 ...

  3. sql server 2012 profiler打开2016的profiler

    软件环境:1.本机是sql server 2012,远程服务器是sql server 20162.本机是Windows 7,安装不了sql server 2016 问题场景1:本机sql server ...

  4. unreal4特性介绍

    原文地址:   https://www.unrealengine.com/products/unreal-engine-4     unreal enginer介绍 我的UE4学习(一) 你曾想过用连 ...

  5. [Xcode 实际操作]五、使用表格-(9)删除UITableView单元格(手势左滑调出删除按钮)

    目录:[Swift]Xcode实际操作 本文将演示如何删除某一行单元格.手势左滑调出删除按钮. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIK ...

  6. SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.Cache缓存简介 从Spring3开始定义Cache和Cac ...

  7. Spring+SpringMVC+JDBC实现登录

    Spring+SpringMVC+JDBC实现登录 有一位程序员去相亲的时候,非常礼貌得说自己是一名程序员,并解释自己是做底层架构的,于是女方听到"底层"两个字,就一脸嫌弃:什么时 ...

  8. mysql--浅谈多表查询1

    这是对自己学习燕十八老师mysql教程的总结,非常感谢燕十八老师. 依赖软件:mysql5.6 系统环境:win 连接查询 在谈连接查询之前我们需要对数学上的笛卡尔积有一定的了解 现在有两个集合m和n ...

  9. jquery jtemplates.js模板渲染引擎的详细用法第二篇

    jquery jtemplates.js模板渲染引擎的详细用法第二篇 关于jtemplates.js的用法在第一篇中已经讲过了,这里就直接上代码,不同之处是绑定模板的方式,这里讲模板的数据专门写一个t ...

  10. IOS 打包提示 No iTunes Connect access for the team

    1.可以在提示页直接点击 Manage Accounts按钮,进去页面后,选择开发者账号点减号删除:(或者在Xcode中直接按command+键进入,选择accounts,选中账号按-键删除) 2.完 ...