【开源库 | xlsxio】C/C++读写.xlsx文件,xlsxio 在 Linux(Ubuntu18.04)的编译、交叉编译

发布于:2024-12-21 ⋅ 阅读:(11) ⋅ 点赞:(0)

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰: 2024-12-20 16:41:55

本文未经允许,不得转发!!!


在这里插入图片描述

在这里插入图片描述

🎄一、概述

最近项目需要将日志写到.xlsx中,了解到C和C++的操作.xlsx几个开源库:
在这里插入图片描述
本文要介绍的 xlsxio,虽然不在上图中,但也很好用。

下面主要介绍 xlsxio 库的下载以及在Ubuntu 18.04 下的编译和使用。


在这里插入图片描述

🎄二、XLSXIO 介绍

XLSXIO 是一款用于读取和写入.xlsx文件的跨平台C库。.xlsx文件格式自2007版起成为微软Excel的默认格式。

XLSXIO 提供了以下库:

  • -lxlsxio_read - 用于读取.xlsx文件,要求#include <xlsxio_read.h>
  • -lxlsxio_write - 用于写入.xlsx文件,要求#include <xlsxio_write.h>
  • -lxlsxio_readw - 实验性库,用于读取.xlsx文件,链接到-lexpatw,要求在#include <xlsxio_read.h>之前定义XML_UNICODE

该库的设计目标包括:

  • 使用标准C编写,但也适用于C++
  • 简单的接口
  • 小巧的体积
  • 可移植到不同平台(Windows,*nix)
  • 最小依赖:仅依赖于expat(仅用于阅读)和minizip或libzip(它们本身依赖于zlib)
  • 分别为读取和写入.xlsx文件提供独立的库
  • 不需要安装微软Excel

读取.xlsx文件:

  • 设计用于以数据表的形式处理.xlsx文件,假设:
    • 假设第一行包含列头名称
    • 假设接下来的行在与列头相同的列中提供值
    • 只处理值,忽略其他所有内容(公式,布局,图形,图表…)
  • 整个共享字符串表被加载到内存中(警告:对于具有大量不同值的大工作簿可能很大)
  • 支持没有共享字符串表的.xlsx文件
  • 工作表数据即时读取,无需在内存中缓冲数据
  • 提供两种方法:
    • 一个简单的方法,允许应用程序遍历行和单元格
    • 一个高级方法(开销较小),为每个单元格和每行后调用回调函数

写入.xlsx文件:

  • 旨在将数据表写入.xlsx文件,假设:
  • 仅支持写入数据(不支持公式,布局,图形,图表…)
  • 不支持多个工作表(每个文件只有一个工作表)
  • 即时文件生成,无需在内存中缓冲数据
  • 不支持共享字符串(所有值作为内联字符串写入)

该项目依赖于以下组件:

  • expat (仅用于libxlsxio_read)
  • minizip 或 libzip (libxlsxio_read 和 libxlsxio_write)

请注意,由于报告称使用libzip构建的XLSX I/O生成的.xlsx文件无法用LibreOffice打开,所以首选minizip。
不依赖于微软Excel。
XLSX I/O考虑了跨平台兼容性,在多种操作系统上运行良好,包括Windows,macOS和Linux。


在这里插入图片描述

🎄三、XLSXIO 的下载

XLSXIO 可以在GitHub下载,地址是:https://github.com/brechtsanders/xlsxio.git

下载地址:https://github.com/brechtsanders/xlsxio/tags

其最新版本是 0.2.35,下载后文件名为:xlsxio-0.2.35.tar.gz

在这里插入图片描述


在这里插入图片描述

🎄四、XLSXIO 的编译

✨4.1 XLSXIO 的编译

这个小节介绍的是使用 Ubuntu 自带的 gcc 编译器编译过程。XLSXIO 库依赖于 minizip 或 libzip,本文使用的是 minizip。关于minizip 的编译可以参考文章 :https://blog.csdn.net/wkd_007/article/details/144596975

下面是编译 XLSXIO 的步骤:

