labwindows/cvi 2019入門(mén)(4)——讀寫(xiě)EXCEL文件生成試驗(yàn)報(bào)告

在工控領(lǐng)域,上位機(jī)經(jīng)常需要操作excel,用于保存測(cè)試的數(shù)據(jù)及測(cè)試結(jié)果。LabwindowsCVI提供了專(zhuān)門(mén)工具庫(kù)ExcelReport實(shí)現(xiàn)對(duì)Excel操作。ExcelReport庫(kù)就是對(duì)windows的excel庫(kù)進(jìn)行了一層封裝,這樣我們就能更好的操作excel了,同時(shí)也要求計(jì)算機(jī)上要安裝Excel軟件。Excelreport.fp的主要函數(shù)如下圖。


image.png

下面將介紹操作Excel的常用API:
1、ExcelRpt_ApplicationNew
ExcelRpt_ApplicationNew用于啟動(dòng)excel程序,其函數(shù)原型如下所示:
HRESULT CVIFUNC ExcelRpt_ApplicationNew (int makeVisible, CAObjHandle *applicationHandle);
其中makeVisible為加載的excel程序是否顯示的標(biāo)志,當(dāng)其值為1時(shí),顯示excel程序界面,如下圖所示,applicationHandle為獲取的excel程序句柄。

2、ExcelRpt_WorkbookOpen
ExcelRpt_WorkbookOpen用于打開(kāi)excel的文件,其函數(shù)原型如下所示:
HRESULT CVIFUNC ExcelRpt_WorkbookOpen (CAObjHandle applicationHandle, const char *fileName,CAObjHandle *workbookHandle);
其中applicationHandle為excel程序的句柄,fileName為要打開(kāi)的excel文件路徑,workbookHandle為獲取的excel文件句柄。

3、ExcelRpt_GetWorksheetFromIndex
ExcelRpt_GetWorksheetFromIndex為獲取excel文件中某個(gè)sheet句柄,其函數(shù)原型如下所示:
HRESULT CVIFUNC ExcelRpt_GetWorksheetFromIndex (CAObjHandle workbookHandle, int Index,CAObjHandle *worksheetHandle);
其中workbookHandle為excel文件的句柄,Index為excel文件中sheet的索引,其索引值從1開(kāi)始,worksheetHandle為獲得的sheet句柄。

4、ExcelRpt_GetCellValue
ExcelRpt_GetCellValue為獲取sheet中某cell的內(nèi)容,其函數(shù)原型如下所示:
HRESULT CVIFUNC ExcelRpt_GetCellValue (CAObjHandle worksheetHandle, const char *cellRange,enum ExREnum_ExDataType dataType, void *dataValue);
其中worksheetHandle為sheet句柄,cellRange為cell的索引,dataType為數(shù)據(jù)類(lèi)型,通常情況下,該值設(shè)置為CAVT_CSTRING,這樣我們可以讀取各種數(shù)據(jù),然后進(jìn)行轉(zhuǎn)換,dataValue為讀取的數(shù)據(jù)指針。

5、ExcelRpt_SetCellValue
ExcelRpt_SetCellValue用于設(shè)置sheet中某cell內(nèi)容,其函數(shù)原型如下所示:
HRESULT ExcelRpt_SetCellValue (CAObjHandle worksheetHandle, char cellRange[], enum ExREnum_ExDataType dataType, ...);
其中worksheetHandle為sheet句柄,cellRange為cell的索引,dataType為數(shù)據(jù)類(lèi)型。

6、ExcelRpt_SetCellRangeAttribute
ExcelRpt_SetCellRangeAttribute為設(shè)置cell的屬性值,其函數(shù)原型如下所示:
HRESULT CVIFUNC_C ExcelRpt_SetCellRangeAttribute (CAObjHandle worksheetHandle, const char* cellRange,int attribute, ...);
其中worksheetHandle為sheet句柄,cellRange為cell的索引,attribute為屬性的名稱(chēng),…為屬性的值。在測(cè)試中,我們經(jīng)常使用該函數(shù)用于設(shè)置cell的背景顏色,用于直觀感受是否測(cè)試通過(guò)。

7、ExcelRpt_WorkbookClose
ExcelRpt_WorkbookClose用于關(guān)閉打開(kāi)的excel文件,其函數(shù)原型如下所示: HRESULT CVIFUNC ExcelRpt_WorkbookClose (CAObjHandle workbookHandle, int saveChanges);
其中workbookHandle為excel打開(kāi)文件的句柄,saveChanges為關(guān)閉時(shí),是否保存excel文件的標(biāo)志,通常我們?cè)O(shè)置該值為1,否則測(cè)試的數(shù)據(jù)將保存不了。

8、ExcelRpt_ApplicationQuit
ExcelRpt_ApplicationQuit用于關(guān)閉打開(kāi)的excel程序,其函數(shù)原型如下所示:
HRESULT CVIFUNC ExcelRpt_ApplicationQuit (CAObjHandle applicationHandle);
其中applicationHandle為打開(kāi)的excel程序?qū)嵗浔?/p>

9、ExcelRpt_GetErrorInfo
ExcelRpt_GetErrorInfo用于得到操作excel異常原因,其函數(shù)原型如下所示:
ERRORINFO * CVIFUNC ExcelRpt_GetErrorInfo(void);
該函數(shù)返回ERRORINFO的指針,我們可以觀察ERRORINFO-> description的異常描述。

10、CA_DiscardObjHandle
CA_DiscardObjHandle用于釋放objHandle對(duì)象,其函數(shù)原型如下所示:
HRESULT CVIFUNC CA_DiscardObjHandle(CAObjHandle objHandle);

