[C#] 抓取 Excel 合併儲存格內容

  • 22903
  • 0

[C#] 抓取 Excel 合併儲存格內容

 

有大陸同事詢問合併儲存格問題,把資料整理放到 Blog 中

 

需求說明

有一個 Excel 文件內容如下圖所示,其中 A2 到 A5 是合併儲存格(跨欄置中),A6 到 A10 是合併儲存格。

image

 

使用 Microsoft.Office.Interop.Excel 使用 Cells.Text 抓儲存格資料時,只有合併儲存格範圍,最左上角的儲存格有資料,如下圖所示。

image

 

程式碼如下所示:


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 控制項是否包含合併儲存格的值。

http://msdn.microsoft.com/zh-tw/library/microsoft.office.tools.excel.namedrange.mergecells(v=vs.80).aspx

NamedRange.MergeArea 屬性:取得 Microsoft.Office.Interop.Excel.Range,表示 NamedRange 控制項包含合併的範圍。

http://msdn.microsoft.com/zh-tw/library/microsoft.office.tools.excel.namedrange.mergearea(v=vs.80).aspx

 

新增判斷邏輯如下:

1. 判斷 MergeCells 屬性,如果是 True 的話,表示是合併儲存格,需進一步處理。

2. 如果是合併儲存格的話,透過 MergeArea 取得合併範圍,其中 MergeCells.Row 與 MergeCells.Column 即為左上角儲存格位置,抓取此儲存格資料。

修改的程式碼如下圖紅色框所示:

image

 

執行結果

image

 

完整程式碼


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效能會比較好
        }
    }
}

 

程式碼下載

WinFormExcel.zip