Qt编写iFIx组态软件日报表插件的实现

news2025/4/5 4:48:04

一、iFIx中生成report.MDB文件

在Ifxi组态软件的【调度】中新建调度任务【report】添加【定时器调度项】FixTimer5,间隔1h触发一次。通过此任务及脚本程序,将相关变量定时存入自动生成的report.MDB文件中。

 用户脚本程序如下:

'---- User ConnectionString ----
Const ExcelConnectionString = "PROVIDER=MSDASQL;DRIVER=Microsoft Excel Driver (*.xls);User ID=Admin;FIL=excel 8.0;DBQ="

'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3

'---- LockTypeEnum Values ----
Const adLockReadOnly = 1
Const adLockPessimistic = 2
Const adLockOptimistic = 3
Const adLockBatchOptimistic = 4

'---- CursorLocationEnum Values ----
Const adUseServer = 2
Const adUseClient = 3

'---- ConnectModeEnum Values ----
Const adModeUnknown = 0
Const adModeRead = 1
Const adModeWrite = 2
Const adModeReadWrite = 3
Const adModeShareDenyRead = 4
Const adModeShareDenyWrite = 8
Const adModeShareExclusive = &HC
Const adModeShareDenyNone = &H10
Const adModeRecursive = &H400000
Dim LastAlarmCount As Long, LastAlarmDate As String, creat_rpt As Boolean
Dim last_re As Boolean

Private Sub rpt_record()

Dim strQuery As String
Dim db As Object, rst As Object
Dim rtn As Integer, v1 As Double, v2 As Double, v3 As Double, v4 As Double, v5 As Double, v6 As Double, v7 As Double, v8 As Double, v9 As Double, v10 As Double, uPath As String     
Dim T1, T2, T3, M1, M2, M3
On Error Resume Next
 rtn = 1
v1 = READVALUE("GFJ_AI_0.F_CV", 1) '进水浊度
v2 = READVALUE("GFJ_AI_1.F_CV", 1) '进水PH
v3 = READVALUE("GFJ_AI_8.F_CV", 1) '空气总管压力
v4 = READVALUE("GFJ_AI_9.F_CV", 1) '提升泵房液位
v5 = READVALUE("OUT_AI_0.F_CV", 1) '出水COD
v6 = READVALUE("OUT_AI_1.F_CV", 1) '出水氨氮
v7 = READVALUE("OUT_AI_2.F_CV", 1) '出水总磷
v8 = READVALUE("OUT_AI_3.F_CV", 1) '出水总氮
v9 = READVALUE("OUT_AI_4.F_CV", 1) '出水PH

T1 = Date
If last_re Then
T2 = 24
Else
T2 = Hour(Now)
End If
T3 = Minute(Now)
M1 = Year(Now)
M2 = Month(Now)
M3 = M1 & M2
Set db = CreateObject("ADODB.Connection")
'db.ConnectionString = "DSN = report; UID =; PWD =;"
db.Open "report", "", ""
db.Execute "select * into " & M3 & " from rptdata"
'---------
db.Execute "insert into " & M3 & "([date],[hr],[mi])values('" & T1 & "','" & T2 & "','" & T3 & "')"
db.Execute "update " & M3 & " set [v1]='" & v1 & "',[v2]='" & v2 & "',[v3]='" & v3 & "',[v4]='" & v4 & "',[v5]='" & v5 & "',[v6]='" & v6 & _
        "',[v7]='" & v7 & "',[v8]='" & v8 & "',[v9]='" & v9 & "',[v10]='" & v10 & "' where date = '" & T1 & "' and hr = '" & T2 & "'"
db.Close
End Sub

Private Sub FixTimer5_OnTimeOut(ByVal lTimerId As Long)
last_re = 0
rpt_record
End Sub

二、本地电脑上设置数据库ODBC

在【Windows管理工具】下打开【ODBC Data Sources(32-bit)】,添加【Driver do Microsoft Access(*.mdb)】,数据源名称设为【12】,数据库选择路径为ifIx组态软件生成的路径下的report.mdb数据库文件,点击【确定】即可。

 三、Qt程序编写

1、数据库连接,注意"SetDatabaseName"内写“12”和上述数据源名称一致

      // 通过ODBC连接ACESSS数据库
        QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
        db.setHostName("127.0.0.1");
        db.setDatabaseName("12");
        db.setUserName("");
        db.setPassword("");
        bool ok = db.open();
        // 判断数据库是否连接成功
        if (ok)
        {
             QMessageBox::information(this, "infor", "success");
        }
        else
        {
             QMessageBox::information(this, "infor", "open failed");
             qDebug()<<"error open database because"<<db.lastError().text();
        }

2、按照表名、日期和时刻(0-23)搜索数据,存入容器内

      注意:QString 数据类型的变量表达“...%1...”.arg(str)

  QString str=QString("SELECT * FROM `%1` where date = '%2' and hr = '%3'").arg(year_month).arg(year_month1).arg(QString::number(hr));
        QSqlQuery query(str,db);
 QSqlRecord rec = query.record();
       while(query.next())
 //调用一次QSqlQuery::next()内部指针就移动到第一条记录上,然后重复调用next()方法就可以移动到其他记录上,
        //直到该函数返回false为止
       {
            rec = query.record();
            int  v1_data=rec.indexOf("v1");
            v1.push_back( query.value(v1_data).toDouble());
            int  v2_data=rec.indexOf("v2");
            v2.push_back( query.value(v2_data).toDouble());
            int  v3_data=rec.indexOf("v3");
            v3.push_back( query.value(v3_data).toDouble());
            int  v4_data=rec.indexOf("v4");
            v4.push_back( query.value(v4_data).toDouble());
            int  v5_data=rec.indexOf("v5");
            v5.push_back( query.value(v5_data).toDouble());
            int  v6_data=rec.indexOf("v6");
            if(query.value(v6_data).toDouble()>1.0)
            v6.push_back( query.value(v6_data).toDouble()/100.0);
            else v6.push_back(query.value(v6_data).toDouble());
            int  v7_data=rec.indexOf("v7");
            if(query.value(v7_data).toDouble()>1.0)
            v7.push_back( query.value(v7_data).toDouble());
            else v7.push_back(query.value(v7_data).toDouble());
            int  v8_data=rec.indexOf("v8");
            v8.push_back( query.value(v8_data).toDouble());
            int  v9_data=rec.indexOf("v9");
            v9.push_back( query.value(v9_data).toDouble());
            int  v10_data=rec.indexOf("v10");
            v10.push_back( query.value(v10_data).toDouble());
          }
           QueryData(db);
        }

3、数据生成.xls文件

采用.xls模板文件的方式,在模板文件Cell上填入读取到的数据,sheet1中总共有27行数据

       int cellrow;
       int rows=27;

        //获取工作表集合的工作表1
        work_sheet = work_sheets->querySubObject("Item(int)",1);
        
       //Sheet1:    D/E/F/H/I/J/K/L/M/N/O/P
        QAxObject *cellB,*cellC,*cellD,*cellE,*cellF,*cellH,*cellI,*cellJ,*cellK,*cellL,*cellM,*cellN,*cellO,*cellP;

        //填写报表日期
        cellrow=4;
        QString D0="D"+QString::number(2);
        cellD = work_sheet->querySubObject("Range(QVariant, QVariant)",D0);
        cellD->dynamicCall("SetValue(const QVariant&)",QVariant(ReportDate));
 
        //获取列表数据,写入excel
        //设置表格数据

        for(int i=0;i<rows;i++)
        {
            //设置要操作的单元格,如A1,A2,A3,A4
            QString C="C"+QString::number(cellrow);
            QString D="D"+QString::number(cellrow);
            QString E="E"+QString::number(cellrow);
            QString F="F"+QString::number(cellrow);
            QString H="H"+QString::number(cellrow);
            QString I="I"+QString::number(cellrow);
            QString J="J"+QString::number(cellrow);
            QString K="K"+QString::number(cellrow);
            QString L="L"+QString::number(cellrow);
            QString M="M"+QString::number(cellrow);
            QString N="N"+QString::number(cellrow);
            QString O="O"+QString::number(cellrow);
            QString P="P"+QString::number(cellrow);
            //获取单元格
            cellC = work_sheet->querySubObject("Range(QVariant, QVariant)",C);
            cellD = work_sheet->querySubObject("Range(QVariant, QVariant)",D);
            cellE = work_sheet->querySubObject("Range(QVariant, QVariant)",E);
            cellF = work_sheet->querySubObject("Range(QVariant, QVariant)",F);
            cellH = work_sheet->querySubObject("Range(QVariant, QVariant)",H);
            cellI = work_sheet->querySubObject("Range(QVariant, QVariant)",I);
            cellJ = work_sheet->querySubObject("Range(QVariant, QVariant)",J);
            cellK = work_sheet->querySubObject("Range(QVariant, QVariant)",K);
            cellL = work_sheet->querySubObject("Range(QVariant, QVariant)",L);
            cellM = work_sheet->querySubObject("Range(QVariant, QVariant)",M);
            cellN = work_sheet->querySubObject("Range(QVariant, QVariant)",N);
            cellO = work_sheet->querySubObject("Range(QVariant, QVariant)",O);
            cellP = work_sheet->querySubObject("Range(QVariant, QVariant)",P);
       

            //设置单元格的值
            if(i<v1.size())  //*****判断下标在容器索引内
             cellD->dynamicCall("SetValue(const QVariant&)",QVariant(v1.at(i)));
            if(i<v2.size())
            cellE->dynamicCall("SetValue(const QVariant&)",QVariant(v2.at(i)));
            if(i<v3.size())
            cellF->dynamicCall("SetValue(const QVariant&)",QVariant(v3.at(i)));
            if(i<v4.size())
            cellJ->dynamicCall("SetValue(const QVariant&)",QVariant(v4.at(i)));
            if(i<v5.size())
            cellK->dynamicCall("SetValue(const QVariant&)",QVariant(v5.at(i)));
            if(i<v6.size())
            cellL->dynamicCall("SetValue(const QVariant&)",QVariant(v6.at(i)));
            if(i<v7.size())
            cellM->dynamicCall("SetValue(const QVariant&)",QVariant(v7.at(i)));
            if(i<v8.size())
            cellN->dynamicCall("SetValue(const QVariant&)",QVariant(v8.at(i)));
            if(i<v9.size())
            cellO->dynamicCall("SetValue(const QVariant&)",QVariant(v9.at(i)));
            if(i<v10.size())
            cellP->dynamicCall("SetValue(const QVariant&)",QVariant(v10.at(i)));


      }
       cellrow++;

