业务场景
我想要利用一套模板,快速生成一段通用文字。这段文字中有部分内容是固定的,而其他内容都是可以自定义的。例如:“xxx,您好。xxxx祝您生日快乐。”
解决思路
最快想到的方案是:利用特定字符串实现数据拼接和处理,如下所示:
姓名 | 类型 | 文本 |
哈哈 | 哥哥 | {0}{1},您好! 很高兴认识你。 最近干的不错。 {0}{1},再见! |
这里{0}和{1}分别表示第一个单元格的内容和第二个单元格的内容,那么只需要在拼接文本的时候,实现字符串的替换,就可以完成文本处理。
同时,针对大量文本,比较好的处理方式应该是:读取excel->处理excel->生成新的excel。
代码实现
1. 准备工作:
(1)新建一个文件夹excel;
(2)进入excel文件夹;
(3)使用go mod
go mod init excel(这里是你的项目名,用什么)
(4)新建一个main.go的文件
(5)下载类库tealeg/xlsx,这里我用的是v1版本,官方已经更新到了v3版本,建议大家使用新版本
go get github.com/tealeg/xlsx# 详细使用方式请访问:https://github.com/tealeg/xlsx/blob/master/tutorial/tutorial.adoc
(6)新建一个demo.xlsx(也可以是其他名字,需要和代码中的源文件名对应起来),建议放在当前目录下。excel中的内容应该是类似这样的:
当然,如果你有很多可变字段,可以继续扩展,不过要注意目前代码实现逻辑仅支持可变字段排在文本前面,不支持文本后面添加可变字段。
完成上述步骤后,你的目录结构应该是这样的
2. 代码:
代码中主要实现了3个func,分别是`文件获取(getFilePath)`,`excel处理(readExcel)`和`excel生成(exportExcel)`。
package mainimport ( "fmt" "log" "os" "strconv" "strings" "github.com/tealeg/xlsx")// 读取Excel,将结果封装成二维数组返回func readExcel(filePath string) [][]string { // 初始化数组 var result [][]string // 打开文件 xlFile, err := xlsx.OpenFile(filePath) if err != nil { fmt.Println(err.Error()) return result } // 遍历sheet页读取 for _, sheet := range xlFile.Sheets { //遍历行读取 for _, row := range sheet.Rows { rowResult := make([]string, 0, len(row.Cells)) // 遍历每行的列读取 for _, cell := range row.Cells { text := cell.String() rowResult = append(rowResult, text) } result = append(result, rowResult) } } return result}func getFilePath(fileName string) string { dir, err := os.Getwd() if err != nil { log.Fatal(err) } return dir + "\\" + fileName}func exportExcel(fileName string, data [][]string) { // 定义输出文件 outFile := getFilePath(fileName) file := xlsx.NewFile() // 定义sheet名称 sheet, err := file.AddSheet("result_list") if err != nil { fmt.Printf(err.Error()) } var columnLen int for i, v := range data { row := sheet.AddRow() for j, v1 := range v { nameCell := row.AddCell() // 因为第一行是表头,所以可以直接略过,columnLen用来保存列数 if i == 0 { // 使用SetValue方法,还有其他方法,如SetFloat等等,应对不同类型字段 nameCell.SetValue(v1) columnLen = len(v) - 1 fmt.Printf("Column len is %d\n", columnLen) } else { // 最后一列是最终处理结果,其他的列都可以直接复制进去 if j != columnLen { nameCell.SetValue(v1) } else { // 进行字符串处理,v是当前行,columnLen-1是单元格位置 v[columnLen] = strConvert(v, columnLen-1) str := v[columnLen] nameCell.SetValue(str) } } } } err = file.Save(outFile) if err != nil { fmt.Printf(err.Error()) }}// 这里需要注意,我把所有可能需要替换的值都写在了前面,最后一列是最终处理结果func strConvert(str []string, tarIndex int) string { fmt.Printf("target index is %d\n", tarIndex) strTarget := str[tarIndex] for i, v := range str { // 这里实现文本替换 if i != tarIndex { repl := "{" + strconv.Itoa(i) + "}" strTarget = strings.Replace(strTarget, repl, v, -1) } } fmt.Printf("str target is %s\n", strTarget) return strTarget}func main() { // 定义源文件名 filePath := getFilePath("demo.xlsx") // 文件处理 result := readExcel(filePath) // 定义输出文件名 exportExcel("result.xlsx", result)}
代码直接运行即可,运行完后,当前目录下会出现result.xlsx,打开看下,实现目标。
3. 扩展:
当然,你还可以运行go bulid直接生成一个main.exe可执行文件,方便在其他人的windows电脑下运行。
简单文本处理完成后,可以考虑接入微信api,实现消息快速编辑与群发。
4. bug:
由于这个类库是针对Microsoft Office开发的,如果你用wps打开了demo,那么就会出现数据处理失败的情况。因此,在运行时,请勿使用wps
。