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("请先设置表格文件保存!");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初识 Conda:一站式包管理和环境管理工具

文章目录 1. 什么是 Conda&#xff1f;2. 为什么选择 Conda&#xff1f;3. Conda 的安装3.1 安装步骤&#xff08;以 Miniconda 为例&#xff09; 4. Conda 的核心功能4.1 包管理4.2 环境管理4.3 Conda Forge4.4 设置国内镜像 5. 常见使用场景5.1 数据科学项目5.2 离线安装5.3 …

docker 搭建集群

准备3台机器&#xff1a; #dockermaster 192.168.31.150 sudo hostnamectl set-hostname dockermaster #初始化主节点 docker swarm init --advertise-addr 192.168.31.150 #查看集群是否搭建成功 docker node ls #dockernode1 192.168.31.151 sudo hostnamectl set-hostname …

Kafka消息不丢失与重复消费问题解决方案总结

1. 生产者层面 异步发送与回调处理 异步发送方式&#xff1a;生产者一般使用异步方式发送消息&#xff0c;异步发送有消息和回调接口两个参数。在回调接口的重写方法中&#xff0c;可通过异常参数判断消息发送状态。若消息发送成功&#xff0c;异常参数为null&#xff1b;若发…

StarRocks 存算分离在得物的降本增效实践

编者荐语&#xff1a; 得物优化数据引擎布局&#xff0c;近期将 4000 核 ClickHouse 迁移至自建 StarRocks&#xff0c;成本降低 40%&#xff0c;查询耗时减半&#xff0c;集群稳定性显著提升。本文详解迁移实践与成果&#xff0c;文末附丁凯剑老师 StarRocks Summit Asia 2024…

微服务-1 认识微服务

目录​​​​​​​ 1 认识微服务 1.1 单体架构 1.2 微服务 1.3 SpringCloud 2 服务拆分原则 2.1 什么时候拆 2.2 怎么拆 2.3 服务调用 3. 服务注册与发现 3.1 注册中心原理 3.2 Nacos注册中心 3.3 服务注册 3.3.1 添加依赖 3.3.2 配置Nacos 3.3.3 启动服务实例 …

IDEA工具使用介绍、IDEA常用设置以及如何集成Git版本控制工具

文章目录 一、IDEA二、建立第一个 Java 程序三、IDEA 常用设置四、IDEA 集成版本控制工具&#xff08;Git、GitHub&#xff09;4.1 IDEA 拉 GitHub/Git 项目4.2 IDEA 上传 项目到 Git4.3 更新提交命令 一、IDEA 1、什么是IDEA&#xff1f; IDEA&#xff0c;全称为 IntelliJ ID…

kafka开机自启失败问题处理

前言&#xff1a;在当今大数据处理领域&#xff0c;Kafka 作为一款高性能、分布式的消息队列系统&#xff0c;发挥着举足轻重的作用。无论是海量数据的实时传输&#xff0c;还是复杂系统间的解耦通信&#xff0c;Kafka 都能轻松应对。然而&#xff0c;在实际部署和运维 Kafka 的…

二维数组综合

第1题 稀疏矩阵 查看测评数据信息 nm矩阵大部分元素是0的矩阵称为稀疏矩阵&#xff0c;假设有k个非0元素&#xff0c;则可把稀疏矩阵用K3的矩阵简记之&#xff0c;其中第一列是行号&#xff0c;第二列是列号&#xff0c;第三列是该行、该列下的非0元素的值。如&#xff1a;…

STM32-笔记20-测量按键按下时间

1、按键按下的时间-思路 我们先检测下降沿信号&#xff0c;检测到以后&#xff0c;在回调函数里切换成检测上升沿信号&#xff0c;当两个信号都检测到的时候&#xff0c;这段时间就是按键按下的时间&#xff0c;如图所示&#xff1a;>N*(ARR1)CCRx的值 N是在这段时间内&…

【网络协议】路由信息协议 (RIP)

未经许可&#xff0c;不得转载。 路由信息协议&#xff08;Routing Information Protocol&#xff0c;简称 RIP&#xff09;是一种使用跳数&#xff08;hop count&#xff09;作为路由度量标准的路由协议&#xff0c;用于确定源网络和目标网络之间的最佳路径。 文章目录 什么是…

PHP后执行php.exe -v命令报错并给出解决方案

文章目录 一、执行php.exe -v命令报错解决方案 一、执行php.exe -v命令报错 -PHP Warning: ‘C:\windows\SYSTEM32\VCRUNTIME140.dll’ 14.38 is not compatible with this PHP build linked with 14.41 in Unknown on line 0 解决方案 当使用PHP8.4.1时遇到VCRUNTIME140.dll…

blender中合并的模型,在threejs中显示多个mesh;blender多材质烘培成一个材质

描述&#xff1a;在blender中合并的模型导出为glb&#xff0c;在threejs中导入仍显示多个mesh&#xff0c;并不是统一的整体&#xff0c;导致需要整体高亮或者使用DragControls等不能统一控制。 原因&#xff1a;模型有多个材质&#xff0c;在blender中合并的时候&#xff0c;…

0xc0000020错误代码怎么处理,Windows11、10坏图像错误0xc0000020的修复办法

“0xc0000020”是一种 Windows 应用程序错误代码&#xff0c;通常表明某些文件缺失或损坏。这可能是由于系统文件损坏、应用程序安装或卸载问题、恶意软件感染、有问题的 Windows 更新等原因导致的。 比如&#xff0c;当运行软件时&#xff0c;可能会出现类似“C:\xx\xxx.dll …

wangEditor富文本插件在vue项目中使用和媒体上传的实现

wangEditor是前端一个比较流行的简洁易用&#xff0c;功能强大的前端富文本编辑器&#xff0c;支持 JS Vue React&#xff0c;提供了很多丰富的功能&#xff0c;下面手把手教你实现wangWditor富文本插件在vue项目中配置&#xff0c;保存、图片上传等功能。无脑ctrlc即可 基本功…

MySQL root用户密码忘记怎么办(Reset root account password)

在使用MySQL数据库的的过程中&#xff0c;不可避免的会出现忘记密码的现象。普通用户的密码如果忘记&#xff0c;可以用更高权限的用户&#xff08;例如root&#xff09;进行重置。但是如果root用户的密码忘记了&#xff0c;由于root用户本身就是最高权限&#xff0c;那这个方法…

C语言学习笔记(1)

在学习前&#xff0c;需要有一定的C语言基础。不必很深入&#xff0c;只需要知道函数&#xff0c;头文件&#xff0c;指针&#xff0c;数组等的概念就可以&#xff0c;但并非0基础笔记。 由于写到后面&#xff0c;不好编辑了&#xff0c;决定分成多篇写&#xff0c;请按编号学…

使用uWSGI将Flask应用部署到生产环境

使用uWSGI将Flask应用部署到生产环境&#xff1a; 1、安装uWSGI conda install -c conda-forge uwsgi&#xff08;pip install uwsgi会报错&#xff09; 2、配置uWSGI 在python程序的同一文件夹下创建 uwsgi.ini文件&#xff0c;文件内容如下表。 需要按照实际情况修改文件名称…

集成方案 | Docusign + 蓝凌 EKP,打造一站式合同管理平台,实现无缝协作!

本文将详细介绍 Docusign 与蓝凌 EKP 的集成步骤及其效果&#xff0c;并通过实际应用场景来展示 Docusign 的强大集成能力&#xff0c;以证明 Docusign 集成功能的高效性和实用性。 在当今数字化办公环境中&#xff0c;企业对于提高工作效率和提升用户体验的需求日益迫切。蓝凌…

CMS漏洞靶场攻略

DeDeCMS 环境搭建 傻瓜式安装 漏洞一&#xff1a;通过文件管理器上传WebShel 步骤⼀:访问目标靶场其思路为 dedecms 后台可以直接上传任意文件&#xff0c;可以通过⽂件管理器上传php文件获取webshell 登陆网站后台 步骤二&#xff1a;登陆到后台点击 【核心】 --》 【文件式…

1、Jmeter、jdk下载与安装

1、访问官网&#xff0c;点击下载Jmeter http://jmeter.apache.org/ 2、在等待期间&#xff0c;下载对应的Java https://www.oracle.com/cn/java/technologies/downloads/#jdk23-windows 3、全部下载好&#xff0c;先安装JDK ![在这里插入图片描述](https://i-blog.csdnimg…