Attachment 'netCSV.v1.1.txt'

Download

   1 :Namespace netCSV
   2 ⍝ Namespace to convert a CSV file to a DataTable while preserving the DataType.
   3 ⍝ This namespace is using the assembly LumenWorks.Framework.IO.dll
   4 
   5 ⍝ See http://aplwiki.com/netCSV for more information
   6 
   7 ⍝ February 2016   - Initial version (1.0)
   8 
   9 ⍝ April 2016 - version (1.1)
  10 ⍝              SimpleCsvFileToDT and CsvFileToDT modified so it will not block the file
  11 ⍝              on disk while doing the conversion to a DataTable
  12 
  13 
  14     (⎕IO ⎕ML ⎕WX)←1 3 3
  15 
  16       TsToDateString←{
  17         ⍝ ⍵ = ⎕TS
  18         ⍝ Result = Date formatted to a String with no ambiguity.
  19      
  20           ⎕USING←'System,mscorlib.dll' 'System.Xml,System.Xml.dll'
  21           XmlConvert.ToString(((⎕NEW DateTime ⍵))(,'dd-MMM-yyyy'))
  22       }
  23 
  24       TsToTimeString←{
  25         ⍝ ⍵ = ⎕TS
  26         ⍝ Result = Time formatted to a String with no ambiguity.
  27      
  28           ⎕USING←'System,mscorlib.dll' 'System.Xml,System.Xml.dll'
  29           XmlConvert.ToString(((⎕NEW DateTime ⍵))(,'h:mm:ss tt'))
  30       }
  31 
  32       TsToDateTimeString←{
  33         ⍝ ⍵ = ⎕TS
  34         ⍝ Result = Date and Time formatted to a String with no ambiguity.
  35      
  36           ⎕USING←'System,mscorlib.dll' 'System.Xml,System.Xml.dll'
  37           XmlConvert.ToString(((⎕NEW DateTime ⍵))(,'dd-MMM-yyyy h:mm:ss tt'))
  38       }
  39 
  40 
  41     ∇ records←{FieldDecSep}AplToCsvRecords aplArray;decimalSeparator;fieldSeparator;test;⎕PP
  42     ⍝ Convert an Apl array to individual CSV records (one record per row of the array).
  43     ⍝ Use the function 'CsvFileAddRecords' to Append the records to a CSV file.
  44     ⍝ Example:  fileName CsvFileAddRecords AplToCsvRecords aplArray
  45 
  46     ⍝ Use the function 'CsvFileNew' to Create the initial CSV file with a Header.
  47 
  48     ⍝ aplArray    = Apl array
  49     ⍝ FieldDecSep = Field and Decimal Separator (like ',.' or ';,' )
  50     ⍝ records     = one record per row of 'apl' formatted according to the CSV format
  51      
  52       :If 0≠⎕NC'FieldDecSep'
  53           (fieldSeparator decimalSeparator)←FieldDecSep
  54       :Else
  55         ⍝ Default values
  56           (fieldSeparator decimalSeparator)←',.' ⍝ North America
  57     ⍝     (fieldSeperator decimalSeparator)←';,' ⍝ Europe
  58       :End
  59      
  60     ⍝ Used by ⍕ to display the number of significant digits
  61       ⎕PP←5
  62      
  63       :If ~0∊test←{0=↑1↑0⍴⍵}¨,aplArray
  64         ⍝ 'apl' is all Numeric. This expression is optimize for all numeric array.
  65           records←fieldSeparator{p←⍵ ⋄ ((p=' ')/p)←⍺ ⋄ ((p='¯')/p)←'-' ⋄ p}¨⍕¨↓aplArray
  66           records←{(decimalSeparator,⍵)[('.',⍵)⍳⍵]}¨records
  67      
  68       :Else
  69         ⍝ 'apl' is all characters or a mixture of numeric and characters
  70         ⍝ Code inspired from: http://aplwiki.com/CsvToApl
  71           (test/,aplArray)←{('-',⍵)[('¯',⍵)⍳⍵]}¨⍕¨test/,aplArray             ⍝ Make numbers characters
  72           (test/,aplArray)←{(decimalSeparator,⍵)[('.',⍵)⍳⍵]}¨test/,aplArray  ⍝ Change the decimal separator
  73           test←,'"'∊¨,aplArray                                 ⍝ Double quotes in the text ?
  74           (test/,aplArray)←{⍵/⍨1+'"'=⍵}¨test/,aplArray         ⍝ Double the double quotes
  75           test←∨/¨(⊂fieldSeparator,'"',⎕UCS 13 10)∊¨,aplArray  ⍝ Special characters ?
  76           (test/,aplArray)←{'"',⍵,'"'}¨test/,aplArray          ⍝ Put double quotes on fields with special characters
  77           records←{⊃{⍺,fieldSeparator,⍵}/⍵}¨↓aplArray          ⍝ Separate fields with fieldSeparator
  78      
  79       :End
  80 
  81 
  82 
  83     ∇ r←fileName CsvFileAddRecords records;⎕USING
  84     ⍝ Function to Add Record(s) to a CSV file.
  85 
  86     ⍝ records =  Line(s) of text with a delimiter like ',' or ';'
  87     ⍝ fileName = Fully qualified file name with extension.
  88     ⍝ r        = 1 if successfull, 0 (ERROR) if failure
  89      
  90       :If 1=≡records
  91           records←⊂records
  92       :EndIf
  93      
  94     ⍝ Add a LF and CR to each record(s) and flatten the result.
  95       records←∊{⍵,⎕UCS 13 10}¨records
  96      
  97       :Trap 0
  98           ⎕USING←',mscorlib.dll'
  99           System.IO.File.AppendAllText((⊂,fileName),(⊂,records),(System.Text.Encoding.UTF8))
 100           r←1
 101       :Else
 102         ⍝ Failure: Unexpected Error While Writing the File
 103           r←0('EXCEPTION CsvFileAddRecords: ',⎕EXCEPTION.Message)
 104       :EndTrap
 105 
 106 
 107     ∇ r←fileName CsvFileNew header;⎕USING
 108     ⍝ Function to Create a New File with a CSV Header
 109 
 110     ⍝ header   = Columns Names separated by a delimiter like ',' or ';'
 111     ⍝ fileName = Fully qualified file name with extension.
 112     ⍝ r        = 1 if successfull, 0 (ERROR) if failure
 113      
 114       header,←⎕UCS 13 10 ⍝ Add CR and LF to the header
 115      
 116       :Trap 0
 117           ⎕USING←',mscorlib.dll'
 118           System.IO.File.WriteAllText((⊂,fileName),(⊂,header),(System.Text.Encoding.UTF8))
 119           r←1
 120       :Else
 121         ⍝ Failure: Unexpected Error While Writing the File
 122           r←0('EXCEPTION CsvFileNew: ',⎕EXCEPTION.Message)
 123       :EndTrap
 124 
 125 
 126 
 127     ∇ dt←{FieldDecSep}CsvFileToDT fileName;bufferSize;colNames;cols;colTypes;comment;csv;cultureInfo;decimalSeparator;escape;fieldCount;fields;fieldSeparator;firstRecord;hasHeaders;headerRecord;headers;ms;nullValue;quote;sr;streamReader;trimmingOptions;⎕USING
 128     ⍝ Parse a CSV file to a DataTable with DataTypes preserved
 129     ⍝ Based on: http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
 130     ⍝ and https://github.com/phatcher/CsvReader
 131     ⍝ The assembly LumenWorks.Framework.IO.dll needs to be in the same directory as Dyalog.exe
 132 
 133     ⍝ fileName    = fully qualified file name with extension
 134     ⍝ FieldDecSep = Field and Decimal Separator (like ',.' or ';,' )
 135     ⍝ dt          = DataTable with DataType preserved
 136 
 137     ⍝ The CSV file must have a Header record, it will be used to give the names to the DataCcolumns of the DataTable
 138     ⍝ The Header can have the DataType of the column within {}, otherwise the DataType will be detected automatically.
 139      
 140       :If 0≠⎕NC'FieldDecSep'
 141           (fieldSeparator decimalSeparator)←FieldDecSep
 142       :Else
 143         ⍝ Default values
 144           (fieldSeparator decimalSeparator)←',.' ⍝ North America
 145     ⍝     (fieldSeparator decimalSeparator)←';,' ⍝ Europe
 146       :End
 147      
 148       ⎕USING←'System.IO,mscorlib.dll' 'LumenWorks.Framework.IO.Csv,LumenWorks.Framework.IO.dll'
 149       ⎕USING,←'System.Data,System.Data.dll' 'System,mscorlib.dll' 'System.Globalization,mscorlib.dll'
 150      
 151     ⍝ Use your local Culture if not appropriate
 152     ⍝ To obtain the Default DecimalSeparator, ThousandsSeparator and CSVSeparator on this computer you can do:
 153     ⍝      ⎕USING←'System.Globalization,mscorlib.dll'
 154     ⍝      CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator
 155     ⍝      CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator
 156     ⍝      CultureInfo.CurrentCulture.TextInfo.ListSeparator
 157     ⍝ To obtain your current culture you can do:
 158     ⍝      CultureInfo.CurrentCulture
 159     ⍝ See also https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28v=vs.110%29.aspx
 160       cultureInfo←⎕NEW CultureInfo(⊂'en-US')
 161       cultureInfo.NumberFormat.NumberDecimalSeparator←,decimalSeparator
 162      
 163     ⍝ Set-up those options before constructing the CsvReader. They cannot be setup later
 164       hasHeaders←0       ⍝ Must be zero to be able to define the DataType of the columns. If 1 all columns are automatically of String type.
 165       quote←'"'
 166       escape←'"'
 167       comment←'#'        ⍝ First character of a record that will not be parse
 168       trimmingOptions←1  ⍝ 0=None, 1=Unquoted Only, 2=Quoted Only, 3=All
 169       bufferSize←4096
 170       nullValue←⊂''
 171      
 172     ⍝ Construct the StreamReader
 173     ⍝ Using a MemoryStream will not block the file to being written.
 174       ms←⎕NEW MemoryStream(⊂File.ReadAllBytes(⊂,fileName))
 175       streamReader←⎕NEW StreamReader(ms)
 176 ⍝     streamReader←⎕NEW StreamReader(⊂,fileName)
 177      
 178     ⍝ Read the Header and remove all the blanks
 179       headerRecord←(streamReader.ReadLine)~' '
 180      
 181     ⍝ Read the first record. Could be multiline.
 182       firstRecord←''
 183       :While 0=streamReader.EndOfStream
 184           firstRecord,←streamReader.ReadLine
 185       :Until 0=1|0.5×+/firstRecord=quote ⍝ Read until even number of quotes
 186      
 187      ⍝ Reset the StreamReader to the beginning.
 188       streamReader.DiscardBufferedData
 189       {}streamReader.BaseStream.Seek((Convert.ToInt64 0),SeekOrigin.Begin)
 190       streamReader.BaseStream.Position←Convert.ToInt64 0
 191      
 192     ⍝ Construct the CsvReader
 193       csv←⎕NEW CsvReader(streamReader,hasHeaders,fieldSeparator,quote,escape,comment,trimmingOptions,bufferSize,nullValue)
 194       csv.MissingFieldAction←csv.MissingFieldAction.ReplaceByNull
 195       csv.DefaultParseErrorAction←csv.DefaultParseErrorAction.AdvanceToNextLine
 196       csv.SkipEmptyLines←1
 197       csv.SupportsMultiline←1
 198      
 199     ⍝ Split the headerRecord at the fieldSeparator character
 200       headers←(~fieldSeparator=headerRecord)⊂headerRecord
 201      
 202     ⍝ Split the first record at the fieldSeparator character
 203       fields←(~fieldSeparator=firstRecord)⊂firstRecord
 204      
 205     ⍝ Read the Header Record and discard it.
 206       {}csv.ReadNextRecord
 207      
 208     ⍝ Check if the DataType was specify in the Header, otherwise detect it on the first record.
 209       colTypes←''
 210       :For header field :In (headers{⍺ ⍵}¨fields)
 211           :If ∧/'{}'∊header
 212             ⍝ DataType is specified in the Header record
 213             ⍝ Could be: Boolean, Byte, Decimal, Double, Single, Int64, Int16, String, DateTime
 214               colTypes,←⊂{h←⌽(⍵⍳'{')↓⍵ ⋄ h←⌽(h⍳'}')↓h ⋄ h}header  ⍝ Get data type between {} of the header
 215      
 216           :Else
 217             ⍝ DataType was not specified in the Header record
 218             ⍝ Analyse the first record to find the DataType
 219             ⍝ The DataType detected will be either: DateTime, Double or String
 220             ⍝ If the first record has empty field(s) it will default to String
 221      
 222               colTypes,←⊂cultureInfo DetectDataType field
 223           :End
 224      
 225       :EndFor
 226      
 227     ⍝ Create the Columns with the DataType, Name and CultureInfo
 228       colNames←{h←(¯1+⍵⍳'{')↑⍵ ⋄ h}¨headers    ⍝ Get the column names from the split headerRecord
 229       cols←⎕NEW¨(⍴headers)⍴Column              ⍝ Instantiate the Columns
 230       cols.Culture←cultureInfo                 ⍝ Set the Culture for each columns for proper parsing
 231       cols.Name←colNames                       ⍝ Set the Columns Names
 232       cols.Type←⍎¨colTypes                     ⍝ Set the Columns Types
 233       csv.Columns.Add¨cols                     ⍝ Set all the Columns previously constructed
 234      
 235     ⍝ Cronstruct the DataTable from the CsvReader
 236       dt←⎕NEW DataTable
 237       dt.TableName←fileName
 238       dt.Load csv
 239      
 240     ⍝ ↓↓↓ Uncomment to see the DataType of each column(s).
 241     ⍝ (⌷dt.Columns).DataType
 242      
 243     ⍝ Clean-up
 244       streamReader.Close ⋄ streamReader.Dispose ⋄ streamReader←⎕NULL
 245       ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL
 246       csv.Dispose ⋄ csv←⎕NULL
 247 
 248 
 249 
 250     ∇ noRows←dt DTtoCsvFile fileName;application;excelEngine;fieldDelimiter;workbooks;⎕USING
 251     ⍝ Convert a DataTable to a CSV file.
 252     ⍝ Using the library of Syncfusion XlsIO.
 253     ⍝ It is using the Decimal Separator of the local culture.
 254 
 255     ⍝ fileName = fully qualified CSV file name with extension (could be different than .csv)
 256     ⍝ dt       = DataTable with columns as DateTime, String or Double types.
 257     ⍝ noRows   = Number of rows written to fileName.
 258      
 259       ⎕USING←'Syncfusion.XlsIO,Syncfusion/4.5/Syncfusion.XlsIO.Base.dll' 'System.Text,mscorlib.dll'
 260      
 261     ⍝ Default fieldDelimiter
 262       fieldDelimiter←,','
 263      
 264     ⍝ Instantiate the spreadsheet creation engine.
 265       excelEngine←⎕NEW ExcelEngine
 266      
 267     ⍝ Instantiate the excel application object.
 268       application←excelEngine.Excel
 269       application.DefaultVersion←application.DefaultVersion.Excel2013
 270      
 271     ⍝ Create one worksheet
 272       workbooks←application.Workbooks.Create 1
 273      
 274     ⍝ Import the DataTable to the worksheet
 275       noRows←workbooks.Worksheets[0].ImportDataTable dt 1 1 1 1 ⍝ DataTable, KeepHeader, FirstRow, FirstColumn, PreserveType
 276      
 277     ⍝ Save as CSV file with the UTF-8 format.
 278       workbooks.Worksheets[0].SaveAs(fileName fieldDelimiter Encoding.UTF8)
 279      
 280     ⍝ Clean-up
 281       workbooks.Close ⍬
 282       excelEngine.ThrowNotSavedOnDestroy←0
 283       excelEngine.Dispose
 284 
 285 
 286 
 287     ∇ dataType←culture DetectDataType string;dateStyle;numberStyle;ptr;⎕USING
 288     ⍝ Detect the DataType of 'string' using CultureInfo
 289     ⍝ The 3 types detected are: DateTime, Double and String
 290 
 291     ⍝ string  = vector of characters
 292     ⍝ culture = CultureInfo object
 293      
 294       ⎕USING←'System,mscorlib.dll' 'Dyalog' 'System.Globalization,mscorlib.dll'
 295      
 296       dateStyle←Globalization.DateTimeStyles.None
 297       numberStyle←culture.NumberStyles.Any
 298      
 299     ⍝ Test to detect if 'string' is a Double
 300       ptr←⎕NEW ByRef(0)
 301       :If 1=Double.TryParse((,string)numberStyle culture ptr)
 302         ⍝ Success
 303           dataType←'Double' ⋄ →0
 304       :EndIf
 305      
 306     ⍝ Test to detect if 'string' is a DateTime
 307       ptr←⎕NEW ByRef(⎕NEW DateTime ⎕TS)
 308       :If 1=DateTime.TryParse((,string)culture dateStyle ptr)
 309         ⍝ Success
 310           dataType←'DateTime' ⋄ →0
 311       :EndIf
 312      
 313     ⍝ Default value if DateTime or Double are not detected
 314       dataType←'String'
 315 
 316 
 317 
 318     ∇ ShowDT dt;dg;win;⎕USING
 319     ⍝ Show a DataTable in a Syncfusion's Grid
 320     ⍝ dt = DataTable to Show
 321      
 322       ⎕USING←'System.Windows,WPF/PresentationFramework.dll'
 323       ⎕USING,←⊂'Syncfusion.UI.Xaml.Grid,Syncfusion/4.5/Syncfusion.SfGrid.WPF.dll'
 324      
 325       win←⎕NEW Window
 326       win.(Width Height)←640 480
 327       win.Title←'Show DataTable [ ',(dt.TableName),' ]'
 328      
 329       dg←⎕NEW SfDataGrid
 330       dg.AutoGenerateColumns←1
 331       dg.ItemsSource←dt           ⍝ ← the DataTable is set here
 332       dg.AllowResizingColumns←1
 333       dg.(ColumnSizer←ColumnSizer.Star)
 334       dg.AllowEditing←1
 335      
 336       win.Content←dg
 337       win.Show
 338 
 339 
 340 
 341     ∇ dt←{fieldSeparator}SimpleCsvFileToDT fileName;bufferSize;comment;csv;escape;hasHeaders;nullValue;quote;streamReader;trimmingOptions;⎕USING;ms
 342     ⍝ Simple CSV File parser to a DataTable where all the DataColumns are of DataType 'String'
 343     ⍝ Based on: http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader
 344     ⍝ and https://github.com/phatcher/CsvReader
 345     ⍝ The assembly LumenWorks.Framework.IO.dll needs to be in the same directory as Dyalog.exe
 346 
 347     ⍝ fieldSeparator = Typically ',' or ';'
 348     ⍝ fileName       = fully qualified file name with extension
 349 
 350     ⍝ Note: The CSV file must have a Header record, it will be used to give the names to the DataColumns.
 351      
 352       ⎕USING←'System.IO,mscorlib.dll' 'LumenWorks.Framework.IO.Csv,LumenWorks.Framework.IO.dll' 'System.Data,System.Data.dll'
 353      
 354       :If 0=⎕NC'fieldSeparator'
 355           fieldSeparator←','   ⍝ Default value if absent
 356       :End
 357      
 358     ⍝ Set-up those options before constructing the CsvReader
 359       hasHeaders←1
 360       quote←'"'
 361       escape←'"'
 362       comment←'#' ⍝ First character of a record that will not be parse
 363       trimmingOptions←1 ⍝ 0=None, 1=Unquoted Only, 2=Quoted Only, 3=All
 364       bufferSize←4096
 365       nullValue←⊂''
 366      
 367     ⍝ Construct the StreamReader
 368     ⍝ Using a MemoryStream will not block the file to being written.
 369       ms←⎕NEW MemoryStream(⊂File.ReadAllBytes(⊂,fileName))
 370       streamReader←⎕NEW StreamReader(ms)
 371 ⍝     streamReader←⎕NEW StreamReader(⊂,fileName)
 372      
 373     ⍝ Construct the CsvReader
 374       csv←⎕NEW CsvReader(streamReader,hasHeaders,fieldSeparator,quote,escape,comment,trimmingOptions,bufferSize,nullValue)
 375       csv.MissingFieldAction←csv.MissingFieldAction.ReplaceByNull
 376       csv.DefaultParseErrorAction←csv.DefaultParseErrorAction.AdvanceToNextLine
 377       csv.SkipEmptyLines←1
 378       csv.SupportsMultiline←1
 379      
 380     ⍝ Create the DataTable from the CsvReader
 381       dt←⎕NEW DataTable
 382       dt.TableName←fileName
 383       dt.Load csv
 384      
 385     ⍝ Clean-up
 386       streamReader.Close ⋄ streamReader.Dispose ⋄ streamReader←⎕NULL
 387       ms.Close ⋄ ms.Dispose ⋄ ms←⎕NULL
 388       csv.Dispose ⋄ csv←⎕NULL
 389 
 390 
 391 :EndNamespace

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2016-02-07 13:38:03, 0.7 KB) [[attachment:Client.csv]]
  • [get | view] (2016-02-07 13:24:16, 34.8 KB) [[attachment:Client.png]]
  • [get | view] (2016-02-09 22:08:03, 4027.0 KB) [[attachment:FL_insurance_sample.csv]]
  • [get | view] (2016-02-06 13:49:06, 45.0 KB) [[attachment:LumenWorks.Framework.IO.dll]]
  • [get | view] (2016-02-07 14:39:38, 137.9 KB) [[attachment:ZipCode.csv]]
  • [get | view] (2016-02-07 14:39:58, 54.9 KB) [[attachment:ZipCode.png]]
  • [get | view] (2016-02-07 14:13:44, 10.7 KB) [[attachment:msft.csv]]
  • [get | view] (2016-02-07 14:18:30, 53.4 KB) [[attachment:msft.png]]
  • [get | view] (2016-02-10 03:02:48, 16.0 KB) [[attachment:netCSV.v1.0.txt]]
  • [get | view] (2016-04-29 13:48:55, 16.9 KB) [[attachment:netCSV.v1.1.txt]]
 All files | Selected Files: delete move to page

You are not allowed to attach a file to this page.