寫了不少blog,也碼了一點點文字,不知道為啥,被大家看的比較多幾篇文章卻總有那篇《C++讀寫EXCEL文件方式比較 》。
小小傷心一下,我blog里面寫的很認真的文字還有幾篇,這篇大概是最隨意的文章。個人估計這是SEO的作用導致的。
另外,由於文中提到了可以加快OLE讀取的EXCEL的速度,總有一些哥們找我要代碼。
好吧,好吧,把代碼放出來,因為我原來也是找人家的代碼逐步改的。來而不往非禮也。
我的代碼參考的地方是這兒,再次感謝原作者
http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx
我根據自己的需要做了整理,干凈了一點,而后根據發現的速度問題做了一些優化。
預加載的思路來自這個帖子
http://topic.csdn.net/t/20030626/21/1962211.html
其實思路很簡單,不再一個CELL一個CELL的傴數據,而是一次把表格里面所有的數據讀取出來處理。
.h文件的源碼代碼如下:
其中的頭文件都是OLE的頭文件。如何導出可以參考
http://blog.csdn.net/wyz365889/article/details/7599924
我自己這兒一直保存了一套別人生成的這幾個文件,也可以用。大家可以找找有沒有下載的,不過我不太確認跨版本是否可行。
還有既然是OLE,你一定要安裝EXCEL的。
1 #pragma once 2 3 //OLE的頭文件 4 #include <CRange.h> 5 #include <CWorkbook.h> 6 #include <CWorkbooks.h> 7 #include <CWorksheet.h> 8 #include <CWorksheets.h> 9 #include <CApplication.h> 10 11 /// 12 ///用於OLE的方式的EXCEL讀寫, 13 class IllusionExcelFile 14 { 15 16 public: 17 18 //構造函數和析構函數 19 IllusionExcelFile(); 20 virtual ~IllusionExcelFile(); 21 22 protected: 23 ///打開的EXCEL文件名稱 24 CString open_excel_file_; 25 26 ///EXCEL BOOK集合,(多個文件時) 27 CWorkbooks excel_books_; 28 ///當前使用的BOOK,當前處理的文件 29 CWorkbook excel_work_book_; 30 ///EXCEL的sheets集合 31 CWorksheets excel_sheets_; 32 ///當前使用sheet 33 CWorksheet excel_work_sheet_; 34 ///當前的操作區域 35 CRange excel_current_range_; 36 37 38 ///是否已經預加載了某個sheet的數據 39 BOOL already_preload_; 40 ///Create the SAFEARRAY from the VARIANT ret. 41 COleSafeArray ole_safe_array_; 42 43 protected: 44 45 ///EXCEL的進程實例 46 static CApplication excel_application_; 47 public: 48 49 /// 50 void ShowInExcel(BOOL bShow); 51 52 ///檢查一個CELL是否是字符串 53 BOOL IsCellString(long iRow, long iColumn); 54 ///檢查一個CELL是否是數值 55 BOOL IsCellInt(long iRow, long iColumn); 56 57 ///得到一個CELL的String 58 CString GetCellString(long iRow, long iColumn); 59 ///得到整數 60 int GetCellInt(long iRow, long iColumn); 61 ///得到double的數據 62 double GetCellDouble(long iRow, long iColumn); 63 64 ///取得行的總數 65 int GetRowCount(); 66 ///取得列的總數 67 int GetColumnCount(); 68 69 ///使用某個shet,shit,shit 70 BOOL LoadSheet(long table_index,BOOL pre_load = FALSE); 71 ///通過名稱使用某個sheet, 72 BOOL LoadSheet(const char* sheet,BOOL pre_load = FALSE); 73 ///通過序號取得某個Sheet的名稱 74 CString GetSheetName(long table_index); 75 76 ///得到Sheet的總數 77 int GetSheetCount(); 78 79 ///打開文件 80 BOOL OpenExcelFile(const char * file_name); 81 ///關閉打開的Excel 文件,有時候打開EXCEL文件就要 82 void CloseExcelFile(BOOL if_save = FALSE); 83 //另存為一個EXCEL文件 84 void SaveasXSLFile(const CString &xls_file); 85 ///取得打開文件的名稱 86 CString GetOpenFileName(); 87 ///取得打開sheet的名稱 88 CString GetLoadSheetName(); 89 90 ///寫入一個CELL一個int 91 void SetCellInt(long irow, long icolumn,int new_int); 92 ///寫入一個CELL一個string 93 void SetCellString(long irow, long icolumn,CString new_string); 94 95 public: 96 ///初始化EXCEL OLE 97 static BOOL InitExcel(); 98 ///釋放EXCEL的 OLE 99 static void ReleaseExcel(); 100 ///取得列的名稱,比如27->AA 101 static char *GetColumnName(long iColumn); 102 103 protected: 104 105 //預先加載 106 void PreLoadSheet(); 107 };
CPP文件的與代碼如下:
1 /****************************************************************************************** 2 Copyright : 2000-2004, Appache 2.0 3 FileName : illusion_excel_file.cpp 4 Author : Sail 5 Version : 6 Date Of Creation : 2009年4月3日 7 Description : 8 9 Others : 10 Function List : 11 1. ...... 12 Modification History: 13 1.Date : 14 Author : 15 Modification : 16 17 這個類是從網上下載的,我坐享其成,感謝原來的作者,我只試試是稍稍做了一下修正。 18 修正包括一些參數的使用不謹慎,bool 改為BOOL等,對於對象關系,我改了一部分,感覺原來的作者對於OO的思路部分不是很清楚。 19 對於這類東西OLE,我完全不了解,用別人封裝的東西感覺還是放心了很多,C++,偉大的C++ 20 http://blog.csdn.net/gyssoft/archive/2007/04/29/1592104.aspx 21 22 OLE讀寫EXCEL都比較慢,所以應該盡量減少OLE的次數 23 對於讀取,還有解決方法,請試用一下預加載的方式,這個方法一次加載所有的讀取數據,如此速度就飛快了。 24 據說寫數據是沒有什么方法加快的 25 http://topic.csdn.net/t/20030626/21/1962211.html 26 27 增加了一些寫入方式的代碼,保證可以寫入EXCEL數據區,但是對於保存,我發現如果調用CLOSE並且保存的方式, 28 速度非常慢,我不理解為什么。 29 所以我吧EXCEL打開了,讓你進行后續管理, 30 31 32 ******************************************************************************************/ 33 34 35 36 37 //-----------------------excelfile.cpp---------------- 38 39 #include "StdAfx.h" 40 #include "illusion_excel_file.h" 41 42 43 44 COleVariant 45 covTrue((short)TRUE), 46 covFalse((short)FALSE), 47 covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR); 48 49 // 50 CApplication IllusionExcelFile::excel_application_; 51 52 53 IllusionExcelFile::IllusionExcelFile(): 54 already_preload_(FALSE) 55 { 56 } 57 58 IllusionExcelFile::~IllusionExcelFile() 59 { 60 // 61 CloseExcelFile(); 62 } 63 64 65 //初始化EXCEL文件, 66 BOOL IllusionExcelFile::InitExcel() 67 { 68 69 //創建Excel 2000服務器(啟動Excel) 70 if (!excel_application_.CreateDispatch("Excel.Application",NULL)) 71 { 72 AfxMessageBox("創建Excel服務失敗,你可能沒有安裝EXCEL,請檢查!"); 73 return FALSE; 74 } 75 76 excel_application_.put_DisplayAlerts(FALSE); 77 return TRUE; 78 } 79 80 // 81 void IllusionExcelFile::ReleaseExcel() 82 { 83 excel_application_.Quit(); 84 excel_application_.ReleaseDispatch(); 85 excel_application_=NULL; 86 } 87 88 //打開excel文件 89 BOOL IllusionExcelFile::OpenExcelFile(const char *file_name) 90 { 91 //先關閉 92 CloseExcelFile(); 93 94 //利用模板文件建立新文檔 95 excel_books_.AttachDispatch(excel_application_.get_Workbooks(),true); 96 97 LPDISPATCH lpDis = NULL; 98 lpDis = excel_books_.Add(COleVariant(file_name)); 99 if (lpDis) 100 { 101 excel_work_book_.AttachDispatch(lpDis); 102 //得到Worksheets 103 excel_sheets_.AttachDispatch(excel_work_book_.get_Worksheets(),true); 104 105 //記錄打開的文件名稱 106 open_excel_file_ = file_name; 107 108 return TRUE; 109 } 110 111 return FALSE; 112 } 113 114 //關閉打開的Excel 文件,默認情況不保存文件 115 void IllusionExcelFile::CloseExcelFile(BOOL if_save) 116 { 117 //如果已經打開,關閉文件 118 if (open_excel_file_.IsEmpty() == FALSE) 119 { 120 //如果保存,交給用戶控制,讓用戶自己存,如果自己SAVE,會出現莫名的等待 121 if (if_save) 122 { 123 ShowInExcel(TRUE); 124 } 125 else 126 { 127 // 128 excel_work_book_.Close(COleVariant(short(FALSE)),COleVariant(open_excel_file_),covOptional); 129 excel_books_.Close(); 130 } 131 132 //打開文件的名稱清空 133 open_excel_file_.Empty(); 134 } 135 136 137 138 excel_sheets_.ReleaseDispatch(); 139 excel_work_sheet_.ReleaseDispatch(); 140 excel_current_range_.ReleaseDispatch(); 141 excel_work_book_.ReleaseDispatch(); 142 excel_books_.ReleaseDispatch(); 143 } 144 145 void IllusionExcelFile::SaveasXSLFile(const CString &xls_file) 146 { 147 excel_work_book_.SaveAs(COleVariant(xls_file), 148 covOptional, 149 covOptional, 150 covOptional, 151 covOptional, 152 covOptional, 153 0, 154 covOptional, 155 covOptional, 156 covOptional, 157 covOptional, 158 covOptional); 159 return; 160 } 161 162 163 int IllusionExcelFile::GetSheetCount() 164 { 165 return excel_sheets_.get_Count(); 166 } 167 168 169 CString IllusionExcelFile::GetSheetName(long table_index) 170 { 171 CWorksheet sheet; 172 sheet.AttachDispatch(excel_sheets_.get_Item(COleVariant((long)table_index)),true); 173 CString name = sheet.get_Name(); 174 sheet.ReleaseDispatch(); 175 return name; 176 } 177 178 //按照序號加載Sheet表格,可以提前加載所有的表格內部數據 179 BOOL IllusionExcelFile::LoadSheet(long table_index,BOOL pre_load) 180 { 181 LPDISPATCH lpDis = NULL; 182 excel_current_range_.ReleaseDispatch(); 183 excel_work_sheet_.ReleaseDispatch(); 184 lpDis = excel_sheets_.get_Item(COleVariant((long)table_index)); 185 if (lpDis) 186 { 187 excel_work_sheet_.AttachDispatch(lpDis,true); 188 excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true); 189 } 190 else 191 { 192 return FALSE; 193 } 194 195 already_preload_ = FALSE; 196 //如果進行預先加載 197 if (pre_load) 198 { 199 PreLoadSheet(); 200 already_preload_ = TRUE; 201 } 202 203 return TRUE; 204 } 205 206 //按照名稱加載Sheet表格,可以提前加載所有的表格內部數據 207 BOOL IllusionExcelFile::LoadSheet(const char* sheet,BOOL pre_load) 208 { 209 LPDISPATCH lpDis = NULL; 210 excel_current_range_.ReleaseDispatch(); 211 excel_work_sheet_.ReleaseDispatch(); 212 lpDis = excel_sheets_.get_Item(COleVariant(sheet)); 213 if (lpDis) 214 { 215 excel_work_sheet_.AttachDispatch(lpDis,true); 216 excel_current_range_.AttachDispatch(excel_work_sheet_.get_Cells(), true); 217 218 } 219 else 220 { 221 return FALSE; 222 } 223 // 224 already_preload_ = FALSE; 225 //如果進行預先加載 226 if (pre_load) 227 { 228 already_preload_ = TRUE; 229 PreLoadSheet(); 230 } 231 232 return TRUE; 233 } 234 235 //得到列的總數 236 int IllusionExcelFile::GetColumnCount() 237 { 238 CRange range; 239 CRange usedRange; 240 usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true); 241 range.AttachDispatch(usedRange.get_Columns(), true); 242 int count = range.get_Count(); 243 usedRange.ReleaseDispatch(); 244 range.ReleaseDispatch(); 245 return count; 246 } 247 248 //得到行的總數 249 int IllusionExcelFile::GetRowCount() 250 { 251 CRange range; 252 CRange usedRange; 253 usedRange.AttachDispatch(excel_work_sheet_.get_UsedRange(), true); 254 range.AttachDispatch(usedRange.get_Rows(), true); 255 int count = range.get_Count(); 256 usedRange.ReleaseDispatch(); 257 range.ReleaseDispatch(); 258 return count; 259 } 260 261 //檢查一個CELL是否是字符串 262 BOOL IllusionExcelFile::IsCellString(long irow, long icolumn) 263 { 264 CRange range; 265 range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true); 266 COleVariant vResult =range.get_Value2(); 267 //VT_BSTR標示字符串 268 if(vResult.vt == VT_BSTR) 269 { 270 return TRUE; 271 } 272 return FALSE; 273 } 274 275 //檢查一個CELL是否是數值 276 BOOL IllusionExcelFile::IsCellInt(long irow, long icolumn) 277 { 278 CRange range; 279 range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true); 280 COleVariant vResult =range.get_Value2(); 281 //好像一般都是VT_R8 282 if(vResult.vt == VT_INT || vResult.vt == VT_R8) 283 { 284 return TRUE; 285 } 286 return FALSE; 287 } 288 289 // 290 CString IllusionExcelFile::GetCellString(long irow, long icolumn) 291 { 292 293 COleVariant vResult ; 294 CString str; 295 //字符串 296 if (already_preload_ == FALSE) 297 { 298 CRange range; 299 range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true); 300 vResult =range.get_Value2(); 301 range.ReleaseDispatch(); 302 } 303 //如果數據依據預先加載了 304 else 305 { 306 long read_address[2]; 307 VARIANT val; 308 read_address[0] = irow; 309 read_address[1] = icolumn; 310 ole_safe_array_.GetElement(read_address, &val); 311 vResult = val; 312 } 313 314 if(vResult.vt == VT_BSTR) 315 { 316 str=vResult.bstrVal; 317 } 318 //整數 319 else if (vResult.vt==VT_INT) 320 { 321 str.Format("%d",vResult.pintVal); 322 } 323 //8字節的數字 324 else if (vResult.vt==VT_R8) 325 { 326 str.Format("%0.0f",vResult.dblVal); 327 } 328 //時間格式 329 else if(vResult.vt==VT_DATE) 330 { 331 SYSTEMTIME st; 332 VariantTimeToSystemTime(vResult.date, &st); 333 CTime tm(st); 334 str=tm.Format("%Y-%m-%d"); 335 336 } 337 //單元格空的 338 else if(vResult.vt==VT_EMPTY) 339 { 340 str=""; 341 } 342 343 return str; 344 } 345 346 double IllusionExcelFile::GetCellDouble(long irow, long icolumn) 347 { 348 double rtn_value = 0; 349 COleVariant vresult; 350 //字符串 351 if (already_preload_ == FALSE) 352 { 353 CRange range; 354 range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true); 355 vresult =range.get_Value2(); 356 range.ReleaseDispatch(); 357 } 358 //如果數據依據預先加載了 359 else 360 { 361 long read_address[2]; 362 VARIANT val; 363 read_address[0] = irow; 364 read_address[1] = icolumn; 365 ole_safe_array_.GetElement(read_address, &val); 366 vresult = val; 367 } 368 369 if (vresult.vt==VT_R8) 370 { 371 rtn_value = vresult.dblVal; 372 } 373 374 return rtn_value; 375 } 376 377 //VT_R8 378 int IllusionExcelFile::GetCellInt(long irow, long icolumn) 379 { 380 int num; 381 COleVariant vresult; 382 383 if (already_preload_ == FALSE) 384 { 385 CRange range; 386 range.AttachDispatch(excel_current_range_.get_Item (COleVariant((long)irow),COleVariant((long)icolumn)).pdispVal, true); 387 vresult = range.get_Value2(); 388 range.ReleaseDispatch(); 389 } 390 else 391 { 392 long read_address[2]; 393 VARIANT val; 394 read_address[0] = irow; 395 read_address[1] = icolumn; 396 ole_safe_array_.GetElement(read_address, &val); 397 vresult = val; 398 } 399 // 400 num = static_cast<int>(vresult.dblVal); 401 402 return num; 403 } 404 405 void IllusionExcelFile::SetCellString(long irow, long icolumn,CString new_string) 406 { 407 COleVariant new_value(new_string); 408 CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional); 409 CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) ); 410 write_range.put_Value2(new_value); 411 start_range.ReleaseDispatch(); 412 write_range.ReleaseDispatch(); 413 414 } 415 416 void IllusionExcelFile::SetCellInt(long irow, long icolumn,int new_int) 417 { 418 COleVariant new_value((long)new_int); 419 420 CRange start_range = excel_work_sheet_.get_Range(COleVariant("A1"),covOptional); 421 CRange write_range = start_range.get_Offset(COleVariant((long)irow -1),COleVariant((long)icolumn -1) ); 422 write_range.put_Value2(new_value); 423 start_range.ReleaseDispatch(); 424 write_range.ReleaseDispatch(); 425 } 426 427 428 // 429 void IllusionExcelFile::ShowInExcel(BOOL bShow) 430 { 431 excel_application_.put_Visible(bShow); 432 excel_application_.put_UserControl(bShow); 433 } 434 435 //返回打開的EXCEL文件名稱 436 CString IllusionExcelFile::GetOpenFileName() 437 { 438 return open_excel_file_; 439 } 440 441 //取得打開sheet的名稱 442 CString IllusionExcelFile::GetLoadSheetName() 443 { 444 return excel_work_sheet_.get_Name(); 445 } 446 447 //取得列的名稱,比如27->AA 448 char *IllusionExcelFile::GetColumnName(long icolumn) 449 { 450 static char column_name[64]; 451 size_t str_len = 0; 452 453 while(icolumn > 0) 454 { 455 int num_data = icolumn % 26; 456 icolumn /= 26; 457 if (num_data == 0) 458 { 459 num_data = 26; 460 icolumn--; 461 } 462 column_name[str_len] = (char)((num_data-1) + 'A' ); 463 str_len ++; 464 } 465 column_name[str_len] = '\0'; 466 //反轉 467 _strrev(column_name); 468 469 return column_name; 470 } 471 472 //預先加載 473 void IllusionExcelFile::PreLoadSheet() 474 { 475 476 CRange used_range; 477 478 used_range = excel_work_sheet_.get_UsedRange(); 479 480 481 VARIANT ret_ary = used_range.get_Value2(); 482 if (!(ret_ary.vt & VT_ARRAY)) 483 { 484 return; 485 } 486 // 487 ole_safe_array_.Clear(); 488 ole_safe_array_.Attach(ret_ary); 489 }
【本文作者是雁渡寒潭,本着自由的精神,你可以在無盈利的情況完整轉載此文檔,轉載時請附上BLOG鏈接:http://www.cnblogs.com/fullsail/ 或者http://blog.csdn.net/fullsail,否則每字一元,每圖一百不講價。對Baidu文庫。360doc加價一倍】