【Go】excelize库实现excel导入导出封装(四),导出时自定义某一列或多列的单元格样式

大家好,这里是符华~

查看前三篇:

【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 字符串,再转成对应的样式类结构体。

代码如下:

go 复制代码
// 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.Builder
	builder.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、加关注呗~🥰🥳

相关推荐
热心市民运维小孙1 小时前
Ubuntu重命名默认账户
linux·ubuntu·excel
LeonNo116 小时前
golang , chan学习
开发语言·学习·golang
龙门吹雪6 小时前
GO语言基础面试题
golang·面试题·map·channel·
zyh_0305217 小时前
GIN中间件
后端·golang·gin
又蓝9 小时前
使用 Python 操作 Excel 表格
开发语言·python·excel
m0_7482309413 小时前
Rust赋能前端: 纯血前端将 Table 导出 Excel
前端·rust·excel
Swift社区14 小时前
Excel 列名称转换问题 Swift 解答
开发语言·excel·swift
neeef_se15 小时前
Vue中使用a标签下载静态资源文件(比如excel、pdf等),纯前端操作
前端·vue.js·excel
℘团子এ15 小时前
js和html中,将Excel文件渲染在页面上
javascript·html·excel
菠萝蚊鸭1 天前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel