• 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 = "           识别行
      设置列";
                            }
                        }
    
    
                    }
                    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
    
    
        }
    }
  • 相关阅读:
    开发体系规范建议
    centos安装samba
    【OF框架】在部署中使用 Windows身份认证
    【OF框架】使用OF.WinService项目,添加定时服务,进行创建启动停止删除服务操作
    【OF框架】定义框架标准WebApi,按照规范返回状态信息及数据信息
    【OF框架】使用IDbContextTransaction在框架中对多个实体进行事务操作
    【OF框架】新建库表及对应实体,并实现简单的增删改查操作,封装操作标准WebApi
    【OF框架】框架Cache/Session在负载均衡部署时,切换Memory/Redis测试
    【OF框架】在Visual Studio中启用Docker支持,编译生成,并在容器运行项目
    【OF框架】在Visual Studio中发布Docker镜像,推送镜像到Azure容器注册表
  • 原文地址:https://www.cnblogs.com/shengkai/p/9647075.html
Copyright © 2020-2023  润新知