using System; using System.Collections.Generic; using System.Text; namespace Sarand.Net.Standard.Base.Data { //======================================================================= /// /// Very basic CSV data handling. /// For more advanced CSV features, see SaCsvHelper in SacsWinOffice. /// public static class SacsCsvHandler { //------------------------------------------------------------------- // Properties. //------------------------------------------------------------------- public static String ToCsv (this IEnumerable values, char fieldDelimiter = ',', char textDelimiter = '"') { String data = ""; int valueCount = 0; foreach (String rawValue in values) { valueCount++; String value = rawValue; if (value.Contains(fieldDelimiter.ToString()) || value.Contains(textDelimiter.ToString())) value = textDelimiter + value.Replace(textDelimiter.ToString(), textDelimiter.ToString() + textDelimiter.ToString()) + textDelimiter; data += (valueCount > 1 ? fieldDelimiter.ToString() : "") + value; } return data; } //------------------------------------------------------------------- /// /// Extract comma delimited fields from data record. /// Fields starting with double quotes are terminated with the next single double quotes character. /// Embedded double quotes pairs are treated as a single double quotes character. /// /// /// public static List ParseCsvRecord (String data, char fieldDelimiter = ',', char textDelimiter = '"') { List fields = new List(); if (data == null) return fields; // Parse control properties. String currentField = ""; bool inTextField = false; bool previousCharTextDelim = false; // Parse the data. foreach (char c in data) { if (inTextField) { if (c == textDelimiter) { // Text delimiter found. if (!previousCharTextDelim) { // Make a note that a text delimiter has been found. previousCharTextDelim = true; continue; } else { // 2nd text delimiter found - add single text delimiter to field. currentField += c; previousCharTextDelim = false; continue; } } if (previousCharTextDelim) { // Non-text delimiter foudn after text delimiter - End of text field. inTextField = false; previousCharTextDelim = false; if (c == fieldDelimiter) { // End of field. fields.Add(currentField); currentField = ""; continue; } continue; } currentField += c; } else { // Non-text field. if (c == fieldDelimiter) { // End of field. fields.Add(currentField); currentField = ""; continue; } if (currentField.Length == 0 && c == textDelimiter) { // First character of field is text delimiter. inTextField = true; continue; } // Append character to field. currentField += c; } } fields.Add(currentField); return fields; } //------------------------------------------------------------------- } //======================================================================= }