在工控领域,上位机经常需要操作excel,用于保存测试的数据及测试结果。LabwindowsCVI提供了专门工具库ExcelReport实现对Excel操作。ExcelReport库就是对windows的excel库进行了一层封装,这样我们就能更好的操作excel了,同时也要求计算机上要安装Excel软件。Excelreport.fp的主要函数如下图。

下面将介绍操作Excel的常用API:
1、ExcelRpt_ApplicationNew
ExcelRpt_ApplicationNew用于启动excel程序,其函数原型如下所示:
HRESULT CVIFUNC ExcelRpt_ApplicationNew (int makeVisible, CAObjHandle *applicationHandle);
其中makeVisible为加载的excel程序是否显示的标志,当其值为1时,显示excel程序界面,如下图所示,applicationHandle为获取的excel程序句柄。
2、ExcelRpt_WorkbookOpen
ExcelRpt_WorkbookOpen用于打开excel的文件,其函数原型如下所示:
HRESULT CVIFUNC ExcelRpt_WorkbookOpen (CAObjHandle applicationHandle, const char *fileName,CAObjHandle *workbookHandle);
其中applicationHandle为excel程序的句柄,fileName为要打开的excel文件路径,workbookHandle为获取的excel文件句柄。
3、ExcelRpt_GetWorksheetFromIndex
ExcelRpt_GetWorksheetFromIndex为获取excel文件中某个sheet句柄,其函数原型如下所示:
HRESULT CVIFUNC ExcelRpt_GetWorksheetFromIndex (CAObjHandle workbookHandle, int Index,CAObjHandle *worksheetHandle);
其中workbookHandle为excel文件的句柄,Index为excel文件中sheet的索引,其索引值从1开始,worksheetHandle为获得的sheet句柄。
4、ExcelRpt_GetCellValue
ExcelRpt_GetCellValue为获取sheet中某cell的内容,其函数原型如下所示:
HRESULT CVIFUNC ExcelRpt_GetCellValue (CAObjHandle worksheetHandle, const char *cellRange,enum ExREnum_ExDataType dataType, void *dataValue);
其中worksheetHandle为sheet句柄,cellRange为cell的索引,dataType为数据类型,通常情况下,该值设置为CAVT_CSTRING,这样我们可以读取各种数据,然后进行转换,dataValue为读取的数据指针。
5、ExcelRpt_SetCellValue
ExcelRpt_SetCellValue用于设置sheet中某cell内容,其函数原型如下所示:
HRESULT ExcelRpt_SetCellValue (CAObjHandle worksheetHandle, char cellRange[], enum ExREnum_ExDataType dataType, ...);
其中worksheetHandle为sheet句柄,cellRange为cell的索引,dataType为数据类型。
6、ExcelRpt_SetCellRangeAttribute
ExcelRpt_SetCellRangeAttribute为设置cell的属性值,其函数原型如下所示:
HRESULT CVIFUNC_C ExcelRpt_SetCellRangeAttribute (CAObjHandle worksheetHandle, const char* cellRange,int attribute, ...);
其中worksheetHandle为sheet句柄,cellRange为cell的索引,attribute为属性的名称,…为属性的值。在测试中,我们经常使用该函数用于设置cell的背景颜色,用于直观感受是否测试通过。
7、ExcelRpt_WorkbookClose
ExcelRpt_WorkbookClose用于关闭打开的excel文件,其函数原型如下所示: HRESULT CVIFUNC ExcelRpt_WorkbookClose (CAObjHandle workbookHandle, int saveChanges);
其中workbookHandle为excel打开文件的句柄,saveChanges为关闭时,是否保存excel文件的标志,通常我们设置该值为1,否则测试的数据将保存不了。
8、ExcelRpt_ApplicationQuit
ExcelRpt_ApplicationQuit用于关闭打开的excel程序,其函数原型如下所示:
HRESULT CVIFUNC ExcelRpt_ApplicationQuit (CAObjHandle applicationHandle);
其中applicationHandle为打开的excel程序实例句柄。
9、ExcelRpt_GetErrorInfo
ExcelRpt_GetErrorInfo用于得到操作excel异常原因,其函数原型如下所示:
ERRORINFO * CVIFUNC ExcelRpt_GetErrorInfo(void);
该函数返回ERRORINFO的指针,我们可以观察ERRORINFO-> description的异常描述。
10、CA_DiscardObjHandle
CA_DiscardObjHandle用于释放objHandle对象,其函数原型如下所示:
HRESULT CVIFUNC CA_DiscardObjHandle(CAObjHandle objHandle);
项目实践:
本项目模拟试验情况生成试验报告。
为了简化代码,首先建一个试验报告模板。每次只需要向EXCEL里面添加对应数据即可。
报告中的图表是事先定义好的,只要数据填进去自动更新。实际上你也可以通过代码插入chart图表。

