工作经常遇到的需求之一,将数据保存至Excel中,然后对Excel中的数据进行一系列操作,本篇文章简单记录这个个过程。
本闻主要实现Excel的读写等一些基本操作,依赖于OLE/COM的Excel库实现,需要先对这些接口进行导入。接口主要是_Application、Workbooks、_Workbook、Worksheets、_Worksheet、Range、Interior、Cfond 类
部分接口说明如图下:
可以通过注册表或者文件的形式导入,注册表打开如果找不到对应的库,可以选择用文件,用everything全局搜索Excel.exe。在位置处搜索到该exe所在路径即可。
需要导入的接口如下图:
点击添加之后,进入各个头文件中注释掉 “#import "C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE" no_namespace”这句话,VC的特性,不需要再次import。
另外如果出现变量名重定义的话,可以对其做一个修改。具体修改方式可以自行百度,不太重要。
至此接口就添加完毕,include对应的.h之后就可以直接对表格内进行读写操作了。
// 初始化Excel库
bool CExcel_TestDlg::InitExcel()
{
HRESULT ht;
ht = ::CoInitialize(NULL);
if (ht == E_INVALIDARG)
{
MessageBox(_T("初始化COM失败"));
}
//创建Execel(启动Excel)
if (!m_App.CreateDispatch(_T("Excel.application"), nullptr))
{
MessageBox(_T("Error!Creat Excel Application Sever Fail!"));
exit(1);
return FALSE;
}
m_App.put_Visible(FALSE);//是否显示EXCEL
m_App.put_DisplayFullScreen(FALSE);//设置全屏显示
m_App.put_DisplayAlerts(FALSE);//屏蔽警告
return TRUE;
}
BOOL CExcel_TestDlg::CreatNewExcel(CString strPath)
{
//InitExcel();
m_Books = m_App.get_Workbooks();
try
{
m_WorkBook = m_Books.Add(_variant_t(strPath));//打开EXCEL文件
}
catch (CException* e)
{
m_WorkBook = m_Books.Add(vtMissing);//找不到就新建一个
}
m_OpenFileName = strPath;
m_WorkSheet = m_WorkBook.get_ActiveSheet();//获取当前工作表
//保存 定义变量//
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
m_WorkBook.SaveAs(COleVariant(strPath),
covOptional,
covOptional,
covOptional,
covOptional,
covOptional,
0,
covOptional,
covOptional,
covOptional,
covOptional,
covOptional,
covOptional);
//释放资源 - 演示用,如果需要对其操作,当然是先不用关闭了
close();
//关闭应用
m_App.Quit();
m_App.ReleaseDispatch();
m_App = nullptr;
return TRUE;
}
void CExcel_TestDlg::close(BOOL ifSave /*= FALSE*/)
{
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
//如果文件已经打开,先关闭文件
if (!m_OpenFileName.IsEmpty())
{
//如果保存,交给用户控制,让用户自己存,如果自己SAVE,会出现莫名的等待
if (ifSave)
{
}
else
{
m_WorkBook.Close(COleVariant(short(FALSE)), COleVariant(m_OpenFileName), covOptional);
m_Books.Close();
}
//清空打开文件名称
m_OpenFileName.Empty();
}
m_Sheets.ReleaseDispatch();
m_WorkSheet.ReleaseDispatch();
m_CurRange.ReleaseDispatch();
m_WorkBook.ReleaseDispatch();
m_Books.ReleaseDispatch();
//m_App.Quit();
return;
}
SYSTEMTIME sys;
GetLocalTime(&sys);
CString strFileName;
strTmp.Format("%04d%02d%02d", sys.wYear, sys.wMonth, sys.wDay + 100);
strFileName.Format("%s\\%s.xlsx", sPath, strTmp);
CApplication app;
CWorkbooks books;
CWorkbook book;
CWorksheets sheets;
CWorksheet sheet;
CRange range;
LPDISPATCH lpDisp = NULL;
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
if (!app.CreateDispatch(_T("Excel.Application")))
{
MessageBox(_T("Error!Creat Excel Application Sever Fail!"));
exit(1);
}
books.AttachDispatch(app.get_Workbooks());
//获得所有工作表
books.AttachDispatch(app.get_Workbooks());
try
{
lpDisp = books.Open(strFileName, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional);
}
catch (CException* e)
{
// r如果该路径没有表格则生成一个表格
CreatNewExcel(strFileName);
// 再次打开
lpDisp = books.Open(strFileName, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional, covOptional);
m_IsNewCreat = TRUE;
}
book.AttachDispatch(lpDisp);//得到Workbook
sheets.AttachDispatch(book.get_Worksheets());//得到Worksheets
lpDisp = book.get_ActiveSheet();//得到当前活跃sheet,如果有单元格正处于编辑状态中,此操作不能返回,会一直等待
sheet.AttachDispatch(lpDisp);
CString strTemp, strTemp1;
CString str[] = { _T("时间(时分秒)") ,_T("结果"),"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20" };
vector HeadString(str, str + 22);
for (int i = 0; i < HeadString.size(); ++i)
{
range = sheet.get_Range(COleVariant(_T("A1")), COleVariant(_T("A1")));
range.put_ColumnWidth(_variant_t((long)20)); // 指定区域 设置列宽
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
range.AttachDispatch(sheet.get_Cells());
range.AttachDispatch(range.get_Item(COleVariant((long)nRow), COleVariant((long)nCol)).pdispVal);
// 给单元格写入值
range.put_Value(covOptional, _variant_t(strValue));
// 给单元格设置字体格式
CFont0 ft;
ft.AttachDispatch(range.get_Font());
ft.put_Name(_variant_t(_T("宋体")));
ft.put_Size(_variant_t(8));
ft.put_Color(_variant_t(RGB(255, 0, 0)));
// 给单元格设置底色
interior.AttachDispatch(range.get_Interior());
//将底色改为红色 44-对应浅黄色 具体数值对应颜色看这个链接 https://msdn.microsoft.com/en-us/library/cc296089.aspx
interior.put_ColorIndex(_variant_t((long)44));
}
int rows,cols; // 整数型行列,以获取指定单元格
rows = 1;
cols = 1;
range.AttachDispatch(range.get_Item(COleVariant((long)rows), COleVariant((long)cols)).pdispVal);
COleVariant vResult;
vResult = range.get_Value2();
CString data;
if (vResult.vt == VT_BSTR) //字符串
{
data = vResult.bstrVal;
}
else if (vResult.vt == VT_R8) //8字节的数字
{
data.Format("%.0f", vResult.dblVal);
}
else if(vResult.vt==VT_EMPTY) //单元格空的
{
data = "";
}
CRange UseRange1;
UseRange1.AttachDispatch(sheet.get_UsedRange(), true);
range.AttachDispatch(UseRange1.get_Rows(), true);
//设置合并单元格的文字的对齐方式【水平垂直居中、竖直垂直居中】
//水平对齐:默认=1,居中=-4108,左=-4131,右=-4152
//垂直对齐:默认=2,居中=-4108,左=-4160,右=-4107
UseRange1.put_HorizontalAlignment(_variant_t((long)-4108));
UseRange1.put_VerticalAlignment(_variant_t((long)-4108));
UseRange1.ReleaseDispatch();
book.Save();
books.Close();
range.ReleaseDispatch();
sheet.ReleaseDispatch();
sheets.ReleaseDispatch();
book.ReleaseDispatch();
books.ReleaseDispatch();
app.ReleaseDispatch();
app.Quit();
至此就结束了excel的基本操作,其他的基本都是先找到单元格的位置,然后调用各自的接口进行想要的操作。接口不清楚只能去网上或者微软官网去查了。
Workbook 对象 (Excel) | Microsoft Docs
源码传送门: