WPF编程excel表格操作

news2025/1/4 5:58:49

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读笔记】SCI算法与代码 | 低照度图像增强 | 2022.4.21

目录 一 SCI 1 SCI网络结构 核心代码&#xff08;model.py&#xff09; 2 SCI损失函数 核心代码&#xff08;loss.py&#xff09; 3 实验 二 SCI效果 1 下载代码 2 运行 一 SCI &#x1f49c;论文题目&#xff1a;Toward Fast, Flexible, and Robust Low-Light Image …

wps透视数据表

1、操作 首先选中你要的行字段表格 -> 插入 -> 透视数据表 -> 拖动行值&#xff08;部门&#xff09;到下方&#xff0c;拖动值&#xff08;包裹数量、运费&#xff09;到下方 2、删除 选中整个透视数据表 -> delete 如图&#xff1a;

STM32配合可编程加密芯片SMEC88ST的防抄板加密方案设计

SMEC88ST SDK开发包下载 目前市场上很多嵌入式产品方案都是可以破解复制的&#xff0c;主要是因为方案主芯片不具备防破解的功能&#xff0c;这就导致开发者投入大量精力、财力开发的新产品一上市就被别人复制&#xff0c;到市场上的只能以价格竞争&#xff0c;最后工厂复制的产…

【电路理论四】正弦电流电路

正弦电流 正弦量是随时间按正弦规律变动的电路变量。 随时间按正弦规律变动的电流称为正弦电流。 正弦电流的瞬时值表达式&#xff1a; 称为正弦电流的三要素。 分别为振幅/幅值&#xff0c;角频率&#xff0c;初相。 幅值为正弦电流的最大值&#xff0c;恒为正。 为正弦电…

多模态论文笔记——Coca(副)

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍多模态模型Coca&#xff0c;在DALLE 3中使用其作为captioner基准模型的原因和优势。 文章目录 ALBEF论文模型结构组成训练目标 CoCa​论文模型结构CoCa…

【Python系列】处理空请求体Body

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【毕业设计选题】目标检测方向毕业设计选题推荐 2025

目录 前言 毕设选题 开题指导建议 更多精选选题 选题帮助 最后 前言 大家好,这里是海浪学长毕设专题! 大四是整个大学期间最忙碌的时光&#xff0c;一边要忙着准备考研、考公、考教资或者实习为毕业后面临的升学就业做准备,一边要为毕业设计耗费大量精力。学长给大家整…

从2024看2025前端发展趋势

前言 又至年关&#xff0c;回顾整个2024年&#xff0c;前端行业仍旧百废待兴&#xff0c;IT业界同样也未见有所起色&#xff0c;AI风潮也从狂热兴奋逐步走向了冷静稳定阶段&#xff0c;造成此形势感观并非单一行业或者某一企业之特例&#xff0c;实为政经等综合影响之结果。因…

QT----------常用界面组件的使用

一、QComboBox 类 主要功能&#xff1a;提供一个下拉列表&#xff0c;用户可以从中选择一个或多个选项。 #include <QApplication> #include <QComboBox> #include <QVBoxLayout> #include <QWidget> #include <QMessageBox>int main(int argc…

AIDD -人工智能药物设计- DrugChat:多模态大语言模型实现药物机制与属性的全方位预测

DrugChat&#xff1a;多模态大语言模型实现药物机制与属性的全方位预测 今天为大家介绍的是来自加州大学圣地亚哥分校谢澎涛团队的一篇论文。准确预测潜在药物分子的作用机制和性质对于推进药物发现至关重要。然而&#xff0c;传统方法通常需要为每个特定的预测任务开发专门的…

智能化人才招聘系统是怎样的?

随着企业规模的扩大和业务范围的拓展&#xff0c;人才招聘成为了企业发展的关键环节。然而&#xff0c;市面上的人才招聘系统琳琅满目&#xff0c;质量参差不齐&#xff0c;许多企业发现&#xff0c;并非所有系统都能满足他们的需求&#xff0c;特别是智能化的需求。今天&#…

分布式专题(9)之Mysql高可用方案

一、分库分表概念 数据库&#xff0c;应该是一个应用当中最为核心的价值所在&#xff0c;也是开发过程中必须熟练掌握的工具。之前我们就学习过很多对MySQL的调优。但是随着现在互联网应用越来越大&#xff0c;数据库会频繁的成为整个应用的性能瓶颈。我们经常使用的MySQL数据库…

LockSupport的源码实现原理(一)

目录 底层源码分析 线程状态变化 许可证机制 中断处理 底层源码分析 public class LockSupport {// Unsafe实例private static final Unsafe U Unsafe.getUnsafe();// Thread对象中parkBlocker字段的偏移量private static final long PARKBLOCKER U.objectFieldOffset(Thre…

CannotRetrieveUpdates alert in disconnected OCP 4 cluster解决

环境&#xff1a; Red Hat OpenShift Container Platform (RHOCP) 4 问题&#xff1a; Cluster Version Operator 不断发送警报&#xff0c;表示在受限网络/断开连接的 OCP 4 集群中无法接收更新。 在隔离的 OpenShift 4 集群中看到 CannotRetrieveUpdates 警报&#xff1a; …

智能家居体验大变革 博联 AI 方案让智能不再繁琐

1. 全球AI技术发展背景及智能家居市场趋势 人工智能&#xff08;AI&#xff09;技术的飞速发展正在推动全球各行业的数字化转型。国际电信联盟与德勤联合发布《人工智能向善影响》报告指出&#xff0c;全球94%的商界领袖认为&#xff0c;人工智能技术对于其企业在未来5年内的发…

logback日志框架源码分析

目录 (一)入口:slf4j选择日志框架 (二)日志框架初始化 (1)logback的3种配置方式 a、BasicConfigurator默认配置 b、SPI方式配置的Configurator实现类 c、通过配置文件初始化 (2)xml配置文件初始化 (三)Logger的创建 (四)打印日志 本文源码基于:logback版…

VScode 只能运行c,运行不了c++的解决问题

原文链接&#xff1a;Vscode只能运行c&#xff0c;运行不了c的解决方法 VScode 只能运行c&#xff0c;运行不了c&#xff0c;怎么回事呢&#xff0c;解决问题&#xff1a; 在tasks.json中加上“"-lstdc"”&#xff0c; 这样之后 要重启VScode&#xff0c;点击链接…

HTML——45.单元格合并

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表格</title></head><body><!--合并单元格&#xff1a;1.在代码中找到要合并的单元格2.在要合并的所有单元格中&#xff0c;保留要合并的第一个单元格…

记录第一次跑YOLOV8做目标检测

今天是24年的最后一天&#xff0c;终于要向新世界开始破门了&#xff0c;开始深度学习&#xff0c;YOLO来敲门~ 最近做了一些皮肤检测的功能&#xff0c;在传统的处理中经历了反复挣扎&#xff0c;终于要上YOLO了。听过、看过&#xff0c;不如上手体会过~ 1、YOLO是什么&#x…

如何配置Java应用程序的远程调试

配置Java应用程序的远程调试涉及几个步骤&#xff0c;包括在启动Java应用程序时设置特定的JVM参数&#xff0c;以及在IDE&#xff08;如Eclipse、IntelliJ IDEA等&#xff09;中配置远程调试连接。以下是详细的步骤&#xff1a; 启动Java应用程序时启用远程调试 为了能够远程…