四、程序运行

1、程序操作界面,选择报表生成的日期,进行先生成,后查看

2、打开iFIx组态软件生成的数据文件report.mdb文件,可看到具体对应的数据

 3、点击程序操作界面报表查看后,生成的数据报表.xls文件,可以看到已将上述2中的数据写入EXCEL表格中。

 4、注意

      在调试过程中,遇到根据模板无法写入到指定Sheet表格中的情况,原因是文件中有隐藏的Sheet,并且该隐藏的Sheet索引顺序在需要写入的Sheet表格前面,需要调整隐藏文件的索引顺序即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/654001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sui对外开放开发者Office Hour

Sui宣布开启新一轮的Sui开发工程师Office Hour。本期的Office Hour由Sui基金会和Mysten Labs共同主办&#xff0c;为Sui上开发的相关技术问题进行答疑解惑并提供支持。 开发工程Office Hour将于每周五1:00 AM&#xff08;GMT8&#xff09;开设&#xff0c;时长为1小时。 每个…

程序性能优化实践总结——JAVA

文章目录 1、 衡量程序性能的指标2、Java 程序性能优化切入点3、获取程序的性能数据1、nmon:获取系统性能数据2、jvisualvm:获取JVM性能数据3、jmc:获取Java应用详细性能数据4、arthas:获取单个请求的调用链耗时5、wrk获取Web接口的性能数据 4、应用程序优化1、缓冲区2、缓存3、…

vm.min_free_kbytes调整导致GI异常,kernel: oracle: page allocation failure

有个11204 rac的测试环境&#xff0c;客户反馈凌晨rman全备时偶尔会有内存耗尽导致数据库重启的情况&#xff0c;不是合同内的维护环境&#xff0c;请我们帮忙处理。我估计是没配置vm.min_free_kbytes&#xff0c;之前也调整多次每次都成功完成&#xff0c;就没有多想&#xff…

ROS1 图像数据转发

