Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I write headers with the CsvProvider without providing a sample?

Tags:

f#

f#-data

Why is it that if I create a new CSV type with the CsvProvider<> in F# like this:

type ThisCsv = CsvProvider<Schema = "A (decimal), B (string), C (decimal)", HasHeaders = false>

then create/fill/save the .csv, the resulting file does not contain the headers in the schema I specified? It seems like there should be a way to include headers in the final .csv file, but that's not the case.

Setting HasHeaders = true errors out, because there's no sample provided. The only way for HasHeaders = true to work is to have a sample .csv. It seems to me that there should be a way to specify the schema without a sample and also include the headers in the final file.

Am I missing something when I use [nameOfMyCSV].Save() that can include the headers from the schema or can this not be done?

like image 894
Steven Avatar asked Sep 21 '16 16:09

Steven


People also ask

Does a CSV need a header?

From those guidelines and giving the lack of standardization, the header line is optional in a CSV file. When present, the header line must be the first line in the file and must contain the same number of fields as the records. Header and records lines must use the same field delimiters.

What is CSV provider?

The CSV type provider takes a sample CSV as input and generates a type based on the data present on the columns of that sample. The column names are obtained from the first (header) row, and the types are inferred from the values present on the subsequent rows.


1 Answers

I'm afraid the headers from the Schema are only used for the property names of the row. To have them in the file you save you have to provide Sample. Though, the sample can contain only the headers. Also, HasHeaders has to be set to true:

type ThisCsv = CsvProvider<
                Sample="A, B, C", 
                Schema = "A(decimal), B, C(decimal)", 
                HasHeaders = true>

If the sample contains only headers then if you want to specify data types the schema has to be provided as well.

You can see that the schema is used for property only when you rename the Sample headers in the Schema:

type ThisCsv = CsvProvider<
                Sample="A, B, C", 
                Schema = "A->AA(decimal), B->BB, C(decimal)", 
                HasHeaders = true>

Then the generated row will have properties like AA, B, CC. But the file generated will still have A, B, C. Also, the Headers property of a csv you created using this schema will be Some [|"A"; "B"; "C"|]:

// Run in F# Interactive
let myCsv = new ThisCsv([ThisCsv.Row(1.0m, "a", 2.0m)])
myCsv.Headers
// The last line returns: Some [|"A"; "B"; "C"|]

Also, to get better understanding of what's happening inside the parser worth taking a look at the source code in GitHub: CSV folder in general and CsvRuntime.fs in particular.

like image 192
PiotrWolkowski Avatar answered Nov 27 '22 21:11

PiotrWolkowski