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

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 数据输出时遇到了一个问题&#xff0c;开发者设计了单行细线下边框的输出模板&#xff0c;如下图设计&#xff1a; 其中 <%syst…...

前端组件化开发

假设这个页面是vue开发的&#xff0c;如果一整个页面都是编写在一个vue文件里面&#xff0c;后期不好维护&#xff0c;会特别的庞大&#xff0c;那么如何这个时候需要进行组件化开发。组件化开发后必然会带来一个问题需要进行组件之间的通信。组要是父子组件之间通信&#xff0…...

异步操作实现线程池

文章目录 futureasyncpromisepackage task C11线程池实现 future 在C11标准库中&#xff0c;提供了一个future的模板类&#xff0c;它表示的是一个异步操作的结果&#xff0c;当在多线程编程中使用异步任务的时候&#xff0c;使用这个类可以帮助在需要的时候获取到对应的数据处…...

长期提供APX515/B原装二手APX525/B音频分析仪

Audio Precision APx515 是一款针对生产测试而优化的高性能音频分析仪。它因其速度、性能、自动化和易用性而成为一流的仪器。它具有卓越的性能&#xff0c;具有 –106 dB 的典型 THDN、1M 点 FFT 和 192k 数字 I/O&#xff0c;以及所有 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注意&#xff01;本文中开启docker远程连接的方法只能在确定环境安全的内网中使用&#xff0c;不可在公网服务器设置&#xff0c;有极大安全风险&#xff01; 注意&#xff01;本文中开启docker远程连接的…...

Docker 安装 ClickHouse 教程

Docker 安装 ClickHouse 教程 创建目录 首先&#xff0c;创建必要的目录用于存放 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 等语言的局限性而出现的现象。 内存安全问题已存在五十多年&#xff0c;它要求程序员从内存管理任务中抽离出来。 Java、Rust、Python 和 JavaScript 等现代语言通…...

在Pycharm中安装Cv2

安装OpenCV&#xff1a; 在Terminal中&#xff0c;输入以下pip命令来安装OpenCV&#xff1a; pip install opencv-python pip install opencv-contrib-python 如果下载速度较慢&#xff0c;可以考虑使用国内的pip镜像源&#xff0c;如清华大学源&#xff1a; pip install openc…...

减少重复的请求之promise缓存池(构造器版) —— 缓存promise,多次promise等待并返回第一个promise的结果

减少重复的请求之promise缓存池 —— 缓存promise&#xff0c;多次promise等待并返回第一个promise的结果 背景简介 当一个业务组件初始化调用了接口&#xff0c;统一个页面多吃使用同一个组件&#xff0c;将会请求大量重复的接口 如果将promise当作一个普通的对象&#xff0…...

cdq+bitset处理高维偏序

高维偏序 CDQ分治 假设处理的区间为 [ l , r ] [l,r] [l,r] &#xff0c;CDQ分治的过程&#xff1a; 如果 l ≥ r l\geq r l≥r &#xff0c;返回。设区间中点为 m i d mid mid &#xff0c;递归处理 [ l , m i d ] [l,mid] [l,mid] 和 [ m i d 1 , r ] [mid1,r] [mid…...

敏捷开发和传统开发,你更适合哪种?

时间&#xff1a;2024年 10月 03日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频&#xff1a;喜马拉雅 大家好&#xff0c;欢迎来到“小蒋聊技术”&#xff0c;我是小蒋&#xff01;今天我们来聊聊两个开发模式的“对决”…...

python之with

with上下文管理是什么呢&#xff1f; 一般都是使用系统提供的一些with语句&#xff0c;列如我要去读取一些数据进行分析&#xff0c;就可以使用with open去读取某些数据&#xff0c;或者我要把一些图片给他保存到某些地方&#xff0c;可以用with给他写入。 上下午管理器with是…...

vue3 升级实战笔记

最近要将公司项目的移动端进行 vue3 的升级工作&#xff0c;就顺便记录下升级过程。 项目迁移的思路 我的想法是最小改动原则。 从 vue2.x 升级到 vue3&#xff0c;且使用 vue3 的 选项式 API。构建工具要从 vue-cli&#xff08;webpack&#xff09;升级到 vite。路由需要升级到…...

利用函数模块化代码实操 ← Python

【知识点】 ● 模块化可以使代码易于维护和调试&#xff0c;并且提高代码的重用性。 ● 函数可以用来减少冗余的代码并提高代码的可重用性。函数也可以用来模块化代码并提高程序的质量。 ● 在 Python 中&#xff0c;可以将函数的定义放在一个被称为模块的文件中,这种文件的后缀…...

Java高效编程(12):重写toString方法

解锁Python编程的无限可能&#xff1a;《奇妙的Python》带你漫游代码世界 尽管 Object 类提供了 toString 方法的默认实现&#xff0c;但它返回的字符串通常不是类的使用者想要看到的。默认返回的字符串格式是类名加上“”符号和哈希码的十六进制表示&#xff0c;例如 PhoneNu…...

谷歌给到的185个使用生成式AI的案例

很多公司从利用AI回答问题&#xff0c;进而使用AI进行预测&#xff0c;向使用生成式AI Agent转变。AI Agent的独特之处在于它们可以采取行动以实现特定目标&#xff0c;比如引导购物者找到合适的鞋子&#xff0c;帮助员工寻找合适的健康福利&#xff0c;或在护理人员交接班期间…...

程序员如何通过专业与软技能提升核心竞争力

一、引言  随着AIGC的兴起&#xff0c;AI辅助编程工具如chatgpt、midjourney、claude等接二连三地涌现&#xff0c;编程领域的变革正逐步深化。面对这一变革&#xff0c;程序员们对于未来工作的前景有着种种不同的担忧和期待。他们担心AI可能取代部分编程工作&#xff0c;同时…...

基于YOLOv8的智能植物监测机器人

摘要:针对传统的植物病害检测方法依赖专家的经验,耗时耗力,并且准确性受限于个人的水平等问题。文中提出无线通信模块采用HTTP协议来传输数据图片,采用SoC核心处理器实现了便携化,采用对射式红外避障传感器实现自动避障功能。以YOLOv8算法为控制核心,并添加注意力机制以提…...

2024年OpenAI DevDay发布实时 API、提示缓存等新功能

就在几天前&#xff0c;一些重要人物如前 CTO Mira Murati 离开了 OpenAI。因此&#xff0c;看到 Sam Altman 在 DevDay 上登台&#xff0c;讨论开发者的新产品&#xff0c;感觉有点奇怪。 随着公司内部的这些变化&#xff0c;你不禁会想&#xff1a;我们还应该信任他吗&#…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...