一、xlslib介绍
C++用来操作Excel的方法很多,但是涉及到跨平台,同时又要对Excel的读写操作兼顾,而且免费的库,那应该是要用xlslib和libxls了。xlslib库只能写Excel文件,libxls库只能读Excel文件。另外libxl库功能强大,但是收费的。
xlslib
官网:http://xlslib.sourceforge.net
下载:http://sourceforge.net/projects/xlslib
libxls
下载:http://sourceforge.net/projects/libxls/
libxl
二、工程加载
1、加载xlslib_lib和xlslib_dll工程时,提示下面错误
xlslib-package-2.5.0\xlslib\xlslib\build\msvc2012\xlslib_dll.vcxproj : error : 筛选器“Source Files”下已存在项目“....\src\xlslib\formula.cpp”。
解决方法:
用记事本打开编辑xlslib_lib.vcxproj和xlslib_dll.vcxproj
删除formula.cpp一行,因为有两行只保留一行就行。
重新打开xlslib.sln工程没有错误。
三、工程编译
createDLL工程编译,此工程用于将xlslib.lib文件转换成xlslib.dll文件。
编译createDLL,提示下面错误
error C2338:
解决方法:在工程属性中增加宏定义_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
xlslib_lib和xlslib_dll工程编译
1 “sheet_notes”前的类型(构造函数有返回类型或是当前类型名称的非法重定义?)
解决
src/xlslib/note.h
44-47行
struct sheet_notes
{
uint16_t sheet_idx
uint16_t sheet_notes;
}
成员sheet_notes和结构名一样冲突了
修改成员名unit16_t sheet_notes为uint16_t sheet_notes__只要不冲突就行。
后续用到这个变量的地方也修改,这个编译的时候会提示的。
note.cpp(342) last_sheet.sheet_notes__
note.cpp(355) sn.sheet_notes__
note.cpp(358) sn.sheet_notes__
2 formula.cpp(917) error C2059 语法错误"{"
解决
将function_propertyp = (function_property) {CELLOP_AS_VALUE, A_UNKNOWN};
修改为
function_property p ={CELLOP_AS_VALUE, A_UNKNOWN};
去掉 (function_property)
3测试的例子也有错误
targets\test\md5.c(464): error C2143: 语法错误 : 缺少“;”(在“类型”的前面)
3>....\targets\test\md5.c(467): error C2065: “bload”: 未声明的标识符
这个是.c语法 后面申明了 int bload
将Int bload提到该函数的最前面一行
再次编译 提示错误
char const * __cdecl check_file(char const *,char const *)
这个是由于c文件导出函数接口不同
在Target/test/md5.h
将
#if defined(__cplusplus)
extern "C"
{
#endif
#if defined(__cplusplus)
}
#endif
注释取消掉
编译xlslib_dll工程时,提示error LNK1104: 无法打开文件“gdi32.lib”。
此类错误解决方法参考这篇文章https://www.cnblogs.com/AkazaAkari/p/6145144.html
右键项目->属性->配置属性->VC++目录 要修改两个值:
包含目录
库目录
点击右侧的倒三角->点击编辑->双击上方的空白编辑区,
包含目录就追加 C:\Program Files\Microsoft SDKs\Windows\v7.1A;$(IncludePath)
库目录追加 C:\Program Files\Microsoft SDKs\Windows\v7.1A\Lib;$(LibraryPath)
(注意,因为版本不同,文件夹不一定是v7.1A,主要看这个目录下的lib目录当中有没有我们报错中提到的库)比如win10系统下lib和include路径
包含目录
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\shared
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt
库目录
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.14393.0\um\x86
四、使用实例
1、生成xls
#include <string.h>
#include <xlslib/xlslib.h>
using namespace xlslib_core;
using namespace std;
int main (int argc, char *argv[]) {
workbook wb;
xf_t* xf = wb.xformat();
worksheet* ws;
ws = wb.sheet("sheet1");
string label = "Hello, World!";
ws->label(1,2,label,xf); // 从0开始数,第1行,第2列,即C3
wb.Dump("workbook.xls");
return 0;
}
2、设置颜色
#include <string.h>
#include <xlslib/xlslib.h>
using namespace xlslib_core;
using namespace std;
int main (int argc, char *argv[]) {
workbook wb;
font_t * _font = wb.font("Calibri");
_font->SetBoldStyle(BOLDNESS_BOLD); // 设置粗字体
xf_t* xf = wb.xformat();
xf->SetFont(_font);
xf->SetFillBGColor(CLR_WHITE);
xf->SetFillFGColor(CLR_RED);
worksheet* ws;
ws = wb.sheet("sheet1");
cell_t * cell;
cell = ws->label(1,2,"hello",xf); // 从0开始数,第1行,第2列,即C3
cell = ws->label(2,2,"world");
cell->fillfgcolor(CLR_RED);
cell->fillbgcolor(CLR_WHITE);
range * _range;
_range = ws->rangegroup(0,0,1500,100); // 设置背景为白色
_range->cellcolor(CLR_WHITE);
_range = ws->rangegroup(1,2,2,2);
_range->cellcolor(CLR_GOLD);
wb.Dump("workbook.xls");
return 0;
}
3、设置列宽
#include <string.h>
#include <xlslib/xlslib.h>
using namespace xlslib_core;
using namespace std;
int main (int argc, char *argv[]) {
workbook wb;
worksheet* ws;
ws = wb.sheet("sheet1");
ws->defaultColwidth(256*10);
ws->colwidth(2,256*30);
cell_t * cell;
cell = ws->label(1,2,"hello",xf); // 从0开始数,第1行,第2列,即C3
cell = ws->label(2,2,"world");
wb.Dump("workbook.xls");
return 0;
}
4、输入中文
int main (int argc, char *argv[]) {
workbook wb;
worksheet* sh = wb.sheet("sheet");
sh->label(1,1,"test1");
sh->label(2,1,L"test3中文");//这里中文使用unicode编码
wb.Dump("workbook.xls");
return 0;
}
5、注意事项
1、用createDLL生成dll文件时,需要用管理员权限打开vs编译。
2、输入字符串中包含有中文,请使用unicode编码,否则就会出现乱码。
3、低于2.5.0版本的xlslib库,写中文字符串时可以使用unicode编码方式写入中文字符串,也可以使用utf-8方式写入中文字符串。但utf-8方式写入中文字符串,需要修改源代码。
/*
* 在xlslib/src/sheetrec.h中增加如下代码
*/
cell_t* label(int code, unsigned16_t row, unsigned16_t col, const std::ustring& strlabel, xf_t* pxformat = NULL);
cell_t* label(int code, unsigned16_t row, unsigned16_t col, const char* strlabel, xf_t* pxformat = NULL);
/*
* 在xlslib/src/sheetrec.cpp中增加如下代码
*/
cell_t* worksheet::label(int code, unsigned16_t row, unsigned16_t col,
const ustring& strlabel, xf_t* pxformat)
{
enum { UTF8, GBK };
u16string str16;
label_t* lbl;
u16string::const_iterator u16begin, u16end;
ustring::const_iterator ubegin, uend;
size_t len;
if (code == UTF8) {
len = strlabel.length();
str16.reserve(len);
ubegin = strlabel.begin();
uend = strlabel.end();
while(ubegin != uend) {
unichar_t c;
c = *ubegin++;
str16.push_back(c);
}
lbl = new label_t(m_GlobalRecords, row, col, str16, pxformat);
AddCell((cell_t*)lbl);
return (cell_t*)lbl;
} else {
return NULL;
}
}
cell_t* worksheet::label(int code, unsigned16_t row, unsigned16_t col,
const char* strlabel, xf_t* pxformat)
{
enum { UTF8, GBK };
unsigned16_t u16;
u16string str16;
label_t* lbl;
wstring::const_iterator wbegin, wend;
size_t len;
if (code == UTF8) {
if (strlabel == NULL) {
return NULL;
} else {
len = strlen(strlabel);
wchar_t wcs[len+1];
mbstowcs(wcs, strlabel, len+1);
len = wcslen(wcs);
for (int i = 0; i < len; i++) {
u16 = wcs[i];
str16.push_back(u16);
}
}
lbl = new label_t(m_GlobalRecords, row, col, str16, pxformat);
AddCell((cell_t*)lbl);
return (cell_t*)lbl;
} else {
return NULL;
}
}
实例:
#include <locale.h>
#include "ocilib.h"
#include "xlslib.h"
using namespace xlslib_core;
#define RECORDCOUNT 65536
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "zh_CN.utf-8");
enum { UTF8, GBK };
workbook wb1, wb2;
worksheet* wb1sh1 = wb1.sheet("Sheet1");
worksheet* wb2sh1 = wb2.sheet("Sheet1");
int row = 0, coloumn = 0;
if (argc != 4) {
printf("Example: ./demo SID USER PASSWORD/n");
return 0;
}
OCI_Connection* cn;
OCI_Statement* st;
OCI_Resultset* rs;
OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT);
cn = OCI_ConnectionCreate(argv[1], argv[2], argv[3], OCI_SESSION_DEFAULT);
st = OCI_StatementCreate(cn);
OCI_ExecuteStmt(st, "select * from t_test_a");
rs = OCI_GetResultset(st);
while (OCI_FetchNext(rs))
{
if (row < RECORDCOUNT) {
wb1sh1->label(UTF8, row, coloumn, OCI_GetString(rs, 1));
wb1sh1->label(UTF8, row, coloumn+1, OCI_GetString(rs, 5));
wb1sh1->label(UTF8, row, coloumn+2, OCI_GetString(rs, 6));
} else {
wb2sh1->label(UTF8, row-RECORDCOUNT, coloumn, OCI_GetString(rs, 1));
wb2sh1->label(UTF8, row-RECORDCOUNT, coloumn+1, OCI_GetString(rs, 5));
wb2sh1->label(UTF8, row-RECORDCOUNT, coloumn+2, OCI_GetString(rs, 6));
}
printf("/r%d", row+1);
fflush(stdout);
row++;
}
printf("/n");
wb1.Dump("./demo1.xls");
wb2.Dump("./demo2.xls");
OCI_Cleanup();
return EXIT_SUCCESS;
}