先决条件

  • 本机安装office2003、2007、2010、2016及以后版本,总之必须安装office
  • 导入Excel库文件,导入方式可参考:
  • 如何在vs2017及以前版本(vs2010、vs2015)上添加 添加类型库中的MFC类
  • 如何在vs2019及以后版本(如vs2022)上添加 添加ActiveX控件中的MFC类
  • 如何使用vs2022通过excel.exe生成VC、C++能够使用的头文件

一、导入头文件

#include "CApplication.h"
#include "CWorkbook.h"
#include "CWorkbooks.h"
#include "CWorksheet.h"
#include "CWorksheets.h"
#include "CRange.h"
#include "CFont0.h"

二、使用示例1

1、打开excel驱动及操作excel (读、写、新建sheet,选择rang,行、列等)

//默认使用第一个sheet
	int nSheetNumber=1;
	//创建对象
	CApplication app;
 
	
     if( !app.CreateDispatch(_T("Excel.Application")))
     {
		 AfxMessageBox("没有安装office2007以上版本,无法操作excel文件");
		 return ;
     }
 
	 //定义其他内部对象
	 CWorkbooks   books;
     CWorkbook    book;
     CWorksheets  sheets;
     CWorksheet   sheet;
	 CFont0 font;
	 CRange range;
 
	 CString FieldName,FieldValue;
     COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR); 
 
     books=app.get_Workbooks();
	
	 //需要在c盘建立一个excel文件,也可以改成系统自带的excel文件
    // book=books.Add(COleVariant("c:\\aa.xlsx"));
	 
     book = books.Add(covOptional); 
	 book.put_Title("Mybooks");
	
	 sheets=book.get_Sheets();	 
     sheet=sheets.get_Item(COleVariant((short)nSheetNumber));
	 sheet.put_Name("wxpSheet");
	 //---------------------
	 app.put_Visible(TRUE);//可见性
     app.put_UserControl(TRUE);//只读	
 
	  //设置标题
	  FieldName="a1";
	  FieldValue="数据A";
	  range=sheet.get_Range(COleVariant(FieldName),COleVariant(FieldName));
	  range.put_Value2(COleVariant(FieldValue));
 
	  FieldName="B1";
	  FieldValue="数据B";
	  range=sheet.get_Range(COleVariant(FieldName),COleVariant(FieldName));
	  range.put_Value2(COleVariant(FieldValue));
 
	  //填充数据-------------------------------------------------------
	  for(int row=1;row<10;++row)
	  {
		//每一行的数据 
		for(int col=0;col<10;++col)
		{
		  //放置自己的指定数据------------------------------
		  FieldName.Format("%c%d",'a'+col,(row+1));
		  FieldValue.Format("(%d,%d)",row+1,col+1);		 
 
		  range=sheet.get_Range(COleVariant(FieldName),COleVariant(FieldName));
		 // range.put_Value2(COleVariant(FieldValue));
 
		  range.put_Formula(_variant_t("=RAND()*100"));
		  range.put_NumberFormat(_variant_t("00.00"));		 
 
		   //设置隔行颜色
		   if(row %2==0)
		   {  
			   font=range.get_Font();
			   font.put_Bold(COleVariant((short)TRUE));
			   font.put_Color(COleVariant((long)RGB(255, 0, 0))); 
			   //  font.put_Name(COleVariant(_T("黑体")));	
		   }
 
		}//end of col
	  }//end of row
 
	  //设计计算公式,所有excel中的公式都可以使用-------------------------
	 
	  FieldName="a11";
	  range=sheet.get_Range(COleVariant(FieldName),COleVariant(FieldName));
 
	  range.put_Formula(COleVariant(_T("=sum(a2:a10")));
	 //自适应列宽度--------------------------------
	  CRange      cols;
      cols=range.get_EntireColumn();
      cols.AutoFit();
 
	  //::Sleep(5000);
	  //读取内容-----------------------------------------------------
	 FieldName="a11";
 
     range = sheet.get_Range(COleVariant(FieldName),COleVariant(FieldName));
 
     COleVariant cov = range.get_Value2();
 
     CString str="success";
 
	 cov.ChangeType(VT_BSTR);
	 str=cov.bstrVal;	
 
	 AfxMessageBox(str);
 
	 //------------------------------------------------------------------
	 //关闭excel文件,根据需要自行决定
	 books.Close();
     app.Quit();
     books.ReleaseDispatch();
     app.ReleaseDispatch();

2、结果

visual studio community 没有MFC_excel

三、使用示例2

1、打开指定excel,设置对齐方式,设置字体颜色,合并单元格

//变量定义
CApplication app;          //Excel应用程序接口
CWorkbooks books;         //工作薄集合
CWorkbook book;          //工作薄
CWorksheets sheets;         //工作表集合
CWorksheet sheet;          //工作表
CRange range;                 //Excel中针对单元格的操作都应先获取其对应的Range对象
CFont0 font;
CRange cols;
CRange iCell;
LPDISPATCH lpDisp;
COleVariant vResult;
COleVariant	covTrue((short)TRUE);
COleVariant covFalse((short)FALSE);
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);

//初始化
if (!app.CreateDispatch("Excel.Application"))
{
	this->MessageBox("无法创建Excel应用!");
	return;
}

app.put_Visible(FALSE);     //可见
app.put_UserControl(TRUE); //用户可控制