全部代码如下:
#include "excelreport.h"
#include "time.h"
#include <ansi_c.h>
#include <utility.h>
#include <cvirte.h>
#include <userint.h>
#include "CviExcelRpt.h"
static int panelHandle;
//定义句柄变量
static CAObjHandle applicationHandle = 0;
static CAObjHandle workbookHandle = 0;
static CAObjHandle worksheetHandle = 0;
//定义含路径的文件名变量
char ExcelFileName[MAX_PATHNAME_LEN]={0};
#define LAUNCHERR "\
An error occurred trying to launch Excel through its automation interface.\n\n\
Ensure that Excel is installed and that you can launch it manually."
//产品代号
static char ProductID[128]={0};
//试验单位
static char TestCompany[128]={0};
//操作员
static char Operator[128]={0};
//试验日期
static char TestDate[20]={0};
//试验时间
static char TestTime[20]={0};
//工作压力
static double TestMPa=0.0;
//试验温度
static double TestTemperature=10.0;
//试验时长
static int TestDuration=10;
//试验项目1-4结果
static BOOL Test1Rst=FALSE;
static BOOL Test2Rst=FALSE;
static BOOL Test3Rst=FALSE;
static BOOL Test4Rst=FALSE;
//生产新报告的名字=report+年月日时分秒.xls
static char NewRptFileName[128]={0};
//获取面板上设定的试验内容
void GetTestResult()
{
GetCtrlVal(panelHandle,PANEL_PRODUCTID,ProductID);
GetCtrlVal(panelHandle,PANEL_TESTCOMPANY,TestCompany);
GetCtrlVal(panelHandle,PANEL_OPERATOR,Operator);
GetCtrlVal(panelHandle,PANEL_MPa,&TestMPa);
GetCtrlVal(panelHandle,PANEL_TEMPERATURE,&TestTemperature);
GetCtrlVal(panelHandle,PANEL_TESTTIME,&TestDuration);
GetCtrlVal(panelHandle,PANEL_TEST1,&Test1Rst);
GetCtrlVal(panelHandle,PANEL_TEST2,&Test2Rst);
GetCtrlVal(panelHandle,PANEL_TEST3,&Test3Rst);
GetCtrlVal(panelHandle,PANEL_TEST4,&Test4Rst);
time_t NowTime;
time(&NowTime);
struct tm *Now;
Now = localtime(&NowTime);
//生成试验日期
sprintf(TestDate,"%04d-%02d-%02d",Now->tm_year+1900,Now->tm_mon,Now->tm_mday);
//生成试验时间
sprintf(TestTime,"%02d:%02d:%02d",Now->tm_hour,Now->tm_min,Now->tm_sec);
//生成新试验报告名
sprintf(NewRptFileName,"\\report%04d%02d%02d%02d%02d%02d.xls",Now->tm_year+1900,Now->tm_mon,Now->tm_mday,Now->tm_hour,Now->tm_min,Now->tm_sec);
}
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((panelHandle = LoadPanel (0, "CviExcelRpt.uir", PANEL)) < 0)
return -1;
DisplayPanel (panelHandle);
RunUserInterface ();
DiscardPanel (panelHandle);
return 0;
}
int CVICALLBACK panelCB (int panel, int event, void *callbackData,
int eventData1, int eventData2)
{
switch (event)
{
case EVENT_GOT_FOCUS:
break;
case EVENT_LOST_FOCUS:
break;
case EVENT_CLOSE:
break;
}
return 0;
}
int CVICALLBACK btnCreateRpt (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
HRESULT error = 0;
switch (event)
{
//插入图表的横坐标纵坐标值cell号和值
char index[8]={0};
char data[8]={0};
int datavalue=0;
case EVENT_COMMIT:
error = ExcelRpt_ApplicationNew(1, &applicationHandle);
if (error<0)
{
MessagePopup ("Error: Microsoft Excel Automation", LAUNCHERR);
return 0;
}
GetProjectDir(ExcelFileName);
strcat(ExcelFileName,"\\report.xls");
//打开报告模板文件
ExcelRpt_WorkbookOpen(applicationHandle,ExcelFileName,&workbookHandle);
//获取想激活worksheet的句柄
ExcelRpt_GetWorksheetFromName(workbookHandle,"Sheet1",&worksheetHandle);
//激活指定sheet
ExcelRpt_ActivateWorksheet(worksheetHandle);
GetTestResult();
//向报告中插入试验数据
ExcelRpt_SetCellValue(worksheetHandle,"C3",ExRConst_dataString,ProductID);
ExcelRpt_SetCellValue(worksheetHandle,"C4",ExRConst_dataString,TestCompany);
ExcelRpt_SetCellValue(worksheetHandle,"C5",ExRConst_dataString,Operator);
ExcelRpt_SetCellValue(worksheetHandle,"F4",ExRConst_dataString,TestDate);
ExcelRpt_SetCellValue(worksheetHandle,"F5",ExRConst_dataString,TestTime);
ExcelRpt_SetCellValue(worksheetHandle,"C7",ExRConst_dataDouble,TestMPa);
ExcelRpt_SetCellValue(worksheetHandle,"C8",ExRConst_dataInt,TestDuration);
ExcelRpt_SetCellValue(worksheetHandle,"C9",ExRConst_dataDouble,TestTemperature);
if(Test1Rst)
ExcelRpt_SetCellValue(worksheetHandle,"F19",ExRConst_dataString,"合格");
else
ExcelRpt_SetCellValue(worksheetHandle,"F19",ExRConst_dataString,"不合格");
if(Test2Rst)
ExcelRpt_SetCellValue(worksheetHandle,"F20",ExRConst_dataString,"合格");
else
ExcelRpt_SetCellValue(worksheetHandle,"F20",ExRConst_dataString,"不合格");
if(Test3Rst)
ExcelRpt_SetCellValue(worksheetHandle,"F21",ExRConst_dataString,"合格");
else
ExcelRpt_SetCellValue(worksheetHandle,"F21",ExRConst_dataString,"不合格");
if(Test4Rst)
ExcelRpt_SetCellValue(worksheetHandle,"F22",ExRConst_dataString,"合格");
else
ExcelRpt_SetCellValue(worksheetHandle,"F22",ExRConst_dataString,"不合格");
//随机生成曲线图表用数据
for(int i=0;i<100;i++)
{
sprintf(index,"C%d",30+i);
sprintf(data,"D%d",30+i);
datavalue = rand()%100;
ExcelRpt_SetCellValue(worksheetHandle,index,ExRConst_dataInt,i);
ExcelRpt_SetCellValue(worksheetHandle,data,ExRConst_dataDouble,datavalue/10.0);
}
GetProjectDir(ExcelFileName);
strcat(ExcelFileName,NewRptFileName);
//报告按照新文件名报表
ExcelRpt_WorkbookSave(workbookHandle,ExcelFileName,ExRConst_DefaultFileFormat);
break;
}
return 0;
}
int CVICALLBACK btnExit (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
if (worksheetHandle)
CA_DiscardObjHandle(worksheetHandle);
if (workbookHandle)
{
//退出程序前一定要释放变量存储
ExcelRpt_WorkbookClose(workbookHandle, 0);
CA_DiscardObjHandle(workbookHandle);
}
if (applicationHandle)
{
ExcelRpt_ApplicationQuit(applicationHandle);
CA_DiscardObjHandle(applicationHandle);
}
QuitUserInterface (0);
break;
}
return 0;
}
运行程序,点击“生成试验报告”按钮,结果如下:

该程序使用简单,但也有不足:1.需要安装office软件;2.运行速度较慢。后续将研究使用第三方控件独立操作Excel文件。
这个例子的练习让我又重新复习了很多C语言的知识。如整数转字符、格式化字符、获取系统时间、获取一定范围随机数等。
欢迎交流QQ:491114509
网友评论