package main import ( "bufio" "errors" "flag" "fmt" "github.com/axgle/mahonia" "github.com/xuri/excelize/v2" "log" "os" "path" "path/filepath" "sort" "strconv" "strings" ) var splitor = "" var charset = "GBK" func splt(c rune) bool { //c = '' if c == rune(splitor[0]) { return true } else { return false } } func ToAlphaString(value int) string { if value < 0 { return "" } var ans string i := value + 1 for i > 0 { ans = string((i-1)%26+65) + ans i = (i - 1) / 26 } return ans } //列表去重 func uniqvalue(vallist []string) (ret []string){ sort.Strings(vallist) vlen:=len(vallist) for i := 0; i < vlen; i++ { if(i>0 && vallist[i-1]==vallist[i])||len(vallist[i])==0{ continue } ret=append(ret,vallist[i]) } return ret } func list2sortdig(fldlistidx []string) []int { //flds:=strings.Split(fldlistidx,",") flds1:=make([]int, len(fldlistidx)) for i, fld := range fldlistidx { if fv,err:=strconv.ParseInt(fld,10,8);err==nil{ flds1[i]= int(fv) } } sort.Ints(flds1) return flds1 } func main() { var enc mahonia.Decoder //filename := "C:\\Users\\Downloads\\11.del" //filename = "C:\\soft1\\11.txt" var filename string var headfile string var hsplitor = "|" var fldidxlist string var top=-1 if len(os.Args) > 1 { flag.ErrHelp = errors.New("") flag.StringVar(&filename, "f", "111.dat", "--filename 文件名【可以把文件拖放在此处】") flag.StringVar(&splitor, "sp", "\u0003", "--splitor [, \u0008 ,\u0003, \u0009 ] 分割符,一般为\u0003或者逗号等可见字符单字符") flag.StringVar(&headfile, "hf", "111_head.txt", "--headfile 表头文件名【可以把文件拖放在此处,默认以|做分割符】,可以自定义") flag.StringVar(&hsplitor, "hs", "|", "--hsplitor [, \u0008 ,\u0003, \u0009 ] 分割符,一般为\u0003或者逗号等可见字符单字符") flag.StringVar(&charset, "c", "GBK", "--charset [,GBK/UTF-8... ] 字符集编码,一般为GBK") flag.StringVar(&fldidxlist, "fdlst", "1", "--字段列表编号,用英文逗号分割,最后用双引号引用,如1,2,3,4,第一列编号为1") flag.IntVar(&top, "t", -1, "--top 取前多少个") flag.Parse() //rune(splitor) fmt.Println("filename:" + filename) //fmt.Println([]rune(splitor)) fmt.Printf("%s,%X", "splitor:"+string(splitor)+",hex:", splitor) //return } else { fmt.Println("请输入文件名,可以直接用鼠标点击文件拖入到此(如果有表头文件,请确保同目录下的文件名以_head.txt结束,如1.dat,头文件名为1_head.txt):") fmt.Scan(&filename) } enc = mahonia.NewDecoder(charset) if len(filename) < 5 { tmpstr := fmt.Sprintf("输入的文件名[%s]长度好像不够5位,是否有问题?", filename) panic(errors.New(tmpstr)) } paths, basefile := filepath.Split(filename) filesuffix := path.Ext(basefile) newbasename := paths + basefile[0:len(basefile)-len(filesuffix)] headname:=newbasename+"_head.txt" xlsfilename := newbasename + ".xlsx" logfilename := newbasename + ".log" logFile, err := os.OpenFile(logfilename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { fmt.Println("open log file failed, err:", err) return } log.SetOutput(logFile) log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate) log.Printf("日志文件:[%s]\n", logfilename) log.Printf("目标文件[%s]\n", xlsfilename) fmt.Printf("目标文件路径为:[%s]\n", xlsfilename) fmt.Printf("目标日志路径为:[%s]\n", logfilename) fp1, err := os.Open(filename) if err != nil { tmpstr := fmt.Sprintf("%s文件打开错误!", filename) log.Println(tmpstr) panic(err) } defer fp1.Close() row0 := make([]string, 10,300) var headname0="" _,err=os.Stat(headname) if err==nil{ headname0=headname log.Printf("-----输入的头文件[%s]存在------,以此为解析!\n", headname) } _, err = os.Stat(headfile) if err==nil{ headname0=headfile log.Printf("-----输入的头文件[%s]存在------,以此为解析!\n", headfile) } if len(headname0)==0{ log.Printf("-----输入的头文件不存在------!\n") } fp2, err := os.Open(headname0) if err != nil { tmpstr := fmt.Sprintf("%s文件打开错误!", headname0) log.Println(tmpstr) }else{ log.Printf("-----读取%s------!\n",headname0) fs2:=bufio.NewScanner(fp2) fs2.Scan() splitstrLine:=fs2.Text() row0= strings.Split(splitstrLine, hsplitor) tmpstr:="{" for i, rval := range row0 { tmpstr+=strconv.Itoa(i+1)+":"+enc.ConvertString(rval)+"," } tmpstr+=tmpstr+"}" log.Printf("-----读取字段%d个,第一个是[%s]------!\n", len(row0),tmpstr) } defer fp2.Close() fs := bufio.NewScanner(fp1) //fs1 := bufio.NewScanner(fp2) var rowno = 2 if len(row0)>1{ rowno = 1 } log.Printf("-----rowno:%d------!\n", rowno) //xlsfilename := "1122221.xlsx" f := excelize.NewFile() f.SaveAs(xlsfilename) file1, err := excelize.OpenFile(xlsfilename) if err != nil { log.Println(err) } streamWriter, err := file1.NewStreamWriter(enc.ConvertString("Sheet1")) if err != nil { log.Println(err) } defer func() { if err := recover(); err != nil { streamWriter.Flush() f.SaveAs(xlsfilename) file1.Save() log.Printf("recover:%v", err) } }() f.SetActiveSheet(1) //f.SetSheetName("Sheet1") //f.SetPanes("Sheet1",`{"freeze":true,"split":false,"x_split":0,"y_split":1,"top_left_cell":"A2","actve_pane":"topRight"}`) streamWriter.SetPanes( &excelize.Panes{ Freeze: true, Split: false, XSplit: 0, YSplit: 1, TopLeftCell: "A2", ActivePane: "bottomLeft", Selection: []excelize.Selection{ { ActiveCell: "A2", Pane: "bottomLeft"}, }, }) //defer f.SaveAs(xlsfilename) //index:=f.NewSheet("data") //f.SetActiveSheet(index) fldidxlist1:=list2sortdig(uniqvalue(strings.Split(fldidxlist,hsplitor))) colcnt:=0 for fs.Scan() { splitstrLine := fs.Text() //fildstr := strings.FieldsFunc(splitstrLine, splt) fildstr := strings.Split(splitstrLine, splitor) //log.Printf("fldidxlist1:[%d] fildstr:[%s]", len(fldidxlist1),fildstr) if len(fldidxlist1)>1 { colcnt=len(fldidxlist1) }else{ colcnt = len(fildstr) } //log.Printf("pos:%d-->colcnt:[%d]\n",rowno,colcnt) //row := make([]interface{}, colcnt) row := make([]interface{}, colcnt) if rowno==1 { log.Printf("recover:%v", fldidxlist1) if len(fldidxlist1)>1{ colcnt=len(fldidxlist1) for i := 0; i < colcnt; i++ { row[i]=enc.ConvertString(row0[fldidxlist1[i]-1]) } }else if(len(row0)>1){ //需要用此语法处理 for i := 0; i < len(row0) && row0[i]!=""; i++ { row[i]=enc.ConvertString(row0[i]) } } //log.Printf("-----[%d]第一个是[%s],rowno[%d]------!\n",colcnt,row[:colcnt],rowno) cell, _ := excelize.CoordinatesToCellName(1, rowno) //log.Printf("----1-") if err := streamWriter.SetRow(cell, row[:colcnt]); err != nil { log.Println(err) } //log.Printf("-----") row = make([]interface{}, len(row)) //log.Printf("-----2") if top>0{ top++ } //log.Printf("top:[%d] ",top) rowno++ } //log.Printf("colcnt:[%d] ",colcnt) //row = make([]interface{}, colcnt) for colno := 0; colno < colcnt; colno++ { tmpcolno:=colno if len(fldidxlist1)>1{ tmpcolno=fldidxlist1[colno]-1 } //log.Printf("tmpcolno:[%d] ",tmpcolno) if fildstr[tmpcolno] != "" { row[colno] = enc.ConvertString(fildstr[tmpcolno]) } else { row[colno] = "" } } //log.Println("for over ") cell, _ := excelize.CoordinatesToCellName(1, rowno) if err := streamWriter.SetRow(cell, row[:colcnt]); err != nil { log.Println(err) } if rowno%30000 == 0 { log.Printf("-----已写入[%d]行------\n", rowno) } if rowno > excelize.TotalRows { panic(errors.New("rows number exceeds maximum limit")) } //if rowno >= 20000 { // break //} if top>0 && rowno>=top{ log.Printf("-----已写入[%d]行------\n", rowno) break } rowno++ } if len(row0)>1{ rowno-- } log.Printf("-----共写入数据[%d]行------\n", rowno) if err := streamWriter.Flush(); err != nil { log.Println(err) //return } if err := file1.Save(); err != nil { log.Println(err) } //println(fp1) log.Println("完成!") os.Exit(0) }
操作步骤
附件中的exe文件是可执行文件,
在wps中需要另存为一个目录,再使用
在word中可以复制,粘贴到一个目录再使用
此程序的作用是把原来的dat文件(带分割符的文件即可,数据文件的后缀名可以是其他,如txt)转换成excel的后缀名为xlsx的文件
可以用于大量的数据的转换
1、双击操作(全表转换)
双击Dat2Xls.exe,拖入程序
如果需要表头,请把表头的名字修改为 _head.txt结尾的文件名
如您要转换的文件为1.dat 表头则为 1_head.txt
回车即可
2、命令行操作(涉及到高级操作,自定义选择选项)
直接在命令行拖入此程序,可以查看有哪些选项
注意:
只有文件是必须有的
运行如图:
帮助如图:
字符编码一般都是GBK,即需要转换的文件和表头文件都是一个编码格式
cmd下切换到Dat2Xls.exe的程序所在目录运行
如下命令:
简写为: -f后跟的是需要转换为excel的文件名
Dat2Xls.exe -f E:\myexe\a20210831.dat -fdlst "1|2|3|4|5|6|7|20|30"
解析:f后面为需要解析的文件名,拖入即可显示全文件名,fdlst后面为数据所在列的编号,需要用双引号引起来,中间的列号用|分割,列号从1开始,至少为两列
如果不需要指定列,则不需要-fdlst参数
Dat2Xls.exe -f E:\myexe\a_20210831.dat
3、查看日志
解析目录下会有一个同名的.log文件为日志文件,可以查看相应日志
标签:rowno,log,err,excel,len,PLUS,Printf,Go,colcnt From: https://www.cnblogs.com/silencemaker/p/17902912.html