李优秀 发表于 2024-8-2 04:37:30

【C#工具类】Excel接口(一)

目录
需求描述
详细需求分析
学习交流(Bug待解决)
Debug代码(写代码的过程,逐渐美满的过程)
参考资料
扩展阅读

 需求描述

用C#生成两个函数
1. 盲读Excel (Excel文件名)
读取全部单元格的数据,并输出Json 
如:{[{"X":"2","Y":"4","V":"第2行第4列的值"}, {"X":"3","Y":"8","V":"第3行第8列的值"}]}

2. 按指定参数读取Excel (Excel文件名,Json参数)
{ "固定单元格读取":[
        {"X":"2","Y":"4","V":"第2行第4列的值"},
      {"X":"3","Y":"8","V":"第3行第8列的值"}    ],
  "二位表格读取":[
        {"二维表格名称":"表格1","列头行数":"1","X1":"2","X2":"6","Y1":"4","Y2":"","行结束方式":"固定列动态行单元格为详细文本","行结束辨认X":"1","行结束文本":""},
        {"二维表格名称":"表格1","列头行数":"1","X1":"2","X2":"6","Y1":"4","Y2":"","行结束方式":"行无数据","行结束辨认X":"","行结束文本":""}
    ]
}

"单元格":[
        {"X":"2","Y":"4","V":"第2行第4列的值"},
      {"X":"3","Y":"8","V":"第3行第8列的值"}    ],
  "表格":[
        {"Name":"表格1",Data:[{"列1名":"1","列2名":"2"},{"列1名":"1","列2名":"2"}]},
        {"Name":"表格1",Data:[{"列1名":"1","列2名":"2"},{"列1名":"1","列2名":"2"}]}
    ]

详细需求分析

Function1.
input:EXCEL(Sheet)
output:内容转换成Json
Function2.
input:固定单元格 or 二位表格(固定单元格 and 二位表格)
output:单元格 and 表格

思路:
1.读取EXCEL
网上有两种方式:
第一种是安装AccessDatabaseEngine,思路:
1)根据Excel文件获取全部Sheet名称
2)获取每一个Sheet的内容组装dataTable
3)table转Json
第二种是使用Npoi读取excel,思路:
1)将excel文件中的内容读取出来,存放到DataSet中
2)将DataTable转换成对应的list对象
3)将list对象转换成json,传递到前端

2.Json转换
1)引用Newtonsoft.Json.dll
下载地址:https://www.newtonsoft.com/json
下载完成后,找到对应版本的dll,项目中直接引用即可。
另有别的一种下载方式,使用Nuget :打开vs工具 - NuGet程序包管理器 - 程序包管理器控制台,这时在VS的底部窗口出现命令行:pm>install-package newtonsoft.json 执行完,会提示下载在哪个位置,再从项目中引用即可。
2)json和List的转换,更多是考虑List<T> 

注:下面记录的是开辟过程中碰到的一些环境,然后随手记了一部分核心代码,完整的DEMO贴在末了。

测试案例 (简单设计了两个表格内容)
https://i-blog.csdnimg.cn/direct/25fe9f4a92b043bdbaa81d63107850c5.png
https://i-blog.csdnimg.cn/direct/e9ecca11467b4a618ef2574584176b3d.png

学习交流(Bug待解决)

