从 csv 文件中提取数据并将其放入 golang 中给出的模板中

pull data from csv file and put it into template given in golang

提问人:carlcaroline 提问时间:11/3/2023 最后编辑:Zach Youngcarlcaroline 更新时间:11/5/2023 访问量:62

问:

有人知道如何根据其列从上传为 multipart.file 的 CSV 文件中提取数据,然后将数据输入到另一个 CSV 文件(模板)?

我仍然无法获得在 golang 中执行此操作的正确逻辑。这是CSV文件的样子:

"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"

这些是我尝试读取以检测表头(至少具有“Msrp”列的行)的代码:

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
            }
        }
    }

但它只返回表头。我需要获取每列的值并将其保存到新的切片中(也许?),以便以后可以使用刚刚从上传的CSV文件中提取的值更新CSV模板文件

假设我有一个结构:

type columnName struct { 
     PartName string json:"part_name" 
     Price int json:"price" 
     Msrp int json:"msrp"
}

如何将列名与该结构匹配?

有没有更好的方法来解决这个问题?

无论如何,我是golang的新手,编程请帮助我

非常感谢!

csv go 解析 切片 csv-parser

评论


答:

0赞 poone 11/3/2023 #1

看起来 的返回可能会有一些混淆。 表示整个表。 如果遍历 ,则可以逐行打印。reader := csv.NewReader(f)readerreader

像这样,写一个测试并打印出数据,你就会有一个清晰的认识。


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
}

希望这能帮到你

评论

0赞 carlcaroline 11/3/2023
哦,谢谢你纠正我。无论如何,您知道我应该如何处理它,以便假设我有一个结构类型 columnName struct { PartName string SourceName string Price int Msrp int Ppn bool } 我如何将列名与该结构相匹配json:"part_name"json:"source_name"json:"price"json:"msrp"json:"ppn"
1赞 poone 11/3/2023
如果要在运行时动态检索 struct 字段,则应使用包 。获取使用 .或者,您可以定义一个映射进行映射,这可能是一种更简单的尝试方法。reflectrelect.TypeOf and the name through typ.Field
0赞 Zach Young 11/4/2023 #2

我清理了您共享的输入 CSV:

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"

在对齐的表视图中查看它:

| 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 |

看起来顶部有几行不会出现在最终数据中,所以我遍历它们并忽略它们:

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
    }
}

我把我的结构做成这样的:

type Record struct {
    PartName string `json:"part_name"`
    Price    int    `json:"price"`
    Msrp     int    `json:"msrp"`
}

现在,我可以迭代其余的行,并警惕中间的标题,如果我看到一个标题,我只需继续下一行即可将其删除,这应该是真实的数据。对于真实的数据行,格式看起来很简单——所以我可以直接将第 2 列和第 3 列解析为 ints(检查错误),将结果附加到我的 Records 切片中,然后将其全部转换为 JSON:string, string, int, int

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))

我看到:

[
  {
    "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
  }
]

其中一个数字列中的错误数据会被记录下来,如下所示:

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]

下面是一个完整的示例,Go Playground