环境:VS2017、Office2013、Windows10
本实例功能:从一个INI文件、一个现有的Office Excel中读取数据,写入到一个新的Excel中
效果:
1.新建一个基于对话框的MFC程序,本实例项目名为ExcelAndINI,如下
2. 新增Read、Write按钮的响应事件,如下
void CExcelAndINIDlg::OnBnClickedBtnRead()
{
// TODO: 在此添加控件通知处理程序代码
}
void CExcelAndINIDlg::OnBnClickedBtnWrite()
{
// TODO: 在此添加控件通知处理程序代码
}
3. 增加Excel _Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range六个操作类,如下
4.在新增的六个OFFICE类的头文件中,做如下动作
//#import "D:\\Program Files\\office\\Office15\\EXCEL.EXE" no_namespace 注释掉此语句
// CRange 包装器类
#pragma once //增加此语句
5. 在ExcelAndINIDlg.cpp中增加六个OFFICE类的头文件
#include "CApplication.h"
#include "CWorkbooks.h"
#include "CWorkbook.h"
#include "CWorksheets.h"
#include "CWorksheet.h"
#include "CRange.h"
6.此时编译出现如下错误
解决方法:双击此error调到此方法实现处,在此方法名前增加下划线_,重新编译即OK
VARIANT _DialogBox()
{
VARIANT result;
InvokeHelper(0xf5, DISPATCH_METHOD, VT_VARIANT, (void*)&result, nullptr);
return result;
}
7. 在CExcelAndINIDlg类中新增三个Public方法
int CExcelAndINIDlg::ReadINIFile()
{
// TODO: 在此处添加实现代码.
return 0;
}
int CExcelAndINIDlg::ReadExcelFile()
{
// TODO: 在此处添加实现代码.
return 0;
}
int CExcelAndINIDlg::GetWorkDir()
{
// TODO: 在此处添加实现代码.用于获取程序所在路径
return 0;
}
8.在CExcelAndINIDlg新增如下Public变量
CString strINI1; //读取INI文件内容CString变量1
CString strINI2; //读取INI文件内容CString变量2
CString strINI3; //读取INI文件内容CString变量3
CString strINI4; //读取INI文件内容CString变量4
CString strExcel1; //读取Excel文件内容CString变量1
CString strExcel2; //读取Excel文件内容CString变量2
CString strINIFilePath; //用于保存数据源INI文件路径
CString strExcleFilePath; //用于保存数据源Excel文件路径
CString strOutputExcleFilePath; //用于保存输出Excel文件路径
CString strWorkDir; //用于保存exe所在路径
9. 在CExcelAndINIDlg::GetWorkDir()方法中增加如下代码
{
// TODO: 在此处添加实现代码.
GetCurrentDirectory(MAX_PATH, pFileName);
CString dir(pFileName);
strWorkDir = dir;
return 0;
}
10.在CExcelAndINIDlg::ReadINIFile()方法中增加如下代码
{
// TODO: 在此处添加实现代码.
strINIFilePath = strWorkDir + _T("\\INITest.ini"); //exe所在路径当前路径下的ini文件
GetPrivateProfileString(_T("Section1"), _T("Item2"), _T(""), strINI2.GetBuffer(MAX_PATH), MAX_PATH, strINIFilePath);
GetPrivateProfileString(_T("Section2"), _T("Item2"), _T(""), strINI4.GetBuffer(MAX_PATH), MAX_PATH, strINIFilePath);
}
11.在int CExcelAndINIDlg::ReadExcelFile()方法中增加如下代码
{
// TODO: 在此处添加实现代码.
strExcleFilePath = strWorkDir + _T("\\ExcelTest.xlsx"); //exe所在路径当前路径下的Excel文件
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
LPDISPATCH lpDisp;
COleVariant vResult;
covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
{
MessageBox(_T("Error!Creat Excel Application Server Faile!"));
return -1;
}
lpDisp = books.Open(strExcleFilePath,
covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional, covOptional, covOptional,
covOptional, covOptional);
//book = books.Add(covOptional); //获取当前工作薄,若使用此语句,则为新建一个EXCEL表
sheets = book.get_Worksheets(); //获取当前工作薄页的集合
sheet = sheets.get_Item(COleVariant((short)1)); //获取当前活动页,第一页sheet1
range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("A1"))); //获取单元格
vResult = COleVariant(range.get_Value2());
strExcel1 = CString(vResult.bstrVal);
range = sheet.get_Range(COleVariant(_T("B1")), COleVariant(_T("B1"))); //获取单元格
vResult = COleVariant(range.get_Value2());
strExcel2 = CString(vResult.bstrVal);
MessageBox(strExcel2);
range.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch(); //释放当前工作薄
books.ReleaseDispatch(); //释放工作薄集
app.Quit(); //退出EXCEL程序
app.ReleaseDispatch(); //释放EXCEL程序
}
12.在void CExcelAndINIDlg::OnBnClickedBtnRead()方法中增加如下代码
{
// TODO: 在此添加控件通知处理程序代码
GetWorkDir();
ReadExcelFile();
13.在void CExcelAndINIDlg::OnBnClickedBtnWrite()方法中增加如下代码
{
// TODO: 在此添加控件通知处理程序代码
CApplication app;
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
COleVariant vResult;
CString strTemp;
covTrue((short)TRUE),
covFalse((short)FALSE),
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
{
MessageBox(_T("Error!Creat Excel Application Server Faile!"));
return;
}
books = app.get_Workbooks(); //获取工作薄集合
book = books.Add(covOptional); //获取当前工作薄,若使用此语句,则为新建一个EXCEL表
sheets = book.get_Worksheets(); //获取当前工作薄页的集合
sheet = sheets.get_Item(COleVariant((short)1)); //获取当前活动页
range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("A1"))); //获取单元格
strTemp.Format(_T("%s"), strINI1);//从ini文件中读取到的数据,需要用CString::Format()再次将字符串格式化一下才能正确写入到Excel中
range.put_Value2(COleVariant(strTemp)); //将内容填入单元格
strTemp.Format(_T("%s"), strINI2);
range.put_Value2(COleVariant(strTemp));
strTemp.Format(_T("%s"), strINI3);
range.put_Value2(COleVariant(strTemp));
strTemp.Format(_T("%s"), strINI4);
range.put_Value2(COleVariant(strTemp));
range = sheet.get_Range(COleVariant(_T("A5")), COleVariant(_T("A5"))); //获取单元格
range.put_Value2(COleVariant(strExcel1));
range.put_Value2(COleVariant(strExcel2));
book.SaveCopyAs(COleVariant(strOutputExcleFilePath));
book.put_Saved(true);
app.put_Visible(FALSE); //FALSE表示操作完,不打开工作表,若此处为FALSE,则一定需要调用app.Quit(),以避免程序结束后,还有EXCEL进程
range.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch(); //释放当前工作薄
books.ReleaseDispatch(); //释放工作薄集
app.ReleaseDispatch(); //释放EXCEL程序
说明:
1.对于有下拉菜单的Excel表项,其读写方式与普通单元格没有差别。
2.对于合并单元格的读写,可以按照普通单元格读写,如B1、C1为合并单元格,对B1按照普通单元格操作即可。
3.对从ini文件读取的内容写入到Excel表中前,一定要先使用Format方法格式化一下,不然写入到Excel为空。
实例代码链接:https://pan.baidu.com/s/1nS3t1n4HkkYdGXzJ1nxJNQ 提取码:kkjn