我必须制作这种CSV布局,但有点不确定该怎么做。
我有一个Order类,我必须将其转换为CSV文件。
public class Order
{
public int ID {get; set;}
public int Created {get;set;}
public List<Item> Items {get;set;}
}
public class Item
{
public string Sku {get;set;}
public int Quantity {get;set;}
}
所以每行代表一个订单。如果一个订单中有超过2个项目,我将不得不继续下一行,除了sku,quanity和一个特定字段外,所有内容都是空白的。
如果从前一行继续,则最后一个字段为“Y”,否则为“N”。
所以我有:
List<Order> orders = Db.GetOrders();
因此CSV的示例输出将是:
"orderID", "Created", "Item01", "quantity01", "Item02", "N"
如果有超过2个项目,则必须输出:
"orderID", "Created", "Item01", "quantity01", "Item02", "N"
"", "", "Item03", "quantity03", "", "", "Y"
所以上面的订单有3个项目,请注意Item#4的占位符是如何仍然存在的,但只是空的双引号。
所以每个字段都是强制性的。
我如何制作这个?
到目前为止,我有:
StringBuilder sb = new StringBuilder();
for(int x = 0; x < orders.Count; x++)
{
Order o = orders[x];
if(x % 2 = 0)
{
sb.Append(o.ID).Append(",");
sb.Append(o.Created).Append(",");
}
}
我猜的诀窍是弄清楚我是否需要继续下一行,然后如果我的行中少于2个项目,我必须填写任何空白点?
(你可以忽略输出中的任何不良字符,稍后我会处理)
答案 0 :(得分:0)
你的内循环看起来像这样:
for (i = 0; i < items.Count; ++i) {
sb.Append(sku)
sb.Append(qty)
if (i % 2 == 1) {
if (i == items.Count - 1) {
sb.Append("N\n")
} else {
sb.Append("Y\n" "" "");
}
}
}
if (items.Count == 0) {
sb.Append("" "" "" "" "N")
}
if (items.Count % 2 == 1) {
sb.Append("" "" "N")
}
你可以扩展伪代码... csv格式有点不寻常。通常,csv将包含一个项目列表,每行一个(每个行中重复的订单号)。
答案 1 :(得分:0)
我发现将这样的问题分解为几种方法是有帮助的,每种方法都很容易理解,只做一小部分工作。然后你可以将它们结合起来解决更大的问题。
这可以帮助您入门。它需要更多的错误处理,并且可能需要逻辑来处理生成CSV字段时转义特殊字符(例如,如果SKU中可能包含逗号或引号)。
public class Order
{
public int ID { get; set; }
public int Created { get; set; }
public List<Item> Items { get; set; }
}
public class Item
{
public string Sku { get; set; }
public int Quantity { get; set; }
}
public class OrderCsvBuilder
{
private readonly StringBuilder m_CsvData = new StringBuilder();
// constructor accepts a sequence or Orders
public OrderCsvBuilder(IEnumerable<Order> orders)
{
foreach (var order in orders)
WriteOrder(order);
}
// returns the formatted CSV data as a string
public string GetCsvData()
{
return m_CsvData.ToString();
}
// writes a single order and its line items to csv format
private void WriteOrder( Order order )
{
WriteCsvFields( false, order.ID, order.Created );
var itemIndex = 0;
foreach( var item in order.Items )
WriteOrderItem( item, itemIndex++ );
}
// writes a single order item to csv format
private void WriteOrderItem( Item item, int itemIndex )
{
// write the extra fields when the order item is not the first item
if( itemIndex > 0 )
WriteCsvFields( false, string.Empty, string.Empty );
// use (?:) to append indicator of whether item is first or additional
WriteCsvFields( true, item.Quantity, item.Sku, itemIndex > 0 ? "Y" : "N" );
}
// writes a series of fields to the file in csv form
private void WriteCsvFields( bool isLineEnd, params object[] fields )
{
// write each field to the StringBuilder in CSV format
// TODO: Need better error handling and escaping of special characters
foreach( var field in fields )
{
m_CsvData.AppendFormat("\"{0}\", ", field);
}
// trim extra trailing space and comma if this is the last item of a line
if( isLineEnd )
m_CsvData.Remove(m_CsvData.Length - 2, 2);
}
}
答案 2 :(得分:0)
public string BuildOrdersCsv(List<Order> orders)
{
StringBuilder sb = new StringBuilder();
foreach (Order o in orders)
{
Append(sb, o.ID, o.Created);
for (int i = 0; i < 2; i++)
{
if (i < o.Items.Count)
Append(sb, o.Items[i].Sku, o.Items[i].Quantity);
else
Append(sb, "", "");
}
sb.AppendLine("\"N\"");
for (int i = 2; i < o.Items.Count; i++)
{
Append(sb, "", "", o.Items[i].Sku, o.Items[i].Quantity, "", "");
sb.AppendLine("\"Y\"");
}
}
return sb.ToString();
}
private void Append(StringBuilder sb, params object[] items)
{
foreach (object item in items)
{
sb.Append("\"").Append(item).Append("\",");
}
}
答案 3 :(得分:0)
未经测试,但你得到了这个小说。它可能无法完全按照您的要求进行操作,但很容易调整到您想要的内容。不需要所有的stringbuilder废话。
public class Order
{
public int ID { get; set; }
public int Created { get; set; }
public List<Item> Items { get; set; }
public override string ToString()
{
string fakeItem = "";
if(Items.Count > 2)
fakeItem = Environment.NewLine + @""""", """", ""Y"" "; // or whatever you want.
return string.Join(@"{0}, {1}, {2}, {3}",
ID,
Created == 0 ? "Y" : "N",
string.Join(", ", from item in Items.Take(2) select item.ToString()),
fakeItem);
}
}
public class Item
{
public string Sku { get; set; }
public int Quantity { get; set; }
public override string ToString()
{
return string.Format(@"{0}, {1}", Sku, Quantity);
}
}