Home
Insert
Update snippet 'CSV writer'
Title
Description
A simple CSV writer implementation as two type extensions for the Seq module. Use it with Records, Classes and Tuples. Have a look at the modified CSV reader sample from Don Symes Expert F# too http://fssnip.net/3T in order to advance this snippet using the ColumnAttribute This version adds quote enclosure support and support for seq<string> datatype.
Source code
module Csv open System.IO open Microsoft.FSharp.Reflection type Array = static member join delimiter xs = xs |> Array.map (fun x -> x.ToString()) |> String.concat delimiter type Seq = static member write (path:string) (data:seq<'a>): 'result = use writer = new StreamWriter(path) data |> Seq.iter writer.WriteLine static member csv (separator:string) (useEnclosure:bool) (headerMapping:string -> string) ( data:seq<'a>) = seq { let dataType = typeof<'a> let stringSeqDataType = typeof<System.Collections.Generic.IEnumerable<string>> let inline enclose s = match useEnclosure with | true -> "\"" + (string s) + "\"" | false -> string s let header = match dataType with | ty when FSharpType.IsRecord ty -> FSharpType.GetRecordFields dataType |> Array.map (fun info -> headerMapping info.Name) | ty when FSharpType.IsTuple ty -> FSharpType.GetTupleElements dataType |> Array.mapi (fun idx info -> headerMapping(string idx) ) | ty when ty.IsAssignableFrom stringSeqDataType -> data :?> seq<seq<string>> |> Seq.head |> Seq.toArray | _ -> dataType.GetProperties() |> Array.map (fun info -> headerMapping info.Name) yield header |> Array.map enclose |> Array.join separator let lines = match dataType with | ty when FSharpType.IsRecord ty -> data |> Seq.map FSharpValue.GetRecordFields | ty when FSharpType.IsTuple ty -> data |> Seq.map FSharpValue.GetTupleFields | ty when ty.IsAssignableFrom stringSeqDataType -> data :?> seq<seq<string>> |> Seq.tail |> Seq.map (fun ss -> Seq.toArray ss |> Array.map (fun s -> s :> obj) ) | _ -> let props = dataType.GetProperties() data |> Seq.map ( fun line -> props |> Array.map ( fun prop -> prop.GetValue(line, null) )) |> Seq.map (Array.map enclose) yield! lines |> Seq.map (Array.join separator) }
Tags
csv
serialize
writer
csv
serialize
writer
Author
Link
Reference NuGet packages
If your snippet has external dependencies, enter the names of NuGet packages to reference, separated by a comma (
#r
directives are not required).
Update