FR多sheet的内置检验和JS校验, 数据集范围校验;填报存在时不提交并提示已存在

跨Sheet校验详解
本文介绍了在报表填报过程中如何实现跨Sheet校验的方法,包括提交校验和JS校验两种方式,并提供了具体的实现步骤和代码示例。

在对多sheet进行填报的时候,往往需要从其他sheet取数参与计算,或者以其他sheet的数据为依据,对当前sheet的填报数据进行一定的约束,这个就是跨sheet校验。

跨sheet校验应用在两个方面:提交校验js校验

提交校验

在提交数据之前对数据进行校验,比如说,当前模板有2个sheet,sheet1里面的某个数据与sheet2里面的某个数据的和必须满足特定条件。

如下图,点击模板>报表填报属性,切换到数据校验标签,添加一个内置校验,校验公式为sheet1!A2+sheet2!B2>1000,校验出错信息为shee1的A2单元格与sheet2的B2单元格和值太小:

注:校验公式中直接跨sheet取数进行计算,跨sheet取数详细请查看多sheet数据计算

js校验

使用js对多sheet进行校验,原理是将其他sheet的数值通过FR取数方法赋值给js里面定义的参数,然后参与校验。

比如说,在编辑sheet2里面的B2单元格的时候,如果sheet1的A2单元格与sheet2的B2单元格的和小于1000,则提示警告,如下图:
222

给sheet2的B2单元格的控件添加一个编辑结束事件,如下图:

js代码为:

 

 

  1. var para=contentPane.getCellValue(0,0,1);//获取sheet1里面的A2单元格数据  
  2. var value=this.getValue();//获取当前单元格数据  
  3. var sum=parseInt(para)+parseInt(value);//将字符串转换为整形并求和  
  4. if(sum<1000){alert("shee1的A2单元格与sheet2的B2单元格和值太小");} 

由上图的js代码可知,在js中进行跨sheet校验,获取其他sheet的单元格值可通过方法contentPane.getCellValue(sheet号,列号,行号); //sheet号,列号,行号是从0开始来获取,详细请参照填报预览JS实例

其它JS比较检验范例:

 

对B2单元格控件设置事件编辑,添加编辑结束事件,具体JS代码如下:

 

  1. var D2value = contentPane.curLGP.getCellValue("D2"); //获取D2单元格的值  
  2. if (this.getValue()*1 < D2value){     //判断输入值是否小于D2单元格值  
  3.    FR.Msg.alert(FR.i18n.Alert, "该值不能小于" + D2value);     //弹出对话框  
  4.    return false;  
  5. }  

其中获取填报单元格的值的详细介绍请查看填报预览JS实例

对B3单元格控件进行事件编辑,添加编辑结束事件,具体JS代码如下:

 

  1. var D3value = contentPane.curLGP.getCellValue("D3"); //获取D3单元格的值  
  2. if (this.getValue()*1 != D3value){     //判断输入值是否与D3单元格相等  
  3.    FR.Msg.alert(FR.i18n.Alert, "该值应等于" + D3value);     //弹出对话框  
  4.    return false;  
  5. }  

其中,D3value是自定义变量,用于获得D3单元格的值,if语句是用来判断该单元格输入后的值是否等于D3value,如果不是是则弹出警告:该值应等于abc。

2.数据集检验:检验某个单元格值是否在数据范围内

 内置校验写法如下:INARRAY(D2,zzdyxy.group(diqu))>0  ;//D2的值要在数据集zzdyxy的diqu列的范围内,否则检验不通过。

引用数据集中的某个列固定写法:数据集名.group(列名)

3.填报单元格重复值检验:

根据要检查的重复值的列,分别取两个单元格:一个B6引用单元列数组求个数如:count([A2]) 为[A2]扩展出数组,

另一个D6为去掉重复值后的个数count(UNIQUEARRAY([A2]))

然后内置检验公式 B6=D6  提示A2重复

其它公式套用:

 

在B5单元格设置公式:JOINARRAY([A3], ""),取数组原始字符串,不加间隔符号,

在D5单元格设置公式:JOINARRAY(UNIQUEARRAY([A3]), ""),取数组去掉重复值后的字符串,不加间隔符号。

4.检验可强提交 在填报WEB属性自定义工具栏里面设置(只提交当前sheet也在其中)

----------------------------------------------------------------------------------------------------------------------------------------------

扩展:填报存在时不提交并提示已存在(重点)

 

控件添加编辑后事件,参考下面代码写js:

  1. //获取填报控件的值
  2. var name = contentPane.getWidgetByName("name").getValue();
  3. //判断填报内容在数据库中是否存在
  4. var sql ="SQL(\"FRDemo\",\"SELECT 销售员 FROM 销量 where 销售员='"+name+"'\",1,1)";
  5. var len = FR.remoteEvaluate(sql).length;
  6. if(len != 0)
  7. {
  8.     FR.Msg.alert(FR.i18n.Alert,"该销售员已存在,请重新输入。");
  9.     contentPane.getWidgetByName("name").setValue("");
  10. }

复制代码


或者用填报属性的数据校验写校验公式:
LEN(SQL("FRDemo", "SELECT 销售员 FROM 销量 where 销售员='" + A1 + "'", 1, 1)) == 0

<think>我们正在讨论报表的填报功能,特别是如何避免覆盖历史数据。根据用户的问题,用户希望在提交数据后保留历史数据,而是覆盖之前的数据填报报表默认情况下,如果提交数据包含相同主键的记录,可能会覆盖已有数据。为了避免覆盖,我们需要设计报表采取一些策略。解决方案通常有两种:1.在数据库设计层面,每次提交都作为新记录插入,而是更新。这需要数据库表有自增主键或者间戳字段来区分同批次的数据。2.在填报设置中,通过设置提交属性,将操作改为插入而是更新。具体到报表设计器中的操作步骤:a.打开填报报表模板,选择需要提交数据的单元格,然后设置其“单元格属性”为“扩展”方式(如果该单元格需要提交数据)。b.在“模板”->“报表填报属性”中,设置提交方式。这里的关键是,如果我们要保留历史数据,那么每次提交都应该生成新的记录,而是更新已有记录。因此,在“提交属性”设置中,我们需要将操作类型设置为“插入”,而是“更新”或“智能提交”(智能提交会根据主键判断是插入还是更新)。但是,如果用户希望同有更新和插入的操作(即部分数据更新,部分数据插入),那么就需要更复杂的逻辑。过根据用户需求,只要求保留历史数据,那么每次提交都插入新记录即可。另外,为了避免覆盖,数据库表设计也很重要。例如,可以添加一个“操作间”字段,每次提交都记录当前间,这样即使其他字段相同,也可以根据间区分。详细步骤:1.在数据库表中,确保有唯一标识每条记录的字段(比如自增ID),或者有足够区分历史记录的字段(如间戳)。2.在设计器中,定义填报属性,选择“插入”操作,绑定到数据库表。3.在绑定字段,注意要将唯一标识字段(如自增ID)绑定到填报单元格(或者将其设置为可更新,且设置为主键),这样每次提交都会生成新记录。如果用户需要更新部分数据覆盖其他历史数据,那么可能需要设计两张表:一张是当前数据表,另一张是历史数据表。在更新当前数据,将旧数据插入到历史数据表中。但这直接能配置的,需要数据库触发器等机制。根据引用[1]中提到的功能,支持“自定义校验”和“智能联动”,我们可以利用自定义校验来避免重复提交,但这里的问题是重复提交,而是保留历史。因此,最直接的方法就是将填报设置为插入操作。示例设置步骤:-打开报表模板,点击“模板”->“报表填报属性”,打开设置窗口。-点击“+”号添加一个内置SQL,选择“插入”。-在“数据库表”中选择目标表。-在“字段”设置中,将报表中的单元格与数据库表的字段一一对应(注意:自增字段要绑定,数据库会自动生成)。-如果表中有间字段,可以设置一个默认值为当前间(如公式:=now()),这样每次插入都会记录提交间。这样设置后,每次提交都会在数据库中插入一条新记录,而会覆盖原有数据。但是,用户可能会问:如果我想更新某些数据怎么办?这,我们可能需要两个提交操作:一个是插入新记录,另一个是更新当前记录。但用户当前的需求只是避免覆盖,所以先提供插入的方法。注意:如果用户需要的是记录每一次修改的历史(即每次修改旧记录都保留,同新记录作为最新数据),这需要更复杂的设计(如版本控制)。本身直接支持,需要结合数据库设计。综上所述,设置填报属性为“插入”即可。相关问题:1.如何设置填报报表的插入操作?2.填报报表如何记录提交间?3.填报报表如何避免重复提交相同数据?4.填报报表如何同实现更新和插入操作?5.填报报表如何实现数据的历史版本记录?由于用户的问题集中在避免覆盖,所以我们先回答设置插入操作的方法。</think>### 填报报表提交后保留历史数据的设置方法 在填报报表中避免覆盖历史数据,需通过以下方法实现: #### 1. **数据库表结构设计** - **添加历史标识字段**:在数据库表中增加间戳字段(如 `update_time`)或版本号字段(如 `version`),每次提交自动记录操作间或版本增量。 - **分离当前表与历史表**: - 创建两张表:`当前数据表`(存储最新数据)和 `历史数据表`(存储所有历史记录)。 - 通过触发器或存储过程,在更新`当前数据表`自动将旧数据插入`历史数据表`。 #### 2. **填报属性设置** - **提交类型选择**: 在「模板 > 报表填报属性」中: - 若需**完全保留历史**:仅配置「插入操作」,禁用更新/删除(如下图)。 ```plaintext 内置SQL → 类型:插入 → 绑定字段 ``` - 若需**部分更新**:启用「智能提交」,但需配置主键和更新策略。 - **主键与更新控制**: - 为每条数据设置唯一主键(如ID),填报属性中绑定主键字段。 - 勾选「未修改更新」选项,避免覆盖未修改字段。 #### 3. **提交流程优化** - **自定义提交事件**: 在「提交按钮」的点击事件中编写JS脚本,实现: ```javascript // 示例:提交前备份旧数据 var oldData = FR.cellWriteback.getOldValue(); // 获取原数据 FR.doPlugIn("saveHistory", oldData); // 调用插件备份 _g().writeReport(); // 执行默认提交 ``` - **联动数据库操作**: 通过「提交事件」触发存储过程,自动将旧数据归档到历史表: ```sql CREATE PROCEDURE backup_history AS BEGIN INSERT INTO history_table SELECT * FROM main_table WHERE id=@id; UPDATE main_table SET ... WHERE id=@id; -- 更新当前表 END ``` #### 4. **版本控制扩展** - **启用「版本管理」插件**: 通过应用商店安装「数据版本管理」插件,自动记录每次提交的差异快照。 - **添加审核流程**: 在「模板 > 工作流配置」中设置级审核,审核通过的数据才更新主表,未通过的存入临表。 #### 5. **验证与调试** - 使用「填报预览」模式测试数据提交行为。 - 开启「SQL日志」检查实际执行的SQL语句,确认无覆盖操作。 - 通过 `FR.log()` 输出调试信息,监控提交逻辑。 > **关键点总结**: > - **插入优先**:默认使用「插入」操作而非更新。 > - **主键分离**:确保主键重复且历史表有独立标识。 > - **自动化归档**:通过触发器/存储过程减少手动操作。 > 填报功能支持灵活的数据处理策略[^1],结合数据库设计可高效实现历史数据留存[^2]。 --- ### 相关问题 1. 填报报表如何实现主键冲突数据? 2. 如何配置触发器实现自动数据归档? 3. 版本管理插件的具体使用步骤是什么? 4. 填报报表如何避免重复提交相同数据? 5. 与哪些数据库的历史数据管理兼容性最佳?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值