Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

新增NPOI对工作簿对象工作表对象的相关操作 #40

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions EasyTool.NPOI/EasyTool.NPOI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;.net6.0</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>11</LangVersion>
<Authors>Hang</Authors>
<Description>
依赖于NPOI 2.6.2
支持通过文件地址或者流的方式读取Excel文件获取工作簿对象IWorkbook,
通过IWorkbook工作簿对象可以转化成Dataset对象
通过ISheet工作表对象可以转化成DataTable对象和List对象
以下是一些示例:
获取数据集对象:
var dateSet = NPOIUtil.OpenWorkbook(path).ConvertToDataSet();
var dateSet = NPOIUtil.ConvertToDataSet(path);
获取工作表对象:
var sheet = NPOIUtil.OpenWorkbook(path).GetSheetAt(0);
获取单表数据对象:
var dataTable = NPOIUtil.OpenWorkbook(path).GetSheetAt(0).ConvertToDataTable();
List《T》 dataList = NPOIUtil.OpenWorkbook(path).GetSheetAt(0).ConvertToList《List《T》》();
从流读取工作簿对象(从流读取需要指定文件类型,缺省值为XLSX):
var workbook = NPOIUtil.OpenWorkbook(stream,ExcelWorkbookType.XLS);
</Description>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NPOI" Version="2.6.2" />
</ItemGroup>

</Project>
17 changes: 17 additions & 0 deletions EasyTool.NPOI/ExcelWorkbookType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace EasyTool.NPOI;

public enum ExcelWorkbookType
{
/// <summary>
/// xls类型适用于Office2003及以下版本
/// </summary>
XLS,
/// <summary>
/// xlsx类型适用于Office2007及以上版本
/// </summary>
XLSX
}
286 changes: 286 additions & 0 deletions EasyTool.NPOI/NPOIUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
using NPOI.HSSF.UserModel;
using NPOI.POIFS.NIO;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.Util.ArrayExtensions;
using NPOI.XSSF.UserModel;

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace EasyTool.NPOI;

public static class NPOIUtil
{
/// <summary>
/// 输入文件绝对路径,获取工作簿对象
/// HHSWorkbook:适用于.xls文件; XSSFWorkbook:适用于.xlsx文件
/// </summary>
/// <param name="path">绝对路径</param>
/// <returns>IWorkbook</returns>
public static IWorkbook OpenWorkbook(string path)
{
if (path == null || !File.Exists(path))
throw new Exception($"路径{path}不存在");
using var stream = File.OpenRead(path);
return Path.GetExtension(path) == ".xls"
? new HSSFWorkbook(stream)
: new XSSFWorkbook(stream);
}
/// <summary>
/// 从流读取工作簿,自动判断类型或者显示指定类型
/// </summary>
/// <param name="stream"></param>
/// <param name="fileExtension">
/// null or 缺省:适用于不明确的文件类型
/// xls:适用于.xls文件
/// xlsx:适用于.xlsx文件
/// </param>
/// <returns></returns>
/// <exception cref="Exception"></exception>

public static IWorkbook OpenWorkbookFromStream(Stream stream, ExcelWorkbookType excelType =ExcelWorkbookType.XLSX)
{
if (stream == null)
throw new Exception("流不能为空");
return excelType switch
{
ExcelWorkbookType.XLS => new HSSFWorkbook(stream),
ExcelWorkbookType.XLSX => new XSSFWorkbook(stream),
_ => throw new Exception("不支持的格式类型,请选择")
};
}
/// <summary>
/// 把IWorkbook类型的对象转换成DataSet
/// </summary>
/// <param name="workbooks"></param>
/// <returns></returns>
public static DataSet? ConvertToDataSet(this IWorkbook workbooks)
{
if (workbooks.NumberOfSheets == 0)
return new DataSet("EmptyDataSet");
var dataSet = new DataSet(workbooks.GetSheetName(0));
for (var i = 0; i < workbooks.NumberOfSheets; i++)
{
var sheet = workbooks.GetSheetAt(i);
var table = new DataTable(sheet.SheetName);
var headerRow = sheet.GetRow(0);
if (headerRow == null)
{
dataSet.Tables.Add(table);
continue;
}
var cellCount = headerRow.LastCellNum;
for (var j = headerRow.FirstCellNum; j < cellCount; j++)
{
var column = new DataColumn(headerRow.GetCell(j).StringCellValue);
table.Columns.Add(column);
}
var rowCount = sheet.LastRowNum;
for (var k = sheet.FirstRowNum +1; k <= rowCount; k++)
{
var row = sheet.GetRow(k);
var dataRow = table.NewRow();
for (var m = 0; m < cellCount; m++)
{
dataRow[m] = row.GetCell(m).ToString();
}
table.Rows.Add(dataRow);
}
dataSet.Tables.Add(table);
}
return dataSet;
}
/// <summary>
/// 输入文件绝对路径,获取解析后的DataSet对象
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static DataSet? ConvertToDataSet(string path)
{
var wookbook = OpenWorkbook(path) ?? throw new Exception("路径");
return ConvertToDataSet(wookbook);
}
/// <summary>
/// 适用单表,把IWorkbook类型的对象转换成List
/// </summary>
/// <typeparam name="T">目标泛型</typeparam>
/// <param name="wookbook"></param>
/// <example> IWorkbook workbook;workbook.GetSheetAt(0).ToList<T>();</example>
/// <returns></returns>
public static List<T> ConvertToList<T>(this ISheet sheet) where T : new()
{
List<T> list = new();
var headerRow = sheet.GetRow(0);
if (headerRow == null)
return list;
var cellCount = headerRow.LastCellNum;
var rowCount = sheet.LastRowNum;
for (var k = sheet.FirstRowNum + 1; k < rowCount; k++)
{
var row = sheet.GetRow(k);
T t = new();
for (var m = row.FirstCellNum; m < cellCount; m++)
{
var cell = row.GetCell(m);
var value = cell?.ToString();
if (value == null)
continue;
var property = t.GetType().GetProperty(headerRow.GetCell(m).StringCellValue);
if (property == null)
continue;
property.SetValue(t, value, null);
}
list.Add(t);
}
return list;
}
/// <summary>
/// 根据工作表对象返回DataTable
/// </summary>
/// <param name="sheet">工作表对象</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException">不应传入一个空的工作表对象</exception>
public static DataTable ConvertToDatatable(this ISheet sheet)
{
if (sheet == null)
throw new ArgumentNullException(nameof(sheet));
DataTable dataTable = new(sheet.SheetName);
var columns= new List<DataColumn>();
var headerRow = sheet.GetRow(0);
if (headerRow == null)
return dataTable;
headerRow.Cells.ForEach(cell =>
{
var column = new DataColumn(cell.StringCellValue);
columns.Add(column);
});
dataTable.Columns.AddRange(columns.ToArray());
var rowCount = sheet.LastRowNum;
for (var k = sheet.FirstRowNum + 1; k < rowCount; k++)
{
var row = sheet.GetRow(k);
var dataRow = dataTable.NewRow();
for (var m = 0; m < columns.Count; m++)
{
dataRow[m] = row.GetCell(m).ToString();
}
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
/// <summary>
/// 导出到Excel
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dataSource">IEnumerable<T></param>
/// <param name="path">文件夹路径</param>
/// <param name="workbookType">工作簿类型</param>
/// <param name="filename">文件名称</param>

public static bool ExportToExcel<T>(IEnumerable<T> dataSource,string path, out string message, ExcelWorkbookType workbookType =ExcelWorkbookType.XLSX,string? filename=null)
{
bool result = true;
message = "导出成功";
try
{
IWorkbook workbook = workbookType.Equals(ExcelWorkbookType.XLSX) ? new XSSFWorkbook() : new HSSFWorkbook();
T t = dataSource.FirstOrDefault();
filename ??= typeof(T).Name;
ISheet sheet = workbook.CreateSheet(filename);
IRow headerRow = sheet.CreateRow(0);
var props = typeof(T).GetProperties().Where(x => x.PropertyType.IsPublic);
int count = props.Count(); //T类型公开属性的数量
for (int i = 0; i < count; i++)
{
headerRow.CreateCell(i).SetCellValue(props.ElementAt(i).Name);
}
var length = dataSource.Count();//数据源的行数
for (int i = 0; i < length; i++)
{
IRow row = sheet.CreateRow(i + 1);
for (int j = 0; j < count; j++)
{
row.CreateCell(j).SetCellValue(props.ElementAt(j).GetValue(dataSource.ElementAt(i)).ToString());
}
}
string filePath = $"{path}{filename}";
string extension = workbookType.Equals(ExcelWorkbookType.XLSX) ? ".xlsx" : ".xls";
int num = 1;
while (File.Exists(filePath + extension))
{
filePath = $"{path}{filename}({num})";
num++;
}
using var fs = new FileStream(filePath + extension, FileMode.Create, FileAccess.Write);
workbook.Write(fs);
}
catch (Exception e)
{
result = false;
message = $"导出失败:{e.Message}";
}
return result;

}
/// <summary>
/// DataTable导出到Excel
/// </summary>
/// <param name="dataTable">数据源</param>
/// <param name="path">保存路径</param>
/// <param name="workbookType">工作簿类型</param>
/// <param name="filename">文件名</param>
public static bool ExportToExcel(this DataTable dataTable, string path, out string message, ExcelWorkbookType workbookType = ExcelWorkbookType.XLSX, string? filename = null)
{
bool result = true;
message = string.Empty;
try
{
IWorkbook workbook = workbookType.Equals(ExcelWorkbookType.XLSX) ? new XSSFWorkbook() : new HSSFWorkbook();
filename = string.IsNullOrEmpty(filename)
? string.IsNullOrEmpty(dataTable.TableName)
? DateTime.Now.ToString("yyyyMMddHHmmss")
: dataTable.TableName
: filename;
ISheet sheet = workbook.CreateSheet(filename);
IRow 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++)
{
IRow row = sheet.CreateRow(i + 1);
for (int j = 0; j < dataTable.Columns.Count; j++)
{
row.CreateCell(j).SetCellValue(dataTable.Rows[i][j].ToString());
}
}
string filePath = $"{path}{filename}";
string extension = workbookType.Equals(ExcelWorkbookType.XLSX) ? ".xlsx" : ".xls";
int num = 1;
while (File.Exists(filePath + extension))
{
filePath = $"{path}{filename}({num})";
num++;
}
using var fs = new FileStream(filePath + extension, FileMode.Create, FileAccess.Write);

workbook.Write(fs);
}
catch (Exception e)
{
result = false;
message = e.Message;
}
return result;

}
}
23 changes: 23 additions & 0 deletions EasyTool.NPOITests/EasyTool.NPOITests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\EasyTool.NPOI\EasyTool.NPOI.csproj" />
</ItemGroup>

</Project>
Loading
Loading