使用golang对CSV文件中的列进行排序

xkrw2x1b  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(124)

我有一段写csv文件的go代码:

func GetCotacao(c *gin.Context) {
    var data models.Cotacao
    var response []models.Cotacao

    query, err := DB.Query(`SELECT 
    f.nome_fornecedor,
    p.nome_produto,
    ic.valor_unitario,
    c.data_cotacao
FROM fornecedor AS f 
INNER JOIN fornecedor_produto   AS fp   ON fp.id_fornecedor     = f.id_fornecedor
INNER JOIN produto              AS p    ON p.id_produto     = fp.id_produto 

INNER JOIN fornecedor_empresa   AS fe   ON fe.id_fornecedor = f.id_fornecedor
INNER JOIN empresa              AS e    ON e.id_empresa     = fe.id_empresa 
INNER JOIN cotacao              AS c    ON c.id_empresa     = e.id_empresa 

INNER JOIN item_cotacao         AS ic   ON ic.id_produto    = fp.id_produto 
AND ic.id_fornecedor    = fe.id_fornecedor 
AND ic.id_cotacao       = c.id_cotacao 
WHERE c.data_cotacao = '2023-08-17'`)
    if err != nil {
        log.Println("Erro ao buscar cotacao", err)
        c.Status(400)
        return
    }

    for query.Next() {
        if err := query.Scan(&data.NomeFornecedor, &data.NomeProduto, &data.ValorUnitario, &data.DataCotacao); err != nil {
            log.Println("Erro ao buscar cotacao")
        }
        response = append(response, data)

    }
    c.JSON(200, response)

    arquivo, err := os.Create("cotacoes.csv")
    if err != nil {
        log.Println("Erro ao criar arquivo CSV", err)
        c.Status(400)
        return
    }
    defer arquivo.Close()

    // Criar um escritor CSV
    escritorCSV := csv.NewWriter(arquivo)
    defer escritorCSV.Flush()

    for _, add := range response {
        linhaCSV := []string{add.NomeFornecedor}
        err = escritorCSV.Write(linhaCSV)
        if err != nil {
            log.Println("Erro ao escrever linha no CSV", err)
            c.Status(400)
            return
        }

    }

}

我在这个csv中有更多的列要写,例如:我希望data.ProductName位于csv文件的B列中(因为我要在Excel中打开该文件)
我在这个csv中有更多的列要写,例如:我希望data.ProductName位于csv文件的B列(因为我要在excel中打开该文件),但我找不到实现此目的的方法
我尝试了什么?

for _, add := range response {
        linhaCSV := []string{add.NomeFornecedor, add.NomeProduto}
        err = escritorCSV.Write(linhaCSV)
        if err != nil {
            log.Println("Erro ao escrever linha no CSV", err)
            c.Status(400)
            return
        }

    }

正如你所看到的,我试图在我的“lineCSV”中添加更多的参数,但它把所有的东西都放在同一行中,用逗号分隔,我怎么能把我的add.ProductName参数放在单独的列中呢?这可能吗?
编辑:这是我的csv,看到它有逗号后的某个部分后,每个逗号,它应该是一个列

编辑2
提前感谢您的关注。根据评论中的要求,下面是我在其他编辑器中打开的.csv文件的打印
vscode:

notpad++

edit 3

我在谷歌表单中打开它,结果如预期的那样来了,用列分开,问题会是我电脑上的excel吗?

hlswsv35

hlswsv351#

你的Go程序正在按预期工作;它将生成一个逗号分隔的文件(包含由逗号,分隔的字段的文件)。CSV是“逗号分隔值”的缩写;你可能认为这意味着什么很明显,但不幸的是,事实并非如此。
没有标准规定CSV文件应该如何格式化;有一个RFC,但它特别声明“它不指定任何类型的互联网标准”(它确实记录了常见的用法)。
用逗号分隔的文件在美国和英国等使用小数点的国家/地区工作得很好(例如“123.01”),但在countries that use逗号中存在相同目的的问题(例如,“123,01”-01是小数还是单独的列?)
可能出于这个原因,在Excel中,CSV文件实际上是一个由设置为"list separator"的任何内容分隔的文件。这会导致“逗号分隔值”文件实际上没有用逗号分隔!尝试在Excel中创建一个包含多列的文件,将其保存为CSV,然后在文本编辑器中打开生成的文件(例如,Notepad++);你会发现这些列实际上并不是用逗号分隔的。(我在这里做了一些假设,在我的电脑上,由于我的语言环境,它将被逗号分隔)。
如果你把你的应用程序生成的文件发给我,我在Excel中打开它们,结果会是你所期望的(类似于你在谷歌工作表中的结果-- Excel会用逗号将数据分隔成列);然而,在您的计算机上打开相同的文件不会有相同的结果(最有可能是因为“列表分隔符”设置为;或其他东西)。
我在评论中链接的superuser question的答案提供了一些建议的解决方案;这包括:

  • 将分隔符更改为计算机上设置为“列表分隔符”的任何内容。
  • 使用制表符分隔的文件而不是逗号分隔的文件。
  • 在文件的第一行写出SEP=,
  • 将文件扩展名更改为.TXT(然后,当您打开Excel时,Excel将询问您如何转换它)

这些解决方案中没有一个是理想的,因为它们不会在所有情况下都起作用(例如,在另一个应用程序或另一台计算机上打开文件可能无法按预期工作)。如果你的目标是Excel(和其他电子表格),那么我建议你写一个.xlsx文件;这将更一致地打开,并且您将避免其他潜在问题,例如:

  • 保存CSV时更改日期格式
  • 丢失客户编号等内容的前导0
  • 大量(例如部件号)转换为科学记数法。

CSV文件很好,因为它们非常简单,会被很多应用程序读取;但是不同的程序会以不同的方式处理它们,所以结果可能并不总是你所期望的。

相关问题