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 設定,其中一個參數需設為 ...
随机推荐
- P1150 Peter的烟
题目描述 Peter有n根烟,他每吸完一根烟就把烟蒂保存起来,k(k>1)个烟蒂可以换一个新的烟,那么Peter最终能吸到多少根烟呢? 输入输出格式 输入格式: 每组测试数据一行包括两个整数n( ...
- 【C++基础】形参实参
c++规定:一个函数的默认实参既可以在定义中,也可在声明中指定,但在一个文件(准确的说,是一个作用域)中只能为一个形参指定默认实参一次
- poj2127——LCIS
题目:http://poj.org/problem?id=2127 LCIS,注意存储路径的方法. 代码如下: #include<iostream> #include<cstdio& ...
- Enum定义位域, 即可以通过位操作来产生未命名的值
通过FlagsAttribute可以实现. // A bit field or flag enumeration of harvesting seasons. [Flags] public enum ...
- 使用XMLConfiguration解析xml,PropertiesConfiguration解析properties等相应信息
org.apache.commons.configuration.XMLConfiguration; Apache Common-Configuration工具可以从Properties文件,XML文 ...
- LabVIEW - 破解加密vi
步骤 使用二进制阅读软件打开加密vi 查找字段"00 00 00 30",其后的16位即可能是密码(可能查找到多个位置带有该字段,只有其中之一为密码位置) 将查找到的密码复制到MD ...
- ABP 软删除ISoftDelete
一.简介 ABP 的软删除是为了,在删除的时候,不是真正的删除数据,是为了保护数据. 二.具体实现 在 Core 层,我们需要这个实体去实现这个 ISoftDelete 接口.实现它的 public ...
- qemu编译
符号说明 $ 表示在用户模式下执行命令 # 表示在root模式下执行命令 ### 表示注释用于解释接下来一条命令的作用 更新环境源 设置阿里源 $ sudo mv /etc/yum.repos.d/C ...
- 洛谷 - P1631 - 序列合并 - 堆
https://www.luogu.org/problemnew/show/P1631 序列a中每个数首先都和序列b中的最小元素配对(虽然好像不是很必要这么早插进来?) 每次从堆顶取出最小的和输出答案 ...
- 仿iPhone、iPad界面滑屏切换
<!DOCTYPE html> <html lange='en'> <head> <meta charset='UTF-8'> <title> ...