简体   繁体   中英

Write F# DataTable to CSV file

I am trying to write an F# DataTable to csv (or output in a txt). The table I have is defined as follows:

let setup_report_tbl ( tbl : DataTable ) =
    ignore( tbl.Columns.Add("business_date", typeof<System.Int32>) )
    ignore( tbl.Columns.Add("ticker", typeof<System.String>) )
    ignore( tbl.Columns.Add("price", typeof<System.String>) )
    ignore( tbl.Columns.Add("rate", typeof<System.Boolean>) )
    ignore( tbl.Columns.Add("range", typeof<System.Double>) )

My goal is to write this empty table with headers into a csv or txt. I'm new to F# and not quite sure where to start here, any help is appreciated thanks!

To write a DataTable as CSV, I would do something like this:

open System
open System.IO
open System.Data

let writeCsv (wtr : StreamWriter) (tbl : DataTable) =

    let writeValues (values : seq<_>) =
        String.Join(',', values)
            |> wtr.WriteLine

    tbl.Columns
        |> Seq.cast<DataColumn>
        |> writeValues

    for row in tbl.Rows do
        row.ItemArray |> writeValues

Note that I haven't done anything to check for special characters in the values, such commas or quotes.

Example:

let tbl = new DataTable()
setup_report_tbl tbl
tbl.Rows.Add(1, "moo", "baa", true, 2.0) |> ignore
use wtr = new StreamWriter(Console.OpenStandardOutput())
writeCsv wtr tbl

Output is:

business_date,ticker,price,rate,range
1,moo,baa,True,2

Update

To avoid compiler error, perhaps try this:

    let writeValues (values : seq<_>) =
        let s = String.Join(',', values)
        wtr.WriteLine(s)

Note that s is a string, so there should be no ambiguity in which version of WriteLine is called.

If you wanted to use an existing library rather than writing your own CSV encoding (which may get tricky when you need to escape things), you could use Deedle which has an easy way to create data frame from a DataTable and save it to a CSV file:

#r "nuget: Deedle"
open Deedle
open System.Data

// Setup table using your function and add some data
let tbl = new DataTable()
setup_report_tbl tbl
tbl.Rows.Add(1, "very\",evil'ticker", "$42", false, 1.23)

// Turn it into a dataframe and save it
let df = Frame.ReadReader(tbl.CreateDataReader())
df.SaveCsv("C:/temp/test.csv")

As a bonus point, you could see if the data frame type from Deedle lets you do some of the other things you want to do with the data - but this depends on your scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM