3个软件另存为CSV,对于本身单元格包含英文逗号和双引号的处理方式是相同的,即,字段包含英文逗号,就用英文双引号包围该字段值,而字段值里面的英文双引号,用两个英文双引号,即英文双引号既用于包围又用于转义。
例如 前单元
A",\d“B,"C |
后单元格
",母猪/咽拭子监测 |
另存为后为 "A"",\d“B,""C",""",母猪/咽拭子监测"
PHP fgetcsv 函数:默认转义符是反斜杠 \
$handle$length$delimiter$enclosure$escape
另外,LibreOffice本身能支持的列数相对于前两者比较少,反正我的文件LibreOffice打开直接提示列数太多。
golang 读取 Excel 可以使用 国人xuri 的 excelize 包 (作者貌似奇安信的,感觉我们学校的奇安信vpn比较烂,不过这不影响这个包很OK,哈哈)
把 Excel 读入输出成原始 csv 的程序 (excelize 自带的直接读出会把日期化成计算后的值,我需要原始整数):用法 readxlsx path/to/xlsxFile.xlsx [maxRows] > data.csv
package main
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/xuri/excelize/v2"
)
func main() {
f, err := excelize.OpenFile(os.Args[1])
if err != nil {
fmt.Println(err)
return
}
//defer f.Close() // 似乎没有这个函数,前者打开文件最后返回文件结构体指针
cntRows := 1000000
if len(os.Args) >= 3 {
cntRows, err = strconv.Atoi(os.Args[2])
if err != nil {
fmt.Println(err)
return
}
}
firstSheetName := f.GetSheetList()[0]
rows, err := f.GetRows(firstSheetName)
if err != nil {
fmt.Println(err)
return
}
for _, row := range rows {
flag := false
for _, colCell := range row {
if findComma := strings.Contains(colCell, ","); findComma { // 单元格有英文逗号
if findDoubleQuote := strings.Contains(colCell, "\""); findDoubleQuote { // 单元格有英文双引号
colCell = strings.Replace(colCell, "\"", "\"\"", -1)
}
colCell = "\"" + colCell + "\""
}
if findNewLine := strings.Contains(colCell, "\n"); findNewLine { // 单元格有换行符
colCell = strings.Replace(colCell, "\n", "<br>", -1)
}
if flag {
fmt.Print(",", colCell)
} else {
fmt.Print(colCell)
flag = true
}
}
fmt.Println()
cntRows--
if cntRows <= 0 {
break
}
}
return
}