tar zxf xlsxio-0.2.35.tar.gz
cd xlsxio-0.2.35
make CFLAGS:="-I `pwd`/../../01_zlib/" LDFLAGS:="-L `pwd`/../../01_zlib/minizip/"
make install PREFIX=`pwd`/../result_gcc

CFLAGS 指明存放 minizip/zip.h 头文件的目录。
LDFLAGS 指明存放 libminizip.so 库文件的目录。

编译完成后,在 ../result_gcc 目录会有如下内容:
在这里插入图片描述


✨4.2 XLSXIO 的交叉编译

交叉编译需要先编译 zlib、minizip、libexpat:

下面是交叉编译 XLSXIO 的步骤:

tar zxf xlsxio-0.2.35.tar.gz
cd xlsxio-0.2.35
make CC=aarch64-mix210-linux-gcc CFLAGS:="-I `pwd`/../../01_zlib -I `pwd`/../../01_zlib/result_mix210/include/ -I `pwd`/../../17_expat/result_mix210/include/" \
LDFLAGS:="-L /home/samba/01_libCompile/opensource/01_zlib/minizip/ -L `pwd`/../../01_zlib/result_mix210/lib -L `pwd`/../../17_expat/result_mix210/lib -lz" 

make install PREFIX=`pwd`/../result_mix210

成功编译后,在 ../result_mix210/ 目录会有如下内容
在这里插入图片描述


在这里插入图片描述

🎄五、XLSXIO 的使用

XLSXIO 源码中有个 xlsxio-0.2.35/examples 目录,里面有几个例子介绍了怎样使用 XLSXIO来操作 .xlsx 文件。感兴趣的可以看看,代码也不难理解。这里以 example_xlsxio_write_cpp.cpp 为例介绍一下怎样单独编译这些例子:

使用动态库编译,运行编译结果时,需要指定动态库路径:

g++ example_xlsxio_write_cpp.cpp -I ./result_gcc/include/ ./result_gcc/lib/libxlsxio_write.a -L ../01_zlib/minizip/ -lminizip -lpthread

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"/home/samba/01_libCompile/opensource/01_zlib/minizip/"

./a.out

下面是使用静态库编译,编译后直接可以运行:

g++ example_xlsxio_write_cpp.cpp -I ./result_gcc/include/ ./result_gcc/lib/libxlsxio_write.a ../01_zlib/minizip/libminizip.a ../01_zlib/result_gcc/lib/libz.a -lpthread 
./a.out

下面是例子 example_xlsxio_write_cpp.cpp 源码,可以帮助我们了解使用XLSXIO :

#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <unistd.h>
#include "xlsxio_write.h"

/*! \class XLSXIOWriter
 *  \brief class for writing data to an .xlsx file
 *\details C++ wrapper for xlsxiowrite_ functions.
 */
class XLSXIOWriter
{
 private:
  xlsxiowriter handle;
 public:

  /*! \brief XLSXIOWriter constructor, creates and opens .xlsx file
   * \param  filename      path of .xlsx file to open
   * \param  sheetname     name of worksheet
   * \param  detectionrows number of rows to buffer in memory, zero for none, defaults to 5
   * \sa     xlsxiowrite_open()
   */
  XLSXIOWriter (const char* filename, const char* sheetname = NULL, size_t detectionrows = 5);

  /*! \brief XLSXIOWriter destructor, closes .xlsx file
   * \sa     xlsxiowrite_close()
   */
  ~XLSXIOWriter ();

  /*! \brief specify the row height to use for the current and next rows
   * \param  height        row height (in text lines), zero for unspecified
   * Must be called before the first call to any Add method of the current row
   * \sa     xlsxiowrite_set_row_height()
   */
  void SetRowHeight (size_t height = 0);

  /*! \brief add a column cell
   * \param  name          column name
   * \param  width         column width (in characters)
   * Only one row of column names is supported or none.
   * Call for each column, and finish column row by calling NextRow().
   * Must be called before any NextRow() or the AddCell methods.
   * \sa     NextRow()
   */
  void AddColumn (const char* name, int width = 0);

  /*! \brief add a cell with string data
   * \param  value         string value
   * \sa     NextRow()
   */
  void AddCellString (const char* value);