Form2
方式一
output==>读文件显示LIST在DGV中,然后用MESSAGEBOX显示Json返回结果。
https://i-blog.csdnimg.cn/direct/0ae64b2fe2a64a76bd251f5dbd55a635.png
0.27读出来是.27,但其他带小数的数字没影响。
可优化点1:方式一的返回参数实在就是方式二的【单元格】返回参数,以是这两个返回结果的实体类可以归并。(Demo已优化)
方式二
input==>{"X":"2","Y":"4","V":"第2行第4列的值"},{ "X":"3","Y":"8","V":"第3行第8列的值"}
1)C#默认从0开始,(2,4)实在在系统中对应的是(3,5)并且还需要考虑是否会存在越界
2)需要格式化输入参数,关于末了一个传参V是否赋值存疑(思索:有没有设定非必填参数的方法?存入后台可以设定not null或者null,但是前端传参好像都是必填的)【通用方法】
输入(2,4)和(2,4,0)和(2,4,Null)是否应该判定为一致?
3)    {"二维表格名称":"表格1","列头行数":"1","X1":"2","X2":"6","Y1":"4","Y2":"","行结束方式":"固定列动态行单元格为详细文本","行结束辨认X":"1","行结束文本":""}
“列头行数”私以为有三种环境:0-没有表头即默认第一活动列头;1-默认第一活动列头;N-跳过多行,从第N行开始读取EXCEL内容
范围:从X1:Y1至X2:Y2(给的参考数据里Y2默认为空,但三个参数也确实可以确定范围)
行结束方式:行无数据(这个是详细输入的文字照旧怎么决定的呢?)
行结束辨认X:详细文本中某个字符?好比逗号空格之类
行结束文本:给的参考数据是空,以是详细逻辑不太清楚(在网上有参考了部分资料,但是好像还都没有细化到这个程度)
待美满点:实在主要是因为我对这个Input的明白还不够清楚,以是先默认表名称,开始表头和表格范围都是必填项,后面3个参数待优化增补。(NPOI中实在也都有提供相关属性)
4) 固定单元格 or 二位表格  照旧 固定单元格 and 二位表格 ?
固定单元格 or 二位表格 :二种方式任选其一,固定单元格 的格式可以选取多个,并不但限于两个(List允许上限范围内都可以查询)同时查询时也存在允许输入任一种或者两种(需要检验输入内容是否冲突)或者完全不选任何一种默认全读。
固定单元格 and 二位表格 : 将 固定单元格 限定为两个,然后作为 二位表格 中的范围条件(这种思路开辟起来更简单,但是从参考Input中并没有发现关联的关系,以是后续可以作为 可优化点4)
output==>读表格名称时默认显示的是Table1,Table2如许的,实在私以为返回1和Sheet1如许的更合理一些。(定义的DataTable dt,然后取的dt.TableName;)
https://i-blog.csdnimg.cn/direct/213f01b7976f40f6a33dc113e0700968.png
==》关于获取到表名1和Sheet 的方式,可以使用NPOI中的方法(雷同下面的思路,Demo已优化)
NPOI.SS.UserModel.ISheet st;

var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var wk=newnew XSSFWorkbook(fs);//2007之后版本的excel

//获取读取的Sheet表的索引
st = wk.GetSheetAt(0);

MessageBox.Show(st.SheetName); //Sheet表名 LIST绑定DGV,因为LIST泛型走了一点弯路,暂时也没想到更好的处理方式(上图是全部的数据)然后绑定DGV的写法疑似存在一定局限性(中心切换的过程是通过MessageBox控制的,然后如今只能单一的绑定List,没法直接绑定实体类)结果如下:
https://i-blog.csdnimg.cn/direct/57fb0e6abec34c9fa5e947957416acf6.png
 https://i-blog.csdnimg.cn/direct/091485707eb646a5839bce321cd787cb.png
https://i-blog.csdnimg.cn/direct/1b9602661ea849ee92e817a607d2ba96.png
对应代码:
            ExcelToJSON tolist = new ExcelToJSON();

            List<Result> list = tolist.ImportExcelResult(strFilePath);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            string jsonData = serializer.Serialize(list);
            MessageBox.Show(jsonData);


            foreach(Result rs in list)
            {
                foreach (单元格Item cell in rs.单元格)
                {
                  this.dataGridView1.DataSource = new BindingSource(new BindingList<单元格Item>(rs.单元格), null);
                  //MessageBox.Show("单元格Item");
                }
                MessageBox.Show(" 单元格Item => 表格Item.DataItem ");

                foreach (表格Item sheet in rs.表格)
                {
                  foreach (DataItem dataitem in sheet.Data)
                  {
                        this.dataGridView1.DataSource = new BindingSource(new BindingList<DataItem>(sheet.Data), null);
                        //MessageBox.Show("DataItem");
                  }
                }

            } 可优化点2:如今两个方式的返回结果是合在一起的返回的,理论上还可以优化精简成泛型。
