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

李优秀  金牌会员 | 2024-8-2 04:37:30 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 499|帖子 499|积分 1497

目录
需求描述
详细需求分析
学习交流(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贴在末了。

测试案例 (简单设计了两个表格内容)



学习交流(Bug待解决)

Form2
方式一
output==>读文件显示LIST在DGV中,然后用MESSAGEBOX显示Json返回结果。

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;)

==》关于获取到表名1和Sheet 的方式,可以使用NPOI中的方法(雷同下面的思路,Demo已优化)
  1.   NPOI.SS.UserModel.ISheet st;
  2.   var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  3.   var wk=new  new XSSFWorkbook(fs);//2007之后版本的excel
  4.   
  5.   //获取读取的Sheet表的索引
  6.   st = wk.GetSheetAt(0);
  7.   MessageBox.Show(st.SheetName); //Sheet表名
复制代码
LIST绑定DGV,因为LIST泛型走了一点弯路,暂时也没想到更好的处理方式(上图是全部的数据)然后绑定DGV的写法疑似存在一定局限性(中心切换的过程是通过MessageBox控制的,然后如今只能单一的绑定List,没法直接绑定实体类)结果如下:

 


对应代码:
  1.             ExcelToJSON tolist = new ExcelToJSON();
  2.             List<Result> list = tolist.ImportExcelResult(strFilePath);
  3.             JavaScriptSerializer serializer = new JavaScriptSerializer();
  4.             string jsonData = serializer.Serialize(list);
  5.             MessageBox.Show(jsonData);
  6.             foreach(Result rs in list)
  7.             {
  8.                 foreach (单元格Item cell in rs.单元格)
  9.                 {
  10.                     this.dataGridView1.DataSource = new BindingSource(new BindingList<单元格Item>(rs.单元格), null);
  11.                     //MessageBox.Show("单元格Item");
  12.                 }
  13.                 MessageBox.Show(" 单元格Item => 表格Item.DataItem ");
  14.                 foreach (表格Item sheet in rs.表格)
  15.                 {
  16.                     foreach (DataItem dataitem in sheet.Data)
  17.                     {
  18.                         this.dataGridView1.DataSource = new BindingSource(new BindingList<DataItem>(sheet.Data), null);
  19.                         //MessageBox.Show("DataItem");
  20.                     }
  21.                 }
  22.             }
复制代码
可优化点2:如今两个方式的返回结果是合在一起的返回的,理论上还可以优化精简成泛型。
可优化点3:如今是进入目录选择相应的EXCEL文件,然后回传相关数据。实在还可以只提供目录,由程式主动遍历找到全部的EXCEL文件。(思索:此处的文件过滤也可以做成下拉选项,除EXCEL是否还可以对CSV,TXT,DOC等文件进行差别的操作呢?)

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

1.DATATABLE转换JSON
思索:读文件显示表头,如何默认过滤第一行标头?

  1.             string strFilePath, strFileName;
  2.             strFilePath = FilePathHelper.SelectFile(null);
  3.             strFileName = textBox2.Text;
  4.             if (string.IsNullOrEmpty(strFileName))
  5.             {
  6.                 strFileName = " ";
  7.             }
  8.             ExcelToJSON ImportExcel = new ExcelToJSON();
  9.             var excelData = ImportExcel.ImportExcelToDataSet(strFilePath); //遍历DataSet
  10.             if (excelData.Tables.Count < 1)
  11.             {
  12.                //...
  13.             }
  14.             foreach (DataTable dt in excelData.Tables)
  15.             {
  16.                 //按Sheet读取Table内容(JSON,默认会带上列名)
  17.                 ExcelToJSON tojson = new ExcelToJSON();
  18.                 string rs = tojson.ToJson(dt);
  19.                 MessageBox.Show(rs);
  20.             }
复制代码
因为想找 TableName 写的一段带参数名称的输出,然而并没有找到。 

  1.             string strFilePath, strFileName;
  2.             strFilePath = FilePathHelper.SelectFile(null);
  3.             strFileName = textBox2.Text;
  4.             if (string.IsNullOrEmpty(strFileName))
  5.             {
  6.                 strFileName = " ";
  7.             }
  8.             ExcelToJSON ImportExcel = new ExcelToJSON();
  9.             var excelData = ImportExcel.ImportExcelToDataSet(strFilePath); //遍历DataSet
  10.             if (excelData.Tables.Count < 1)
  11.             {
  12.                //...
  13.             }
  14.             foreach (DataTable dt in excelData.Tables)
  15.             {
  16.                 //按Sheet读取Table内容(会带上格式)
  17.                 DataContractJsonSerializer serializer = new DataContractJsonSerializer(dt.GetType());
  18.                 using (MemoryStream ms = new MemoryStream())
  19.                 {
  20.                     serializer.WriteObject(ms, dt);
  21.                     StringBuilder sb = new StringBuilder();
  22.                     sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
  23.                     MessageBox.Show(sb.ToString());
  24.                 }
  25.             }
