给Excel加页眉页脚 - 非OLE的C/C++实现

首页 / 技术 / 正文

我上班的地方规定,Office文档要在页眉页脚上加上密级才能传输,而我做的内部软件里会导出来很多Excel文档,于是,为了防止同事忘记加密级,我对Office文件结构作了一番研究。我做的软件使用的语言主要是C/C++,还用黑魔法连接了nodejs、python等各种各样的东西,汇聚了一堆非常小众的框架,于是在这上面费了老半天劲....好久没更新博客了,就记录一下探索的过程吧...

一些尝试

首先当然是要找找看有没有现成的轮子啦,我兴致冲冲直接打开了浏览器,输入关键词“Excel C++”...

OLE

结果出现了一堆基于“OLE”技术的范例,这个OLE技术全称Object Linking and Embedding,翻译过来是对象链接和嵌入,我横看竖看不对劲,最终还是放弃了这个方案,主要原因有以下几点:

  1. OLE是微软的技术,我的软件需要在各种操作系统上运行,可移植性不好
  2. 基于这篇文章的若干观点,加上我用vbs的实践,发现它运行太慢了,而且不稳定,加个页眉页脚要跑好几秒

开源库 - libxlsxwriter

于是我继续往下翻啊翻,翻啊翻...还是很难翻到啊,于是我加了个关键词搜索“开源”...

欸,咱就是说,开源真不辍,一搜就搜出来了这篇文章,根据文章的指引,OpenXLSX不行不支持UTF-8,readxl只能读取不能写入,libxl要收费...似乎只能试试这个BasicExcel,还有这个libxlsxwriter了啊,于是我又兴致勃勃地打开了BasicExcel原作者的博客,一看日期,好家伙,2006年写的,xlsx格式都还没出来呢吧....我果断关掉了这个页面,转眼将目光看上了最后的希望——libxlsxwriter...

一顿搜索猛如虎,我直接找到了它的Github项目主页,先看看日期,一个月前更新的,好耶!我熟练地点进了Release,下载了它1.1.4 October 9 2021的版本(作为经历大半年毒打的老油条,我已经深谙稳定之道,绝不再像之前的少年那样,直接Download zip下最新版直面一堆报错了...)

解压下来一看,我一眼瞄到了其中的CMakeLists.txt,于是我熟练地打开了CMake GUI,将路径粘了进去,又熟练地点击了Configure,被报错糊了一脸....


2022-03-27T13:30:40.png
2022-03-27T13:33:38.png

一看,原来有个zlib依赖库,直接进入了zlib官网,一眼瞄到了它的source code,直接下载下来,又是熟悉的CMakeLists.txt,又是一顿熟练的Configure-Generate-make install操作,很快啊,直接就装上了


2022-03-27T13:37:55.png

再回来libxlsxwriter这里,大抵是要在configure前填写这一项ZLIB_ROOT配置吧,填上,Configure-Generate-make install,过啦!


2022-03-27T13:39:20.png
2022-03-27T13:40:26.png

接下来便是看文档了,U1S1,文档、范例写得真不辍,两分钟就上手了,把之前编译好的链接库、头文件放项目里,随手写个CMakeLists.txt配置一下,再把官方的例程放进来,很快啊,直接就编译成功了奥


2022-03-27T13:59:05.png

官方例程代码大意是创建了一个excel档并写入了一些数据:

#include "xlsxwriter.h"

int main() {

    /* Create a new workbook and add a worksheet. */
    lxw_workbook  *workbook  = workbook_new("demo.xlsx");
    lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);

    /* Add a format. */
    lxw_format *format = workbook_add_format(workbook);

    /* Set the bold property for the format */
    format_set_bold(format);

    /* Change the column width for clarity. */
    worksheet_set_column(worksheet, 0, 0, 20, NULL);

    /* Write some simple text. */
    worksheet_write_string(worksheet, 0, 0, "Hello", NULL);

    /* Text with formatting. */
    worksheet_write_string(worksheet, 1, 0, "World", format);

    /* Write some numbers. */
    worksheet_write_number(worksheet, 2, 0, 123,     NULL);
    worksheet_write_number(worksheet, 3, 0, 123.456, NULL);

    /* Insert an image. */
    worksheet_insert_image(worksheet, 1, 2, "logo.png");

    workbook_close(workbook);

    return 0;
}

运行了一下,得到了这样的一个demo.xlsx


2022-03-27T14:00:15.png

看起来一切都很nice,接下来该翻翻文档看怎么加页眉页脚了,很快我便找到了对应的文档:


2022-03-27T14:05:55.png

文档里给出了各种范例,例如在页眉左部添加图片,以及其中各种控制字的含义:


2022-03-27T14:07:30.png
2022-03-27T14:09:17.png
2022-03-27T14:08:13.png

一切看起来都非常简单,我很快便在官方例程的基础上写出了如下的代码:

    // 添加页眉
    lxw_header_footer_options header_options = {.image_left = (char*)"logo.png"};
    worksheet_set_header_opt(worksheet, "&L&[Picture]&R▲机密", &header_options);

然后编译运行,没!有!报!错!直接通过了奥,运行看看效果,Nice!大成功啊!


2022-03-27T14:19:24.png

似乎很好写了吧,接下来只需要把逻辑从写入改成读取并修改....等等...这个libxlsxwriter...从名字上看是不是有点不太对劲?我查了查文档,通篇没有找到如何读取文件....莫非?

不信邪的我又去issue区搜了搜....一搜吓一跳....


2022-03-27T14:22:37.png

好家伙我直接好家伙...我不禁陷入了沉思,到底该咋整捏?

不得已的造轮经历

(未完待续...)

无标签
打赏
评论区
头像
    头像
    爱老黄
    2022年07月28日 19:51
    回复

    老黄已经快半年没造轮子了,期待ing

      头像
      huanghaozi
      2022年08月18日 11:31
      回复

      出差中,事情太多辣,打算出差回来更新了