Developer forum

Forum » PIM » Feed: data to CSV

Feed: data to CSV

Alex Guo
Reply

Hey,

I'm an intern and new with dynamic web.

I am struggling to transform the product data to a csv. 
The code I currently have is displaying the id and name, but not the variantId, or Numbe, these show as empty:

@using Dynamicweb.Rendering;
@using Dynamicweb.Ecommerce.ProductCatalog;
@using System.Collections.Generic;
@using System.Text;
@inherits ViewModelTemplate<ProductListViewModel>
@functions
{
    public enum FieldType
    {
        System,
        Standard
    };
 
    public class Field
    {
        public string ID { get; set; }
        public FieldType FieldType { get; set; }
        public string Label { get; set; }
 
        public Field(string id, string label, FieldType type)
        {
            ID = id;
            Label = label;
            FieldType = type;
        }
    }
 
    public List<Field> GetFields(ProductViewModel productViewModel)
    {
        var fields = new List<Field>();
        if (productViewModel == null)
        {
            return fields;
        }
 
        fields.Add(new Field("Id", "Product Id", FieldType.System));
        fields.Add(new Field("VariantId", "Variant id", FieldType.System));
        fields.Add(new Field("Number", "Number", FieldType.Standard));
        fields.Add(new Field("Name", "Name", FieldType.Standard));
       
        return fields;
    }
 
    public string GenerateCsv()
    {
        var fields = GetFields(Model.Products.FirstOrDefault());
 
        var allHeaders = fields.Select(x => new KeyValuePair<string, string>(x.ID, x.Label)).ToList();
 
        var headerSystemNames = allHeaders.Select(x => x.Key).ToList();
 
        StringBuilder contentBuilder = new System.Text.StringBuilder();
 
        contentBuilder.Append(Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble()));
 
        var headerLine = string.Join(";", allHeaders.Select(x => String.Format("\"{0}\"", x.Value))).ToString();
 
        contentBuilder.AppendLine(headerLine);
 
        var productsOuput = new StringBuilder();
        foreach (var product in Model.Products)
        {
            var values = new string[headerSystemNames.Count];
           
            values[headerSystemNames.IndexOf("Id")] = product.Id;
            values[headerSystemNames.IndexOf("VariantId")] = product.VariantId;
            values[headerSystemNames.IndexOf("DefaultVariantId")] = product.DefaultVariantId;
            values[headerSystemNames.IndexOf("Number")] = product.Number;
            values[headerSystemNames.IndexOf("Name")] = product.Name;
 
            productsOuput.AppendLine(string.Join(";", values.Select(x => String.Format("\"{0}\"", (x == null ? "" : x.Replace("\"", "'"))))));
        }
 
        contentBuilder.Append(productsOuput.ToString());
 
        return contentBuilder.ToString();
    }
}
@GenerateCsv()

This is the result: 

The variant Id and number are empty. I dont need the defaultVariantId that was just for testing.
 

 

Thanks in advance!

 

 


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

The problem is that you’re trying to fill in a field ("DefaultVariantId") that isn’t even part of your header list. In your foreach loop you have:

values[headerSystemNames.IndexOf("DefaultVariantId")] = product.DefaultVariantId;

Since "DefaultVariantId" isn’t added in your GetFields method, calling IndexOf("DefaultVariantId") returns –1. This can cause unexpected behavior (or an exception) that interferes with filling in the correct values for the VariantId and Number fields.

Simplified CSV Code

A simpler approach is to hard-code the header and iterate over your products without doing the header lookup via indices. For example:

@functions {
    public string GenerateCsv()
    {
        var sb = new System.Text.StringBuilder();

        // Write CSV header
        sb.AppendLine("\"Product Id\";\"Variant Id\";\"Number\";\"Name\"");

        // Write each product's data
        foreach (var product in Model.Products)
        {
            sb.AppendLine(
                $"\"{(product.Id ?? "")}\";" +
                $"\"{(product.VariantId ?? "")}\";" +
                $"\"{(product.Number ?? "")}\";" +
                $"\"{(product.Name ?? "")}\""
            );
        }

        return sb.ToString();
    }
}

This code does the following:

  • Writes a fixed header line with the correct field labels.
  • Loops over each product and outputs the corresponding fields using string interpolation.
  • Handles potential null values by replacing them with an empty string.

This approach is not only more straightforward but also avoids the error of mismatched header keys.

 
Alex Guo
Reply

Yes, I noticed a little later after posting that I forgot to remove `DefaultVariantId` from the headers.
However, the initial issue still persists—`VariantId` and `Number` are both empty in the generated CSV.  

I found the issue, Thanks for the fast reply

 

You must be logged in to post in the forum