C#、VSTO讀取Excel類
之前寫的類存在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類的更多相关文章
- PHPExcel讀取excel數據
require_once 'PHPExcel.php'; $PHPReader = new PHPExcel_Reader_Excel2007(); $filePath = 'wjyl.xlsx'; ...
- POI 讀取EXCEL
/*** 獲取單元格數值* * @param cell* @return*/private String getCellValue(Cell cell) {String cellValue = &qu ...
- Android Training精要(五)讀取Bitmap對象實際的尺寸和類型
讀取Bitmap對象實際的尺寸和類型 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecode ...
- 【WIN10】程序內文件讀取與保存
DEMO下載:http://yunpan.cn/cFHIZNmAy4ZtH 访问密码 cf79 1.讀取與保存文件 Assets一般被認為是保存用戶文件數據的地方.同時,微軟還支持用戶自己創建文件夾 ...
- 讓 SourceTree 讀取自定的 SSH key
我目前都在 Mac 底下開發,用 Git 來管理我的程式碼,比較一番之後決定用 SourceTree 來做為 Git client.SourceTree 是一款 Mac 底下的版本控制系統 clien ...
- MailSystem.NET Gmail IMAP讀取信件
程式的主流程為: 開啟SSL連線,逐一讀取收信匣中的信件,將信件內文HTML及附檔逐一存檔後,再將信件移至垃圾桶. 程式碼如下,補充說明我寫在註解裡,請參考: static void Main(str ...
- 如何使用VSTO自动将Excel中的图表复制到Word
如何使用VSTO自动将Excel中的图表复制到Word 原文地址:https://code.msdn.microsoft.com/How-to-copy-Chart-in-Excel-a29f9029 ...
- asp.net C#取Excel 合并单元格内容
asp教程.net c#取excel 合并单元格内容读取excel数据,填充dataset// 连接字符串 string xlspath = server.mappath("~/www.11 ...
- 設定 gpio 為 讀取用途,需注意的參數
Schematic 解說 上面的 線路圖, R1 R2 只能有一個被接上, R3 R4 只能有一個被接上, 是使用 gpio 讀取 電壓 判斷為0 或是 1 這時的 gpio 設定,其中一個參數需設為 ...
随机推荐
- Python连接Mysql数据库_20160928
python版本 2.7.1,python 连接mysql需要安装MYSQLdb模块 安装方法一种是cmd pip命令安装 pip install MySQLdb 一种是网上下载python MYSQ ...
- HP SiteScope安装
下载地址以及安装方法见 http://www.jianshu.com/p/fce30e333578 数据库连接URL:jdbc:mysql://mysql_ip:mysql_port/database ...
- Azure一个Cloud Service支持多个公网地址
Azure刚刚发布在同一个Cloud Service下支持多个公网IP地址的功能. 这个功能主要是用于: 当相同的端口需要公用相同的LoadBalance时. 比如: 一种使用场景是多组Web服务器被 ...
- ambari快速安装hadoop
资源下载http://www.cnblogs.com/bfmq/p/6027202.html 大家都知道hadoop包含很多的组件,虽然很多都是下载后解压简单配置下就可以用的,但是还是耐不住我是一个懒 ...
- 【239】◀▶IEW-Unit04
Unit 4 Youth Issues: Computer Use 1 Model1题目及范文分析 Some teenagers spend a lot of time playing compute ...
- nohup开机自启脚本
#!/bin/bash cd /root/xcloud/ str=$"/n" sstr=$(echo -e $str) nohup ./deploy >>/dev/nu ...
- opencvsharp BitmapSource图片截取问题
private BitmapSource GetUiImage(FrameworkElement ui) { RenderTargetBitmap bmp=new RenderTargetBitmap ...
- 二维数组是二级指针pointer to pointer!
二维数组居然是个类似于二级指针(pointer to pointer)的东西,十分震惊! #include <stdio.h> int main() { ][]={{,,,},{,,,}, ...
- Protobuf 文件生成工具 Prototool 命令详解
Protobuf 文件生成工具 Prototool 命令详解 简介 Prototool 是 Protobuf 文件的生成工具, 目前支持go, php, java, c#, object c 五种语言 ...
- # program once 用途 及与 ifndef使用异同
在头文件中用这种写法就是为了该头文件被重复包含时不会出现符合重定义的错误. 效果等同于 #ifndef __xxx__ #define __xxx__ ... #endi ...