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

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

情景:将工资条的内容发送到相应员工的邮箱中。
xlsx文件内容格式:
使用GO操作excel文件并发送email_第1张图片

  1. 获取excel文件内容,使用第三方库:github.com/tealeg/xlsx
    代码:
package main

import (
    "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("%s", strings.Join(cells, ""))

        }
  }
  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("%s
"
, content), "html"); err != nil { fmt.Printf(" ... 发送错误(X) %s %s \n", mail, err.Error()) } else { fmt.Printf(" ... 发送成功(V) %s \n", mail) } index++ fmt.Printf("%s
\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("%s", strings.Join(cells, ""))
                } else {
                    sendList[curMail] += fmt.Sprintf("%s", len(cells), strings.Join(cells, ""))
                }

            }

        }
    }

    sendMail(sendList)
    fmt.Print("按下回车结束")
    bufio.NewReader(os.Stdin).ReadLine()

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

你可能感兴趣的:(GO语言)