Files
ExcelTool/ExcelTool/ExcelHelper.cs
T
Oliver 965998b56f feat(refactor): introduce configuration-based Excel table processing
- Replace command-line options with single tables file configuration
- Add TablesConfig class for parsing table configuration from Excel
- Add TableEntry class for storing table configuration data
- Change GetCellValue method visibility from static to internal static
- Simplify Program.cs command line interface with single --tables option
- Add error handling for missing files and directories
- Update README with new usage instructions and examples
- Remove deprecated command-line option descriptions
2026-04-13 12:37:16 +08:00

182 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
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.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using ExcelTool.Parser;
namespace ExcelTool
{
public static class ExcelHelper
{
public static List<ParsedSheet> ParseAllSheets(string fileName, out List<ParsedEnum> enumSheets)
{
List<ParsedSheet> result = [];
enumSheets = [];
try
{
using FileStream fs = File.OpenRead(fileName);
XSSFWorkbook wk = new(fs);
int sheetCount = wk.NumberOfSheets;
for (int sheetNum = 0; sheetNum < sheetCount; sheetNum++)
{
ISheet sheet = wk.GetSheetAt(sheetNum);
string sheetName = sheet.SheetName;
// # 开头的 sheet 跳过
if (string.IsNullOrEmpty(sheetName) || sheetName.StartsWith('#'))
continue;
if (sheetName.Equals("__enums__", StringComparison.OrdinalIgnoreCase))
{
enumSheets = ParseEnumSheet(sheet);
continue;
}
ParsedSheet parsed = ParseSheet(sheet, sheetName);
if (parsed != null)
result.Add(parsed);
}
}
catch (Exception ex)
{
ex.ToString().WriteErrorLine();
}
return result;
}
static ParsedSheet ParseSheet(ISheet sheet, string sheetName)
{
try
{
IRow nameRow = sheet.GetRow(0);
IRow typeRow = sheet.GetRow(1);
IRow descRow = sheet.GetRow(2);
List<TableExcelHeader> headers = [];
for (int j = 0; j < nameRow.LastCellNum; j++)
{
string fieldName = nameRow.GetCell(j)?.ToString() ?? "";
string fieldType = typeRow.GetCell(j)?.ToString() ?? "";
string fieldDesc = descRow.GetCell(j)?.ToString() ?? "";
if (string.IsNullOrEmpty(fieldName))
{
$"列 {j} 字段名为空".WriteErrorLine();
continue;
}
headers.Add(new TableExcelHeader
{
FieldName = fieldName,
FieldType = fieldType,
FieldDesc = fieldDesc,
});
}
// 数据从第 6 行开始(0-indexed
List<TableExcelRow> tableRows = [];
for (int i = 5; i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
TableExcelRow tableExcelRow = new();
for (int j = 0; j < headers.Count; j++)
tableExcelRow.Add(GetCellValue(row.GetCell(j)));
tableRows.Add(tableExcelRow);
}
return new ParsedSheet
{
SheetName = sheetName,
Headers = headers,
Data = new TableExcelData(headers, tableRows),
};
}
catch (Exception ex)
{
ex.ToString().WriteErrorLine();
return null;
}
}
static List<ParsedEnum> ParseEnumSheet(ISheet sheet)
{
List<ParsedEnum> result = [];
// 列索引约定:A=0 Id, B=1 EnumName, C=2 items.Name, D=3 items.Value, E=4 items.Desc
// 数据从第 6 行开始(0-indexed = 5
ParsedEnum currentEnum = null;
for (int i = 5; i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
if (row == null) continue;
string idStr = GetCellValue(row.GetCell(0));
string enumName = GetCellValue(row.GetCell(1));
string memberKey = GetCellValue(row.GetCell(2));
string memberVal = GetCellValue(row.GetCell(3));
string memberDesc = GetCellValue(row.GetCell(4));
// 成员名为空则跳过此行
if (string.IsNullOrEmpty(memberKey)) continue;
// Id / EnumName 非空时,开启新枚举
if (!string.IsNullOrEmpty(enumName))
{
currentEnum = new ParsedEnum
{
Id = string.IsNullOrEmpty(idStr) ? 0 : Convert.ToUInt32(double.Parse(idStr)),
EnumName = enumName,
};
result.Add(currentEnum);
}
// 如果没有任何枚举上下文就跳过
currentEnum?.Members.Add(new ParsedEnumMember
{
Key = memberKey,
Value = string.IsNullOrEmpty(memberVal) ? null : Convert.ToInt32(double.Parse(memberVal)),
Desc = memberDesc,
});
}
return result;
}
internal static string GetCellValue(ICell cell)
{
if (cell == null)
return "";
switch (cell.CellType)
{
case CellType.String:
return cell.StringCellValue;
case CellType.Numeric:
return DateUtil.IsCellDateFormatted(cell) ? cell.DateCellValue.ToString() : cell.NumericCellValue.ToString();
case CellType.Boolean:
return cell.BooleanCellValue ? "1" : "0";
case CellType.Formula:
return cell.ToString();
default:
return "";
}
}
}
public class ParsedSheet
{
public string SheetName { get; init; }
public List<TableExcelHeader> Headers { get; init; }
public TableExcelData Data { get; init; }
}
}