Reputation: 65
anyone knows how to pull data from CSV file that uploaded as multipart.file based on its column and then input the data to another CSV file (the template)?
I still can't get the right logic to do that in golang. this is the csv file look alike:
"Coorporate",,,
Address :,,,
Boulevard Street,,,
Service / Office : 021-62318113 / 021-22684901,,,
"VGA WITH GUARANTEE",Dealer,Msrp,MARGIN
VGA-1,"37,000","38,000","1,000"
VGA-2,"27,500","28,500","1,000"
CASE ,Dealer ,Msrp ,MARGIN
CASE-1 ,"430,000","480,000","50,000"
CASE-2 ,"450,000","500,000","50,000"
"MAXSUN VGA ",Dealer ,Msrp ,MARGIN
MVGA-1,"13,300,000","13,800,000","500,000"
these are the codes I've tried to read to detect the table header (the row that at least having "Msrp" column):
reader := csv.NewReader(f)
records, err := reader.ReadAll()
var rows []string
columns := []string{"Msrp", "MSRP", "msrp"}
for _, column := range columns {
for _, columnName := range records {
for _, cols := range columnName {
if cols == column {
row := strings.Join(columnName, " ")
rows = append(rows, row)
break
}
}
}
but it just return the table header only. I need to get the value for each column and save it into a new slice (maybe?) so that later I can update the CSV template file with the value that I just pull from the CSV file uploaded
and let's say i have a struct :
type columnName struct {
PartName string json:"part_name"
Price int json:"price"
Msrp int json:"msrp"
}
how do i match the column name to that struct?
is there any better way to solve this problem?
anyway I'm new to golang and programming pls help me
many thanks!
Upvotes: 0
Views: 485
Reputation: 11223
I cleaned up the input CSV you shared:
Coorporate,,,
Address :,,,
Boulevard Street,,,
Service / Office : 021-62318113 / 021-22684901,,,
VGA WITH GUARANTEE,Dealer,Msrp,MARGIN
VGA-1,"37,000","38,000","1,000"
VGA-2,"27,500","28,500","1,000"
CASE,Dealer,Msrp,MARGIN
CASE-1,"430,000","480,000","50,000"
CASE-2,"450,000","500,000","50,000"
MAXSUN VGA,Dealer,Msrp,MARGIN
MVGA-1,"13,300,000","13,800,000","500,000"
Looking at it in an aligned table view:
| Coorporate | | | |
| Address : | | | |
| Boulevard Street | | | |
| Service / Office : 021-62318113 / 021-22684901 | | | |
| VGA WITH GUARANTEE | Dealer | Msrp | MARGIN |
| VGA-1 | 37,000 | 38,000 | 1,000 |
| VGA-2 | 27,500 | 28,500 | 1,000 |
| CASE | Dealer | Msrp | MARGIN |
| CASE-1 | 430,000 | 480,000 | 50,000 |
| CASE-2 | 450,000 | 500,000 | 50,000 |
| MAXSUN VGA | Dealer | Msrp | MARGIN |
| MVGA-1 | 13,300,000 | 13,800,000 | 500,000 |
It looks like you have a couple of rows at the top that won't end up in the final data, so I iterate over them and ignore them:
f, _ := os.Open("input.csv")
r := csv.NewReader(f)
// iterate and discard Coorporate ... Service / Office...
for i := 0; i < 4; i++ {
_, err := r.Read()
if doneReading(err) {
break
}
}
I made my struct like:
type Record struct {
PartName string `json:"part_name"`
Price int `json:"price"`
Msrp int `json:"msrp"`
}
Now, I can iterate the rest of the rows and be on guard for intermediate looking headers, if I see one I just drop it by continuing to the next row, which should be real data. For the real data rows the format looks straightforward—string, string, int, int
—so I can parse the 2nd and 3rd column directly as ints (checking for errors), append the results to my slice of Records, then turn it all into JSON:
Records := make([]Record, 0)
for i := 5; ; i++ {
record, err := r.Read()
if doneReading(err) {
break
}
col3 := strings.TrimSpace(record[2])
// discard records that look like an intermediate header
// with "MSRP" in the 3rd colum
if strings.ToLower(col3) == "msrp" {
continue
}
col1 := strings.TrimSpace(record[0])
col2 := strings.TrimSpace(record[1])
price, err1 := strconv.Atoi(strings.ReplaceAll(col2, ",", ""))
msrp, err2 := strconv.Atoi(strings.ReplaceAll(col3, ",", ""))
if err1 != nil || err2 != nil {
log.Printf("could not parse ints in Col2 and/or Col3 of row %d: %v\n", i, record)
}
Records = append(Records, Record{col1, price, msrp})
}
b, err := json.MarshalIndent(Records, "", " ")
must(err)
fmt.Println(string(b))
and I see:
[
{
"part_name": "VGA-1",
"price": 37000,
"msrp": 38000
},
{
"part_name": "VGA-2",
"price": 27500,
"msrp": 28500
},
{
"part_name": "CASE-1",
"price": 430000,
"msrp": 480000
},
{
"part_name": "CASE-2",
"price": 450000,
"msrp": 500000
},
{
"part_name": "MVGA-1",
"price": 13300000,
"msrp": 13800000
}
]
Bad data in one of the number columns gets logged like:
2009/11/10 23:00:00 could not parse ints in Col2 and/or Col3 of row 6: [VGA-1 37,000 38,000--AAA 1,000]
Here's a complete example, Go Playground.
Upvotes: 0
Reputation: 44
Looks like there might be some confusion regarding the return of reader := csv.NewReader(f)
.
The reader
represents the entire table.
If you loop through the reader
,you can print each line one by one.
like this, write a test and print out the data,you will have a clear understanding.
reader := csv.NewReader(file)
//the first line data is the titles
titles, _ = reader.Read()
// perform a data comparison with columns := []string{"Msrp", "MSRP", "msrp"}
// allocate a container below to store it
//loop the row
for {
records, _ = reader.Read() // the records
// the records is a var record []string
// you should loop that value
//there record[1], record[2], record[3] is your col
}
hope this can help you
Upvotes: 0