Note
In the following code examples - for easier readability - exception
handling has been omitted.
public static TypeConverter<string> CreateNonNullable(
string defaultValue = ""
)
Public Shared Function CreateNonNullable (
Optional defaultValue As String = ""
) As TypeConverter(Of String)
public:
static TypeConverter<String^>^ CreateNonNullable(
String^ defaultValue = L""
)
static member CreateNonNullable :
?defaultValue : string
(* Defaults:
let _defaultValue = defaultArg defaultValue ""
*)
-> TypeConverter<string>
Exporting CSV data to Excel:
using FolkerKinzel.CsvTools;
using FolkerKinzel.CsvTools.Mappings;
using System.Globalization;
using System.Text;
// A namespace alias helps to avoid name conflicts
// with the converters from System.ComponentModel
using Conv = FolkerKinzel.CsvTools.Mappings.TypeConverters;
namespace Examples;
internal sealed record Customer(string Name, decimal Sales, DateOnly RecentPurchase);
internal static class ExcelExample
{
internal static void CsvDataExchangeWithExcel(string filePath)
{
// Which field separators and formatting Excel accepts and exports depends on the
// "Regional Settings" in Excel. The default setting corresponds to the settings
// of the user's computer (and thus of CultureInfo.CurrentCulture).
// Using CultureInfo.CurrentCulture, the corresponding parameters can be determined
// automatically.
// The application is free to override the value of CurrentCulture for the current
// Thread if users do not use the default setting in Excel.
// This example shows the procedure for exporting CSV data to Excel. The procedure
// for importing is equivalent.(The console output is from a computer with the locale
// "de-DE".)
Console.WriteLine("Current culture: {0}", CultureInfo.CurrentCulture);
Customer[] customers = [ new("Susi", 4_711m, new DateOnly(2004, 3, 14)),
new("Tom", 38_527.28m, new DateOnly(2006, 12, 24)),
new("Sören", 25.8m, new DateOnly(2011, 8, 27)) ];
// Get the Excel arguments for CultureInfo.CurrentCulture:
(char delimiter,
IFormatProvider formatProvider,
Encoding ansi) = Csv.GetExcelArguments();
// Pass the formatProvider from the Excel arguments to all localizable converters.
// (The same CsvMapping can be used for writing and parsing.)
CsvMapping mapping = CsvMappingBuilder
.Create()
.AddProperty("Name", Conv::StringConverter.CreateNonNullable())
.AddProperty("Sales", new Conv::DecimalConverter(formatProvider))
.AddProperty("RecentPurchase", new Conv::DateOnlyConverter(formatProvider))
.Build();
static void FillMapping(Customer customer, dynamic mapping)
{
mapping.Name = customer.Name;
mapping.Sales = customer.Sales;
mapping.RecentPurchase = customer.RecentPurchase;
}
// Don't forget to pass the delimiter from the Excel arguments!
// (The textEncoding can be omitted when writing, but not when reading.)
customers.SaveCsv(filePath, mapping, FillMapping, delimiter, textEncoding: ansi);
Console.WriteLine();
Console.WriteLine(File.ReadAllText(filePath, ansi));
// =================================================
// Parsing CSV that comes from Excel:
static Customer InitializeCustomer(dynamic mapping) => new(mapping.Name,
mapping.Sales,
mapping.RecentPurchase);
// Using this method allows to switch automatically to Unicode if the file
// has a byte order mark, and to detect a different delimiter character if
// the user had changed the default settings in Excel.
using CsvReader<Customer> reader = CsvConverter.OpenReadAnalyzed(filePath,
mapping,
InitializeCustomer,
defaultEncoding: ansi);
Console.WriteLine();
Console.WriteLine("The customer with the lowest sales is {0}.",
reader.MinBy(x => x.Sales)?.Name);
}
}
/*
Console output:
Current culture: de-DE
Name;Sales;RecentPurchase
Susi;4711;14.03.2004
Tom;38527,28;24.12.2006
Sören;25,8;27.08.2011
The customer with the lowest sales is Sören.
*/
Object serialization with CSV:
using FolkerKinzel.CsvTools;
using FolkerKinzel.CsvTools.Mappings;
using System.Text;
// A namespace alias helps to avoid name conflicts
// with the converters from System.ComponentModel
using Conv = FolkerKinzel.CsvTools.Mappings.TypeConverters;
namespace Examples;
internal sealed record Pupil(string? Name, string? Subject, DayOfWeek? LessonDay, TimeOnly? LessonBegin);
internal static class ObjectSerializationExample
{
public static void CsvReadWritePupils(string filePath)
{
Pupil[] pupils = [
new("Susi", "Piano", DayOfWeek.Wednesday, new TimeOnly(14, 30)),
new("Carl Czerny", "Piano", DayOfWeek.Thursday, new TimeOnly(15, 15)),
new("Frederic Chopin", "Piano", null, null)
];
// A converter can be reused for more than one DynamicProperty:
Conv::TypeConverter<string?> stringConverter = Conv::StringConverter.CreateNullable();
// Initialize a CsvMapping that maps the data from the CSV-Columns and converts it to the right data type.
// Aliases with wildcards can be used to match the column-headers of the CSV file.
CsvMapping mapping = CsvMappingBuilder
.Create()
.AddProperty("Name", ["*name"], stringConverter)
.AddProperty("Subject", ["*subject", "*fach"], stringConverter)
.AddProperty("LessonDay", ["*day", "*tag"], new Conv::EnumConverter<DayOfWeek>().ToNullableConverter())
.AddProperty("LessonBegin", ["*begin?"], new Conv::TimeOnlyConverter().ToNullableConverter())
.Build();
// Create a CSV-File:
pupils.SaveCsv(filePath,
mapping,
static (pupil, mapping) =>
{
mapping.Name = pupil.Name;
mapping.Subject = pupil.Subject;
mapping.LessonDay = pupil.LessonDay;
mapping.LessonBegin = pupil.LessonBegin;
},
columnNames:
["Unterrichtstag", "Unterrichtsbeginn", "Vollständiger Name", "Unterrichtsfach"]);
Console.WriteLine(File.ReadAllText(filePath));
Console.WriteLine();
// Read the CSV file:
using CsvReader<Pupil> pupilsReader =
CsvConverter.OpenRead<Pupil>(filePath,
mapping,
static mapping => new Pupil(mapping.Name,
mapping.Subject,
mapping.LessonDay,
mapping.LessonBegin));
pupils = [.. pupilsReader];
// Write the results to the Console:
foreach (Pupil pupil in pupils)
{
Console.WriteLine(pupil);
}
}
}
/*
Console output:
Unterrichtstag,Unterrichtsbeginn,Vollständiger Name,Unterrichtsfach
3,14:30:00,Susi,Piano
4,15:15:00,Carl Czerny,Piano
,,Frederic Chopin,Piano
Pupil { Name = Susi, Subject = Piano, LessonDay = Wednesday, LessonBegin = 14:30 }
Pupil { Name = Carl Czerny, Subject = Piano, LessonDay = Thursday, LessonBegin = 15:15 }
Pupil { Name = Frederic Chopin, Subject = Piano, LessonDay = , LessonBegin = }
*/