You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:52:47