I want to put a data from simple csv file into the records containing custom made class.
Here is my code:
using System;
using CsvHelper;
using System.IO; // for accessing the files
using System.Globalization;
using System.Linq; // to call a list enumerable
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
namespace Reading_CSV_Files
{
class Program
{
static void Main(string[] args)
{
ReadCSVFile(#"C:\path_to_my_file\file.csv");
}
public static void ReadCSVFile(String filePath)
{
if (filePath == null)
{
return;
}
using (var streamReader = new StreamReader(filePath) )
{
using (var foodFileCSVReader = new CsvReader(streamReader,
CultureInfo.InvariantCulture))
{
//var records = foodFileCSVReader.GetRecords<dynamic>().ToList();
var records = foodFileCSVReader.GetRecords<Pizza>().ToList();
// replace dynamic type argument on our records
}
}
}
}
public class Pizza
{
// attributes
[Name("Name")]
public String Name { get; set; }
[Name("PLN_Cost")]
public double Price { get; set; }
}
}
The csv file looks like this:
Screenshot from csv file
The file was saved as comma separated. I found some advices with manual setting it up, but currently it says, this field is read-only.
CsvHelper.HeaderValidationException: Header with name 'Name'[0] was not found.
Header with name 'PLN_Cost'[0] was not found.
If the program is going to be using CSV files which might have a comma or semi-colon as the separator, you could read the first line and set the separator to either of those, like this:
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApp1
{
class Program
{
public class Pizza
{
// attributes
[Name("Name")]
public String Name { get; set; }
[Name("PLN_Cost")]
public decimal Price { get; set; }
public override string ToString()
{
return $"{Name} - {Price}";
}
}
public static List<Pizza> ReadCSVFile(String filePath)
{
if (!File.Exists(filePath))
{
return new List<Pizza>();
}
var sep = ";";
/* Check the header for the separator character to use. */
string headerLine = File.ReadLines(filePath).First();
if (headerLine?.IndexOf(',') >= 0) { sep = ","; }
using (var sr = new StreamReader(filePath))
{
var config = new CsvConfiguration(CultureInfo.CurrentCulture)
{
Delimiter = sep,
Encoding = Encoding.UTF8
};
using (var foodFileCSVReader = new CsvReader(sr, config))
{
return foodFileCSVReader.GetRecords<Pizza>().ToList();
}
}
}
static void Main(string[] args)
{
var pp = ReadCSVFile(#"C:\temp\PizzaPrices.csv");
Console.WriteLine(string.Join("\r\n", pp));
Console.ReadLine();
}
}
}
Note that it is better to use the decimal type for money instead of the double type.
You might need additional code to set the decimal separator to be used.
Is there anyway to change the file extension on a csv download from mvcgrid? It downloads as .csv and i'd like .txt to stop my users from opening the contents in excel?
I can see there is a custom rendering engine, but that seems to offer file contents formats rather than the extension.
Thanks
Managed it via a customendering engine
using MVCGrid.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace MVCGrid.Web.Models
{
public class TextExportEngine : IMVCGridRenderingEngine
{
public bool AllowsPaging
{
get { return false; }
}
public void PrepareResponse(HttpResponse httpResponse)
{
httpResponse.Clear();
httpResponse.ContentType = "text/comma-separated-values";
httpResponse.AddHeader("content-disposition", "attachment; filename=\"" + "export" + ".txt\"");
httpResponse.BufferOutput = false;
}
public void Render(MVCGrid.Models.RenderingModel model, MVCGrid.Models.GridContext gridContext, System.IO.TextWriter outputStream)
{
var sw = outputStream;
StringBuilder sbHeaderRow = new StringBuilder();
foreach (var col in model.Columns)
{
if (sbHeaderRow.Length != 0)
{
sbHeaderRow.Append(",");
}
sbHeaderRow.Append(Encode(col.Name));
}
sbHeaderRow.AppendLine();
sw.Write(sbHeaderRow.ToString());
foreach (var item in model.Rows)
{
StringBuilder sbRow = new StringBuilder();
foreach (var col in model.Columns)
{
var cell = item.Cells[col.Name];
if (sbRow.Length != 0)
{
sbRow.Append(",");
}
string val = cell.PlainText;
sbRow.Append(Encode(val));
}
sbRow.AppendLine();
sw.Write(sbRow.ToString());
}
}
private string Encode(string s)
{
if (String.IsNullOrWhiteSpace(s))
{
return "";
}
return s;
}
public void RenderContainer(MVCGrid.Models.ContainerRenderingModel model, System.IO.TextWriter outputStream)
{
}
}
}
and then adding the following to my grid definition
.AddRenderingEngine("tabs", typeof(TextExportEngine)
I have ASP.Net site. I have JSON string that need to exported to physical CSV file.
private String JsonToCsv(string jsonData, string delimiter)
{
try
{
StringWriter swObj = new StringWriter();
using (var csv = new CsvWriter(swObj))
{
csv.Configuration.SkipEmptyRecords = true;
csv.Configuration.WillThrowOnMissingField = false;
csv.Configuration.Delimiter = delimiter;
using (var dt = jsonStringToTable(jsonData))
{
foreach (DataColumn col in dt.Columns)
{
csv.WriteField(col.ColumnName);
}
csv.NextRecord();
foreach(DataRow row in dt.Rows)
{
for (var i = 0; i < dt.Columns.Count; i++)
{
csv.WriteField(row[i]);
}
csv.NextRecord();
}
}
}
return swObj.ToString();
}
catch (Exception ex)
{
//handle exception
return null;
}
}
private DataTable jsonStringToTable(string jsonContent)
{
DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonContent);
return dt;
}
public HttpResponseMessage ExportToCSV(string jsonData)
{
string csv = JsonToCsv(jsonData, ",");
HttpResponseMessage res = new HttpResponseMessage(HttpStatusCode.OK);
res.Content = new StringContent(csv);
res.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
res.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "export.csv" };
return res;
}
But neither I am getting any exception nor CSV file is getting any data.
The Export.csv is located in the root folder.
How do I export the JSON & auto download the file??
It seems you do have an error, that you are suppressing in your catch.
Your first error is in that your jsonContent is not actually json. You have a variable assignment jsonContent = [...] in your sample. the section [...] is your actual json.
to handle that, you need only compose it better, by not having it assign to a variable (recommended approach), or handle instances here with jsonContent.Split(new [] {'='}).Last(). (a declarative vs imperative approach/strategy).
Also, you are attempting to deserialize into an incorrect type, for it does not reflect your json data structure.
although there are other manners to convert and process one string to another. I do agree the proper thing to do here is to deserialize your object (or not serialize beforehand - recommended).
I'm providing a sample Console Application for you to review two implementations of handle a JsonToCsv operation.
dynamic (imperative)
and providing a Type and using System.Reflection on that type. (declarative to the Json.Convert.DeserializeObject<T>() method, imperative afterward)
there is a dependency on NewtonSoft.Json Assembly (Install it via NuGet package) in this implementation; it reflects your provided code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Dynamic;
using System.Reflection;
using Newtonsoft;
namespace JsonToCsvTests
{
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
TestJsonToCsv();
Console.ReadLine();
}
static void TestJsonToCsv()
{
string jsonData = #"jsonData = [
{
""DocumentName"": ""Test Document"",
""ActionDate"": ""2015-09-25T16:06:25.083"",
""ActionType"": ""View"",
""ActionPerformedBy"": ""Sreeja SJ""
},
{
""DocumentName"": ""Test Document"",
""ActionDate"": ""2015-09-25T16:12:02.497"",
""ActionType"": ""View"",
""ActionPerformedBy"": ""Sreeja SJ""
},
{
""DocumentName"": ""Test Document"",
""ActionDate"": ""2015-09-25T16:13:48.013"",
""ActionType"": ""View"",
""ActionPerformedBy"": ""Sreeja SJ""
}]";
Console.WriteLine("...using System.Dynamic and casts");
Console.WriteLine();
Console.WriteLine(JsonToCsv(jsonData, ","));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("...using a provided StrongType with System.Reflection.");
Console.WriteLine();
Console.WriteLine(JsonToCsv<JsonData>(jsonData, ","));
}
static private string JsonToCsv(string jsonContent, string delimiter)
{
var data = jsonStringToTable(jsonContent);
var headers = ((IEnumerable<dynamic>)((IEnumerable<dynamic>)data).First()).Select((prop) => prop.Name).ToArray();
var csvList = new List<string>
{
string.Join(delimiter, headers.Select((prop) => string.Format(#"""{0}""", prop)).ToArray())
};
var lines = ((IEnumerable<dynamic>)data)
.Select(row => row)
.Cast<IEnumerable<dynamic>>()
.Select((instance) => string.Join(delimiter, instance.Select((v) => string.Format(#"""{0}""", v.Value))))
.ToArray();
csvList.AddRange(lines);
return string.Join(Environment.NewLine, csvList );
}
static private string JsonToCsv<T>(string jsonContent, string delimiter) where T : class
{
var data = jsonStringToTable<T>(jsonContent);
var properties = data.First().GetType().GetProperties();
var lines = string.Join(Environment.NewLine,
string.Join(delimiter, properties.Select((propInfo) => string.Format(#"""{0}""", propInfo.Name))),
string.Join(Environment.NewLine, data.Select((row) => string.Join(delimiter, properties.Select((propInfo) => string.Format(#"""{0}""", propInfo.GetValue(row)))))));
return lines;
}
static private dynamic jsonStringToTable(string jsonContent)
{
var json = jsonContent.Split(new[] { '=' }).Last();
return JsonConvert.DeserializeObject<dynamic>(json);
}
static private IEnumerable<T> jsonStringToTable<T>(string jsonContent) where T : class
{
var json = jsonContent.Split(new[] { '=' }).Last();
return JsonConvert.DeserializeObject<IEnumerable<T>>(json);
}
public class JsonData
{
public string DocumentName { get; set; }
public DateTime ActionDate { get; set; }
public string ActionType { get; set; }
public string ActionPerformedBy { get; set; }
}
}
}
Console.Output
...using System.Dynamic and casts
"DocumentName","ActionDate","ActionType","ActionPerformedBy"
"Test Document","9/25/2015 4:06:25 PM","View","Sreeja SJ"
"Test Document","9/25/2015 4:12:02 PM","View","Sreeja SJ"
"Test Document","9/25/2015 4:13:48 PM","View","Sreeja SJ"
...using a provided StrongType with System.Reflection.
"DocumentName","ActionDate","ActionType","ActionPerformedBy"
"Test Document","9/25/2015 4:06:25 PM","View","Sreeja SJ"
"Test Document","9/25/2015 4:12:02 PM","View","Sreeja SJ"
"Test Document","9/25/2015 4:13:48 PM","View","Sreeja SJ"
This is what i use to generate CSV file on my ASP.NET Website
public static class CSVUtils
{
public static void AddCsvLine(bool isFrenchSeparator, StringBuilder csv, params object[] values)
{
foreach (var value in values)
{
csv.Append('"').Append(value).Append('"');
if (isFrenchSeparator)
{
csv.Append(';');
}
else
{
csv.Append(',');
}
}
csv.Append('\r'); // AppendLine() adds a double line break with UTF32Encoding
}
}
public FileContentResult ExportCSV()
{
StringBuilder csv = new StringBuilder();
CSVUtils.AddCsvLine(false, csv, "Field1", "Field2", "Field3");
CSVUtils.AddCsvLine(false, csv, "value1", "value2", "value3");
return this.File(new UTF32Encoding().GetBytes(csv.ToString()), "text/csv", "myfile.csv");
}
I basically call the ExportCSV action from my website, on a button click for example and it downloads the file. Make sure to clean your JSON beforehand from all coma otherwise it would mess your CSV file.
EDIT: Specifically for JSON, you'd also have to anti-slash every " otherwise it would mess the StringBuilder i guess
How can I write HTML in a Word document using C#?
I made a class to help writing a document
using System;
using System.IO;
using Microsoft.Office.Interop.Word;
namespace WordExporter
{
public class WordApplication : IDisposable
{
private Application application;
private Document document;
private string path;
private bool editing;
public WordApplication(string path)
{
this.path = path;
this.editing = File.Exists(path);
application = new Application();
if (editing)
{
document = application.Documents.Open(path, ReadOnly: false, Visible: false);
}
else
{
document = application.Documents.Add(Visible: false);
}
document.Activate();
}
public void WriteHeader(string text)
{
foreach (Section wordSection in document.Sections)
{
var header = wordSection.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
header.Font.ColorIndex = WdColorIndex.wdDarkRed;
header.Font.Size = 20;
header.Text = text;
}
}
public void WriteFooter(string text)
{
foreach (Section wordSection in document.Sections)
{
var footer = wordSection.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range;
footer.Font.ColorIndex = WdColorIndex.wdDarkRed;
footer.Font.Size = 20;
footer.Text = text;
}
}
public void Save()
{
if (editing)
{
application.Documents.Save(true);
}
else
{
document.SaveAs(path);
}
}
#region IDisposable Members
public void Dispose()
{
((_Document)document).Close(SaveChanges: true);
((_Application)application).Quit(SaveChanges: true);
}
#endregion
}
class Program
{
static void Main(string[] args)
{
using (var doc = new WordApplication(Directory.GetCurrentDirectory() + "\\test.docx"))
{
doc.WriteHeader("<h1>Header text</h1>");
doc.WriteFooter("<h1>Footer text</h1>");
doc.Save();
}
}
}
}
In the WriteHeader I write some text on the document header, but I need to use HTML. How can I say the contents are HTML? I will also need to insert HTML in the document content...
I can just insert the html file on the section I want using:
range.InsertFile("file.html");
I am learning XML Serialization and meet an issue, I have two claess
[System.Xml.Serialization.XmlInclude(typeof(SubClass))]
public class BaseClass
{
}
public class SubClass : BaseClass
{
}
I am trying to serialize a SubClass object into XML file, I use blow code
XmlSerializer xs = new XmlSerializer(typeof(Base));
xs.Serialize(fs, SubClassObject);
I noticed Serialization succeed, but the XML file is kind of like
<?xml version="1.0"?>
<BaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="SubClass">
...
</Employee>
If I use
XmlSerializer xs = new XmlSerializer(typeof(Base));
SubClassObject = xs.Deserialize(fs) as SubClass;
I noticed it will complain xsi:type is unknown attribute(I registered an event), although all information embedded in the XML was parsed successfully and members in SubClassObject was restored correctly.
Anyone has any idea why there is error in parsing xsi:type and anything I did wrong?
Thanks
Here is the program that I wrote
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace XmlIncludeExample
{
[XmlInclude(typeof(DerivedClass))]
public class BaseClass
{
public string ClassName = "Base Class";
}
public class DerivedClass : BaseClass
{
public string InheritedName = "Derived Class";
}
class Program
{
static void Main(string[] args)
{
string fileName = "Test.xml";
string fileFullPath = Path.Combine(Path.GetTempPath(), fileName);
try
{
DerivedClass dc = new DerivedClass();
using (FileStream fs = new FileStream(fileFullPath, FileMode.CreateNew))
{
XmlSerializer xs = new XmlSerializer(typeof(BaseClass));
xs.Serialize(fs, dc);
}
using (FileStream fs = new FileStream(fileFullPath, FileMode.Open))
{
XmlSerializer xs = new XmlSerializer(typeof(BaseClass));
DerivedClass dc2 = xs.Deserialize(fs) as DerivedClass;
}
}
finally
{
if (File.Exists(fileFullPath))
{
File.Delete(fileFullPath);
}
}
}
}
}
This produced the following xml
<?xml version="1.0" ?>
- <BaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="DerivedClass">
<ClassName>Base Class</ClassName>
<InheritedName>Derived Class</InheritedName>
</BaseClass>
And it worked
I got the same error.
I have not a great answer but this is what I have done:
using System;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;
namespace HQ.Util.General
{
/// <summary>
/// Save by default as User Data Preferences
/// </summary>
public class XmlPersistence
{
// ******************************************************************
public static void Save<T>(T obj, string path = null) where T : class
{
if (path == null)
{
path = GetDefaultPath(typeof(T));
}
var serializer = new XmlSerializer(typeof(T));
using (TextWriter writer = new StreamWriter(path))
{
serializer.Serialize(writer, obj);
writer.Close();
}
}
// ******************************************************************
public static T Load<T>(string path = null,
Action<object, XmlNodeEventArgs> actionUnknownNode = null,
Action<object, XmlAttributeEventArgs> actionUnknownAttribute = null) where T : class
{
T obj = null;
if (path == null)
{
path = GetDefaultPath(typeof(T));
}
if (File.Exists(path))
{
var serializer = new XmlSerializer(typeof(T));
if (actionUnknownAttribute == null)
{
actionUnknownAttribute = UnknownAttribute;
}
if (actionUnknownNode == null)
{
actionUnknownNode = UnknownNode;
}
serializer.UnknownAttribute += new XmlAttributeEventHandler(actionUnknownAttribute);
serializer.UnknownNode += new XmlNodeEventHandler(actionUnknownNode);
using (var fs = new FileStream(path, FileMode.Open))
{
// Declares an object variable of the type to be deserialized.
// Uses the Deserialize method to restore the object's state
// with data from the XML document. */
obj = (T)serializer.Deserialize(fs);
}
}
return obj;
}
// ******************************************************************
private static string GetDefaultPath(Type typeOfObjectToSerialize)
{
return Path.Combine(AppInfo.AppDataFolder, typeOfObjectToSerialize.Name + ".xml");
}
// ******************************************************************
private static void UnknownAttribute(object sender, XmlAttributeEventArgs xmlAttributeEventArgs)
{
// Correction according to: https://stackoverflow.com/questions/42342875/xmlserializer-warns-about-unknown-nodes-attributes-when-deserializing-derived-ty/42407193#42407193
if (xmlAttributeEventArgs.Attr.Name == "xsi:type")
{
}
else
{
throw new XmlException("UnknownAttribute" + xmlAttributeEventArgs.ToString());
}
}
// ******************************************************************
private static void UnknownNode(object sender, XmlNodeEventArgs xmlNodeEventArgs)
{
// Correction according to: https://stackoverflow.com/questions/42342875/xmlserializer-warns-about-unknown-nodes-attributes-when-deserializing-derived-ty/42407193#42407193
if (xmlNodeEventArgs.Name == "xsi:type")
{
}
else
{
throw new XmlException("UnknownNode" + xmlNodeEventArgs.ToString());
}
}
// ******************************************************************
}
}