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
}