今天来看一个libxlsxwriter的高级用法:一个条件格式的示例。
说它“高级”,也是基于非Excel专家的小白们的视角。对,没错,本小白正是这样的小白。
1 一个简单的问题
来看我们今天的场景问题:有一列数据,有正有负,我们希望从中找到“绝对值最大”的那个数,并将其变红、加粗;且找到“绝对值最小”的那个数,将其变绿、加粗。
我们先来看一下希望达成的效果:
在这个案例中,绝对值最大的那个数是85,绝对值最小的那个数是-1。
看起来是一个非常简单的问题,但我们提升一下难度,在以上要求的同时,不允许添加辅助列。
相信如果有辅助列,对大家来说非常简单,因为在Excel中,可以使用一个辅助列,先求出每个值的绝对值,然后对绝对值设置条件格式的最大或最小值,提取出行号后按行更改格式即可。
但现在不允许。
2 libxlsxwriter的条件格式设置
单刀直入,先放代码,关键注释已经全部写入:
#include "xlsxwriter.h"
int main(int argc, char* argv[])
{
lxw_workbook* workbook = workbook_new("conditionFormat.xlsx");
lxw_worksheet* worksheet = workbook_add_worksheet(workbook, NULL);
// 写入初始数据列
worksheet_write_number(worksheet, CELL("A1"), -5, NULL);
worksheet_write_number(worksheet, CELL("A2"), 12, NULL);
worksheet_write_number(worksheet, CELL("A3"), -1, NULL);
worksheet_write_number(worksheet, CELL("A4"), 30, NULL);
worksheet_write_number(worksheet, CELL("A5"), -40, NULL);
worksheet_write_number(worksheet, CELL("A6"), 4, NULL);
worksheet_write_number(worksheet, CELL("A7"), 35, NULL);
worksheet_write_number(worksheet, CELL("A8"), 85, NULL);
worksheet_write_number(worksheet, CELL("A9"), 18, NULL);
worksheet_write_number(worksheet, CELL("A10"), 10, NULL);
worksheet_write_number(worksheet, CELL("A11"), 32, NULL);
// 先设置两种情况下的格式
lxw_format* maxValueFormat = workbook_add_format(workbook);
lxw_format* minValueFormat = workbook_add_format(workbook);
// 绝对值最大:加粗、红色
format_set_bold(maxValueFormat);
format_set_font_color(maxValueFormat, LXW_COLOR_RED);
// 绝对值最大:加粗、绿色
format_set_bold(minValueFormat);
format_set_font_color(minValueFormat, LXW_COLOR_GREEN);
// 为条件格式开辟内存
lxw_conditional_format* conditionFormat = (lxw_conditional_format*)calloc(1, sizeof(lxw_conditional_format));
// 条件格式类型选择以公式格式
conditionFormat->type = LXW_CONDITIONAL_TYPE_FORMULA;
// 最大绝对值的公式,要么等于最大值,要么等于最大值的负值
conditionFormat->value_string = "=OR(A1=MAX(ABS($A$1:$A$11)), A1=-MAX(ABS($A$1:$A$11)))";
conditionFormat->format = maxValueFormat;
worksheet_conditional_format_range(worksheet, RANGE("A1:A11"), conditionFormat);
// 最小绝对值的公式,要么等于最小值,要么等于最小值的负值
conditionFormat->value_string = "=OR(A1=MIN(ABS($A$1:$A$11)), A1=-MIN(ABS($A$1:$A$11)))";
conditionFormat->format = minValueFormat;
worksheet_conditional_format_range(worksheet, RANGE("A1:A11"), conditionFormat);
// 释放条件格式内存
free(conditionFormat);
// 关闭工作表,生成最终Excel表格
workbook_close(workbook);
return 0;
}
要点如下:
- 先为不同的目标设置格式类型,如代码中的
maxValueFormat
和minValueFormat
; - 再为条件格式开辟内存,注意可以选择多种模式,本例中选择
LXW_CONDITIONAL_TYPE_FORMULA
; - 为所关注的目标设置公式,本例中是绝对值最大和绝对值最小(这里的技巧是纯Excel的,不在本文描述之内);
- 利用
worksheet_conditional_format_range
来应用条件格式.
最终生成的效果如下:
这里细心的小伙伴可以注意到,小白第一次贴出的效果图中,字体为等线,而小白第二次贴出的效果图中,字体是宋体,这是由于第一次贴出的效果图是手动写入的,单元格默认的数据类型是“常规”,它的默认字体是等线,而代码是使用了worksheet_write_number
函数写入的,在小白的电脑上,系统设置的默认字体是宋体。仅此而已。
如果想要对这个细节问题进行修复,请参看小白上一篇博客libxlsxwriter设置字体格式
ps: 条件格式中还有很多更简单的用例,比如说找一个等于、大于、小于某个阈值的数,这种情况下不需要用到本文中提到的LXW_CONDITIONAL_TYPE_FORMULA
类型,只需要使用LXW_CONDITIONAL_TYPE_CELL
即可,具体的使用方法可以直接查看libxlsxwriter的官方例程,小白觉得如果能够掌握本文所说的这个“高级”案例,应该不难掌握更简单的官方例程。