可优化点3:如今是进入目录选择相应的EXCEL文件,然后回传相关数据。实在还可以只提供目录,由程式主动遍历找到全部的EXCEL文件。(思索:此处的文件过滤也可以做成下拉选项,除EXCEL是否还可以对CSV,TXT,DOC等文件进行差别的操作呢?)

Debug代码(写代码的过程,逐渐美满的过程)

1.DATATABLE转换JSON
思索:读文件显示表头,如何默认过滤第一行标头?
https://i-blog.csdnimg.cn/direct/2d569718af864cdebfc5f379e573c565.png
            string strFilePath, strFileName;

            strFilePath = FilePathHelper.SelectFile(null);
            strFileName = textBox2.Text;
            if (string.IsNullOrEmpty(strFileName))
            {
                strFileName = " ";
            }
            ExcelToJSON ImportExcel = new ExcelToJSON();

            var excelData = ImportExcel.ImportExcelToDataSet(strFilePath); //遍历DataSet
            if (excelData.Tables.Count < 1)
            {
               //...
            }
            foreach (DataTable dt in excelData.Tables)
            {
                //按Sheet读取Table内容(JSON,默认会带上列名)
                ExcelToJSON tojson = new ExcelToJSON();
                string rs = tojson.ToJson(dt);
                MessageBox.Show(rs);
            } 因为想找 TableName 写的一段带参数名称的输出,然而并没有找到。 
https://i-blog.csdnimg.cn/direct/095db81f19d142008d01a1574aaa0f16.png
            string strFilePath, strFileName;

            strFilePath = FilePathHelper.SelectFile(null);
            strFileName = textBox2.Text;
            if (string.IsNullOrEmpty(strFileName))
            {
                strFileName = " ";
            }
            ExcelToJSON ImportExcel = new ExcelToJSON();

            var excelData = ImportExcel.ImportExcelToDataSet(strFilePath); //遍历DataSet
            if (excelData.Tables.Count < 1)
            {
               //...
            }
            foreach (DataTable dt in excelData.Tables)
            {
                //按Sheet读取Table内容(会带上格式)
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(dt.GetType());
                using (MemoryStream ms = new MemoryStream())
                {
                  serializer.WriteObject(ms, dt);
                  StringBuilder sb = new StringBuilder();
                  sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
                  MessageBox.Show(sb.ToString());
                }
            } 末了在NPOI读取EXCEL时将对应表名赋值给table,末了照旧用dt.TableName读到了相应表名。
优化代码: table.TableName = sheet.SheetName; //Sheet表名 
 https://i-blog.csdnimg.cn/direct/d384c3c4f1d24980a0428c283c4e778c.png
