一步一步地教你實現OLE讀取EXCEL(一)
建立一個對外介面標頭檔案DLL_API.h檔案,程式碼如下:#include "stdafx.h" #include "CExcelFileRead.h" COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); // Excel App初始化 CApplication CReadExcelFile::excel_application; // 初始化Excel OLE BOOL CReadExcelFile::InitExcel() { // 初始化COM庫 CoInitialize(NULL); // 初始化Excel if (!excel_application.CreateDispatch("Excel.Application", NULL))return FALSE; excel_application.put_DisplayAlerts(FALSE); // 遮蔽警告 return TRUE; } // 釋放Excel OLE void CReadExcelFile::ReleaseExcel() { excel_application.ReleaseDispatch(); excel_application.Quit(); excel_application = NULL; } // 建構函式 CReadExcelFile::CReadExcelFile(const char * file_name) { // 連線excel app excel_books.AttachDispatch(excel_application.get_Workbooks()); // 開啟檔案並初始化excel_work_book LPDISPATCH lpDisp = NULL; TRY { lpDisp = excel_books.Open(file_name, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional); } CATCH(COleDispatchException, e) { AfxMessageBox(e->m_strDescription); OpenFileFlag = FALSE; return; } END_CATCH OpenFileFlag = TRUE; excel_work_book.AttachDispatch(lpDisp); // 得到所有的sheets並初始化excel_sheets excel_sheets.AttachDispatch(excel_work_book.get_Worksheets()); // 得到活動的工作表並初始化excel_work_sheet excel_work_sheet.AttachDispatch(excel_work_book.get_ActiveSheet()); // 初始化當前的操作區域excel_current_range excel_current_range.AttachDispatch(excel_work_sheet.get_Cells()); // 設定當前的檔名 open_excel_file = file_name; } // 解構函式:關閉檔案 CReadExcelFile::~CReadExcelFile() { excel_books.Close(); } // 判斷是否開啟成功 BOOL CReadExcelFile::IsOpenSuccess() { return OpenFileFlag; } // 返回開啟的Excel檔名稱 CString CReadExcelFile::GetCurrentFileName() { return open_excel_file; } // 載入某個Sheet,通過index BOOL CReadExcelFile::LoadSheet(long iSheet) { if (iSheet > excel_sheets.get_Count())return FALSE; // 如果iSheet當前已經載入 if (iSheet == excel_work_sheet.get_Index())return TRUE; // 釋放先前的 excel_current_range.ReleaseDispatch(); excel_work_sheet.ReleaseDispatch(); // 載入iSheet LPDISPATCH lpDisp = excel_sheets.get_Item(COleVariant((long)iSheet)); if (!lpDisp)return FALSE; excel_work_sheet.AttachDispatch(lpDisp); excel_current_range.AttachDispatch(excel_work_sheet.get_Cells()); return TRUE; } // 載入某個Sheet,通過名稱 BOOL CReadExcelFile::LoadSheet(const char * sheet_name) { // 如果iSheet當前已經載入 if (excel_work_sheet.get_Name() == sheet_name)return TRUE; // 釋放先前的 excel_current_range.ReleaseDispatch(); excel_work_sheet.ReleaseDispatch(); // 載入iSheet LPDISPATCH lpDisp = excel_sheets.get_Item(COleVariant(sheet_name)); if (!lpDisp)return FALSE; excel_work_sheet.AttachDispatch(lpDisp); excel_current_range.AttachDispatch(excel_work_sheet.get_Cells()); return TRUE; } // 獲得sheet數目 int CReadExcelFile::GetSheetCount() { return excel_sheets.get_Count(); } // 獲得某個Sheet的名稱 CString CReadExcelFile::GetSheetName(long iSheet) { // 載入iSheet if (!LoadSheet(iSheet))return CString(); return excel_work_sheet.get_Name(); } // 獲得某個Sheet的row數目 int CReadExcelFile::GetRowCount(long iSheet) { // 載入iSheet if (!LoadSheet(iSheet))return 0; // 獲取使用範圍usedRange,獲取行range CRange usedRange; usedRange.AttachDispatch(excel_work_sheet.get_UsedRange()); CRange range; range.AttachDispatch(usedRange.get_Rows()); // 獲得數目 int count = range.get_Count(); // 釋放 usedRange.ReleaseDispatch(); range.ReleaseDispatch(); // 返回 return count; } // 獲得某個Sheet的column數目 int CReadExcelFile::GetColCount(long iSheet) { // 載入iSheet if (!LoadSheet(iSheet))return 0; // 獲取使用範圍usedRange,獲取行range CRange usedRange; usedRange.AttachDispatch(excel_work_sheet.get_UsedRange()); CRange range; range.AttachDispatch(usedRange.get_Columns()); // 獲得數目 int count = range.get_Count(); // 釋放 usedRange.ReleaseDispatch(); range.ReleaseDispatch(); // 返回 return count; } // 根據Sheet的名稱獲得Sheet的index int CReadExcelFile::GetSheetIndex(const char * sheet_name) { if (!LoadSheet(sheet_name))return -1; return excel_work_sheet.get_Index(); } // 獲得某個Sheet的字串Cell CString CReadExcelFile::GetCellString(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return CString(); // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); range.ReleaseDispatch(); // 分析vResult CString str; if (vResult.vt == VT_BSTR)str = vResult.bstrVal; // 字串 else if (vResult.vt == VT_INT)str.Format(_T("%d"), vResult.pintVal); // 整數 else if (vResult.vt == VT_R8)str.Format(_T("%0.0f"), vResult.dblVal); // 8位元組的整數 else if (vResult.vt == VT_DATE) // 時間格式 { SYSTEMTIME st; VariantTimeToSystemTime(vResult.date, &st); CTime tm(st); str = tm.Format("%Y-%m-%d"); } else if (vResult.vt == VT_EMPTY)str = ""; // 空的單元格 else str = ""; return str; } // 獲得某個Sheet的整數Cell int CReadExcelFile::GetCellInt(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return 0; // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); range.ReleaseDispatch(); // 分析vResult int num = static_cast<int>(vResult.dblVal); return num; } // 獲得某個Sheet的浮點數Cell double CReadExcelFile::GetCellDouble(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return 0.0; // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); range.ReleaseDispatch(); // 分析vResult double rtn_value = 0.0; if (vResult.vt == VT_R8)rtn_value = vResult.dblVal; return rtn_value; } // 檢查Cell是否空 BOOL CReadExcelFile::IsCellEmpty(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return TRUE; // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); range.ReleaseDispatch(); // 分析vResult if (vResult.vt == VT_EMPTY)return TRUE; else return FALSE; } // 檢查Cell是否是字串 BOOL CReadExcelFile::IsCellString(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return FALSE; // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); //VT_BSTR標示字串 if (vResult.vt == VT_BSTR)return TRUE; return FALSE; } // 檢查Cell是否是int BOOL CReadExcelFile::IsCellInt(long iSheet, long iRow, long iCol) { // 載入iSheet if (!LoadSheet(iSheet))return FALSE; // 讀取 CRange range; range.AttachDispatch(excel_current_range.get_Item(COleVariant((long)iRow), COleVariant((long)iCol)).pdispVal); COleVariant vResult = range.get_Value2(); // 檢查 if (vResult.vt == VT_INT || vResult.vt == VT_R8)return TRUE; return FALSE; } // 取得列的名稱(如第27列為AA) CString CReadExcelFile::GetColName(long iCol) { // 初始化column_name char column_name[64]; // 分析iCol size_t str_len = 0; while (iCol > 0) { int num_data = iCol % 26; iCol /= 26; if (num_data == 0) { num_data = 26; iCol--; } column_name[str_len] = (char)((num_data - 1) + 'A'); str_len++; } column_name[str_len] = '\0'; // 反轉 _strrev(column_name); // 返回 return CString(column_name); }
建立一個實現檔案DLL_API.cpp,程式碼如下:#pragma once //--------------------------------------------------------------------// // DLL對外介面函式: // 1.完成Excel OLE的初始化 // 2.給出要讀取的檔名、Sheet標號、列數、行數等相關資訊進行讀取; // 3.完成Excel OLE的釋放 //--------------------------------------------------------------------// // 維護函式: // 維護函式實現從讀取函式到CReadExcel類物件的過程實現和維護。在得到 // 使用者呼叫的讀取函式之後,維護函式判斷該檔案是否已經開啟: // 1.如果已經開啟,那麼到OpenFileList中找到對應的CReadExcelFile類的 // 指標,並進行後續的操作; // 2.如果沒有開啟,那麼申請一個新的CReadExcelFile類並將其存入開啟文 // 件列表OpenFileList,之後進行後續操作; //--------------------------------------------------------------------// #pragma once #include "CExcelFileRead.h" #include<vector> #define DLL_API extern "C" __declspec(dllexport) using namespace std; //----DLL全域性變數:讀取檔案記錄---------------------------------------// vector<CReadExcelFile*> OpenFileList; //----DLL對外介面函式-------------------------------------------------// // 完成Excel OLE的初始化 DLL_API bool Excel_Init(); // 完成Excel OLE的釋放 DLL_API void Excel_Release(); // 得到某檔案Sheet的總數 DLL_API int get_sheets_count(string &file_name); // 得到某檔案某個Sheet的名稱 DLL_API string get_sheet_name(string &file_name, long iSheet); // 得到某個檔案某個Sheet的行數 DLL_API int get_rows_count(string &file_name, long iSheet); // 得到某個檔案某個Sheet的列數 DLL_API int get_cols_count(string &file_name, long iSheet); // 根據Sheet名稱獲得Sheet標號 DLL_API int get_sheet_index(string &file_name, string &sheet_name); // 得到某個檔案某個Sheet某個Cell(字串) DLL_API string get_cell_string(string &file_name, long iSheet, long iRows, long iCols); // 得到某個檔案某個Sheet某個Cell(整數) DLL_API int get_cell_int(string &file_name, long iSheet, long iRows, long iCols); // 得到某個檔案某個Sheet某個Cell(浮點數) DLL_API double get_cell_double(string &file_name, long iSheet, long iRows, long iCols); // 判斷Cell是否空 DLL_API bool IsCellEmpty(string &file_name, long iSheet, long iRows, long iCols); //----維護函式,對外不可見---------------------------------------------// // 在OpenFileList中尋找某檔案的index,不存在返回-1 int FindFileIndexInList(string &file_name); // 總維護過程 CReadExcelFile *Maintain(string &file_name); // 釋放Excel OLE時要清空列表,析構其中所有CReadExcelFile類 void CloseAllFile();
相關推薦
一步一步地教你實現OLE讀取EXCEL(一)
#include "stdafx.h" #include "CExcelFileRead.h" COleVariant covTrue((short)TRUE), covFalse((short)FALSE), covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERRO
一步一步地教你實現OLE讀取EXCEL(二)
在上一篇中本人向大家介紹了OLE讀取EXCEL檔案所用到的動態連結庫的方法!下面這一章節為大家介紹簡單的UI介面以及使用DLL的方法! (一)介面 介面很垃圾,內容很樸實。在lineedit中輸入學生姓名後點擊“開始搜尋”,之後在textedit顯示該學生參加的社會實踐
前端教你學UI——人物處理(一)
適應 logs 減少 方法 情況 總結 -a 但是 影響 一、序言 本文作為本系列的第一篇寫UI的文章,開頭還是有必要申明一些東西的,本系列主要是為了作為博主在前端工作之余學習UI的一個記錄,同時為了讓更多的同行學習到一些編程之外的其他東西。所以本文會盡可能詳細的介紹如何
手把手教你開發jquery插件(一)
PE ora ID outside sep write -c visio .sh Just as the auther of jQuery Tools said: 上海代孕 http://www.xyrjkf.cn/ jQuery UI has a so-called
手把手教你移植linux核心---------OK6410(一)
配置資訊: 移植核心:linux-3.3.5 可以從 http://www.kernel.org/ 下載純正的版本 編譯環境:vmware下ubuntu11.04 交叉編譯版本:4.3.2 準備工作: 一塊OK6410開發板,交叉網線,串列埠線
教你寫響應式框架(一)
在真正開始編寫自己的響應式框架之前,我們先來從觀察者模式說起。已經對觀察者模式很熟悉的可以直接掠過。 基本概念 觀察者模式屬於物件行為模式之一,也可叫做釋出——訂閱模式。它定義了一種以對多的依賴關係,讓多個觀察者(訂閱者)同時觀察(監聽)一個被觀察者(主
手把手教你做智慧LED燈(一) 功能規劃與設計方案
前言 智慧硬體有意思,現在市場上有很多針對普通消費者的智慧硬體。例如,智慧燈泡、智慧插座、智慧電子秤,甚至無人飛行器。拋開這些智慧裝置實現的功能不談,它們的實現原理都是大同小異:通過手機的藍芽(或者wifi網路),連線智慧硬體上的藍芽模組,向藍芽模組傳送各種控
【教程】一步步教你使用以太坊(ETH)錢包
很多小夥伴不知道選擇怎樣的以太坊錢包,下載以太坊PC端錢包更新太慢而且交易不方便,那麼我推薦大家使用GTETH以太坊錢包,操作方便非常安全的以太坊錢包 詳細介紹GTETH以太坊錢包教程 建立錢包(網頁版/桌面軟體/手機軟體),備份錢包(一定要拿到私鑰,不見私鑰千萬不要
教你玩App怎麼賺錢(一)
在看這篇文章之前,你一定要接受一下謀哥的觀點:金錢就是價值流通的手段,不要高看了錢。 玩App怎麼賺錢?貌似謀哥寫的文章超級多,把這個最重要的忘記了。說實在的,我為啥要寫“玩App"呢?其實就是一種比較輕鬆的心態。就好像現在我寫文章,簡直就是神速,那思路就
手把手教你寫fio 插件(一)
type 添加 libaio sample rev any ins The direct FIO是一款方便IO性能測試的工具,以統計全面、模式靈活深得用戶歡心。當前支持libaio、sync等IO引擎。在存儲系統開發中,如何快速快速全面評測系統IO性能?給FIO添加調用存儲
分分鐘教你學會 ToolBar 的使用(轉)
window map pri end case instance em1 oom title 轉自:http://blog.csdn.net/itguangit/article/details/52042203 1.和平常一樣,新建一個Moudle 在xml布局文件中使用
教你建立Oracle複合索引(精)
什麼是複合索引? 複合索引顧名思義,區別於單列索引,是由兩個或多個列一起構成的索引。其在B樹上的資料結構是什麼樣?如下圖,是一個包含兩列的複合索引。 如果你觀察仔細,還會發現它的葉子節點是ASC遞增排序的。現根據第一個值排序,然後根據第二個值排序。查的時候也一樣,先查第一個值,在查
手把手教你構建 C 語言編譯器(6)
由於語法分析本身比較複雜,所以我們將它拆分成 3 個部分進行講解,分別是:變數定義、函式定義、表示式。本章講解函式定義相關的內容。 手把手教你構建 C 語言編譯器系列共有10個部分: EBNF 表示 這是上一章的 EBNF 方法中與函式定義相關的內容。 variable_decl ::= type {'*
手把手教你構建 C 語言編譯器(4)
本章我們將講解遞迴下降的方法,並用它完成一個基本的四則運算的語法分析器。 手把手教你構建 C 語言編譯器系列共有10個部分: 什麼是遞迴下降 傳統上,編寫語法分析器有兩種方法,一種是自頂向下,一種是自底向上。自頂向下是從起始非終結符開始,不斷地對非終結符進行分解,直到匹配輸入的終結符;自底向上是不斷地將終
手把手教你構建 C 語言編譯器(8)
這是整個編譯器的最後一部分,解析表示式。什麼是表示式?表示式是將各種語言要素的一個組合,用來求值。例如:函式呼叫、變數賦值、運算子運算等等。 表示式的解析難點有二:一是運算子的優先順序問題,二是如何將表示式編譯成目的碼。我們就來逐一說明。 手把手教你構建 C 語言編譯器系列共有10個部分: 運算子的優先順
手把手教你構建 C 語言編譯器(2)
本章是“手把手教你構建 C 語言編譯器”系列的第三篇,本章我們要構建一臺虛擬的電腦,設計我們自己的指令集,執行我們的指令集,說得通俗一點就是自己實現一套匯編語言。它們將作為我們的編譯器最終輸出的目的碼。 手把手教你構建 C 語言編譯器系列共有10個部分: #計算機的內部工作原理 計算機中有三個基本部件需要
手把手教你構建 C 語言編譯器(5)
本章中我們用 EBNF 來大致描述我們實現的 C 語言的文法,並實現其中解析變數定義部分。 由於語法分析本身比較複雜,所以我們將它拆分成 3 個部分進行講解,分別是:變數定義、函式定義、表示式。 手把手教你構建 C 語言編譯器系列共有10個部分: EBNF 表示 EBNF 是對前一章提到的 BNF 的擴充
手把手教你構建 C 語言編譯器(9)
恭喜你完成了自己的 C 語言編譯器,本章中我們發一發牢騷,說一說編寫編譯器值得注意的一些問題;編寫編譯器時遇到的一些難題。 手把手教你構建 C 語言編譯器系列共有10個部分: 虛擬機器與目的碼 整個系列的一開始,我們就著手虛擬機器的實現。不知道你是否有同感,這部分對於整個編譯器的編寫其實是十分重要的。我認
手把手教你構建 C 語言編譯器(1)
本章是“手把手教你構建 C 語言編譯器”系列的第二篇,我們要從整體上講解如何設計我們的 C 語言編譯器。 手把手教你構建 C 語言編譯器系列共有10個部分: 首先要說明的是,雖然標題是編譯器,但實際上我們構建的是 C 語言的直譯器,這意味著我們可以像執行指令碼一樣去執行 C 語言的原始碼檔案。這麼做的理由
手把手教你構建 C 語言編譯器(0)
“手把手教你構建 C 語言編譯器” 這一系列教程將帶你從頭編寫一個 C 語言的編譯器。希望通過這個系列,我們能對編譯器的構建有一定的瞭解,同時,我們也將構建出一個能用的 C 語言編譯器,儘管有許多語法並不支援。 手把手教你構建 C 語言編譯器系列共有10個部分: 在開始進入正題之前,本篇是一些閒聊,談談這