libxlsxwriter的功能覆盖面很大,今天一起来看一下如何用这个库来生成带有簇状柱形图的表格。
1 簇形柱状图
首先来看一下Excel的样例表格,簇状柱形图往往是用来对比若干“系列”的数据在某一时间段内,或某一情境下的差异情况。在商务领域还是非常常见的。
对于人工智能领域的程序员来说,往往更熟悉的簇状柱形图是核弹厂的性能对比图:
题外话题外话~
这种图表相信大多数人已经非常熟悉。这里就不多说了。它的几个要素为:
- 系列
- 柱形
- 成簇
2 代码示例及详解
二话不说,先上代码。
#include "xlsxwriter.h"
#include <iostream>
#include <wchar.h>
#include <windows.h>
using std::string;
string GBKToUTF8(const char* strGBK)
{
int len = MultiByteToWideChar(CP_ACP, 0, strGBK, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len + 1];
memset(wstr, 0, len + 1);
MultiByteToWideChar(CP_ACP, 0, strGBK, -1, wstr, len);
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len + 1];
memset(str, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
string strTemp = str;
if (wstr) delete[] wstr;
if (str) delete[] str;
return strTemp;
}
/* 向worksheet中写入一些数据. */
void write_worksheet_data(lxw_worksheet* worksheet) {
uint8_t data[5][3] = {
/* 三列数据. */
{1, 2, 3},
{2, 4, 6},
{3, 6, 9},
{4, 8, 12},
{5, 10, 15}
};
int row, col;
worksheet_write_string(worksheet, 0, 0, GBKToUTF8("2018年").data(), NULL);
worksheet_write_string(worksheet, 1, 0, GBKToUTF8("2019年").data(), NULL);
worksheet_write_string(worksheet, 2, 0, GBKToUTF8("2020年").data(), NULL);
worksheet_write_string(worksheet, 3, 0, GBKToUTF8("2021年").data(), NULL);
worksheet_write_string(worksheet, 4, 0, GBKToUTF8("2022年").data(), NULL);
for (row = 0; row < 5; row++)
{
for (col = 1; col < 4; col++)
{
worksheet_write_number(worksheet, row, col, data[row][col-1], NULL);
}
}
}
/* 创建一个带有图表的表格文件. */
int main(int argc, char* argv[])
{
lxw_workbook* workbook = workbook_new(GBKToUTF8("簇状柱形图示例.xlsx").data());
lxw_worksheet* worksheet = workbook_add_worksheet(workbook, NULL);
/* 向表格中写入一些数据. */
write_worksheet_data(worksheet);
/* 创建一个图表对象. */
lxw_chart* chart = workbook_add_chart(workbook, LXW_CHART_COLUMN);
// 指定表格,在最简单的例子中我们添加一些数据系列,空的系列种类将默认为1到5
// 若非空指定数据系列的名称,则可以按照索引列进行指定。
lxw_chart_series* series1 = chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5");
lxw_chart_series* series2 = chart_add_series(chart, NULL, "=Sheet1!$C$1:$C$5");
lxw_chart_series* series3 = chart_add_series(chart, NULL, "=Sheet1!$D$1:$D$5");
chart_series_set_categories(series1, "Sheet1", 0, 0, 4, 0);
chart_series_set_categories(series2, "Sheet1", 0, 0, 4, 0);
chart_series_set_categories(series3, "Sheet1", 0, 0, 4, 0);
// 给表格添加系列名称
chart_series_set_name(series1, GBKToUTF8("青菜").data());
chart_series_set_name(series2, GBKToUTF8("萝卜").data());
chart_series_set_name(series3, GBKToUTF8("鸡蛋").data());
// 给表头文字设置格式
lxw_chart_font font;
font.bold = LXW_EXPLICIT_FALSE;
font.color = LXW_COLOR_GREEN;
chart_title_set_name(chart, GBKToUTF8("年终销售情况").data());
chart_title_set_name_font(chart, &font);
// 给坐标轴添加名称
chart_axis_set_name(chart->x_axis, GBKToUTF8("年份").data());
chart_axis_set_name(chart->y_axis, GBKToUTF8("万吨").data());
/* 向worksheet中插入图表. */
worksheet_insert_chart(worksheet, CELL("B7"), chart);
return workbook_close(workbook);
}
小白这里的代码还是延续了这个系列文章的一贯风格,即将中文使用添加进了例程之中。以上例程改编自libxlsxwriter官网的例程chart.c。
以上程序生成一个名为簇状柱形图示例.xlsx
的表格。最终内容呈现如下图所示:
重点需要说明的是:
系列,即图中横坐标上的2018年~2022年
,有两种方式进行插入
-
chart_add_series(chart, "=Sheet1!$A$1:$A$5", "=Sheet1!$B$1:$B$5");
这种方式中第二个参数指定了系列数据的来源是A1到A5单元格; -
chart_series_set_categories(series1, "Sheet1", 0, 0, 4, 0);
这种方式通过坐标指定(0,0)到(0,4)单元格为系列的数据来源。
chart_series_set_name(series1, GBKToUTF8("青菜").data());
通过这种方式给系列指定名称。
chart_axis_set_name(chart->x_axis, GBKToUTF8("年份").data());
通过这种方式来给坐标轴插入标题;
worksheet_insert_chart(worksheet, CELL("B7"), chart);
通过这种方式来将图表插入到表格中的指定位置(图片的左上角插入到对应的单元格,此例中插入到B7)。
看似简单,实际上,确实也不难。注意消化掉这个例程就好。还有一些其他的表格相关的指定功能这里可能没涉及到,在以后的博客文章中可能慢慢涉及。