2.没有套用INPUT的OUTPUT方式二( 先依照方式一做的output,直接根据选择的文件名返回全部数据)
 function2事件:
      private void button2_Click(object sender, EventArgs e)
      {

            string strFilePath, strFileName;

            strFilePath = FilePathHelper.SelectFile(null);
            strFileName = textBox2.Text; //先默认不填
            if (string.IsNullOrEmpty(strFileName))
            {
                strFileName = " ";
            }
            


            ExcelToJSON tolist = new ExcelToJSON();

            List<Result> list = tolist.ImportExcelResult(strFilePath);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            string jsonData = serializer.Serialize(list);
            MessageBox.Show(jsonData);

            /*
            foreach(Result rs in list)
            {
                foreach (单元格Item cell in rs.单元格)
                {
                  this.dataGridView1.DataSource = new BindingSource(new BindingList<单元格Item>(rs.单元格), null);
                  //MessageBox.Show("单元格Item");
                }
                MessageBox.Show(" 单元格Item => 表格Item.DataItem ");

                foreach (表格Item sheet in rs.表格)
                {
                  foreach (DataItem dataitem in sheet.Data)
                  {
                        this.dataGridView1.DataSource = new BindingSource(new BindingList<DataItem>(sheet.Data), null);
                        //MessageBox.Show("DataItem");
                  }
                }

            }
            */
         


      } ExcelToJSON中ImportExcelResult(strFilePath);的代码: 
      #region DataTable内容转成Result(只选择文件即可返回两种结果)
      public List<Result> ImportExcelResult(string filePath)
      {


            List<Result> result = new List<Result>();


            var excelData = ImportExcelToDataSet(filePath);                //遍历DataSet
            if (excelData.Tables.Count < 1)
            {               
                return result;
            }
            foreach (DataTable dt in excelData.Tables)
            {
                按Sheet读取Table内容(JSON,默认会带上列名)
                //ExcelToJSON tojson = new ExcelToJSON();
                //string rs = tojson.ToJson(dt);
                //MessageBox.Show(rs);

                按Sheet读取Table内容(会带上格式)
                //DataContractJsonSerializer serializer = new DataContractJsonSerializer(dt.GetType());
                //using (MemoryStream ms = new MemoryStream())
                //{
                //    serializer.WriteObject(ms, dt);
                //    StringBuilder sb = new StringBuilder();
                //    sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
                //    MessageBox.Show(sb.ToString());
                //}

                Result rs = new Result();

                List<单元格Item> item = new List<单元格Item>();            


                List<表格Item> sheet = new List<表格Item>();
                表格Item bit = new 表格Item();

                bit.Name = dt.TableName;


                foreach (DataRow dr in dt.Rows)
                {

                  List<DataItem> data = new List<DataItem>();                  

                  List<string> columnName = new List<string>();//实例化一个参数集合
                  foreach (DataColumn dataColumn in dt.Columns)
                  {
                        columnName.Add(dataColumn.ColumnName);
                  }

                  for (var i = 0; i < dr.ItemArray.Length; i++)
                  {
                        单元格Item it = new 单元格Item();

                        DataItem di = new DataItem();
                        di.col_X = columnName; //DataItem集合中添加键值

                        //验证是否包含特殊字符
                        if (dr.ItemArray.ToString() != "" && ValidateSymbol(dr.ItemArray.ToString()) == true)
                        {
                            it.X = "0";
                            it.Y = "0";
                            it.V = "0";
                        }
                        else
                        {                        

                            if (dr.ItemArray.ToString() != "")
                            {
                              it.X = dt.Rows.IndexOf(dr).ToString();
                              it.Y = i.ToString();
                              it.V = dr.ItemArray.ToString();                              
                              
                            }                        
                                                
                        }
                        
                        item.Add(it);      
                        rs.单元格 = item;

                        di.col_Y = dr.ItemArray.ToString();
                        data.Add(di);
                  }
                  
                  bit.Data=data;
                }


                sheet.Add(bit);
                rs.表格=sheet;

                result.Add(rs);

            }      

            
            return result;
      }
      #endregion 3.转换方式二Input的JSON格式
输入的是实体类,传参时传入实体类,转换json格式放在工具类中照旧在输入界面更合适?(textBox.Text->List<CellItem>->Input->json分析后使用)思索:能否写一个通用的转换方法?
 将1,3赋值给 单元格List 
         string inputValue = textBox1.Text.Trim(); //"1,3"
         inputValue = inputValue.Replace(",",",");//替换中文状态的逗号

         Input inparam = new Input();

            //固定单元格
            List<CellItem> cs = new List<CellItem>();
            //{"X":"2","Y":"4","V":"第2行第4列的值"},{ "X":"3","Y":"8","V":"第3行第8列的值"}
            List<string> inputlist = new List<string>(inputValue.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)); //去除中间的空格
            CellItem ci = new CellItem();   
            ci.X = inputlist;
            ci.Y = inputlist;
            //ci.V = "";//Input时要不要赋值,我的理解是输入固定单元格,输出时返回这个单元格所对应的数据
            cs.Add(ci);
            inparam.CellItem=cs; 输入参数应该请使用者如何输入?如今先手输数组,雷同(1,3),默认参数V不传;但是存在C#从0开始计数,实际习惯从1开始数EXCEL单元格的环境,并且由使用者输入的参数另有可能存在中英文符号,不加括号等等各种格式(仅查一个单元格时肯定大部分人都不喜好加括号,就算key括号也会存在()<>{}并且全角半角的输入法区别)。思索:能否通过正则或者其他方式单独写一个处理方法让input格式更规范统一?(思索:能否用正则取出了括号中心的单元格数组)
