c# - 在同一文件中循环标题和详细信息记录
问题描述
我在下面重新编辑了这个问题我有一个示例文件,它作为文件中的多个采购订单,由第二列标识。
订单号、采购号、日期、货品代码、数量、描述 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 拆分为两个列表,其次如何正确访问强类型对象中的标题行,正如您看到的那样,我首先使用的是无法正常工作的。
解决方案
对于 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.
});
推荐阅读
- mongodb - 如何在 Mongoose 排序结束时生成空值?
- oracle - 表突变在哪里发生(Oracle)?
- node.js - 在 node.js 中使用 fetch 测量 API 响应时间
- javascript - Vue 无法修改 slot 对象的顶层数据
- php - Stripe API 在编辑模式下无法工作 Wordpress
- php - 如何使用 PHP 和 MySQL 收集站点浏览量统计数据,例如每日、每周、每月和每年的浏览量?
- sql - Scala Slick Play 框架:如何使用 slick 3.x 连接多个数据库表?
- c# - 在 WPF 中,如何更新用户控件中的主 UI?
- xamarin - 保存选取器值空异常无法将字符串转换为模型
- python - 12296:26672:0420/163936.459:ERROR:browser_switcher_service.cc(238) XXX Init() Error in "Selenium Python"