項(xiàng)目實(shí)踐:

本項(xiàng)目模擬試驗(yàn)情況生成試驗(yàn)報(bào)告。
為了簡(jiǎn)化代碼,首先建一個(gè)試驗(yàn)報(bào)告模板。每次只需要向EXCEL里面添加對(duì)應(yīng)數(shù)據(jù)即可。
報(bào)告中的圖表是事先定義好的,只要數(shù)據(jù)填進(jìn)去自動(dòng)更新。實(shí)際上你也可以通過(guò)代碼插入chart圖表。

軟件運(yùn)行后界面如下:
image.png

全部代碼如下:
#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."
//產(chǎn)品代號(hào)
static char ProductID[128]={0};
//試驗(yàn)單位
static char TestCompany[128]={0};
//操作員
static char Operator[128]={0};
//試驗(yàn)日期
static char TestDate[20]={0};
//試驗(yàn)時(shí)間
static char TestTime[20]={0};
//工作壓力
static double TestMPa=0.0;
//試驗(yàn)溫度
static double TestTemperature=10.0;
//試驗(yàn)時(shí)長(zhǎng)
static int TestDuration=10;
//試驗(yàn)項(xiàng)目1-4結(jié)果
static BOOL Test1Rst=FALSE;
static BOOL Test2Rst=FALSE;
static BOOL Test3Rst=FALSE;
static BOOL Test4Rst=FALSE;
//生產(chǎn)新報(bào)告的名字=report+年月日時(shí)分秒.xls
static char NewRptFileName[128]={0};
//獲取面板上設(shè)定的試驗(yàn)內(nèi)容
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);
        //生成試驗(yàn)日期
    sprintf(TestDate,"%04d-%02d-%02d",Now->tm_year+1900,Now->tm_mon,Now->tm_mday);
        //生成試驗(yàn)時(shí)間
    sprintf(TestTime,"%02d:%02d:%02d",Now->tm_hour,Now->tm_min,Now->tm_sec);
        //生成新試驗(yàn)報(bào)告名
    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)
    {
            //插入圖表的橫坐標(biāo)縱坐標(biāo)值cell號(hào)和值
            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");
            //打開(kāi)報(bào)告模板文件
            ExcelRpt_WorkbookOpen(applicationHandle,ExcelFileName,&workbookHandle);
            //獲取想激活worksheet的句柄 
            ExcelRpt_GetWorksheetFromName(workbookHandle,"Sheet1",&worksheetHandle);
            //激活指定sheet 
            ExcelRpt_ActivateWorksheet(worksheetHandle);
            GetTestResult();
            //向報(bào)告中插入試驗(yàn)數(shù)據(jù)    
            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,"不合格");
            //隨機(jī)生成曲線圖表用數(shù)據(jù)
            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);
            //報(bào)告按照新文件名報(bào)表    
            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)
            {
                //退出程序前一定要釋放變量存儲(chǔ)
                ExcelRpt_WorkbookClose(workbookHandle, 0);
                CA_DiscardObjHandle(workbookHandle);
            }
            if (applicationHandle)
            {
                ExcelRpt_ApplicationQuit(applicationHandle);
                CA_DiscardObjHandle(applicationHandle);
            }
            QuitUserInterface (0);
            break;
    }
    return 0;
}

運(yùn)行程序,點(diǎn)擊“生成試驗(yàn)報(bào)告”按鈕,結(jié)果如下:


image.png

該程序使用簡(jiǎn)單,但也有不足:1.需要安裝office軟件;2.運(yùn)行速度較慢。后續(xù)將研究使用第三方控件獨(dú)立操作Excel文件。
這個(gè)例子的練習(xí)讓我又重新復(fù)習(xí)了很多C語(yǔ)言的知識(shí)。如整數(shù)轉(zhuǎn)字符、格式化字符、獲取系統(tǒng)時(shí)間、獲取一定范圍隨機(jī)數(shù)等。
歡迎交流QQ:491114509

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 使用首先需要了解他的工作原理 1.POI結(jié)構(gòu)與常用類(lèi) (1)創(chuàng)建Workbook和Sheet (2)創(chuàng)建單元格 (...
    長(zhǎng)城ol閱讀 8,755評(píng)論 2 25
  • 轉(zhuǎn)自鏈接 目錄 1.認(rèn)識(shí)NPOI 2.使用NPOI生成xls文件 2.1創(chuàng)建基本內(nèi)容 2.1.1創(chuàng)建Workboo...
    腿毛褲閱讀 11,165評(píng)論 1 3
  • [轉(zhuǎn)]C/C++ 文件讀寫(xiě)操作總結(jié) 在編程的過(guò)程中,文件的操作是一個(gè)經(jīng)常用到的問(wèn)題,在C++Builder中,可以...
    天之道天知道閱讀 5,299評(píng)論 0 7
  • 轉(zhuǎn)自鏈接 3.項(xiàng)目實(shí)踐 3.1基于.xls模板生成Excel文件 3.2生成九九乘法表 3.3生成一張工資單 3....
    腿毛褲閱讀 3,781評(píng)論 0 0
  • 應(yīng)用程序經(jīng)常需要保存一些的有用的信息等,如下次打開(kāi)軟件時(shí)要加載的數(shù)據(jù),程序設(shè)定的基本工藝參數(shù)等等。INI文件是一種...
    菜鳥(niǎo)筆記閱讀 5,010評(píng)論 1 5

友情鏈接更多精彩內(nèi)容