;;  
;;=====================================================================================----- 
;;  
;;FUNCTION       csv()  
;;  
;;ACTION         Converts between CSV record and array  
;;  
;;AUTHOR         Glenn Barnas   
;;  
;;VERSION	 1.4  - 2020/08/09 
;; 
;;HISTORY        1.0  - 2005/02/19 - Initial Release 
;;               1.1  - 2006/12/06 - added @ERROR test so when used as $X=csv(ReadLine(2))  
;;                                   the error from the embedded ReadLine would be acted upon.  
;;		 1.2  - 2010/07/28 - Added a flag to ignore the @ERROR, as calling CSV with   
;;		                     an error condition set would return immediately. 
;;		 1.3  - 2014/01/28 - Added a trap for embedded arrays in fields that will convert 
;;                                   to delimited text 
;;               1.4  - 2020/08/09 - Added option to specify the delimiter. NOTE - changing the 
;;                                   delimiter invalidates the CSV specification. 
;;  
;;SYNTAX         csv(Record [, IgnoreErr] [, DelimChar])  
;;  
;;PARAMETERS     Record - REQUIRED - String or Array 
;;               - the data to be converted. 
;;                      If String - returns array of fields  
;;                      If Array - returns comma-delimited string  
;;                      Fields are delimited with commas. If a field contains a  
;;                      comma, that field is enclosed in double-quotes (")  
;;  
;;		 IgnoreErr - Optional - boolean 
;;               - flag that, when set, ignores the active @ERROR status  
;; 
;;               DelimChar - Optional - Char 
;;               - Specify an alternate delimiter character - INVALIDATES CSV STANDARD 
;;  
;;REMARKS        Converts between CSV text and an array. If an embedded array is found,  
;;		 it will be converted to a delimited string, using a Chr(31) (Unit Separator) 
;;               as a delimiter. 
;;  
;;RETURNS        CSV format string or array of fields  
;;  
;;DEPENDENCIES   none  
;;  
;;TESTED WITH    NT4, W2K, WXP  
;;  
;;EXAMPLES       ; Load an array from a CSV record 
;;               $Array = CSV('this,that,"a,whole,lot,of,things"') 
;;               ; create a CSV record from an array 
;;               $Ary = 'that','this','several,common,things' 
;;               $Record = CSV($Ary) 
;;                
;  
Function CSV($_Record, OPTIONAL $_Ignore, $_Delim)
 
  ; Handle embedded ReadLine errors passed to this wrapper func  
  If @ERROR And Not $_Ignore Exit @ERROR EndIf
 
  Dim $_C, $_D, $_DF, $_F, $_I, $_L, $_Q, $_QC, $_QP, $_QT, $_Tmp
 
  $_D = Chr(5)					                        ; invisible delimiter  
  $_Q = Chr(4)					                        ; invisible quote  
  $_DF = 0					                        ; Delimiter status  
  $_Tmp = ''
  If Not $_Delim
    $_Delim = ','                                                       ; default to comma delimiter 
  EndIf
 
  If VarType($_Record) > 8191			                        ; have array, convert to record  
 
    For $_F = 0 to UBound($_Record)
      
      If VarType($_Record[$_F]) > 8191		                        ; have array in field - convert to delimited string 
        $_Record[$_F] = Join($_Record[$_F], Chr(31))
      EndIf
 
      $_Tmp = ''
      ; Convert embedded quotes to double quotes  
      $_L = Len($_Record[$_F])
      For $_I = 1 to $_L
        $_C = SubStr($_Record[$_F], $_I, 1)
        $_Tmp = $_Tmp + $_C
        If $_C = '"' $_Tmp = $_Tmp + '"' EndIf
      Next
      $_Record[$_F] = $_Tmp
 
      ; encase field in quotes if needed  
      If InStr($_Record[$_F], $_Delim) Or InStr($_Record[$_F], '"')
        $_Record[$_F] = '"' + $_Record[$_F] + '"'
      EndIf
      If $_F < UBound($_Record)			                        ; add ',' to all but last field  
        $_Record[$_F] = $_Record[$_F] + $_Delim
      EndIf
      $CSV = $CSV + $_Record[$_F]			                ; create the output record  
    Next
 
  Else						                        ; have record, convert to array  
 
    ; Handle embedded quotes  
    ; Triple quotes - have to handle leading vs trailing  
    $_QC = 1
    $_QT = 0
    While $_QC
      $_QP = InStr($_Record, '"""')
      If $_QP > 0
	If $_QT = 0
	  $_Record = Left($_Record, $_QP) + $_Q + SubStr($_Record, $_QP + 3)
          $_QT = Not $_QT
	Else
	  $_Record = Left($_Record, $_QP - 1) + $_Q  + SubStr($_Record, $_QP + 2)
          $_QT = Not $_QT
        EndIf
      Else
	$_QC = 0
      EndIf
    Loop
 
    ; double quotes - become single quotes in the data field  
    $_QC = 1
    While $_QC
      $_QP = InStr($_Record, '""')
      If $_QP > 0
	$_Record = Left($_Record, $_QP - 1) + $_Q + SubStr($_Record, $_QP + 2)
      Else
	$_QC = 0
      EndIf
    Loop
 
    $_L = Len($_Record)
    For $_I = 1 to $_L
      $_C = SubStr($_Record, $_I, 1)
      Select
        Case $_C = '"'				                        ; quoted data, (re)set flag  
          $_DF = Not($_DF)
        Case $_C = $_Delim And Not $_DF		                        ; valid delimiter, add special delimiter to string  
          $_Tmp = $_Tmp + $_D
        Case 1					                        ; normal data, add character to string  
          $_Tmp = $_Tmp + $_C
      EndSelect
    Next
 
    $CSV = Split(Join(Split($_Tmp, $_Q), '"'), $_D)                     ; prepare to return the array  
 
  EndIf
 
EndFunction