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

WPF编程excel表格操作

WPF编程excel表格操作

  • 摘要
  • NPOI安装
  • 封装代码
  • 测试代码

摘要

Excel操作几种方式

  • 使用开源库NPOI(常用,操作丰富)
  • 使用Microsoft.Office.Interop.Excel COM组件(兼容性问题)
  • 使用OpenXml(效率高)
  • 使用OleDb(过时)

NPOI安装

在这里插入图片描述

封装代码

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;using NPOI.SS.Util;
using NPOI.SS.UserModel;    
using NPOI.XSSF.UserModel;  // 对于.xlsx文件
using NPOI.HSSF.UserModel;  // 对于.xls文件namespace GasAlarmTestTool
{internal class ExcelTools{/// <summary>/// 创建Excel表/// </summary>/// <param name="filePath"></param>/// <param name="dataTable"></param>public void CreateNewExcel(string filePath, DataTable dataTable){IWorkbook workbook;if (filePath.EndsWith(".xlsx")){workbook = new XSSFWorkbook(); // 创建 .xlsx 文件}else{workbook = new HSSFWorkbook(); // 创建 .xls 文件}var sheet = workbook.CreateSheet("Sheet1");// 写入表头var headerRow = sheet.CreateRow(0);for (int i = 0; i < dataTable.Columns.Count; i++){headerRow.CreateCell(i).SetCellValue(dataTable.Columns[i].ColumnName);}// 写入数据for (int i = 0; i < dataTable.Rows.Count; i++){var dataRow = sheet.CreateRow(i + 1);for (int j = 0; j < dataTable.Columns.Count; j++){dataRow.CreateCell(j).SetCellValue(dataTable.Rows[i][j].ToString());}}SetUniformColumnWidth(sheet, 20);   // 默认统一列宽20// 保存文件using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)){workbook.Write(stream);}}/// <summary>/// 追加Excel表/// 追加数据时,可以定位到现有数据的末尾,创建新行并写入。/// </summary>/// <param name="filePath"></param>/// <param name="dataTable"></param>public void AppendDataToExistingExcel(string filePath, DataTable dataTable){IWorkbook workbook;using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)){workbook = filePath.EndsWith(".xlsx") ? (IWorkbook)new XSSFWorkbook(stream) : new HSSFWorkbook(stream);}var sheet = workbook.GetSheetAt(0);int lastRowNum = sheet.LastRowNum;for (int i = 0; i < dataTable.Rows.Count; i++){var dataRow = sheet.CreateRow(lastRowNum + i + 1);for (int j = 0; j < dataTable.Columns.Count; j++){dataRow.CreateCell(j).SetCellValue(dataTable.Rows[i][j].ToString());}}using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Write)){workbook.Write(stream);}}/// <summary>/// 查找指定列是否存在item项/// </summary>/// <param name="filePath"></param>/// <param name="item"></param>/// <param name="colIndex"></param>/// <returns></returns>public bool SearchColumnExitsItem(string filePath, string item, int colIndex){IWorkbook workbook;using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)){workbook = filePath.EndsWith(".xlsx") ? (IWorkbook)new XSSFWorkbook(stream) : new HSSFWorkbook(stream);}var sheet = workbook.GetSheetAt(0);// 遍历每一行for (int row = 0; row <= sheet.LastRowNum; row++){IRow currentRow = sheet.GetRow(row);if (currentRow != null){// 遍历每一列for (int column = 0; column < currentRow.LastCellNum; column++){ ICell currentCell = currentRow.GetCell(column);var cellValue = currentCell.ToString();if ((column == colIndex) && (cellValue == item)){return true;}}}}     return false;}/// <summary>/// 设置列宽/// </summary>/// <param name="workbook"></param>/// <param name="sheetIndex"></param>/// <param name="columnIndex"></param>public void SetColumnWidth(IWorkbook workbook, int sheetIndex, int columnIndex){var sheet = workbook.GetSheetAt(sheetIndex);// 设置列宽(单位是 1/256 字符宽度)sheet.SetColumnWidth(columnIndex, 20 * 256); // 设置第1列宽度为20}/// <summary>/// 设置行高/// </summary>/// <param name="workbook"></param>/// <param name="sheetIndex"></param>/// <param name="rowIndex"></param>public void SetColumnRowHeight(IWorkbook workbook, int sheetIndex, int rowIndex){var sheet = workbook.GetSheetAt(sheetIndex);// 设置行高(单位是点数)var row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex);row.HeightInPoints = 25; // 设置行高为25点}/// <summary>/// 同时设置列宽和行高/// </summary>/// <param name="workbook"></param>/// <param name="sheetIndex"></param>/// <param name="columnIndex"></param>/// <param name="rowIndex"></param>/// <param name="width"></param>/// <param name="height"></param>public void SetColumnWidthAndRowHeight(IWorkbook workbook, int sheetIndex, int columnIndex, int rowIndex, int width, int height){var sheet = workbook.GetSheetAt(sheetIndex);// 设置列宽(单位是1/256字符宽度)sheet.SetColumnWidth(columnIndex, width * 256); // 设置第1列宽度为 20 var row = sheet.GetRow(rowIndex) ?? sheet.CreateRow(rowIndex); row.HeightInPoints = height; // 25}/// <summary>/// 设置统一行高/// </summary>/// <param name="sheet"></param>/// <param name="heightInPoints"></param>public void SetUniformRowHeight(ISheet sheet, float heightInPoints){for (int i = 0; i < sheet.LastRowNum; i++){ var row = sheet.GetRow(i) ?? sheet.CreateRow(i);row.HeightInPoints = heightInPoints;}}/// <summary>/// 设置统一列宽/// </summary>/// <param name="sheet"></param>/// <param name="widthInCharacters"></param>public void SetUniformColumnWidth(ISheet sheet, int widthInCharacters){for (int i = 0; i < sheet.GetRow(0).LastCellNum; i++) // 以第一行的单元格数量为列数{sheet.SetColumnWidth(i, widthInCharacters * 256); // 设置列宽}}/// <summary>/// 设置统一行高和列宽/// </summary>/// <param name="sheet"></param>/// <param name="rowHeightInPoints"></param>/// <param name="columnWidthCharacters"></param>public void SetUniformRowHeightAndColumnWidth(ISheet sheet, float rowHeightInPoints, int columnWidthCharacters){SetUniformRowHeight(sheet, rowHeightInPoints);SetUniformColumnWidth(sheet, columnWidthCharacters);}/// <summary>/// 合并单元格可以通过 CellRangeAddress 设置,需要定义起始和结束的行列。/// </summary>/// <param name="workbook"></param>/// <param name="sheetIndex"></param>/// <param name="firstRow"></param>/// <param name="lastRow"></param>/// <param name="firstCol"></param>/// <param name="lastCol"></param>public void MergeCells(IWorkbook workbook, int sheetIndex, int firstRow, int lastRow, int firstCol, int lastCol){var sheet = workbook.GetSheetAt(sheetIndex);// 合并单元格var cellRangeAddress = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);sheet.AddMergedRegion(cellRangeAddress);// 可以对合并后的单元格设置样式var cell = sheet.GetRow(firstRow).GetCell(firstCol) ?? sheet.GetRow(firstRow).CreateCell(firstCol);var style = workbook.CreateCellStyle();style.Alignment = HorizontalAlignment.Center;cell.CellStyle = style; }public void SetCellStyle(IWorkbook workbook, int sheetIndex, int rowIndex, int colIndex){var sheet = workbook.GetSheetAt(sheetIndex);var cell = sheet.GetRow(rowIndex).GetCell(colIndex) ?? sheet.GetRow(rowIndex).CreateCell(colIndex);var style = workbook.CreateCellStyle();// 设置字体var font = workbook.CreateFont();font.FontHeightInPoints = 1;font.FontName = "Arial";font.IsBold = true;style.SetFont(font);// 设置边框style.BorderBottom = BorderStyle.Thin;style.BorderLeft = BorderStyle.Thin;style.BorderRight = BorderStyle.Thin;style.BorderTop = BorderStyle.Thin;// 设置背景颜色style.FillForegroundColor = IndexedColors.LightBlue.Index;style.FillPattern = FillPattern.SolidForeground;cell.CellStyle = style;cell.SetCellValue("示例文本内容");}}
}

测试代码

private ExcelTools excel = new ExcelTools();
string excelFileName = Properties.Settings.Default.SavePath + "/燃气报警器数据表格.xlsx";// TODO: 生成保存数据
DataTable dt = new DataTable();
dt.Columns.Add("设备UUID", typeof(string));
dt.Columns.Add("SIM卡号", typeof(string));
dt.Columns.Add("设备型号", typeof(string));
dt.Columns.Add("网络型号", typeof(string));
dt.Columns.Add("生产日期", typeof(string));DataRow dr = dt.NewRow();
dr["设备UUID"] = "2021886000001";
dr["SIM卡号"] = "86452215642112345675";
dr["设备型号"] = "单甲烷";
dr["网络型号"] = "NB-IoT";
dr["生产日期"] = DateTime.Now.ToString();
dt.Rows.Add(dr);if (excelFileName.EndsWith(".xls") || excelFileName.EndsWith(".xlsx"))
{if (!File.Exists(excelFileName)){// TODO: 文件不存在创建文件excel.CreateNewExcel(excelFileName, dt);}else{// TODO: 将IMEI号写入个Excel表格,若已经写入过则不再写入,防止重复写入if (excel.SearchColumnExitsItem(excelFileName, label_imei.Content.ToString(), 0) == false){excel.AppendDataToExistingExcel(excelFileName, dt);}}
}
else
{MessageBox.Show("请先设置表格文件保存!");
}

相关文章:

WPF编程excel表格操作

WPF编程excel表格操作 摘要NPOI安装封装代码测试代码 摘要 Excel操作几种方式 使用开源库NPOI(常用&#xff0c;操作丰富)使用Microsoft.Office.Interop.Excel COM组件(兼容性问题)使用OpenXml(效率高)使用OleDb(过时) NPOI安装 封装代码 using System; using System.IO; u…...

Day10补代码随想录 理论基础|232.用栈实现队列|225.用队列实现栈|20.有效的括号|1047.删除字符串中的所有相邻重复项

栈和队列理论基础 抽象认识 栈是先进后出(FIFO)&#xff0c;队列是先进先出(LIFO) 队首(先进))队尾(后进)栈顶(后进)栈底(先进) 栈(Stack) 只在一端进行进出操作(只在一端进一端出)像个篮球框&#xff0c;取用篮球从一端进出。 /进栈 int a[1000];//足够大的栈空间 int top-1…...

【Devops】什么是Devops?(Development+Operations)和运维的区别?

DevOps&#xff08;Development Operations&#xff09;是一种将开发&#xff08;Development&#xff09;和运维&#xff08;Operations&#xff09;团队结合在一起的文化和实践&#xff0c;目的是通过自动化、协作和持续反馈来加快软件的开发、部署和运维的周期&#xff0c;…...

基于NodeMCU的物联网电灯控制系统设计

最终效果 基于NodeMCU的物联网电灯控制系统设计 小程序关灯 上图展现了小程序关灯过程的数据传输过程&#xff1a;用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。 项目介绍 该项目是“物联网实验室监测控制系统设计&#xff08;…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02

在嵌入式开发中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种常用的串行通信协议&#xff0c;广泛应用于与外设&#xff08;如 EEPROM、传感器、显示屏等&#xff09;进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器&#xff0c;它提供 2Kbit…...

Linux应用软件编程-多任务处理(线程)

线程&#xff1a;轻量级的进程&#xff0c;线程的栈区独立&#xff08;8M&#xff09;&#xff0c;与同一进程中的其他线程共用进程的堆区&#xff0c;数据区&#xff0c;文本区。 进程是操作系统资源分配的最小单位&#xff1b;线程是cpu任务调度的最小单位。 1. 线程的创建…...

VITUREMEIG | AR眼镜 算力增程

根据IDC发布的《2024年第三季度美国AR/VR市场报告》显示&#xff0c;美国市场AR/VR总出货量增长10.3%。其中&#xff0c;成立于2021年的VITURE增长速度令人惊艳&#xff0c;同比暴涨452.6%&#xff0c;成为历史上增长最快的AR/VR品牌。并在美国AR领域占据了超过50%的市场份额&a…...

Jenkins管理多版本python环境

场景&#xff1a;项目有用到python3.8和3.9&#xff0c;python环境直接安装在jenkins容器内。 1、进入jenkins容器 docker exec -it jenkins /bin/bash 2、安装前置编译环境 # 提前安装&#xff0c;以便接下来的配置操作 apt-get -y install gcc automake autoconf libtool ma…...

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件&#xff0c;而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能&#xff0c;比如在富文本…...

如何解决 OpenAI API 连接问题:降级 urllib3 版本

如何解决 OpenAI API 连接问题&#xff1a;降级 urllib3 版本 在使用 OpenAI API 时&#xff0c;很多开发者可能会遇到连接问题&#xff0c;特别是在使用 Python 代码与 OpenAI 进行交互时。常见的错误包括 ProxyError、SSLError 和 MaxRetryError&#xff0c;它们通常表示在通…...

【C语言】库函数常见的陷阱与缺陷(三):内存分配函数[4]--free

C语言中的free函数用于释放之前通过malloc、calloc或realloc动态分配的内存。然而,在使用free函数时,开发者可能会遇到一些陷阱和缺陷。 一、功能与用法 free 函数是 C 语言中用于释放动态分配内存的关键函数。在程序使用 malloc、calloc 或 realloc 等函数在堆上分配了内存…...

论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试

大语言模型拥有的强大能力可以用来辅助多种工作&#xff0c;但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz&#xff0c;它利用模型提示生成模糊测试驱动代码&#xff0c;并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…...

JavaSE笔记(四)

Java泛型与集合类 在前面我们学习了最重要的类和对象,了解了面向对象编程的思想,注意,非常重要,面向对象是必须要深入理解和掌握的内容,不能草草结束。在本章节,我们会继续深入了解,从我们的泛型开始,再到我们的数据结构,最后再开始我们的集合类学习。 走进泛型 为…...

C语言基础——指针(5)

一&#xff0e; 函数指针变量 1. 函数指针变量的定义&#xff1a; 类比数组指针变量&#xff0c;数组指针变量是存放数组地址的变量&#xff0c;那么同理&#xff0c;函数指针变量就是存放函数地址的变量。 2. 创建函数指针变量&#xff1a; 函数是有地址的&#xff0…...

curl+openssl 踩坑笔记

curl编译&#xff1a;点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

Unity 实现Canvas显示3D物体

新建一个UI相机&#xff0c;选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体&#xff0c;并将3D物体的层级设置为UI层 适当的放缩3DObjParent&#xff0c;让3D物体能显示出来…...

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…...

NetSuite Formula(HTML)超链打开Transaction

当Saved Search作为Sublist应用在Form时&#xff0c;如果Document Number是Group过的&#xff0c;则会出现如下超链失效的情况。 解决办法&#xff1a; 可以利用Saved Search中的Formula&#xff08;HTML&#xff09;功能来构建超链&#xff0c;用于打开Transaction。 以下图…...

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...