网上有找到过一些正则截取括号中心内容的写法,但是处理起一连的()好像不停不太得劲,后续有精神再研究一下,如今用了比较暴力的原始截取方法。
            string inputValue = "(1,3,1),(1,4,5)";
            //string inputValue ="(1,3),(1,4)";

            // var str=Regex.Match(inputValue, @"(\(+,+\))");//1,3

            int length = inputValue.Length - 1;
            int firstLeft = inputValue.IndexOf("(");
            int firstRight = inputValue.IndexOf(")")-1;
            int arr = firstRight - firstLeft;
            string str2 ;

            while (length > 0) //10
            {
                //结束位置 减 1 再减 开始位置 获取中间位置数
                str2=inputValue.Substring(inputValue.IndexOf("(") + 1, arr);//参数1:开始位置加1 参数2:长度:中间位置数
                MessageBox.Show(str2);//这里就是我想要的()中间的数据
                inputValue = inputValue.Remove(firstLeft, firstRight+2>length?length:firstRight+2);
                firstLeft = inputValue.IndexOf("(");
                firstRight = inputValue.IndexOf(")") - 1;
                arr = firstRight - firstLeft;
                length = inputValue.Length - 1;
            } 转换JSON格式的方法:
      public static string Obj2Json<T>(T data)
      {
            try
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(data.GetType());
                using (MemoryStream ms = new MemoryStream())
                {
                  serializer.WriteObject(ms, data);
                  return Encoding.UTF8.GetString(ms.ToArray());
                }
            }
            catch
            {
                return null;
            }
      } 4.方式二的Input表格读取范围
1)通过 固定单元格 决定 二位表格 选取范围(就是上面的 可优化点4)
【固定单元格】对应的实体类在本次Project中多次用到,以是顺手就写了这种方式
https://i-blog.csdnimg.cn/direct/dd202c130f4a4e7d97a2a9b45b8cc7bb.png
https://i-blog.csdnimg.cn/direct/5fb224d891fe443daf664a86cf79a57b.png
https://i-blog.csdnimg.cn/direct/31d3413de4b142cf8cee714d7447f9e8.png
但是通过上图可知我这里另有一个BUG:
对于没有读取的栏位,好比ABEFG,在单元格读取时在DGV中显示成了空白,并不是我最初设想的直接只返回两行的环境。有试过在读取Table栏位时只读取第C列和第D列,然而二维表格读取的分支里,赋值时会出现找不到对应列的环境。以是末了就酿成了上述结果。

