在同一文件中循环 header 和详细记录
Looping header and details records in same file
我在下面重新编辑了这个问题我有一个示例文件,它是文件中的多个采购订单,由第二列标识。
Order Number, Purchase Number,DATE,Item Code ,Qty, Description
1245456,98978,12/01/2019, 1545-878, 1,"Test"
1245456,98978,12/01/2019,1545-342,2,"Test"
1245456,98978,12/01/2019,1545-878,2,"Test"
1245456,98979,12/02/2019,1545-878,3,"Test 3"
1245456,98979,12/02/2019,1545-342,4,"Test 4"
1245456,98979,12/02/2019,1545-878,5,"Test 4"
我想要的最终结果是能够将以上内容合二为一class,如下所示
最开始我正在使用 filelpers 来解析 csv 文件,如果我有 sep header 文件和行文件,这会很好用,但如您所见,它们是组合在一起的
var engine = new FileHelperEngine<CSVLines>();
var lines = engine.ReadFile(csvFileName);
所以 Class 应该如下所示
[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 订单例程中看到的那样,我首先创建 header,然后在其中添加行。
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 分成两个列表,其次我如何在强类型 object 中正确访问 header 行,如你所见我先用,但不能正常使用。
对于 FileHelpers,重要的是避免将映射 class 用于描述底层文件结构以外的任何内容。在这里,我怀疑您正试图直接映射到太复杂的 class。
FileHelpers class 只是一种使用 C# 语法定义平面文件规范的方法。
因此,FileHelpers classes 是一种不常见的 C# class 类型,您不应尝试使用公认的 OOP 原则。 FileHelpers 不应具有超出 FileHelpers 库使用的属性或方法。
仅将 FileHelpers class 视为 CSV 格式的 'specification'。这应该是它唯一的作用。 (无论如何,从维护的角度来看,这是一个很好的做法 - 如果底层 CSV 结构发生变化,则更容易调整您的代码)。
然后如果你需要更多'normal'object中的记录,然后将结果映射到更好的东西,即封装了[的所有功能的class =13=] object 而不是 CSVOrder
.
因此,处理此类文件的一种方法是对文件进行两次解析。在第一遍中,您提取 header 记录。像这样:
var engine1 = new FileHelperEngine<CSVHeaders>();
var headers = engine1.ReadFile(csvFileName);
在第二遍中提取细节;
var engine2 = new FileHelperEngine<CSVDetails>();
var details = engine2.ReadFile(csvFileName);
然后您将这些信息合并到一个新的专用 class 中,也许与此类似的一些 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.
});
我在下面重新编辑了这个问题我有一个示例文件,它是文件中的多个采购订单,由第二列标识。
Order Number, Purchase Number,DATE,Item Code ,Qty, Description 1245456,98978,12/01/2019, 1545-878, 1,"Test"
1245456,98978,12/01/2019,1545-342,2,"Test"
1245456,98978,12/01/2019,1545-878,2,"Test"
1245456,98979,12/02/2019,1545-878,3,"Test 3"
1245456,98979,12/02/2019,1545-342,4,"Test 4"
1245456,98979,12/02/2019,1545-878,5,"Test 4"
我想要的最终结果是能够将以上内容合二为一class,如下所示
最开始我正在使用 filelpers 来解析 csv 文件,如果我有 sep header 文件和行文件,这会很好用,但如您所见,它们是组合在一起的
var engine = new FileHelperEngine<CSVLines>();
var lines = engine.ReadFile(csvFileName);
所以 Class 应该如下所示
[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 订单例程中看到的那样,我首先创建 header,然后在其中添加行。
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 分成两个列表,其次我如何在强类型 object 中正确访问 header 行,如你所见我先用,但不能正常使用。
对于 FileHelpers,重要的是避免将映射 class 用于描述底层文件结构以外的任何内容。在这里,我怀疑您正试图直接映射到太复杂的 class。
FileHelpers class 只是一种使用 C# 语法定义平面文件规范的方法。
因此,FileHelpers classes 是一种不常见的 C# class 类型,您不应尝试使用公认的 OOP 原则。 FileHelpers 不应具有超出 FileHelpers 库使用的属性或方法。
仅将 FileHelpers class 视为 CSV 格式的 'specification'。这应该是它唯一的作用。 (无论如何,从维护的角度来看,这是一个很好的做法 - 如果底层 CSV 结构发生变化,则更容易调整您的代码)。
然后如果你需要更多'normal'object中的记录,然后将结果映射到更好的东西,即封装了[的所有功能的class =13=] object 而不是 CSVOrder
.
因此,处理此类文件的一种方法是对文件进行两次解析。在第一遍中,您提取 header 记录。像这样:
var engine1 = new FileHelperEngine<CSVHeaders>();
var headers = engine1.ReadFile(csvFileName);
在第二遍中提取细节;
var engine2 = new FileHelperEngine<CSVDetails>();
var details = engine2.ReadFile(csvFileName);
然后您将这些信息合并到一个新的专用 class 中,也许与此类似的一些 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.
});