377 lines
17 KiB
C#
377 lines
17 KiB
C#
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 = 400,Bold = 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
|
||
}
|
||
}
|