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

😁博客主页😁:🚀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
C++ xlsx文件格式读写

要读取XLSX文件,可以使用C语言中的第三方库来实现。其中比较常用的是libxlsxwriter和libxl。这里以libxl为例,介绍如何使用C语言读取XLSX文件。 1. 下载和安装libxl 首先,需要从libxl官网下载和安装该库。下载地址为:https://www.libxl.com/download.html。根据操作系统选择对应的版本进行下载和安装。 2. 创建工作簿和工作表 在开始读取XLSX文件之前,需要先创建一个工作簿和至少一个工作表。可以使用以下代码实现: ``` BookHandle book = xlCreateBook(); // 创建工作簿 SheetHandle sheet = xlBookAddSheet(book, "Sheet1", NULL); // 添加工作表 ``` 3. 打开XLSX文件并读取数据 使用以下代码可以打开XLSX文件并读取其中的数据: ``` BookHandle book = xlCreateXMLBook(); // 创建工作簿 if (xlBookLoad(book, "example.xlsx") == XL_OK) { // 打开XLSX文件 SheetHandle sheet = xlBookGetSheet(book, 0); // 获取工作表 int row = xlSheetLastRow(sheet); // 获取最后一行 int col = xlSheetLastCol(sheet); // 获取最后一列 for (int i = 0; i <= row; i++) { // 循环读取每一行 for (int j = 0; j <= col; j++) { // 循环读取每一列 const char* value = xlSheetReadStr(sheet, i, j, NULL); // 读取单元格数据 printf("%s\t", value); // 打印单元格数据 } printf("\n"); // 换行 } xlBookRelease(book); // 释放工作簿 } ``` 以上代码中,xlSheetReadStr函数用于读取单元格数据,第一个参数为工作表句柄,第二个和第三个参数为行号和列号,最后一个参数为格式化字符串,这里设置为NULL即可。 4. 完整代码示例 下面是完整的读取XLSX文件的代码示例: ``` #include <stdio.h> #include "libxl.h" int main() { BookHandle book = xlCreateXMLBook(); // 创建工作簿 if (xlBookLoad(book, "example.xlsx") == XL_OK) { // 打开XLSX文件 SheetHandle sheet = xlBookGetSheet(book, 0); // 获取工作表 int row = xlSheetLastRow(sheet); // 获取最后一行 int col = xlSheetLastCol(sheet); // 获取最后一列 for (int i = 0; i <= row; i++) { // 循环读取每一行 for (int j = 0; j <= col; j++) { // 循环读取每一列 const char* value = xlSheetReadStr(sheet, i, j, NULL); // 读取单元格数据 printf("%s\t", value); // 打印单元格数据 } printf("\n"); // 换行 } xlBookRelease(book); // 释放工作簿 } return 0; } ``` 注意,以上代码中需要包含libxl.h头文件,并且编译时需要链接libxl库。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wkd_007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值