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 上登台,讨论开发者的新产品,感觉有点奇怪。 随着公司内部的这些变化,你不禁会想:我们还应该信任他吗&#…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
