分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限

时间:2022-05-30 15:52:40

大家都知道使用NPOI导出Excel格式数据 很简单,网上一搜,到处都有示例代码。

因为工作的关系,经常会有处理各种数据库数据的场景,其中处理Excel 数据导出,以备客户人员确认数据,场景很常见。

一个系统开发出来,系统要运行起来,很多数据要初始化,这个时候也是需要客户提供各种业务的基础数据。客户提供的数据中,其中除了word、pdf,最常见的就是Excel。

废话不多说,直接上图上代码:

如图,

左侧三列,作为 一个系统 所有菜单的树状结构。

其他列 以用户的信息(如用户名、登录名) 作为表头,需要注意的是,在整理数据进行导出时,需保证列名不能重复。

分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限

 public static void DataTree(string path, DataTable table, int treeIndex = )
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
IWorkbook workBook = new HSSFWorkbook();
//现在使用的仍然是生成Excel2003的Excel文件,由于03对行数(65535)和列数(255)有限制,所以当数据超出范围后难免出错
//ArgumentException: Invalid column index (256). Allowable column range for BIFF8 is (0..255) or ('A'..'IV') ...
if (Path.GetExtension(path).Equals(".xlsx", System.StringComparison.OrdinalIgnoreCase))
{
workBook = new XSSFWorkbook();
} string sheetName = string.IsNullOrWhiteSpace(table.TableName) ? "Sheet1" : table.TableName;
ISheet sheet = workBook.CreateSheet(sheetName);
IRow row = null;
int colNum = table.Columns.Count;
if (treeIndex < table.Columns.Count || treeIndex > )
{
colNum = treeIndex;
} ICellStyle cellCenterStyle = GetCenter(workBook); int beginNum = ;//排除列头,从1开始 //处理表格列头
row = sheet.CreateRow(beginNum - );
for (int i = ; i < table.Columns.Count; i++)
{
string strVal = table.Columns[i].ColumnName;
ICell cell = row.CreateCell(i);
cell.SetCellValue(strVal);
cell.CellStyle = cellCenterStyle;
row.Height = ;
sheet.AutoSizeColumn(i);
} //处理数据内容
for (int i = ; i < table.Rows.Count; i++)
{
row = sheet.CreateRow(beginNum + i);
row.Height = ;
for (int j = ; j < table.Columns.Count; j++)
{
string strVal = table.Rows[i][j].ToString();
ICell currCell = row.CreateCell(j);
currCell.SetCellValue(strVal);
currCell.CellStyle = cellCenterStyle;
sheet.SetColumnWidth(j, * );
}
} for (int i = ; i < colNum; i++)
{
List<int> lstColWidth = new List<int>();
string currVal = string.Empty;
string nextVal = string.Empty;
for (int j = beginNum; j <= sheet.LastRowNum; j++)
{
currVal = sheet.GetRow(j).Cells[i].StringCellValue; int mk = j;
if (!string.IsNullOrWhiteSpace(currVal))//排除 空值,空值不做合并处理
{
for (int k = j + ; k <= sheet.LastRowNum; k++)
{
nextVal = sheet.GetRow(k).Cells[i].StringCellValue; if (currVal != nextVal)
{
//因为k 累加所以导致当前值与下个值 不相同,所以记录 当前行数要 减去1
mk = k - ;
break;
}
else if (k == sheet.LastRowNum) //边界值,处理最后一行,则提前Break 并记录当前 k
{
mk = k;
break;
}
}
} if (mk != j)//排除 空值外,下个值的行数不等于当前行数,则需要合并
{
sheet.AddMergedRegion(new CellRangeAddress(j, mk, i, i));
} //if (i == 0) //如果是第一列,则 垂直水平居中
{
sheet.GetRow(j).Cells[i].CellStyle = cellCenterStyle;
}
//跳到执行下一个不同数据的行
j = mk; //记录列长度
lstColWidth.Add(DataLength(currVal));
} //设置列宽
int maxWidth = lstColWidth.Max() * ;
sheet.SetColumnWidth(i, maxWidth);
}
//固定列、行 滚动时不变
sheet.CreateFreezePane(, , , ); //写入数据流
workBook.Write(fs);
}
} private static ICellStyle GetCenter(IWorkbook workBook, short fontSize = )
{
ICellStyle cellStyle = workBook.CreateCellStyle();
IFont font = workBook.CreateFont();
font.FontName = "微软雅黑";
font.FontHeightInPoints = fontSize;
cellStyle.SetFont(font);
cellStyle.VerticalAlignment = VerticalAlignment.Center;
cellStyle.Alignment = HorizontalAlignment.Center;
return cellStyle;
} /// <summary>
/// 获取字符串长度(中文按2个字节长度)
/// </summary>
/// <param name="stringWithEnglishAndChinese"></param>
/// <returns></returns>
private static int DataLength(string stringWithEnglishAndChinese)
{
int lng = ;
for (int i = ; i < stringWithEnglishAndChinese.Length; i++)
{
byte[] b = System.Text.Encoding.Default.GetBytes(stringWithEnglishAndChinese.Substring(i, ));
if (b.Length > )
lng += ;
else
lng += ;
}
return lng;
}