一、簡介
xlslib庫是用來創建excel文件、libxls是用來讀取excel文件的,在使用C++或者QT語言來設計對excel文件的讀取。都需要事先下載這兩個庫編譯成功后再進行程序設計的。之所以選擇這兩個庫來使用,是因為這兩個庫即可以在windows系統下使用,又可以在Linux系統下使用。對於設計跨平台使用的程序來說這兩個庫是一個不錯的選擇。xlslib源碼生成動(xlslib.dll)/靜(xlslib.lib)態庫的具體的編譯方法,網上有很多資源,再次不在贅述。本文注重介紹libxls庫的生成方法。
二、libxls庫的生成方法
1、首先下載cygwin,32位操作系統下載setup-x86.exe,64位電腦下載setup-x86_64.exe。
2、安裝cygwin下的編譯環境
編譯x86鏈接庫安裝以下組件:
Devel下的make、mingw64-i686-binutils、mingw64-i686-gcc-core、mingw64-i686-gcc-g++、mingw64-i686-win-iconv
編譯x64鏈接庫安裝以下組件:
Devel下的make、mingw64-x86_64-binutils、mingw64-x86_64-gcc-core、mingw64-x86_64-gcc-g++、mingw64-x86_64-win-iconv
3、下載libxls(1.4.0版本)源碼:
4、打開cygwin(默認當前路徑為/home/Administrator),使用cd libxls命令將當前文件路徑切換到源碼所在文件夾,執行下面命令進行configure配置:
32位: CC='i686-w64-mingw32-gcc' ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32
64位: CC='x86_64-w64-mingw32-gcc' ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32
5、前面步驟正確的話,步驟4中的配置就會成功並生成必須的makefile文件,執行“make && make install”來進行編譯安裝了。
6、只要make沒報錯,我們就能在$(cygwin_home)/usr/local/libxls下即可看到安裝成果($(cygwin_home)是指cygwin的安裝目錄)。
安裝成果中的bin目錄只有xls2csv.exe,但是沒法成功運行,原因就如提示一樣:缺少iconv.dll。
x86:拷貝\usr\i686-w64-mingw32\sys-root\mingw\bin下的iconv.dll;
x64:拷貝\usr\x86_64-w64-mingw32\sys-root\mingw\bin下的iconv.dll即可正常運行。
安裝成果中的lib目錄只有libxlsreader.a和libxlsreader.la,並沒有我們需要的dll和lib文件。不過可以利用.a文件最終轉換出運行需要的dll、鏈接需要的lib及def文件。
7、接下來我們利用安裝成果中的libxlsreader.a來生成我們需要的dll、lib和def文件。
(1)x86:在cygwin命令行下執行“i686-w64-mingw32-ar x libxlsreader.a”提取a中的.o文件
x64:在cygwin命令行下執行“x86_64-w64-mingw32-ar x libxlsreader.a”提取a中的.o文件
(2)然后利用.o文件來生成dll和def文件,具體命令如下:
x86:i686-w64-mingw32-gcc -shared -o libxls.dll *.o -Wl,--export-all-symbols,--output-def,libxls.def -liconv
x64:x86_64-w64-mingw32-gcc -shared -o libxls.dll *.o -Wl,--export-all-symbols,--output-def,libxls.def -liconv
(3)利用dll和def通過visual studio的lib來得到鏈接需要的lib文件,打開visual studio 命令提示,然后切換目錄到dl所在目錄並執行:
x86:lib /machine:X86 /def:libxls.def
x64:lib /machine:X64 /def:libxls.def
8、至此大功告成,我們得到了x86和x64兩個版本的libxls鏈接庫(dll&lib),而且中文也能正常支持。接下來我們就可以愉快地封裝和使用libxls庫了
三、使用示例
本程序中我對這兩個庫做了簡易的封裝,生成了兩個動態庫,主要功能就是對excel文件的創建寫入和讀取顯示。
xlslib庫的封裝
createxcel_global.h文件
#ifndef CREATEXCEL_GLOBAL_H #define CREATEXCEL_GLOBAL_H #ifdef QEXCEL__API_EXPORTS # define QEXCEL__API _declspec(dllexport) #else # define QEXCEL__API _declspec(dllimport) #endif #endif // QEXCEL_GLOBAL_H
createxcel.h文件
#ifndef QEXCEL_H #define QEXCEL_H #include "createxcel_global.h" #include <QString> #include <sstream> #include <string> #include "xlslib.h" using namespace std; using namespace xlslib_core; class QEXCEL__API QEXCEL { public: QEXCEL(); ~QEXCEL(); void CreateWorkSheet(QString SheetName); //創建表格 void SaveExcelFile(QString FileName); //保存工作簿 void SetCellNumber(int row,int col,int number); //設置序號 void SetCellText(int row,int col,QString text,bool setFont); //設置文本信息 void SetCellSize(int row,int col,int row_width ,int col_hight); //設置單元格大小 void SetCellCenter(); //設置單元格格式居中 void SetCellLeft(); //設置單元格格式靠左居中 void MergeCells(int begin_row,int begin_col,int end_row,int end_col); //合閉單元格 // void SetFontSize(int Fontsize); public: // 單元格 cell_t * cell; font_t * _font; xf_t * xf; private: // 工作簿 workbook pWB; // 工作表 worksheet *pWS; }; #endif // QEXCEL_H
createxcel.cpp文件
#include "createxcel.h" #include <stdio.h> #pragma comment(lib, ".\\lib\\xlslib_lib.lib") QEXCEL::QEXCEL() { pWS = NULL; cell = NULL; _font = NULL; xf = NULL; } QEXCEL::~QEXCEL() { } void QEXCEL::CreateWorkSheet( QString SheetName ) { string sheetname = string((const char *)SheetName.toLocal8Bit()); //Qstring 轉換成String pWS = pWB.sheet(sheetname); pWS->defaultColwidth(25); //設置默認列寬 pWS->defaultRowHeight(15); //設置默認行高 _font = pWB.font("Arial"); _font->SetBoldStyle(BOLDNESS_BOLD); // 設置粗字體 _font->SetHeight(220); //設置字體大小11 xf = pWB.xformat(); xf->SetFont(_font); xf->SetFillBGColor(CLR_WHITE); xf->SetFillFGColor(CLR_RED); pWS->MakeActive(); } void QEXCEL::SaveExcelFile( QString FileName ) { string filename = string((const char *)FileName.toLocal8Bit()); pWB.Dump(filename); } void QEXCEL::SetCellText( int row,int col,QString text,bool setFont ) { string value = string((const char *)text.toLocal8Bit()); //xlslib_strings::ustring value = text.toStdWString(); if (setFont == true) //顯示為粗體 { cell = pWS->label(row, col,value/* L"中國"*/,xf); } else { cell = pWS->label(row, col, value,NULL); } } void QEXCEL::SetCellNumber( int row,int col,int number ) { stringstream oss; string Num; oss << number; oss >> Num; cell = pWS->label(row, col, Num,NULL); } void QEXCEL::SetCellSize( int row,int col,int row_width ,int col_hight ) { if(row_width!=0) { pWS->rowheight(row,row_width); } if (col_hight!=0) { pWS->colwidth(col,col_hight); } } void QEXCEL::SetCellCenter() { cell->halign(HALIGN_CENTER); //單元格水平方向居中 cell->valign(VALIGN_CENTER); //單元格垂直方向居中 } void QEXCEL::SetCellLeft() { cell->halign(HALIGN_LEFT); //單元格水平方向靠左 cell->valign(VALIGN_CENTER); } void QEXCEL::MergeCells( int begin_row,int begin_col,int end_row,int end_col ) { pWS->merge(begin_row,begin_col,end_row,end_col); //合並單元格 }
libxls庫的封裝
readexcel_global.h 文件
#ifndef QLIBCOMMON_GLOBAL_H #define QLIBCOMMON_GLOBAL_H #ifdef QLibCommon_API_EXPORTS #define QLibCommon_API _declspec(dllexport) #else #define QLibCommon_API _declspec(dllimport) #endif #endif // QLIBCOMMON_GLOBAL_H
ReadExcel.h 文件
#ifndef CSKQEXCELCOMMOM_H #define CSKQEXCELCOMMOM_H #include "readexcel_global.h" #include <QString> #include "xls.h" using namespace xls; class QLibCommon_API ReadExcel { public: ReadExcel(QString strpath); ~ReadExcel(); // 工作簿 xlsWorkBook* getworkbooks(); // 工作表 xlsWorkSheet* selectSheet(int sheetIndex); //獲取工作表數量 int getSheetsCount(); //獲取工作表名稱 QString getSheetName(int sheetIndex); //獲取工作表單元格內容 QString getCellValue(int row, int column); //獲取單元表行數 int getUsedRowsCount(); //獲取單元表列數 int getUsedColsCount(); //關閉工作表 void closeSheet(); //關閉工作簿 void closeWorkBook(); private: // 工作簿 xlsWorkBook *pWB; // 工作表 xlsWorkSheet *pWS; // 單元格 xlsCell * cell; }; #endif // CSKQEXCELCOMMOM_H
ReadExcel.cpp 文件
#include "ReadExcel.h" #pragma comment(lib, ".\\lib\\libxls.lib") ReadExcel::ReadExcel( QString strpath ) { pWB = NULL; pWS = NULL; cell = NULL; ///qstring轉換為const char *///////// //方法一 std::string str = strpath.toStdString(); const char* path = str.c_str(); //方法2 // const char* path; // QByteArray ba = strpath.toLatin1(); // path=ba.data(); ////////////////////// pWB = xls_open(path, "GBK"); if (!pWB) { printf("Open File Error! pWB\n"/*,pWB*/); return ; } else { xls_parseWorkBook(pWB); } } ReadExcel::~ReadExcel() { } xlsWorkBook* ReadExcel::getworkbooks() { return pWB; } xlsWorkSheet* ReadExcel::selectSheet(int sheetIndex) { // 獲取工作表(第幾個工作表) pWS = xls_getWorkSheet(pWB,sheetIndex); // 解析工作表 xls_parseWorkSheet(pWS); return pWS; } int ReadExcel::getSheetsCount() { return pWB->sheets.count; } QString ReadExcel::getSheetName( int sheetIndex ) { return (char *)pWB->sheets.sheet[sheetIndex].name; } QString ReadExcel::getCellValue( int row, int column ) { cell = xls_cell(pWS, row-1, column-1); //行列起始號為1 // 判斷單元格及內容是否為空 if (cell && cell->str) { return (char *)cell->str; } } int ReadExcel::getUsedRowsCount() { return pWS->rows.lastrow; } int ReadExcel::getUsedColsCount() { return pWS->rows.lastcol; } void ReadExcel::closeSheet() { //關閉表格 xls_close_WS(pWS); cell = NULL; pWS = NULL; } void ReadExcel::closeWorkBook() { // 關閉工作簿 xls_close_WB(pWB); pWB = NULL; }