大家好,这里是符华~
查看前三篇:
【Go】excelize库实现excel导入导出封装(一),自定义导出样式、隔行背景色、自适应行高、动态导出指定列、动态更改表头
【Go】excelize库实现excel导入导出封装(二),基于map、多个sheet、多级表头、树形结构表头导出,横向、纵向合并单元格导出
【Go】excelize库实现excel导入导出封装(三),基于excel模板导出excel
背景
前两篇文章中,导出时的样式都有设置统一的基础样式的。但是有些时候,我们需要对特定的某一列或某几列设置单独的样式。比如某一列单元格的值都是数值类型,我们需要让这一列右对齐,其它列不变(基础样式是居中对齐);又或者是把某一列文字标红或背景色填充为红色,其它列不变(保持基础样式)。
这篇文章就是来实现:在基础样式的基础上,对特定的列设置单独的自定义样式,且这些特定的列每列都可以设置单独的样式。
实现
修改 tag
因为我们是对一整列设置样式,因此我们可以直接将自定义的样式,放在需要设置样式的那个字段的tag里面。
如下图:
我们解析excel这个tag的时候,是通过正则表达式来解析的,因此在之前的正则表达式基础上,需要再加上style的解析:
同时对应的tag结构体,也需要再加上Style属性:
然后根据正则表达式解析tag值时,将解析到的style值设置到tag结构体的Style属性中:
设置
tag和tag解析部分修改完后,我们需要考虑下在tag里面添加样式的时候,我们应该按什么格式来设置,到后面解析这些样式的时候更方便。
然后我目前想到的设置格式是这样的:
样式类名和样式名,对应excelize库下的xmlStyles.go里面的Style结构体里的属性名:
样式类名是必须的,这样方便我们判断这个样式是属于哪个样式类(对应的结构体)的,然后将Alignment{Horizontal:left},Font{Color:#ff0000,Size:16.0,Family:黑体},Fill{Color:#f9cb9c,Type:pattern,Pattern:1}
这一段字符串根据样式类名分隔,分隔后处理成 json 字符串,再转成对应的样式类结构体。
代码如下:
// customStyle就是 Alignment{Horizontal:left},Font{Color:#ff0000,Size:16.0,Family:黑体},Fill{Color:#f9cb9c,Type:pattern,Pattern:1} 这一串字符
// 设置自定义样式:customStyle 定义的样式、 baseStyle 基础样式
func (e *Excel) SetCustomCellStyle(customStyle string, baseStyle int) int {style, _ := e.F.GetStyle(baseStyle)if style == nil {style = &excelize.Style{}}patt := ".*?{.*?}" // 使用正则解析每一个样式类和它的大括号里面包含的样式re := regexp.MustCompile(patt)matches := re.FindAllStringSubmatch(customStyle, -1)for i := range matches {s := matches[i][0]if strings.HasPrefix(s, ",") {s = strings.TrimPrefix(s, ",")}s = strings.ReplaceAll(s, "{", "")s = strings.ReplaceAll(s, "}", "")if strings.HasPrefix(s, "Alignment") { // 对齐样式result := stringBuilder("Alignment", s) // 处理成json字符串json.Unmarshal([]byte(result), &style.Alignment) // 将json字符串转成对应的结构体} else if strings.HasPrefix(s, "Font") { // 字体样式result := stringBuilder("Font", s)json.Unmarshal([]byte(result), &style.Font)} else if strings.HasPrefix(s, "Fill") { // 背景填充样式result := stringBuilder("Fill", s)json.Unmarshal([]byte(result), &style.Fill)}}i, _ := e.F.NewStyle(style)return i
}// 字符串处理拼接(处理成结构体json字符串)replaceStr 需要替换的字符
func stringBuilder(replaceStr, str string) string {var builder strings.Builderbuilder.WriteString("{")str = strings.ReplaceAll(str, replaceStr, "")split := strings.Split(str, ",")for v := range split {split1 := strings.Split(split[v], ":")if v > 0 {builder.WriteString(",")}builder.WriteString("\"")builder.WriteString(split1[0])builder.WriteString("\"")// 如果是数值或bool类型,不需要拼接引号if IsNumeric(split1[1]) || IsBool(split1[1]) {builder.WriteString(":")builder.WriteString(split1[1])} else {// 因为Fill下面的Color属性是字符串数组的,因此需要拼接中括号if replaceStr == "Fill" && split1[0] == "Color" {builder.WriteString(":[\"")builder.WriteString(split1[1])builder.WriteString("\"]")} else {// 字符串需要拼接引号builder.WriteString(":\"")builder.WriteString(split1[1])builder.WriteString("\"")}}}builder.WriteString("}")return builder.String()
}// 是否是数字:包含正负整数和正负小数
func IsNumeric(s string) bool {// 正则表达式匹配整数和小数b, _ := regexp.MatchString(`^-?\d+(\.\d+)?$`, s)return b
}// 是否是bool值
func IsBool(s string) bool {return strings.EqualFold(s, "true") || strings.EqualFold(s, "false")
}
样式解析并且设置完成后,在导出excel时,将在tag里设置了的样式,应用到对应的列中。因此我们还需要对构建数据行的代码进行修改:
测试
效果图:
最后
完整代码:点这里
ok以上就是今天的全部内容了,大家看完顺便给我点个Star、加关注呗~🥰🥳