复制代码
末了在NPOI读取EXCEL时将对应表名赋值给table,末了照旧用dt.TableName读到了相应表名。
优化代码: table.TableName = sheet.SheetName; //Sheet表名 
 

2.没有套用INPUT的OUTPUT方式二( 先依照方式一做的output,直接根据选择的文件名返回全部数据)
 function2事件:
  1.         private void button2_Click(object sender, EventArgs e)
  2.         {
  3.             string strFilePath, strFileName;
  4.             strFilePath = FilePathHelper.SelectFile(null);
  5.             strFileName = textBox2.Text; //先默认不填
  6.             if (string.IsNullOrEmpty(strFileName))
  7.             {
  8.                 strFileName = " ";
  9.             }
  10.             
  11.             ExcelToJSON tolist = new ExcelToJSON();
  12.             List<Result> list = tolist.ImportExcelResult(strFilePath);
  13.             JavaScriptSerializer serializer = new JavaScriptSerializer();
  14.             string jsonData = serializer.Serialize(list);
  15.             MessageBox.Show(jsonData);
  16.             /*
  17.             foreach(Result rs in list)
  18.             {
  19.                 foreach (单元格Item cell in rs.单元格)
  20.                 {
  21.                     this.dataGridView1.DataSource = new BindingSource(new BindingList<单元格Item>(rs.单元格), null);
  22.                     //MessageBox.Show("单元格Item");
  23.                 }
  24.                 MessageBox.Show(" 单元格Item => 表格Item.DataItem ");
  25.                 foreach (表格Item sheet in rs.表格)
  26.                 {
  27.                     foreach (DataItem dataitem in sheet.Data)
  28.                     {
  29.                         this.dataGridView1.DataSource = new BindingSource(new BindingList<DataItem>(sheet.Data), null);
  30.                         //MessageBox.Show("DataItem");
  31.                     }
  32.                 }
  33.             }
  34.             */
  35.            
  36.         }
复制代码
ExcelToJSON中ImportExcelResult(strFilePath);的代码: 
  1.         #region DataTable内容转成Result(只选择文件即可返回两种结果)
  2.         public List<Result> ImportExcelResult(string filePath)
  3.         {
  4.             List<Result> result = new List<Result>();
  5.             var excelData = ImportExcelToDataSet(filePath);                //遍历DataSet
  6.             if (excelData.Tables.Count < 1)
  7.             {               
  8.                 return result;
  9.             }
  10.             foreach (DataTable dt in excelData.Tables)
  11.             {
  12.                 按Sheet读取Table内容(JSON,默认会带上列名)
  13.                 //ExcelToJSON tojson = new ExcelToJSON();
  14.                 //string rs = tojson.ToJson(dt);
  15.                 //MessageBox.Show(rs);
  16.                 按Sheet读取Table内容(会带上格式)
  17.                 //DataContractJsonSerializer serializer = new DataContractJsonSerializer(dt.GetType());
  18.                 //using (MemoryStream ms = new MemoryStream())
  19.                 //{
  20.                 //    serializer.WriteObject(ms, dt);
  21.                 //    StringBuilder sb = new StringBuilder();
  22.                 //    sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
  23.                 //    MessageBox.Show(sb.ToString());
  24.                 //}
  25.                 Result rs = new Result();
  26.                 List<单元格Item> item = new List<单元格Item>();              
  27.                 List<表格Item> sheet = new List<表格Item>();
  28.                 表格Item bit = new 表格Item();
  29.                 bit.Name = dt.TableName;
  30.                 foreach (DataRow dr in dt.Rows)
  31.                 {
  32.                     List<DataItem> data = new List<DataItem>();                    
  33.                     List<string> columnName = new List<string>();  //实例化一个参数集合
  34.                     foreach (DataColumn dataColumn in dt.Columns)
  35.                     {
  36.                         columnName.Add(dataColumn.ColumnName);
  37.                     }
  38.                     for (var i = 0; i < dr.ItemArray.Length; i++)
  39.                     {
  40.                         单元格Item it = new 单元格Item();
  41.                         DataItem di = new DataItem();
  42.                         di.col_X = columnName[i]; //DataItem集合中添加键值
  43.                         //验证是否包含特殊字符
  44.                         if (dr.ItemArray[i].ToString() != "" && ValidateSymbol(dr.ItemArray[i].ToString()) == true)
  45.                         {
  46.                             it.X = "0";
  47.                             it.Y = "0";
  48.                             it.V = "0";
  49.                         }
  50.                         else
  51.                         {                        
  52.                             if (dr.ItemArray[i].ToString() != "")
  53.                             {
  54.                                 it.X = dt.Rows.IndexOf(dr).ToString();
  55.                                 it.Y = i.ToString();
  56.                                 it.V = dr.ItemArray[i].ToString();                              
  57.                                 
  58.                             }                          
  59.                                                 
  60.                         }
  61.                         
  62.                         item.Add(it);      
  63.                         rs.单元格 = item;
  64.                         di.col_Y = dr.ItemArray[i].ToString();
  65.                         data.Add(di);
  66.                     }
  67.                     
  68.                     bit.Data=data;
  69.                 }
  70.                 sheet.Add(bit);
  71.                 rs.表格=sheet;
  72.                 result.Add(rs);
  73.             }        
  74.             
  75.             return result;
  76.         }
  77.         #endregion
复制代码
3.转换方式二Input的JSON格式
输入的是实体类,传参时传入实体类,转换json格式放在工具类中照旧在输入界面更合适?(textBox.Text->List<CellItem>->Input->json分析后使用)思索:能否写一个通用的转换方法?
 将1,3赋值给 单元格List 
  1.            string inputValue = textBox1.Text.Trim(); //"1,3"
  2.            inputValue = inputValue.Replace(",",",");//替换中文状态的逗号
  3.            Input inparam = new Input();
  4.             //固定单元格
  5.             List<CellItem> cs = new List<CellItem>();
  6.             //{"X":"2","Y":"4","V":"第2行第4列的值"},{ "X":"3","Y":"8","V":"第3行第8列的值"}
  7.             List<string> inputlist = new List<string>(inputValue.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)); //去除中间的空格
  8.             CellItem ci = new CellItem();   
  9.             ci.X = inputlist[0];
  10.             ci.Y = inputlist[1];
  11.             //ci.V = "";//Input时要不要赋值,我的理解是输入固定单元格,输出时返回这个单元格所对应的数据
  12.             cs.Add(ci);
  13.             inparam.CellItem=cs;
复制代码
输入参数应该请使用者如何输入?如今先手输数组,雷同(1,3),默认参数V不传;但是存在C#从0开始计数,实际习惯从1开始数EXCEL单元格的环境,并且由使用者输入的参数另有可能存在中英文符号,不加括号等等各种格式(仅查一个单元格时肯定大部分人都不喜好加括号,就算key括号也会存在()<>{}并且全角半角的输入法区别)。思索:能否通过正则或者其他方式单独写一个处理方法让input格式更规范统一?(思索:能否用正则取出了括号中心的单元格数组)
网上有找到过一些正则截取括号中心内容的写法,但是处理起一连的()好像不停不太得劲,后续有精神再研究一下,如今用了比较暴力的原始截取方法。
  1.             string inputValue = "(1,3,1),(1,4,5)";
  2.             //string inputValue ="(1,3),(1,4)";
  3.             // var str=  Regex.Match(inputValue, @"(\([0-9]+,[0-9]+\))");//1,3
  4.             int length = inputValue.Length - 1;
  5.             int firstLeft = inputValue.IndexOf("(");
  6.             int firstRight = inputValue.IndexOf(")")-1;
  7.             int arr = firstRight - firstLeft;
  8.             string str2 ;
  9.             while (length > 0) //10
  10.             {
  11.                 //结束位置 减 1 再减 开始位置 获取中间位置数
  12.                 str2=inputValue.Substring(inputValue.IndexOf("(") + 1, arr);//参数1:开始位置加1 参数2:长度:中间位置数
  13.                 MessageBox.Show(str2);//这里就是我想要的()中间的数据
  14.                 inputValue = inputValue.Remove(firstLeft, firstRight+2>length?length:firstRight+2);
  15.                 firstLeft = inputValue.IndexOf("(");
  16.                 firstRight = inputValue.IndexOf(")") - 1;
  17.                 arr = firstRight - firstLeft;
  18.                 length = inputValue.Length - 1;
  19.             }
复制代码
转换JSON格式的方法:
  1.         public static string Obj2Json<T>(T data)
  2.         {
  3.             try
  4.             {
  5.                 DataContractJsonSerializer serializer = new DataContractJsonSerializer(data.GetType());
  6.                 using (MemoryStream ms = new MemoryStream())
  7.                 {
  8.                     serializer.WriteObject(ms, data);
  9.                     return Encoding.UTF8.GetString(ms.ToArray());
  10.                 }
  11.             }
  12.             catch
  13.             {
  14.                 return null;
  15.             }
  16.         }
复制代码
4.方式二的Input表格读取范围
1)通过 固定单元格 决定 二位表格 选取范围(就是上面的 可优化点4)
【固定单元格】对应的实体类在本次Project中多次用到,以是顺手就写了这种方式



但是通过上图可知我这里另有一个BUG:
对于没有读取的栏位,好比ABEFG,在单元格读取时在DGV中显示成了空白,并不是我最初设想的直接只返回两行的环境。有试过在读取Table栏位时只读取第C列和第D列,然而二维表格读取的分支里,赋值时会出现找不到对应列的环境。以是末了就酿成了上述结果。

参考代码:
  1.             string inputValue = textBox1.Text.Trim(); //"1,3"
  2.             inputValue = inputValue.Replace(",",",");//替换中文状态的逗号
  3.             //通过遍历inputValue获取具体的单元格
  4.             //inputValue = inputValue.Replace("(", "").Replace(")","").Replace("(", "").Replace(")", "");//去除所有(),默认中间也会key逗号,遍历每2-3个元素为固定单元格
  5.            //把List集合转换为json字符串
  6.             JavaScriptSerializer serializer = new JavaScriptSerializer();
  7.             Input inparam = new Input();
  8.             //固定单元格
  9.             List<CellItem> cs = new List<CellItem>();
  10.             //"(1,3),(1,4)"
  11.             int length = inputValue.Length - 1;
  12.             int firstLeft = inputValue.IndexOf("(");
  13.             int firstRight = inputValue.IndexOf(")") - 1;
  14.             int arr = firstRight - firstLeft;
  15.             string str2;
  16.             List<string> resList = new List<string>();
  17.             while (length > 0) //10
  18.             {
  19.                 //结束位置 减 1 再减 开始位置 获取中间位置数
  20.                 str2 = inputValue.Substring(inputValue.IndexOf("(") + 1, arr);//参数1:开始位置加1 参数2:长度:中间位置数
  21.                 resList.Add(str2);
  22.                 inputValue = inputValue.Remove(firstLeft, firstRight + 2 > length ? length : firstRight + 2);
  23.                 firstLeft = inputValue.IndexOf("(");
  24.                 firstRight = inputValue.IndexOf(")") - 1;
  25.                 arr = firstRight - firstLeft;
  26.                 length = inputValue.Length - 1;
  27.             }
  28.             foreach (string i in resList.ToArray())
  29.             {
  30.                 //{"X":"2","Y":"4"},{ "X":"3","Y":"8"}
  31.                 //{"X":"2","Y":"4","V":"第2行第4列的值"},{ "X":"3","Y":"8","V":"第3行第8列的值"}
  32.                 List<string> cist = new List<string>(i.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)); //去除中间的空格
  33.                 CellItem ci = new CellItem();
  34.                 ci.X = cist[0];
  35.                 ci.Y = cist[1];
  36.                 //ci.V = "";//Input时要不要赋值,我的理解是输入固定单元格,输出时返回这个单元格所对应的数据
  37.                 cs.Add(ci);
  38.             }
  39.             inparam.CellItem=cs;
  40.             //二位表格
  41.             //{ "二维表格名称":"表格1","列头行数":"1","X1":"2","X2":"6","Y1":"4","Y2":"","行结束方式":"固定列动态行单元格为具体文本/行无数据","行结束识别X":"1","行结束文本":""},
  42.             List<SheetItem> ss = new List<SheetItem>();
  43.             SheetItem si = new SheetItem();
  44.             si.Sheet = strFileName;//Sheet1
  45.             si.Col = "1";
  46.             si.X1 = cs[0].X;
  47.             si.X2 = cs[1].X;
  48.             si.Y1 = cs[0].Y;
  49.             si.Y2 = cs[1].Y;
  50.             si.Row = "";
  51.             si.Row_X = "";
  52.             si.Row_End = "";
  53.             ss.Add(si);
  54.             inparam.SheetItem = ss;
  55.             //格式化传参JSON Input
  56.             string jsonInput = serializer.Serialize(inparam);
  57.             MessageBox.Show(jsonInput);
  58.             
  59.             
复制代码
  1.         public DataSet ImportExcelToDataSet(string filePath,Input inparam)
  2.         {            
  3.             //表名             inparam.SheetItem[0].Sheet
  4.             //列头行数         inparam.SheetItem[0].Col
  5.             //范围            inparam.SheetItem[0].X1/X2/Y1/Y2
  6.             //行结束方式
  7.             //行结束识别
  8.             //行结束文本
  9.             DataSet ds = new DataSet();
  10.             IWorkbook workbook;
  11.             string fileExt = Path.GetExtension(filePath).ToLower();
  12.             try
  13.             {
  14.                 using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
  15.                 {
  16.                     if (fileExt == ".xlsx")
  17.                     {
  18.                         workbook = new XSSFWorkbook(fs);//2007之后版本的excel
  19.                     }
  20.                     else
  21.                     {
  22.                         workbook = new HSSFWorkbook(fs);//2003版本的excel
  23.                     }
  24.                   
  25.                     //for (int a = 0, b = workbook.NumberOfSheets; a < b; a++)
  26.                     //{
  27.                         //获取读取的Sheet表的索引
  28.                         ISheet sheet = workbook.GetSheet(inparam.SheetItem[0].Sheet);
  29.                         DataTable table = new DataTable();
  30.                         table.TableName = sheet.SheetName; //Sheet表名
  31.                     int firstrow;
  32.                     if (inparam.SheetItem[0].Col == "1" || inparam.SheetItem[0].Col == "0")
  33.                     {
  34.                         //将第一行的文本作为列名 inparam.SheetItem[0].Col
  35.                         firstrow = sheet.FirstRowNum;
  36.                     }
  37.                     else
  38.                     {
  39.                         firstrow = Convert.ToInt16( inparam.SheetItem[0].Col)-1;
  40.                        
  41.                     }
  42.                     IRow headerRow = sheet.GetRow(firstrow);
  43.                     int cellCount = headerRow.LastCellNum;
  44.                     for (int i = sheet.FirstRowNum; i < cellCount; i++)
  45.                     {
  46.                             DataColumn column;
  47.                             object obj = GetValueType(headerRow.GetCell(i));
  48.                             if (obj == null || obj.ToString() == string.Empty)
  49.                             {
  50.                                 column = new DataColumn("Columns" + i.ToString());
  51.                             }
  52.                             else
  53.                             {
  54.                                 column = new DataColumn(obj.ToString());
  55.                             }
  56.                             table.Columns.Add(column);
  57.                        
  58.                      }
  59.                     //读取第一行下面的数据,将他们作为数据行存储
  60.                     //for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)  //首列名称不保留
  61.                     //excel单元格默认+1,所以此处设定-1
  62.                     int begini = Convert.ToInt32(inparam.SheetItem[0].X1) - 1;
  63.                     int endi = Convert.ToInt32(inparam.SheetItem[0].X2) - 1;
  64.                     int beginj = Convert.ToInt32(inparam.SheetItem[0].Y1) - 1;
  65.                     int endj = Convert.ToInt32(inparam.SheetItem[0].Y2) - 1;
  66.                     for (int i =begini ; i <= endi; i++)  
  67.                     {
  68.                             IRow row = sheet.GetRow(i);
  69.                             if (row == null || row.GetCell(0) == null || row.GetCell(0).ToString().Trim() == "")
  70.                             {
  71.                                 // 如果遇到第一个空行,跳出本次循环,继续向下读取                              
  72.                                 continue;
  73.                             }
  74.                             DataRow dataRow = table.NewRow();
  75.                             for (int j = beginj; j <= endj; j++)
  76.                             {
  77.                                 if (row.GetCell(j) != null)
  78.                                 {
  79.                                     dataRow[j] = row.GetCell(j).ToString();
  80.                                 }
  81.                             }
  82.                             table.Rows.Add(dataRow);
  83.                      }
  84.                         ds.Tables.Add(table);
  85.                    // }
  86.                     workbook = null;
  87.                     return ds;
  88.                 }
  89.             }
  90.             catch (Exception ex)
  91.             {
  92.                 return ds;
  93.             }
  94.         }
复制代码
2)通过3个参数决定选取范围(需要别的判定范围从小到大)





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企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表