# Munge A set of functions that enable you to get blocks of tabular (row and column) data from a variety of sources, manipulate the data in various ways, then store the result as a Rebol/Red block or even save back as a [CSV](https://en.wikipedia.org/wiki/Comma-separated_values), [tab-delimited](https://en.wikipedia.org/wiki/Delimiter-separated_values) or [Excel](https://en.wikipedia.org/wiki/Microsoft_Excel) file! ## Getting started Download [munge3.r](http://dobeash.com/files/munge3.r), then from a Rebol or Red console: <pre> >> do %munge3.r >> ctx-munge/list [1 2 3] == [ 1 2 3 ] </pre> Alternatively, you can selectively export functions to the global context: <pre> >> ctx-munge/export [list munge] </pre> Or export all functions with: <pre> >> ctx-munge/export bind words-of ctx-munge 'self </pre> ### Windows-specific functions The following functions are windows-specific and are set to `none` on non-windows platforms: * call-oledb * load-excel * sheets? * sqlcmd In addition, the `/sheet` refinement of the following functions are not available on non-windows platforms: * cols? * fields? ## Data Structure Rows are represented as blocks of data within a "table" block. <pre> >> load-dsv "a,1^/b,2" == [["a" "1"] ["b" "2"]] </pre> ## Reading files ### Delimiter Separated Values (DSV) <pre> >> load-dsv %file.csv >> load-dsv/part %file.csv 1 >> load-dsv/part %file.csv [1 2] >> load-dsv/where %file.csv [row/1 = 1] </pre> ### Excel <pre> >> load-excel %file.xlsx 'Sheet1 >> load-excel/part %file.xlsx 'Sheet1 1 >> load-excel/part %file.xlsx 'Sheet1 [1 2] >> load-excel/where %file.xlsx 'Sheet1 "F1 = 1" </pre> This only works on Windows and requires the [Microsoft Access Database Engine 2010 Redistributable](https://www.microsoft.com/en-au/download/details.aspx?id=13255) to first be installed. ### PDF <pre> >> read-pdf %file.pdf >> read-pdf/lines %file.pdf </pre> This requires the [pdftotext command-line shell](http://www.foolabs.com/xpdf/download.html) program to be in the same folder as `munge3.r`. ## Writing files ### DSV <pre> >> write-dsv %file.csv block >> write-dsv %file.txt block </pre> ### Excel <pre> >> write-excel %file.xlsx ["Sheet1" [[a b][1 2]] [5 10]] >> write-excel/filter %file.xlsx ["Sheet1" [[a b][1 2]] [5 10]] </pre> ## Querying databases ### SQL Server <pre> >> sqlcmd sn db "SELECT * FROM TABLE" >> sqlcmd/headings sn db "SELECT * FROM TABLE" </pre> This only works on Windows and requires the [Microsoft Command Line Utilities for SQL Server](https://www.microsoft.com/en-us/download/details.aspx?id=53591) to first be installed. ### SQLite <pre> >> sqlite %file.db "SELECT * FROM TABLE" >> sqlite/headings %file.db "SELECT * FROM TABLE" </pre> This requires the [SQLite command-line shell](http://sqlite.org/download.html) program to be available. For Windows this means `sqlite3.exe` must be downloaded and placed in the same folder as `munge3.r`, whilst for other platforms (e.g. macOS) it comes pre-installed with the OS. ## Munging blocks The main function, `munge`, is typically used to manipulate blocks of data retrieved from files and databases. ### /where The `/where` refinement lets you specify a block of Rebol conditions (wrapped within an `all` block) that can reference row values as `row/1`, `row/2`, etc). <pre> >> munge/where data [row/1 = 1] >> munge/delete/where data [row/1 > 1 row/1 < 10] >> munge/update/where data [1 row/2] [any [row/1 < 5 row/1 > 10]] </pre> Alternatively, if the data is sorted a key value may be specified. The key value does not need to be unique, but it must be the first value of each row retrieved. <pre> >> sort data >> munge/where data 1 >> munge/delete/where data 1 >> munge/update/where data [1 row/2] 1 </pre> This initiates a [binary search](https://en.wikipedia.org/wiki/Binary_search_algorithm) that can be thousands of times faster than a block predicate. ### /update The `/update` refinement lets you specify a block of offset/value pairs where the value can also be a row reference or `block!`. <pre> >> munge/update [[0]] [1 1] == [[1]] >> munge/update [["0"]] [1 integer!] == [[0]] >> munge/update [[0]] [1 now/year] == [[2017]] >> munge/update [[0]] [1 [row/1 + 1]] == [[1]] </pre> # ctx-munge ##append-column <pre> USAGE: append-column block value /header heading DESCRIPTION: Append a column of values to a block. append-column is of type: function! ARGUMENTS: block [block!] value REFINEMENTS: /header heading </pre> ##ascii-file? <pre> USAGE: ascii-file? file DESCRIPTION: Returns TRUE if file is ASCII. ascii-file? is of type: function! ARGUMENTS: file [file!] </pre> ##average-of <pre> USAGE: average-of block DESCRIPTION: Average of values in a block. average-of is of type: function! ARGUMENTS: block [block!] </pre> ##call-oledb <pre> USAGE: call-oledb file cmd /hdr DESCRIPTION: Call OLEDB via PowerShell returning STDOUT. call-oledb is of type: function! ARGUMENTS: file [file!] cmd [string!] REFINEMENTS: /hdr => First row contains columnnames not data. </pre> ##call-out <pre> USAGE: call-out cmd DESCRIPTION: Call OS command returning STDOUT. call-out is of type: function! ARGUMENTS: cmd [string!] </pre> ##check <pre> USAGE: check data DESCRIPTION: Verify data structure. check is of type: function! ARGUMENTS: data [block!] </pre> ##cols? <pre> USAGE: cols? data /with delimiter /sheet name DESCRIPTION: Number of columns in a delimited file or string. cols? is of type: function! ARGUMENTS: data [file! binary! string!] REFINEMENTS: /with delimiter [char!] /sheet => Excel worksheet name (default is "Sheet 1"). name [string! word!] </pre> ##delimiter? <pre> USAGE: delimiter? data DESCRIPTION: Probable delimiter, with priority given to tab, bar, tilde, semi-colon then comma. delimiter? is of type: function! ARGUMENTS: data [file! string!] </pre> ##digit <pre>digit is a bitset! of value: make bitset! #{000000000000FFC0} </pre> ##digits? <pre> USAGE: digits? data DESCRIPTION: Returns TRUE if data not empty and only contains digits. digits? is of type: function! ARGUMENTS: data [string! binary!] </pre> ##distinct <pre> USAGE: distinct data DESCRIPTION: Remove duplicate and empty rows. distinct is of type: function! ARGUMENTS: data [block!] </pre> ##enblock <pre> USAGE: enblock data cols DESCRIPTION: Convert a block of values to a block of row blocks. enblock is of type: function! ARGUMENTS: data [block!] cols [integer!] </pre> ##export <pre> USAGE: export words DESCRIPTION: Export words to global context. export is of type: function! ARGUMENTS: words [block!] => Words to export. </pre> ##fields? <pre> USAGE: fields? data /with delimiter /sheet name DESCRIPTION: Column names in a delimited file or string. fields? is of type: function! ARGUMENTS: data [file! string!] REFINEMENTS: /with delimiter [char!] /sheet => Excel worksheet name (default is "Sheet 1"). name [string! word!] </pre> ##first-line <pre> USAGE: first-line data DESCRIPTION: Returns the first non-empty line of a file. first-line is of type: function! ARGUMENTS: data [file! string!] </pre> ##flatten <pre> USAGE: flatten data DESCRIPTION: Flatten nested block(s). flatten is of type: function! ARGUMENTS: data [block!] </pre> ##latin1-to-utf8 <pre> USAGE: latin1-to-utf8 data DESCRIPTION: Latin1 binary to UTF-8 string conversion. latin1-to-utf8 is of type: function! ARGUMENTS: data [binary!] </pre> ##letter <pre>letter is a bitset! of value: make bitset! #{00000000000000007FFFFFE07FFFFFE0} </pre> ##letters? <pre> USAGE: letters? data DESCRIPTION: Returns TRUE if data only contains letters. letters? is of type: function! ARGUMENTS: data [string! binary!] </pre> ##like <pre> USAGE: like series value DESCRIPTION: Finds a value in a series, expanding * (any characters) and ? (any one character), and returns TRUE if found. like is of type: function! ARGUMENTS: series [any-string!] => Series to search. value [any-string! block!] => Value to find. </pre> ##list <pre> USAGE: list data DESCRIPTION: Sets the new-line marker to end of block. list is of type: function! ARGUMENTS: data [block!] </pre> ##load-dsv <pre> USAGE: load-dsv source /part columns /preserve /ignore /where condition /with delimiter DESCRIPTION: Parses delimiter-separated values into row blocks. load-dsv is of type: function! ARGUMENTS: source [file! binary! string!] REFINEMENTS: /part => Offset position(s) to retrieve. columns [block! integer!] /preserve => keep line breaks and extra spaces. /ignore => Ignore truncated row errors. /where => Expression that can reference columns as f1, f2, etc. condition [block!] /with => Alternate delimiter (default is tab, bar then comma). delimiter [char!] </pre> ##load-excel <pre> USAGE: load-excel file sheet /part columns /where condition /distinct /string DESCRIPTION: Loads an Excel file. load-excel is of type: function! ARGUMENTS: file [file!] sheet [integer! word! string!] REFINEMENTS: /part => Offset position(s) / columns(s) to retrieve. columns [block! integer!] /where => Expression that can reference columns as F1, F2, etc. condition [string!] /distinct /string </pre> ##max-of <pre> USAGE: max-of series DESCRIPTION: Returns the largest value in a series. max-of is of type: function! ARGUMENTS: series [series!] => Series to search. </pre> ##merge <pre> USAGE: merge outer key1 inner key2 columns /default DESCRIPTION: Join outer block to inner block on primary key. merge is of type: function! ARGUMENTS: outer [block!] => Outer block. key1 [integer!] inner [block!] => Inner block to index. key2 [integer!] columns [block!] => Offset position(s) to retrieve in merged block. REFINEMENTS: /default => Use none on inner block misses. </pre> ##min-of <pre> USAGE: min-of series DESCRIPTION: Returns the smallest value in a series. min-of is of type: function! ARGUMENTS: series [series!] => Series to search. </pre> ##mixedcase <pre> USAGE: mixedcase string DESCRIPTION: Converts string of characters to mixedcase. mixedcase is of type: function! ARGUMENTS: string [string!] </pre> ##munge <pre> USAGE: munge data /update action /delete /part columns /where condition /group having DESCRIPTION: Load and/or manipulate a block of tabular (column and row) values. munge is of type: function! ARGUMENTS: data [block!] REFINEMENTS: /update => Offset/value pairs (returns original block). action [block!] /delete => Delete matching rows (returns original block). /part => Offset position(s) to retrieve. columns [block! integer!] /where => Expression that can reference columns as f1, f2, etc. condition /group => One of count, max, min or sum. having [word! block!] => Word or expression that can reference the initial result set column as count, max, etc. </pre> ##oledb-file? <pre> USAGE: oledb-file? file DESCRIPTION: Returns true for an Excel or Access file. oledb-file? is of type: function! ARGUMENTS: file [file!] </pre> ##read-pdf <pre> USAGE: read-pdf file /lines DESCRIPTION: Reads from a PDF file. read-pdf is of type: function! ARGUMENTS: file [file!] REFINEMENTS: /lines => Handles data as lines. </pre> ##read-string <pre> USAGE: read-string data /lines DESCRIPTION: Read string(s) from a text file. read-string is of type: function! ARGUMENTS: data [file! binary!] REFINEMENTS: /lines => Convert to block of strings. </pre> ##remove-column <pre> USAGE: remove-column block index DESCRIPTION: Remove a column of values from a block. remove-column is of type: function! ARGUMENTS: block [block!] index [integer!] </pre> ##replace-deep <pre> USAGE: replace-deep data search new DESCRIPTION: Replaces all occurences of a search value with the new value in a block or nested block. replace-deep is of type: function! ARGUMENTS: data [block!] => Block to replace within (modified). search => Value to be replaced. new </pre> ##rows? <pre> USAGE: rows? data DESCRIPTION: Number of rows in a delimited file or string. rows? is of type: function! ARGUMENTS: data [file! binary! string!] </pre> ##sheets? <pre> USAGE: sheets? file DESCRIPTION: Excel sheet names. sheets? is of type: function! ARGUMENTS: file [file!] </pre> ##split-line <pre> USAGE: split-line line delimiter DESCRIPTION: Splits and returns line of text as a block. split-line is of type: function! ARGUMENTS: line [string!] delimiter [char!] </pre> ##sqlcmd <pre> USAGE: sqlcmd server database statement /key columns /headings /string DESCRIPTION: Execute a SQL Server statement. sqlcmd is of type: function! ARGUMENTS: server [string!] database [string!] statement [string!] REFINEMENTS: /key => Columns to convert to integer. columns [integer! block!] /headings => Keep column headings. /string </pre> ##sqlite <pre> USAGE: sqlite database statement /key columns /headings /string DESCRIPTION: Execute a SQLite statement. sqlite is of type: function! ARGUMENTS: database [file!] statement [string!] REFINEMENTS: /key => Columns to convert to integer. columns [integer! block!] /headings => Keep column headings. /string </pre> ##sum-of <pre> USAGE: sum-of block DESCRIPTION: Sum of values in a block. sum-of is of type: function! ARGUMENTS: block [block!] </pre> ##to-column-alpha <pre> USAGE: to-column-alpha number DESCRIPTION: Convert numeric column reference to an alpha column reference. to-column-alpha is of type: function! ARGUMENTS: number [integer!] => Column number between 1 and 702. </pre> ##to-column-number <pre> USAGE: to-column-number alpha DESCRIPTION: Convert alpha column reference to a numeric column reference. to-column-number is of type: function! ARGUMENTS: alpha [word! string! char!] </pre> ##to-rebol-date <pre> USAGE: to-rebol-date date /mdy /ydm /day DESCRIPTION: Convert a string date to a Rebol date. to-rebol-date is of type: function! ARGUMENTS: date [string!] REFINEMENTS: /mdy => Month/Day/Year format. /ydm => Year/Day/Month format. /day => Day precedes date. </pre> ##to-rebol-time <pre> USAGE: to-rebol-time time DESCRIPTION: Convert a string date/time to a Rebol time. to-rebol-time is of type: function! ARGUMENTS: time [string!] </pre> ##to-string-date <pre> USAGE: to-string-date date /mdy /ydm DESCRIPTION: Convert a string or Rebol date to a YYYY-MM-DD string. to-string-date is of type: function! ARGUMENTS: date [string! date!] REFINEMENTS: /mdy => Month/Day/Year format. /ydm => Year/Day/Month format. </pre> ##to-string-time <pre> USAGE: to-string-time time DESCRIPTION: Convert a string or Rebol time to a HH.MM.SS string. to-string-time is of type: function! ARGUMENTS: time [string! date! time!] </pre> ##write-dsv <pre> USAGE: write-dsv file data DESCRIPTION: Write block(s) of values to a delimited text file. write-dsv is of type: function! ARGUMENTS: file [file!] => csv or tab-delimited text file. data [block!] </pre> ##write-excel <pre> USAGE: write-excel file data /filter DESCRIPTION: Write block(s) of values to an Excel file. write-excel is of type: function! ARGUMENTS: file [file!] data [block!] => Name [string!] Data [block!] Widths [block!] records. REFINEMENTS: /filter => Add auto filter. </pre> # Tests |#|Test|Result| |-:|-|-| |1|append-column [[a] [1]] 2|[[a 2] [1 2]]| |2|append-column/header [[a] [1]] 2 'b|[[a b] [1 2]]| |3|ascii-file? %test.r|true| |4|ascii-file? %test.xlsx|false| |5|average-of []|none| |6|average-of [1 2]|1.5| |7|call-oledb %test.xlsx "echo munge"|"munge"| |8|call-out {sqlite3.exe a.db ""}|""| |9|check []|true| |10|check [[1]]|true| |11|cols? ""|0| |12|cols? ","|2| |13|cols? "a,b"|2| |14|cols? "a^-b"|2| |15|cols? "a&#124;b"|2| |16|cols? "a~b"|2| |17|cols? "a;b"|2| |18|cols?/with ":" #":"|2| |19|cols? %test.xlsx|2| |20|cols?/sheet %test.xlsx 'x|0| |21|cols?/sheet %test.xlsx 'S1|2| |22|cols?/sheet %test.xlsx "S 2"|2| |23|delimiter? ""|#","| |24|delimiter? "a"|#","| |25|delimiter? "^-"|#"^-"| |26|delimiter? "&#124;"|#"&#124;"| |27|delimiter? "~"|#"~"| |28|delimiter? ";"|#";"| |29|digit|make bitset! #{000000000000FFC0}| |30|digits? ""|none| |31|digits? "a"|none| |32|digits? "1"|true| |33|distinct [["" ""] [a 1]]|[[a 1]]| |34|distinct [[none none] [a 1]]|[[a 1]]| |35|distinct [[a] [a]]|[[a]]| |36|distinct [[a 1] [a 1]]|[[a 1]]| |37|enblock [1 2 3 4] 1|[[1] [2] [3] [4]]| |38|enblock [1 2 3 4] 2|[[1 2] [3 4]]| |39|export []|[]| |40|export [distinct]|[distinct]| |41|export [cols? rows?]|[cols? rows?]| |42|fields? ""|[]| |43|fields? ","|["" ""]| |44|fields? "a,b"|["a" "b"]| |45|fields? "a:b"|["a:b"]| |46|fields? {"a","b"}|["a" "b"]| |47|fields? {"a" ,"b"}|["a" "b"]| |48|fields? {"a", "b"}|["a" "b"]| |49|fields?/with "a:b" #":"|["a" "b"]| |50|fields? %test.xlsx|["c" "3"]| |51|fields?/sheet %test.xlsx 'x|[]| |52|fields?/sheet %test.xlsx 'S1|["a" "1"]| |53|fields?/sheet %test.xlsx "S 2"|["c" "3"]| |54|first-line ""|""| |55|first-line "a,1"|"a,1"| |56|first-line "^/a,1"|"a,1"| |57|first-line "a,1^/"|"a,1"| |58|flatten []|[]| |59|flatten [[a] [b]]|[a b]| |60|flatten [[a 1] [b 2]]|[a 1 b 2]| |61|latin1-to-utf8 #{}|""| |62|latin1-to-utf8 #{00}|""| |63|latin1-to-utf8 #{C2A0}|" "| |64|latin1-to-utf8 #{FC}|"ΓΌ"| |65|letter|make bitset! #{00000000000000007FFFFFE07FFFFFE0}| |66|letters? ""|true| |67|letters? "a"|true| |68|letters? "1"|false| |69|like "" ""|none| |70|like %abc %a|true| |71|like %abc %*a|true| |72|like %abc %?a|false| |73|like %abc %b|false| |74|like %abc %*b|true| |75|like %abc %?b|true| |76|like %abc %a?c|true| |77|like %abc %a?b|false| |78|like %abc %a*c|true| |79|like %abc %a*b|true| |80|list []|[]| |81|list [a b]|[a b]| |82|list [[a] [b]]|[[a] [b]]| |83|load-dsv ""|[]| |84|load-dsv ","|[]| |85|load-dsv {" a^/b" }|[["a b"]]| |86|load-dsv/preserve {" a^/b" }|[[" a^/b "]]| |87|load-dsv "a,"|[["a" ""]]| |88|load-dsv/part "a,b,c" 1|[["a"]]| |89|load-dsv/part "a,b,c" [1]|[["a"]]| |90|load-dsv/part "a,b,c" [3 1]|[["c" "a"]]| |91|load-dsv "a,1^/b,2"|[["a" "1"] ["b" "2"]]| |92|load-dsv/where "a,1^/b,2" [row/1 = "a"]|[["a" "1"]]| |93|load-dsv "a:b"|[["a:b"]]| |94|load-dsv/with "a:b" #":"|[["a" "b"]]| |95|load-excel %test.xlsx 2|[["a" "1"] ["b" "2"]]| |96|load-excel %test.xlsx 'S1|[["a" "1"] ["b" "2"]]| |97|load-excel %test.xlsx "S1"|[["a" "1"] ["b" "2"]]| |98|load-excel %test.xlsx "S 2"|[["c" "3"] ["d" "4"]]| |99|load-excel/part %test.xlsx "S1" 1|[["a"] ["b"]]| |100|load-excel/part %test.xlsx "S1" [2 1]|[["1" "a"] ["2" "b"]]| |101|load-excel/where %test.xlsx "S1" "F1 = 'a'"|[["a" "1"]]| |102|max-of []|none| |103|max-of [1 2]|2| |104|merge [] 1 [] 1 [1]|[]| |105|merge [[a 1] [b 2]] 2 [[1 "A"]] 1 [1 4]|[[a "A"]]| |106|merge [[a 1]] 2 [[2 1] [1 "A"]] 1 [1 4]|[[a "A"]]| |107|merge/default [[a 1] [b 2]] 2 [[1 "A"]] 1 [1 4]|[[a "A"] [b none]]| |108|min-of []|none| |109|min-of [1 2]|1| |110|mixedcase ""|""| |111|mixedcase "aa"|"Aa"| |112|mixedcase "aa bb"|"Aa Bb"| |113|munge []|[]| |114|munge/where [[a] [a] [b]] 'a|[[a] [a]]| |115|munge [[a 1] [b 2]]|[[a 1] [b 2]]| |116|munge/part [[a 1]] 1|[[a]]| |117|munge/part [[a 1]] [2 1]|[[1 a]]| |118|munge/where [[a 1]] [even? row/2]|[]| |119|munge/where [[a 1]] [odd? row/2]|[[a 1]]| |120|munge/where [[a 1] [a 2] [b 3]] 'a|[[a 1] [a 2]]| |121|munge/update [[a 1]] [1 0]|[[0 1]]| |122|munge/update [[a 1]] [1 row/2]|[[1 1]]| |123|munge/update [[a 1]] [1 string!]|[["a" 1]]| |124|munge/update/where [[a 1]] [1 0] 'a|[[0 1]]| |125|munge/update/where [[a 1]] [1 row/2] 'a|[[1 1]]| |126|munge/update/where [[a 1]] [1 string!] 'a|[["a" 1]]| |127|munge/update/where [[a 1]] [1 0] [row/1 = 'a]|[[0 1]]| |128|munge/update/where [[a 1]] [1 row/2] [row/1 = 'a]|[[1 1]]| |129|munge/update/where [[a 1]] [1 string!] [row/1 = 'a]|[["a" 1]]| |130|munge/delete [[a 1] [b 2]]|[]| |131|munge/delete/where [[a 1] [b 2]] 'a|[[b 2]]| |132|munge/delete/where [[a 1] [b 2]] [row/1 = 'a]|[[b 2]]| |133|munge/group [[1] [2]] 'count|[[1 1] [2 1]]| |134|munge/group [[1] [2]] 'avg|1.5| |135|munge/group [[1] [2]] 'sum|3| |136|munge/group [[1] [2]] 'min|1| |137|munge/group [[1] [2]] 'max|2| |138|munge/group [[a 1] [a 2] [b 3]] 'avg|[[a 1.5] [b 3]]| |139|munge/group [[a 1] [a 2] [b 3]] 'sum|[[a 3] [b 3]]| |140|munge/group [[a 1] [a 2] [b 3]] 'min|[[a 1] [b 3]]| |141|munge/group [[a 1] [a 2] [b 3]] 'max|[[a 2] [b 3]]| |142|oledb-file? %tmp|none| |143|oledb-file? %test.r|none| |144|oledb-file? %test.xls|none| |145|oledb-file? %test.xlsx|true| |146|read-pdf %test.pdf|"a b^/^/1 2"| |147|read-pdf/lines %test.pdf|["a b" "" "1 2"]| |148|write-dsv %a.txt [[1] [2]] read-string %a.txt|"1^/2^/"| |149|read-string/lines %a.txt|["1" "2"]| |150|remove-column [[a 1] [b 2]] 1|[[1] [2]]| |151|remove-column [[a 1] [b 2]] 2|[[a] [b]]| |152|replace-deep [a [a]] 'a 'b|[b [b]]| |153|rows? ""|0| |154|rows? "a"|1| |155|rows? "a^/"|2| |156|sheets? %test.xlsx|["S 2" "S1"]| |157|sheets? %test.accdb|["Table 2" "Table1"]| |158|split-line "" #","|[]| |159|split-line "," #","|["" ""]| |160|sqlcmd sn db "select ''"|[]| |161|sqlcmd sn db "select NULL"|[]| |162|sqlcmd sn db "select 1 where 0 = 1"|[]| |163|sqlcmd sn db "select NULL,NULL"|[]| |164|sqlcmd sn db "select 1,NULL"|[["1" ""]]| |165|sqlcmd sn db "select NULL,1"|[["" "1"]]| |166|sqlcmd sn db "select 0"|[["0"]]| |167|sqlcmd sn db "select 0,1"|[["0" "1"]]| |168|sqlcmd sn db "select 0,''"|[["0" ""]]| |169|sqlcmd/key sn db "select 0" 1|[[0]]| |170|sqlcmd/headings sn db "select 1 A"|[["A"] ["1"]]| |171|sqlite %a.db "select ''"|[]| |172|sqlite %a.db "select NULL"|[]| |173|sqlite %a.db "select 1 where 0 = 1"|[]| |174|sqlite %a.db "select NULL,NULL"|[]| |175|sqlite %a.db "select 1,NULL"|[["1" ""]]| |176|sqlite %a.db "select NULL,1"|[["" "1"]]| |177|sqlite %a.db "select 0"|[["0"]]| |178|sqlite %a.db "select 0,1"|[["0" "1"]]| |179|sqlite %a.db "select 0,''"|[["0" ""]]| |180|sqlite/key %a.db "select 0" 1|[[0]]| |181|sqlite/headings %a.db "select 1 A"|[["A"] ["1"]]| |182|sum-of []|none| |183|sum-of [1 2]|3| |184|to-column-alpha 1|"A"| |185|to-column-alpha 27|"AA"| |186|to-column-number 'A|1| |187|to-column-number "aa"|27| |188|to-rebol-date "01-02-2015"|1-Feb-2015| |189|to-rebol-date/mdy "01-02-2015"|2-Jan-2015| |190|to-rebol-date/day "Mon 01-02-2015"|1-Feb-2015| |191|to-rebol-time "1:00AM"|1:00| |192|to-rebol-time "1:00PM"|13:00| |193|to-rebol-time "1:00 AM"|1:00| |194|to-rebol-time "1:00 PM"|13:00| |195|to-string-date "01-02-67"|"2067-02-01"| |196|to-string-date "01-02-68"|"1968-02-01"| |197|to-string-date 1-Feb-2015|"2015-02-01"| |198|to-string-date "01/02/2015"|"2015-02-01"| |199|to-string-date/mdy "01/02/2015"|"2015-01-02"| |200|to-string-date/ydm "15/02/01"|"2015-01-02"| |201|to-string-date "01-02-2015"|"2015-02-01"| |202|to-string-date/mdy "01-02-2015"|"2015-01-02"| |203|to-string-date/ydm "15-02-01"|"2015-01-02"| |204|to-string-time 1:00|"01.00.00"| |205|to-string-time "1:00PM"|"13.00.00"| |206|write-dsv %a.txt [] read-string %a.txt|""| |207|write-dsv %a.txt [[]] read-string %a.txt|""| |208|write-dsv %a.csv [[a 1] [b 2]] read-string %a.csv|"a,1^/b,2^/"| |209|write-dsv %a.txt [[a 1] [b 2]] read-string %a.txt|"a^-1^/b^-2^/"| |210|write-excel %a.xlsx ["A" [[A B] [1 2]] [5 10]]|%a.xlsx| |211|write-excel/filter %a.xlsx ["A" [[A] [B]] [5]]|%a.xlsx|