C++ 读写 Excel 在 vs2015 中实现(利用开源库xlnt)
参考:C++读写EXCEL文件方式比较,当然,读写csv也是可以的开源项目QtXlsxWriter,用的是qmake,而不是cmake,不太熟悉开源项目OpenXLSXOpenXLSX读写教程
踩坑爬坑系列……本来一个挺简单的问题,由于解决的方法太多,网上的博客太多,海量教程中想找到适合自己的方法实在太难了。下面是我看过的一些比较优秀的教程,整理记录一下:
- C++读写EXCEL文件方式比较。补充:读写csv也是可以的,但其实 写csv有点投机取巧,不算真正的excel。
- 开源项目QtXlsxWriter,用的是qmake(我不熟),而不是cmake,所以我放弃
- 开源项目OpenXLSX,需要C++17,我只有vs2015,不想装vs2019,故弃之
- OpenXLSX读写教程,R语言
- C++使用OLE高速读写EXCEL的源码,有代码,但是有点复杂,搞不懂
- xlnt代码,xlnt详细文档
从上面可以看到,我找了一大堆教程,实际上合适的只有最后一个——xlnt。下面就介绍一下,如何用xlnt这个开源库,非常非常简单的实现excel的读写。
对于大忙(懒)人,可以用我上传的资源(xlnt_demo,利用C++开源库xlnt读写excel,vs2015工程 ,免积分,觉得有用就关注一下博主),是编译好的vs2015工程,项目的属性设置都用的相对目录,无需改动,直接打开即可。
xlnt 编译
先去xlnt的github地址下载代码,再用cmake生成vs2015的工程。
按下面左图把Configure的编译器和位数(本文都用x64)设置好。按下面右图把多余的勾都去掉。不需要编译TEST、SAMPLES,CMAKE_INSTALL_PREFIX也不用改,它默认是build目录下的installed,编译成功后,生成的东西就在build/installed
目录下。installed目录下东西,就是下一步配置 xlnt 需要用的。
cmake 完成后,用vs2015打开工程。找到 菜单->生成->批生成,给 ALL_BUILD 和 INSTALL 的 Release x64 打勾就行,然后点击生成。如下图:
可能遇到的问题: error c2001: 常量中有换行符。原因:编码问题导致的。
解决办法:找到出现错误的 xlnt\source\detail\number_format\number_formatter.cpp
,在171行和467行,都出现了中文的引号,把它换成英文引号即可。然后再重新批生成一遍。我也暂时不理解那个文件的作用,有知道的朋友可以在评论区分享给大家。
当然,在Ubuntu系统下也能安装xlnt:xlnt在Ubuntu 16.04 的安装教程
xlnt 配置
批生成成功后,把 xlnt\build\installed
目录下四个文件夹(bin、include、lib、share),全部复制到自己vs工程的项目目录下(.vcxproj文件所在的目录)。理论上只需要include、lib文件夹,但是怕其他文件夹也会被依赖,所以干脆全复制过去。
注意xlnt与vs工程的版本和位数要一样(我的都是Release x64),否则会出现无法链接库的问题。
还要注意,上一步操作中,静态库的选项没有打勾,所以生成的是动态库xlnt.dll(在bin目录下),以后的程序运行都要带在这个dll。
四个文件夹复制过去之后,设置项目的属性(设置的时候检查一下是不是Release x64,否则设置无效):
- 附加包含目录:$(ProjectDir)\include,用预定义的宏指定相对路径。
- 附加库目录:$(ProjectDir)\lib
- 附加依赖项:xlnt.lib
- 最后再把 xlnt.dll 复制到项目目录和生成的exe所在的目录
以下的几个例子,都来源于 xlnt 的 examples,我只做点改动和注释。
读 excel
简单地读
#include <iostream>
#include <xlnt/xlnt.hpp>
int main()
{
xlnt::workbook wb;
wb.load("test_read.xlsx");
auto ws = wb.active_sheet();
std::clog << "Processing spread sheet" << std::endl;
// 会把当前占用的单元格全都打印出来,空单元格则为空格。
for (auto row : ws.rows(false))
{
for (auto cell : row)
{
std::clog << cell.to_string() << "\t";
}
std::clog << std::endl;
}
std::clog << "Processing complete" << std::endl;
getchar();
return 0;
}
输入的表格和输出的结果如下图所示:
把数据读入vector
#include <iostream>
#include <xlnt/xlnt.hpp>
#include <vector>
int main()
{
xlnt::workbook wb;
wb.load("test_read.xlsx");
auto ws = wb.active_sheet();
std::clog << "Processing spread sheet" << std::endl;
std::clog << "Creating a single vector which stores the whole spread sheet" << std::endl;
std::vector< std::vector<std::string> > theWholeSpreadSheet;
for (auto row : ws.rows(false))
{
std::vector<std::string> aSingleRow;
for (auto cell : row)
{
aSingleRow.push_back(cell.to_string());
}
theWholeSpreadSheet.push_back(aSingleRow);
}
std::clog << "Processing complete" << std::endl << std::endl;
std::clog << "Reading the vector and printing output to the screen" << std::endl;
for (int rowInt = 0; rowInt < theWholeSpreadSheet.size(); rowInt++)
{
for (int colInt = 0; colInt < theWholeSpreadSheet.at(rowInt).size(); colInt++)
{
std::cout << theWholeSpreadSheet.at(rowInt).at(colInt) << "\t";
}
std::cout << std::endl;
}
getchar();
return 0;
}
输入的表格和输出的结果如下图所示:
写 excel
简单地写
#include <iostream>
#include <xlnt/xlnt.hpp>
int main()
{
xlnt::workbook wb;
xlnt::worksheet ws = wb.active_sheet();
//赋值为数值
ws.cell("A1").value(0.5);
//设置单位格格式,设为百分比形式
ws.cell("A1").number_format(xlnt::number_format::percentage());
//赋值为字符串
ws.cell("B2").value("string data");
//赋值为公式
ws.cell("C3").formula("=RAND()");
//合并单元格
ws.merge_cells("C3:C4");
//冻结窗格
ws.freeze_panes("B2");
//保存
wb.save("test_save.xlsx");
getchar();
return 0;
}
输出结果如下图所示,完全符合预期。
用vector批量写
#include <iostream>
#include <xlnt/xlnt.hpp>
#include <vector>
#include <string>
int main()
{
std::vector< std::vector<std::string> > wholeWorksheet;
for (int outer = 0; outer < 10; outer++)
{
std::vector<std::string> singleRow;
for (int inner = 0; inner < 10; inner++)
{
//给vector中的每个元素赋值
std::string val = std::to_string(inner + 1);
singleRow.push_back(val);
}
wholeWorksheet.push_back(singleRow);
}
//创建工作簿
std::clog << "Creating workbook" << std::endl;
xlnt::workbook wbOut;
//创建工作表,并把vector中的元素写入表格
xlnt::worksheet wsOut = wbOut.active_sheet();
//给工作表设置名称
wsOut.title("data");
std::clog << "Looping through vector and writing to spread sheet" << std::endl;
for (int fOut = 0; fOut < wholeWorksheet.size(); fOut++)
{
std::clog << "Row" << fOut << std::endl;
for (int fIn = 0; fIn < wholeWorksheet.at(fOut).size(); fIn++)
{
// 给单元格赋值。特别注意:工作表中的单元格下标是从1开始,而vector中的元素下标是从0开始
wsOut.cell(xlnt::cell_reference(fIn + 1, fOut + 1)).value(wholeWorksheet.at(fOut).at(fIn));
}
}
std::clog << "Finished writing spread sheet" << std::endl;
wbOut.save("test_save.xlsx");
getchar();
return 0;
}
输出结果如下图所示:
更多推荐
所有评论(0)