NewCoder
NewCoder

Reputation: 13

Tcl to write a file using csv

I need help writing a tcl, which reads portions of data from a csv file and write into a text file in the following pattern.

NAME : FROM= -100 -346 -249 -125 TO= -346 -249 -125 100 COLOR= COLOR1 COLOR2 COLOR3 COLOR4

NAME will be a fixed row,

FROM and TO information should be retreived from csv file and

COLOR information can be hardcoded array of colors from the Tcl itself.

From csv data below, the first value(-100) under MIN will be the first value(-100) under FROM of text file. The last value(100) from excel MAX column will be the last value(100) under text file TO column. The values under VALUE column in excel will be rounded and used as TO and FROM per pattern shown.

Data    VALUE   
100 -345.8756   
200 -249.3654   
300 -125.3554   
COUNT   MIN MAX
1   -100    -98
93  84  86
98  94  96
99  96  98
100 98  100

enter image description here

Upvotes: 0

Views: 1709

Answers (2)

syox
syox

Reputation: 3

package require struct::matrix
package require csv
package require fileutil

array set OPTS { 
    csv_input_filename    output/stackoverflow.csv 
    txt_output_filename   output/stackoverflow.txt
    colors                {COLOR1 COLOR2 COLOR3 COLOR4}
}

set output_format {NAME : 
FROM= %s %s %s %s
TO= %s %s %s %s
COLOR= %s
}

try {::struct::matrix xdata} on error {} {xdata destroy; ::struct::matrix xdata}
set chan [open $OPTS(csv_input_filename)]
csv::read2matrix $chan xdata , auto
close $chan
csv::joinlist [xdata get rect 0 0 end end]

fileutil::writeFile $OPTS(txt_output_filename) \
 [format $output_format [xdata get cell 1 5] \
 [expr {round([xdata get cell 1 1])}] [expr {round([xdata get cell 1 2])}] \
 [expr {round([xdata get cell 1 3])}] [expr {round([xdata get cell 1 1])}] \
 [expr {round([xdata get cell 1 2])}] [expr {round([xdata get cell 1 3])}] \
 [xdata get cell 2 9] [list {*}$OPTS(colors)]]
xdata destroy

fileutil::cat [file native $OPTS(txt_output_filename)]
# NAME :
# FROM= -100 -346 -249 -125
# TO= -346 -249 -125 100
# COLOR= COLOR1 COLOR2 COLOR3 COLOR4

Note:

The script should result to the expected output .txt file, assuming the .csv file is contained within the output subfolder from within the current running directory of course.

Assuming the script filename is 'matrix_csv_extract.tcl' you would simply source the tcl script interactively to have it run:

source matrix_csv_extract.tcl

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 247012

Some pointers:

  • reading lines from a file
  • use set fields [regexp -inline -all {\S+} $line] to split the line into words separated by arbitrary whitespace
  • you'll need to keep a couple of boolean flags as a state machine to determine what to do with the current line (are you collecting values or looking for the min/max)
  • use [expr {round([lindex $fields end])}] to round the values: see https://tcl.tk/man/tcl8.6/TclCmd/expr.htm#M22

See if that gets you started.

Upvotes: 0

Related Questions