一、环境概述
开发工具:Visual Studio 2022
.Net环境:.Net Core 6.0
相关依赖:NPOI
二、基本概述
需求要实现导出的数据里如果连续行满足某个条件就用颜色标记,但是标记的区间要用不同颜色区分开,用了双指针,但是是记录了起始位置和偏移量,封装比较屎,这里主要记录一下思想。
三、代码实现
1、核心代码
/// <summary>
/// 用于获取线性表中需要标记的坐标(起始位置+偏移量)
/// </summary>
/// <param name="WorkBook"></param>
/// <param name="ExportData"></param>
/// <param name="comparer"></param>
public static Dictionary<int,int> GetMarkPosition(DataTable ExportData, Func<DataRow, DataRow, bool> comparer) {
Dictionary<int, int> PositionDic = new Dictionary<int, int>();
if (ExportData == null || ExportData.Rows.Count == 0)
{
return PositionDic;
}
int RowCount = ExportData.Rows.Count;
int StartRow = 0;//开始指针
int CurrentLength = 0;//偏移量
for (int i = 1; i < RowCount; i++)
{
if (comparer(ExportData.Rows[i], ExportData.Rows[i - 1]))
{
CurrentLength++;
}
else
{
if (CurrentLength > 0)
{
PositionDic.Add(StartRow, CurrentLength);
}
StartRow = i;
CurrentLength = 0;
}
}
if (CurrentLength > 0)
{
PositionDic.Add(StartRow, CurrentLength);
}
return PositionDic;
}
/// <summary>
/// 用于标记连续相等的行
/// </summary>
/// <param name="WorkBook">用于获取样式的</param>
/// <param name="Sheet">标记操作作用的Excel表</param>
/// <param name="ExportData">数据</param>
/// <param name="comparer">自定义的比较器</param>
/// <param name="ColorAction">自定义的标记操作</param>
public static void MarkSameRow(IWorkbook WorkBook,ISheet Sheet,DataTable ExportData, Func<DataRow, DataRow, bool> comparer,Action<IWorkbook,ISheet, KeyValuePair<int, int>,bool> ColorAction) {
Dictionary<int,int> PositionDic = GetMarkPosition(ExportData, comparer);
if (PositionDic==null||PositionDic.Count()==0) {
return;
}
bool change = false;
foreach (var item in PositionDic) {
change = !change;
ColorAction(WorkBook,Sheet,item, change);
}
}
2、实际使用
//自定义的行比较的逻辑,作为委托参数
private bool CompareRowData(DataRow CurRow, DataRow PreRow)
{
bool IsEquals = false;
if (CurRow == null || PreRow == null)
{
return IsEquals;
}
string CurValue1 = Convert.ToString(CurRow[0]) ?? string.Empty;
string CurValue2 = Convert.ToString(CurRow[1]) ?? string.Empty;
string PreValue1 = Convert.ToString(PreRow[0]) ?? string.Empty;
string PreValue2 = Convert.ToString(PreRow[1]) ?? string.Empty;
if (CurValue1.Equals(PreValue1) && CurValue2.Equals(PreValue2))
{
IsEquals = true;
return IsEquals;
}
return IsEquals;
}
//自定义的填充颜色的逻辑,作为委托参数
private void FillColor(IWorkbook WorkBook, ISheet Sheet, KeyValuePair<int, int> Position, bool IsChange)
{
if (WorkBook == null)
{
return;
}
XSSFColor Color1 = ExcelUtils.GetXSSFColorWithRGB(68, 179, 225);
XSSFColor Color2 = ExcelUtils.GetXSSFColorWithRGB(166, 166, 166);
XSSFCellStyle ColorStyle1 = ExcelUtils.GetBGColorStyle(WorkBook, Color1);
XSSFCellStyle ColorStyle2 = ExcelUtils.GetBGColorStyle(WorkBook, Color2);
if (Sheet == null)
{
return;
}
for (int i = Position.Key + 2; i < Position.Key + Position.Value + 3; i++)
{
for(int j = 0; j < 9; j++) {
ICell Cell = ExcelUtils.GetCell(Sheet, i, j);
Cell.CellStyle = IsChange ? ColorStyle1 : ColorStyle2;
}
}
}
//实际使用
ExcelUtils.MarkSameRow(WorkBook, Sheet, ExportData, CompareRowData, FillColor);
3、注意
-- 如果你用的XLS结尾的Excel你需要用这个来设置背景颜色
HSSFPalette palette = ((HSSFWorkbook)WorkBook).GetCustomPalette();
IColor color= palette.FindSimilarColor(190, 231, 233);
HSSFCellStyle cellStyle = (HSSFCellStyle)WorkBook.CreateCellStyle();
cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
cellStyle.VerticalAlignment = VerticalAlignment.Center;
cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
cellStyle.FillForegroundColor = color.Indexed;
cellStyle.FillPattern = FillPattern.SolidForeground;
-- 如果你用的是XLSX结尾的Excel你需要使用这个来设置背景颜色
XSSFColor XSSFColor = new XSSFColor();
byte[] ColorRGB = { R, G, B };-- R,G,B是三个byte范围的数值,这个可以自定义的。
XSSFColor.SetRgb(ColorRGB);
XSSFCellStyle ColorStyle = (XSSFCellStyle)WorkBook.CreateCellStyle();
ColorStyle.FillForegroundColorColor = XSSFColor ;
ColorStyle.FillPattern = FillPattern.SolidForeground;
ColorStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
ColorStyle.VerticalAlignment = VerticalAlignment.Center;
ColorStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
ColorStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
ColorStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
ColorStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
二者如果混用会报错
-- 还有一个坑就是你读取模板的时候如果有一行是空白的,你想删除这一行
比如我有读取一个XLS的模板想删除第一行(不知道制作模板的傻逼设置了什么,填不进去数据,所以直接删了),
你要使用RemoveRow只能删除内容,你要用Sheet.ShiftRows(4, RowCount + 5, -1);就是从第四行到最后一行所有行往上移动一行,然后这一行会放到最后去,贼鸡儿傻逼。
三、效果展示