[C#] 抓取 Excel 合併儲存格內容
有大陸同事詢問合併儲存格問題,把資料整理放到 Blog 中
需求說明
有一個 Excel 文件內容如下圖所示,其中 A2 到 A5 是合併儲存格(跨欄置中),A6 到 A10 是合併儲存格。
使用 Microsoft.Office.Interop.Excel 使用 Cells.Text 抓儲存格資料時,只有合併儲存格範圍,最左上角的儲存格有資料,如下圖所示。
程式碼如下所示:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WinFormExcel
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Excel.Application _Excel = null;
string pFileName = Application.StartupPath + "\\excel.xlsx";
private void btnProcess_Click(object sender, EventArgs e)
{
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
Excel.Range range = null;
try
{
book = _Excel.Workbooks.Open(pFileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);//開啟舊檔案
sheet = (Excel.Worksheet)book.Sheets[1];
range = sheet.get_Range("A1", "A10");
foreach (Excel.Range item in range)
{
string strData = string.Format("[{0},{1}] = {2}",item.Cells.Column,item.Cells.Row,item.Cells.Text);
lbData.Items.Add(strData);
}
}
finally
{
book.Close(Type.Missing, Type.Missing, Type.Missing);
book = null;
}
}
private void Form1_Load(object sender, EventArgs e)
{
initailExcel();
}
/// <summary>
/// 初始化 Excel
/// </summary>
void initailExcel()
{
//檢查PC有無Excel在執行
bool flag = false;
foreach (var item in Process.GetProcesses())
{
if (item.ProcessName.Equals("EXCEL"))
{
flag = true;
break;
}
}
if (!flag)
{
this._Excel = new Excel.Application();
}
else
{
object obj = Marshal.GetActiveObject("Excel.Application"); //引用已在執行的Excel
_Excel = obj as Excel.Application;
}
this._Excel.Visible = false; //設false效能會比較好
}
}
}
如果我想要合併儲存格範圍內,都可以抓到資料的話,該怎麼做?
方法
我們利用兩個屬性
NamedRange.MergeCells 屬性:取得或設定指出 NamedRange 控制項是否包含合併儲存格的值。
NamedRange.MergeArea 屬性:取得 Microsoft.Office.Interop.Excel.Range,表示 NamedRange 控制項包含合併的範圍。
新增判斷邏輯如下:
1. 判斷 MergeCells 屬性,如果是 True 的話,表示是合併儲存格,需進一步處理。
2. 如果是合併儲存格的話,透過 MergeArea 取得合併範圍,其中 MergeCells.Row 與 MergeCells.Column 即為左上角儲存格位置,抓取此儲存格資料。
修改的程式碼如下圖紅色框所示:
執行結果
完整程式碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WinFormExcel
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Excel.Application _Excel = null;
string pFileName = Application.StartupPath + "\\excel.xlsx";
private void btnProcess_Click(object sender, EventArgs e)
{
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
Excel.Range range = null;
try
{
book = _Excel.Workbooks.Open(pFileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);//開啟舊檔案
sheet = (Excel.Worksheet)book.Sheets[1];
range = sheet.get_Range("A1", "A10");
foreach (Excel.Range item in range)
{
string strData = string.Format("[{0},{1}] = {2}", item.Cells.Column, item.Cells.Row, item.Cells.Text);
// 1. 判斷 MergeCells 屬性,如果是 True 的話,表示是合併儲存格
if (item.Cells.MergeCells == true)
{
// 2. 如果是合併儲存格的話,透過 MergeArea 取得合併範圍,
// 其中 MergeCells.Row 與 MergeCells.Column 即為左上角儲存格位置,抓取此儲存格資料。
var MergeAreaCell = sheet.Cells[item.MergeArea.Row, item.MergeArea.Column];
strData = string.Format("[{0},{1}] = {2}", item.Cells.Column, item.Cells.Row, MergeAreaCell.Cells.Text);
}
lbData.Items.Add(strData);
}
}
finally
{
book.Close(Type.Missing, Type.Missing, Type.Missing);
book = null;
}
}
private void Form1_Load(object sender, EventArgs e)
{
initailExcel();
}
/// <summary>
/// 初始化 Excel
/// </summary>
void initailExcel()
{
//檢查PC有無Excel在執行
bool flag = false;
foreach (var item in Process.GetProcesses())
{
if (item.ProcessName.Equals("EXCEL"))
{
flag = true;
break;
}
}
if (!flag)
{
this._Excel = new Excel.Application();
}
else
{
object obj = Marshal.GetActiveObject("Excel.Application"); //引用已在執行的Excel
_Excel = obj as Excel.Application;
}
this._Excel.Visible = false; //設false效能會比較好
}
}
}