使用C# FileHelpers加载可变长度行CSV至DataTable及银行报表解析求助
用FileHelpers处理带摘要头部的银行报表并生成DataTable
我来帮你搞定这个FileHelpers配置问题!针对这种包含5行摘要头部+结构化交易数据的银行CSV报表,我们可以分步骤提取并整合所有信息到DataTable里,下面是具体的实现思路和代码示例:
1. 先明确文件结构
你的文件大致是这样的:
第1-5行:摘要信息(每行格式可能不固定,比如有的是多列文本,有的是键值对)
第6行:交易数据的表头(Date,Transaction Type,Description,Amount,Running Balance)
第7行及以后:实际交易数据(每行5列)
我们需要分别处理摘要部分和交易数据部分,再把它们整合起来。
2. 方案一:手动拆分+FileHelpers解析交易数据
这种方式简单直接,适合摘要格式不固定的情况:
步骤1:读取并拆分文件内容
先把文件所有行读出来,拆分出摘要行和交易数据行:
// 读取文件所有行,注意根据实际文件编码调整(比如UTF-8、GB2312) var allLines = File.ReadAllLines("your_bank_statement.csv", Encoding.UTF8); // 提取前5行作为摘要 var summaryLines = allLines.Take(5).ToList(); // 剩下的行(从第6行开始)是交易数据(包含表头) var transactionLines = allLines.Skip(5).ToArray();
步骤2:用FileHelpers解析交易数据
首先定义交易数据的实体类,和表头字段对应:
using FileHelpers; [DelimitedRecord(",")] [IgnoreFirst(1)] // 跳过第6行的表头 [FieldNames("Date", "Transaction Type", "Description", "Amount", "Running Balance")] public class BankTransaction { // 根据文件中的日期格式调整Converter参数,比如"MM/dd/yyyy" [FieldConverter(ConverterKind.Date, "yyyy-MM-dd")] public DateTime TransactionDate { get; set; } // 自动映射表头的"Transaction Type" public string TransactionType { get; set; } public string Description { get; set; } // 根据文件中的金额格式调整分隔符,比如","作为千分位,"."作为小数点 [FieldConverter(ConverterKind.Decimal, ".")] public decimal Amount { get; set; } [FieldConverter(ConverterKind.Decimal, ".")] public decimal RunningBalance { get; set; } }
然后解析交易数据并转成DataTable:
var transactionEngine = new FileHelperEngine<BankTransaction>(); // 解析交易数据(把数组转成字符串再读取) var transactions = transactionEngine.ReadString(string.Join(Environment.NewLine, transactionLines)); // 转成DataTable var transactionDataTable = transactionEngine.ToDataTable(transactions);
步骤3:整合摘要信息到DataTable
根据你的需求,有两种整合方式:
方式A:把摘要作为元数据附加到每个交易行
如果需要每条交易记录都关联文件的摘要信息,可以给DataTable加一个摘要列:// 添加摘要列 transactionDataTable.Columns.Add("FileSummary", typeof(string)); // 把5行摘要拼接成一个字符串 var summaryText = string.Join(Environment.NewLine, summaryLines); // 给每个交易行赋值 foreach (DataRow row in transactionDataTable.Rows) { row["FileSummary"] = summaryText; }方式B:单独存储摘要行
如果要把摘要和交易数据分开存储,可以创建两个DataTable,或者在同一个表中先插入摘要行再插入交易行(注意列要兼容):var combinedTable = new DataTable(); // 先添加摘要相关列 combinedTable.Columns.Add("Content", typeof(string)); // 插入5行摘要 foreach (var line in summaryLines) { combinedTable.Rows.Add(line); } // 再添加交易数据的列(可以直接复制transactionDataTable的结构) foreach (DataColumn col in transactionDataTable.Columns) { combinedTable.Columns.Add(col.ColumnName, col.DataType); } // 插入交易数据行 foreach (DataRow row in transactionDataTable.Rows) { combinedTable.ImportRow(row); }
3. 方案二:用MultiRecordEngine自动识别行类型
如果你的摘要行有固定格式(比如每行都是3列,交易行都是5列),可以用FileHelpers的MultiRecordEngine自动区分两种行类型:
步骤1:定义摘要行和交易行的实体类
// 摘要行类(假设每行3列) [DelimitedRecord(",")] public class SummaryRecord { public string Header1 { get; set; } public string Header2 { get; set; } public string Header3 { get; set; } } // 交易行类和之前一样 [DelimitedRecord(",")] [FieldNames("Date", "Transaction Type", "Description", "Amount", "Running Balance")] public class BankTransaction { [FieldConverter(ConverterKind.Date, "yyyy-MM-dd")] public DateTime TransactionDate { get; set; } public string TransactionType { get; set; } public string Description { get; set; } [FieldConverter(ConverterKind.Decimal, ".")] public decimal Amount { get; set; } [FieldConverter(ConverterKind.Decimal, ".")] public decimal RunningBalance { get; set; } }
步骤2:配置MultiRecordEngine并解析
// 创建多记录引擎,指定行类型的识别规则(通过列数区分) var engine = new MultiRecordEngine( typeof(SummaryRecord), typeof(BankTransaction) ); // 设置规则:列数为3的是摘要行,列数为5的是交易行 engine.RecordSelector = record => { var columns = record.Split(','); return columns.Length switch { 3 => typeof(SummaryRecord), 5 => typeof(BankTransaction), _ => null // 跳过不符合的行(比如表头行) }; }; // 读取文件 var records = engine.ReadFile("your_bank_statement.csv"); // 分离摘要和交易记录 var summaries = records.OfType<SummaryRecord>().ToList(); var transactions = records.OfType<BankTransaction>().ToList(); // 转成DataTable并整合(方法和方案一类似) var summaryDt = engine.ToDataTable(summaries); var transactionDt = engine.ToDataTable(transactions);
关键注意事项
- 编码问题:如果文件是GBK或其他编码,一定要在读取时指定对应的
Encoding,避免乱码 - 格式匹配:日期、金额的格式必须和文件中的一致,否则会解析失败,可通过
FieldConverter调整 - 表头映射:用
FieldNames特性可以精准匹配表头字段,即使表头有空格或大小写差异
内容的提问来源于stack exchange,提问作者dobre dani
相关产品推荐
相关产品推荐

