😁博客主页😁:🚀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:
- zlib 库交叉编译参考:https://blog.csdn.net/wkd_007/article/details/140573322
- minizip 库交叉编译参考:https://blog.csdn.net/wkd_007/article/details/144596975
- libexpat
下载最新版本: https://github.com/libexpat/ ,然后参考下面编译过程:tar zxf expat-2.6.4.tar.gz cd expat-2.6.4 ./configure --prefix=`pwd`/../result_mix210 --host=aarch64-mix210-linux CC=aarch64-mix210-linux-gcc
下面是交叉编译 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 的编译、交叉编译以及使用教程。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