为节约带宽提高效率采用jpeg: sensor_msgs::CompressedImage image_msg; ros::Publisher img_pub n.advertise<sensor_msgs::CompressedImage>(“image1”, 10); image_msg.format“jpeg” ; image_msg.data.resize(jpeg_data_size); memcpy(image_msg.data.data(),jpeg…

【CUDA编程】 动态体素化实现

动态体素化实现 动态体素化DV克服了硬体素化HV的一些缺点。动态体素化DV保留了分组grouping阶段&#xff0c;相反&#xff0c;它没有采样固定的点数或体素容量&#xff0c;它保留了点和体素之间的完全映射。因此&#xff0c;体素数和每个体素中的点数都是动态的&#xff0c;依…

深入理解 SpringBoot 日志框架:从入门到高级应用——(七)SpringBoot日志配置

SpringBoot 官方文档&#xff1a;https://docs.spring.io/spring-boot/docs/2.7.12/reference/htmlsingle SpringBoot 底层依赖 Spring Boot 对所有内部日志记录使用 Commons Logging&#xff0c;但使底层日志实现保持为打开状态。 为 Java Util Logging、Log4J2 和 Logback …

【计算机网络自顶向下】如何学好计网-第一章概论

相关术语 URI&#xff1a;Uniform Resource Identifier 统一资源标识符&#xff0c;指的是一个资源 URL&#xff1a;Uniform Resource Location 统一资源定位符&#xff0c;URI的子集&#xff0c;用地址定为的方式指定一个资源 URN&#xff1a;Uniform Resource Name 统一资…

DBeaver连接SQLite数据库

一、前言 SQLite小巧轻便的开源免费关系型数据库&#xff0c;适合嵌入单机应用随身携带。桌面版推荐使用DBeaver。 官网&#xff1a;SQLite Download Page github&#xff1a;GitHub - sqlite/sqlite: Official Git mirror of the SQLite source tree 类似的开源免费且小巧…

vue+elementui实现app布局小米商城,样式美观大方

目录 一、效果图 1.首页效果图 2.分类 3.购物车 4.我的 5.登录注册 6.商品详情 7.搜索 二、项目实现 1.项目结构、设计说明 2.路由配置实现 3.首页实现源码 4.登录注册实现&#xff0c;模拟登录注册流程&#xff0c;用户数据存储到本地浏览器缓存 三、总结 一、效果…

『2023北京智源大会』开幕式以及基础模型前沿技术论坛

『2023北京智源大会』开幕式以及基础模型前沿技术论坛 文章目录 一. 黄铁军丨智源研究院院长1. 大语言模型2. 大语言模型评测体系FlagEval3. 大语言模型生态(软硬件)4. 三大路线通向 AGI(另外2条路径) 二. Towards Machines that can Learn, Reason, and Plan(杨立昆丨图灵奖得…

UE4/5样条线学习(四):样条线的创建和自然摆动

这一次我们创建一个actor蓝图&#xff0c;不过我们这次并不需要在一开始就创建样条线组件&#xff0c;而是在游戏中根据两个点去创建样条线&#xff0c;然后用时间轴根据样条线带动物品旋转位移。 制作&#xff1a; 组件部分&#xff1a; 第一步&#xff0c;创建一个actor蓝图…

CSDN铁粉增长秘籍

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

【Jmeter】在进行综合场景压测时,由于不同的请求,要求所占比例不同,那如何实现呢?

在进行综合场景压测时&#xff0c;由于不同的请求&#xff0c;要求所占比例不同&#xff0c;那如何实现呢&#xff1f; 有人说将这些请求分别放到单独的线程组下&#xff0c;然后将线程组的线程数按照比例进行配置&#xff0c;这种方法不是很好&#xff0c;想想&#xff0c;不…

【计算机网络自顶向下】如何学好计网-第二章应用层

第二章 应用层 应用层协议原理 网络应用程序体系结构 客户机/服务器体系结构&#xff1a;至少有一个服务器&#xff0c;一个客户机&#xff0c;其中服务器总是打开的&#xff0c;具有固定的众所周知的IP地址&#xff0c;主机群集常被用于创建强大的虚拟服务器&#xff0c;而客…

OpenCV 笔记_1

笔记_1 文章目录 笔记_1Mat类数据类型读取Mat类支持的运算图像读取&#xff0c;显示&#xff0c;保存imread 图像读取namedWindow 创建要显示的窗口imshow 窗口显示imwrite 图像保存 视频加载与摄像头的使用VideoCapture 加载视频或摄像头get 获取属性VideoWriter 保存视频 图像…

vue 生命周期

人的-生命周期 一组件从 创建 到 销毁 的整个过程就是生命周期 Vue_生命周期 1. 钩子函数 Vue 框架内置函数&#xff0c;随着组件的生命周期阶段&#xff0c;自动执行 作用: 特定的时间点&#xff0c;执行特定的操作 场景: 组件创建完毕后&#xff0c;可以在created 生命周期…

实际项目中使用gorm-gen来生成实体类

一、为什么要使用gorm-gen来生成实体类和查询 1、根据gorm官网地址&#xff0c;正常的写法是先写数据模型,然后由数据模型自动同步生成到数据库中,但是这样的工作量会比较大,对于写后端的人来说都熟悉sql语句,正常来说都是先自己手动创建表,利用工具将表字段同步到项目实体类中…

java商业销售分析系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 商业销售分析系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

电脑重装系统后需要更新哪些驱动

在电脑重装系统后&#xff0c;由于系统的重置&#xff0c;您需要重新安装和更新一些关键的驱动程序&#xff0c;以确保硬件设备正常工作和性能最佳化。以下是在电脑重装系统后需要更新的一些常见驱动程序。 工具/原料&#xff1a; 系统版本&#xff1a;win10系统 品牌型号&…

TOGAF10®标准中文版-(介绍和核心概念)摘要

第1章&#xff1a;简介 TOGAF标准是企业架构的框架。任何希望开发企业架构以在该组织内使用的组织都可以免费使用它&#xff08;见第1.3.1节&#xff09;。 TOGAF标准由The Open Group成员在架构论坛内开发和维护&#xff08;请参阅www.opengroup.org/Architecture&#xff0…