DataTableExtensionWriteCsv(DataTable, String, CsvMapping, Char, Encoding, IEnumerableString) Method

Saves the content of a DataTable as a CSV file with header.

Definition

Namespace: FolkerKinzel.CsvTools.Mappings
Assembly: FolkerKinzel.CsvTools.Mappings (in FolkerKinzel.CsvTools.Mappings.dll) Version: 1.1.0+1263e8243dc2cd78095f678f813d7d9c52ea4315
C#
public static void WriteCsv(
	this DataTable dataTable,
	string filePath,
	CsvMapping mapping,
	char delimiter = ',',
	Encoding? textEncoding = null,
	IEnumerable<string?>? csvColumnNames = null
)

Parameters

dataTable  DataTable
The DataTable whose content is written.
filePath  String
File path of the CSV file.
mapping  CsvMapping
The CsvMapping to be used.
delimiter  Char  (Optional)
The field separator character.
textEncoding  Encoding  (Optional)
The text encoding to be used or null for UTF8.
csvColumnNames  IEnumerableString  (Optional)

A collection of column names for the CSV header row to be written, or null to use the ColumnNames of dataTable as CSV column names.

The collection determines the order in which the columns appear in the CSV file.

The collection will be copied. If the collection contains null values, empty strings or white space, these are replaced by automatically generated column names. Column names cannot appear twice. By default the comparison is case-sensitive but it will be reset to a case-insensitive comparison if the column names are also unique when treated case-insensitive.

Usage Note

In Visual Basic and C#, you can call this method as an instance method on any object of type DataTable. When you use instance method syntax to call this method, omit the first parameter. For more information, see Extension Methods (Visual Basic) or Extension Methods (C# Programming Guide).

Remarks

Creates a new CSV file. If the target file already exists, it is truncated and overwritten.

Each PropertyName of mapping MUST have a corresponding DataColumn in dataTable - corresponding in the Caption property (case-insensitive) and the accepted data type.

Effort must be taken that the PropertyNames in mapping are unique, even when treated case-insensitive.

The DynamicProperty instances in mapping don't need to match all columns of the DataTable or all columns of the CSV file (neither in number nor in order).

When exchanging CSV data with Excel, the appropriate arguments can be determined with GetExcelArguments.

Example

  Note

In the following code examples - for easier readability - exception handling has been omitted.

DataTable serialization with CSV:

C#
using FolkerKinzel.CsvTools;
using FolkerKinzel.CsvTools.Mappings;
using System.Data;
// A namespace alias helps to avoid name conflicts
// with the converters from System.ComponentModel
using Conv = FolkerKinzel.CsvTools.Mappings.TypeConverters;

namespace Examples;

internal static class DataTableExample
{
    public static void DataTableWriteReadCsv(string filePath)
    {
        using var dataTable = new DataTable();

        dataTable.Columns.Add(new DataColumn("not_used", typeof(int)));
        dataTable.Columns.Add(new DataColumn("name"));
        dataTable.Columns.Add(new DataColumn("subject"));
        dataTable.Columns.Add(new DataColumn("day", typeof(DayOfWeek)));
        dataTable.Columns.Add(new DataColumn("lesson start", typeof(TimeOnly)));

        // The DataColumn.Caption property allows you to override the DataColumn.ColumnName property
        // when the ColumnName does not meet C# identifier requirements. The values ​​of the
        // DataColumn.Caption properties must be unique for CSV serialization (case-insensitive,
        // like DataColumn.ColumnName).
        dataTable.Columns["lesson start"]!.Caption = "begin";

        _ = dataTable.Rows.Add(
            [4711, "Susi Meyer", "Piano", DayOfWeek.Wednesday, new TimeOnly(14, 30, 0)]);
        _ = dataTable.Rows.Add(
            [0, "Carl Czerny", "Piano", DayOfWeek.Thursday, new TimeOnly(15, 15, 0)]);
        _ = dataTable.Rows.Add(
            [111, "Frederic Chopin", "Piano"]);

        // Store the stringConverter because you can reuse the same 
        // converter for more than one property in CsvRecordWrapper.
        Conv::TypeConverter<object> stringConverter
            = Conv::StringConverter.CreateNullable().ToDBNullConverter();

        // Each dynamic property name of the CsvMapping has to have a corresponding column in
        // the DataTable - corresponding in the DataColumn.Caption property (case-insensitive)
        // and the accepted data type. Mapping properties and DataColumns don't need to
        // correspond in their number and order and they don't need to match the columns of
        // the CSV file:
        CsvMapping mapping = CsvMappingBuilder
            .Create()
            .AddProperty("Name", stringConverter)
            .AddProperty("Subject", stringConverter)
            .AddProperty("Day", new Conv::EnumConverter<DayOfWeek>(format: "G")
                                .ToNullableConverter()
                                .ToDBNullConverter())
            .AddProperty("Begin", ["begin", "*start"], new Conv::TimeOnlyConverter()
                                                       .ToNullableConverter()
                                                       .ToDBNullConverter())
            .Build();

        // Write the CSV file:
        // (The CSV column names and the CsvMapping determine which DataColumns will be
        // part of the CSV and their order in the CSV file.)
        dataTable.WriteCsv(filePath,
                           mapping,
                           csvColumnNames: ["Subject", "Lesson Start", "Name", "Day", "Reserved"]);

        dataTable.Clear();

        // Refill the DataTable from the CSV-file:
        dataTable.ReadCsv(filePath, mapping);

        Console.WriteLine("Csv file:");
        Console.WriteLine();
        Console.WriteLine(File.ReadAllText(filePath));
        Console.WriteLine();
        Console.WriteLine("Content of the refilled DataTable:");
        Utility.WriteConsole(dataTable);
    }
}
/* 
Console output:

Csv file:

Subject,Lesson Start,Name,Day,Reserved
Piano,14:30:00,Susi Meyer,Wednesday,
Piano,15:15:00,Carl Czerny,Thursday,
Piano,,Frederic Chopin,,

Content of the refilled DataTable:
<DBNull>        Susi Meyer      Piano           3               14:30
<DBNull>        Carl Czerny     Piano           4               15:15
<DBNull>        Frederic Chopin Piano           <DBNull>        <DBNull>
*/

Exceptions

ArgumentNullExceptiondataTable, or filePath, or mapping is null.
ArgumentException

filePath is not a valid file path.

- or -

There is a DynamicProperty in mapping whose PropertyName finds no corresponding ColumnName in dataTable.

InvalidCastException A value in dataTable does not match the expected data type in mapping.
FormatException One of the TypeConverterT instances uses an invalid format string.
IOExceptionI/O error.
ObjectDisposedExceptionThe file was already closed.

See Also