//打开XLS文件
books.AttachDispatch(app.get_Workbooks());
lpDisp = books.Open("C:\\test\\excel\\test.xlsx",
	covOptional, covOptional, covOptional, covOptional, covOptional,
	covOptional, covOptional, covOptional, covOptional, covOptional,
	covOptional, covOptional, covOptional, covOptional);

//得到Workbook
book.AttachDispatch(lpDisp);

//得到Worksheets
sheets.AttachDispatch(book.get_Worksheets());

//得到当前活跃sheet
//如果有单元格正处于编辑状态中,此操作不能返回,会一直等待

lpDisp = book.get_ActiveSheet();
sheet.AttachDispatch(lpDisp);

//*****
//读取已经使用区域的信息,包括已经使用的行数、列数、起始行、起始列
CRange usedRange;

usedRange.AttachDispatch(sheet.get_UsedRange());
range.AttachDispatch(usedRange.get_Rows());

//已经使用的行数
long iRowNum = range.get_Count();
range.AttachDispatch(usedRange.get_Columns());

//已经使用的列数
long iColNum = range.get_Count();

//已使用区域的起始行,从开始
long iStartRow = usedRange.get_Row();

//已使用区域的起始列,从开始
long iStartCol = usedRange.get_Column();


//读取第一个单元格的值
range.AttachDispatch(sheet.get_Cells());

range.AttachDispatch(range.get_Item(COleVariant((long)1), COleVariant((long)1)).pdispVal);

vResult = range.get_Value2();

CString str;
if (vResult.vt == VT_BSTR)       //字符串
{
	str = vResult.bstrVal;
}
else if (vResult.vt == VT_R8)     //8字节的数字

{
	str.Format("%f", vResult.dblVal);
}
else if (vResult.vt == VT_DATE)    //时间格式
{
	SYSTEMTIME st;
	VariantTimeToSystemTime((long)&vResult.date, &st);
}
else if (vResult.vt == VT_EMPTY)   //单元格空的
{
	str = "";
}

//读取第一个单元格的对齐方式,数据类型:VT_I4
//读取水平对齐方式
range.AttachDispatch(sheet.get_Cells());
iCell.AttachDispatch((range.get_Item(COleVariant(long(1)), COleVariant(long(1)))).pdispVal);
vResult.lVal = 0;
vResult = iCell.get_HorizontalAlignment();
if (vResult.lVal != 0)
{
	switch (vResult.lVal)
	{
	case 1:      //默认
		break;
	case -4108:  //居中
		break;
	case -4131: //*左
		break;
	case -4152: //*右
		break;
	}
}

//垂直对齐方式
iCell.AttachDispatch((range.get_Item(COleVariant(long(1)), COleVariant(long(1)))).pdispVal);
vResult.lVal = 0;

vResult = iCell.get_VerticalAlignment();
if (vResult.lVal != 0)
{
	switch (vResult.lVal)
	{
	case -4160:  //*上
		break;
	case -4108:  //居中
		break;
	case -4107:  //*下
		break;
	}
}

//设置第一个单元格字体颜色:红色
range.AttachDispatch(sheet.get_Cells());
range.AttachDispatch((range.get_Item(COleVariant(long(1)), COleVariant(long(1)))).pdispVal);

font.AttachDispatch(range.get_Font());
font.put_Color(COleVariant((long)0xFF0000));

//合并单元格的处理
 //包括判断第一个单元格是否为合并单元格,以及将第一个单元格进行合并
CRange unionRange;

range.AttachDispatch(sheet.get_Cells());
unionRange.AttachDispatch(range.get_Item(COleVariant((long)1), COleVariant((long)1)).pdispVal);

vResult = unionRange.get_MergeCells();
if (vResult.boolVal == -1)             //是合并的单元格  
{
	//合并单元格的行数
	range.AttachDispatch(unionRange.get_Rows());
	long iUnionRowNum = range.get_Count();

	//合并单元格的列数
	range.AttachDispatch(unionRange.get_Columns());
	long iUnionColumnNum = range.get_Count();

	//合并区域的起始行,列
	long iUnionStartRow = unionRange.get_Row();       //起始行,从开始
	long iUnionStartCol = unionRange.get_Column();    //起始列,从开始
}

else if (vResult.boolVal == 0)
{
	//不是合并的单元格
}


//将第一个单元格合并成行,列
range.AttachDispatch(sheet.get_Cells());

unionRange.AttachDispatch(range.get_Item(COleVariant((long)1), COleVariant((long)1)).pdispVal); //第一个单元格
unionRange.AttachDispatch(unionRange.get_Resize(COleVariant((long)3), COleVariant((long)2)));     //GetResize(3,2) 从第一个单元格开始合并行列的所有单元格
unionRange.Merge(COleVariant((long)0));   //合并单元格

//将文件保存为.xls
app.put_DisplayAlerts(FALSE);
book.SaveAs(COleVariant("C:\\test\\excel\\test1.xlsx"), covOptional, covOptional,
	covOptional, covOptional, covOptional, 0,
	covOptional, covOptional, covOptional, covOptional, covOptional, covOptional);
//book.Save();

book.Close(covOptional, COleVariant("C:\\test\\excel\\test.xlsx"), covOptional);
books.Close();

//释放对象(相当重要!)
range.ReleaseDispatch();
cols.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
//App一定要释放,否则程序结束后还会有一个Excel进程驻留在内存中,而且程序重复运行的时候会出错
app.Quit();
app.ReleaseDispatch();

2、结果

visual studio community 没有MFC_excel操作_02


更多使用方式,可以参考VC 设置EXCEL单元格的格式