首页 > 解决方案 > 在同一文件中循环标题和详细信息记录

问题描述

我在下面重新编辑了这个问题我有一个示例文件,它作为文件中的多个采购订单,由第二列标识。

订单号、采购号、日期、货品代码、数量、描述 1245456,98978,12/01/2019, 1545-878, 1,"Test"

1245456,98978,12/01/2019,1545-342,2,“测试”

1245456,98978,12/01/2019,1545-878,2,"测试"

1245456,98979,12/02/2019,1545-878,3,"测试 3"

1245456,98979,12/02/2019,1545-342,4,"测试 4"

1245456,98979,12/02/2019,1545-878,5,“测试 4”

我希望最终结果是能够将上述内容放入一个类中,如下所示

在我使用 filelpers 解析 csv 文件的时候,如果我有 sep 头文件和行文件,这会很好,但它们会像你看到的那样组合在一起

var engine = new FileHelperEngine<CSVLines>();
var lines = engine.ReadFile(csvFileName);

所以类应该如下所示

  [DelimitedRecord(",")]
  public class SalesOrderHeader
  {
     private Guid? _guid;


    public  Guid RowID
    {
        get
        {
            return _guid ?? (_guid = Guid.NewGuid()).GetValueOrDefault();
        }
    }
    public string DocReference { get; set; }
    public string CardCode { get; set; }
    public string DocDate { get; set; }
    public string ItemCode { get; set; }

    public string Description { get; set; }
    public string Qty { get; set; }

    public string Price { get; set; }


    [FieldHidden]
    public List<SalesOrderHeader> OrdersLines { get; set; }
  }

我想我要做的是两个循环,正如您从我的 createsales 订单例程中看到的那样,我首先创建标题,然后添加行。

 public void CreateSalesOrder(List<SalesOrderHeader> _salesOrders)
    {
        foreach (var record in _salesOrders.GroupBy(g => g.DocReference))
        {

            // Init the Order object
            oOrder = (SAPbobsCOM.Documents)company.GetBusinessObject(SAPbobsCOM.BoObjectTypes.oOrders);
            SAPbobsCOM.SBObob oBob;
            // set properties of the Order object
           // oOrder.NumAtCard = record.Where(w=>w.RowID = record.Where()
            oOrder.CardCode = record.First().CardCode;
            oOrder.DocDueDate = DateTime.Now;

            oOrder.DocDate =Convert.ToDateTime(record.First().DocDate);
            foreach (var recordItems in _salesOrders.SelectMany(e=>e.OrdersLines).Where(w=>w.DocReference ==record.First().DocReference))
            {
                oOrder.Lines.ItemCode = recordItems.ItemCode;
                oOrder.Lines.ItemDescription = recordItems.Description;
                oOrder.Lines.Quantity = Convert.ToDouble(recordItems.Qty);
                oOrder.Lines.Price = Convert.ToDouble(recordItems.Price);

                oOrder.Lines.Add();
                log.Debug(string.Format("Order Line added to sap Item Code={0}, Description={1},Qty={2}", recordItems.ItemCode, recordItems.Description, recordItems.Qty));

            }
            int lRetCode = oOrder.Add(); // Try to add the orer to the database
        }

        if(lRetCode == 0)
        {
            string body = "Purchase Order Imported into SAP";               
 
        }
        if (lRetCode != 0)
        {
            int temp_int = lErrCode;
            string temp_string = sErrMsg;
            company.GetLastError(out temp_int, out temp_string);
            if (lErrCode != -4006) // Incase adding an order failed
            {
                log.Error(string.Format("Error adding an order into sap ErrorCode {0},{1}", temp_int, temp_string));
            }

        }
    }

您将看到我遇到的问题是如何首先将 csv 拆分为两个列表,其次如何正确访问强类型对象中的标题行,正如您看到的那样,我首先使用的是无法正常工作的。

标签: c#filehelpers

解决方案


对于 FileHelpers,除了描述底层文件结构之外,避免使用映射类是很重要的。在这里,我怀疑您正试图直接映射到一个过于复杂的类。

FileHelpers 类只是使用 C# 语法定义平面文件规范的一种方式。

因此,FileHelpers 类是一种不常见的 C# 类,您不应尝试使用公认的 OOP 原则。FileHelpers 不应具有 FileHelpers 库使用的属性或方法之外的属性或方法。

仅将 FileHelpers 类视为 CSV 格式的“规范”。这应该是它的唯一作用。(无论如何,从维护的角度来看,这是一个很好的做法——如果底层 CSV 结构发生变化,那么调整代码会更容易)。

然后,如果您需要更“正常”对象中的记录,则将结果映射到更好的东西,即封装Order对象所有功能的类,而不是CSVOrder.

因此,处理此类文件的一种方法是解析文件两次。在第一遍中,您提取标题记录。像这样的东西:

var engine1 = new FileHelperEngine<CSVHeaders>();
var headers = engine1.ReadFile(csvFileName);

在第二遍中,您提取细节;

var engine2 = new FileHelperEngine<CSVDetails>();
var details = engine2.ReadFile(csvFileName);

然后将这些信息组合到一个新的专用类中,可能使用一些类似于此的 LINQ

var niceOrders = 
    headers
        .DistinctBy(h => h.OrderNumber)
            .SelectMany(d => details.Where(d => d.OrderNumber = y))
                 .Select(x => 
                      new NiceOrder() { 
                          OrderNumber = x.OrderNumber,  
                          Customer = x.Customer,
                          ItemCode = x.ItemCode                                     
                          // etc.
                      });

推荐阅读