Files
T-DAS/Common/ExcelHelper.cs
2023-01-13 15:30:20 +08:00

377 lines
17 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.Hosting;
namespace Epost.Common
{
public class ExcelHelper
{
#region
/// <summary>
///
/// </summary>
/// <param name="resultMsg">导出结果</param>
/// <param name="excelFilePath">保存excel文件路径</param>
/// <param name="table"></param>
/// <param name="filename"></param>
/// <param name="filetitle"></param>
/// <param name="WebRootPath"></param>
/// <returns></returns>
public bool ExcelDataExport(DataTable table, string filename, string filetitle, string WebRootPath, out string resultMsg, out string excelFilePath)
{
var result = true;
excelFilePath = "";
resultMsg = "successfully";
//Excel导出名称
try
{
//首先创建Excel文件对象
var workbook = new HSSFWorkbook();
//创建工作表也就是Excel中的sheet给工作表赋一个名称(Excel底部名称)
var sheet = workbook.CreateSheet(filename);
//sheet.DefaultColumnWidth = 20;//默认列宽
sheet.ForceFormulaRecalculation = true;//TODO:是否开始Excel导出后公式仍然有效非必须
//设置顶部大标题样式
var cellStyleFont = CreateStyle(workbook, HorizontalAlignment.Center, VerticalAlignment.Center, 20, true, 700, "楷体", true, false, false, true, FillPattern.SolidForeground, HSSFColor.White.Index, HSSFColor.Black.Index,
FontUnderlineType.None, FontSuperScript.None, false);
//第一行表单
IRow row = CreateRow(sheet, 0, 28);
var cell = row.CreateCell(0);
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, table.Columns.Count - 1));
cell.SetCellValue(filetitle);//合并单元格后只需对第一个位置赋值即可TODO:顶部标题)
cell.CellStyle = cellStyleFont;
//处理表格列头
row = sheet.CreateRow(1);
for (int i = 0; i < table.Columns.Count; i++)
{
row.CreateCell(i).SetCellValue(table.Columns[i].ColumnName);
row.Height = 350;
sheet.AutoSizeColumn(i);
}
//处理数据内容
for (int i = 0; i < table.Rows.Count; i++)
{
row = sheet.CreateRow(2 + i);
row.Height = 250;
for (int j = 0; j < table.Columns.Count; j++)
{
row.CreateCell(j).SetCellValue(table.Rows[i][j].ToString());
sheet.SetColumnWidth(j, 256 * 15);
}
}
string folder = DateTime.Now.ToString("yyyyMMdd");
//保存文件到静态资源文件夹中wwwroot,使用绝对路径
var uploadPath = WebRootPath + "/File/" + folder + "/";
//excel保存文件名
string excelFileName = filename + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
//创建目录文件夹
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);
}
//Excel的路径及名称
string excelPath = uploadPath + excelFileName;
//使用FileStream文件流来写入数据传入参数为文件所在路径对文件的操作方式对文件内数据的操作
var fileStream = new FileStream(excelPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//向Excel文件对象写入文件流生成Excel文件
workbook.Write(fileStream);
//关闭文件流
fileStream.Close();
//释放流所占用的资源
fileStream.Dispose();
//excel文件保存的相对路径提供前端下载
var relativePositioning = "/File/" + folder + "/" + excelFileName;
excelFilePath = relativePositioning;
}
catch (Exception e)
{
result = false;
resultMsg = e.Message;
}
return result;
}
/// <summary>
/// 行内单元格常用样式设置
/// </summary>
/// <param name="workbook">Excel文件对象</param>
/// <param name="hAlignment">水平布局方式</param>
/// <param name="vAlignment">垂直布局方式</param>
/// <param name="fontHeightInPoints">字体大小</param>
/// <param name="isAddBorder">是否需要边框</param>
/// <param name="boldWeight">字体加粗 (None = 0,Normal = 400Bold = 700</param>
/// <param name="fontName">字体(仿宋,楷体,宋体,微软雅黑...与Excel主题字体相对应</param>
/// <param name="isAddBorderColor">是否增加边框颜色</param>
/// <param name="isItalic">是否将文字变为斜体</param>
/// <param name="isLineFeed">是否自动换行</param>
/// <param name="isAddCellBackground">是否增加单元格背景颜色</param>
/// <param name="fillPattern">填充图案样式(FineDots 细点SolidForeground立体前景isAddFillPattern=true时存在)</param>
/// <param name="cellBackgroundColor">单元格背景颜色当isAddCellBackground=true时存在</param>
/// <param name="fontColor">字体颜色</param>
/// <param name="underlineStyle">下划线样式(无下划线[None],单下划线[Single],双下划线[Double],会计用单下划线[SingleAccounting],会计用双下划线[DoubleAccounting]</param>
/// <param name="typeOffset">字体上标下标(普通默认值[None],上标[Sub],下标[Super]),即字体在单元格内的上下偏移量</param>
/// <param name="isStrikeout">是否显示删除线</param>
/// <returns></returns>
public HSSFCellStyle CreateStyle(HSSFWorkbook workbook, HorizontalAlignment hAlignment, VerticalAlignment vAlignment, short fontHeightInPoints, bool isAddBorder, short boldWeight, string fontName = "宋体", bool isAddBorderColor = true, bool isItalic = false, bool isLineFeed = false, bool isAddCellBackground = false, FillPattern fillPattern = FillPattern.NoFill, short cellBackgroundColor = HSSFColor.Yellow.Index, short fontColor = HSSFColor.Black.Index, FontUnderlineType underlineStyle =
FontUnderlineType.None, FontSuperScript typeOffset = FontSuperScript.None, bool isStrikeout = false)
{
HSSFCellStyle cellStyle = (HSSFCellStyle)workbook.CreateCellStyle(); //创建列头单元格实例样式
cellStyle.Alignment = hAlignment; //水平居中
cellStyle.VerticalAlignment = vAlignment; //垂直居中
cellStyle.WrapText = isLineFeed;//自动换行
//背景颜色,边框颜色,字体颜色都是使用 HSSFColor属性中的对应调色板索引关于 HSSFColor 颜色索引对照表详情参考https://www.cnblogs.com/Brainpan/p/5804167.html
//TODO引用了NPOI后可通过ICellStyle 接口的 FillForegroundColor 属性实现 Excel 单元格的背景色设置FillPattern 为单元格背景色的填充样式
//TODO:十分注意要设置单元格背景色必须是FillForegroundColor和FillPattern两个属性同时设置否则是不会显示背景颜色
if (isAddCellBackground)
{
cellStyle.FillForegroundColor = cellBackgroundColor;//单元格背景颜色
cellStyle.FillPattern = fillPattern;//填充图案样式(FineDots 细点SolidForeground立体前景)
}
//是否增加边框
if (isAddBorder)
{
//常用的边框样式 None(没有),Thin(细边框,瘦的),Medium(中等),Dashed(虚线),Dotted(星罗棋布的),Thick(厚的),Double(双倍),Hair(头发)[上右下左顺序设置]
cellStyle.BorderBottom = BorderStyle.Thin;
cellStyle.BorderRight = BorderStyle.Thin;
cellStyle.BorderTop = BorderStyle.Thin;
cellStyle.BorderLeft = BorderStyle.Thin;
}
//是否设置边框颜色
if (isAddBorderColor)
{
//边框颜色[上右下左顺序设置]
cellStyle.TopBorderColor = HSSFColor.DarkGreen.Index;//DarkGreen(黑绿色)
cellStyle.RightBorderColor = HSSFColor.DarkGreen.Index;
cellStyle.BottomBorderColor = HSSFColor.DarkGreen.Index;
cellStyle.LeftBorderColor = HSSFColor.DarkGreen.Index;
}
/**
* 设置相关字体样式
*/
var cellStyleFont = (HSSFFont)workbook.CreateFont(); //创建字体
//假如字体大小只需要是粗体的话直接使用下面该属性即可
//cellStyleFont.IsBold = true;
cellStyleFont.Boldweight = boldWeight; //字体加粗
cellStyleFont.FontHeightInPoints = fontHeightInPoints; //字体大小
cellStyleFont.FontName = fontName;//字体(仿宋,楷体,宋体
cellStyleFont.Color = fontColor;//设置字体颜色
cellStyleFont.IsItalic = isItalic;//是否将文字变为斜体
cellStyleFont.Underline = underlineStyle;//字体下划线
cellStyleFont.TypeOffset = typeOffset;//字体上标下标
cellStyleFont.IsStrikeout = isStrikeout;//是否有删除线
cellStyle.SetFont(cellStyleFont); //将字体绑定到样式
return cellStyle;
}
/// <summary>
/// TODO:先创建行,然后在创建对应的列
/// 创建Excel中指定的行
/// </summary>
/// <param name="sheet">Excel工作表对象</param>
/// <param name="rowNum">创建第几行(从0开始)</param>
/// <param name="rowHeight">行高</param>
public HSSFRow CreateRow(ISheet sheet, int rowNum, float rowHeight)
{
HSSFRow row = (HSSFRow)sheet.CreateRow(rowNum); //创建行
row.HeightInPoints = rowHeight; //设置列头行高
return row;
}
/// <summary>
/// 创建行内指定的单元格
/// </summary>
/// <param name="row">需要创建单元格的行</param>
/// <param name="cellStyle">单元格样式</param>
/// <param name="cellNum">创建第几个单元格(从0开始)</param>
/// <param name="cellValue">给单元格赋值</param>
/// <returns></returns>
public HSSFCell CreateCells(HSSFRow row, HSSFCellStyle cellStyle, int cellNum, string cellValue)
{
HSSFCell cell = (HSSFCell)row.CreateCell(cellNum); //创建单元格
cell.CellStyle = cellStyle; //将样式绑定到单元格
if (!string.IsNullOrWhiteSpace(cellValue))
{
//单元格赋值
cell.SetCellValue(cellValue);
}
return cell;
}
#endregion
#region
/// <summary>
/// 读取excel表格中的数据,将Excel文件流转化为dataTable数据源
/// 默认第一行为标题
/// </summary>
/// <param name="stream">excel文档文件流</param>
/// <param name="fileType">文档格式</param>
/// <param name="isSuccess">是否转化成功</param>
/// <param name="resultMsg">转换结果消息</param>
/// <returns></returns>
public DataTable ExcelToDataTable(Stream stream, string fileType)
{
//isSuccess = false;
//resultMsg = "Excel文件流成功转化为DataTable数据源";
var excelToDataTable = new DataTable();
try
{
IWorkbook workbook;
//XSSFWorkbook 适用XLSX格式HSSFWorkbook 适用XLS格式
#region excel版本
switch (fileType)
{
//2007以下版本excel
case ".xlsx":
workbook = new XSSFWorkbook(stream);
break;
case ".xls":
workbook = new HSSFWorkbook(stream);
break;
default:
throw new Exception("Excel文档格式有误");
}
#endregion
var sheet = workbook.GetSheetAt(0);
var rows = sheet.GetRowEnumerator();
var headerRow = sheet.GetRow(0);
int cellCount = headerRow.LastCellNum;//最后一行列数(即为总列数)
//获取第一行标题列数据源,转换为dataTable数据源的表格标题名称
for (var j = 0; j < cellCount; j++)
{
var cell = headerRow.GetCell(j);
excelToDataTable.Columns.Add(cell.ToString());
}
//获取Excel表格中除标题以为的所有数据源转化为dataTable中的表格数据源
for (var i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
{
var dataRow = excelToDataTable.NewRow();
var row = sheet.GetRow(i);
if (row == null) continue; //没有数据的行默认是null 
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)//单元格内容非空验证
{
//获取指定的单元格信息
var cell = row.GetCell(j);
#region NPOI获取Excel单元格数据不同类型数据
switch (cell.CellType)
{
//首先在NPOI中数字和日期都属于Numeric类型
//通过NPOI中自带的DateUtil.IsCellDateFormatted判断是否为时间日期类型
//case CellType.Numeric when DateUtil.IsCellDateFormatted(cell):
// dataRow[j] = cell.DateCellValue;
// break;
case CellType.Numeric:
//其他数字类型
dataRow[j] = cell.NumericCellValue;
break;
//空数据类型
case CellType.Blank:
dataRow[j] = "";
break;
//公式类型
case CellType.Formula:
{
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(workbook);
dataRow[j] = eva.Evaluate(cell).StringValue;
break;
}
//布尔类型
case CellType.Boolean:
dataRow[j] = row.GetCell(j).BooleanCellValue;
break;
//错误
case CellType.Error:
// dataRow[j] = HSSFErrorConstants.GetText(row.GetCell(j).ErrorCellValue);
break;
//其他类型都按字符串类型来处理未知类型CellType.Unknown字符串类型CellType.String
default:
dataRow[j] = cell.StringCellValue;
break;
}
#endregion
}
}
excelToDataTable.Rows.Add(dataRow);
}
//isSuccess = true;
}
catch (Exception e)
{
LogHelper.WriteLogInfo("上传" + e, LogHelper.Log_Type.ERROR);
}
return excelToDataTable;
}
#endregion
}
}