Files
WC-CZGKJ/SCADA/Core/OExcel.cs
2026-05-23 13:54:15 +08:00

627 lines
30 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NPOITest
{
/// <summary>
/// Execl工具辅助类
/// </summary>
public class ExeclHelper
{
/// <summary>
/// 读取Execl数据到DataTable中
/// </summary>
/// <param name="filePath">指定Execl文件路径</param>
/// <param name="isColumnName">设置第一行是否是列名</param>
/// <returns>返回一个DataTable数据集</returns>
public static DataTable ExcelToDataTable(string filePath, string sheetName, bool isColumnName)
{
DataTable dataTable = null;
FileStream fs = null;
DataColumn column = null;
DataRow dataRow = null;
IWorkbook workbook = null;
ISheet sheet = null;
IRow row = null;
ICell cell = null;
int startRow = 0;
try
{
using (fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// 2007版本
if (filePath.IndexOf(".xlsx") > 0)
workbook = new XSSFWorkbook(fs);
// 2003版本
else if (filePath.IndexOf(".xls") > 0)
workbook = new HSSFWorkbook(fs);
if (workbook != null)
{
sheet = workbook.GetSheet(sheetName);//读取第一个sheet当然也可以循环读取每个sheet
dataTable = new DataTable();
if (sheet != null)
{
int rowCount = sheet.LastRowNum;//总行数
if (rowCount > 0)
{
IRow firstRow = sheet.GetRow(0);//第一行
int cellCount = firstRow.LastCellNum;//列数
//构建datatable的列
if (isColumnName)
{
startRow = 1;//如果第一行是列名,则从第二行开始读取
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
cell = firstRow.GetCell(i);
if (cell != null)
{
if (cell.StringCellValue != null)
{
column = new DataColumn(cell.StringCellValue);
dataTable.Columns.Add(column);
}
}
}
}
else
{
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
column = new DataColumn("column" + (i + 1));
dataTable.Columns.Add(column);
}
}
//填充行
for (int i = startRow; i <= rowCount; ++i)
{
row = sheet.GetRow(i);
if (row == null) continue;
dataRow = dataTable.NewRow();
for (int j = row.FirstCellNum; j < cellCount; ++j)
{
cell = row.GetCell(j);
if (cell == null)
{
dataRow[j] = "";
}
else
{
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
switch (cell.CellType)
{
case CellType.Blank:
dataRow[j] = "";
break;
case CellType.Numeric:
short format = cell.CellStyle.DataFormat;
//对时间格式2015.12.5、2015/12/5、2015-12-5等的处理
if (format == 14 || format == 31 || format == 57 || format == 58)
dataRow[j] = cell.DateCellValue;
else
dataRow[j] = cell.NumericCellValue;
break;
case CellType.String:
dataRow[j] = cell.StringCellValue;
break;
}
}
}
dataTable.Rows.Add(dataRow);
}
}
}
}
}
return dataTable;
}
catch (Exception err)
{
if (fs != null)
{
fs.Close();
}
return null;
}
}
public static DataTable ExcelToDataTable(string filePath,int sheetIndex, bool isColumnName)
{
DataTable dataTable = null;
FileStream fs = null;
DataColumn column = null;
DataRow dataRow = null;
IWorkbook workbook = null;
ISheet sheet = null;
IRow row = null;
ICell cell = null;
int startRow = 0;
try
{
using (fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// 2007版本
if (filePath.IndexOf(".xlsx") > 0)
workbook = new XSSFWorkbook(fs);
// 2003版本
else if (filePath.IndexOf(".xls") > 0)
workbook = new HSSFWorkbook(fs);
if (workbook != null)
{
sheet = workbook.GetSheetAt(sheetIndex);//读取第一个sheet当然也可以循环读取每个sheet
dataTable = new DataTable();
if (sheet != null)
{
int rowCount = sheet.LastRowNum;//总行数
if (rowCount > 0)
{
IRow firstRow = sheet.GetRow(0);//第一行
int cellCount = firstRow.LastCellNum;//列数
//构建datatable的列
if (isColumnName)
{
startRow = 1;//如果第一行是列名,则从第二行开始读取
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
cell = firstRow.GetCell(i);
if (cell != null)
{
if (cell.StringCellValue != null)
{
column = new DataColumn(cell.StringCellValue);
dataTable.Columns.Add(column);
}
}
}
}
else
{
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
column = new DataColumn("column" + (i + 1));
dataTable.Columns.Add(column);
}
}
//填充行
for (int i = startRow; i <= rowCount; ++i)
{
row = sheet.GetRow(i);
if (row == null) continue;
dataRow = dataTable.NewRow();
for (int j = row.FirstCellNum; j < cellCount; ++j)
{
cell = row.GetCell(j);
if (cell == null)
{
dataRow[j] = "";
}
else
{
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
switch (cell.CellType)
{
case CellType.Blank:
dataRow[j] = "";
break;
case CellType.Numeric:
short format = cell.CellStyle.DataFormat;
//对时间格式2015.12.5、2015/12/5、2015-12-5等的处理
if (format == 14 || format == 31 || format == 57 || format == 58 || format == 22)
dataRow[j] = cell.DateCellValue;
else
dataRow[j] = cell.NumericCellValue;
break;
case CellType.String:
dataRow[j] = cell.StringCellValue;
break;
}
}
}
dataTable.Rows.Add(dataRow);
}
}
}
}
}
return dataTable;
}
catch (Exception)
{
if (fs != null)
{
fs.Close();
}
return null;
}
}
public static void DataTableToExcel(DataTable dataTable, string templatePath, string outputPath, int startRow, int startCol)
{
// 加载模板文件
using (FileStream fs = new FileStream(templatePath, FileMode.Open, FileAccess.Read))
{
IWorkbook workbook = new XSSFWorkbook(fs);
ISheet sheet = workbook.GetSheetAt(0); // 获取第一个工作表
// 创建单元格样式
ICellStyle cellStyle = workbook.CreateCellStyle();
IFont font = workbook.CreateFont();
font.FontHeightInPoints = 12;
cellStyle.SetFont(font);
cellStyle.BorderTop = BorderStyle.Thin;
cellStyle.BorderBottom = BorderStyle.Thin;
cellStyle.BorderLeft = BorderStyle.Thin;
cellStyle.BorderRight = BorderStyle.Thin;
cellStyle.Alignment = HorizontalAlignment.Center;
// 遍历DataTable的每一行
for (int i = 0; i < dataTable.Rows.Count; i++)
{
IRow row = sheet.CreateRow(startRow + i); // 创建新行
// 遍历DataTable的每一列
for (int j = 0; j < dataTable.Columns.Count; j++)
{
ICell cell = row.CreateCell(startCol + j); // 创建新单元格
cell.SetCellValue(dataTable.Rows[i][j].ToString());
cell.CellStyle = cellStyle; // 应用单元格样式
}
}
// 保存输出文件
using (FileStream outputStream = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
{
workbook.Write(outputStream);
}
}
}
/// <summary>
/// 将DataTable导出到Excel文档自动根据扩展名选择 .xlsx / .xls 格式)
/// </summary>
/// <param name="dt">传入一个DataTable数据集</param>
/// <param name="sheetName">工作表名称</param>
/// <param name="Outpath">导出文件完整路径(支持 .xlsx 和 .xls</param>
/// <returns>True表示导出成功False表示导出失败</returns>
public static bool DataTableToExcel(DataTable dt, string sheetName, string Outpath)
{
if (dt == null || dt.Rows.Count == 0 || string.IsNullOrWhiteSpace(Outpath))
return false;
IWorkbook workbook = null;
try
{
// ── 1. 根据文件扩展名选择正确的 Workbook 类型 ──
string ext = Path.GetExtension(Outpath).ToLowerInvariant();
if (ext == ".xlsx")
workbook = new XSSFWorkbook(); // OOXML 格式
else
workbook = new HSSFWorkbook(); // BIFF8 格式
ISheet sheet = workbook.CreateSheet(sheetName);
int rowCount = dt.Rows.Count;
int columnCount = dt.Columns.Count;
// ── 2. 创建表头样式(加粗 + 背景色 + 边框) ──
ICellStyle headerStyle = workbook.CreateCellStyle();
IFont headerFont = workbook.CreateFont();
headerFont.IsBold = true;
headerFont.FontHeightInPoints = 11;
headerFont.FontName = "微软雅黑";
headerStyle.SetFont(headerFont);
headerStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
headerStyle.FillPattern = FillPattern.SolidForeground;
headerStyle.Alignment = HorizontalAlignment.Center;
headerStyle.VerticalAlignment = VerticalAlignment.Center;
headerStyle.BorderTop = BorderStyle.Thin;
headerStyle.BorderBottom = BorderStyle.Thin;
headerStyle.BorderLeft = BorderStyle.Thin;
headerStyle.BorderRight = BorderStyle.Thin;
// ── 3. 创建数据行样式(边框) ──
ICellStyle dataStyle = workbook.CreateCellStyle();
IFont dataFont = workbook.CreateFont();
dataFont.FontHeightInPoints = 10;
dataFont.FontName = "微软雅黑";
dataStyle.SetFont(dataFont);
dataStyle.VerticalAlignment = VerticalAlignment.Center;
dataStyle.BorderTop = BorderStyle.Thin;
dataStyle.BorderBottom = BorderStyle.Thin;
dataStyle.BorderLeft = BorderStyle.Thin;
dataStyle.BorderRight = BorderStyle.Thin;
// ── 4. 写入列头 ──
IRow headerRow = sheet.CreateRow(0);
headerRow.HeightInPoints = 22;
for (int c = 0; c < columnCount; c++)
{
ICell cell = headerRow.CreateCell(c);
cell.SetCellValue(dt.Columns[c].ColumnName);
cell.CellStyle = headerStyle;
}
// ── 5. 写入数据行 ──
for (int i = 0; i < rowCount; i++)
{
IRow row = sheet.CreateRow(i + 1);
for (int j = 0; j < columnCount; j++)
{
ICell cell = row.CreateCell(j);
object val = dt.Rows[i][j];
// 根据数据类型设置单元格值,保留数值精度
if (val == null || val == DBNull.Value)
{
cell.SetCellValue("");
}
else if (val is DateTime dtVal)
{
cell.SetCellValue(dtVal.ToString("yyyy-MM-dd HH:mm:ss"));
}
else if (val is double || val is float || val is decimal)
{
cell.SetCellValue(Convert.ToDouble(val));
}
else if (val is int || val is long || val is short)
{
cell.SetCellValue(Convert.ToDouble(val));
}
else
{
cell.SetCellValue(val.ToString());
}
cell.CellStyle = dataStyle;
}
}
// ── 6. 自动调整列宽(限制最大宽度避免过宽) ──
for (int c = 0; c < columnCount; c++)
{
sheet.AutoSizeColumn(c);
int colWidth = sheet.GetColumnWidth(c);
// 最大列宽限制为 50 个字符宽度 (50 * 256)
if (colWidth > 50 * 256)
sheet.SetColumnWidth(c, 50 * 256);
// 最小列宽
else if (colWidth < 10 * 256)
sheet.SetColumnWidth(c, 10 * 256);
}
// ── 7. 写入文件(使用 FileMode.Create 确保覆盖写入) ──
using (FileStream fs = new FileStream(Outpath, FileMode.Create, FileAccess.Write))
{
workbook.Write(fs);
}
return true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"[ExeclHelper] 导出Excel失败: {ex.Message}");
return false;
}
finally
{
if (workbook != null)
{
workbook.Close();
workbook = null;
}
}
}
/// <summary>
/// 读取Execl数据到DataTable(DataSet)中
/// </summary>
/// <param name="filePath">指定Execl文件路径</param>
/// <param name="isFirstLineColumnName">设置第一行是否是列名</param>
/// <returns>返回一个DataTable数据集</returns>
public static DataSet ExcelToDataSet(string filePath, bool isFirstLineColumnName)
{
DataSet dataSet = new DataSet();
int startRow = 0;
try
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
IWorkbook workbook = null;
// 如果是2007+的Excel版本
if (filePath.IndexOf(".xlsx") > 0)
{
workbook = new XSSFWorkbook(fs);
}
// 如果是2003-的Excel版本
else if (filePath.IndexOf(".xls") > 0)
{
workbook = new HSSFWorkbook(fs);
}
if (workbook != null)
{
//循环读取Excel的每个sheet每个sheet页都转换为一个DataTable并放在DataSet中
for (int p = 0; p < workbook.NumberOfSheets; p++)
{
ISheet sheet = workbook.GetSheetAt(p);
DataTable dataTable = new DataTable();
dataTable.TableName = sheet.SheetName;
if (sheet != null)
{
int rowCount = sheet.LastRowNum;//获取总行数
if (rowCount > 0)
{
IRow firstRow = sheet.GetRow(0);//获取第一行
int cellCount = firstRow.LastCellNum;//获取总列数
//构建datatable的列
if (isFirstLineColumnName)
{
startRow = 1;//如果第一行是列名,则从第二行开始读取
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
ICell cell = firstRow.GetCell(i);
if (cell != null)
{
if (cell.StringCellValue != null)
{
DataColumn column = new DataColumn(cell.StringCellValue);
dataTable.Columns.Add(column);
}
}
}
}
else
{
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
DataColumn column = new DataColumn("column" + (i + 1));
dataTable.Columns.Add(column);
}
}
//填充行
for (int i = startRow; i <= rowCount; ++i)
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
DataRow dataRow = dataTable.NewRow();
for (int j = row.FirstCellNum; j < cellCount; ++j)
{
ICell cell = row.GetCell(j);
if (cell == null)
{
dataRow[j] = "";
}
else
{
//CellType(Unknown = -1,Numeric = 0,String = 1,Formula = 2,Blank = 3,Boolean = 4,Error = 5,)
switch (cell.CellType)
{
case CellType.Blank:
dataRow[j] = "";
break;
case CellType.Numeric:
short format = cell.CellStyle.DataFormat;
//对时间格式2015.12.5、2015/12/5、2015-12-5等的处理
if (format == 14 || format == 31 || format == 57 || format == 58)
dataRow[j] = cell.DateCellValue;
else
dataRow[j] = cell.NumericCellValue;
break;
case CellType.String:
dataRow[j] = cell.StringCellValue;
break;
}
}
}
dataTable.Rows.Add(dataRow);
}
}
}
dataSet.Tables.Add(dataTable);
}
}
}
return dataSet;
}
catch (Exception err)
{
return null;
}
}
/// <summary>
/// 将DataTable(DataSet)导出到Execl文档
/// </summary>
/// <param name="dataSet">传入一个DataSet</param>
/// <param name="Outpath">导出路径(可以不加扩展名,不加默认为.xls</param>
/// <returns>返回一个Bool类型的值表示是否导出成功</returns>
/// True表示导出成功Flase表示导出失败
public static bool DataSetToExcel(DataSet dataSet, string Outpath)
{
bool result = false;
try
{
if (dataSet == null || dataSet.Tables == null || dataSet.Tables.Count == 0 || string.IsNullOrEmpty(Outpath))
throw new Exception("输入的DataSet或路径异常");
int sheetIndex = 0;
//根据输出路径的扩展名判断workbook的实例类型
IWorkbook workbook = null;
string pathExtensionName = Outpath.Trim().Substring(Outpath.Length - 5);
if (pathExtensionName.Contains(".xlsx"))
{
workbook = new XSSFWorkbook();
}
else if (pathExtensionName.Contains(".xls"))
{
workbook = new HSSFWorkbook();
}
else
{
Outpath = Outpath.Trim() + ".xls";
workbook = new HSSFWorkbook();
}
//将DataSet导出为Excel
foreach (DataTable dt in dataSet.Tables)
{
sheetIndex++;
if (dt != null && dt.Rows.Count > 0)
{
ISheet sheet = workbook.CreateSheet(string.IsNullOrEmpty(dt.TableName) ? ("sheet" + sheetIndex) : dt.TableName);//创建一个名称为Sheet0的表
int rowCount = dt.Rows.Count;//行数
int columnCount = dt.Columns.Count;//列数
//设置列头
IRow row = sheet.CreateRow(0);//excel第一行设为列头
for (int c = 0; c < columnCount; c++)
{
ICell cell = row.CreateCell(c);
cell.SetCellValue(dt.Columns[c].ColumnName);
}
//设置每行每列的单元格,
for (int i = 0; i < rowCount; i++)
{
row = sheet.CreateRow(i + 1);
for (int j = 0; j < columnCount; j++)
{
ICell cell = row.CreateCell(j);//excel第二行开始写入数据
cell.SetCellValue(dt.Rows[i][j].ToString());
}
}
}
}
//向outPath输出数据
using (FileStream fs = File.OpenWrite(Outpath))
{
workbook.Write(fs);//向打开的这个xls文件中写入数据
result = true;
}
return result;
}
catch (Exception ex)
{
return false;
}
}
}
}