当前位置: 首页 > news >正文

C# 实现完善 Excel 不规则合并单元格数据导入

 

目录

功能完善

Excel与DataSet的映射关系

运行环境

Excel DCOM 配置

设计实现

组件库引入

方法更新

返回值 

参数设计

打开数据源并计算Sheets

拆分合并的单元格

创建DataTable

将单元格数据写入DataTable

删除虚拟列 

总结


功能完善

在我的文章 《C#实现Excel合并单元格数据导入数据集》里讲述了可以将具有合并单元格的Excel文件数据导入到DataSet里,在实际使用情况中遇到如下情况,如下图:

如图中的 H 列,它是一个合并单元格,但它也属于一个特殊的单元格,即 worksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell,Type.Missing) 最后一个内容单元格,由于其合并单元格的地址问题(),导入程序可能会计算成为一行数据:

如图 H1 列假设为标题列(字段名),那么 H2 列为数据行的第一行,作为最后一个单元格,因此可能会被识别为只有一行数据,而忽略后面所有的行。

因此比较快速的一种解决方案是在右侧增加一个虚拟列:

如图通过增加列标题(“虚拟列”)达到重新计算出 最后单元格 ,根据最后单元格的地址,可以计算出新的行数,以达到计算出正确行数据的目的。

Excel与DataSet的映射关系

下图是 Excel 与 DataSet 的映射关系图:

1、Excel应用的Workbook对象与 DataSet 同为容器对象

2、Worksheets和Tables均代表各自的表集合

3、Worksheet与Table进行对应,产生和导入实际的数据

运行环境

操作系统: Windows Server 2019 DataCenter

操作系统上安装 Office Excel 2016

.net版本: .netFramework4.7.1 或以上

开发工具:VS2019  C#

Excel DCOM 配置

请参考我的文章《C# 读取Word表格到DataSet》有对Office DCOM详细配置介绍,这里不再赘述,Excel的对应配置名称如下图所示:

  

设计实现

组件库引入

方法更新

设计  object[] ExcelAsDataSet(string _filename,bool hastitle,string startaddress,string endaddress) 方法

返回值 

方法返回object数组,共包括两个object对象,如果成功转化则 object[0] 存储 DataSet对象,否则为 null。如果不成功则 object[1] 存储string 错误信息对象,可根据object[1].ToString()!="" 来判断是否转化成功。

参数设计
  1. string _filename:Excel 数据源文件路径
  2. bool hastitle: 是否包含标题,如果设置为true,则表示首行数据为列名称定义
  3. string startaddress:可指定有效的起始单元格地址,不设置则默认为“A1”(即第一个单元格)
  4. string endaddress:可指定有效的截止单元格地址,不设置则默认为最后一个有值单元格(即XlCellType.xlCellTypeLastCell 枚举) 

    通过3、4参数的定义,可以定义出有效的导入矩形区域。

打开数据源并计算Sheets

			object[] rv=new object[2];rv[0]=null;rv[1]="";//创建一个名为ExcelApp的组件对象
//			ExcelApplication excel = new ExcelApplication();Excel.Application excel = new Excel.Application();excel.DisplayAlerts=false;excel.AskToUpdateLinks=false;Excel.Workbook xb=excel.Workbooks.Add(_filename);
//获取活动的 worksheet和 excel sheet的个数,准备遍历sheetsWorksheet worksheet = (Worksheet) excel.ActiveSheet;sheetCount=excel.Sheets.Count;  int	startSheetIndex=1;int	endSheetIndex=sheetCount;DataSet ds=new DataSet();
//遍历sheetsfor (int currentIndex = startSheetIndex; currentIndex <= endSheetIndex; currentIndex++){worksheet = (Worksheet)excel.Worksheets[currentIndex];worksheet.Activate();//处理每一个sheet.....}

拆分合并的单元格

在获取有效的单元格区域后,就开始遍历单元格对象,判断单元格对象 MergeCells 属性即可,判断 Cell.MergeCells.ToString() == "True"  即表示该单元格为合并单元格对象。

示例代码如下:

//获取起始单元和截止单元格,以确定有效区域Excel.Range _startcell=worksheet.Range["A1","A1"]; //默认为第一个单元格if(startaddress!=""){try{_startcell=worksheet.Range[startaddress,startaddress];}catch(Exception ex){rv[1]+=string.Format("{1}指定的起始单元格地址{0},不是合法的地址。\r\n",startaddress,worksheet.Name);//					KillProcessByStartTime("EXCEL",beforetime,aftertime);continue;}}Excel.Range _lastcell=worksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell,Type.Missing);
//默认获取有值的最后一个有效的单元格excel.Cells[1, _lastcell.Column + 1] = "vcol"+ (_lastcell.Column + 1).ToString();_lastcell = worksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);if(endaddress!=""){try{_lastcell=worksheet.Range[endaddress,endaddress];}catch(Exception ex){rv[1]+=string.Format("{1}指定的结束单元格地址{0},不是合法的地址。\r\n",endaddress,worksheet.Name);//					KillProcessByStartTime("EXCEL",beforetime,aftertime);//						return rv;continue;}}//遍历有效区域单元格foreach (Excel.Range aicell in worksheet.Range[_startcell,_lastcell]){if (aicell.MergeCells.ToString() == "True"){//处理合并单元格object temp_merge_value = aicell.Value2; //备份单元格的值int u_row = aicell.Row;  //记录单元格的首行索引int u_rows = aicell.MergeArea.Rows.Count; //记录单元格的合并区域包含的行数int u_col = aicell.Column; //记录单元格的首列索引int u_cols = aicell.MergeArea.Columns.Count; //记录单元格的合并区域包含的列数aicell.MergeArea.UnMerge();  //取消合并,拆分单元格Excel.Range new_aicell = worksheet.Range[worksheet.Cells[u_row, u_col], worksheet.Cells[u_row + u_rows - 1, u_col + u_cols - 1]];  //获取拆分后单元格后的有效区域new_aicell.Value2 = temp_merge_value; //将拆分的单元格重新赋值(备份值)}}

程序中通过 excel.Cells[1, _lastcell.Column + 1] = "vcol"+ (_lastcell.Column + 1).ToString(); 设置增加虚拟列列名,以达到重新计算最后单元格的目的。

创建DataTable

如果首行是列数据,则以该行的值创建表结构,否则自动创建以“C”为前缀的列名,如C1、C2...Cn以此类推。

				System.Data.DataTable dt=ds.Tables.Add();dt.TableName=worksheet.Name;  //表名为worksheet的名称for(int i=_startcell.Column;i<=_lastcell.Column;i++){Excel.Range _cell=worksheet.Range[worksheet.Cells[_startcell.Row,i],worksheet.Cells[_startcell.Row,i]];string _colname=hastitle==true?_cell.Value2.ToString():"C"+(i-_startcell.Column+1).ToString(); //如果第一行是标题,则赋单元格的值,否则以C开头加序号DataColumn dc=dt.Columns.Add();dc.ColumnName=_colname;dc.DataType=System.Type.GetType("System.String");dc.AllowDBNull=true;}

将单元格数据写入DataTable

object[,] cells=null;  定义二维对象数组if(hastitle) //如果首行包含列,则加行索引加1取数据行{startrow=_startcell.Row+1;  }
//将有效区域单元格转化赋值为 object[,]	
cells=(object[,])worksheet.Range[worksheet.Cells[startrow,_startcell.Column],worksheet.Cells[_lastcell.Row,_lastcell.Column]].Value2;//遍历数组,添加行数据到 DataTable里
int _rowcount=cells.GetLength(0);
int _colcount=cells.GetLength(1);
for(int i=0;i<_rowcount;i++)
{object[] newrowdata=new object[_colcount];for(int j=0;j<_colcount;j++){newrowdata[j]=cells[i,j];}DataRow dr=dt.Rows.Add(newrowdata);
}

删除虚拟列 

重新计算最后单元格,删除 DataSet 最后列(虚拟列),这样就达到正确输出数据集数据的目的。 代码如下:

_lastcell = excel.Cells[_lastcell.Row, _lastcell.Column - 1];
dt.Columns.Remove(dt.Columns[dt.Columns.Count - 1]);

总结

在实际的应用中,还可能遇到更多的合并情况,我们要进行进一步的情况判断和功能完善,让导入功能变得更强大,本文示例提供了一些操作Excel相关的关键方法和属性,这里仅作参考,欢迎大家评论指教!

相关文章:

C# 实现完善 Excel 不规则合并单元格数据导入

目录 功能完善 Excel与DataSet的映射关系 运行环境 Excel DCOM 配置 设计实现 组件库引入 方法更新 返回值 参数设计 打开数据源并计算Sheets 拆分合并的单元格 创建DataTable 将单元格数据写入DataTable 删除虚拟列 总结 功能完善 在我的文章 《C#实现Excel…...

C#功能测试

List 内部元素为引用 src[0]为"11" List<Source> src new List<Source>(); src.Add(new Source() { Name "1", Age 1, Description "1" }); src.Add(new Source() { Name "2", Age 2, Description "2"…...

C++17并行化加速STL算法——std::execution

C17 并行化STL算法 文章目录 C17 并行化STL算法概念环境准备工具类 并行算法 - 使用并行算法 - 执行策略总览选择标准详细介绍顺序执行 seq并行化顺序执行 par并行化乱序执行 par_unseq 并行算法 - 异常处理可以不使用并行算法并行算法 - 限制并行算法有哪些原有算法17引入新算…...

从sumsub获取用户图片

已经拿到了imageid 然后从哪个接口可以获取图片文件呢&#xff1f; 根据您的问题,我可以为您提供以下信息: 一旦您获得了imageId,您可以使用以下几个API接口来获取图片文件: 获取文档图片: Get document images GET https://api.sumsub.com/resources/inspections/{inspection…...

DeepSeek + Mermaid编辑器——常规绘图

下面这张图出自&#xff1a;由清华大学出品的 《DeepSeek&#xff1a;从入门到精通》。 作为纯文本生成模型&#xff0c;DeepSeek虽不具备多媒体内容生成接口&#xff0c;但其开放式架构允许通过API接口与图像合成引擎、数据可视化工具等第三方系统进行协同工作&#xff0c;最终…...

ARM64 Trust Firmware [五 ]

本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。 要了解 SMC&#xff0c;必须从 SMC 指令本身开始&#xff0c;其指令如下图&#xff1a; 指令格式为&#xff1a;SMC #<imm>&#xff0c;从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用&#xff…...

Excel核心函数VLOOKUP全解析:从入门到精通

一、函数概述 VLOOKUP是Excel中最重要且使用频率最高的查找函数之一&#xff0c;全称为Vertical Lookup&#xff08;垂直查找&#xff09;。该函数主要用于在数据表的首列查找特定值&#xff0c;并返回该行中指定列的对应值。根据微软官方统计&#xff0c;超过80%的Excel用户在…...

KTransformers如何通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度?

KTransformers通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度&#xff0c;具体体现在以下几个方面&#xff1a; 内核级优化&#xff1a; KTransformers采用了高效的内核级优化技术&#xff0c;包括对Transformer模型中的关键操作进行优化。例如…...

审计级别未启用扩展模式导致查询 DBA_AUDIT_TRAIL 时 SQL_TEXT 列为空

如果查询 DBA_AUDIT_TRAIL 时发现 SQL_TEXT 列为空&#xff0c;但其他字段&#xff08;如 OS_USERNAME、USERNAME、TIMESTAMP 等&#xff09;有数据&#xff0c;可能是由于以下原因之一。以下是可能的原因及解决方法&#xff1a; 1. 审计级别未启用扩展模式 默认情况下&#x…...

微信小程序项目 video 组件失效问题,无法播放本地视频

问题与处理策略 问题描述 <video src"../../assets/video/test-video.mp4" controls style"width: 100%; height: 300px;"></video>在微信小程序项目中&#xff0c;上述 video 组件失效&#xff0c;视频无法加载&#xff0c;无法播放本地视频…...

若依-@Excel新增注解numberFormat

Excel注解中原本的scale会四舍五入小数&#xff0c;导致进度丢失 想要的效果 显示的时候保留两个小数真正的数值是保留之前的数值 还原过程 若以中有一個專門的工具类&#xff0c;用来处理excel的 找到EXCEL导出方法exportExcel()找到writeSheet,写表格的方法找到填充数据的方法…...

网络安全行业有哪些公司

只是简单做一下网络安全公司梳理&#xff0c;不作点评&#xff0c;下列排名不分先后。 一、常见的网络安全公司 1、天融信 天融信&#xff08;002212.SZ&#xff09;创始于1995年&#xff0c;是上市公司中成立最早的网络安全企业&#xff0c;亲历中国网络安全产业的发展历程…...

存储区域网络(SAN)管理

存储区域网络&#xff08;Storage Area Network&#xff0c;SAN&#xff09;采用网状通道&#xff08;Fibre Channel &#xff0c;简称FC&#xff09;技术&#xff0c;通过FC交换机连接存储阵列和服务器主机&#xff0c;建立专用于数据存储的区域网络。SAN提供了一种与现有LAN连…...

如何使用Spark SQL进行复杂的数据查询和分析

使用Spark SQL进行复杂的数据查询和分析是一个涉及多个步骤和技术的过程。以下是如何使用Spark SQL进行复杂数据查询和分析的详细指南&#xff1a; 一、准备阶段 环境搭建&#xff1a; 确保已经安装并配置好了Apache Spark环境。准备好数据源&#xff0c;可以是CSV文件、JSON…...

sass报错:[sass] Undefined variable. @import升级@use语法注意事项

今天创建vue3项目&#xff0c;迁移老项目代码&#xff0c;使用sass的时候发现import语法已经废弃&#xff0c;官方推荐使用use替换。 这里我踩了一个坑找半天的问题&#xff0c;原因是sass升级到1.85之后 定义变量前加上 - 就是表示变量私有&#xff0c;即使使用use导出 在新的…...

使用 SDKMAN! 在 Mac(包括 ARM 架构的 M1/M2 芯片)安装适配 Java 8 的 Maven

文章目录 1、安装 SDKMAN!2、安装 Maven:2.1、maven 3.9.62.2、maven 3.8.1 好的&#xff0c;这是使用 SDKMAN! 安装适配 Java 8 的 Maven 的步骤&#xff1a; 1、安装 SDKMAN! 前提条件: 安装 SDKMAN!: 如果你的系统上没有安装 SDKMAN!&#xff0c;请按照以下说明进行安装: c…...

anythingllm服务器部署+ollama+deepseek+实现本地知识库问答

一、docker安装anythingllm 1、拉取镜像 docker pull mintplexlabs/anythingllm:latest 2、创建db目录和配置文件并运行 anythingLLM 容器 export STORAGE_LOCATION/data/ai/wjh_team/anythingllm && \mkdir -p $STORAGE_LOCATION && \touch "$STORAG…...

深度学习04 数据增强、调整学习率

目录 数据增强 常用的数据增强方法 调整学习率 学习率 调整学习率 ​调整学习率的方法 有序调整 等间隔调整 多间隔调整 指数衰减 余弦退火 ​自适应调整 自定义调整 数据增强 数据增强是通过对训练数据进行各种变换&#xff08;如旋转、翻转、裁剪等&#xff09;&am…...

2023年全国职业院校技能大赛GZ073网络系统管理赛项赛题第10套模块A:网络构建

​有问题请留言或主页私信咨询 2023年全国职业院校技能大赛 GZ073网络系统管理赛项 赛题第10套 模块A&#xff1a;网络构建 ​ ​ **目 **录 任务清单 &#xff08;一&#xff09;基础配置 &#xff08;二&#xff09;有线网络配置 &#xff08;三&#xff09;无线…...

2023年河北省职业院校技能大赛网络系统管理赛项样题解法

​ 有问题请留言或主页私信咨询 配置文件有部分测试时的冗余配置无视即可。 解法只有大致解法&#xff0c;并不完整。请参考配置&#xff0c;自己补全 基础配置 1.所有交换机和无线控制器开启SSH服务&#xff0c;用户名密码分别为admin、admin1234&#xff1b;密码为明文类…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...