使用GO操作excel文件并发送email

来源:互联网 发布:js正则验证非负正整数 编辑:程序博客网 时间:2024/05/16 07:04

原文链接:http://studygolang.com/articles/9154

情景:将工资条的内容发送到相应员工的邮箱中。
xlsx文件内容格式:
这里写图片描述

  1. 获取excel文件内容,使用第三方库:github.com/tealeg/xlsx
    代码:
package mainimport (    "fmt"    "github.com/tealeg/xlsx"    "log")func main()  {    /* 获取excel文件路径 */    excelFileName := "F:\\Test\\list.xlsx"    /* 获取excel文件对象 */    xlFIle, err := xlsx.OpenFile(excelFileName)    /* 日志打印 */    if err != nil {        log.Fatalln("err:", err.Error())    }    /* 通过for循环获取表格中单元格的内容 */    for _, sheet := range xlFIle.Sheet{        for _, row := range sheet.Rows {            for _, cell := range row.Cells {                fmt.Printf("%s\n", cell.Value)            }        }    }}

知识点:
xlsx操作excel文件先获取Sheet对象,代表excel文件的sheet,通过遍历Sheet对象,获取每个sheet的行结果Rows,对Rows遍历,就获取到了每个单元格的内容,封装在Cells对象中。

  1. 分割工资条
    使用正则表达式,将每个人的工资条分开,如果读取到新的邮箱地址,就用新的存储空间存储工资条的内容。这里使用一个函数:isEmailRow()
func isEmailRow(r []string) (isEmail bool, email string)  {    /* 编译正则表达式 */    reg := regexp.MustCompile(`^[a-zA-Z_0-9.-]{1,64}@([a-zA-Z0-9-]{1,200}.){1,5}[a-zA-Z]{1,6}$`)    /* 遍历r中内容,匹配正则表达式 */    for _, v := range r{        if reg.MatchString(v) {            return true, v        }    }    return false, ""}

isEmailRow函数接收的参数是数组,所以将单元格内容转换为数组形式,并且去除了空格和空行:

func _getCellValues(r *xlsx.Row) (cells []string)  {    for _, cell := range r.Cells{        /* 去除换行和空格 */        txt := strings.Replace(strings.Replace(cell.Value, "\n", "", -1)," ", "", -1)        /* 使用append函数拼接 */        cells = append(cells, txt)    }    return}

使用map来存储每个人的工资条数据,并且用电子邮件作为键值,然后将数据组装成一个HTML的表格行代码(因为需要发送HTML格式的电子邮件才能以表格的形式展现)。于是,main里的循环代码就变成了这样:

/* 创建map */sendList := make(map[string]string)for _, sheet := range xlFile.Sheets {        curMail := ""        for _, row := range sheet.Rows {            cells := getCellValues(row)            //如果行包含电子邮件,创建一个新字典项            if isEmail, emailStr := isEmailRow(cells); isEmail {                curMail = emailStr            }             sendList[curMail] += fmt.Sprintf("<tr><td>%s</td></tr>", strings.Join(cells, "</td><td>"))        }  }
  1. 发送电子邮件

使用标准包:net/smtp就可以发送电子邮件
封装一个函数:

func sendToMail(user, password, host, to, subject, body, mailtype string) error {    /* 返回一个实现了PLAIN身份认证机制的Auth接口 */    auth := smtp.PlainAuth("", user, password, strings.Split(host, ":")[0])    /* 邮件元数据 */    msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + subject + "\r\n" + "Content-Type: text/" + mailtype + "; charset=UTF-8" + "\r\n\r\n" + body)    sendto := strings.Split(to, ";")    /* 发送邮件 */    err := smtp.SendMail(host, auth, user, sendto, msg)    return err}

创建一个函数,遍历所有内容并调用发送邮件函数发送出去

func sendMail(sendList map[string]string) {    fmt.Printf("共需要发送%d封邮件\n", len(sendList))    index := 1    for mail, content := range sendList {        fmt.Printf("发送第%d封", index)        /* 将里边的用户名密码,smtp服务器换成自己的 */        if err := sendToMail("xxx@xxxxxx.com",            "xxxxxxx",            "smtp.xxxxxx.com:25",            mail,            "工资条",            fmt.Sprintf("<table border='2'>%s</table>", content),            "html"); err != nil {            fmt.Printf(" ... 发送错误(X) %s %s \n", mail, err.Error())        } else {            fmt.Printf(" ... 发送成功(V) %s \n", mail)        }        index++        fmt.Printf("<table border='2'>%s</table> \n", content)    }}

最后的main函数:

excelFileName := "F:\\Test\\list.xlsx"    xlFile, err := xlsx.OpenFile(excelFileName)    if err != nil {        log.Fatalln("err:", err.Error())    }    sendList := make(map[string]string)    for _, sheet := range xlFile.Sheets {        curMail := ""        for _, row := range sheet.Rows {            cells := getCellValues(row)            //如果行包含电子邮件,创建一个新字典项            if isEmail, emailStr := isEmailRow(cells); isEmail {                curMail = emailStr            } else {                count := 0                for _, c := range cells {                    if len(c) > 0 {                        count++                    }                }                if count > 1 {                    sendList[curMail] += fmt.Sprintf("<tr><td>%s</td></tr>", strings.Join(cells, "</td><td>"))                } else {                    sendList[curMail] += fmt.Sprintf("<tr><td colspan='%d'>%s</td></tr>", len(cells), strings.Join(cells, ""))                }            }        }    }    sendMail(sendList)    fmt.Print("按下回车结束")    bufio.NewReader(os.Stdin).ReadLine()

亲测可用。作为学习收藏。

原创粉丝点击