  /*! \brief add a cell with integer data
   * \param  value         integer value
   * \sa     NextRow()
   */
  void AddCellInt (long long value);

  /*! \brief add a cell with floating point data
   * \param  value         floating point value
   * \sa     NextRow()
   */
  void AddCellFloat (double value);

  /*! \brief add a cell with date and time data
   * \param  value         date and time value
   * \sa     NextRow()
   */
  void AddCellDateTime (time_t value);

  /*! \brief insertion operators
   * \sa     AddCellString()
   * \name   operator<<
   * \{
   */
  XLSXIOWriter& operator << (const char* value);
  XLSXIOWriter& operator << (const std::string& value);
  XLSXIOWriter& operator << (int64_t value);
  XLSXIOWriter& operator << (double value);
  //XLSXIOWriter& operator << (time_t value);
  /*! @} */

  /*! \brief mark the end of a row (next cell will start on a new row)
   * \sa     xlsxiowrite_next_row()
   * \sa     AddCellString()
   */
  void NextRow ();
};




inline XLSXIOWriter::XLSXIOWriter (const char* filename, const char* sheetname, size_t detectionrows)
{
  unlink(filename);
  handle = xlsxiowrite_open(filename, sheetname);
  xlsxiowrite_set_detection_rows(handle, detectionrows);
}

inline XLSXIOWriter::~XLSXIOWriter ()
{
  xlsxiowrite_close(handle);
}

inline void XLSXIOWriter::SetRowHeight (size_t height)
{
  xlsxiowrite_set_row_height(handle, height);
}

inline void XLSXIOWriter::AddColumn (const char* name, int width)
{
  xlsxiowrite_add_column(handle, name, width);
}

inline void XLSXIOWriter::AddCellString (const char* value)
{
  xlsxiowrite_add_cell_string(handle, value);
}

inline void XLSXIOWriter::AddCellInt (long long value)
{
  xlsxiowrite_add_cell_int(handle, value);
}

inline void XLSXIOWriter::AddCellFloat (double value)
{
  xlsxiowrite_add_cell_float(handle, value);
}

inline void XLSXIOWriter::AddCellDateTime (time_t value)
{
  xlsxiowrite_add_cell_datetime(handle, value);
}

inline XLSXIOWriter& XLSXIOWriter::operator << (const char* value)
{
  AddCellString(value); return *this;
}

inline XLSXIOWriter& XLSXIOWriter::operator << (const std::string& value)
{
  AddCellString(value.c_str());
  return *this;
}

inline XLSXIOWriter& XLSXIOWriter::operator << (int64_t value)
{
  AddCellInt(value);
  return *this;
}

inline XLSXIOWriter& XLSXIOWriter::operator << (double value)
{
  AddCellFloat(value);
  return *this;
}

/*
inline XLSXIOWriter& XLSXIOWriter::operator << (time_t value)
{
  AddCellDateTime(value);
  return *this;
}
*/

inline void XLSXIOWriter::NextRow ()
{
  xlsxiowrite_next_row(handle);
}



const char* filename = "example.xlsx";

int main (int argc, char* argv[])
{
  XLSXIOWriter* xlsxfile = new XLSXIOWriter(filename);
  xlsxfile->SetRowHeight(1);
  xlsxfile->AddColumn("Col1");
  xlsxfile->AddColumn("Col2");
  xlsxfile->AddColumn("Col3");
  xlsxfile->AddColumn("Col4");
  xlsxfile->AddColumn("Col5");
  xlsxfile->NextRow();
  int i;
  for (i = 0; i < 1000; i++) {
    *xlsxfile << "Test" << (char*)NULL << (int64_t)i;
    xlsxfile->AddCellDateTime(time(NULL));
    *xlsxfile << 3.1415926;
    xlsxfile->NextRow();
  }
  delete xlsxfile;
  return 0;
}

运行结果生成example.xlsx,内容如下:
在这里插入图片描述


在这里插入图片描述

🎄六、总结

本文介绍 xlsxio 开源库在 Ubuntu 18.04 的编译、交叉编译以及使用教程。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考:
https://gitcode.com/gh_mirrors/xl/xlsxio/overview