tricky CSV-Datei Ausgabe basiert auf einer Liste <Order> Aufträge Sammlung

stimmen
0

Ich habe dieses CSV-Layout zu erzeugen, aber ein wenig unsicher, wie es zu tun.

Ich habe eine Order-Klasse, die ich in eine CSV-Datei zu konvertieren.

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;}
}

So stellt jede Zeile einen Auftrag. Wenn ein Auftrag mehr als 2 Artikel in ihm hat, werde ich in der nächsten Zeile fortzusetzen alles leer mit Ausnahme der sku verlassen, quanity und ein specifical Feld.

Das letzte Feld wird „Y“, wenn sein aus der vorherige Zeile fortgesetzt, „N“ sonst.

Also habe ich:

List<Order> orders = Db.GetOrders();

So ein Beispiel für die Ausgabe des CSV wäre:

orderID, Created, Item01, quantity01, Item02, N

wenn es mehr als zwei Elemente sind, hat es zur Ausgabe von:

orderID, Created, Item01, quantity01, Item02, N
, , Item03, quantity03, , , Y

So hatte die obige Reihenfolge 3 Artikel, beachten Sie, wie der Platzhalter für Item # 4 noch vorhanden ist, aber nur leere doppelte Anführungszeichen.

So ist jedes Feld obligatorisch.

Wie würde ich produzieren das?

Bisher habe ich:

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(,);
         }

}

Der Trick, den ich denke, ist es, herauszufinden, ob ich in der nächsten Zeile fortsetzen müssen, und dann muss ich alle leeren Stellen füllen, wenn ich weniger als 2 Elemente in der Reihe?

(Sie irgendwelche schlechten Zeichen in der Ausgabe ignorieren kann, werde ich Willen befassen, die später dank)

Veröffentlicht am 30/12/2009 um 00:45
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
0

Ihre innere Schleife sieht wie folgt aus etwas:

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")
}

Sie können den Pseudo-Code erweitern ... das CSV-Format ein bisschen ungewöhnlich ist. typischerweise würde eine CSV eine Liste von Elementen enthält, eine pro Zeile (die Zahl in jeder Reihenfolge wiederholt).

Beantwortet am 30/12/2009 um 01:08
quelle vom benutzer

stimmen
0

Ich finde es hilft, Probleme wie diese in mehrere Methoden zu zersetzen, die jeder einfach zu verstehen und machen einen kleinen Teil des Jobs. Dann können Sie sie kombinieren, um das größere Problem zu lösen.

Hier ist etwas zu erleichtern Ihnen den Einstieg. Es braucht mehr Fehlerbehandlung und braucht wahrscheinlich Logik mit Flucht Sonderzeichen umgehen, wenn die CSV-Felder erzeugen (wenn die SKU Kommas oder Anführungszeichen innerhalb es zum Beispiel haben kann).

    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);
        }
    }
Beantwortet am 30/12/2009 um 01:21
quelle vom benutzer

stimmen
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("\",");
    }
}
Beantwortet am 30/12/2009 um 01:29
quelle vom benutzer

stimmen
0

Ungeprüfte aber Sie bekommen die jist. Es ist vielleicht nicht genau das tun, was Sie in dieser Form wollen, aber einfach zu zwicken, was Sie wollen. Keine Notwendigkeit für alle, den String Mist.

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);
    }
}
Beantwortet am 07/07/2014 um 11:28
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more