Skip to content

Instantly share code, notes, and snippets.

@jacotan
Created December 12, 2013 04:12
Show Gist options
  • Save jacotan/7923084 to your computer and use it in GitHub Desktop.
Save jacotan/7923084 to your computer and use it in GitHub Desktop.
http://fssnip.net/3U をMS Excel向けCSVに特化 (Not Tested!)
// http://fssnip.net/3U をベースとするCSV出力モジュール。
/// F#のSeqを拡張している。
/// 元ネタではセパレータを選べたが、その機能を殺してMicrosoft Excel向けCSVに特化した。
module Csv
open System.IO
open System.Text
open System.Text.RegularExpressions
open Microsoft.FSharp.Reflection
let csvEscape str =
// CSVのエスケープが必要な文字列表現を拾う正規表現
let NeedCsvEscape str = Regex("(\"|'|,|\n|\r)",RegexOptions.Multiline).IsMatch(str)
let tempstr = str.ToString()
if (NeedCsvEscape tempstr) then
"\"" + tempstr.Replace("\"","\"\"") + "\""
else tempstr
type Array =
static member join delimiter xs =
xs
|> Array.map (csvEscape)
|> String.concat delimiter
type Seq =
static member write (path:string) (data:seq<'a>): 'result =
use writer = new StreamWriter(path,false,Encoding.GetEncoding(932))
data
|> Seq.iter writer.WriteLine
static member csv (headerMapping:string -> string) ( data:seq<'a>) =
let separator = ","
seq {
let dataType = typeof<'a>
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) )
| _ -> dataType.GetProperties()
|> Array.map (fun info -> headerMapping info.Name)
yield header |> 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
| _ ->
let props = dataType.GetProperties()
data |> Seq.map ( fun line ->
props |> Array.map ( fun prop ->
prop.GetValue(line, null) ))
yield! lines |> Seq.map (Array.join separator)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment