# 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, tab-delimited or 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> ## 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 Seperated 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> ### PDF <pre> >> read-pdf %file.pdf >> read-pdf/lines %file.pdf </pre> This requires [pdftotext](http://www.foolabs.com/xpdf/download.html) 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> 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. ## Querying databases ### SQL Server <pre> >> sqlcmd sn db "SELECT * FROM TABLE" >> sqlcmd/headings sn db "SELECT * FROM TABLE" </pre> This will only work on Windows and requires the SQLCMD utility to be installed. ### SQLite <pre> >> sqlite %file.db "SELECT * FROM TABLE" >> sqlite/headings %file.db "SELECT * FROM TABLE" </pre> This requires [sqlite](http://sqlite.org/download.html) to be in the same folder as `munge3.r`. ## 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. # ctx-munge ##append-column <pre>USAGE: APPEND-COLUMN block value DESCRIPTION: Append a column of values to a block. APPEND-COLUMN is a function! value. ARGUMENTS: block [block!] value REFINEMENTS: /header => heading </pre> ##ascii-file? <pre>USAGE: ASCII-FILE? source DESCRIPTION: Returns TRUE if file is ASCII. ASCII-FILE? is a function! value. ARGUMENTS: source [file! url!] </pre> ##average-of <pre>USAGE: AVERAGE-OF block DESCRIPTION: Average of values in a block. AVERAGE-OF is a function! value. ARGUMENTS: block [block!] </pre> ##call-oledb <pre>CALL-OLEDB is a none! value: none </pre> ##call-out <pre>USAGE: CALL-OUT cmd DESCRIPTION: Call OS command returning STDOUT. CALL-OUT is a function! value. ARGUMENTS: cmd [string!] </pre> ##check <pre>USAGE: CHECK data DESCRIPTION: Verify data structure. CHECK is a function! value. ARGUMENTS: data [block!] </pre> ##cols? <pre>USAGE: COLS? data DESCRIPTION: Number of columns in a delimited file or string. COLS? is a function! value. ARGUMENTS: data [file! url! binary! string!] REFINEMENTS: /with => delimiter [char!] </pre> ##delimiter? <pre>USAGE: DELIMITER? data DESCRIPTION: Probable delimiter, with priority given to comma, tab, bar, tilde then semi-colon. DELIMITER? is a function! value. ARGUMENTS: data [file! url! string!] </pre> ##delta <pre>USAGE: DELTA source target DESCRIPTION: Remove source rows that exist in target. DELTA is a function! value. ARGUMENTS: source [block!] target [block!] </pre> ##dezero <pre>USAGE: DEZERO string DESCRIPTION: Remove leading zeroes from string. DEZERO is a function! value. ARGUMENTS: string [string!] </pre> ##digit <pre>DIGIT is a bitset! value: make bitset! #{000000000000FFC0} </pre> ##digits? <pre>USAGE: DIGITS? data DESCRIPTION: Returns TRUE if data not empty and only contains digits. DIGITS? is a function! value. ARGUMENTS: data [string! binary!] </pre> ##distinct <pre>USAGE: DISTINCT data DESCRIPTION: Remove duplicate and empty rows. DISTINCT is a function! value. ARGUMENTS: data [block!] </pre> ##enblock <pre>USAGE: ENBLOCK data cols DESCRIPTION: Convert a block of values to a block of row blocks. ENBLOCK is a function! value. ARGUMENTS: data [block!] cols [integer!] </pre> ##export <pre>USAGE: EXPORT words DESCRIPTION: Export words to global context. EXPORT is a function! value. ARGUMENTS: words [block!] "Words to export". </pre> ##fields? <pre>USAGE: FIELDS? data DESCRIPTION: Column names in a delimited file or string. FIELDS? is a function! value. ARGUMENTS: data [file! url! string!] REFINEMENTS: /with => delimiter [char!] </pre> ##first-line <pre>USAGE: FIRST-LINE data DESCRIPTION: Returns the first non-empty line of a file. FIRST-LINE is a function! value. ARGUMENTS: data [file! url! string!] </pre> ##flatten <pre>USAGE: FLATTEN data DESCRIPTION: Flatten nested block(s). FLATTEN is a function! value. 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 a function! value. ARGUMENTS: data [binary!] </pre> ##letter <pre>LETTER is a bitset! value: make bitset! #{00000000000000007FFFFFE07FFFFFE0} </pre> ##letters? <pre>USAGE: LETTERS? data DESCRIPTION: Returns TRUE if data only contains letters. LETTERS? is a function! value. 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 a function! value. 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 a function! value. ARGUMENTS: data [block!] </pre> ##load-dsv <pre>USAGE: LOAD-DSV source DESCRIPTION: Parses delimiter-separated values into row blocks. LOAD-DSV is a function! value. ARGUMENTS: source [file! url! binary! string!] REFINEMENTS: /part => Offset position(s) to retrieve. columns [block! integer!] /where => Expression that can reference columns as row/1, row/2, etc. condition [block!] /compact => Remove duplicate and empty rows (uses map!). /with => Alternate delimiter (default is tab, bar then comma). delimiter [char!] /preserve => keep line breaks and extra spaces. /ignore => Ignore truncated row errors. </pre> ##load-excel <pre>LOAD-EXCEL is a none! value: none </pre> ##load-fixed <pre>USAGE: LOAD-FIXED file widths DESCRIPTION: Loads fixed-width values from a file. LOAD-FIXED is a function! value. ARGUMENTS: file [file! url!] widths [block!] REFINEMENTS: /part => columns [integer! block!] </pre> ##map-source <pre>USAGE: MAP-SOURCE source target map DESCRIPTION: Maps source columns to target columns. MAP-SOURCE is a function! value. ARGUMENTS: source [file! url! string!] target [block!] map [map!] REFINEMENTS: /verify => Number of column matches expected. columns [integer!] /load => </pre> ##max-of <pre>USAGE: MAX-OF series DESCRIPTION: Returns the largest value in a series. MAX-OF is a function! value. ARGUMENTS: series [series!] "Series to search". </pre> ##merge <pre>USAGE: MERGE outer key1 inner key2 columns DESCRIPTION: Join outer block to inner block on primary key. MERGE is a function! value. 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 a function! value. ARGUMENTS: series [series!] "Series to search". </pre> ##mixedcase <pre>USAGE: MIXEDCASE string DESCRIPTION: Converts string of characters to mixedcase. MIXEDCASE is a function! value. ARGUMENTS: string [string!] </pre> ##munge <pre>USAGE: MUNGE data DESCRIPTION: Load and/or manipulate a block of tabular (column and row) values. MUNGE is a function! value. ARGUMENTS: data [block!] REFINEMENTS: /update => Offset/value pairs (returns original block). action [block!] /delete => Delete matching rows (returns original block). /part => Offset position(s) and/or values to retrieve. columns /where => Expression that can reference columns as row/1, row/2, 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 a function! value. ARGUMENTS: file [file! url!] </pre> ##order <pre>USAGE: ORDER data columns DESCRIPTION: Orders rows by one or more column offsets. ORDER is a function! value. ARGUMENTS: data [block!] columns [block! integer!] "Offset position(s) to order by". REFINEMENTS: /desc => Descending order. </pre> ##penult <pre>USAGE: PENULT string DESCRIPTION: Returns the second last value of a series. PENULT is a function! value. ARGUMENTS: string [series!] </pre> ##read-binary <pre>USAGE: READ-BINARY source DESCRIPTION: Read bytes from a file. READ-BINARY is a function! value. ARGUMENTS: source [file! url!] REFINEMENTS: /part => Reads a specified number of bytes. length [integer!] </pre> ##read-pdf <pre>USAGE: READ-PDF file DESCRIPTION: Reads from a PDF file. READ-PDF is a function! value. ARGUMENTS: file [file! url!] REFINEMENTS: /lines => Handles data as lines. </pre> ##read-string <pre>USAGE: READ-STRING data DESCRIPTION: Read string(s) from a text file. READ-STRING is a function! value. ARGUMENTS: data [file! url! 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 a function! value. 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 a function! value. 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 a function! value. ARGUMENTS: data [file! url! binary! string!] </pre> ##second-last <pre>USAGE: SECOND-LAST string DESCRIPTION: Returns the second last value of a series. SECOND-LAST is a function! value. ARGUMENTS: string [series!] </pre> ##sheets? <pre>SHEETS? is a none! value: none </pre> ##split-line <pre>USAGE: SPLIT-LINE line delimiter DESCRIPTION: Splits and returns line of text as a block. SPLIT-LINE is a function! value. ARGUMENTS: line [string!] delimiter [char!] </pre> ##sqlcmd <pre>SQLCMD is a none! value: none </pre> ##sqlite <pre>USAGE: SQLITE database statement DESCRIPTION: Execute a SQLite statement. SQLITE is a function! value. ARGUMENTS: database [file! url!] 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 a function! value. 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 a function! value. 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 a function! value. ARGUMENTS: alpha [word! string! char!] </pre> ##to-rebol-date <pre>USAGE: TO-REBOL-DATE date DESCRIPTION: Convert a string date to a Rebol date. TO-REBOL-DATE is a function! value. 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 a function! value. ARGUMENTS: time [string!] </pre> ##to-string-date <pre>USAGE: TO-STRING-DATE date DESCRIPTION: Convert a string or Rebol date to a YYYY-MM-DD string. TO-STRING-DATE is a function! value. 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 a function! value. 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 a function! value. ARGUMENTS: file [file! url!] "csv or tab-delimited text file". data [block!] </pre> ##write-excel <pre>USAGE: WRITE-EXCEL file data DESCRIPTION: Write block(s) of values to an Excel file. WRITE-EXCEL is a function! value. ARGUMENTS: file [file! url!] 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;"|#"|"| |27|delimiter? "~"|#"~"| |28|delimiter? ";"|#";"| |29|delta [1 2 3] [2]|[1 3]| |30|delta [[1] [2] [3]] [[2]]|[[1] [3]]| |31|dezero ""|""| |32|dezero "0"|""| |33|dezero "10"|"10"| |34|dezero "01"|"1"| |35|dezero "001"|"1"| |36|digit|make bitset! #{ 000000000000FF03000000000000000000000000000000000000000000000000 }| |37|digits? ""|none| |38|digits? "a"|none| |39|digits? "1"|true| |40|distinct [["" ""] [a 1]]|[[a 1]]| |41|distinct [[none none] [a 1]]|[[a 1]]| |42|distinct [[a] [a]]|[[a]]| |43|distinct [[a 1] [a 1]]|[[a 1]]| |44|enblock [1 2 3 4] 1|[[1] [2] [3] [4]]| |45|enblock [1 2 3 4] 2|[[1 2] [3 4]]| |46|export []|[]| |47|export [distinct]|[distinct]| |48|export [cols? rows?]|[cols? rows?]| |49|fields? ""|[]| |50|fields? ","|["" ""]| |51|fields? "a,b"|["a" "b"]| |52|fields? "a:b"|["a:b"]| |53|fields? {"a","b"}|["a" "b"]| |54|fields? {"a" ,"b"}|["a" "b"]| |55|fields? {"a", "b"}|["a" "b"]| |56|fields?/with "a:b" #":"|["a" "b"]| |57|fields? %test.xlsx|["c" "3"]| |58|fields?/sheet %test.xlsx 'x|[]| |59|fields?/sheet %test.xlsx 'S1|["a" "1"]| |60|fields?/sheet %test.xlsx "S 2"|["c" "3"]| |61|first-line ""|""| |62|first-line "a,1"|"a,1"| |63|first-line "^/a,1"|"a,1"| |64|first-line "a,1^/"|"a,1"| |65|flatten []|[]| |66|flatten [[a] [b]]|[a b]| |67|flatten [[a 1] [b 2]]|[a 1 b 2]| |68|latin1-to-utf8 #{}|""| |69|latin1-to-utf8 #{00}|""| |70|latin1-to-utf8 #{C2A0}|" "| |71|latin1-to-utf8 #{FC}|"�"| |72|letter|make bitset! #{ 0000000000000000FEFFFF07FEFFFF0700000000000000000000000000000000 }| |73|letters? ""|true| |74|letters? "a"|true| |75|letters? "1"|false| |76|like "" ""|none| |77|like %abc %a|true| |78|like %abc %*a|true| |79|like %abc %?a|false| |80|like %abc %b|false| |81|like %abc %*b|true| |82|like %abc %?b|true| |83|like %abc %a?c|true| |84|like %abc %a?b|false| |85|like %abc %a*c|true| |86|like %abc %a*b|true| |87|list []|[]| |88|list [a b]|[a b]| |89|list [[a] [b]]|[[a] [b]]| |90|load-dsv ""|[]| |91|load-dsv ","|[]| |92|load-dsv {" a^/b" }|[["a b"]]| |93|load-dsv/preserve {" a^/b" }|[[" a^/b "]]| |94|load-dsv "a,"|[["a" ""]]| |95|load-dsv/part "a,b,c" 1|[["a"]]| |96|load-dsv/part "a,b,c" [1]|[["a"]]| |97|load-dsv/part "a,b,c" [3 1]|[["c" "a"]]| |98|load-dsv/part "a,b,c" [1 "Y"]|[["a" "Y"]]| |99|load-dsv "a,1^/b,2"|[["a" "1"] ["b" "2"]]| |100|load-dsv/where "a,1^/b,2" [row/1 = "a"]|[["a" "1"]]| |101|load-dsv "a:b"|[["a:b"]]| |102|load-dsv/with "a:b" #":"|[["a" "b"]]| |103|load-excel %test.xlsx 2|[["a" "1"] ["b" "2"]]| |104|load-excel %test.xlsx 'S1|[["a" "1"] ["b" "2"]]| |105|load-excel %test.xlsx "S1"|[["a" "1"] ["b" "2"]]| |106|load-excel %test.xlsx "S 2"|[["c" "3"] ["d" "4"]]| |107|load-excel/part %test.xlsx "S1" 1|[["a"] ["b"]]| |108|load-excel/part %test.xlsx "S1" [2 1]|[["1" "a"] ["2" "b"]]| |109|load-excel/where %test.xlsx "S1" "F1 = 'a'"|[["a" "1"]]| |110|load-fixed %a.txt [1 1]|[["1" "2"] ["3" "4"]]| |111|load-fixed/part %a.txt [1 1] 1|[["1"] ["3"]]| |112|map-source "FIRST-NAME" ["FirstName"] make map! []|[[1 "A" "FIRST-NAME" none]]| |113|map-source "FIRST NAME" ["FirstName"] make map! []|[[1 "A" "FIRST NAME" "FirstName"]]| |114|map-source "A" [] make map! ["A" "GivenName"]|[[1 "A" "A" "GivenName"]]| |115|max-of []|none| |116|max-of [1 2]|2| |117|merge [] 1 [] 1 [1]|[]| |118|merge [[a 1] [b 2]] 2 [[1 "A"]] 1 [1 4]|[[a "A"]]| |119|merge [[a 1]] 2 [[2 1] [1 "A"]] 1 [1 4]|[[a "A"]]| |120|merge/default [[a 1] [b 2]] 2 [[1 "A"]] 1 [1 4]|[[a "A"] [b none]]| |121|min-of []|none| |122|min-of [1 2]|1| |123|mixedcase ""|""| |124|mixedcase "aa"|"Aa"| |125|mixedcase "aa bb"|"Aa Bb"| |126|munge []|[]| |127|munge/where [[a] [a] [b]] 'a|[[a] [a]]| |128|munge [[a 1] [b 2]]|[[a 1] [b 2]]| |129|munge/part [[a 1]] 1|[[a]]| |130|munge/part [[a 1]] [2 1]|[[1 a]]| |131|munge/part [[a 1]] [1 "Y"]|[[a "Y"]]| |132|munge/where [[a 1]] [even? row/2]|[]| |133|munge/where [[a 1]] [odd? row/2]|[[a 1]]| |134|munge/where [[a 1] [a 2] [b 3]] 'a|[[a 1] [a 2]]| |135|munge/update [[a 1]] [1 0]|[[0 1]]| |136|munge/update [[a 1]] [1 row/2]|[[1 1]]| |137|munge/update [[a 1]] [1 string!]|[["a" 1]]| |138|munge/update/where [[a 1]] [1 0] 'a|[[0 1]]| |139|munge/update/where [[a 1]] [1 row/2] 'a|[[1 1]]| |140|munge/update/where [[a 1]] [1 string!] 'a|[["a" 1]]| |141|munge/update/where [[a 1]] [1 0] [row/1 = 'a]|[[0 1]]| |142|munge/update/where [[a 1]] [1 row/2] [row/1 = 'a]|[[1 1]]| |143|munge/update/where [[a 1]] [1 string!] [row/1 = 'a]|[["a" 1]]| |144|munge/delete [[a 1] [b 2]]|[]| |145|munge/delete/where [[a 1] [b 2]] 'a|[[b 2]]| |146|munge/delete/where [[a 1] [b 2]] [row/1 = 'a]|[[b 2]]| |147|munge/group [[1] [2]] 'count|[[1 1] [2 1]]| |148|munge/group [[1] [2]] 'avg|1.5| |149|munge/group [[1] [2]] 'sum|3| |150|munge/group [[1] [2]] 'min|1| |151|munge/group [[1] [2]] 'max|2| |152|munge/group [[a] [b] [a]] [count > 1]|[[a 2]]| |153|munge/group [[a 1] [a 2] [b 3]] 'avg|[[a 1.5] [b 3]]| |154|munge/group [[a 1] [a 2] [b 3]] 'sum|[[a 3] [b 3]]| |155|munge/group [[a 1] [a 2] [b 3]] 'min|[[a 1] [b 3]]| |156|munge/group [[a 1] [a 2] [b 3]] 'max|[[a 2] [b 3]]| |157|oledb-file? %tmp|none| |158|oledb-file? %test.r|none| |159|oledb-file? %test.xls|none| |160|oledb-file? %test.xlsx|true| |161|order [[1 a] [1 b] [2 a] [2 b]] 1|[[1 a] [1 b] [2 a] [2 b]]| |162|order [[1 a] [1 b] [2 a] [2 b]] [1 2]|[[1 a] [1 b] [2 a] [2 b]]| |163|order [[1 a] [1 b] [2 a] [2 b]] [2 1]|[[1 a] [2 a] [1 b] [2 b]]| |164|order/desc [[1 a] [1 b] [2 a] [2 b]] 1|[[2 a] [2 b] [1 a] [1 b]]| |165|order/desc [[1 a] [1 b] [2 a] [2 b]] [1 2]|[[2 b] [2 a] [1 b] [1 a]]| |166|order/desc [[1 a] [1 b] [2 a] [2 b]] [2 1]|[[2 b] [1 b] [2 a] [1 a]]| |167|read-pdf %test.pdf|"a b^/^/1 2"| |168|read-pdf/lines %test.pdf|["a b" "" "1 2"]| |169|write-dsv %a.txt [[1] [2]] read-string %a.txt|"1^/2^/"| |170|read-binary %pdftotext.exe true|true| |171|read-binary/part %pdftotext.exe 2|#{4D5A}| |172|read-string/lines %a.txt|["1" "2"]| |173|remove-column [[a 1] [b 2]] 1|[[1] [2]]| |174|remove-column [[a 1] [b 2]] 2|[[a] [b]]| |175|replace-deep [a [a]] 'a 'b|[b [b]]| |176|rows? ""|0| |177|rows? "a"|1| |178|rows? "a^/"|2| |179|penult []|none| |180|penult [1]|none| |181|penult [1 2]|1| |182|penult [1 2 3]|2| |183|second-last ""|none| |184|second-last "1"|none| |185|second-last "12"|#"1"| |186|second-last "123"|#"2"| |187|sheets? %test.xlsx|["S 2" "S1"]| |188|sheets? %test.accdb|["Table 2" "Table1"]| |189|split-line "" #","|[]| |190|split-line "," #","|["" ""]| |191|sqlcmd sn db "select ''"|[]| |192|sqlcmd sn db "select NULL"|[]| |193|sqlcmd sn db "select 1 where 0 = 1"|[]| |194|sqlcmd sn db "select NULL,NULL"|[]| |195|sqlcmd sn db "select 1,NULL"|[["1" ""]]| |196|sqlcmd sn db "select NULL,1"|[["" "1"]]| |197|sqlcmd sn db "select 0"|[["0"]]| |198|sqlcmd sn db "select 0,1"|[["0" "1"]]| |199|sqlcmd sn db "select 0,''"|[["0" ""]]| |200|sqlcmd/key sn db "select 0" 1|[[0]]| |201|sqlcmd/headings sn db "select 1 A"|[["A"] ["1"]]| |202|sqlite %a.db "select ''"|[]| |203|sqlite %a.db "select NULL"|[]| |204|sqlite %a.db "select 1 where 0 = 1"|[]| |205|sqlite %a.db "select NULL,NULL"|[]| |206|sqlite %a.db "select 1,NULL"|[["1" ""]]| |207|sqlite %a.db "select NULL,1"|[["" "1"]]| |208|sqlite %a.db "select 0"|[["0"]]| |209|sqlite %a.db "select 0,1"|[["0" "1"]]| |210|sqlite %a.db "select 0,''"|[["0" ""]]| |211|sqlite/key %a.db "select 0" 1|[[0]]| |212|sqlite/headings %a.db "select 1 A"|[["A"] ["1"]]| |213|sum-of []|none| |214|sum-of [1 2]|3| |215|to-column-alpha 1|"A"| |216|to-column-alpha 27|"AA"| |217|to-column-number 'A|1| |218|to-column-number "aa"|27| |219|to-rebol-date "01-02-2015"|1-Feb-2015| |220|to-rebol-date/mdy "01-02-2015"|2-Jan-2015| |221|to-rebol-date/day "Mon 01-02-2015"|1-Feb-2015| |222|to-rebol-time "1:00AM"|1:00| |223|to-rebol-time "1:00PM"|13:00| |224|to-rebol-time "1:00 AM"|1:00| |225|to-rebol-time "1:00 PM"|13:00| |226|to-string-date "01-02-68"|"2068-02-01"| |227|to-string-date "01-02-69"|"1969-02-01"| |228|to-string-date 1-Feb-2015|"2015-02-01"| |229|to-string-date "01/02/2015"|"2015-02-01"| |230|to-string-date/mdy "01/02/2015"|"2015-01-02"| |231|to-string-date/ydm "15/02/01"|"2015-01-02"| |232|to-string-date "01-02-2015"|"2015-02-01"| |233|to-string-date/mdy "01-02-2015"|"2015-01-02"| |234|to-string-date/ydm "15-02-01"|"2015-01-02"| |235|to-string-time 1:00|"01.00.00"| |236|to-string-time "1:00PM"|"13.00.00"| |237|write-dsv %a.txt [] read-string %a.txt|""| |238|write-dsv %a.txt [[]] read-string %a.txt|""| |239|write-dsv %a.csv [[a 1] [b 2]] read-string %a.csv|"a,1^/b,2^/"| |240|write-dsv %a.txt [[a 1] [b 2]] read-string %a.txt|{a 1 b 2 }| |241|write-excel %a.xlsx ["A" [[A B] [1 2]] [5 10]]|%a.xlsx| |242|write-excel/filter %a.xlsx ["A" [[A] [B]] [5]]|%a.xlsx|