参考代码:

            string inputValue = textBox1.Text.Trim(); //"1,3"
            inputValue = inputValue.Replace(",",",");//替换中文状态的逗号
            //通过遍历inputValue获取具体的单元格
            //inputValue = inputValue.Replace("(", "").Replace(")","").Replace("(", "").Replace(")", "");//去除所有(),默认中间也会key逗号,遍历每2-3个元素为固定单元格


         //把List集合转换为json字符串
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            Input inparam = new Input();

            //固定单元格
            List<CellItem> cs = new List<CellItem>();


            //"(1,3),(1,4)"
            int length = inputValue.Length - 1;
            int firstLeft = inputValue.IndexOf("(");
            int firstRight = inputValue.IndexOf(")") - 1;
            int arr = firstRight - firstLeft;
            string str2;

            List<string> resList = new List<string>();

            while (length > 0) //10
            {
                //结束位置 减 1 再减 开始位置 获取中间位置数
                str2 = inputValue.Substring(inputValue.IndexOf("(") + 1, arr);//参数1:开始位置加1 参数2:长度:中间位置数
                resList.Add(str2);
                inputValue = inputValue.Remove(firstLeft, firstRight + 2 > length ? length : firstRight + 2);
                firstLeft = inputValue.IndexOf("(");
                firstRight = inputValue.IndexOf(")") - 1;
                arr = firstRight - firstLeft;
                length = inputValue.Length - 1;
            }


            foreach (string i in resList.ToArray())
            {
                //{"X":"2","Y":"4"},{ "X":"3","Y":"8"}
                //{"X":"2","Y":"4","V":"第2行第4列的值"},{ "X":"3","Y":"8","V":"第3行第8列的值"}
                List<string> cist = new List<string>(i.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)); //去除中间的空格

                CellItem ci = new CellItem();
                ci.X = cist;
                ci.Y = cist;
                //ci.V = "";//Input时要不要赋值,我的理解是输入固定单元格,输出时返回这个单元格所对应的数据

                cs.Add(ci);

            }
            inparam.CellItem=cs;


            //二位表格
            //{ "二维表格名称":"表格1","列头行数":"1","X1":"2","X2":"6","Y1":"4","Y2":"","行结束方式":"固定列动态行单元格为具体文本/行无数据","行结束识别X":"1","行结束文本":""},
            List<SheetItem> ss = new List<SheetItem>();

            SheetItem si = new SheetItem();
            si.Sheet = strFileName;//Sheet1
            si.Col = "1";
            si.X1 = cs.X;
            si.X2 = cs.X;
            si.Y1 = cs.Y;
            si.Y2 = cs.Y;
            si.Row = "";
            si.Row_X = "";
            si.Row_End = "";
            ss.Add(si);
            inparam.SheetItem = ss;

            //格式化传参JSON Input
            string jsonInput = serializer.Serialize(inparam);
            MessageBox.Show(jsonInput);

            
            
      public DataSet ImportExcelToDataSet(string filePath,Input inparam)
      {            
            //表名             inparam.SheetItem.Sheet
            //列头行数         inparam.SheetItem.Col
            //范围            inparam.SheetItem.X1/X2/Y1/Y2
            //行结束方式
            //行结束识别
            //行结束文本

            DataSet ds = new DataSet();
            IWorkbook workbook;
            string fileExt = Path.GetExtension(filePath).ToLower();
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                  if (fileExt == ".xlsx")
                  {
                        workbook = new XSSFWorkbook(fs);//2007之后版本的excel
                  }
                  else
                  {
                        workbook = new HSSFWorkbook(fs);//2003版本的excel
                  }

                  
                  //for (int a = 0, b = workbook.NumberOfSheets; a < b; a++)
                  //{
                        //获取读取的Sheet表的索引
                        ISheet sheet = workbook.GetSheet(inparam.SheetItem.Sheet);
                        DataTable table = new DataTable();
                        table.TableName = sheet.SheetName; //Sheet表名


                  int firstrow;

                  if (inparam.SheetItem.Col == "1" || inparam.SheetItem.Col == "0")
                  {
                        //将第一行的文本作为列名 inparam.SheetItem.Col
                        firstrow = sheet.FirstRowNum;
                  }
                  else
                  {
                        firstrow = Convert.ToInt16( inparam.SheetItem.Col)-1;
                     
                  }
                  IRow headerRow = sheet.GetRow(firstrow);
                  int cellCount = headerRow.LastCellNum;

                  for (int i = sheet.FirstRowNum; i < cellCount; i++)
                  {
                            DataColumn column;
                            object obj = GetValueType(headerRow.GetCell(i));
                            if (obj == null || obj.ToString() == string.Empty)
                            {
                              column = new DataColumn("Columns" + i.ToString());
                            }
                            else
                            {
                              column = new DataColumn(obj.ToString());
                            }
                            table.Columns.Add(column);
                     
                     }

                  //读取第一行下面的数据,将他们作为数据行存储
                  //for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)//首列名称不保留

                  //excel单元格默认+1,所以此处设定-1
                  int begini = Convert.ToInt32(inparam.SheetItem.X1) - 1;
                  int endi = Convert.ToInt32(inparam.SheetItem.X2) - 1;
                  int beginj = Convert.ToInt32(inparam.SheetItem.Y1) - 1;
                  int endj = Convert.ToInt32(inparam.SheetItem.Y2) - 1;

                  for (int i =begini ; i <= endi; i++)
                  {
                            IRow row = sheet.GetRow(i);
                            if (row == null || row.GetCell(0) == null || row.GetCell(0).ToString().Trim() == "")
                            {
                              // 如果遇到第一个空行,跳出本次循环,继续向下读取                              
                              continue;
                            }
                            DataRow dataRow = table.NewRow();
                            for (int j = beginj; j <= endj; j++)
                            {
                              if (row.GetCell(j) != null)
                              {
                                    dataRow = row.GetCell(j).ToString();
                              }
                            }
                            table.Rows.Add(dataRow);
                     }

                        ds.Tables.Add(table);

                   // }
                  workbook = null;
                  return ds;
                }
            }
            catch (Exception ex)
            {
                return ds;
            }
      } 2)通过3个参数决定选取范围(需要别的判定范围从小到大)
https://i-blog.csdnimg.cn/direct/f7ebb1fcbb0b4b0d83aa610438d8e0f8.png
https://i-blog.csdnimg.cn/direct/c7ad709a12364fed9bca2228d2eb4780.png
https://i-blog.csdnimg.cn/direct/82bff08de067415c972d8cd1f1d99b70.png


DEMO源码(包罗我测试的两个excel文件)
附:Form1是我拿来测试截取单元格的小玩意儿~包罗最基础的循环和正则,可以当作小彩蛋吧~

参考资料:

C#读取EXCEL文件并生成Json
C#将List集合转换为json字符串_c#list转换成json-CSDN博客
C#如何将DataTable转换成List类
json与DataTable相互转换
C#中把Datatable转换为Json的5个代码实例_c# html 源码 获取table转json-CSDN博客
unity C#将excel分析为json
c#读写EXCEL的几种方法
c#使用NPOI读写EXCEL
C# 使用 NPOI 库读写 Excel 文件_c# npoi读取excel数据-CSDN博客
 C# dataGridView绑定List数据-CSDN博客
winform DataGridView绑定List<T>类型数据_winfrom t-CSDN博客
C#中WinForm制作点击"选择文件"按钮选择Excel文件, 并读取Excel内容到DataTable_winform click事件从文件读取列表-CSDN博客
C# 通过行和列直接读取Excel中数据的方法_c#获取excel每一列已使用单元格数量-CSDN博客
c#中List<Object>取出对应的值----dynamic_c# 获取 object 转 dynamic-CSDN博客
在C#中使用正则表达式提取括号中的内容_c# 正则表达式 匹配括号中内容-CSDN博客
C#从字符串中批量截取中心字符串_c# 获取字符串中全部td中心的内容-CSDN博客
C#获取动态key的json对象的值_c# 获取json对象中的值和key-CSDN博客
扩展阅读:

JSON压缩转义 - 站长工具
C#中如何将List<自定义>转为Json格式 及相关函数-DataContractJsonSerializer_c# 数组转json-CSDN博客
使用NPOI读取Excel到DataTable_npoi读取excel到datable并设置列数据类型-CSDN博客
java-读取Excel文件,自定义读取固定行、列(不区分xls、xlsx)_java excel自定义行列-CSDN博客 NPOI使用手册-CSDN博客

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【C#工具类】Excel接口(一)