WPF编程excel表格操作

WPF编程excel表格操作

摘要

Excel操作几种方式

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

NPOI安装

封装代码

csharp 复制代码
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("示例文本内容");
        }
    }
}

测试代码

csharp 复制代码
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("请先设置表格文件保存!");
}
相关推荐
one99611 小时前
WPF-绑定
microsoft·c#·.net·wpf
badogyang13 小时前
python脚本,读取当前目录文件名,写入excel表格,并给对应文件名分配mac
python·excel
qq_4585638115 小时前
通过excel导入数据
java·excel
one99618 小时前
WPF 数据绑定中的通知机制及其性能考虑
c#·.net·wpf
孤蓬&听雨19 小时前
Java SpringBoot使用EasyExcel导入导出Excel文件
java·spring boot·excel·导出·导入
Tulipes1 天前
Excel导出功能:vue2+SpringBoot
java·vue·excel·springboot·easyexcel
△曉風殘月〆1 天前
WPF自定义任务栏缩略图
wpf·dwm·任务栏
奈川直子1 天前
EasyExcel自定义动态下拉框(附加业务对象转换功能)
java·mysql·spring·excel
智慧老师1 天前
职场常用Excel基础03-自定义排序
excel
疋瓞2 天前
Excel重新踩坑5:二级下拉列表制作;★数据透视表;
excel