C# winform 可視化操作 Excel文件並讀取數據


 

本人近期接到一個任務,要求開發一個可以操作和讀取Excel文件的軟件。

花了幾天時間開發完成。本機跑的可以,兼容性還待檢測。

 

解決方案:

 dsoframer.ocx  + Microsoft.Office.Interop.Excel

dsoframer.ocx 是用來可視化操作office文件的C#控件,Microsoft.Office.Interop.Excel 是用來操作和讀取的控件。

 

效果圖如下:

這個是可視化操作,導入excel文件,可以刪除行,當然所有的excel操作都可以,已測試wps和Microsoft office 軟件都可以正常讀取和操作。導入數據是將excel數據讀取到DataTable 中。

第一行和第一列是通過代碼添加的,具體實現方式將在下面貼出來。

 

DataTable 讀取到數據展示如下:

  

 

 

代碼部分:

using System;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Data.OleDb;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace ReadExcel
{
    public partial class Form1 : Form
    {
        private AxDSOFramer.AxFramerControl m_axFramerControl = new AxDSOFramer.AxFramerControl();
        System.Data.DataTable dtEnd = new System.Data.DataTable();
        bool isOpenExcel = false;
        public Form1()
        {
            InitializeComponent();
        }


        #region 按鈕事件
        private void button1_Click(object sender, EventArgs e)
        {
            //讀取excel
            OpenFileDialog dia = new OpenFileDialog();
            dia.Filter = "公路計價文件(*.xls)|*.xls;*.xlsx";
            dia.FilterIndex = 0;
            dia.ShowDialog();
            if (string.IsNullOrEmpty(dia.FileName))
            {
                return;
            }
            if (isOpenExcel == true)//先關閉已打開的excel
            {
                try
                {
                    CloseFrom();
                }
                catch (Exception)
                {
                }
            }

            //復制到本地 因為快捷方式可以用,修改后可以保存,會導致修改源文件
            string tempFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TempFile");
            if (!System.IO.Directory.Exists(tempFile)) System.IO.Directory.CreateDirectory(tempFile);
            string tempExcelPath = Path.Combine(tempFile, "tempExcel" + Path.GetExtension(dia.FileName));
            System.IO.File.Copy(dia.FileName, tempExcelPath, true);

            try
            {

                //打開本地excel 
                Init(tempExcelPath);
                isOpenExcel = true;

                try
                {
                    //所有的sheet都應該增加
                    object documentExcel = m_axFramerControl.ActiveDocument;
                    //// 獲取當前工作薄
                    Workbook workbook = (Microsoft.Office.Interop.Excel.Workbook)documentExcel;
                    foreach (Worksheet worksheet in workbook.Sheets)
                    {
                        if (worksheet != null)
                        {
                            int columnsint = worksheet.UsedRange.Cells.Columns.Count;//得到列數  
                            int rowsint = worksheet.UsedRange.Rows.Count; //得到行數
                            if (rowsint == 1) continue;
                            #region  增加行
                            Range range = (Range)worksheet.Rows[1, Type.Missing];
                            //object   Range.Insert(object   shift,   object   copyorigin);     
                            //shift:   Variant類型,可選。指定單元格的調整方式。可以為下列   XlInsertShiftDirection   常量之一:   
                            //xlShiftToRight   或   xlShiftDown。如果省略該參數,Microsoft   Excel   將根據區域形狀確定調整方式。   
                            range.Insert(XlInsertShiftDirection.xlShiftDown, Type.Missing);

                            System.Data.DataTable dt = new System.Data.DataTable();
                            dt.Columns.Add("Name");
                            DataRow dr = dt.NewRow();
                            dr[0] = "姓名";
                            dt.Rows.Add(dr);
                            DataRow dr1 = dt.NewRow();
                            dr1[0] = "性別";
                            dt.Rows.Add(dr1);
                            DataRow dr2 = dt.NewRow();
                            dr2[0] = "年齡";
                            dt.Rows.Add(dr2);
                            DataRow dr3 = dt.NewRow();
                            dr3[0] = "地址";
                            dt.Rows.Add(dr3);
                            range = worksheet.get_Range("A1", ToName(columnsint - 1) + "1"); 
                            range.RowHeight = 30;
                            range.Font.Bold = true;
                            string strName = GetNameFromDt(dt);
                            //綁定下拉列表
                            range.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, strName, Type.Missing);//Name就是上面獲取的列表
                            // range.Validation.Modify(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, Type.Missing, strName, Type.Missing);//單元格已設置數據有效性,只能用代碼修改有效性;如果單元格未設置有效性,需要使用 Add 方法

                            // 填充值
                            worksheet.Cells[1, 1] = "姓名";
                            worksheet.Cells[1, 2] = "性別";
                            worksheet.Cells[1, 3] = "年齡";
                            worksheet.Cells[1, 4] = "地址";
                            #endregion

                            #region 增加列
                            Range xlsColumns = (Range)worksheet.Columns[1, Type.Missing];
                            xlsColumns.Insert(XlInsertShiftDirection.xlShiftToRight, Type.Missing);


                            System.Data.DataTable dtColumn = new System.Data.DataTable();
                            dtColumn.Columns.Add("Name");
                            DataRow drcol = dtColumn.NewRow();
                            drcol[0] = "有效行";
                            dtColumn.Rows.Add(drcol);
                            DataRow drcol1 = dtColumn.NewRow();
                            drcol1[0] = "無效行";
                            dtColumn.Rows.Add(drcol1);
                            strName = GetNameFromDt(dtColumn);

                            //綁定下拉列表
                            //xlsColumns = (Range)worksheet.Columns[1, Type.Missing];
                            xlsColumns = worksheet.get_Range("A2", "A"+ (rowsint+1).ToString());
                            xlsColumns.Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, XlFormatConditionOperator.xlBetween, strName, Type.Missing);//Name就是上面獲取的列表
                            xlsColumns.ColumnWidth = 20;
                            // 填充值
                            xlsColumns.Value = "有效行";
                            #endregion
                            Range m_objRange = worksheet.get_Range("A1", Type.Missing);
                            m_objRange.Borders[XlBordersIndex.xlDiagonalDown].ColorIndex = XlColorIndex.xlColorIndexAutomatic;
                            m_objRange.Value = "           識別行\r\n  設置列";
                        }
                    }


                }
                catch (Exception ex)
                {

                    throw;
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show("打開失敗!" + ex.ToString());
            }
        }

        /// <summary>
        /// 讀取쫽뻝
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (!isOpenExcel)
            {
                MessageBox.Show("未導入Excel文件!");
                return;
            }
            object documentExcel = m_axFramerControl.ActiveDocument;

            #region 保存本地讀取方法 存在的問題是多個sheet 不知道讀取哪個,下面的方法可以讀取當前活動頁
            ////另存為excel
            //string filePath = "F:\\111.xls";
            //m_axFramerControl.SaveAs(filePath, true);//另存為xls       

            ////讀取excel 到datatable
            //System.Data.DataTable dt = GetDataFromExcel(filePath);
            #endregion

            try
            {
                //先保存本地,不然在修改中的單元格依然讀取的是原數據
                m_axFramerControl.SaveAs(m_axFramerControl.DocumentFullName, true);//另存為xls  


                //// 獲取當前工作薄
                Workbook workbook = (Microsoft.Office.Interop.Excel.Workbook)documentExcel;
                Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.ActiveSheet;

                if (worksheet != null)
                { // 取得總記錄行數(包括標題列)
                    int rowsint = worksheet.UsedRange.Rows.Count; //得到行數
                    int columnsint = worksheet.UsedRange.Cells.Columns.Count;//得到列數
                    //取得數據范圍區域 (標題列) 
                    Range rng1 = worksheet.Cells.get_Range("A1", ToName(columnsint - 1) + "1");   //item
                    object[,] arryItem = (object[,])rng1.Value2;
                    string[] tmp = new string[columnsint];
                    for (int i = 0; i < columnsint; i++)
                    {
                        if (arryItem[1, i + 1] == null)
                            continue;
                        tmp[i] = arryItem[1, i + 1].ToString();
                    }

                    Range mRange = worksheet.get_Range("A2", ToName(columnsint - 1) + rowsint);

                    object[,] mArray = (object[,])mRange.Formula;
                    string[,] myStrArr = new string[rowsint - 1, columnsint];
                    for (int i = 0; i < rowsint - 1; i++)
                    {
                        for (int j = 0; j < columnsint; j++)
                        {
                            myStrArr[i, j] = mArray[i + 1, j + 1].ToString();
                        }
                    }

                    dtEnd = ConvertToDataTable(tmp, myStrArr);
                    MessageBox.Show("讀取成功!");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("讀取失敗!" + ex.ToString());
            }


        }
        private void btn_deleteRow_Click(object sender, EventArgs e)
        {
            if (!isOpenExcel)
            {
                MessageBox.Show("未導入Excel文件!");
                return;
            }
            //先保存本地,不然在修改中的單元格依然讀取的是原數據
            m_axFramerControl.SaveAs(m_axFramerControl.DocumentFullName, true);//另存為xls  

            object documentExcel = m_axFramerControl.ActiveDocument;

            Range excelRange = GetSelectionCell(documentExcel);
            if (excelRange == null)
            {
                MessageBox.Show("未選擇單元格或行!");
                return;
            }
            excelRange.Select();
            excelRange.EntireRow.Delete(XlDeleteShiftDirection.xlShiftUp);

        }

        /// <summary>
        /// 顯示數據
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2(this.dtEnd);
            frm.ShowDialog();

        }
        #endregion


        #region AxFramerControl Excel 的加載

        //總的加載Excel方法
        private void Init(string _ExcelFilePath)
        {
            try
            {
                RegControl();

                if (!File.Exists(_ExcelFilePath))
                {
                    MessageBox.Show("文件不存在或未標識的文件格式!", "提示信息");
                    return;
                    //throw new ApplicationException("文件不存在或未標識的文件格式!");
                }

                AddAxFramerControl();//加載填充控件
                m_axFramerControl.Titlebar = false;//是否顯示excel標題欄
                m_axFramerControl.Menubar = false;//是否顯示excel的菜單欄
                m_axFramerControl.Toolbars = false;//是否顯示excel的工具欄

                InitOfficeControl(_ExcelFilePath);
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        //第二步:向panel填充AxFramerControl控件
        private void AddAxFramerControl()
        {
            try
            {
                this.panel1.Controls.Add(m_axFramerControl);
                m_axFramerControl.Dock = DockStyle.Fill;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                throw;
            }

        }

        //第一步:注冊AxFramerControl
        public bool RegControl()
        {
            try
            {
                Assembly thisExe = Assembly.GetExecutingAssembly();
                System.IO.Stream myS = thisExe.GetManifestResourceStream("NameSpaceName.dsoframer.ocx");

                string sPath = System.AppDomain.CurrentDomain.BaseDirectory + @"\dsoframer.ocx";
                ProcessStartInfo psi = new ProcessStartInfo("regsvr32", "/s " + sPath);
                Process.Start(psi);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return true;
        }

        //下面這個方法是dso打開文件時需要的一個參數,代表office文件類型
        /// <summary>
        /// 根據后綴名得到打開方式
        /// </summary>
        /// <param name="_sExten"></param>
        /// <returns></returns>
        private string LoadOpenFileType(string _sExten)
        {
            try
            {
                string sOpenType = "";
                switch (_sExten.ToLower())
                {
                    case "xls":
                    case "xlsx":
                        sOpenType = "Excel.Sheet";
                        break;
                    case "doc":
                    case "docx":
                        sOpenType = "Word.Document";
                        break;
                    case "ppt":
                        sOpenType = "PowerPoint.Show";
                        break;
                    case "vsd":
                    case "vsdx":
                        sOpenType = "Visio.Drawing";
                        break;
                    default:
                        sOpenType = "Word.Document";
                        break;
                }
                return sOpenType;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 第三步:初始化office控件,加載Excel
        /// </summary>
        /// <param name="_sFilePath">本地文檔路徑</param>
        private void InitOfficeControl(string _sFilePath)
        {
            try
            {
                if (m_axFramerControl == null)
                {
                    throw new ApplicationException("請先初始化office控件對象!");
                }

                //this.m_axFramerControl.SetMenuDisplay(48);
                //這個方法很特別,一個組合菜單控制方法,我還沒有找到參數的規律,有興趣的朋友可以研究一下
                string sExt = System.IO.Path.GetExtension(_sFilePath).Replace(".", "");
                //this.m_axFramerControl.CreateNew(this.LoadOpenFileType(sExt));//創建新的文件
                this.m_axFramerControl.Open(_sFilePath, false, this.LoadOpenFileType(sExt), "", "");//打開文件
                //隱藏標題
                this.m_axFramerControl.Titlebar = false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 關閉當前界面
        /// </summary>
        public void CloseFrom()
        {
            try
            {
                if (this.m_axFramerControl != null)
                {
                    this.m_axFramerControl.Close();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                CloseFrom();
            }
            catch (Exception)
            {
            }
        }
        #endregion


        #region 方法
        // 獲得當前窗體
        Window GetActiveWindow(object Document)
        {
            if (Document == null)
            {
                return null;
            }

            Workbook workbook = null;
            Worksheet worksheet = null;
            try
            {
                //// 獲取當前工作薄
                workbook = (Microsoft.Office.Interop.Excel.Workbook)Document;
                //// 獲取當前工作頁
                worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.ActiveSheet;
                Window window = null;

                if (worksheet != null)
                {
                    //// 獲取當前活動窗口
                    window = worksheet.Application.ActiveWindow;
                }

                return window;
            }
            catch
            {
                return null;
            }
        }
        Range GetSelectionCell(object Document)
        {
            if (Document == null)
            {
                return null;
            }

            Workbook workbook = null;
            Worksheet worksheet = null;
            try
            {
                workbook = (Microsoft.Office.Interop.Excel.Workbook)Document;
                worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.ActiveSheet;
                Range range = null;

                if (worksheet != null)
                {
                    //// 獲取所選區域的第一次選中的單元格
                    range = worksheet.Application.ActiveCell;
                }

                return range;
            }
            catch
            {
                return null;
            }

        }

        public System.Data.DataTable GetDataFromExcel(string filePath)

        {
            string connStr = "";


            string fileType = System.IO.Path.GetExtension(filePath);
            if (string.IsNullOrEmpty(fileType)) return null;
            if (fileType == ".xls")
                connStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filePath + ";" + ";Extended Properties=\"Excel 8.0;HDR=NO;IMEX=1\"";
            else
                connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + filePath + ";" + ";Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"";
            string sql_F = "Select * FROM [{0}]  ";
            OleDbConnection conn = null;
            OleDbDataAdapter da = null;
            System.Data.DataTable dataTable = new System.Data.DataTable();
            try
            {
                // 初始化連接,並打開                    
                conn = new OleDbConnection(connStr);
                conn.Open();
                da = new OleDbDataAdapter();
                da.SelectCommand = new OleDbCommand(String.Format(sql_F, "Sheet1$"), conn);
                da.Fill(dataTable);
            }
            catch (Exception ex)
            {


            }
            finally
            {                  // 關閉連接                    
                if (conn.State == ConnectionState.Open)
                {
                    conn.Close();
                    da.Dispose();
                    conn.Dispose();
                }
            }
            conn.Close();
            da.Dispose();
            conn.Dispose();
            return dataTable;
        }

        #region - 由數字轉換為Excel中的列字母 -

        public int ToIndex(string columnName)
        {
            if (!Regex.IsMatch(columnName.ToUpper(), @"[A-Z]+")) { throw new Exception("invalid parameter"); }

            int index = 0;
            char[] chars = columnName.ToUpper().ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                index += ((int)chars[i] - (int)'A' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
            }
            return index - 1;
        }


        public string ToName(int index)
        {
            if (index < 0) { throw new Exception("invalid parameter"); }

            List<string> chars = new List<string>();
            do
            {
                if (chars.Count > 0) index--;
                chars.Insert(0, ((char)(index % 26 + (int)'A')).ToString());
                index = (int)((index - index % 26) / 26);
            } while (index > 0);

            return String.Join(string.Empty, chars.ToArray());
        }
        #endregion


        /// <summary>  
        /// 反一個M行N列的二維數組轉換為DataTable  
        /// </summary>  
        /// <param name="ColumnNames">一維數組,代表列名,不能有重復值</param>  
        /// <param name="Arrays">M行N列的二維數組</param>  
        /// <returns>返回DataTable</returns>  
        /// <remarks>柳永法 http://www.yongfa365.com/ </remarks>  
        public static System.Data.DataTable ConvertToDataTable(string[] ColumnNames, string[,] Arrays)
        {
            System.Data.DataTable dt = new System.Data.DataTable();

            foreach (string ColumnName in ColumnNames)
            {
                dt.Columns.Add(ColumnName, typeof(string));
            }

            for (int i1 = 0; i1 < Arrays.GetLength(0); i1++)
            {
                DataRow dr = dt.NewRow();
                bool isData = false;
                for (int i = 0; i < ColumnNames.Length; i++)
                {
                    if (Arrays[i1, i] != null)
                    {
                        isData = true;
                        dr[i] = Arrays[i1, i].ToString();
                    }
                }
                if (isData)
                    dt.Rows.Add(dr);
            }

            return dt;

        }

        private string GetNameFromDt(System.Data.DataTable dt)
        {
            string str = "";
            foreach (DataRow dr in dt.Rows)
            {
                str += dr["Name"].ToString() + ",";
            }
            return str.TrimEnd(',');
        }
        #endregion


    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM