C# 解决Excel边框样式无法复制问题及实现格式刷功能
目录
问题现象
范例运行环境
解决方案
剪贴板加特殊粘贴
自定义样式
直接赋值
完美方案
小结
问题现象
在运行数据表数据导出到 EXCEL 数据输出时遇到了一个问题,开发者设计了单行细线下边框的输出模板,如下图设计:

其中 <%system.excel.title.dyna.by.craneoffice%> 字符标记用于输出报表标题替换。数据从A5列开始至D5列结束,按行输出。期望得到如下输出样式:

虽然已经自定义了复制样式的方法,包括边框风格的复制,但实际输出遇到了如下情况:
实际想要得到的单行细线下边框输出没有实现,使用简单 Borders.LineStyle 赋值没有奏效,以后输出的行复制第一行的样式没有成功,因此需要调整样式输出策略,实现类似格式刷那样的操作,这样即实现了格式输出的完整性,也保证了性能。
范例运行环境
操作系统: Windows Server 2019 DataCenter
.net版本: .netFramework4.0 或以上
Office Excel 2016
开发工具:VS2019 C#
解决方案
剪贴板加特殊粘贴
使用 COM 操作的流程原理如下图:

实现代码,示例如下:
SRange.Copy(); //将源选定范围复制到剪贴板
Range.PasteSpecial(Excel.XlPasteType.xlPasteFormats); //特殊粘贴格式到目标选定范围
Copy() 方法实现了复制所有数据到剪贴板功能,其中也包括了样式。 PasteSpecial() 方法实现了指定粘贴的功能,其中 Excel.XlPasteType.xlPasteFormats 表示只粘贴格式样式,至此实现了模拟格式刷的功能。 但此方法可能会引起多 Excel 应用的复制冲突,因此相对保险的写法可以改成如下代码:
SRange.Copy(Range);
但这样会有一个问题是,如果像模板输出还好,但想要仅粘贴格式则无法实现,因此也有局限性。而且这种实现原理,微软可能也会有所调整,也无法保障以后的应用是否会引起复制冲突。所以我们在下个小节通过自定义样式的方式来模拟格式刷的功能。
自定义样式
使用 COM 操作的流程原理如下图:


示例代码如下:
string stylename = Guid.NewGuid().ToString();
WorkBook xb=WorkBooks[1];Style newStyle = xb.Styles.Add(stylename);设置样式属性
newStyle.Font.Name = "宋体";
newStyle.Font.Size = 11;
newStyle.Font.Bold = true;newStyle.Borders.Weight = XlBorderWeight.xlHairline; //最细的线
newStyle.Borders.LineStyle = XlLineStyle.xlContinuous; //实线
以上是添加样式的示例,因为样式很多,实现格式复制的简单方法,是创建新名称并直接引用源单元格的样式,应用到目标选范围上即可,如果有需要移除或修改的样式,可以继续对新建样式进行赋值,修改后如下代码示例:
string stylename = Guid.NewGuid().ToString();
WorkBook xb=WorkBooks[1];Style newStyle = xb.Styles.Add(stylename);newStyle = SRange.Style; //将源选定范围样式赋值到自定义新建样式newStyle.Font.Name="宋体"; //修改字体为宋体Range.Style = newStyle.Name;
直接赋值
Range.Style 是一个 dynamic 类型,可以赋予任何可以正确实现的类型,如自定义样式名称(newStyle.Name),也可以直接赋值为 Style 类型,简单而暴力,代码如下:
Range.Style = SRange.Style; //将源选定范围样式赋值到目标
完美方案
在实际的运行中,无论是自定义样式还是直接赋值模式,对复制字体时出现了无法复制的问题,因此还是需要结合自定义复制样式方法来弥补问题,代码如下:
public void copyRangeStyle(Excel.Range srcRange,Excel.Range desRange)
{desRange.Font.Background=srcRange.Font.Background;desRange.Font.Bold=srcRange.Font.Bold;desRange.Font.Color=srcRange.Font.Color;desRange.Font.Italic=srcRange.Font.Italic;desRange.Font.Name=srcRange.Font.Name;desRange.Font.OutlineFont=srcRange.Font.OutlineFont;desRange.Font.Shadow=srcRange.Font.Shadow;desRange.Font.Size=srcRange.Font.Size;desRange.Font.Strikethrough=srcRange.Font.Strikethrough;desRange.Font.Underline=srcRange.Font.Underline;desRange.RowHeight=srcRange.RowHeight;desRange.HorizontalAlignment=srcRange.HorizontalAlignment;desRange.VerticalAlignment=srcRange.VerticalAlignment;
}
copyRangeStyle 自定义复制样式方法包括 源选定范围参数(Excel.Range srcRange)和目标选定范围参数(Excel.Range desRange),至此,完整代码可修整如下:
Range.Style = SRange.Style;copyRangeStyle(SRange, Range);
至此结合 copyRangeStyle 方法完美解决样式复制问题。
copyRangeStyle 方法请根据实际需要的样式进行扩充或调整。
小结
关于 Range.Borders 的COM 操作如下图:

这个样式的设定是有点击顺序的,选边框后点击样式是无效的,需要点击样式再进行选边框的切换,才会得到预期效果。正常可通过 Range.Borders 直接表示所有6个框线的集合,直接为其赋值,如下代码:
newStyle.Borders.Weight = XlBorderWeight.xlHairline; //最细的线
newStyle.Borders.LineStyle = XlLineStyle.xlContinuous; //实线类型边框
newStyle.Borders.Color = Color.Red; //红色边框
如果想只设置某一边框,则需要获取 Borders 集合里的 Border,如下几种方式都可以获取其中的某一个 Border 对象:
//右、左、下、上边框
Range.Borders.get_Item(XlBordersIndex.xlEdgeRight).LineStyle = XlLineStyle.xlLineStyleNone;
Range.Borders.get_Item(XlBordersIndex.xlEdgeLeft).LineStyle = XlLineStyle.xlContinuous;
Range.Borders.get_Item(XlBordersIndex.xlEdgeBottom).LineStyle = XlLineStyle.xlContinuous;
Range.Borders.get_Item(XlBordersIndex.xlEdgeTop).LineStyle = XlLineStyle.xlContinuous;//内部交叉斜线
Range.Borders.Item[XlBordersIndex.xlDiagonalDown].LineStyle = XlLineStyle.xlLineStyleNone;
Range.Borders[XlBordersIndex.xlDiagonalUp].LineStyle = XlLineStyle.xlLineStyleNone;
我们可以使用 Borders.get_Item 方法或引用 Item 索引或直接引用索引的方法得到 Border,但实际的使用过程中,预期效果不理想,因此我们使用了样式赋值,类似格式刷的方法来解决。
更多可参考如下文章链接:
https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.office.interop.excel.xlbordersindex?view=excel-pia&source=recommendations
https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.office.interop.excel.styles?view=excel-pia
《C# 实现二维数据数组导出到 Excel》
本文代码仅供您参考使用,感谢您的阅读,希望本文能够对您有所帮助。
相关文章:
C# 解决Excel边框样式无法复制问题及实现格式刷功能
目录 问题现象 范例运行环境 解决方案 剪贴板加特殊粘贴 自定义样式 直接赋值 完美方案 小结 问题现象 在运行数据表数据导出到 EXCEL 数据输出时遇到了一个问题,开发者设计了单行细线下边框的输出模板,如下图设计: 其中 <%syst…...
前端组件化开发
假设这个页面是vue开发的,如果一整个页面都是编写在一个vue文件里面,后期不好维护,会特别的庞大,那么如何这个时候需要进行组件化开发。组件化开发后必然会带来一个问题需要进行组件之间的通信。组要是父子组件之间通信࿰…...
异步操作实现线程池
文章目录 futureasyncpromisepackage task C11线程池实现 future 在C11标准库中,提供了一个future的模板类,它表示的是一个异步操作的结果,当在多线程编程中使用异步任务的时候,使用这个类可以帮助在需要的时候获取到对应的数据处…...
长期提供APX515/B原装二手APX525/B音频分析仪
Audio Precision APx515 是一款针对生产测试而优化的高性能音频分析仪。它因其速度、性能、自动化和易用性而成为一流的仪器。它具有卓越的性能,具有 –106 dB 的典型 THDN、1M 点 FFT 和 192k 数字 I/O,以及所有 APx 系列音频分析仪的一键式自动化和易用…...
【数据库差异研究】update与delete使用表别名的研究
目录 ⚛️总结 ☪️1 Update ♋1.1 测试用例UPDATE users as a SET a.age 111 WHERE a.name Alice; ♏1.2 测试用例UPDATE users as a SET a.age 111 WHERE name Alice; ♐1.3 测试用例UPDATE users as a SET age 111 WHERE a.name Alice; ♑1.4 测试用例UPDATE us…...
idea远程连接docker
idea远程连接docker docker、ubuntu、linux、远程连接、IntelliJ idea注意!本文中开启docker远程连接的方法只能在确定环境安全的内网中使用,不可在公网服务器设置,有极大安全风险! 注意!本文中开启docker远程连接的…...
Docker 安装 ClickHouse 教程
Docker 安装 ClickHouse 教程 创建目录 首先,创建必要的目录用于存放 ClickHouse 的配置、数据和日志文件。 mkdir -p /home/clickhouse/conf mkdir -p /home/clickhouse/data mkdir -p /home/clickhouse/log chmod -R 777 /home/clickhouse/conf chmod -R 777 /…...
过渡到内存安全语言:挑战和注意事项
开放源代码安全基金会 ( OpenSSF )总经理 Omkhar Arasaratnam 讨论了内存安全编程语言的演变及其为应对 C 和 C 等语言的局限性而出现的现象。 内存安全问题已存在五十多年,它要求程序员从内存管理任务中抽离出来。 Java、Rust、Python 和 JavaScript 等现代语言通…...
在Pycharm中安装Cv2
安装OpenCV: 在Terminal中,输入以下pip命令来安装OpenCV: pip install opencv-python pip install opencv-contrib-python 如果下载速度较慢,可以考虑使用国内的pip镜像源,如清华大学源: pip install openc…...
减少重复的请求之promise缓存池(构造器版) —— 缓存promise,多次promise等待并返回第一个promise的结果
减少重复的请求之promise缓存池 —— 缓存promise,多次promise等待并返回第一个promise的结果 背景简介 当一个业务组件初始化调用了接口,统一个页面多吃使用同一个组件,将会请求大量重复的接口 如果将promise当作一个普通的对象࿰…...
cdq+bitset处理高维偏序
高维偏序 CDQ分治 假设处理的区间为 [ l , r ] [l,r] [l,r] ,CDQ分治的过程: 如果 l ≥ r l\geq r l≥r ,返回。设区间中点为 m i d mid mid ,递归处理 [ l , m i d ] [l,mid] [l,mid] 和 [ m i d 1 , r ] [mid1,r] [mid…...
敏捷开发和传统开发,你更适合哪种?
时间:2024年 10月 03日 作者:小蒋聊技术 邮箱:wei_wei10163.com 微信:wei_wei10 音频:喜马拉雅 大家好,欢迎来到“小蒋聊技术”,我是小蒋!今天我们来聊聊两个开发模式的“对决”…...
python之with
with上下文管理是什么呢? 一般都是使用系统提供的一些with语句,列如我要去读取一些数据进行分析,就可以使用with open去读取某些数据,或者我要把一些图片给他保存到某些地方,可以用with给他写入。 上下午管理器with是…...
vue3 升级实战笔记
最近要将公司项目的移动端进行 vue3 的升级工作,就顺便记录下升级过程。 项目迁移的思路 我的想法是最小改动原则。 从 vue2.x 升级到 vue3,且使用 vue3 的 选项式 API。构建工具要从 vue-cli(webpack)升级到 vite。路由需要升级到…...
利用函数模块化代码实操 ← Python
【知识点】 ● 模块化可以使代码易于维护和调试,并且提高代码的重用性。 ● 函数可以用来减少冗余的代码并提高代码的可重用性。函数也可以用来模块化代码并提高程序的质量。 ● 在 Python 中,可以将函数的定义放在一个被称为模块的文件中,这种文件的后缀…...
Java高效编程(12):重写toString方法
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 尽管 Object 类提供了 toString 方法的默认实现,但它返回的字符串通常不是类的使用者想要看到的。默认返回的字符串格式是类名加上“”符号和哈希码的十六进制表示,例如 PhoneNu…...
谷歌给到的185个使用生成式AI的案例
很多公司从利用AI回答问题,进而使用AI进行预测,向使用生成式AI Agent转变。AI Agent的独特之处在于它们可以采取行动以实现特定目标,比如引导购物者找到合适的鞋子,帮助员工寻找合适的健康福利,或在护理人员交接班期间…...
程序员如何通过专业与软技能提升核心竞争力
一、引言 随着AIGC的兴起,AI辅助编程工具如chatgpt、midjourney、claude等接二连三地涌现,编程领域的变革正逐步深化。面对这一变革,程序员们对于未来工作的前景有着种种不同的担忧和期待。他们担心AI可能取代部分编程工作,同时…...
基于YOLOv8的智能植物监测机器人
摘要:针对传统的植物病害检测方法依赖专家的经验,耗时耗力,并且准确性受限于个人的水平等问题。文中提出无线通信模块采用HTTP协议来传输数据图片,采用SoC核心处理器实现了便携化,采用对射式红外避障传感器实现自动避障功能。以YOLOv8算法为控制核心,并添加注意力机制以提…...
2024年OpenAI DevDay发布实时 API、提示缓存等新功能
就在几天前,一些重要人物如前 CTO Mira Murati 离开了 OpenAI。因此,看到 Sam Altman 在 DevDay 上登台,讨论开发者的新产品,感觉有点奇怪。 随着公司内部的这些变化,你不禁会想:我们还应该信任他吗&#…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
