
前言 报表工具是一个接近 20 年的产物了 但是,直到现在,在各种数据信息化的系统中,报表工具的作用,不仅没有褪色,反而是因为信息化需求的增大、数据的增多,以及报表工具本身迭代后越来越方便好用,使得它的使用范围越发的广泛了 报表选型也是一个老生常谈的话题了 但是,直到现在,依然有很多项目组,很多技术人员并不知道该怎样正确的选一个合适的报表,一个不会让自己在项目后期掉坑里的报表 本文全文 9990 字,大概需要 10-20 分钟阅读,旨在把这么多年总结下来的一些选型重点注意事项和验证技巧分享给需要做报表选型的技术同仁们,让我们选型变的更有重点,轻松又有保障 如果有想偷懒同学,也可以直接跳到文章尾部去看结论,也有完整的选型指标,和对应的重点注意事项表格供大家下载使用 常规选型的误区 常规的选型基本都是做一个功能需求列表(也可能从网上搜来),然后去找厂商应答,形式没问题,但很多需求列表却会有很多误区: l 陈年老列表,体现不出当前的新技术,有些指标还可能是错的 l 没有错但也没有用的废话列表,任何厂商都可以应答全部支持 l 没有想到重点要验证什么的列表,也都会被应答成全部支持,没有区分度 l 厂家散布在网络中的钓鱼列表,有些厂商的还算中肯,但也有些厂商会把把一些看似有用实则无用的所谓独有功能说成重点去误导选型 这是一个常规选型表开头的小部分,在这么短短几行中就能出现两个典型的误区(图中标出的 1 和 2 ) 1. 指标写的不够细致,不知道该验证啥 比如中国式复杂报表这项,哪些是复杂的,哪些需要重点验证,这里就没写清楚,反而写了一些卡片式,分组式这类简单报表,这样就会误导选型的人了,选出来的产品可能根本做不了真正的复杂报表 多数据源支持也是一样的问题,也是说了等于没说,要支持哪些,以及如何支持法,都必须说清楚,否则这样的指标,所有的厂商都会答复支持,那这样的选型还有啥意义? 这类不细致的指标,会导致选型没有区分度,得到的结果都是支持,但如何支持的却会导致完全不一样的后果,这是传统选型表的最关键问题 后面我们会具体说到这两项指标的验证重点 2. 错误无效的指标 像 WEB 设计器和 APP 之类,就属于错误的指标了,为什么呢? 因为 web 设计器出发点是美的,想让做表的人员,不管是技术,还是业务,都可以方便的打开一个网页就可以做表,然而事实上却是没有一个工程师愿意用(不好用),也没有任何业务人员去用(不会用 + 不好用 + 懒) 提供的移动端 APP,看起来似乎是个必要的功能,但其实不然。报表自带的 APP,不能和整体项目的 app 集成,本身又缺少用户组织功能或不合适,没法拿来直接用,也不好二次开发补充功能,结果就是基本上还是没法用 所以这些指标如果列出来,就会误导一些对报表还不太了解的选型人员把它们加到自己的列表中,不仅把好产品给筛掉了,还选了不好用的产品 这里了就只举这两个误区的例子,其他的,会在后面系统详细的给大家展开分析 我们会从报表功能,BI、填报这几大方面,分类分项的去列出这些坑,列出每一项指标中的重点 让我们在以后的选型中,即使随便拿着一个列表,也能有目的,有针对的去验证,带着尖锐的问题去让厂商应答,做到心中了然,手中井然 开发工具 关注本地设计器 BI 页面分析概念逐渐流行后,有些客户就提出了一些新想法,比如是否所有报表都可以在页面上制作,厂商是否可以提供 web 端的复杂报表设计器?这样业务人员就可以摆脱技术人员自己制作复杂报表了 但事实上却是,业务人员根本都搞不定中国式复杂报表,不管是在桌面设计器还是 web 设计器,而且他们也根本不想搞,最终做表的任务还得是要靠技术人员来做,而技术人员则没人愿意用这些 web 端制表的功能的 原因有 2 1)web 端设计器因为技术局限性,很难做到像桌面设计器一样功能全面,很多复杂功能做不了,而且开发效率低下,对于有很多报表的项目,效率就是成本 WEB 编辑界面,看上去很美 2)web 端设计器会让应用变的臃肿庞杂,原本报表的应用基本只有 100 多 M 大小,带上 web 设计器后,就可能到了 600M 以上,而且 web 端功能很不稳定,会影响服务器的稳定 所以报表工具必须提供桌面设计器,所有国内的优秀厂商也基本都是通过桌面设计器来的做报表的。其实你想一下,有没有什么面向程序员的成熟开发工具是基于 WEB 的,复杂报表开发本质上是一种开发工具 清爽快捷的桌面设计器,实际上也很美 布局方式是 Excel 式的还是控件式的? Excel 式的更直观,易上手,易操作,可以看上面的图,用过 Excel 的人天生就会对这个界面有一种亲近感 国产货大都是Excel风格的,基本都能过关 其他方式的,控件式 条带拖拽式等,都不易摆放,不易对齐,设计不便 国外产品和开源产品很多都这样,可以批量放弃 可以看看下面这俩,看着就有点蒙圈,不知道该怎么弄了,完全和我们平时看到的表格不一样,增加学习成本不说,即使学会了也不好设计 另外还有一点非常重要,大部分的报表都是有原始 Excel 表样,只有类 Excel 的设计器,才可以把历史 Excel 直接转换成报表,而其他形式的,那就得全部重新画,成本太高 控件式操作方式是国外 20 年之前第一代报表工具的制作方式,从来就没有好用过,直到现在一些国外的开源报表仍然延用这一落伍的方式,这也是他们逐渐没落的原因了,现在开源报表论坛基本都沉寂了,无人问津了 数据源 关系数据库怎么验证 Oracle、DB2、SQL Server、MYSQL、INFORMIX 达梦 金仓 Gbase 。。。。。。。。。。。。。。等等 一大堆我都支持 是不是写得越多越牛? 其实这项不用考察,只要是关系数据库,写上的没写上的统统都会支持,因为这是世界标准!列更多并不更值钱! 如果有某个奇怪的数据库不能被支持,那大概率是数据库的问题而不是报表工具的事情,应该去找数据库厂商的麻烦。 非关系数据源怎么访问 1)不能简单相信“支持 xx 等”的说法,咱们需要什么,必须自己想清楚,然后去验证 2)所谓的支持,是直接做好读取功能,还是只给个二次开发的接口,这二者是完全不同的 比如下面这些常见的非关系数据源,提供直接能连才方便。 如果只是给个二次开发接口也算,那理论上就没什么不能支持的数据源了。然则,如果一切都要自己再二次开发,那买报表工具何用? txt,xls,xlsx,csv 文件做为数据源支持情况 txt,xls,xlsx,csv 文件做为数据源,大部分国产的都允许,有些开源和免费的不行 但是你的读取方式是啥的,提供流式读取了吗? 如果不是,那大数据量极有可能卡死,怎么解决? 报表模型 分组交叉列表简单报表怎么验证 什么????这么简单的功能也是坑???? 对,是 坑是啥,是不要被列表误导去验证这些大家都支持的,在简单报表身上都不用浪费时间,都支持!!!!! 如果哪个报表工具做不了这个,就没资格出来混了,敢拿出来溜的,这种事都不必再问了。就象你没必要去确认一辆车是不是有轮子 是不是支持复杂报表 然而,复杂的报表却不是任何报表工具都支持,或者能支持得比较好的。复杂报表的总数也许不多,但占用的开发工作量会是大头中的大头,一两个报表就可能把整个项目组给憋死。 那么,什么报表才算复杂的呢? 我们来挑几个中国报表中常见的复杂表样,抛砖引玉,只是为了唤醒大家这个意识,带着这些复杂的,再想想自己有哪些复杂的,让厂商去看是否能做出来,以及如何做出来。后一条非常重要,毕竟硬编码时什么都能做出来,但这是不是您想要的结果呢? 多源分片关联: 特殊分组、其他分组: 跨行组计算、同期比、排名 特殊分页,补空行: 每页得有表头表位,中间固定 7 行明细,不足的补空行 特殊分栏: 以上挑选的几个只是作为示例,中国式复杂报表也完全不至于这些,选型的时候记得先找出自己项目中最难的报表去找厂商看就是了 如果还想了解更多复杂报表还有哪些以及到底复杂在哪里,可以看这个帖子 中国式复杂报表复杂在哪里 呈现输出 图形种类是否全 不用考查 很多人喜欢把这个列一大堆,纯属多余。常见图形对任何成熟报表工具全都支持 而且还有很多开源图形包,要啥有啥;太特殊的那是真没有,也是到处都没有,只能自己做 是否支持第三方的统计图,以及是否可以自定义的统计图,才应该是考察重点 集成第三方统计图组件,如 echarts,D3 等,并可导出打印 这个是必须有的功能 为什么必须有?因为第三方的更漂亮 全面 简单,而且还不要钱!!比如 echarts,使用范围非常的广,很多工程师都喜欢也都用的很熟练 这个功能有两个要点要验证: `1)是否内置支持,而不是开放接口 2)是否可以导出打印,图表不是光看就可以的 `(这点可以就卡掉一部分厂商) 三种打印方式:applet、flash、pdf 3 种方式必须都支持才可以,因为很多浏览器已经不支持 applet 打印了,用户也需要根据项目浏览器要求来实际验证才可以,比如想用 chrome 浏览器,又想用 applet 打印,那就不行了 导出功能 普通的 Excel、Word、PDF 导出 对于网格式工具其实不需要考察,都支持,而且支持的都挺好,真正的做到了所见即所得 控件式的稍微差一些,遇到格式复杂的报表,导出可能会有格式紊乱,失真的情况 特殊一些的导出需求,才是验证的重点 比如近年来比较常见的 Word 报告式报表,这样的报表有几个特点 1 篇幅比较长 2 格式要求严格,各种缩进,对齐,间隔,分页,特殊字体都一点不能差 3 文字基本是固定的,但是表格的数据是实时的 就像上面这个,整个报告会有几十页,如果按照之前传统的办法,在设计器中硬排版,然后导出成 Word,那会非常的费劲,而且导出后的 Word 基本上格式都会有问题,即使后面再怎么微调,也做不到完美 这个其实和在 Excel 中排版一个 Word 文档是一样的道理,Excel 和设计器都不擅长大段文本的排版,它们擅长的是图表 那怎么解决? 如果能同时把 Word 的排版优势和设计器实时图表的优势利用起来,才是好的解决办法,可以在 Word 中先做好文字的排版,然后空出需要实时数据图和表的地方,由报表工具动态的生成实时图表然后插入到 Word 中 所以必须有这种能把图表动态插入到word模板中的能力才能更好的解决word报告式报表的需求,这点是必须拿来专门去问问各厂商的 对这个技术感兴趣的,可以看下这个帖子 怎样自动把报表插入到 word 文档中 大屏 DashBaord 大屏现在很火,很多项目都需要做大屏,那到底报表工具和是个什么关系呢,有没有一些厂商说的那么神奇,买个工具就能轻松做大屏呢? 确实,如果是简单的大屏,在 PC 上显示的,基本上是所有国内报表产品都直接支持的,工程师用报表就可以直接做出来,比如上面这个,就是工程师自己用报表自带的 echarts 统计图做出来的 因为用户的需求强劲,有些厂商会把做大屏专门弄成一个单独收费的模块,但其实这玩意儿并没有增加多少专门的内容,就是常规报表工具再加点布局功能,值不了多少钱 复杂的大屏,在专业 LED 大屏幕上显示的,有的超长,有的很高,因为屏幕分辨率特殊,需求特殊,基本上都是得定制开发的,相当于一个小型的项目实施交付了,这时候,任何所谓大屏模块都没多少用武之地的,那些号称万能的模板适应不了不同的分辨率,全部都得美工手动设计,然后工程师协助完成 所以,不要相信有专门做大屏的工具,没必有专门花钱买,这东西,简单情况报表工具直接就能做,复杂的,也全部是手工定制来对付 移动端该如何支持? 这也是近年的一个热点,报表纷纷上了移动端,似乎对报表工具也提出了新要求 其实,这是个伪需求。因为现在移动端的呈现都是用 HTML5,只要支持 H5 的报表工具都自然适应移动端,而近 20 年来的报表工具都是在 WEB 机制的,也天生就支持 HTML,根本就不存在所谓专门的移动报表功能 一定要考查,也就是一点点分辨率自适应的能力(手机分辨率种类多,还会横屏竖屏),少得可怜,和大屏工具类似,都值不了啥钱 还有一个常常被提出来的指标是有没有成型的 APP,这还是个伪需求。 从两方面来看: 一:项目需要 APP,如果自己已经做了,那你还要另外一个 APP 干嘛? 二:项目需要 APP,自己还没做,那报表厂商给我们的的 APP 能满足需求吗? 满足不了,厂商自带 APP 中的用户管理和功能组织和我们的期望几乎不可能适应。那么,能提供源码给我们改造吗?或者报表厂商能给我们定制开发吗? 答案基本上都是不能满足需求,不能提供源码,不提供定制开发,那你要这个 APP 又有什么用,到时候还是得自己动手 所以,是否提供app,不应该成为一个评测项,只要是报表能发布成H5的就可以 集成部署 集成还是独立? 这个是容易被忽视的一点,许多使用了国外大牌产品的用户,最后经常被集成问题折磨得死去活来,甚至有的 Linux 都不支持,还得专门摆个 Windows 配合工作。 所以选型的时候就得问清楚自己 我们有没有系统? 是要买个能集成到系统中的报表,还是要弄两套系统? 我们的系统什么架构,语言,能集成什么样的报表 想清楚了,再带着结论去选 至于集成还是独立,这里也简单说一下各自的优缺点 无缝嵌入式集成 方便项目管理,报表作为整个系统的一部分,统一使用用户系统的权限,流程等 大部分 java 项目,都愿意报表工具可以无缝集成 不能无缝集成,那就只能独立部署,然后一般是通过远程 web 访问来调用 独立部署也有一定的好处,可以把报表和应用分离,互不干扰 但更多的是不便之处 要管理两个应用 两个服务器 要考虑调用的安全性,或者单点登录 报表支持热加载 大部分厂商都可以做到报表热加载了 如果做不到,那就会有大问题,谁的生产机也不可能会让频繁重启 但是如果报表中用到了程序数据源,这个就多半做不到热加载了 现在有一些厂商有数据中间层,把数据源计算做成解释执行的脚本,可以做到热加载。 20% 困难的报表都会用到程序数据源 带有计算层的报表架构,其实和现在的数据中台的概念差不多 对集群的支持 在 WebServer 的帮助下,几乎所有应用都可以部署到集群上的,报表也不例外。但这只是初级阶段 对于报表来讲,真地要支持集群,还得有集群缓存同步的本事才行 访问 A 节点计算完的报表,再通过 B 节点查看就不用再算了,缓存已经同步,直接用就可以了 如果没有缓存同步,那跳转了节点就得重新算,性能会损失很多;这个所谓的集群就不是个整体,只是一堆独立机器的集合而已 安全问题 安全很重要,然而大部分情况却不用考查 因为,报表作为中间件产品,要嵌入到用户系统中,将被用户应用藏在里面或挡在后面 大部分安全问题,就该由主应用系统来负责了,报表工具不用管,也管不了 但是,注意但是,有一个很重要的安全问题,却必须是在报表工具层面解决,那就是SQL植入。 报表需要提供参数,而普通的参数查询,SQL 是固定的,基本无风险 但报表会提供通用查询功能,一般是使用 SQL 语句替换来实现的,这样带来了灵活性,但同时就有可能出现 SQL 植入的风险,泄露数据库信息。有个别厂商还甚至总是使用 SQL 替换的方式来处理普通参数查询。而报表开发人员的数据安全意识和技能一般都不会很高,很可能造成恶劣的后果,所以必须提前做好防范 至于什么是 SQL 植入风险及如何防范的详细信息,可以参考这篇文章 报表的 SQL 植入风险及规避方法 性能与容量 分析性能和容量应该如何验证之前,我们先看两种不专业的验证说法 两种不专业的说法 • 我们可以支撑多大多大数据量 • 千万数据几秒可以响应 不说场景,只说性能是不负责任的。多大数据量是和内存相关的,几秒能响应则相关的因素就更多,比如数据库速度、CPU 性能等。 所以千万不要被这些话述蒙蔽,也不要问这样的问题!!! 对性能知识感兴趣的可以看看下面的几篇文章,看完以后会对数据的性能问题产生一个更科学的认识 1T 数据到底有多大? 最简单的大数据性能估算方法 问产品支持多大数据量为什么不专业 然后我们再来看报表工具的性能和容量, 在有报表参与的数据分析项目生命周期中,对报表性能的理解误区,是容易强调报表工具的性能,其实报表性能的主要问题在数据源,报表工具本身的性能是次要的 数据源的性能 大部分的性能问题,都出在数据源上,也就是数据准备阶段!!!!但这时候考查报表工具的性能并没有意义 为什么? 因为这个时候的性能问题多出现在下面的环节 • 数据量太大,不会异步加载 • jdbc 读取慢 • 计算太复杂,需要复杂 sql 或者长存储过程 这些环节其实并没有报表工具参与,不该归罪于报表厂商,因为没有报表时候它们本身也慢 所以这点上,要问问厂商是否有协助计算的工具和方法,把数据准备阶段的性能提升上来,如果有,那这点上可以给厂商加分,性能问题可不是小问题,也不是谁都能做好的 报表本身的性能 少部分情况下的性能问题,才会体现报表本身的计算性能,那怎样才能测出纯报表的性能? 那就要抛开数据准备的时间,单独统计报表运算的时间了 可以用下面的两个例子来测试对比看看哪家的工具计算能力更强了,这两个更能体现出报表工具本身做计算和渲染的能力 • 多数据集关联的复杂报表 • 带部分明细的分组汇总表 这类报表需要由报表工具实现分组和关联对齐的动作,就会考查出报表本身的计算性能。 除了性能,还有容量 大数据量报表 报表中,最能代表容量问题的,就是大数据量的报表了,很多行业,都会有展现明细数据的要求,比如电信行业月底要看本月的全部充值记录,银行业要看当月交易记录清单,数据量会达到百万甚至千万级别 千万级别的数据,如果等全部取出算完再呈现,需要很长时间,没有人可以接受这么恶劣的用户体验,而且还有另外一个限制因素,那就是服务器的内存是有限的,一次装不下这么多数据,都得溢出,所以大部分的厂商都会想到用数据库的分页技术 但是数据库分页是有如下局限性的 也有厂商通过游标取数方式解决,但是游标是一个单向操作,只能向后翻页,不能向前翻页,也不是一个完美的方法 另外各种数据库分页的实现方式不同,每种写法和对应的数据源都是强耦合的,万一换了数据源,那还得重新来一遍 更先进的方法应该是能解决上面的这些问题才行的,具体怎么做,可以参考 海量清单与分组报表的实现 所以对于大数据量报表的验证重点就应该是:问问厂商是怎么处理的,如果是数据库分页机制,那上面的4个问题他们怎么解决?有没有更先进的方式? BI 自助报表 自助报表不是万能的!!! 首先就必须明确这一点,BI 不是万能的,不是上了一套 BI 信息系统,就能覆盖自己的数据分析需求了,完全不能! 目前市面上的 BI,多维分析,自助报表,都做不了复杂的报表 比如上面提到的中国式复杂报表,就必须得用固定报表工具来做 所以完整的数据分析系统,数据可视化项目,必然是BI+固定报表一起的 然后我们再继续看 BI 选型的一些重点事项 常规的,经典的分析动作 都不用考察,做不了的不配叫 BI 重点要看的是这几方面 支持排名、占比、环比、同比等指标计算 除了一些经典分析动作外,排名,占比这些分析也是常见的分析,但是有些 BI 软件是不具备这个能力的,去实际问问就可以了 环比与同比 如何解决多表关联查询 这个其实是 BI 的通病,CUBE 是个单表,原始数据是多表,需要 JOIN 生成好 如果有漏项,就得重新 JOIN 于是,很多 BI 产品只支持大宽表的后台,这确实是大家常用来对付这件事的手段。但灵活性很差,经常需要技术人员重新 JOIN 建模。 也有些自助报表产品提供有让业务用户做 JOIN 的功能,那一定要试试,感受一下您的业务人员能不能理解得了。如果不行,最后麻烦事还是回到 IT 部门,也还是大宽表 简单几个表关联并不困难,无法考查出效果。要重点针对有同维多关联或自关联的情况 拿下面这种数据结构去试吧,看看业务人员会不会晕,能不能用界面把正确的 JOIN 给拼出来 其实,有些厂商是真正动了脑筋去解决这个难题的 把数据结构呈现成树状就能解决这个问题,让业务人员可理解的方式拼出正确的JOIN 是否可被集成,是否提供源码供改造 选 BI 之前,要先想一想,是需要一个单独的BI,还是需要把自助报表功能嵌入到自己的页面中? 如果要集成,那就要考查自助报表是不是可集成,能不能被改造了 很不幸,大部分厂商提供的产品都无法被集成,也不允许用户自己改造 因为自助报表功能需要元数据支持,是在一个完整应用系统内的东西,很难将这一个功能集成到别的应用中了 不能被集成,又不给源码,那就必须得让厂商给定制了,直到做成自己想要的样子才能放手,否则厂商不给做,自己又开发不了,那就不是尴尬的事情了 有兴趣可以去看看那些实施了国外 BI 的用户,部门级使用问题不大,业务用户也常常会叫好。但是,如果想集成进企业门户体系的话,那去问问当初的实施商经历过的痛苦吧 报表平台 大部分的软件开发商不需要报表厂商提供平台 为啥 因为软件开发商就是做系统的,做平台的,你又给我一个平台干吗?而且你给我的大概率也没有我的行业色彩,不合我用 他们欠缺的是一个性价比高,能替他们节省报表开发工作量和软件成本的中间件 但终端用户,或者有些想急着上马来不及搞开发的软件开发商,是有可能需要一个现成平台的,这倒没毛病,问题在于:能不能让我进一步定制开发,甚至是不是开源 那些所谓的用户组织、权限、调度这些功能统统其实不用考察,因为只要喊报表平台,这些功能一定有 而且这些东西和应用环境,使用场景密切相关,肯定不会全适合,到了现场反正还得改,得去完善,所以,还不如问问是不是开源,或者是不是提供定制修改的服务?要收多少钱? 填写采集 输入控件 控件可以协助用户快速准确的录入数据,比如说下拉日历,下拉树,复选框这些 这些控件怎么考察,种类要多要全? 其实不用考察,号称支持填报的产品都会提供,各种下拉控件,复选框等 但是,某些涉及较大数据量的输入控件的性能,是需要考察的。 比如一些下拉框,下拉树,会涉及非常多的选择项,一般要提供异步加载的能力,否则就把界面卡死了 Excel 导入相关 导入 Excel 填报, 1 是可以把历史数据导入,免去手动输入的工作量,2 是可以很好的支持离线填报场景,不方便在线填,那就生成一个 Excel 模板去填,填完后上传就可以。这里要考查的是能够用填报模板生成带有校验或自动计算的 Excel,也能把填后的 Excel 中的数据填进填报模板,而不需要为每种 Excel 写段代码 但是很多厂商目前其实只能支持最简单的一行一行的标准格式的Excel来填报,稍微复杂一些的,就不支持了,比如下面这个表样 能不能和填报模板对应起来,不写代码就能正确采集数据入库? 就拿着这个表样去问厂家吧,看看能不能基本不写代码就搞定。支持的真没几个,几个老牌国产的还差不多 业务人员自定义填报 有些时候,业务人员希望能自己画个表样就安排下级机构填写,这功能做得到吗? 数据填写不是目的,填写上来的数据还要再分析统计,而分析统计就需要把填写的数据变成结构化数据写入数据库,否则谁也不会对着一团 Excel 文件做统计。 那么,业务人员有能力把表格转换成合理的数据结构吗? 直接用一个表样来说吧 同样的,简单的所有厂商都会,表样一难就做不了了,上面这个表样,入库时必然会对应多个数据表,还有主外键关联!你想业务人员能自己造出数据结构吗? 造不出来,那就还得技术去搞,就不能叫业务填报了 但好的工具,只要能画出表样就可以,工具就能自动构造好数据结构 所以真正能把这样有业务意义的复杂表样让业务人员自己画出来就填的厂商,并且填完的东西能够结构化后再统计,才算是真的做到了业务填报 总结== 以上就是我们列出的常见验证重点和坑了,大家可以根据自己的项目需求,去思考有哪些是自己会遇到的,有哪些自己没想到,然后重新弄一个重点验证列表,去找厂商逐个验证了 虽然说 20 多年的报表技术早已没有什么壁垒,但也并不是所有的报表都能经的起这份重点列表的考验的 在这里,我们也替大家做一个简短的总结,方便大家能从形形色色的工具中快速的筛掉那么一大批不合格的,然后再从合格的中间,挑选真正适合自己的 国外的基本都不行 功能严重欠缺,复杂展现、填报做不了,使用繁琐,浪费的工作量够买好几套国产工具了。冲着开源免费省钱去的,基本上都被搞的焦头烂额了,去问问老项目经理们就明白了 国产的几家大的老的都行 报表工具,很可能是企业级软件中仅有的、国产货品质远远超过国外货的领域了。国内的几家,大方面找不出什么你能做而他做不了的,虽然外围延伸方向有些注重性能,有些注重美观,但确实找不出什么大的功能和使用差异,市场推广方面倒是差异很大,有的看着轰轰烈烈,有的则比较低调传统 国产的新的也大都不行 市场大了都想来分一杯羹,但是技术活还是技术活,1 得有技术,2 得有沉淀 新产品大都功能不完善,不稳定,项目上天天改 bug 换包,是要人命的,哪个 PM 敢承担这样的风险 怎么区分是不是新冒出的产品,1 问厂家什么时候开始做的,2 去他们的技术群里或者论坛,看看其他用户都问些什么问题,如果问的都是各种报错,那就肯定是不稳定,bug 多了 BI 重点是实施与服务 拖拽分析谁都行,切个片,往下钻,往上返,再旋转下,操作像极了炒土豆片,说自己做不了的,那不配叫 BI 软件 BI 分析这个行业,和传统的咨询公司有些类似,并不是有了工具就能搞好分析的,是得有人给你服务,得有人告诉你这个行业应该去分析些啥指标,有人给你分享经验,做咨询,做好实施才行的 买 BI,千万别想着买个工具就行,一定得拉着厂商或集成商给你做好后续服务才行,否则旧服务器还能卖个二手价,旧 BI 软件,可是没人要的 价格是不用说的重点 筛选出功能差不多,资质差不多的,剩下的当然就是对比价格了,这经济下行的年代,能给公司省点钱,能给项目组挤点奖金出来,是多么大的贡献呢 报表工具 10 年之前,动辄都是上十万几十万的,但现在还有一些厂商要这么高的价格就没有道理了,不管是杀生还是杀熟,都说不过去,也不知道哪个牛 X 功能点能支撑这么高的价格体系呢 附录 下面是整理的目前比较新的指标列表,因为不管怎样,大家最终还是得拿一个列表去验证的,只不过这个列表和别的不太一样,就是把本文中提到的验证重点,都加到各验证项后面了,专门做了标注和解读,拿着这个列表就可以有重点的去验证了 最新 BI 报表工具产品选型指标和验证重点
通常我们在浏览网页的时候经常会看到多行热点信息列表数据,会每隔几秒钟在页面上就会顺次高亮显示链接标题的效果。 这种效果在我们的业务系统中也比较常见,比如企业仪表盘中部分区块的列表数据,网格式报表中。 在报表展现的页面中,如何能让所有数据行在指定的时间间隔内自动顺次高亮显示呢?还有如何做到无闪烁刷新页面来改变行的颜色呢? 下面我以设计器下报表实例网格式报表.rpx 为例具体说下实现方法。 这张报表原来有静态的隔行异色的设置,为了更方便看到我们实现的最终效果,这里我删除了原报表中第 5 行的背景色表达式的设置。 在报表展现的页面 showReport.jsp 中增加标签属性 generateCellID=”yes”, 目的是让报表在页面生成的时候每个格子都带有 ID,我们可以通过 ID 来获取到对应的格子来改变格子的样式效果。 在页面中增加 JS 方法。 浏览式报表初次加载的时候我们从数据区的第一行开始改变,当前行的行号也会自动增加,将变化的行号使用 setAttribute 保存,通过 JS 中的 setTimeout()每隔 3 秒钟回调 changeColor(),通过 getAttribute 取到变化的行号,再顺次改变当前行的颜色,当到最后一行后,再从数据区的第一行开始改变颜色。 var hcolor = "CornflowerBlue"; function changeColor(){ var tbl = document.getElementById("report1"); var currow = tbl.getAttribute( "currow" ); if( currow != null ) { currow = parseInt( currow ); var colLen = tbl.rows[currow].cells.length; for( var i = 0; i < colLen; i++ ){ tbl.rows[currow].cells[i].style.backgroundColor = "white"; tbl.rows[currow].cells[i].style.color="black" } } else currow = 3; currow++; if( currow == tbl.rows.length ) currow = 4; var cols = tbl.rows[currow].cells.length; for( var i = 0; i < cols; i++ ){ tbl.rows[currow].cells[i].style.backgroundColor = hcolor; tbl.rows[currow].cells[i].style.color="white" } tbl.setAttribute( "currow", currow + "" ); setTimeout( changeColor, 3000 ); } changeColor(); 通过以上步骤我们就已经实现了列表式报表每隔三秒钟从第一行数据区到最后一行顺次的高亮显示,在页面中可以方便用户避免看错行能更准确的看到列表数据,这样的效果在多区块的页面中也可以有效的引导用户查看。 除了上面介绍的这种页面自动高亮显示列表记录的效果外,还有静态的隔行异色的效果,具体实现可以参考文 页面表格怎么实现隔行异色、隔行变色 ;如果不想页面记录自动来高亮显示,还可以参考这篇文 鼠标移入报表时高亮显示所在行 ,实现鼠标指向时数据高亮显示的效果哦!
在 web 端我们查看一些数据时,为了方便用户理解数据的计算方法,会在鼠标指向格子的时候出现一些提示,鼠标移开的时候提示就不显示了,再比如说,鼠标指向页面按钮,出现按钮功能的提示,这样的效果在润乾中可以轻松实现,也有相应的文档介绍 鼠标悬停出现提示信息怎么做 。 除了上面说的那种静态信息外,在润乾报表中也可以实现鼠标指向显示对应的动态数据,还可以实现鼠标指向显示图片的效果哦! 这里以学生信息表为例,实现鼠标指向不同人员的照片,可以在旁边显示出相应的大图。 具体实现方法 制作一张学生信息表 数据库中存的人员基本信息是在一条记录里,而我们常见的人员信息表是将一条记录里的数据在不同行中显示,这种报表相对于网格式报表来说格式更加随意,我们称之为自由报表,关于如何实现自由格式报表可以参考数据库中的图片字段怎么在报表中呈现 (图片字段呈现) 。 报表模板设计如下图所示 增加要显示的图片的图层 在报表中追加一列,将 J2~J6 合并单元格,并将合并后的 J2 单元格数据类型设置为 html, 单元格的内容为: =" 人员信息高清免冠证件照 " 页面中增加鼠标悬停时图层的样式 在 showReport.jsp 中增加如下的样式: sjbb_hover{ padding: 10px 10px 10px 10px; border-radius: 3px; box-shadow: 0px 0px 2px #ccc; background: #fff; color: #000; position: absolute; text-align: center; display: inline-block; left: 532px; top: 47px;} 页面中增加图层的显示隐藏的 JS 方法 $("#sjbb_hover").hide();function show(){ $("#sjbb_hover").show();}function hide(){ $("#sjbb_hover").hide(); } 在报表中给图片增加 html 事件 选中 H2,设置 HTML 事件为 onmouseover=‘show()’ onmouseout=‘hide()’ 经过以上设置我们就完成了鼠标悬停显示图片的需求了。 浏览器中通过http://localhost:6868/demo/reportJsp/showReport.jsp?rpx= 学生信息表.rpx 就可以看到效果了。 翻页查看另一人的信息时,鼠标指向是对应人员的照片。 通过这样的设置,我们还可以实现鼠标指向,显示个二维码,用户可以通过手机扫码二维码,在手机上查看更多需要了解的信息。
想要制作一个时间轴记录事件的报表,通过报表工具要怎么制作呢?该怎么制作时间轴呢?下面我们就以润乾报表为例制作两种类型的时间轴记录表,具体看下如何实现。 简洁版时间轴 增加数据集,将需要记录的时间和事件取到。 时间和事件数据我从 EXCEL 文件中读取,数据如下图所示: 报表设计器下新建一张报表,然后在“报表”菜单——数据集,中增加文件数据集。 选择 EXCEL 文件,然后选择字段点击确定。 建好数据集后,在报表设计界面右下角就可以看到新建的数据集字段名称,选中对应的字段分别拖拽到 B2,C2 单元格,自动在格子中生成取数的表达式。 单元格默认的尺寸调整方式是按设计尺寸不变,为了内容能完全显示出来,我们需要手动将尺寸调整方式改为按单元格内容扩大。 将 A1、B1、C1 选中,然后合并单元格,在单元格输入文字“新型冠状病毒肺炎”。 设计器下预览报表的效果如下图所示。 接下来添加时间轴。 我将时间轴上截取部分存成图片,在 A2 单元格中增加图片文件。 添加完图片后,我们预览报表发现,只是在中间的那个位置中出现了一个事件轴节点。 上图的效果是因为 B2 是个扩展格,将前面这个带图片的格子拉伸了,而我们想要的是每个时间前都需要有一个时间轴节点,这就需要手动将 A2 格子的左主格修改为 B2。 再来预览下效果。 通过以上设置我们就通过图片的方式,做好了一个简洁风格的时间记录表。 时间轴颜色动态变化 下面截图的时间记录表的时间轴就是虚线,从样式来看,貌似不难,我们第一想法貌似可以直接通过单元格的边框线搞定,但是扩展单元格的边框线颜色是固定的,不能通过条件表达式来动态改变的。 一个格子的边框颜色不能动态改变,但是它的前景色和背景色是可以动态变化的呀! 这里截图中的效果是通过在格子中输入一个竖线的字符,根据事件累加的值做条件判断来动态改变格子的颜色的。 在 B1 格中定义了个变量并赋了初始值 0,在 D4 单元格设置值表达式为 =a=a+1, 前景色设置位白色,这样累加出来的 a 的值用来做条件判断,又不会显示出来。 在 E4 单元格中在前景色的地方设置条件判断表达式根据 D4 累加的值,动态改变竖线的颜色。 现在画重点:注意临时变量的使用,以及跟随扩展如何手动修改主格。
现在报表工具被广泛应用在各行业中实现 web 端的数据展现,其中有很多行业都会涉及文档的数据展现形式,大多文档中都会存在大段的文字,比较常见的如保险公司的保单,医疗行业里的药检证明等。而在报表中数据展现的基本单位是单元格,如果一个字段的内容是大段文本,内容非常多,要如何换行显示并且根据内容扩大格子高度?当内容多到一页放不下的时候,要如何设置才能自动将没显示完的内容分到下一页显示呢? 下面我会对常见文档报表中出现的大文本需求实现具体说明下。 内容超过格子宽度自动换行显示 报表单元格的尺寸调整方式默认为按设计尺寸不变,当内容很多,因为格子大小固定,内容只能显示出格子那么宽的内容。 为了看的效果更明显些,我给 A1 设置了边框,下面是预览的效果。 设置 A1 格子自动换行,它的寸调整方式会自动变成为按单元格内容扩大,这样设置后,文本内容就会分在多行显示。 预览效果如下: 内容超过一页截取部分显示 设置单元格的扩展方式为按单元格内容扩大,自动换行的话,当文本比较多,多到一页没显示完的时候,默认会在内容最后显示“文本太长,超出部分未显示……”。 除了截图中这种自动的截取方式外,也可以通过润乾的字符串截取函数进行截取,配合提示功能,实现格子中展现部分内容,鼠标指向展现全部内容的效果。 大文本内容分页显示 如果想余下的内容可以分在下一页中显示需要做如下设置: (1)可以在当前行下增加一行; (2)并将新增的行和原来大文本所在行进行合并单元格设置; (3)并将合并行设置上单元格拆分。 页面展现的效果,在下一页中将内容完全展现。 调整大段文本在分页时与页脚的距离 当大段文本分了多页,报表带有页脚,对于正文中的大文本和页脚的距离如果出现较大的情况,可以通过下面的两种方法控制: (1)增加多行进行合并,设置单元格拆分; 当内容一定的时候,通过增加多行进行合并,如下面的报表,增加行合并,然后预览,最后调整完报表后增加了差不多有一百行。 (2)根据内容多少动态扩展单元格大小。 根据字符个数大致算出展现大文本需要的行数,在大文本单元格后,用 to(1,len( 大文本所在单元格)/ 每行最多的字符个数 ),然后动态扩展相应数量的行,拉伸大文本所在单元格的行高,辅助列宽度为 0。 需要注意的是内容所在格子高度要合适,如上图中 A236 单元格的高要合适,因为当内容越多,行数就越多,由于行高需要是整数像素,那乘起来,误差也就越大。 以上介绍了常见报表中带有大文本报表的效果和设置方法,如果你也遇到了这种大文本的问题,可以参考看下,希望有助于你更轻松搞定报表中的大文本,如果上面没有讲到你所遇到的大文本需求或问题,欢迎下面留言,我再补充。
举例:多源普通填报表 描述:2~6 行的数据来源于 rq_report_address_main 数据库表 字段指定对象名为 address_main,8 行的数据来源于 rq_report_address_detail 数据库表 字段指定对象名为 details1如果原始数据表 rq_report_address_detail 中,记录数小于 2,那么再预览查看表结构的时候会发现系统解析后将上下俩部分 分为了一片 如下图: 出现此现象的原因是:目前分片规则是把界面中所有的单值划分到一组,只有存在多个值得字段才划分成新的组;比如 我现在 D2 D3 C8 D8 等都是单值 如果解析的时候发现 C8 扩展出了多个值 那就把它及相关数值格单独划分为一个分片,而后要根据分析出来的分组情况编写不同的去向 dfx 程序。 补充:除上述情况外,如精确指定字段名称所属对象的话,按照指定字段名称行列进行分片;如不指定字段名称所属对象,第一步先自动确定字段名,第二步才自动分片 规则如下:每片形成一个序表(序表可以理解为一个数据表)。通常行列上连续的一片数值格(连同对应的维度格)会被当做一片;连续的多行(两行以上)中,只有数值格,没有维度格和非空普通格会被当做自由增删行的行式分片;除了这些分片以外的单值数据(维度格、数值格)将被拼到一个一行记录的序表中。
一般来说,在报表中设计的统计图要用到两个变量值,一个是分类值,一般是统计中的横轴,还有一个就是系列值,相应的就是统计图中的纵轴。绝大多数情况下,分类值与系列值都是来源于表中的数据,也就是说,统计图是基于数据库表中的记录来设计器的,例如下面这个统计图: 一般会来自于这样的数据: 但是,有时会遇到下面这样的数据: 显然,如果还需要做出前面的统计图,那么分类值和系列值就需要使用数据库中的列名也就是字段名了。说实话,小编以前看到这种数据除了摇头,也就是想办法重新设计一张数据表,把所有列名存入一个字段,然后再进行数据转换和导入了。不是小编无能,没办法直接用这些数据画出统计图,实在是因为列名与列名之间都是独立的个体,并没有一个整体的概念,所以也就没有办法表示出对应的占比情况了。但是修改数据库这种操作往往用户是极不愿意接受的,那么,这种统计图就做不了了吗? 现在,经过技能升级的小编可以负责任地告诉你,润乾报表完全可以不修改数据表就搞定问题! 还是用上图的数据和图表来展示一下润乾报表的这个秘技: 首先, 设计报表模板: 其中: A1:= ds1.select(设备类型),扩展方向为横向。 A2:=list(“待机时间“,”空转时间“,”加工时间“),扩展方向为横向。 A3:=case(A2,”待机时间“,ds1. 待机时间,”空转时间“,ds1. 空转时间,”加工时间“, ds1. 加工时间) 这里用到了 list()和 case() 函数,是因为系列值实际上是分类轴的一个附属格,而报表画图的时候,只是把分类轴当成集合,系列值是当成一个值来画的,所以这里只取了 list 的第一个值。 看一下统计图中的设置: 接下来,保存,看下展现的效果,如下图: 噹噹噹… 一个列名作为分类的统计图报表就完成了。 我们来回顾一下其中遇到的问题和解决的技巧: 列名集合化 【技巧】使用 list() 函数获得一个枚举的数据集合。 系列值正确匹配列名 【技巧】使用 case() 函数使数据与列名匹配。
场景 在项目中做查询表单或者填报表时,经常会有动态关联的业务需求,比如省市区的关联,润乾填报 / 参数表单报表不仅可以实现单个省市区的动态关联,还可以实现多省市区的动态关联。 下面我们就以润乾报表示例数据库现有的数据表—客户表和订单表 为例,来举例介绍一下数据多选的动态关联。 最终效果 实现步骤 绘制主表,这里是一个简单的网格表单 统计不同城市的客户量以及销售额。 单元格表达式如下图 其中, 报表数据集及参数设置如下 制作参数表单,如下 其中 数据集 SQL 如下 重点设置为 C2、E2、G2 单元格实现国家 省 市 的多选关联过滤,具体设置如下: C2 单元格:设置 web 变量名为 arg1,同时设置编辑风格为 下拉数据集 取值 ds2. 国家,如下 E2 单元格:设置 web 变量名为 province,同时设置编辑风格为 下拉数据集 取值 ds2. 省份,关联过滤表达式:(‘,’+C2.toString()+‘,’).indexOf(‘,’+ 国家 +‘,’) >= 0,触发关联过滤单元格为 C2,如下 G2 单元格:设置 web 变量名为 city,同时设置编辑风格为 下拉数据集 取值 ds2. 城市,关联过滤表达式:(‘,’+E2.toString()+‘,’).indexOf(‘,’+ 省份 +‘,’) >= 0,触发关联过滤单元格为 E2,如下 3.确认保存,分别将主表和参数表单保存为:dzglgl.rpx dzglgl_arg.rpx。 到这里我们就完成了数据多选的动态关联。 本文要点: 掌握关联过滤表达式的用法,以 E2 的表达式为例解析如下: E2 关联过滤表达式:(‘,’+C2.toString()+‘,’).indexOf(‘,’+ 国家 +‘,’) >= 0 意为:从 E2 中检索与 C2 所选国家相符的省份。 此关联表达式灵活结合了 javascript 的 indexOf() 方法,方法说明:
概述 在《像 word 一样增加水印功能》中,已经介绍了如何在润乾报表中增加文字水印功能,包括了静态及动态水印。水印功能将标识信息嵌入到报表载体后,使得信息安全、版权保护有了更有效的方法。 水印除了纯文字形式,还有一种情况采用图片的形式,比如常用的 Logo。 整体效果如下 Logo 如下(为了看得更清晰,logo 用较大点的图片) 《像 word 一样增加水印功能》文中介绍的方式目前仅支持纯文字形式的,想实现如 Logo 图片一样的水印功能,在产品中并没有明确指出,所以要重新考虑解决方式。 功能分析 因为涉及到图片,所以还要从润乾报表在图片的支持情况上考虑。 1、 单元格图片:水印是对整个报表页面添加,单元格图片显然不可行,总不能给每个单元格都设置上图片,再者设置为图片后也就没办法再搞数据了。 2、 数据图层:该功能也可以为报表添加图片。但是,尽管可以定义该图层的大小,但是也仅能支持一张图片的缩放,也没法实现想要的水印效果。 3、 背景图:背景图是为整个报表设置,同时在“样式”上也支持“平铺”模式,这显然也更能符合水印的效果。 具体实现过程 找到可实现的方式后,接下来将实现的过程操作一遍。 1, 准备一张报表,并将单元格背景色设置为透明 注意:为了整体效果,此处最好将整行都个报表都设置为透明背景。 2, 将 logo 图片放至应用下 此处为设计器安装环境,将 logo 图片(logo.png)放在 demo/WEB-INF/reportFiles 下。 注:也可以是一个 url 地址 3, 为报表添加背景图,并将“样式”设置为“平铺” 4, 查看 web 端效果 总结 以上是实现图片水印效果的方式,操作过程相对比较简单,主要是找到这个更合理的解决的方法。当然,这个实现也有缺点,比如无法让水印随意按角度倾斜、要求报表单元格的背景透明等。不过倾斜问题,稍微辛苦点就是让美工同学们给提供一个倾斜角度的 logo 图片,也可轻松实现。
在很多填报表项目的开发过程中,为了保证数据规范且有效,常会在报表中设置各种校验以达到目的,比如:工资金额最多只允许包含两位小数、邮政编码必须是全数字组成的 6 位数且首位数字不能是 0 ,等等。这些要求,我们都可以利用报表工具提供的数据类型校验、单元格校验等手段来实现,但是总有“意外”情况出现,比如:小计校验要求分组内的各值相加等于分组小计,这种类型的校验有什么难点?怎么实现?下面我们举例实际看一下。 首先,了解基本情况及要求: 展现效果: 要求: 报表数据来源于数据库,其中 A 列指标名称是从数据库扩展取出的,要求各项计算结果满足分组内各值相加等于分组小计(比如:要求本年本月累计项中,指标代码 2 = 指标代码 3 + 指标代码 4),如果不满足则给出提示信息,要求进行修改,满足则可以正常提交。 报表设计界面如下: 其中 数据来源: 数据去向: 数据处理部分直接通过向导生成,这里不多做说明了。 分析难点: 由于分组小计(指标代码 2) 和 分组各项(指标代码 3+ 指标代码 4)都是从同一个字段“指标名称”扩展而来,报表不能准确定位取到参与计算单元格的位置并进行计算,故报表层面很难实现这种小计校验。 那么,就没办法实现了吗?(坏笑)对于润乾报表来说,显然那是不可能的。下面重点介绍这个神技能 :脚本校验 什么?脚本校验没听过?没关系,往下看… 操作: 从回填脚本中取出需要计算值; 按照要求结合集算器的 if 函数进行校验(提交时触发)。 数据去向脚本修改如下 其中 第 3-5 行,利用 A.select() 函数分别定位找出了需要参与校验的值; 第 6 行,按照原始需求利用 if 函数,进行数据校验,如果判断条件 A3!=A4+A5 成立,则在提交时通过 return 返回错误提示信息。 效果: 到这里,我们可以看出来,在报表层不好处理的小计校验,在脚本中很轻松就可以搞定了,是不是对脚本有那么一丢丢喜爱了,那就持续关注吧,毕竟人家是潜力股。 最最后,技术要点分享 巧用向导生成填报脚本 数据处理,右侧 【使用向导生成脚本】可以零代码完成普通填报表的数据处理 熟知集算器常用函数 A.select() 选出序列中符合条件的成员。 r.field(F) 取得记录中某个字段的字段值。 了解更多函数参考 doc.raqsoft.com.cn/esproc/func
你还认为填报表只能完成标准行列布局的数据填报?还在因表样复杂,填报分片错乱,设计不够灵活而苦恼?还在为业务填报表样设计灵活,但数据不能实时入库而感到惋惜? 那要先“祝贺”看到这段话的你了,这个难题遇到集算器脚本迎刃而解了。(撒花撒花….) 下面来举栗证实一下。 了解基本情况: 某单位上级下发统一报表模板其中包含 5 列(即 5 个字段),下级操作时随时可能在原表基础上增加字段,且增加的字段不需要回填至中央数据库,且下级报表操作人员不具备开发报表的能力。 了解基本情况后,综合考虑建议采用业务填报表来实现,原因业务填报表对使用者的要求比较低,简单来说会用 Excel 画表就行。但是此时有一个实际问题是我们不得不考虑的,那就是业务填报表不能将数据及时的录入到数据库中,需要手动处理入库这样很可能会出现数据遗漏的现象。 疑难点: 业务填报最终以外存文件(json/binary)的形式保存数据,那么,怎么保证这些数据能在提交后即使入库呢? 今天我们就重点说道说道,怎么样才能保证业务填报的数据能够及时的入库。 以流动资产统计表为例,操作如下: 以 sqlserver 2008 数据库作为中央数据库,表结构如下: CREATE TABLE [dbo].[ZCB1]( [id] [int] IDENTITY(1,1) NOT NULL, [zc] varchar NULL, [ncye] varchar NULL, [qmye] varchar NULL, CONSTRAINT [PK_ZCB1] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] 报表设计界面,如下: 其中 A3-A5, 单元格设置单元格类型为“维度格”,A3 字段名称为“流动资产. 资产”; B3-C15, 单元格设置单元格类型为“数值格”; B16 表达式为:=sum(B3:B15) C16 表达式为:=sum(C3:C15) 此时,业务填报表就做好了,发布到 web 端就可以实现数据的填报录入。 注意还没完现在的数据还是以外存文件的形式存储,下面重点要来了,我们通过集算器脚本将 json 的数据入库,脚本(json.dfx)如下: 其中 A1 使用 connect() 函数获取数据库的连接 A2-A4 使用 file() read() import() 函数将外存文件转成序表 A6 使用 db.update() 函数将序表内容保存至数据库 A7 使用 db.close() 函数关闭数据源连接 到这里已经完成了一大步,最后,将执行脚本与填报表的提交操作绑定。 操作如下: 在报表展现的 jsp 中使用回调函数,提交后自动执行 json.dfx 进行数据入库操作。 新建 other.jsp,调用 dfx 并执行,如下: 到这里,就实现了业务填报数据及时入库的操作了。有木有喜欢集算器脚本多一点了。想要 get 更多抓紧关注吧。 实例
润乾报表的统计图可以在图例 / 图形上设置超链接,从而实现钻取到明细报表的操作,钻取得到的报表可以在新窗口或者当前窗口中打开。关于如何在统计图的图形 / 图例上设置超链接,在用户手册中有常用示例的介绍。今天小编要给大家介绍的是如何在非模态窗口中打开图形超链接钻取得到的报表。首先创建一张带有统计图的报表,报表文件名为 planWorkView2.rpx。增加数据集 ds1, 下面是 ds1 的数据:在 A2 单元格中增加一个柱形图,统计图的分类和系列值数据分别来源于数据集 ds1 的 ORG_NAME 和 PLAN_CON。 在显示外观的选项卡中,设置图形超链接的表达式:=“javascript:showModal(’showReport.jsp?rpx=/planItemsInfo.rpx&reportType=2&arg3=”+ @orgId + “’, 800, 350)”,在超链接目标窗口中设置 =“_self”。 一张明细报表 planItemsInfo.rpx,明细报表中定义参数,可接收数据报表传递过来的参数。 在报表展现的页面 showReport.jsp 中增加 js 方法,调用非模态窗口来展现报表。 下面通过 showReport.jsp 访问 planWorkView2.rpx, 点击图形,看下在非模态窗口展现的效果吧! 由于使用的是非模态窗口展现明细报表,因此不会在关闭前强制焦点一直停留这个窗口上,而是可以进行任意切换,不会影响用户的其他操作。如果换成模态弹窗的话,则需要用户进行功能操作后,关闭窗口,才可进行其他操作。 好了,以上是关于在非模态窗口展现明细报表的介绍,如果你也有这样的需求,不妨参照本文介绍的图形超链接表达式的写法试一试吧!
填报功能是报表工具不可或缺的功能之一,此功能可以让用户在页面中进行数据维护操作。特别是在行式填报中,用户不仅可以修改数据,而且可以插入 / 添加新数据或删除已有数据。这样,在更新行式填报页面中的数据记录时,主键字段就会涉及 insert 和 delete 操作,而对于不同类型的主键我们应该如何进行更新设置?有哪些方面是需要我们注意的呢?下面我们将以雇员信息表的维护为例探讨一下主键设置的相关内容。 附 Employee 表结构: 先准备一张行式填报表,制作效果如下图所示: (行式填报表快速制作教程参见 数据维护不求人,一招搞定增删改 ) 来源脚本设置: 重点来啦 ~~ 去向脚本中不同的主键类型应该如何配置呢?我们来逐个攻破: 1.单主键 Employee 表的主键为 empno,那么脚本中的 update 函数配置为: A1.update@k(employee:employee_old,employee,empno,ename,salary,sex;empno) 在英文分号后面配置主键 empno,报表在做更新处理时,会以 empno 为主键对比 employee 和 employee_old 对象的数据,然后将差异数据更新到表 employee 中。 完整版脚本内容如下图所示: 2.多主键 一般情况下,物理表只设置一个主键字段就可以将数据记录区分开来,特殊情况下会设置两个及以上主键字段,例如上述 employee 表我们可以通过 empno 字段来区分数据记录,也可以通过 ename+sex 两个字段来锁定唯一一条符合条件的记录,此时我们的脚本中应该如何设置主键呢? 很简单,只需要用英文逗号隔开多个主键字段就可以了: A1.update@k(employee:employee_old,employee,empno,ename,salary,sex;ename,sex) 完整版脚本内容如下图所示: 3.自增主键 自增主键可以提升查询效率、节省磁盘空间,在填报中也有广泛应用。以 mysql 设置为例:可以通过第三方工具(如 Navicat)或者 sql 语句设置某个主键字段的数据自动增长。 在数据库端很容易配置主键字段的自动增长,那么在润乾报表中如何实现自动增长字段的数据更新呢?很简单,只需要添加一个 @1 选项就搞定了。 A1.update@1k(employee:employee_old,employee,empno,ename,salary,sex;empno) 其中,@1 选项表示第一个字段是自增字段,没有对应更新值表达式 注意:这里是数字 1 而不是字母 l 完整版脚本内容如下图所示: 4.“动态”主键 “动态”主键我们理解成通常说的 UUID,表示主键的值是一个不重复的随机数,这种方式比自动增长方式更安全、重复率更低。 我们以 mysql 数据库为例,将随机生成的四位数字作为主键 empno 的数据,并将数据更新入库。在润乾报表中只需要多一步 run 操作给主键字段赋值,剩下的和常规更新配置一样。 =employee.run(if(empno==null,~.empno=A1.query(“select round(round(rand(),4)*10000) as xuhao”).xuhao)) // 当 employee 对象中的主键 empno 字段为空的时候,我们将随机生成的四位数字赋值给主键字段 (这里为什么条件是判断为空呢?因为一般自增主键或者 UUID 主键都不允许编辑或者直接设置用户不可见,所以此时新增的记录中主键字段为空。) 完整版脚本内容如下图所示: 至此,我们已经将几种常见主键设置方式探讨完毕,现在回过头来看填报数据处理中的主键设置,是不是有种“wow~~amazing~”的感觉? 如果您在填报学习过程中有任何疑问,欢迎留言,我们一起来盘它!
随着信息时代的快速发展,报表工具的应用也越来越普遍,其中难免会涉及到很多填报需求。 比如: 数据采集录入填报时如何只更新当前修改行、用报表工具实现树状层级结构的填报表、web 操作数据留痕等等,今天我们主要来介绍一下 web 操作数据留痕,简单说就是填报表从 A 表取数,将 web 端修改记录更新到 B 表保存操作记录……如果您还不明白,其实就相当于记录您某个账号的登录时间地点。 下面我们具体看一下。 工具:润乾报表 oracle11g 数据库表结构(SQL 语句): A表:create table GDFW_RB_FHQK_MX( ID NUMBER, JCSJ DATE not null, TJRQ DATE, TJSJ VARCHAR2(12), QKJFH NUMBER(12,2) ) B表:create table GDFW_RB_FHQK_MX_HISTORY( ID NUMBER, JCSJ DATE not null, TJRQ DATE, TJSJ VARCHAR2(12), QKJFH NUMBER(12,2), CREATER NVARCHAR2(20) default ‘SYSTEM’, CREATETIME DATE default SYSDATE, XGYY NVARCHAR2(200) default ‘暂未填写’ ) 当前报表设计如下,首先实现基本的行式填报操作: 数据来源: 数据去向: 至此,填报表的基本功能已经实现, 下面我们继续以这个报表为例看一下怎么实现web 操作数据留痕。 保证数据来源、数据去向、报表中涉及到的字段个数名称一致。 在数据去向执行 update 前对要插入到 B 表的数据做处理。方式如下: 通过对比新旧对象的记录来实现,以获取到 web 端操作的记录,因为行式填报表在 web 页面上支持做增、删、改三种操作,故不能保证新旧对象的记录条数一致,所以这里需要通过双层循环来获取新旧对象的差集(即 web 页面操作的记录集)。 注:旧对象保存的是修改前的数据,新对象保存的是修改后的数据。 具体的数据处理过程: 数据来源脚本增加 XGYY,并且以对象(如对象:GDFW_RB_F HQK_MX)的方式返回新增后的结果集。如下: 数据去向脚本修改如下: 其中: 第 2 行、第 8 行以及第 10 行的 debug 部分,是为了观察各部操作前后数据的变化,有助于排查问题,最终可以视实际情况删除或注释。 3-7 行 使用双层 for 循环对比 GDFW_RB_FHQK_MX 与 GDFW_RB_FHQK_MX_old 对象记录并从 GDFW_RB_FHQK_MX 中删除两者相同的记录,从而整理出 web 端操作的行; for 循环原理: for 旧对象 if(新对象主键对比旧对象主键) for 新对象 if (旧对象记录 == 新对象记录)从新对象里删除 else 将 web 页面删除的记录插入新对象 注:if…else…作用是对比主键保证 web 页面上删除的记录也被记录下来。 最后新对象中保留的记录既是 web 端操作的行。 A9 单元格 使用 db.update@i() 函数实现更新入库, 其中 @i 选项代表的是仅执行插入操作。 通过上面的修改后,我们就可以实现 web 操作数据留痕了。 效果如下: web 操作前,B 表数据记录。 在 web 端访问报表,修改原有数据,并增加行(动图) web 操作后,在数据库端查询数据,检查一下,我们会发现仅把 web 端操作的数据插入到数据库中了,Bingo! 没想到吧,就这么轻松搞定了。 最后,课外知识扩展 怎样在不改变数据库表结构的基础上,增加字段。 使用集算器函数 P.derive(xi :Fi,…),给序表 / 排列 P 增加 Fi,…字段,形成 "P 中原有的字段, Fi,…" 结构的序表,然后对 P 的每条记录遍历,给每个 Fi 赋值为 xi。简单说就是使用此函数可以复制原序表也可以在原序表的基础上追加字段。 数据更新时,如何控制仅执行插入操作。 灵活运用 db_.update_(A:A’,tbl,Fi:xi,…;P,…) 函数的选项。 @i 对比主键只生成 INSERT。无 A’ 时不再对比,直接用 A 插入到数据库。 @u 对比主键只生成 UPDATE。无 A’ 时不再对比,直接用 A 更新到数据库。 @k 完成后不提交事务,缺省将提交。 等等,具体参考集算器函数参考 doc.raqsoft.com.cn/esproc/func/update.html 填报更新原理: 目前,行式填报表在提交的时会自动对比修改前和修改后的数据:首先对比主键,根据主键是否有新增或缺失确定数据的增删操作;然后再针对前后都有的记录对比每条记录值是否有不同,如有不同则执行 update 操作。 所以,建议数据处理(数据来源、数据去向)中的字段名称与报表中的字段名称个数要保持一致,不然填报更新时就会因新旧对象字段不匹配导致更新失败。 另外细心的你也一定找到了更新前后的数据是分开编辑的的好处了吧–灵活、自由、不受约束! 实例报表
需求说明: 润乾报表的单元格中支持超链接属性,用户可以通过设置该属性,实现在浏览器端用鼠标点击某个单元格跳转到指定页面,并且还能够传递所需要的参数,从而实现数据的钻取(详见《玩转报表超链接》)。不过这种超链接的设置方式只能跳转到单一的指定页面,在一些特殊的业务要求中,用户可能需要基于一个单元格查看不同的明细信息。比如,用户在访问一个地区列表时,既想经由该页面查看某地区的销售收入情况,又想查看该地区的其他信息。这样,在原有方式下就需要增加多个超链接按钮,每个按钮设置不同的超链接,而这种做法不一定能符合用户的页面样式需要或者操作习惯。下面,通过一个实际例子来介绍一下,如何在页面中增加右键操作,点击右键时先弹出可钻取的列表,选择后跳转到不同的页面。 一:设置报表格式 按照实际需求,开发报表模板,如下图: 报表格式比较简单,是一个比较普通的分组报表,A2 单元格按照国家进行分组,B2 单元格按照省份进行分组,C2 单元格显示出对应的城市名称,报表展现结果如下: 现在要求,在城市列增加右键操作,右键时弹出地址选择列表。 报表单元格有个属性为 HTML 事件属性,可以在该属性中设置 html 触发事件,如在 C2 单元格的 HTML 事件属性表达式中写入:“oncontextmenu=popMenu(’”+C2+“’) onClick=hidemenu()”,该表达式含义为,设置点击右键时调用 popMenu 函数,并将 C2 单元格的值传入进行,这样报表中设置了 C2 单元格的右键操作,只需要在显示报表的 jsp 中实现 popMenu 这个 js 函数以及相关操作即可。 二:页面 javascript 设置 在显示报表的 jsp 的 javascript 中实现相应操作,首先,因为页面中要右键操作,所以要先屏蔽掉浏览器本身的右键,在 js 中加入如下代码: function disClick(){ return false; } document.oncontextmenu=disClick; 接下来的话就是要实现报表中指定的右键操作,整体的js代码如下: <SCRIPT> function disClick(){ return false; } document.oncontextmenu=disClick; var strMenu = "<div id=\\"menu\\" class=\\"clsMenu\\" onMouseover=\\"highlight()\\" onMouseout=\\"lowlight()\\">" strMenu += "</div>" // 判断客户端浏览器 function showmenu(){ var rightedge=document.body.clientWidth-event.clientX var bottomedge=document.body.clientHeight-event.clientY if (rightedge<menu.offsetWidth) menu.style.left=document.body.scrollLeft+event.clientX-menu.offsetWidth else menu.style.left=document.body.scrollLeft+event.clientX if (bottomedge<menu.offsetHeight) menu.style.top=document.body.scrollTop+event.clientY-menu.offsetHeight else menu.style.top=document.body.scrollTop+event.clientY menu.style.visibility="visible" return false } function sysMenu(){ return false } // 隐藏菜单 function hidemenu(){ menu.style.visibility="hidden" } // 菜单项获得焦点时加亮显示 function highlight(){ if (event.srcElement.className=="menuitems"){ event.srcElement.style.backgroundColor="highlight" event.srcElement.style.color="highlighttext" } } // 菜单项失去焦点 function lowlight(){ if (event.srcElement.className=="menuitems"){ event.srcElement.style.backgroundColor="" event.srcElement.style.color="menutext" } } function openNewWindow(winhref,winstyle){ var objNewWindow = window.open(winhref,"",winstyle); objNewWindow.focus(); } document.write(strMenu); function popMenu(cb) { var SubstrMenu = "<div class=\\"menuitems\\" onClick=\\"window.open('http://www.baidu.com/s?wd="+cb+"','_self')\\">查“"+cb+"”的所有客户(百度)</div>"; SubstrMenu += "<div class=\\"menuitems\\" onClick=\\"window.open('http://www.baidu.com/s?wd="+cb+"','_self')\\">查“"+cb+"”的重点客户(百度)</a></div>"; SubstrMenu += "<hr>"; SubstrMenu += "<div class=\\"menuitems\\" onClick='hidemenu()'>隐藏此菜单</a></div>"; menu.innerHTML = SubstrMenu; showmenu(); return false; } </SCRIPT> 另外,为了更好的显示效果,还可以增加css样式来进行控制,将如下样式同样加入到jsp页面中: <STYLE>.clsMenu { BORDER-RIGHT: buttonhighlight 2px outset; BORDER-TOP: buttonhighlight 2px outset; VISIBILITY: hidden; BORDER-LEFT: buttonhighlight 2px outset; WIDTH: 200px; CURSOR: default; COLOR: menutext; BORDER-BOTTOM: buttonhighlight 2px outset; POSITION: absolute; BACKGROUND-COLOR: menu } .menuitems { PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-SIZE: 12px; COLOR: #000000; LINE-HEIGHT: 18px } </STYLE> 这样,在浏览器端就能够实现在单元格上鼠标右键跳转到不同的链接地址:  注:本例链接地址设置到了百度,实际中跳转可以自行根据实际需求在js中进行设置。 ##### 总结: 本例中通过报表的HTML事件属性实现了单元格的右键跳转到不同的链接地址,报表中除了右键属性外,还支持其他的一些触发事件操作,具体可以参考报表帮助文档:http://doc.raqsoft.com.cn/report/preference/cfsj170.htmlfunction disClick(){ return false; } document.oncontextmenu=disClick; 接下来的话就是要实现报表中指定的右键操作,整体的js代码如下: <SCRIPT> function disClick(){ return false; } document.oncontextmenu=disClick; var strMenu = "<div id=\\"menu\\" class=\\"clsMenu\\" onMouseover=\\"highlight()\\" onMouseout=\\"lowlight()\\">" strMenu += "</div>" // 判断客户端浏览器 function showmenu(){ var rightedge=document.body.clientWidth-event.clientX var bottomedge=document.body.clientHeight-event.clientY if (rightedge<menu.offsetWidth) menu.style.left=document.body.scrollLeft+event.clientX-menu.offsetWidth else menu.style.left=document.body.scrollLeft+event.clientX if (bottomedge<menu.offsetHeight) menu.style.top=document.body.scrollTop+event.clientY-menu.offsetHeight else menu.style.top=document.body.scrollTop+event.clientY menu.style.visibility="visible" return false } function sysMenu(){ return false } // 隐藏菜单 function hidemenu(){ menu.style.visibility="hidden" } // 菜单项获得焦点时加亮显示 function highlight(){ if (event.srcElement.className=="menuitems"){ event.srcElement.style.backgroundColor="highlight" event.srcElement.style.color="highlighttext" } } // 菜单项失去焦点 function lowlight(){ if (event.srcElement.className=="menuitems"){ event.srcElement.style.backgroundColor="" event.srcElement.style.color="menutext" } } function openNewWindow(winhref,winstyle){ var objNewWindow = window.open(winhref,"",winstyle); objNewWindow.focus(); } document.write(strMenu); function popMenu(cb) { var SubstrMenu = "<div class=\\"menuitems\\" onClick=\\"window.open('http://www.baidu.com/s?wd="+cb+"','_self')\\">查“"+cb+"”的所有客户(百度)</div>"; SubstrMenu += "<div class=\\"menuitems\\" onClick=\\"window.open('http://www.baidu.com/s?wd="+cb+"','_self')\\">查“"+cb+"”的重点客户(百度)</a></div>"; SubstrMenu += "<hr>"; SubstrMenu += "<div class=\\"menuitems\\" onClick='hidemenu()'>隐藏此菜单</a></div>"; menu.innerHTML = SubstrMenu; showmenu(); return false; } </SCRIPT> 另外,为了更好的显示效果,还可以增加css样式来进行控制,将如下样式同样加入到jsp页面中: <STYLE>.clsMenu { BORDER-RIGHT: buttonhighlight 2px outset; BORDER-TOP: buttonhighlight 2px outset; VISIBILITY: hidden; BORDER-LEFT: buttonhighlight 2px outset; WIDTH: 200px; CURSOR: default; COLOR: menutext; BORDER-BOTTOM: buttonhighlight 2px outset; POSITION: absolute; BACKGROUND-COLOR: menu } .menuitems { PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-SIZE: 12px; COLOR: #000000; LINE-HEIGHT: 18px } </STYLE> 这样,在浏览器端就能够实现在单元格上鼠标右键跳转到不同的链接地址: 注:本例链接地址设置到了百度,实际中跳转可以自行根据实际需求在js中进行设置。 总结: 本例中通过报表的HTML事件属性实现了单元格的右键跳转到不同的链接地址,报表中除了右键属性外,还支持其他的一些触发事件操作,具体可以参考报表帮助文档:doc.raqsoft.com.cn/report/preference/cfsj170.html
报表系统中,往往要对数据进行编号处理,从而使数据的条目更加清晰。在 excel 中,我们可以直接在一个单元格中输入 1,然后按住 Ctrl 向下拖拽单元格就可以自动生成连续的序号。不过除了连续的序号,实际情况中我们还会有其它对序号的需求,例如组内序号,或者是隐藏某些行之后显示连续或不连续的序号,这些又该怎么处理呢?润乾报表提供了一些快速添加序号方式和函数,让我们来一起看一下吧。 概述: 1)对于网格式报表,即数据设置是列表显示的,可以直接在单元格中填写 =seq() 或者是 &Cell ,然后设置该单元格的左主格即可。 2)对于数据设置是分组显示的,还有两种不同的效果:即组内序号和组间序号。 **准备工具:润乾报表 V2018 栗子 1:列表式报表显示序号** 如下图所示,数据集本身只有后面 7 个字段的值,前面的序号需要根据后面的序号自动扩展生成连续的序号。 实现方式 1: 使用自带的序号函数 seq() 的方式,然后设置单元格的左主格 实现方式 2: 使用自带的序号函数 &Cell,并且设置单元格的左主格 实现方式 3: 使用行序号函数 row(), 因为数据不是从第一行取数的,所以需要减 1,并且设置左主格 栗子 2:扩展数据中隐藏某些行时,显示连续序号 如下图所示:当 G2 的数据大于 50 的时候,就隐藏该行,并显示连续的序号。 如果还继续使用前面的三种方式,实现的序号则是不连续的。: 若想实现隐藏行之后的连续序号,可以使用临时变量的方式,实现方式为: 先在空白单元格定义一个变量 a,然后在 A3 单元格写 if 条件的判断,如果 G3 大于 50,就显示 a,否则显示 a+1。如下图所示: 预览结果为下图,然后第一行的行高可用设置为 0,不显示。 栗子 3:分组报表之组内序号 设置 B5 单元格的表达式为:&C5,然后设置其左主格为 select 扩展的单元格,即 C5。 预览效果为: 栗子 4:分组报表之组间序号 设置 B5 单元格的表达式为:=seq(C5),然后设置其左主格为 C5 预览效果为: 以上介绍的是普通报表序号的实现方式,填报表也是有可以添加序号的,填报表添加序号的方式可参考文章 填报流水号,缺省表达式设置
熟悉报表的人都知道,报表中实现数据排序通常有三种方法: 1、 在 sql 语句中增加 order by,如 order by id asc 2、 select 函数取数时,指定排序字段,如 ds1.select(name:-1),或者按照其他字段排序,如 ds1.select(EMPID, ,,;NAME:1) 按照 NAME 字段升序排序 3、 还可以按照某字段汇总后的结果进行排序,如:ds1.group(省份; 省份:1; ds1.sum( 工业产值):-1),对数据集 ds1 按照省份进行分组,分组后求出每组的 sum( 工业产值),然后按照这个汇总值对组进行逆序排列 可以看到,这三种方式有一个共性,排序字段的数据都存储在数据库中。但是,在实际使用中,数据经常会在报表单元格中进行运算(比如单元格数据乘以一个系数然后再和其他单元格数据相加等),而此时如果要根据计算后的单元格数据进行排序,上述三种方法就无法做到了。 下面,我们就介绍一下如何实现这种需求,基于单元格计算后的数据进行排序。 思路: 我们首先分析一下排序操作是怎么做的:按照某列数据排序,实际上是先算出该数据的“排名”,然后根据排名的“顺序”对数据进行重新排序。因此主要有两部分操作,一是如何生成排名,二如何根据排名重新对数据排序。 下面就按照这个思路实现一个实际例子。 首先,按照用户需求先将数据取出来以网格式方式展现,设计后的模板如下: 前几列按照实际需要将相应字段拖拽到单元格中即可,在 E3 单元格中,对运货费进行了单元格间的计算操作,需要解决的问题就是根据 E3 单元格数据进行排序。 接下来先生成 E3 的排名,排名写法比较固定,在报表后追加一列,在 F3 单元格中写入表达式:=count(E3[`0]{E3>$E3})+1,统计 E3 扩展出来的列中大于当前 E3 单元格的数量加 1,即为当前 E3 的排名。 好,现在排名生成了,看下如何基于排名重新对数据进行排序。 在报表第一列前插入一列,下边追加一行,在 A4 单元格中写入表达式:=to(1,count(B3{})),根据扩展区域重新模拟出一片扩展,如下图: 接下来就可以使用报表的动态格间计算功能,根据 G3(排名)和 A4 关联,重新在第四行取出想要的数据,在 B4 单元格中写入表达式:=B3{G3==$A4},该表达式含义为在 B4 单元格中取出排名(G3)和当前行相同的 B3 的值,并将 B3 单元格的扩展方向设置“纵向扩展”,报表预览如下: 可以看到,在 B 列中能够取到相应的 ID 值,其中,排名 6 和 8 都有两条记录,这是因为运货费单元格有相同的值,所以排名相同。 B 列中取出了订单 ID 的值,剩余单元格使用数据集. 字段名取数就可以了,如下图: 而原来的第三行数据作为中间数据,可以隐藏掉,同时将 A 列和 G 列也隐藏掉。 因为有相同数据,所以同一个排名会出现多条,相应的,有的名次下就会有空数据,例如因为有两个第 6 名,所以没有就没有第 7 名,为此我们在 B4 单元格的隐藏行表达式中写入:value()==null。剩下就可以根据实际需要设置报表样式了,最终展示结果如下: 可以看到,报表已经按照实际运费列的顺序从大到小排序了。 总结: 本文的例子中,首先根据单元格的顺序生成排名,然后在通过 to 函数模拟出一片数据进行扩展,再根据排名的名次重新获取需要的数据,这样就可以按照在单元格中经过复杂运算后的结果进行排序了。在实际应用中,还可以在表头中增加超链接,控制升序或者降序排序,具体的做法只需要在点击时控制 to 函数是从小到大还是从大到小扩展就可以了。
女人衣柜里总是缺少那么一件衣服,怎么办呢?当然是买买买呀!!!现在出国方便,电商平台有全球购,朋友圈里有代购,即使足不出户,漂亮衣服也会出现在眼前,时不时的勾引下你购买的欲望。可是,如果买来的衣服大小不合适,那就破坏了我们美丽的心情,这该如何避免呢?当然是看好尺码对照表呀! 上面这样的尺码对照表,对于小编这样执着于技术的宅女来说,看懂挺难, 但是小编知道怎么用报表实现这样的尺码表哦! 数据表结构如下: 在 COLNO,ROWNO 中分别存储了对应尺码表在报表的坐标数据,CODE 字段存储的是对应的尺码值,我们怎样根据行列坐标从一个字段中读取尺码信息,形成上面那 4 行的尺码对照表呢? 其实,这样根据行列数据取到对应交叉格的值的形式,就是一张典型的交叉报表,在报表中实现很简单,不信我就来和你说一下基本实现思路: 我们可以通过 to() 函数根据列号最小值和最大值横向扩展列,行号最小值和最大值纵向扩展行;接着通过报表取数函数(加过滤条件)取到对应行列的值。 下面就是报表中具体的做法: 1.. 获取行号最小值和行号最小值。 在 A1 中通过 ds1.min(rowno) 取出所有尺码中行号的最小值,在 B1 中通过 ds1.max(rowno) 得到行号的最大值。 获取列号最小值和列号最大值 在 A2 中通过 ds1.min(colno) 取出所有尺码中列号的最小值,在 B2 中通过 ds1.max(colno) 得到列号的最大值。 得到所有行号 在 C4 单元格通过 to(A1:B1) 函数表达式, 将尺码的行的坐标纵向扩展出来。 得到所有列号 在 D3 单元格通过 to(A2:B2) 函数表达式, 将尺码列的坐标横向扩展出来,这里要注意的是,需要手动将 D3 单元格的扩展方式改成横向,这样通过 C4,D3 就形成了尺码表的左表头和上表头。 根据行号列号取到对应尺码值 中间的交叉点 D4 单元格则用 ds1.select(CODE,colno==D3 && rowno==C4,1) 将对应行列坐标的数据检索出来。 将辅助行列进行隐藏 将前三行选中设置隐藏行,将前三列选中设置隐藏列,就画出了尺码对照表了。
现在的报表用户已经不再将报表作为一个单纯的报表工具看待了,有时候也会当作页面工具来使用,这时为了页面显示工整美观,就需要报表能够自适应宽度。下面我们就基于润乾报表来讲一下是如何做到自适应展现报表。 产品:润乾报表 V2018 方法 1:使用自带的 matchReport.jsp 访问报表,这个页面通过 reportMatchSize 这个自适应 js 函数实现自适应功能。 1、 新建报表(过程不再详细说明) 将报表保存在安装目录的 reportwebwebappsdemoWEB-INFreportFiles 下面。 2、 启动服务,访问报表 访问报表的连接为:http://IP:端口 /demo/reportJsp/matchReport.jsp?rpx= 报表名称.rpx (如果报表保存在 reportFiles 的下级文件夹中,访问报表的 url 需要改为:……rpx= 文件夹名称 / 报表名称.rpx) 3、 报表在 PC 端的展现效果: 通过上面的展现效果可以看出,使用自带的 matchReport.jsp 访问报表,在自适应宽度的时候高度也同比例缩放了。如果我们不想要这种宽度自适应,高度同比例缩放的效果,我们可以试试下面这种方式。 方法 2:润乾报表在网页端展示时是以纯 html 形式展现,所以可以通过页面对展现的报表进行控制。 在展现页面的 showReport.jsp 添加到以下 js: <script language="javascript"> myResize(); function myResize() { var tab1 = document.getElementById("report1"); tab1.style.width=document.body.clientWidth;// 网页可见区域宽 } window.onload=myResize; window.onresize=myResize; </script> PC 端展现效果: 小提示: 1、润乾报表自带 mode 自适应方式,有以下 8 种取值,可直接修改 matcvhReport.jsp 里面的 mode 属性: 2、matchReport.jsp 自适应方式也适用于手机端,在手机浏览器输入访问报表的 URL 即可。具体可参考文章:关于报表在移动端展现你需要知道哪些?(c.raqsoft.com.cn/article/1539050767973?r=IBelieve)
在实际的项目开发中,填报表的应用十分广泛。 多数情况下,填报表会作为整个项目的一部分配合需求灵活使用,但有时也会受大项目环境的影响,产生一些特别的要求。比如,通常报表单元格的数据类型大多是文本,有时却需要借助 HTML 或者 JavaScript 实现一些交互效果,例如在报表中添加一些说明性的提示、自定义功能性按钮等。显然,单纯的文本数据类型不支持这种交互操作,那么我们就会想填报表是不是能够支持 HTML 数据类型的用法呢?如果支持又该怎么使用呢? 答案肯定是支持的(你懂得),下面我们就举个栗子: 实例一要求: 报表中增加说明提示框,供填报表格参考。 下面以报表工具自带报表 2.2.sht 为例,看一下如何应用 HTML。 实例报表如下: 要求效果:报表右上角定义按钮,点击按钮后弹出说明信息。 具体实现: 在当前报表的基础上新增行,如下: 填报表展现页面(此实例为:previewInput.jsp)中,定义 String sgid=""; 且将 String sgid = InputTag.getInputId(); 修改为 sgid = InputTag.getInputId();,如下: 最后在 jsp 末尾的标签内添加 js 方法代码如下: 其中: abc() 方法 指定具体的弹出信息及方式; cell 变量 获取触发 abc()方法的单元格,并通过 $(cell).html() 定义具体的 html 事件。 效果:(动图) 实例二要求: 在行式填报表单元格中自定义按钮,点击后可以插入行。 这里之所以不直接应用自带的工具条按钮,是因为报表应用与项目集成后会屏蔽应用自带的工具条。 这里还是以报表工具自带报表 2.2.sht 为例,演示一下怎么在报表中调用报表工具内置的方法。 具体实现: 明确报表中需要自定义的按钮所要执行的操作; 这里以自定义插入行为例。 找出对应的方法; 插入行:_insertRow()删除行: _deleteRow() 追加行: _appendRow() 导出 excel: _inputDownloadExcel()导入 excel: _inputLoadExcelData() 因版本差异具体参考 inputtoolbar.jsp 参照实例一修改 $(cell).html() 中具体触发的方法,如下: 效果:(动图) 温馨提示: Jsp 中 39 行的部分必须重定义变量 String sgid=""; 且将 String sgid = InputTag.getInputId(); 修改为 sgid = InputTag.getInputId(); 否则报表展现会出现类似如下报错: $(cell).html() 中涉及多组单引号和双引号时,注意使用转移符 以保证 js 正确解析。 课外知识扩充: 文本类型是单元格默认的数据类型,我们在报表单元格里使用最多的就是这种类型。如果单元格的类型为“文本”,系统就把单元格中的字符、数字或表达式的计算结果都当成文本来处理。 HTML** 类型是超文本标记语言,一个 HTML 文件不仅包含文本内容,还包含一些标记。 如果报表中需要用到一些标记,但单元格不支持这种标记,这时就可以把单元格的类型设置为“html”类型,在单元格中嵌入 html 标记,通过 html 类型可以在单元格中显示单元格本身不支持的标记信息。html 类型还有一个用途是可以在单元格中嵌入隐藏的 javascript 函数,如果报表中多处都用到同一个 js 函数,我们可以把一个隐藏单元格设置为 html 类型,在此单元格中定义 js 函数,供其他单元格引用,这样就可以给用户的报表设计带来很大方便。
在数据填报的场景中,常常会遇到根据条件动态更新数据的需求,例如:在条件 A 下将页面所有数据插入到数据库表中,而在条件 B 下则将页面中做了修改的数据更新到数据库表中。 遇到这种需求,脑海中的第一个想法就是:存储过程更新、或者 java 代码更新。不过,这两种实现方式的工作量和后期维护却实在让人头疼不已。那么,还有其他什么实现方式吗?而且最好是能和报表完美整合到一起的那种…. 这样的美事儿,还真有!润乾报表提供了脚本模式的填报表制作方式,通过脚本,可以实现你各种天马行空想法。具体怎么操作呢?且听我慢慢道来。 下面我们以动态更新 demo 库中雇员表数据为例,当 type 参数的值为 1 时,将页面中 employee 表的所有数据更新入库;否则只将做了修改的 employee 记录更新入库。操作步骤如下: 第一步 制作行式填报 我们先使用行式填报制作向导制作一个简单的行式填报表,如下图所示: 【小技巧】 如果对采集规则不熟悉,那么可以对第二行每个单元格设置字段名称:对象. 字段 第二步 定义参数 在填报–参数配置页面中新增需要的参数,本文需要定义 type 参数作为数据更新处理方式判断依据,如下图所示: 第三步 修改脚本,实现动态更新数据处理 来源脚本为默认生成的脚本: 其中, B2 的语句:>EMPLOYEE=A1.query(“SELECT EID,NAME,SURNAME,BIRTHDAY,HIREDATE from EMPLOYEE”) 从 demo 库中查询 employee 表的数据,并将结果写到 employee 对象中 去向脚本修改为如下图所示的内容: 动态更新数据时,需要用到 if 函数来动态判断,这里着重讲解下 if 的相关配置: A2:if type==1 // 判断是否满足 type 参数值是 1 的条件 B3:>A1.update@ik(EMPLOYEE, 雇员, 雇员 ID:EID, 姓氏:NAME, 名字:SURNAME, 出生日期:BIRTHDAY, 雇用日期:HIREDATE ; 雇员 ID) // 当满足 if 条件时,将 EMPLOYEE 对象中的数据全部插入到雇员表中,update@i 表示只执行插入更新操作 A4:else // 不满足条件,type 参数值不是 1 B5:>A1.update@k(EMPLOYEE:EMPLOYEE_old, 雇员, 雇员 ID:EID, 姓氏:NAME, 名字:SURNAME, 出生日期:BIRTHDAY, 雇用日期:HIREDATE; 雇员 ID) // 当不满足 if 条件时,将页面中 EMPLOYEE 对象修改了的数据更新到数据库中,当 update 后无其他选项时,表示执行智能更新 【小技巧】 在不确定如何处理数据或者检查计算结果时,我们可以使用 debug()或者 output() 函数输出需要检查的信息,通过观察控制台结果来调试和判断。 【延伸】 类似场景: 1)type 参数是否为 1 只是我们假设的一个条件,实际的条件可能更加灵活和复杂。例如动态更新数据的判断依据可能是某个结果集是否为空,我们就可以使用 T.len() 获取结果集的长度,当长度为 0 时,表示结果集为空。 2)假设示例中的需求修改为:当 type 的值不是 1 时,将雇员表和 EMPLOYEE 对象的数据作比较,然后将差异数据更新入库。而雇员表数据在 guyuan 对象中,那么此时可以将 update 的写法改为: A1.update@k(EMPLOYEE:guyuan, 雇员, 雇员 ID:EID, 姓氏:NAME, 名字:SURNAME, 出生日期:BIRTHDAY, 雇用日期:HIREDATE; 雇员 ID) 至此,我们就实现了在脚本模式下制作填报表,进而动态更新数据的效果。这里需要重点理解的是 if 和 update 函数的使用,不过显然也是比较简单的哦 ~ 当我们遇到需要用脚本进行数据处理的情况,不要害怕,盘它就对了,盘的多了,你会发现原来脚本真的是很有意思的一种处理方式。
在实际的项目开发中,填报表的应用十分广泛。 多数情况下,填报表会作为整个项目的一部分配合需求灵活使用,下面就举例介绍一下。 要求: 当前用户在页面上修改了某行数据,报表自动将用户名更新到这些行的【操作人】字段,但在报表展现内容中不要显示。 当前报表设计如下,首先实现基本的填报操作: 数据来源: 数据去向: 至此,填报表的基本功能已经实现, 下面我们继续以这个报表为例看一下怎么实现只对修改过的行进行更新。 报表底端增加辅助格,用于获取用户名。 在数据回填执行 update 前对要更新的数据做处理。方式如下: 通过对比新旧对象的记录来实现,如果新旧对象不同,则在新对象中保留不同的记录供后面更新使用,如果新旧对象一致则不参与执行更新,以此达到只更新修改行的效果。 注:旧对象保存的是修改前的数据,新对象保存的是修改后的数据。 具体的数据处理过程如下: 数据来源脚本不做任何修改,数据去向脚本修改如下: 其中: B1 单元格表达式:=employee.([编号, 部门, 姓名, 性别, 出生日期, 入职日期, 籍贯, 工资]),列出对象 employee 中需要对比的字段; C1 单元格表达式: =employee_old.([编号, 部门, 姓名, 性别, 出生日期, 入职日期, 籍贯, 工资]),列出对象 employee_old 中需要对比的字段; 2-3 行 使用 for 循环对比 employee 与 employee_old 对象记录并从 employee 中删除两者相同的记录,从而整理出被用户修改的行; A5 单元格 使用 db.update() 函数实现更新,这里用变量 Operator 模拟后台获取的用户名。 其中,后台获取当前用户名可以参考以下实例: 在报表展现界面 showInput.jsp 中获取用户名,并将其拼接到系统变量 param 中,供更新使用 通过上面的脚本,我们就可以实现只对修改过的行标记【操作人】了。 效果如下: 修改前,操作人为空。 在 Web 端访问报表,修改其中任意几行 然后,在数据库端查询数据,检查一下,我们会发现只有刚才修改过的几行才标记了【操作人】,Bingo!没想到吧,就这么轻松搞定了。最最后,一定不要忘记把辅助格隐藏起来噢!!! 辅助行,行高设置为 0,这样就完美了。 课外知识扩展 什么是填报表: 通常我们看到的报表基本都是对已有数据的读取展现,但还有一类报表不仅能读取展现数据还可以做增删改的操作并与数据库交互,这类报表我们称为填报表。 填报表的用处有哪些: 作为一种“介质”,如:收集各地区的某项指标数据,供中央汇总统计使用; 作为审核流程的“材料”,如:项目经理填写预算报表,提交后由对应部门审批处理。 填报更新原理: 目前,行式填报表在提交的时会自动对比修改前和修改后的数据:首先对比主键,根据主键是否有新增或缺失确定数据的增删操作;然后再针对前后都有的记录对比每条记录值是否有不同,如有不同则执行 update 操作。 所以,建议数据处理(数据来源、数据去向)中的字段名称与报表中的字段名称个数要保持一致,不然填报更新时就会因新旧对象字段不匹配导致更新失败。 另外细心的你会发现,更新前后的数据是分开编辑的,这样设计有什么好处?容我卖个关子,想了解更多的就关注关注我吧!!!
在上一篇《脚本模式下的填报表制作》中,我们详细讲述了如何使用脚本进行数据处理、制作填报表,今天我们盘道一下脚本模式下如何实现条件查询。 一、需求描述 然后再进行增删改操作。例如,先过滤出所关心城市的客户信息,然后再对查询结果进行更新操作。那么,实现这个需求需要解决两个问题: 如何让条件录入更加人性化 脚本模式下如何实现参数的接收处理和数据过滤? 二、实现难点 多城市值传入时,脚本中如何处理参数并实现数据过滤; 参数模板中如何实现地区和城市之间的关联过滤。 三、操作步骤 第一步 制作行式填报表 我们先使用行式填报制作向导制作一个简单的行式填报表,如下图所示: 【小技巧】 如果对采集规则不熟悉,可以对第二行每个单元格设置字段名称:对象. 字段 第二步 定义参数 在填报–参数配置页面中新增需要的参数,本文需要定义城市参数,所以我们新增一个 city 参数,如下图所示: 第三步 修改脚本,实现数据过滤 这里着重讲解下 A2 执行语句: 对象 1=A1.query(“select * from 客户 where 城市 in (?)”,city.split(“,”)) 用户可以传递多个城市值,所以检索条件部分我们需要使用 in; 因为允许用户传递多个城市值,所以检索条件部分我们需要使用 in; 填报表的参数是没有数据类型的,所以我们需要将接收到的参数值处理成我们需要的格式,例如通过 split 函数将 city 参数值处理成数组形式:city.split(“,”)。 【小技巧】 在不确定如何处理数据或者检查计算结果时,我们可以使用 debug()或者 output() 函数输出需要检查的信息,通过观察控制台结果来判断。 第四步 制作参数模板 新建空白统计表,设置报表类型为参数模板,绘制如下图所示的效果: 其中, C1 单元格为辅助单元格,其意义是方便用户选择城市数据 设置 C1 单元格的 web 变量名为:area,编辑风格为下拉数据集: E1 单元格的 web 变量名为 city,编辑风格为下拉数据集,同时设置关联过滤表达式,用户在选择了省份后,可以选择对应省份下的城市数据: 至此,我们就实现了脚本模式下填报表的数据查询以及填报更新设置,这里需要理解的是 query 函数的使用,不过也是比较简单的哦 ~ 当我们遇到需要用脚本进行数据处理的情况,不要害怕,盘它就对了,盘的多了,你会发现原来脚本是很有意思的一种处理方式。
目前,多用户的软件平台已经是再常见不过的了,有成千上万个用户账号的平台也很正常。为了保证每个用户准确访问各自的信息,免不了要做这样或那样的权限控制,而且这种权限控制往往是需要基于数据层面进行管理的。 对于报表平台的数据权限管理,我们可以直观地理解为:不同的机构、角色甚至具体到人,在访问同一张报表时所看到的数据都有可能不同的。最常见的例子比如工资条(也可以看做是一张简单的报表),因为绝大多数公司薪资都是保密的,所以很显然,系统内不同人看到的结果肯定是不相同的。 再比如,区域销售情况统计对于不同区域的销售经理来说,也应该只能看到其所负责区域的数据。 今天我们将讨论这些传统权限管理中,一个特殊的需求:如何在报表中控制一个文件的上传和下载权限。比如:公司内部管理系统中,对于合同模板,法务部人员允许上传和下载,而销售人员则只能下载不允许上传。再比如,学校的教务系统中,关于学生的成绩单,教务处既可以上传也可以下载,而学生则只能浏览。 通常情况下,这种针对报表中某个编辑框进行权限控制的需求,我们会通过”是否可编辑表达式”来实现。例如: 以报表工具自带的实例 2.1.sht 为例,根据不同的用户名控制部门字段的可写性操作。 这里设定只允许 lis 可以编辑修改部门信息,其他人均不可以。 具体的操作如下: 选中部门列所在单元格 B3 然后在右边属性栏中设置 【是否可编辑表达式】为 user==’lis’或者 user==‘lis’?true:false(注意:此表达式严格按照 js 的规则书写,不能使用报表中定义的 if() 函数 ),并且在报表中增加对应的参数 user 用于接收用户名。 效果: 这个小例子显示了如何针对编辑框做权限控制,不过,如果我们照葫芦画瓢对”上下载文件”进行权限管理设置,当发布到页面上后就会发现,不仅刚刚设置的权限管理没生效,而且还会导致对其他单元格设置的“不可写”也同时失效了!估计一开始遇到这个问题,大家都会忍不住地以为自己写错了,经过再三检查也没发现问题,最终才能确定:目前不支持通过【是否编辑表达式】对”上下载文件”做权限控制。 那么,到底应该怎么实现”上下载文件”的权限控制呢?别着急,往下看…… 以报表工具自带的实例 4.3.sht 为例,对雇员照片所在的 E3 单元格做上传下载的权限控制。 报表设计界面如下: 其中,F1 单元格输出 userId 是为了辅助后面做权限控制。 在报表展现界面中,增加 js 方法实现上传下载的权限控制: 其中, ss变量,指定要对那个单元格做权限控制; qx变量,是报表工具内置变量名,其变量值0** 代表可以上载下载、1 代表 仅上载 2** 代表 仅下载、3 代表 不能上下载。 用户名 userID,,可以根据需要从后台传入,演示中采用参数模板传值。 效果: 用户 zhangsan 只允许查看不允许做任何操作,其他用户可以上下载文件。 这样,通过内置的参数 qx 结合 js 访问,我们就可以轻松实现这个需求,大家可以参考本文根据自己的实际情况做相应的调整。如果还想了解更多内容,那就关注我吧。
在企业的业务系统中,如何从纷繁复杂的数据中抽丝剥茧看到关键数据信息呢?一个重要的途径就是将企业和各部门运营中关键的 KPI 集中在一起显示,同时尽量省去在企业的各个业务系统中分别查找数据。 下面是我近期遇到的一个客户实际要求的效果,在一个列表页面中有多个模块,每个模块又可以以多 TAB 页的方式切换不同的报表,并且每个区块都有自己独立的查询过滤条件。在查询条件发生变化的时候,只是该区块刷新,而不需要刷新整个页面。 显然,上面截图的效果,通过硬编码或者通过 iframe 嵌套多张报表也是可以实现这样的数据展现效果,但肯定也需要相当的工作量,而且性能和灵活度较差……那么,有没有更快捷、灵活布局的方法呢? 我们知道,润乾报表的报表组是支持多 TAB 页的,同时也是支持参数查询的。通常,我们使用的参数查询条件是通过参数报表实现的,这时报表组中所有报表都共用该参数,而且位置只能在报表组的最上方而不能在每个区块上,因此也做不到局部刷新。 这样,是不是说润乾报表就无法实现客户的这个需求了呢? 当然不是,润乾通过报表组展现多张报表不仅有常规的多 TAB 页方式,还有下拉选择切换,以及 Dashboard 布局的方式展现。而上面的需求就可以通过使用报表组 Dashbord 布局,通过 dashboardlink() 来实现局部刷新。 下面就用个简化的实例来看下如何通过报表组实现一个页面多区块局部刷新的这样的需求吧! 分解页面,做出页面中涉及的报表文件。 上面截图中分了两个区块:区块一,区块二。 区块一有区块标题、3 个 TAB 页签以及与 3 个页签对应显示报表的区域,我们将区块的标题和 TAB 页签做在一个报表中,报表文件名为 T1.rpx。 另外分别制作 3 个页签对应的报表,命名为 d1.rpx,d2.rpx,d3.rpx。 区块二中有区块标题,查询条件,数据报表三个部分,我们同样将区块标题和查询条件做在一张报表中,报表文件名为 T2.rpx; D2 单元格的类型为 html, 表达式为 数据报表文件名为 d4.rpx. 数据报表中定义了一个参数,参数名为“姓名”,类型为字符串 数据集将根据该参数动态查询过滤,数据集定义如下: 创建报表组设置布局 新建报表组,添加上面我们做好的 6 张报表。 在报表组布局面板中设置报表显示的位置,并设置每一个报表在对应区块的适应方式。 保存报表组,在设计器下默认使用 previewDashboard.jsp 来展现经过布局设置的报表组, 而这里我们使用 showDashboard.jsp 来访问该报表。showDashboard.jsp 默认会显示标题和边框,如下图所示。 可以通过设置标签属性 needTitle=“no”, 去掉标题,needBorder="no",去掉边框,展现效果如下: 对区块一中的页签报表添加切换操作,选中 B2,C2,D2 单元格,添加超链接表达式,“javascript:dashboardLink(‘board.jsp?board=/00Dashboard/ 销售系统 /d1.rpx’,‘item1’);” 区块二中针对下拉列表添加查询操作 通过以上设置,我们就已经完成了不同区块多张报表以 TAB 页形式切换,并且区块查询条件相对独立的需求,当每个区块的查询控件值发生变化,下方的数据就会动态的变化的效果。 有没有觉得做这种报表有点像做皮影戏的人物?首先,分解出一个人物有哪些部分,分别制作好后上色(报表制作);然后,将制作好后的各组件组装到一起(布局设置),给各关节部位装上木棍(在联动的地方挂上 JS 事件)。这样,这个人影就能在幕布上栩栩如生地呈现了。
填报是报表工具不可或缺的功能之一,润乾报表不仅提供了多源 SQL 填报方式,而且提供了脚本模式填报,以便适应不同的填报数据处理需求。在线教程中对多源 SQL 方式做了详细的配置说明,这里就不再赘述了。(附在线教程地址:http://doc.raqsoft.com.cn/report/input/zzygwgstbb.html) 今天小编将带领大家解锁另外一种填报处理方式——脚本模式 以行式填报表实现雇员信息维护为例,我们来看一下脚本模式如何实现数据处理,请紧随小编的步伐: 第一步 新建填报表,编辑填报表内容和样式,如下图所示: 报表工具会将连续两行数值格会自动识别为行式填报,所以需要将第三、四行的单元格类型设置为数值格,设置方法如下图所示: 第二步 设置数据处理 依次点击“填报”---“数据处理”---“使用向导生成脚本”,会弹出如下图所示的向导配置页面,然后按照下图标示的顺序进行操作就可以自动生成脚本。! 其中,对象名称用户可以自行修改,例如修改为 employee,那么自动生成的来源脚本和去向脚本如下图所示: 其中, A1:=connect(“demo”) 表示连接 demo 数据库 B1:>employee=A1.query(SQL) 表示在 demo 库中查询员工表信息,并将结果赋值给 employee 对象 C1:>A1.close() 表示关闭数据库连接 其中, A1:=connect@e(“demo”) 表示连接 demo 数据库,@e 选项表示出错时返回错误信息由代码自行处理,否则将中断 B1:>A1.update@k(新对象: 旧对象, 更新表名称, 更新字段列表; 主键) 表示根据新旧对象的数据差异智能更新表的字段数据(关于 update 函数使用心得参见附录) C1:=A1.error@m() 表示获取数据库异常信息 D1:>if(C1==null,A1.commit(),A1.rollback()) 表示如果没有异常抛出,则更新入库,否则回滚处理 E1:>A1.close() 表示关闭数据库连接 第三步 配置字段名称 选中 A3 单元格,在右侧属性列表的字段名称中输入“employee. 编号”。 对数据采集规则不理解的同学,可以直接对每个数值格设置字段名称,规则是:对象名. 字段名。 这里分享一个【小技巧】,我们可以通过设计器的预览按钮查看填报表的分区识别结果: 在制作填报表时,需要保证右侧识别到的对象、字段名称和来源脚本的对象结构是匹配的,这是将数据成功更新入库的必要条件之一。 第四步 其他设置 按照需求设置编辑风格、校验、自动计算、显示格式等。 其中, 校验设置可参考文章: 报表数据填报中的合法性校验 ](http://c.raqsoft.com.cn/article/1544091400841?r=IBelieve) 自动计算配置可参考文章: 报表数据填报中的自动计算 ](http://c.raqsoft.com.cn/article/1544091026876?r=IBelieve) 总结: 至此,一个简单的脚本模式填报表就制作完成了。实现过程也很简单,但是你可能会有疑问:脚本模式到底是个啥(What)?我为什么需要它(Why)?它适合什么样的场景(Where)? What?脚本模式是基于集算器 (SPL) 语法的填报模式,通过内置函数实现数据获取、数据处理、数据回填等操作。 Why?脚本模式可以让开发人员更加明确需要维护的内容,也可以让开发人员处理填报数据时更加自由,让填报本身更加 open 和 free。 Where?多源填报场景下,多源 SQL 的配置步骤比较多,而脚本模式可以简化此配置;同时,从文件系统中获取数据、多表关联取数、动态取数等情况多源 SQL 是无法支持的,此时需要通过脚本模式实现。讲真,80% 的填报场景需要通过脚本模式制作实现。 附录: 脚本模式的核心函数:update() 一、语法: db.update(新对象: 旧对象, 更新表名称, 字段: 更新值,…; 主键,…) 有旧对象时,新旧对象的数据先进行对比,将差异数据更新入库,例如,根据主键对比数据后,新增了的主键会进行插入操作;主键相同,其他字段不同时执行修改操作;主键字段减少时,则执行删除操作。 如果只有新对象,那么将直接将新对象的数据按照主键设置更新入库,此时只涉及修改和插入操作,无删除操作。 update 函数详细说明可参考:http://doc.raqsoft.com.cn/esproc/func/dbupdate.html 二、常用选项: 举个栗子: 1)根据新旧对象差异数据执行智能更新 demo.update( 对象 1: 对象 1_old,EMPLOYEE,EID,NAME,SURNAME,GENDER, SALARY:SALARY+1000;EID) 说明:根据主键 EID 对比对象 1 和对象 1_old 的数据差异,并将差异数据智能更新到 demo 库的物理表 EMPLOYEE 中,更新字段为 EID、NAME、SURNAME、GENDER、SALARY,其中 SALARY 字段的更新值为 SALARY+1000 智能更新时,程序会自行判断执行 insert、update 或者 delete 操作。 2)根据新对象数据执行插入更新 demo.update@i( 对象 1,EMPLOYEE,EID,NAME,SURNAME,GENDER, SALARY:SALARY+1000;EID) 说明:对比主键 EID,将对象 1 的数据插入 demo 库的 EMPLOYEE 表中,插入数据的字段为 EID、NAME、SURNAME、GENDER、SALARY,其中 SALARY 字段的更新值为 SALARY+1000 三、注意事项: 1)必须设置主键字段 2)更新的字段内容需要在新旧对象中都存在 3)自增字段的选项写法是 @1,注意:这里是数字 1 而不是字母 l
在 IT 行业中,总有一些终端用户输入的内容让统计人员无从下手。技术人员在做统计汇总时,经常会遇到数据对不上的情况,经过一番沟通、讨论、排查后才发现有非法内容录入,这类问题在月初月底的财务报表中尤为常见。 那么,有没有一劳永逸的解决办法呢?(苦思冥想中…… ding~)有了,如果能在用户录入数据时进行有效性验证,从源头保证数据输入的准确性,那么这些问题就都不存在了! So,具体应该怎么操作呢? 不用担心,不用着急,我们接下来要请出的润乾报表就提供了一整套的解决机制,来看这里,我们从最简单的部分开始。 1.数据类型校验 最简单的校验方式莫过于数据类型校验,它是针对数据类型做匹配的一种校验方式,例如,当我们需要用户输入整数数据时,只需要把这个单元格的数据类型设置为整数型就可以了,这样,在数据录入的页面中,如果用户输入了不是日期格式的数据,就会弹出提示信息。 润乾报表提供了各种常见的数据类型供用户选择使用:日期、字符串、整数、数值···· 配置方式如下图所示:在右侧单元格属性中设置数据类型 2.单元格校验 如果我们在要求用户输入整数的基础上,再加上对整数范围的要求,那么简单地数据类型校验就不能满足需求了,怎么办? Don’t worry~ 润乾报表提供了“单元格校验”方式,这种方式通过遵从 javascript 语法规则的表达式来检查属性的合法性,可以在校验表达式中写一个 javascript 表达式,也可以调用一个函数。 配置方法: 设计器上方菜单栏中依次点击“填报”—-“单元格校验” 在弹出的对话框中配置表达式,如下图所示: PS:单元格校验也支持正则表达式的配置 例如 18 位身份证号的校验,可以使用 match 函数进行如下图所示的配置: 3.JS 校验 如果校验处理过程比较复杂,不能单纯用表达式配置,怎么办?Take it easy~ 我们还有终极大招:JS 校验 我们可以在 jsp 中定义 js 函数处理复杂判断,报表中调用这个 js 函数进行数据有效性验证。 以日期比较为例,当入职日期小于出生日期时,弹出提示框给用户以提示,具体操作如下: 1)在 showInput.jsp(展现填报表的 jsp)中增加如下 js 代码: 2)设置单元格校验,引用此 js 函数: 至此,关于数据校验的基本招式已经传授完毕,你 get 了吗?更多填报相关专题内容尽在润乾官方论坛:http://c.raqsoft.com.cn
都说数据是死的,其实它们也可以生龙活虎,到底咋回事呢?且听我慢慢道来。接触过 excel 的小伙伴们都知道,excel 中可以设置表达式,用以支持常见的加减乘除等运算,更复杂的还可以自己写 function,单元格中的数据会根据表达式自己计算出来结果,不要再用计算器了。这么方便的一个功能如果能在报表中实现,而且是在填报表中将自动计算后的数据填入数据库,那岂不是美事一桩?问题又来了,具体应该怎么操作呢?不用担心,不用着急,我们接下来要请出的润乾报表就提供了一整套的解决机制,来,看这里,我们从最简单的部分开始。 简单自动计算最简单的校验方式莫过于加减乘除了,润乾报表可以直接通过“列号 + 行号”的引用方式来获取对应单元格的数据。例如:下图是自动计算工资的自动计算表达式配置:=H3*1.2,表示应发工资是工资的 1.2 倍,用户只需要填写工资基数,就可以计算出来应发工资。 其中,表达式 =H3*1.2 中 H3 表示取第三行 H 列对应单元格的数据如果 H3 单元格是扩展数据,润乾报表可以自动识别扩展数据进行计算,无需另外做配置。 表达式自动运算如果我们在简单计算的基础上,加上一些判断处理,比如不同的工资段发放的奖金不同,那么简单的自动计算就不能满足需求了,怎么办?Don’t worry~ 润乾报表还提供了“表达式自动计算”方式,这种自动计算表达式的规则遵从 javascript 的语法规则,可以在自动计算表达式中写一个 javascript 表达式,也可以调用一个函数。 例如,我们需要对于工资基数在一万元以下的员工给予 1.2 倍的奖励,一万元以上的按照原基数发放工资,此时可以进行如下配置: =H3>=10000 ? H3 : (H31.2) 的写法是三目运算,它的效果类似于 if,表示如果满足 H3>=10000 的条件,那么返回 H3 单元格的值,否则返回 H31.2 的计算结果 < 三目运算说明 >:对于条件表达式 b ? x : y,先计算条件 b,然后进行判断。如果 b 的值是 true,计算 x 的值,运算结果是 x 的值;否则,计算 y 的值,运算结果是 y 的值。 3.JS 自动计算如果自动计算处理过程比较复杂,不能单纯用表达式配置,怎么办?Take it easy~ 我们还有终极大招:JS 自动计算我们可以在 jsp 中定义 js 函数处理复杂计算,报表中调用这个 js 函数进行数据自动计算。以计算日期差为例:在入职日期的基础上计算员工的在职时长,具体操作如下:1)在 showInput.jsp(展现填报表的 jsp)中增加如下 js 代码: 2)设置单元格自动计算表达式,引用此 js 函数: 关于自动计算的分享就先到这里了。
需求说明 对于带有层级结构的数据中,用户为了能够更加清晰直观地查看,往往需要在数据展示时将层级展示出来,比如常见的省、市、县结构,或者一些科目中也会带有层级。通常,我们管这种形式叫做树状报表。在查询统计类报表中可以使用报表的左主格来实现,但是由于填报模型更加侧重于数据处理,格式设计上有别于查询统计报表,往往较难实现树状报表。 下面,我们通过一个层级科目的例子介绍一下在填报表中如何实现这个需求。首先,我们看一下报表展示的结果: 这个报表是一个按照科目录入数据的填报表,科目分不同等级,比如 1001 为第一层,下属 100101、100102,然后下边又有不同科目。展示时要求能够按层级展示。 解决方案 此类报表根据数据库中数据层级要求不同,有不同的解决方案: 一:科目固定不变 比如省、市、县,行政区域极少发生变动,针对这种固定不变的,可以制作固定的报表格式,如下图: 报表设计时的格式和展现格式完全一致,因此技术门槛低,但是工作量大,如果是几十个科目,就需要设计几十行,如果更多,需要耗费的时间也就更多了。并且如果万一科目发生变化,后续的维护工作也会十分不便。 二:数据库中数据已经按层级存储好 在数据库中,科目顺序以及层级等都已经按照要求存储好了,此时填报表只需要按照正常的清单格式制作即可,如下图: 这种方式报表开发量小,但对数据库数据有特定要求。如果数据库中新增了科目,那么数据库中的数据顺序及格式都需要调整,以满足严格要求,才能达到效果,例如不同层级的前方有相应的缩进。这时往往需要人工对数据进行维护,因此实际应用中有一定的限制性。 三:数据库中数据灵活存储,有相应层级关联关系 上述两种方式对数据自身的要求都比较严格,而且都不利于系统维护。下面这个例子应该才是大家真正关心的,也就是在对数据库数据无特殊要求的情况下,如何实现一个带层级结构的树状填报表。 当然,如果要实现层级,数据格式不能是完全杂乱无章的,比如以下数据: CODE 字段存储的是科目,科目中的层级关系是:1001 这种四位的为第一层级,然后六位为第二层级,并且第二层级通过 CODE 的前四位来确定属于哪个第一层科目,第三层同样规律。这也就是说,要想实现层级结构,数据中是必须要有相应规律的。 需求实现 数据结构和层次规则确定了,接下来看看如何在填报表中实现该需求。这个需求的难点主要是如何设置层级,由于层级是动态的,单写 sql 很难实现,所以就需要借助数据处理利器:集算器。在集算器中,可以根据规律生成想要的数据格式,具体脚本如下: A1:连接数据源 B1:执行 sql,从数据库中取出需要的数据 C1:按照 B1 的结果,生成一个空序表,用于存放生成的数据,该序表中有四个字段:CODE、NAME、QCYE、QMYE A2:=B1.select(len(CODE)==4),从 B1 中取出 CODE 长度为 4 位的数据,即第一层数据。 A3:for A2,按照 A2 做循环,本例的思路就是按不同层级依次循环,然后取出下级数据拼接进去。 B4:>C1=C1|A3,C1 是之前定义的空序表,这里将 A3 的内容插入到 C1 中,A3 为每次循环的单条记录,此例中是第一层级数据 C4:=B1.select(len(CODE)==6 && left(CODE,4)==A3.CODE).run(if(CODE!=null," "+CODE):CODE),该表达式可以拆分成两步操作,select 是按照条件从 B1 中取出 CODE 长度为 6 位,并且前四位和第一层级相同的数据,即第二层。由于报表展示时,第二层前方需要缩进几个空格,所以此处在通过 run 函数,在科目前增加几个空格,并且可以增加判断,当 CODE 不为空时,也就是有子层级时再操作。这样就在 C4 里按照 A2 做循环取出了第二层。 C5:for C4,按照第二层再次做循环,要取第三层数据 D6:>C1=C1|C5,在 C1 的基础上再将 C5(第二层)插入进去,这样 C5 中就有两层数据了。 D7:=B1.select(len(CODE)==8 && left(CODE,6)==trim(C5.CODE)).run(if(CODE!=null," "+CODE):CODE) 该表达式同 C4,从 B1 中取出 CODE 长度为 8 位并且左六位为第二层 CODE 的值,也就是取出第三层数据,注意,由于第二层要设置缩进,在 C4 单元格中在 CODE 前插入了空格,所以此处条件关联时用 trim 函数去掉空格,再通过 run 函数在 CODE 前增加相应空格,具体缩进多少,增加几个空格即可。 D8:>C1=C1|D7,再将 D7 取出来的数据追加到 C1 中。 这样通过两个循环,就能够实现层级格式,此时 C1 中的结果如下: NAME 字段在原数据库中已经有相应空格了,所以集算器中并没有对其做处理,如果数据库中数据没有空格,也想做缩进的话,通过 run 函数在循环中一并处理即可。 A9:>taizhang=C1.new(CODE:CODE,NAME:NAME,QCYE:QCYE,QMYE:QMYE),C1 中数据是个序列,此处通过 new 取出相应数据生成序表设置给对象 taizhang,在填报表中使用。 A10:通过 close() 函数关闭数据库连接。 将该集算器文件保存为 get.dfx 供填报表使用。 数据来源 在填报表中,设置:数据处理——数据来源,采用 DFX 文件,选择刚才保存的 get.dfx 文件: 填报表制作 数据都已在取数 dfx 文件中处理完毕,所以报表格式设计起来就方便很多,如下图: 标题、表头按照需求设置。 A3 单元格类型设置成维度格,表达式设置成:=taizhang.(CODE),字段名称设置成:taizhang.CODE B3、C3、D3 单元格类型设置成数值格,字段名称为别设置为:NAME、QCYE、QMYE 这样报表就能够取出相应的数据进行展示,展示结果如下图: 数据去向 要想将数据保存回数据库,需要在数据去向中进行回写设置,此处同样可以使用 dfx 文件,脚本如下: A1:连接数据源 A2:>A1.update@k(taizhang:taizhang_old,TAIZHANG,CODE:trim(CODE),NAME,QCYE,QMYE;CODE),NAME,QCYE,QMYE;CODE)),通过 update 函数向数据库中 taizhang 表回写数据,具体可参看 update 函数说明,注意:之前取出时在 CODE 前加了空格做数据缩进,所以回写时要通过 trim 函数去掉空格。 A3:=A1.error@m(),看保存过程中是否有错误 A4:>if(A3==null,A1.commit(),A1.rollback()),如果错误(A3)为空,则提交,否则回滚事务 A5:关闭数据链接。 另外,还需要在保存对象的旧对象中设置: 这样,就能够完成填报表的树状层级结构。 后记: 通过此例可以看到,如果在集算器中对数据进行处理,事先形成层级树状结构数据,那么在报表中只需要直接使用集算器处理后的数据就行了。本例中通过科目的 CODE 位数确定层级,而在其它不同的数据结构中可能会有不同的形式,但必然会有相应的规律可循,只需要在集算器中按照相应规律整合数据。 小遗憾:这种方式灵活方便,但是报表数据扩展前在设计器中都在同一个单元格内,如果需要页面端按照层级自动计算,比如第三级数据更改后相应的第二级数据需要自动变化,这样就很难写对应的自动计算公式,but,报表展现后是可以通过 javascript 对页面中数据做处理的,所以可以在 js 中根据层级规律设置自动计算公式来实现。
应用场景及需求: 某电力集团在实际应用中需要在填报数据时将数据库中的字段以更符合业务人员使用习惯的方式进行呈现,其中就有行列转换的情况。在常规的应用开发中,一般都是通过专门设计的数据界面进行录入,然后再通过程序转换存入数据库。而现在有了集算器支持的润乾填报表,就能够处理各种有关数据结构的填报需求了,这种行列转换自然也不在话下。 首先,我们来看一下行列转换的准确含义: 在一些企业应用中,一些指标项在数据库存储时会做为不同的字段存储,这样数据结构会更加清晰,但是在报表展示或填报表数据录入时,又需要将列转换成行的形式,从而更加符合业务人员的使用习惯,这就是行列转换。首先看一个报表展示页面: 需求一:这个填报表是月度报表,要求按照月份查询某公司下各项目以及机组信息数据,并且能够对数据进行修改。 需求二:工具栏中增加两个按钮:“报表保存”保存当前页面数据,“报表锁定”能够对当前页面数据进行保存并对数据锁定,锁定后用户再次访问该月份数据就无法再修改了。 需求三:报表第二列是项目名称。用户系统结构比较特殊,页面中每个项目名称都是数据库表中的字段名称,第三列和第四列为机组信息数据,在数据库中每个机组为一条记录,也就是说数据存放在数据库中两个表中,分别是 rep_tl_config 表和 rep_tl_yb 表,取数或回写时要根据项目名称从不同表中取数或回写。 下面是这些需求的实现过程。 解决方案: 这个报表的格式相对比较简单,按照需求制作即可,如下图: A 列为序号列,单元格中设置序号。 B 列为项目名称 C 设置,B 列中项目名称中是有特殊符号的,和数据库中字段名称无法完全对应,会对取数造成影响,所以增加了 C 列,单元格类型为维度格,值为对应的字段名称。 D 列、E 列为数值格,该报表要取两个机组的数据,分别显示在 D 列、E 列中。 F 列为固定列,输入相应信息即可, G 列用于控制页面端加锁后数据是否能够被修改。 C、D、E、G 列均需要设置字段名称,根据数据取数的数据对象来确定。 取数设置 由于数据结构较为特殊,所以取数使用集算器文件(dfx),并且由于报表中数据来自数据库两张数据表,所以取数脚本分两部分处理,脚本一如下: A1:链接数据源 D1:单元格从数据表中取出公司名称赋值给变量:公司名称 E1:填报表首次访问时,如果没有传入年月,则取当前系统时间上月数据,表达式为:>month=if(month==null,pdate@m(now()),date(month/“-01”)) A2、A3 单元格分别定义了从两个数据表中取数的字段名称 D4、E4 分别定义两个变量设置机组名称,groupID 为机组传入参数,传入格式为 #1#2 方式,所以此处做了拆分。 A5:从 rep_tl_config 表中取出需要数据,数据返回如下: A6:使用集算器的 pivot 函数,将 A5 中的数据做行列转换,将列转成行,将字段名称转为行数据。 A8:将 A7 数据按照脱硫设备编号进行分组拆分,将数据放到 data 列中 A9、B9、C9 取第一个脱硫编号的数据,处理后放到 t1 对象中 A10、B10、C10 取第二个脱硫编号的数据,处理后放到 t2 对象中 A11:通过序号字段,将 t1、t2 两个对象关联在一起 A12:取出需要数据,此时数据格式为: 可以看到,已经将数据进行了行列转换,原来的字段做为项目字段中的值,另外两列存储对应的数据值。 A13:将 A12 单元格数据赋值给 tl_config 对象 至此,第一部分取数完成,接下来看下第二部分数据处理。 A16:从 rep_tl_yb 表中取出相应数据 B16:设置页面端是否加锁标志,数据表中有个字段“是否经过修正”,判断 A16 是否为空,如果为空,那么证明是第一次访问该月数据,所以值为 false,否则取数据库中对应值。 A17 中做判断,如果 A16 数据为空,则直接在之前定义的 tl_config 对象基础上增加公司名称、month、是否经过修正、flag 字段,返回给报表,即报表第二部分数据为空。 B22~B30 之间单元格设置和脚本一中设置设置方式类似,由于篇幅原因,此处不做过详细说明,最终将所需要数据放到 tl_config 对象中,tl_config 对象中数据为: 接下来,设置填报表中对应单元格的字段名称,将 C 列单元格字段名称设置为:tl_config. 项目,D 列字段名称设置为:1 脱硫装置,E 列字段名称设置为:2 脱硫装置,G 列设置为:是否经过修正 这样,填报表能够从数据库中取出相应数据展示到页面中。 数据回写 接下来看下数据回写脚本,同样,回写时也需要将数据回写到数据库的两个表中,此处脚本分两段来说明: B1:取出公司名称 D1:设置 month 对象值,如果传入参数为空,则取当前系统时间的前一个月 A2、A3 分别定义两个表中的字段名 D4、E4,分别解析两个机组编号放大 groupID1、groupID2 中 A7:>tl_config=tl_config.new(项目,1 脱硫装置,2 脱硫装置, 是否经过修正),从 tl_config 对象中取出相应字段,并生成新对象 tl_config A9:从对象中取出项目在 A2 中的数据,A2 为数据库表 rep_tl_config 中字段名 B9:=A9.new(#1,#2).derive(groupID1: 脱硫设备编号,kks:kks 编码,B1(1). 所属公司: 所属公司 ),从 A9 中取第 1、第 2 两列数据,并且增加相应字段,之前看过 tl_config 对象中数据,1、2 列中存储的是项目名称、机组 1 数据 C9:=B9.pivot(kks 编码, 脱硫设备编号, 所属公司;#1,#2),通过 pivot 函数,将行在转回成列形式。 B10、C10,取 1、3 列,同上,将机组 2 数据取出并作行列转换。 A11:>A1.update@u(C9|C10,rep_tl_config,${C9.fname().concat(“,”)};kks 编码, 脱硫设备编号, 所属公司 ),用 update 函数执行更新操作,将页面中数据更新到 rep_tl_config 表中,其中 C9|C10 是将机组 1 和机组 2 纵向拼接,fname() 取 C9 的字段名,并转换成字符串格式。 这样,rep_tl_config 表更新完毕,接下来看下 rep_tl_yb 表的处理,脚本如下: 处理方式和之前一样,A3 单元格定义的是 rep_tl_yb 中的字段名称,在 A14~A17 中按照之前方式,取出对应字段并通过 pivot 做行列转换,将数据更新到数据库即可。 这样就完成了数据的取数及回写操作。 加锁设置 在取数对象中,取出了数据库的是否经过修正字段,通过该字段的值控制页面中的数据是否经过锁定,该字段的值在报表的 G 列中取出,所以报表可以根据 G 列的值控制页面端是否能够修改数据,是否修改数据可以通过报表单元格的是否可编辑表达式属性控制,在 D、E 两列(两个机组数据列)的是否可编辑表达式中写入:G4!=“true”,表示 G4 单元格不为 true 时,在页面端可编辑。 上述完成了报表取数时可以根据相应字段控制页面端是否能够修改数据,接下来看下,如果在页面端点击报表锁定按钮,实现数据加锁操作。 报表工具栏默认使用的是 inputtoolbar.jsp,里边定义了工具栏的按钮,可在该页面自定义按钮: 里边增加按钮,点击时调用 submit 函数,在 showInput.jsp 中增加 submit 函数如下: function submit(arg1){ for(var i=4;i<=65;i++){// 报表共 65 行,从第 4 行开始设置 document.getElementById(arg1+“0_G”+i).setAttribute(“value”,“true”);// 将值设成 true _inputSubmit(arg1);// 调用报表保存的 js 函数 } 这样,在页面端点击报表锁定按钮,就能通过 js 更改标识位的值并将值保存到数据库中,再次访问报表时,页面中的数据处于锁定状态,无法编辑。 总结: 至此,完成了客户的所有需求,该例中可以看到,对于数据库结构比较特殊的表,可以通过集算器先对数据进行处理,将处理后的数据返回给报表使用,点击填报后又能在脚本中对数据再次处理,从而实现行列转换的需求,此例中主要是 pivot 函数的使用,具体可以看一下函数说明。并且,润乾填报表页面端的值可以通过 javascript 进行处理,从而实现数据加锁等相应需求。
使用类 excel 的多 sheet 报表进行数据采集填报是很常见的情况,而且多 sheet 间互相取数计算也是非常常见的。大家都知道,多报表之间是可以通过参数或超链接等传递数据,但同一个模板中多个 sheet 间是无法用参数和超级链接传值的。那么,我们该如何在一个 sheet 中取另外一个 sheet 某个单元格的值来做计算呢? 我们通过下面的这个例子来看一下,在润乾报表工具里面是如何实现的 ~ 需求: 通过输入订单 ID 查询订单的用户信息和明细信息,在订单信息中获取订单明细中包含几条数据,同时在订单明细表中计算总金额:总金额 = 订单金额 + 订单表中的运货费。效果如下: 实现工具: 润乾报表 V2018 实现步骤: 1、 新建填报表 1) 数据处理–- 设置报表的取数来源(例子中使用 demo 数据源中的订单表) 然后工具栏点击【填报】–【参数】,在弹出的参数编辑框中增加参数:arg1,跟数据来源的 sql 里的参数名称一致。 2)设置表样,如下图所示: 1、 对填报表增加 sheet 页 在报表的下方,选中【sheet1】,然后右击,在弹出的列表中选择【追加表格】,会出现 sheet2。 2、 修改 sheet 页的名称。 在报表的下方,选中【sheet1】,然后右击,在弹出的列表中选择【页属性】,然后在弹出的页属性中修改 页名称为”订单”,sheet2 同样的操作,将页名称改为”订单明细”。 3、 设置【订单明细】表的表样 1) 增加订单明细表的取数来源对象。(例子中使用 demo 数据源中的订单明细表) 2)设计表样,如下图所示: 好了,下面重点来喽,如何做到在订单表中获取订单明细表中的数据的条数,以及在订单明细表中获取订单表中的运货费做总金额的计算呢?这时候就用到我们的跨表计算了,快捷简单,一起来看一下吧。 4、 自动计算 首先,我们在订单表的 G11 单元格输入表达式:=count({订单明细!C3}) , 然后在订单明细表中,在 H3 单元格输入表达式:= 订单!D4+G3 5、 保存报表,名称为 test.sht 6、 建立参数模板 1) 新建参数模板 2) 设置参数模板样式如下图,并且设置 C1 单元格的变量名称为 arg1,跟填报表的参数名称保持一致。 3)保存参数模板,名称为 test_arg.rpx 8、启动服务器发布报表预览 9、 在参数模板中输入订单 ID:10345 在下面的预览图中可以看到,跨表取数的自动计算表达式 OK! 如果我们在订单明细中增加一条数据并提交,在订单表中,相应的包含多少类产品的数量也会自动 +1。 噔噔噔噔噔 ~ 效果轻松完美的实现啦 ~ 是不是很方便呢?除了这个相加的操作,还可以获取到订单表的值做加减乘除等计算,有兴趣的小伙伴可以自己尝试一下。 拓展: 在使用这种填报表组的时候,我们可能还会遇到想要两个 sheet 中的某个值保持一致的需求。拿上面的示例来说,想要订单明细表中增加数据行的时候,和订单表中的订单 ID 的值保持一致,如不一致,则给一个提示。 我们可以这样做: 选中订单中的 B2 单元格,然后在工具栏点击【填报】-【格间校验】,在弹出的单元格校验框中增加一个校验表达式: 这样当我们新增的雇员 ID 不一致的时候就会给一个提示: 关于校验的这些需求我不做详细说明了,有需要的话,大家可以看一下我们的另外一篇文章:报表工具之数据校验竟可以如此简单 小提示: 1、 如果想要获取 sheet1 输入的字符串,写法也是一样的。 2、 自动计算的单元格值不可编辑。 3、 目前只能获取其他 sheet 中非扩展单元格的值,即固定单元格的值。
在报表开发过程中,为了保证信息准确无误入库, 我们经常会被要求对报表增加校验以保证数据类型和格式的正确。比如:工资金额最多只允许包含两位小数、邮政编码必须是全数字组成的 6 位数且首位数字不能是 0 等等。面对多种多样、层出不穷的校验需求,如果都写 js 来实现的话,那工作量真是…(你懂得),那么有没有一款报表神器,能轻松搞定这些校验呢? 呵呵呵… 下面我就给大家推荐一下解救我的神器—润乾报表,此神器提供了强有力的校验方法,例如通过设置单元格的数据类型、在填报单元格校验或格间校验里写校验公式、自定义有效性验证脚本,等等。利用好这些手段,就能摆脱大量写 js 的命运。 下面我们就分类说明一下,润乾报表是怎么实现各种校验的。 数据类型校验 – 栗子 1: 要求: 工资录入的数据必须是数值。 设置如下: 选中工资所在单元格 H3,右侧属性 -- 表达式 -- 数据类型,选择数值型即可。 效果: 当工资输入非数值时,单元格失去焦点后,便会弹出提示“请输入数值!”,如下图 单元格类型校验 - 栗子 2: 这个栗子我们从多个较多进行分析讲解: 角度 1: 要求在原来数据类型的基础上,限定工资最多可录入两位小数。 设置如下: 菜单栏 中选择 填报 – 单元格校验,新增单元格校验表达式,其中, 表达式为:(/^d{0,8}.{0,1}(d{1,2})?$/).test(H3) 意为:H3 单元格内容必须包含 0 ~ 8 位整数,可带 0 ~ 1 个小数点和 1 ~ 2 位小数 出错提示为:工资金额,最多两位小数 如下图 效果: 当输入工资金额小数多于两位时,单元格失焦后,便会弹出预先指定提示信息,如下图: 角度 2: 要求邮政编码必须输入 6 个数字组成的数值串且首位数值不能为 0 。 设置如下: 菜单栏 中选择 填报 – 单元格校验,新增单元格校验表达式,其中 表达式为:D5.toString().match(/^[1-9]d{5}$/ 意为:D5 单元格的字符串,首位必须是 1-9 之间的数字,其 5 位后随意取 5 位数字。 出错提示为:邮政编码必须是首位不为 0 且长度需为 6 位的纯数字 如下图 效果: 当输入邮政编码输入数值串为数超出 6 位且首位数字为 0 时,单元格失焦后,便会弹出预先指定提示信息,如下图: 角度 3: 要求员工表中姓名列必须填写,不能为空。 设置如下: 菜单栏 中选择 填报 – 单元格校验,新增单元格校验表达式,其中 表达式为:C3!=null&&C3!="" 出错提示为:姓名不能为空! 如下图 效果: 当管理员录入员工信息忘记输入姓名时,单元格失焦后,便会弹出预先指定提示信息,如下图: 有效性校验脚本 – 栗子 3: 要求: 筛选面板中选择的截止日期不能早于起始日期,否则给出提示且不能进行查询。 设置如下: 筛选面板 菜单栏 报表 报表属性 其他选项卡,有效性校验脚本中写入方法,如下图: 其中,startDate 为起始日期的 web 变量名,endDate 为截止日期的 web 变量名。 方法为: if (getParamValue(“startDate”) > getParamValue(“endDate”)){ alert(“起始日期不能大于截止束日期!”); return false; } return true; 效果: 当筛选面板中选择的起始时间早于截止时间时,点击查询便会弹出提示,提醒用户修改。如下图 格间校验 - 栗子 4: 要求: 报表组中的关联项需要保持一致,或者计算后结果保持一致。例如:报表组中包含订单表和订单明细表,那么订单明细表中所有产品的订单金额总和就必须跟订单表中的订单金额保持一致,否则,给出错误提示不允许数据入库。 设置如下: 报表组中 菜单栏 填报 格间校验,新增格间校验表达式,其中 表达式为:订单!H6== 订单明细!G5 出错提示为:订单明细中总金额和订单中金额不一致! 注:表达式中“订单”和“订单明细”分别代表报表组中订单表和订单明细表的 sheet 页名称,见下图标注,H6 和 G5 分别对应订单表和订单明细表中的单元格,感叹号为连接符 效果: 订单明细中,所有产品金额总和为 1810,如下图: 那么如果在订单明细中输入其他值,在提交保存时,就会给出错误提示。如下图: 作者:IBelieve链接:http://c.raqsoft.com.cn/article/1543893011793?r=IBelieve著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
数据库中存储的数据通常会有一些代码值字段,如员工编号、部门代码、类别 ID 等等,报表展示时如果直接展示代码值形式,使用人员无法理解该值的具体含义,所以要求将编码值转换成对应的使用人员能够理解的中文形式,又或者数据库中存储的出生日期是 date 形式,展现时要将其转换成标准的 2018 年 12 月 12 日这种形式。下面通过一个例子的实际操作来介绍下这种需求的实现方法。 首先连接润乾自带的 demo 数据源,从“员工”表中取数制作一个员工信息表,报表模板如下图: 此时点击预览,报表结果如下: 要求: 1、 将出生日期转换成标准的 yyyy 年 MM 月 dd 日格式 2、 将性别、学历转换成对应的中文形式 3、 将工资加上货币符号 日期格式设置 报表单元格中支持显示格式设置,直接对数据进行格式化操作,选中 C3 单元格,双击右侧的显示格式的值属性,会弹出显示格式设置对话框: 里边有各类型格式设置,找到日期分类中的 yyyy 年 MM 月 dd 日,点击确定,这样,出生日期列就能按照想要的格式效果展示。 数值转中文 接下来看下性别和学历设置,性别比较固定,一般就是“男”或者“女”,针对此种比较固定的,可以在显示值表达式中的 if 函数进行控制,在 D4 单元格的显示值表达式中写入:if(value()==1,“男”,“女”),value() 函数是报表自带的一个函数,用于获取当前单元格的真实值,通过判断当前单元格为 1 时,返回显示值“男”,否则显示“女”,注意:value()==1,性别字段在数据库中是整数,所以此处直接写 1,如果是字符串,需要写成”1”,要注意数据类型,如果有多种类型,可以做 if 嵌套,具体可以参考报表函数说明。针对此种数据比较固定的,还有一个函数可以实现:map 函数,也可以在 D4 单元格的显示值表达式中写入:map(list(1,2),list(“男”,“女”)),第一个 list 中列出的是单元格内真实值的列表,第二个 list 会进行显示值的映射。 学历单元格设置和性别有些类似,都要通过显示值表达式进行设置,可以使用 if 或 map 函数,但是学历数据会较多,需要写入大量的表达式,并且学历在数据库中可能是会变化的,比如过段时间会增加个新学历,还要再次修改报表,针对此种形式,数据库中通常会有中文字典表。在报表中新增数据集,从“DEGREE”表中取数,该表中数据如下: 可以看到,ID 中的数据就是员工表中学历列的值,NAME 字段存储的是对应的中文,这样可以根据 ID 和 DEGREE 字段的关联,取出需要的中文进行显示,在 E3 单元格的显示值表达式中写入:ds2.select(NAME,ID==value(),1),该表达式含义为从 ds2 数据集中取出 ID 等于当前单元格值的 NAME 字段的值放到显示值中显示,注意后边的 1 为取出满足条件的第一条记录,如果有满足直接进行返回不再向后判断,所以为提高报表计算效率,需要增加“1”的设置。这里用到了从另外一个数据集中取出对应的中文的写法,实际使用中,如果字典表和数据表在同一个库中,建议通过一个 sql 通过 where 关联方式直接取出中文,这样当数据量大时效率更高,如果数据来自不同库,数据量大时导致计算较慢,可以通过集算器将两个数据集 join 在一起返回到报表是一个数据集,这样效率更高,具体看实际需求。 货币格式 最后工资列设置显示格式“¥#0.00”就行了,如图: 最终报表展示效果如下: 本例中通过显示格式和显示值表达式的使用能够控制单元格的显示样式,此时更改的只是单元格显示效果,如果在其他单元格引用这些单元格的话,引用的还是报表单元格的原值,如果要引用显示值,可以使用 disp() 函数。 显示格式表达式控制 显示格式目前用到最多的是直接在显示格式中选择,实际上显示格式支持表达式对其进行控制,比如某个单元格表达式为:=list(11,12.5345,14,15.66),这个单元格展示时既有浮点数,又有整数,好多客户希望如果是整数则直接显示整数, 如果是浮点数,则保留两位小数显示,这样就用到了显示格式表达式,如在该单元格的显示格式表达式中写入:if(value()==int(value()),“#”,“#0.00”),判断该单元格的数值是否是整数,如果是则显示格式为”#”, 否则显示格式为”#0.00”, 该单元格预览后效果如下: 可以看到报表属性可以通过表达式进行动态控制,达到动态的显示效果。 显示值实现特殊格式 润乾自带了显示格式,但有些格式可能无法满足客户的特殊需要,比如 2018-11-30 这种日期格式需要显示成:30 Nov. 2018,此时可以使用显示值表达式进行特殊设置,比如 B2 单元格为日期,则在 B2 单元格显示值表达式中写入:string(day(value()))+"“+case(string(month(value())),“1”:“Jan.”;“2”:“Feb.”;“3”:“Mar.”;“4”:“Apr.”;“5”:” May.“;“6”:“Jun.”;“7”:“Jul.”;“8”:“Aug.”;“9”:“Sept.”;“10”:“Oct.”;“11”:“Nov.”;“12”:“Dec.”)+” "+string(year(value())) 该表达式先通过润乾函数分别截取日期中的日、月、年,然后通过 case 函数将月转换成想要的格式再拼接在一起,这样就能够实现特殊显示格式的控制。 总结 通过显示格式能将数据进行格式话操作,通过显示值能够将单元格内的值换成其他值进行显示而不影响原单元格的真实值,并且两个属性都可以通过表达式灵活设置,使得数据显示设置真的灵活运用于各种需求之中。 作者:gxy链接:http://c.raqsoft.com.cn/article/1543563271737?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在业务系统中,常常会遇到这样的需求,用户录入了某些数据后,系统需要自动算出另外一部分单元格的值,从而方便用户的计算、简化用户的输入,进而减少错误率,这就是我们常说的自动计算功能。自动计算在 excel 中很常见,那么在报表工具里我们要如何去实现呢? 下面我们就通过润乾报表设计器来讲解一下,如何实现自动计算并提交入库的功能。 使用工具: 润乾报表 V2018 操纵步骤: 第① 步: 安装并启动设计器 第② 步:配置报表使用的数据源(我们以润乾自带的 demo 数据源里员工表为例) 点击【本地应用】-【启动示例数据库】,启动系统自带的 demo 示例数据库服务。 然后点击【填报】-【数据源】,在弹出的会话窗口中,选中 demo 数据源,点击连接按钮。demo 数据源变为粉色,即为连接成功。 第③ 步:设计报表 我们使用向导来生成一个简单的行式填报: 点击【文件】-【新建行式填报】,然后在弹出的会话窗口中,选择要使用的字段,并且勾选出主键。 点击确定之后会自动生成一个行式填报。 第④ 步: 调整样式(这个不再做详细说明) 第⑤ 步: 保存并且发布报表,展现效果如下图所示: 第⑥步:实现自动计算:让应发工资按照工资的 1.2 倍发放。 现在我们在 I3 单元格里面写自动计算的表达式:=H3*1.2 第⑦步: 保存并且发布报表,展现效果如下图:我们可以看到应发工资自动做出了改变。 这时,我们修改工资列里的任一数值,可以看到应发工资都会自动做出改变。点击提交按钮后,自动计算的数据也会保存入库。 这就是一个简单的自动计算的小例子,其中用到的自动计算表达式遵循 Excel 风格,并且允许跨页计算。为了方便使用自动计算,润乾报表中还提供了 sum(汇总)、average(平均值)、count(计数)和 sumproduct(单元格数组乘积之和)等聚合函数。 例如,汇总运算 sum(C),对扩展格中的扩展数据进行汇总。继续以上面的行式填报为例,对应发工资做一个汇总统计: 预览结果为: 对于网格式报表扩展格的汇总可以使用表达式 sum({C}),对于非扩展区域的汇总可以使用 sum(H5:I5)。 再比如单元格数组乘积之和,sumproduct(cell1,cell2),是求 cell1 与 cell2 两个单元格中数组的同位单元格乘积之和。对于非行式报表,可以写成 sumproduct({A3},{B3}),对于行式报表可以写成 sumproduct(A3,B3)。这个计算要求两个数组的成员个数一样。 这些函数的具体用法我们就不再做详细的示例了,包括在自动计算里面也支持三目运算的写法。有兴趣的小伙伴们赶紧动手实际操练起来吧 ~ 填报表 JavaScript 函数说明链接:http://doc.raqsoft.com.cn/report/preference/tbbjshs.html 小提示: 1、自动计算的结果想要保存入库,在数据库表里面必须有对应的字段,我们的应发工资在员工表里面有对应的字段,所以可以保存入库,但是应发工资小计,没有对应的字段,所以即使提交也不能保存入库。2、自动计算的数值格不可填写或修改。 作者:Spoiled链接:http://c.raqsoft.com.cn/article/1543550151602?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在对报表数据进行打印时,经常会要求进行精确打印,比如一张纸能打印 20 行数据,如果超过就分页,如果不满 20 行,则在数据下方进行补够空行。这种情况最常见于银行对账信息等明细数据的打印。同时,在某些业务中还会按照一些字段分组,比如地区、类别等,在报表展示或打印时则要求先按照字段进行分组,将分组字段相同的数据放到一组内进行明细数据的打印,并在组内要求实现补空行操作。另外,对于分组数据,打印时所显示的页码要求是组内页码,比如报表总共 10 页,某一组分三页,则该组内页码应该显示为“第 1 页 / 共 3 页”。当然,最常见的每页打印表头也一定是需要的。 总结起来,其实是四点: 一:每页的表头; 二:报表分组后,每组的表头以及布局; 三:要求每组内数据补足空行,打印时每页都占满整张纸张; 四:组内页码。 下面是一个实际例子的效果图: 熟悉报表工具的同学都知道,报表中可以设置表头、分组表头,这样前两点就 OK 了。然后,我们可以算出数据条数用 to 函数进行补空行,第三点也满足了。但是,第四点,组内页码却无法实现,报表内置的 pno() 等函数都是相对于整张报表的,无法确定到组内是第几页,所以 pass,只能换种方式实现:“人为分页”。何为“人为分页”?就是在报表中根据特定的方法人为的去指定分几页,每页取什么数据。 下面通过一个报表介绍一下实现的过程。先看一下数据集的结构: 报表展示时要根据 MDS_OPERATION_SEQ_ID 字段进行分组,然后取出其他字段的明细数据,经测算,在 A4 纸上打印时刨除表头信息,能够打印 19 行数据,所以打印时要求每页打印 19 行,超过数据分页,不满 19(或 19 整数倍)则补空行。 看下整个报表设计模板: 首先报表要求表头信息每页都打印,此处可以使用报表的左主格,以要求报表纵向扩展时实现跟随扩展,将 A1~A7 合并,这样 A1 单元格就是后边单元格的左主格,A1 每纵向扩展都会实现后边区域的跟随扩展,A1 单元格表达式为:=ds2.group(MDS_OPERATION_SEQ_ID;MDS_OPERATION_SEQ_ID:1),该表达式按照 MDS_OPERATION_SEQ_ID 分组。 A1 单元格按照字段分组后,组内数据可能是多页,所以要在 B1 单元格中再进行一次分页操作,同样 B1~B7 单元格合并,里边表达式为:=to(1,if(ds2.count()%19==0,ds2.count()/19,int(ds2.count()/19)+1)),这里用到了 to 函数来实现扩展几页,具体页数要根据分组后数据条数来确定,之前说过每页能显示 19 行,所以表达式中是根据 19 进行了判断,如果表达式 ds2.count()%19==0 成立,表示数据量是 19 的整数倍,所以此时该组分 ds2.count()/19 页,否则分 int(ds2.count()/19)+1) 页,int 函数为取整操作,这样 B1 单元格实现组内页数的扩展。 页数取出后,接下来要进行数据行的操作,在 C6 单元格中写入表达式:=to((B1-1)19+1,B119),该单元格同样用到 to 函数实现数据扩展,用来根据 B1 单元格(页数)里构造一个纵向的扩展区域,如果 B1 中分了两页,则 C6 会扩展出两片区域 119,2038,这样 C6 这就能构造出 19 的整数倍行(视页数定),也就实现了补空行的操作。 通过 A、B、C 三列现在实现了按字段分组、获取页数并且根据行扩展构造出了整个展示的轮廓,下面看下怎么将数据和之前模拟扩展的行关联上,在 D6 单元格中写入表达式:=ds2.select(#0)(C6),#0 是报表在数据集前默认保留了一个序号列,=ds2.select(#0)可以理解成是一个数组然后后边的 (C6) 是根据 C6 取数组中的第几个值,这样,就能将 ds2 数据集和扩展行关联上,在实际中有可能该组只有一条记录,也就是 =ds2.select(#0)是 1 条, (C6)是对数组操作,所以会报错,修改 D6 表达式为:=if(ds2.count()<=1,ds2.#0,ds2.select(#0)(C6)),先根据条数判断下,再决定返回什么表达式。 这样前四列结果如下: 在 D 列中取出了 ds2 数据集中的 #0,在 E6 单元格中写入表达式:=ds2.select(ID,#0==D6),根据#0 列做为条件取出对应的 ID 字段,后边其他列就是常规的网格式报表的制作,直接用数据集. 字段名即可。 上面实现了分组报表的表头每页可见、数据补空行操作,接下来看下怎么实现组内页码的操作,之前说过,在 B 列中根据数据条数能够获取该组内一共分了几页并进行 to 的纵向扩展,组内页码可以直接获取 B1 单元格的值就是组内的第几页,在 L3 单元格中写入:=“第”+B1+“页 / 共”+count(B1[A1]{})+“页”,此处获取总页数时,要获取该组内一共几页,表达式为 count(B1[A1]{}),此处用了润乾报表特有的“位移坐标”概念(位移坐标具体用法见《报表高级设计》),取该组(A1)内扩展出的 B1 的数量。这样,就实现了组内页码的需求。 最后,将 A~E 列隐藏,将 C7 单元格的行后分页属性选中以实现强制分页,最后再按照实际要求设置报表样式,这样就实现了报表分组时组内页码及补空行的操作。最终效果如下: 由本例可以看到,不管用户需求千变万化,除了使用在报表工具中自带的一些分页方式外,我们还可以自己在报表中根据用户需求做更加灵活的设置。通过行后分页属性,可以在指定位置进行分页,根据 select 的集合属性,可以取集合中的某个值,从而实现数据集和人为定义出的扩展数据之间的结合。 扩展: 此例中通过 B1 的 to 函数模拟出了组内分了几页,所以在表中同样可以实现分组后的页内小计和组内合计,直接用 sum(单元格 {}) 即可。 作者:gxy链接:http://c.raqsoft.com.cn/article/1543409366793?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
润乾报表中支持用户通过参数对数据过滤,而当多个条件联合查询时,如果某个条件没有输入值,用户会希望该条件失效,也就是条件为空则视为没有这个条件,取出所有满足其它条件的数据。 例如,按照地区查询,参数值输入东北,则报表展示如下: 如该参数为空,则结果如下: 下面通过一个订单信息表来看下该需求的实现过程。 首先在报表设计器中制作一个网格式报表,如图: 并在该报表的基础上增加两个参数用于数据过滤: area:用于接收参数对地区进行过滤 amount:接收参数对订单金额过滤 接下来更改数据集,增加参数过滤,如图: 在 sql 语句中,条件写法为:(货主地区 =? or ? is null),在对应的参数表达式中写上两个相同的参数名(area),表示如果 area 参数有值,则用货主地区 =area 条件过滤数据,否则执行 or 参数 is null,这样参数为空时后边条件成立,取出所有数据。 注意: 1、 参数表达式中内容和 sql 语句中的问号要一一对应,此处可以写重复名称。 2、 如果有多个条件过滤数据,则用括号将每组条件括起来。 通过上述操作,可以实现用户的需求。在实际使用中,用户希望货主地区能够传递多个地区,一次查询出多个地区数据,比如要同时查询华北和东北地区数据,对于此种方式,需要将对应参数类型更改为数组方式,并且更改 sql 语句中的条件写法。 将 area 参数类型更改成字符串组,并更改 sql 语句中语法为: 如多选方式,sql 中要用 in (?) 方式。 现在预览报表,如果 area 参数为空,则取出所有地区数据,如下图: 但是当 area 参数多选时会报错,如下图: 主要原因:如参数类型是数组方式,参数值是多个时,sql 中的问号会自动根据值的个数解析出多个,这样 or 后边多个问号会出现语法错误。 解决办法:将 or 后对应的参数用 string 函数强制转换成字符串格式即可,如: 再次预览报表即能取出正确结果。 注意: 一:当数据为 db2 时,使用 or ? is null 会出错,此时需要更改 sql 语句为 cast(? as varchar(10)) is null) 把这个 varchar 改成数据库中的类型即可, 需要对参数进行类型转换 。 二:当参数类型为数组形式,按照上边做法使用 string()函数转换时,有可能数组值太多导致 sql 报错,此时可改成:where ( 货主地区 in (?) or ? =’!EOF’),在参数表达式中写入 if(@area==” OR @area==null ,’!EOF’),此种做法是如果参数为空则给对应的问号处返回!EOF,这样就取出所有数据了,同理,DB2 问题也可以用此种方式实现。 可以看到,数据集的参数表达式处不仅能够直接写参数,而且还可以写润乾的函数对参数值先行处理,将处理后的结果再传递到 sql 中进行过滤。回顾一下,我们首先解决的了单一参数值为空时,忽略该条件的问题;然后通过数组类型解决了参数中同时传递多个值的问题;最后通过分析,利用润乾报表可以在参数表达式中写函数的方式,彻底解决了传递多个参数值可能会遇到的问题。 作者:gxy链接:http://c.raqsoft.com.cn/article/1543386793666?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在各种产品直销系统中,随时可能更新产品信息,例如将过时产品信息下架、新开发产品上新、根据不同节假日修改产品价格,等等等等。传统的做法中,如果没有面向业务人员的专门维护界面,或者数据修改的策略常常发生变化,业务人员就只能求助开发人员,让他们去数据库中执行查询或更新 sql 语句来实现产品信息的维护,这样既不能保证产品信息的实时性,也增加了不必要的工作量。 那怎么办呢?不用担心,因为润乾报表来了,这就来教你如何一招搞定数据表的实时维护。 下面我们就以 demo 数据库中的产品表为例,看看如何对产品信息进行增删改的维护操作。 工具:润乾报表 第一步:数据源准备 首先,打开润乾报表设计器,点击【本地应用】-【启动示例数据库】,启动系统自带的 demo 示例数据库服务。 然后,依次点击菜单栏中的工具–数据源,在弹出的对话框中,选中 demo 数据库,并点击右侧的“连接”按钮,当 demo 显示为粉色时,表示已成功连接。 第二步:利用向导制作行式填报表 依次点击菜单栏中的“文件”—“新建行式填报”,在弹出的对话框中选择自己需要更新的物理表以及字段,并勾选主键字段,设置完成后点击确定: 我们会看到会自动绘制成了一个新的行式填报表: 第三步:美化报表,优化信息录入方式 首先,点击根格(A 和 1 交叉上方的格子),然后选择边框类型,为报表添加边框 然后,修改 A1 单元格的内容为:产品 ID,并设置 A2 的字段名称为:产品. 产品 ID 同时,设置 D2 单元格的显示格式为货币:¥#0.00 最后,我们为 C2 单元格设置下编辑风格,便于用户的录入: 右击 C2 单元格,点击“编辑风格”,在弹出来的对话框中选择“下拉列表框”风格,并增加对应代码值和显示值 第四步:测试增删改操作 通过如下 URL 访问填报表:http://localhost:6868/demo/reportJsp/showInput.jsp?sht=/hangshi.sht 结果页面如上图所示,我们可以通过工具栏中的按钮实现数据的增删改操作,点击提交后,就可以将修改后的数据更新入库了。下面的动图就演示了这个过程: 至此,我们已制作完成了数据增删改的行式填报表,业务人员可以随时访问此填报表进行产品信息的实时维护了。 学会此招式,从此数据维护不求人,赶快来和润乾报表一起制作自己的第一个行式填报表吧。 作者:xiaohuihui链接:http://c.raqsoft.com.cn/article/1543283745266?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在各式各样的报表业务需求中,有这样一类,不仅要对数据进行统计呈现,还要基于这些数据做增、删、改的操作并与数据库进行交互。这种情况下,无论从数据库统一管理还是数据合法性角度考虑,都难免需要进行诸如自动计算、校验、跨表取数之类的计算。今天,小编就带领大家 get 其中的一个新姿势:自动计算特殊用法之“流水号”。 场景举栗如下: 实际项目应用中,当多用户并发填报时我们常常会遇到主键重复的问题,造成的结果便是前一个用户填报的内容,会被另一个用户给覆盖掉,从而造成数据丢失。如果由开发人员通过编程来解决这个问题,一般都是比较麻烦的事情。而如果交由数据库去处理,就变得简单多了,因为不管多少个用户,对数据库来说只是一个更新数据库的命令队列,数据库本身会对主键的问题进行判断。这也就是大多数数据库能够提供字段自动增长功能的原因。 不过选对了报表工具,我们也可以不依赖数据库就轻松生成流水号,避免因为主键重复造成数据丢失。下面我们就以润乾报表为例,看一下具体的做法: 方法一:序号格 报表设计界面如下图所示: 其中, 数据处理部分选择【多源 SQL】然后【使用向导生成脚本】,“数据来源”设置如下: “数据去向”指定编号字段作为主键,如下图所示: 保存对象的旧数据,提取前两步设置的对象名供报表取数回填使用。 报表设计方面 第 2 行标题名均与数据库字段名称一致; A3 单元格,设置字段名称为 employee. 编号; I3 单元格,表达式为 =H3*1.2, 实现自动计算; A3-I4 单元格类型为数值格。 要求新增行时,编号自动增长,最终效果如下图所示 重点来了,实现方法只需选中 A3 单元格,勾选右侧属性【类型】–【序号格】即可。 【注】此方法采用数据全查询且按照间隔为 1 的递增规则,也就是在当前值的基础上进行递增计算,然后把每一次计算出的新值作为当前值。 方法二:UUID 算法 首先,在报表展现的 jsp(如:previewInput.jsp) 页面中定义 js 方法如下: function newUUID() { var uuid = ""; for (var i = 1; i <= 16; i++){ var n = Math.floor(Math.random()*16.0).toString(16); uuid += n; } var len = uuid.length; return uuid; } 然后,修改方法一中的报表,不要勾选【序号格】,然后将【缺省值表达式】设置为 newUUID(),调用自定义的 UUID 算法。如下图 最终页面上新增行展现效果如下,生成 16 位的字符串。 【注】此方法将按照一定规则随机产生主键,由数字、字符串等组成的 16 位字符串。 通过以上 2 种方法,我们在报表端就可以轻轻松松搞定主键自增长,永久避免因主键冲突导致数据丢失的事情。 最最后,我们来回顾一下其中的技术要点: 生成间隔为 1 的连续递增数值做主键: 【技能】报表设计区域右侧属性栏–类型–序号格 勾选即可。 生成由数字,字母组成的 16 位随机字符串做主键: 【技能】巧妙运用 UUID 方法 +【缺省值表达式】。 作者:IBelieve链接:http://c.raqsoft.com.cn/article/1542937624221?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需求说明 在报表对数据进行汇总统计时,通常是按照某个字段进行分组,比如按地区、类别等字段分组后对其他信息进行汇总,但有一种分组模式为不规则分组,其分组是根据数据的值段来分的,例如按照分数段、年龄段、按时间段等,属于某个值区间的记录归到一个组里如下图所示: 在上图中我们可以看到,报表根据订购日期将订单数量和订单金额分成四组,分别统计 "2012 年圣诞前"、“2012 年圣诞–2013 年国庆”、“2013 年国庆–2014 年五一”、"2014 年五一以后" 四个时间段的订单。 这种按值段进行分组的分组报表被称为按段分组,下面我们介绍一下润乾报表中如何实现该报表。 定义数据集 ds1:SELECT 订单. 订购日期, 订单明细. 数量, 订单明细. 单价, 订单明细. 折扣, 客户. 地区 FROM 订单明细, 订单, 客户 WHERE 客户. 客户 ID = 订单. 客户 ID AND 订单. 订单 ID = 订单明细. 订单 增加参数 报表中按时间段进行分组,实际应用中时间段通常是动态变化的,动态变化的时间段可以通过参数动态控制,所以此处增加参数进行控制: 参数名:arg1,数据类型:日期组,值表达式:2012 -12 -25, 2013 -10 -1, 2014 -5-1 参数名:arg2,数据类型:字符串组,值表达式:2012 年圣诞前, 2012 年圣诞–2013 年国庆, 2013 年国庆–2014 年五一, 2014 年五一以后 arg1 参数用于控制按段分组时的日期段,arg2 用于设置报表展示时单元格的显示信息,稍后做详细介绍 制作报表 报表设计模板如图: A3:=ds1.group(地区; 地区:1),按照地区进行分组 B3:=ds1.count(),进行计数操作,统计订单数量 C3:=ds1.sum( 单价数量 ),对订单金额汇总,注意,数据库中并没有订单金额字段,订单金额可通过单价数量计算出,润乾中支持 sum 前先对字段进行相应操作,并设置 C3 单元格显示格式为:¥#0.00 B1:表达式为 =ds1.plot(订购日期, arg1),此处使用数据集的 plot 函数(按段分组),第一个参数(订购日期)为要分组字段,第二个参数(arg1)为分段区间,函数主要功能是根据订购日期字段将数据集按照 arg1 参数指定的分段区间划分到不同的组内,该函数返回值为整数组,代表记录按值段分组后组的顺序,如 list(0,1,2,3) 代表第一组,第二组,第三组,第四组,具体函数说明见附注,将单元格扩展方向改成横向,此时报表预览展示效果如下: 可以看到,B1 单元格返回的是 0,1,2,3 这种整数,所以要对其设置显示值表达式以达到显示效果,这里就用到了之前定义的 arg2 参数,在 B1 单元格显示值表达式中写入:map(to(0,count(arg1)),arg2),map 函数主要用于显示值表达式映射,该函数有两个参数均为 list,由于 B1 单元格的真实值为 0,1,2 这种整数,所以 map 函数第一个参数为 0 到分段区间个数的扩展,第二个参数会按照顺序映射返回到显示值属性中,这样 B1 单元格就能按照 arg2 参数中设置好的内容进行显示。而分段区间和显示值均是通过参数传递,所以此报表的分段信息可以通过程序控制参数达到动态效果。 根据实际要求设置报表样式,最终效果如下: 附注: plot 函数说明: 根据数据值段进行分组,俗称“按段分组” 语法: datasetName.plot(valueExp,listExp{,filterExp}) 参数: valueExp 用于分组的值表达式 listExp 数据值段列表,同 valueExp 数据类型相同的数组,要求其中元素从小到大排列 filterExp 过滤表达式 返回值: 整数组,代表记录按值段分组后组的顺序,如 list(0,1,2,3) 代表第一组,第二组,第三组,第四组。因此,定义完单元格数据值表达式后还需要定义显示值表达式,比如第一组代表不及格,第二组代表及格等等 选项: @r 是否为根数据集表达式 @c 表示与元素比较时数据值段临界值只包含在第 1 个碰到的区间,相同的临界值不包含在第 2 个碰到的区间。缺省数据值段临界值只包含在第 2 个碰到的区间。 @z 表示 listExp 返回的数组按从大到小排列; 缺省为从小到大排列 示例: 例 1:ds1.plot(成绩,list(60,80,90) ,科目 ==“数学”) 返回值为 list(0,1,2,3) 对数据集 ds1 过滤出科目等于数学的记录按成绩段进行分组,60 分以下不包含 60 分、60-79,80-89,90 分及 90 分以上等四组。同时定义显示值表达式为:map(list(0,1,2,3),list(不及格, 及格, 良好, 优秀)) 例 2:ds1.plot@c(成绩,arg1) 其中 arg1 为参数,其数据类型是整数组,其值为 "60,70,80,90" 。显示值表达式为:map(to(0,count(arg1)),arg2),其中 arg2 为字符串组,其值为 {“不及格”,“及格”,“中”,“良好”,“优秀”}。 本例通过参数动态控制分组值段以及结果组的显示值。 作者:gxy链接:http://c.raqsoft.com.cn/article/1542609796494?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需求: 报表以图形方式,也就是我们常说的“图表”形式展示时,不同的用户对图形类型有不同的要求,希望能够动态切换统计图类型,例如实现柱形图、条形图、折线图等图形间的动态切换。 思路: 常见的做法是在报表中多个单元格中生成不同的统计图,然后通过参数动态隐藏行来实现图形类型切换,但此种方法需要制作大量的图形图表,工作量较大,而且大量隐藏单元格会耗用内存,在性能上也有一定影响。 当然,肯定还会有别的方式……我们在制作统计图时会发现,绝大多数统计图设置方式基本类似,只需要设置分类轴、系列即可生成统计图。而生成的统计图是通过单元格表达式中的 graph() 函数实现的,参考该函数的帮助文档发现,该函数可以传入一个整型参数来控制统计图类型,这样我们就可以通过该参数实现统计图类型间的动态切换。下面,我们具体介绍下该种方式的实现。 一:制作统计表 以订单表为例,按货主地区统计订单数量,报表设计界面如下: 二:增加统计图 A3、B3 单元格合并,并更改该行高度,在 A3 中设置统计图: 统计图类型可任选,分类轴以及系列中设置相应表达式 ,点击确定即可。这样该单元格就生成了一个柱形图。 三:动态更改类型 报表中增加一个整数型参数:type,用于控制统计图类型,默认值设成 7 表示默认图形类型是柱形图: 将 A3 单元格的值表达式更改成 graph(type) 这样预览报表给该参数传递不同的值该单元格就能展示不同的图形类型。 四:页面端控制 报表制作好后,可在页面端增加一个参数表单进行动态控制。如果用户只需要看图形,可将报表的前两行设置隐藏,然后将没用的行列删除,将报表保存为为 tu.rpx,并增加参数表单报表,设置如下: C1 单元格变量名属性设置成:type,C1 可做为下拉框供用户选择,值如下: 将报表保存为 tu_arg.rpx,在浏览器端访问 tu.rpx,更改参数点击查询即可,如选择折线图: 选择柱形图: 附:各图形类型对照关系: 1:区域图 2:条形图 3:三维条形图 4:三维簇状条形图 5:堆积条形图 6:三维堆积条形图 7:柱形图 8:三维柱形图 9:三维簇状柱形图 10:堆积柱形图 11:三维堆积柱形图 12:折线图 13:饼型图 14:散列图 15:三维区域图 16:三维折线图 17:三维饼型图 18:时序状态图 19:时间走势图 20:双轴折线图 21:双轴柱线图 22:雷达图 23:甘特图 24:仪表盘 25:里程碑 作者:gxy链接:http://c.raqsoft.com.cn/article/1542008169051?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需求场景 在用户录入完数据后,如果能确保数据正确,可以在页面端点击锁定按钮,从而将数据锁定,以便防止误操作对数据产生影响,并且限定锁定状态的数据才是有效数据,在查询统计时只需要统计有效数据。 解决方案 针对这个需求,我们可以在数据表中增加一个标志字段,通过该标志字段的状态来确定数据是否处于“锁定”状态。 下面是具体的实现步骤: 一:在数据表中增加字段:flag FLAG 字段为 0 时表示数据为暂存数据,为 1 是表示是锁定数据 二:根据需求制作订单明细表,表样如下图: A3 单元格类型为维度格,表达式为 =dd.(DDID), 字段名称设置为:dd.DDID B3~E3 单元格类型为数值格,字段名称分别设置数据表中对应的名称。 数据处理中使用多源 SQL,数据来源为: 接下来就看一下如何通过增加标志位字段进行数据控制。 在报表后追加一数据列(F 列),将 F3 单元格设置成数值格,并在字段名称属性处设置“FLAG”,这样就能在 F3 单元格取出状态位,其余单元格可根据 F3 的值进行是否可写控制,值为 1 时为锁定状态。 在 B3~E3 单元格的是否可编辑表达式中写入表达式:F3!=“1”, 这样当 F3 单元格的值不为 1(非状态锁定)时,这些单元格可编辑。 现在报表展现时就能够根据状态位的值来控制数据是否可被修改了。接下来再看一下,如何控制状态位的标志值。 用户操作时是在页面端点击锁定按钮,所以可以在点击该按钮时先更改报表中的状态位,然后再执行数据保存操作,而更改状态位的值可以通过 javascript 脚本更改报表单元格 (F2) 的值来实现。 接下来看下 F2 单元格设置,如图: F2 单元格既要接受 js 控制,又要将值回写到数据库表中。在通过多源 SQL 回写数据时,需要设置表达式,这里将 F2 单元格类型设置成数值型,字段名称中写入:a.TYPE,表示 F2 单元格放入对象 a 中,名字为 TYPE,并且该单元格要读取数据表中的初始值,所以单元格中写入 =F3。然后在数据处理的数据去向中设置如下: 也就是说,保存时会将 a.TYPE 的值保存到 FLAG 字段中。这里对通过 string() 函数把 a.TYPE 转换成字符串,这样就可以将 F2 单元格的值保存到数据库表的对应状态位中。F 列为控制状态列,设置完成后将列宽设成 0 即可。 接下来看一下如何动态更改 F2 的值。 1、 在填报表工具条中增加锁定按钮。 填报表工具条是在 showInput.jsp 中引入的:inputtoolbar.jsp,用文本编辑器打开,在里边增加一个按钮: 锁定 注:按钮样式可自行设置,此处用简单的文本。 2、 在 showInput.jsp 中增加 js 函数 function save(arg1){ document.getElementById(arg1+“0_F”+2).setAttribute(“value”,“1”); _inputSubmit(arg1);// 保存报表 } 该 js 函数控制,如果页面端点击锁定按钮后,将 F2 单元格的值设成 1,然后再执行保存报表操作,从而能够将标志位保存到数据库中。 页面如下: 再将 F 列隐藏掉即可(列宽设成 0) 这样,我们就实现了点击“锁定”按钮将数据锁定以防在页面端再次修改。 如需要在查询统计时只针对锁定的有效数据,那么只需要在 where 条件中增加 FLAG=’1’就行了。 需求扩展 有了标志位的使用,在实际中可以做更复杂的控制,比如将填报嵌入业务流程中,实现数据的审核,回退,入库等操作,后续文章我们会做详细的介绍。 作者:gxy链接:http://c.raqsoft.com.cn/article/1542007656738?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需求描述: 用户在页面端修改数据时为保证数据的可追溯性,可以在数据表中增加修改人字段,用于保存修改人的信息,追溯数据的有效性。下面就介绍一下如何实现这个需求。 解决方案 一:填报表制作 按照用户的需求制作填报表,如“订单信息表”: 1、 新建填报表,新增参数:userid,用于接收系统传进来的用户信息。 2、 在“数据处理”对话框中中把“数据来源”设置为使用“脚本”方式,如图: 3、 在“数据处理”对话框中把“数据去向”也设置为使用“脚本”,如图: 注意:B2 中 EDITUSER 字段为数据库中的修改人字段,将其赋值为 userid,表示更新时将参数 userid 的值保存到对应字段中。 4、 制作填报表,如下图: A3 设置单元格类型为维度格,表达式为 =dd.(DDID),dd 为数据来源中定义的数据对象名称,此单元格取表中 DDID 的值,字段名称中设置 dd.DDID。 B3~E3 单元格类型设置成数值格,用于填写信息,按照填报表取字段名称规则,B3 单元格默认取其上方单元格为字段名称,由于数据库中存储的是英文字段名“KHID”,和 B2 中的“客户编号”不一致,所以为取出正确数据,在 B3 单元格的字段名称中设置“KHID”,指定单元格字段名称,其余类似。 按照客户样式要求调整报表样式,并保存报表即可。 5、 发布报表并设置参数传递 在浏览器中访问该报表,并且在 url 中将用户编号传递给参数 userid,如:http://localhost:6868/demo/reportJsp/showInput.jsp?sht=ddxx.sht&userid=zhangsan 参数可以在 url 中传递,为保证其安全性,用户信息可能存在 session 中,那么在 showInput.jsp 中获取 session 中的用户信息,并传递给报表标签的 params 标签即可,传递格式:参数名称 = 参数值。 报表展现后,格式如下: 页面端修改数据保存后,去数据库端查看数据发现,EDITUSER 字段数据为传入的用户信息,如下图: 发现问题 实际使用中发现,用户可能只修改了某几条记录,但是数据库中的 EDITUSER 字段的所有数据都会发生变化,而用户需求肯定是只更改该用户修改的数据。 问题原因及解决办法: 前面更新数据采用的是集算脚本中的 update 函数,该函数处理时会根据新旧对象数据进行判断,从而判定处理时是 update、insert 还是 delete 操作。因此解决办法就是在新旧对象中删除没有修改的数据即可,下面是更改后的数据去向脚本: B1 中通过 join 函数将两个对象关联在一起,此时关联字段是对象中的所有字段,这样可以找到没有修改的数据。 C1 中取出两个对象中所有数据相同 (没有修改的) 的主键字段 A2、B2 中分别从两个对象中根据 C1 的值过滤出没有修改的数据 A3、B3 删除没有修改的数据,这样两个对象中的数据均为用户页面端修改后的数据,再执行 update 操作即可。数据库中数据如下: 可见,只有页面端修改的数据 EDITUSER 字段的值会发生变化,其余不变,这样就可以定位到具体哪些数据被哪些人做了修改。 总结: 本例中通过在脚本中对填报对象的数据进行修改,做到了在相应数据表中更新最后修改人字段,并且能精确到他修改的数据。实际应用中也可以增加最后修改时间等,或者在脚本中做更复杂的业务处理。 作者:gxy链接:http://c.raqsoft.com.cn/article/1540825011256?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
数据一般都具有天然的时间属性,在很多业务中,以自然月为周期进行数据统计、分析和展示非常普遍。例如,在人事系统中查看某个月的考勤信息、销售人员查看自己或者部门的日程安排等。这些情况下,将报表以日历形式进行展示,往往具有更加直观的展示效果。 下面,我们将通过一个常见的考勤报表的制作,说明如何制作这些日历形式的报表。先看一下报表应有的展示效果: 该报表以日历形式清晰、直观地展示了 3 月份的人员出勤情况。下面介绍下该报表的制作方法。 在润乾报表中,制作日历类报表主要的操作是通过 to 函数实现一个交叉报表扩展出对应的行列,然后在想办法找到该月第一天是周几,这样后边的日期就能依次获取,至于日历最终用于考勤还是其他业务,只需要将实际业务中的日期字段和日历中的日期对应即可,下面看下详细的操作步骤。 一、日历格式制作 实际应用中需要动态传入月份,从而实现动态日历的设置,因此先在报表中增加一个参数 rq,值表达式默认为 2018-03 在一个自然月中,日期最多会跨六周,因此只需在单元格 A2 输入 =to(0,5),B1 单元格输入 =to(1,7),并且将 B1 单元格的扩展方向设置成横向扩展,然后将 A 列隐藏。 这样报表展现时就会纵向扩展出 6 行,横向扩展出 7 列。 在 B2 单元格表达式中写入 =A2*7+B1, 此时报表预览结果如下: 大家知道,每个月的第一天有可能是一周中的任何一天,以 2018-03-01 为例,该日为周四,所以日历展示时,1 号要展示在周四处,也就是上图红框中的“5”的位置(国际日历中,第一列为周日),简单来看就是将上图中的日期 -4 即可,接下来看下这个 4 是怎么动态获取的。 润乾函数中有个时间日期函数 day,通过该函数可以获取某个日期在该月中是几号,使用时可以增加 w 参数,即 day@w,可以获取某个日期是一个星期中的第几天,先用 rq+”-01”字符串拼接成一个日期格式字符串,再用 date 函数对其进行日期格式转换 date(rq+“-01”),这样 day@w(date(rq+“-01”)) 就能够获取该月 1 号是一个星期中的第几天,因为是国际日历,如果是周日则返回 1,周一则返回 2,所以如果是周四的话,day@w(date(rq+“-01”)) 返回的值是 5,要取得想要的 4 则在该值的基础上减 1 即可。 还有一种可能,如果 1 号恰好是周日的话,之前纵向扩展时是 0 到 5 扩展出了 6 行,日历中通常 1 号为周日的话是放在日历的第二行,所以要进行 1 号是否是周日的判断,如果是则在第二行显示(值 -7),最终 B2 单元格表达式为: =A2*7+B1-if(day@w(date(rq+“-01”))==1,7,day@w(date(rq+“-01”))-1) 也就是在原有生成连续日期的基础上减去当月第一天处于该周中第几天,预览结果如下: 可以看到 1 号目前显示在了周四的位置。 ps:day@w 函数返回日期所在该周的第几天,周日返回 1. 做为日历,第一行展示时要显示成中文,并且是从周日开始显示,在 B1 单元格显示值表达式写入:map(to(1,7),list(“星期日”,“星期一”,“星期二”,“星期三”,“星期四”,“星期五”,“星期六”)) 另外,由于交叉区域扩展出来 6*7(42)个单元格,而一个月为 30 天左右,所以会有负数(上个月)以及大于当前月最大值的数。这些值在展示时是不需要的,可以通过表达式将不需要数据隐藏掉,在 B2 单元格显示值表达式中写入:if(value()<1||value()>days((date(rq+“-01”))),"",value()) A2 中扩展出 6 行数据,实际中该月可能会横跨四周到 5 周,所以同样要将不需要数据给隐藏掉,判断规则: 如果在第五行第一天的日期超过了该月天数,那么其他几天肯定也超过最大天数了,这行数据就需要隐藏,或者如果日期在扩展的第一行中,并且该行最后那天日期 <1 的话,那么该行也需要隐藏,所以在 B2 单元格隐藏行表达式中写入:if(A2>=4 and B1==1 and value()>days((date(rq+“-01”))),true,if(A2==0 and B1==7 and value()<1,true,false)) 这样报表就展示成如下日历格式: 二、考勤数据如何结合日历报表 接下来看一下考勤数据如何放到日历中显示。 考勤数据通常会有两个字段,一个为考勤日期,另一个为出勤情况,如下述数据集: 数据集中有两列数据,rq 为考核日期,sfcq:是否出勤,1:出勤,0:缺勤 在上述制作好的报表基础上将 A2 和 A3 单元格合并,在 B3 单元格中输入表达式:=ds1.select(sfcq,day(rq)==B2) B2 单元格为日历的天,day(rq) 含义取 rq 字段的日,这样将这个做为过滤条件就能从 ds1 数据集中取出该天的出勤情况。 展示时要展示成中文,在 B3 单元格显示值表达式中写入:if(value()==“1”,“出勤”,if(B1==1 or B1==7,"",“缺勤”)),当数据库中字段的值为 1 时代表出勤,并且当 B1 等于 1 或者 7 时,表示周末,不参与考勤评定,其余日期为空的同样算缺勤。 再调整边框样式,主要 B2、B3 单元格展示时,要将日期和出勤情况展示成一个单元格内,所以 B2 和 B3 单元格中间的边框设成不显示。 报表展现时,为了更加醒目的显示哪些日期没有出勤,可以设置成如果缺勤则字体变成橙色展示,在 B3 单元格的前景色表达式中写入:if(value()!=“1”,-32768,-16777216),通常情况下,周末的日期以红色展示,所以在 B2 单元格前景色表达式中写入:if(B1==1 or B1==7,-65536,-16777216)。 在之前 B2 单元格隐藏行表达式中动态控制哪些行隐藏,因为报表增加了 B3 单元格,所以要在 B3 中要做同样控制,在 B3 单元格隐藏行表达式中写入: if(A2>=4 and B1==1 and B2>days((date(rq+“-01”))),true,if(A2==0 and B1==7 and B2<1,true,false))。 报表中可增加一行用于展示当前月份信息,在报表上方插入行,将 A1、B1 合并,单元格中写入表达式:=string(date(rq+“-01”),“yyyy 年 MM”)+“月份出勤统计” 剩余进行样式调整,根据实际需要设置报表前景色、背景色、边框样式等,这样考勤报表就制作完成了。 最终报表展现结果如下: 总结:本例中通过单元格扩展以及日期函数的使用,实现了报表的灵活定制,使之以日历形式展示,并且能够在日历中显示考勤等信息。实际应用中同样可显示其他信息,只需要将日期字段和日历中的日期做关联即可,并且该报表还可和其他报表或业务系统联动,比如日历中可显示技术部门每天处理的任务数,结合报表的超链接功能,点击任务数就能够跳转到任务列表中查看具体的任务信息,等等。 作者:gxy链接:http://c.raqsoft.com.cn/article/1540824028843?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Dashboard 以丰富的动态、可交互的可视化界面为用户提供了更好的数据使用体验,让决策者能够更高效的了解企业的重要信息和细节层次。在 DBD 的各种动态效果中,滚屏是较为常见的一种,例如下图中的数据列表因为布局是固定的,因此就需要滚动显示数据。 通常报表中见到的滚屏是因为“页面大、窗口小”,也就是打开的窗口区域容纳不了整个页面的内容,需要靠键盘的方向键或鼠标滚轮来移动查看。而在 DBD 中,为了更好的交互效果,需要滚动自动持续进行,只有当鼠标移到该区域时才暂停。这种方式虽说已经比较常见了,但一般来说报表厂商却并没有直接提供,而是需要通过 jquery,JS 来实现。现在我就给大家介绍一下如何实现这种文字滚屏效果。 我们将在润乾报表设计器自带的“设备故障分析.rpx”基础上实现文字滚屏实例。 数据集整理 对于从数据库读取的数据,可以通过集算器,将数据整理成下面截图中的效果。为了方便做效果,这里我直接将 ds2 这个内建数据中的所有字段的值整理到“设备”这个字段中,并且在里面加上了些空格,以便页面上缩进的效果好看些。 合并单元格 将 G15 列删除,B15—F15 选中,合并。 单元格数据类型设置为 html 设置单元格表达式,如上图所示。下面是具体的表达式。 =“”+replace(string@q(ds2.select( 设备)),“,”,“”)+“” 其中: onmouseover=this.stop() 表示当鼠标以上区域的时候滚动停止; onmouseout=this.start() 表示当鼠标移开的时候继续滚动。 调整样式 原 B15-F15 设置了各行异色,因为我们的文字滚动项作为统一的一串内容,所以按照以上设置,效果感觉会有些突兀,如下图所示。 去掉 B15-F15 背景色的设置,这样滚动区域就整体浑然一体。 经过以上步骤我们的数据列表就在 DBD 面板中滚动起来了,并且当鼠标指向数据的时候就会停止滚动,鼠标移开的时候就继续滚动了,这样的交互效果无疑会为你的大屏展现锦上添花。 上面这个小例子简单实现了文字滚动显示的效果。下面我具体讲解下看似神奇的标签的各个属性值,相信看过后一定会帮助您实现更好的文字滚动效果: 另外,您也可以将 <marquee> 和 </marquee> 之间的内容替换成图像或其它对象。 怎么样,是不是您已经在摩拳擦掌跃跃欲试了?别犹豫,让我们一起来丰富 Dashboard 效果,让页面效果动起来吧! 作者:shiguang链接:http://c.raqsoft.com.cn/article/1539048212781?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在业务系统中分组统计是比较常见的数据分析形式,但当数据项较多,或分组的层级过多时看着就会比较烦乱,为了数据更清晰的展现,通常用户会需要伸缩(折叠)显示的效果,这样分类汇总的数据就可一目了然的呈现。 润乾报表内置了这种伸缩功能,提供了两种形式的折叠报表:树型折叠报表和 OLAP 型折叠报表。报表开发人员不再需要编写 JS 脚本,只需要两步,设计报表,在报表展现的 jsp 页面中加入 tag 属性,就可以将格式符合的报表以伸缩的形式展现。 下面我们来分别看下这两种形式的折叠报表在润乾中是如何实现的吧! Olap 折叠报表 olap 折叠报表格式要求:分组格与它的子格在同一行,行上必须是全包含关系。 报表设计如下: 页面标签设置: 页面展现效果: 初始收拢 节点展开效果 树形折叠报表 树形报表格式要求:分组格与它的子格不在同一行上,不能有行上的全包含或半包含关系。 报表设计如下: 报表展现页面标签设置如下: 页面初始展现效果: 全部收齐 部分节点展开 下面是关于折叠报表标签属性列表: 说明:1、树形报表对浏览器没有要求,olap 折叠表对浏览器要求 IE 类浏览器版要大于 IE9,其它类浏览器不限2、这两种展现方式互斥,只能同时用一种3、树形报表暂时只实现行向的折叠,列向未实现4、foldOnBegin 和 foldIcon 属性都适用于两种折叠报表 作者:shiguang链接:http://c.raqsoft.com.cn/article/1540280455361?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在各企业中或者电商平台的商家,业务方,每天都有大量的人需要在线查看大量的指标,用于监控、分析关键业务数据的发展趋势。同时,又有着能够随时随地,方便快捷的查看分析数据的诉求。我们习惯于,使用润乾报表在 PC 端或大屏中展现,但是你知道吗?润乾报表 V2018 是以 HTML5 方式输出,不仅支持在 PC 端展现,也支持在手机端展现,并且在手机端展现时可以在手机端自适应。 手机报表已有功能 目前我们提供的手机报表 APP 示例的功能有:钻取、填报表、参数查询、统计图,自适应,长按电话号码拨打电话、扫码、分享报表到微信或 QQ 的功能。 注:长按电话号码拨打电话、扫码、分享的功能是在手机 APP 中有效,只有部分浏览器支持这个功能。 自适应方式 设计器安装目录 reportJsp 目录下提供了 matchReport.jsp, 在这个页面中是通过 reportMatchSize 这个自适应 js 函数实现的自适应功能。 js 函数用法说明如下: reportMatchSize(rongqi, reportdiv, mode) 参数说明: rongqi 页面中的 html 容器元素 (如 div,td 等),报表将按此容器的尺寸进行匹配适应。 reportdiv 报表所在的 div 对象。 mode 自适应方式,有以下 8 种取值: 0 按设计尺寸展现,不用适应容器。 1 始终用报表宽度适应容器宽度,报表高度同比例缩放 2 始终用报表高度适应容器高度,报表宽度同比例缩放 3 竖屏时,相当于 mode=2;横屏时,相当于 mode=1 4 竖屏时,相当于 mode=1;横屏时,相当于 mode=2 5 竖屏时,报表高和宽均分别适应容器的高和宽;横屏时,不需适应容器 6 竖屏时,不需适应容器;横屏时,报表高和宽均分别适应容器的高和宽 7 报表高和宽均分别适应容器的高和宽 函数功能:让 reportdiv 按照实际尺寸以指定的适应方式与容器 rongqi 的尺寸相匹配适应 说明:自适应功能不适合用于固定表头的报表和折叠报表,也可以在自己写的报表展现页面中添加 reportMatchSize 这个 js 方法实现自适应功能。 实例 设计器下 reportFiles 目录下的 mobile 目录中有一张名为 phone_1.rpx,该报表如果想在手机端按高宽自适应的话,调用该报表的 url 应该为:http://192.168.0.229:6868/demo/reportJsp/matchReport.jsp?rpx=/mobile/phone_1.rpx&match=7,其中 match=7。 下面是该报表在手机端浏览器显示的效果: 设计器下 reportFiles 目录下的 mobile 目录中有一张名为 match.rpx,该报表如果想在手机端竖屏的时候按高自适应,横屏的时候按宽自适应的话,调用该报表的 url 应该为:http://192.168.0.229:6868/demo/reportJsp/matchReport.jsp?rpx=/mobile/match.rpx&match=3,其中 match=3。 下面是该报表在手机端浏览器显示的效果: 关于手机客户端 APP 说明 一般有手机报表需求的客户,都有自己的 APP,所以润乾提供的 APP 也只是让客户能快速了解润乾报表手机端展现的效果而已,不作为最终提供给客户使用的手机客户端程序。 润乾报表手机端演示的 APP 下载地址: 链接:https://pan.baidu.com/s/1z59YfHQULJKjJwrU8_1fGg 密码:l7r5 注:该 APP 安装后默认访问的是润乾官网的手机报表http://report5.raqsoft.com.cn/mobile, 如果需要使用该客户端访问自己的手机报表需要在手机中的 raqsoft 目录中添加 url.cfg 文件,该文件中内容就是要访问的手机报表的 url(如:http://192.168.0.56:6868/demo/mobile/index.jsp) 移动端展现数据的报表特点 简单数据(避繁就简) 如 iphone 自带应用健康中,提供的统计数据,我们可以选择相应的日期,就能显示出该日期的 3 个指标数据。 从汇总到明细,有层次结构(钻取) 数字与图表联动 在上方点击对应的月份,下方就会以统计数据的列表和图表将信息显示。 看了以上在移动端展现的报表形式,我们不难发现由于移动端的屏幕空间有限,统计图,列表的布局多是上下的,我们在报表设计器下设计的 PC 端展现的报表布局是固定的,不是那种流式布局的,所以,我们要在手机端展现和 PC 端同类的数据时还要制作出对应更适合移动端的报表才好,否则直接拿一个很宽很大的报表让报表在手机端横屏自适应,展现的也不尽如人意的 作者:shiguang链接:http://c.raqsoft.com.cn/article/1539050767973?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
润乾报表多维分析功能漫游 是不是还在为成千上万的数据处理不完而苦恼? 是不是一想到要处理这些数据就头大? 今天又要为整理这些枯燥的数据加班怎么办? ——不要担心!不要担心!润乾来拯救你!DQL分组分析的神秘力量会协助你顺利完成数据的操作与分析,加班?不存在的!隔壁组的老王和老李都羡慕哭了。 分析控件功能 拖拽字段 首先从分析控件本身的功能入手——打开分析页面第一件事是做什么呢?对啦,当然是要展示报表了~脱离敲打复杂的查询语句,只需要动动鼠标就可以获取所需要的数据。第一步就是要将所需要的字段拖拽到指标数据区。 这里是第一个例子: 上图的报表内容为入库单中商品类别及其入库数量的数据展示。 汇总 每个类型的商品出现了很多次,没有被汇总起来,这样看起来不方便。我们将商品类别拖拽到左表头的位置。 点击指标数据区中“入库数量计数”字段旁边的三角,将“计数”改为“求和”。我们这里的求和操作,相当于SQL中的SUM关键字。 这样看来,左侧报表显示的数据就是不同商品类别下入库数量的总计。 那么如果想要继续在报表中添加显示各个类别下有多少种商品,就可以把“商品”字段拖拽到指定数据区,并且字段类型改为“计数”就可以了~~~这里的计数相当于SQL中的COUNT关键字。 钻取 得到了关于入库商品明细汇总的报表,对于报表中的汇总值,我们想看看其中某个汇总值是哪些明细数据汇总出来的,这就需要用到钻取功能。 点击商品类别为“饮料”的入库数量求和数据,展示的钻取报表显示的数据就是饮料类别下各商品的入库数量。 这样,饮料类别下每个商品的入库数量就展现在我们眼前了,是不是很方便呢? 多层报表 在汇总功能下,我们使用的报表还是很简单滴,那么如果我们有更多更复杂的数据需要展示该如何是好?不要慌张!下面我们来介绍多层报表—— 让我们来一起完成第二个例子:报表中需要展示每个上级所管理的经办人中,每人每月的入库量统计。很简单——我们将“上级”、“经办人”拖拽到上表头,“年”、“月”拖拽到左表头,而中间数据区要展示“入库数量求和”,这样一个多层表格就可以展示出来了。 行列互换 老板又提出特殊要求了!——要让“年”、“月”展示在报表的上方,“上级”和“经办人”展示在左边,也就是说行列需要互换一下。这种小问题怎么会难倒我呢~我们需要通过拖拽字段,也就是将左表头和上表头互换,来实现行列的互换。 此时展示的就是行列互换之后的报表样式。 以上就是分析控件一些本身的常用功能,无非就是对字段进行拖拽,显示数据,然后算一算总和。那么如果老板提出更更更难的条件怎么办?我们就不得不来继续研究特殊复杂条件的设置了。 特殊复杂条件 设置过滤条件 一口吃不成个胖子,我们先来学习一下设置简单的过滤条件——这里用到例子中行列互换前的报表。 如果我们要取2010年的全部数据,那么需要进行如下操作:点击“年”→“数据过滤”,设置过滤条件。 或者可以在数据分析设计器中选择“复杂条件”来设置查询条件。 在“年”后的下拉列表中,选中“等于”,并且在输入框中输入“2010”,点击保存; 当然,在过滤数据的过程中,我们还可以根据其它需求,在“设置查询条件”中选择不同的比较方式,如不等于、大于、小于、不为空等。 这时,报表中显示的数据就是条件过滤后的数据了。 在SQL中,过滤相对复杂,会有层层嵌套、层层查询,有时稍有不慎,多写一处括号,或是少写一个逗号,都会出错,或者使查询结果不是预期的。而我们的分析控件通过简单的图形化界面操作,就可以使数据轻轻松松展示为你想要的样子,并且所见即所得。如此贴心的设计,真是令人爱不释手啊! 切片与切块 为了更细分的查看所需数据,我们可以继续设置一些特殊复杂条件——通过编辑复杂条件,对报表中的数据进行切片或者切块,“切”出来的数据更加方便查看以及使用,并且报表展示也十分美观。 在上面的例子中,我们可以通过更细分的切片使显示的数据更为精准。我们来查看一下2010年后半年上级为王伟的各经办人入库情况。修改复杂条件设置如下图,就可以得到切片后的数据表啦! 当当当敲黑板——请注意,在设置过滤条件的时候要留意调整条件的层次,点击条件前的绿色箭头即可自由调整层级,相当于SQL语句括号,也就是最左侧的字段相当于在括号的最外层,点击右键头往右移一位相当于嵌套一层括号,所以在控制查询条件的时候要注意条件的层次哟。 接下来试一试切块——在切片后报表的基础上,我们来查看一下经办人赵军在2010年后半年的入库数量统计——我们只要在“设置查询条件”处添加经办人的筛选就可以了。 我们通过层层切片/切块,可以使报表中的数据准确细分,从而达到需求。在切片/切块的时候要注意调整条件的层次,由大到小来进行细分——就像切土豆块一样,需要先把土豆切成片、从而切成条,最后才能切成小块。所以切片/切块时一定要细心哟~ 到这里,设置特殊复杂条件也是小case了~在繁杂的数据面前不要慌张,只要捋顺好思路,按照顺序依次设置复杂条件,相信你一定可以做的更好! 跨行组计算 最后我们终于迎来了跨行组计算——常常有一些复杂的功能性计算操作,比如排名、占比、同比等,如果数据量很大,不借助报表工具的话,人工计算可能三天三夜都算不完,是不是有点小小的害怕呢?但借助于报表中的跨行组计算,我们只需要动动手指就可以完成这些数据的计算。不信?咱们来试试! 大展身手之前,我们先来设置好需要用到的报表,为了使数据更便于我们查看,还需要对数据进行一下筛选——下图报表中展示的数据为2010年和2011年两年中,上级为赵军的各经办人每月的入库数量求和。 排名 先从排名开始吧!我们首先要对报表中,每个经办人在这两年中的入库数量总和进行排名——点击绿色加号“添加分析指标”。 选中五种分析数据功能中的“排名”功能,此时页面上展示的排名算法是可以直接使用的模板,点击确定即可保存。 下图为计算排名之后的报表,在原报表的基础上,添加了一列排名,此处对每个经办人在这两年中,所有月份的入库量求和进行排名(注:会出现排名并列的现象)。 报表中计算出了两年内的排名情况,那么如果我们想看一看在同一年中,各个经办人在不同月份的入库量排名情况该如何操作呢? 在数据分析设置器中,点击“入库量排名”的下拉列表,选择“编辑”。 我们在条件输入框中输入“&& 年当前值 == 年查找值”,这里输入的条件控制了排名的范围。 作为懒星人的你抱怨道:手动输入太麻烦了!如果条件特别多岂不是要输入一大串? 嘿嘿嘿,懒星人请看这里: 这两排选项可是专为懒星人设计的哟~不想打键盘输入条件的话,就动一动鼠标,点击相应的选项,就可以拼接成你想要的控制条件了!比如“&& 年当前值 == 年查找值”,就可以通过依次点击“或者”—“年当前值”—“等于”—“年查找值”完成拼接。 下面我们来看一看,各个经办人在不同年份中的月入库量排名吧— 占比 接下来计算一下,这两年里各个经办人的月入库数量的占比是多少。 在“添加分析指标”的编辑框中选择“占比”,并且选择所要求占比的字段值,点击确定即可保存。 如果想要得到每一年里各经办人的月入库量占比,就需要设置一下查找条件表达式啦。 “当前值”是指当前入库数量求和的这一个数据,“查找值”是指符合查找条件表达式的所有数据,而这里的查找条件就是输入框中的“年当前值 == 年查找值”。 设置显示格式 占比现在显示成小数看起来实在是不习惯,还是显示成百分数才比较好。 报表中计算得到的入库数量的占比可以修改成百分比形式来显示数据。点击数据分析设计器中“入库量占比”→“显示格式”,在“设置显示格式”中选择所需要的显示格式或者手动输入显示格式,点击确定保存。 环比 环比是指本月数据与上个月的数据进行对比,比如2010年12月与2010年11月的入库量总和做比值。这里我们来继续计算一下每个经办人在这两年中,每个月份的入库量环比。 如果要在每年范围内求环比,如之前所讲,条件表达式中加上“&& 年当前值==年查找值”即可。 计算完成之后记得要修改显示格式哦。 累积 下面来介绍累积——分析指标中的“累积”功能就是将数据累积的过程显示在报表中,而每张统计报表的最下方都会显示“总计”,代表这一列数据累加到最后的总和。 查询条件“月当前序号>=月查找序号”是按照月份进行累加的 如果想要展示通过年份进行累加的报表,则需要将条件中的“月当前序号>=月查找序号”改为“年当前序号>=年查找序号”。 这里显示年的累积不是很美观呀,不用担心,再动动手指就可以解决这个问题啦。我们来修改一下分析指标—— 这时候我们就可以用到这两排绿油油的按钮来进行控制啦。 上图报表中的分析指标是基于“月”进行控制的,这里我们单击“年”按钮,使其变成的样子,保存后查看报表。 报表中的“入库量累积”字段不受“月”的控制,以“年”为分析对象进行计算。 总的来说,这部分的设置是通过取从右往左第一个被选中的按钮(按钮背景为绿色)字段作为分析对象,忽略未被选中的按钮(按钮无背景色)的字段,进行相应的跨行组计算的。 同比 同比是指本月数据与上一年同月的数据进行对比,例如2011年12月的入库量总和与2010年12月的入库量总和做比值。此处可以展示这两年中,每个经办人每一个月的入库量同比。 查找条件表达式中“月当前序号==(月查找序号+12)”定位到查找一年前(12个月)的相同月份。 这里再提出一个小小的需求:显示上级为“赵军”所负责的所有经办人的入库量同比。 在分析指标中,点击“上级”,就将控制条件修改为“上级”了。 点击保存后,报表显示如下图: 在以上五种分析指标的设置中,我们可以发现,其实每一项数据都是通过公式运算得出的,它们的不同之处在于各自使用的公式和取值字段是不一样的,而它们的相同之处在于得到数据的步骤很简单,我们不需要了解计算过程是如何复杂,只需要掌握计算公式如何使用以及各个参数代表什么,继而点击“确定”保存就可以进行跨行组计算啦~ 多维分析功能的神秘面纱现在已经揭开,但它并不只限于所讲的这些功能,它是一个很有“内容”的功能哟~如此高效率又操作简单的分析控件是否令你心动了呢?想要了解更多的话,就请跟我一起动手操作起来吧! 作者:lee869486359链接:http://c.raqsoft.com.cn/article/1535678317741?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在目前的大数据趋势中,数据的大屏可视化成为大家所推崇的一种互动展示模式。如果我们能够早一些了解和掌握这方面的技术,相信对我们的未来将会非常有帮助! 我们知道,通过报表工具实现大屏展示可以通过单张报表、多张报表 Dashboard 布局或者多张报表页面布局等方式实现,那么,如何能设计出优秀的 dashboard 呢? 下面是国外的著名的可视化专家 Stephen Few 在 2012 年举办的 Dashboard 图表设计竞赛中列出的关于优秀的 dashboard 应该具有的特征: 小编对这些特征进行了翻译以供参考,如有不准确的请指正。 根据上面的评分标准,你所做的大屏数据可视化图表及格了吗? 对于 dashboard 来说,如果需要完美的展现效果,是需要技术人员,UI 设计人员,以及业务人员协调工作完成的。而作为程序开发人员,如何在没有美工的情况下,做出能上得了台面的 dashboard 效果呢? 上面的标准说得比较概括,下面介绍一下我使用报表工具实际做 dashboard 时所考虑的具体因素: 确定使用人群 了解使用人群,有助于把握好要显示的 kpi 以及数据的逻辑分解 布局 人的阅读习惯是从做到用从上到下的,而中间位置又是最能吸引关注的,所以重要内容应该放在最上面或者中间。如下图,我们可以在这个页面顶端直接展现重要的指标信息,这种布局是目前众多以运营人员为对象的报表系统最喜欢使用的结构,整体数字指标一目了然,可以让阅读者在几秒内把握全局数据,是一种阅读报表时间投入产出比很高的方式。 背景 在不同场景下,背景色为深色(蓝,蓝绿,黑)时投放到大屏的展现效果较好。同时,为了显示的内容更加清晰,字的颜色应该反差较大,因此文字多为浅色。 另外,除了使用背景颜色外,还可以使用背景图片,加上这样的深色调图片,不止酷炫,而且科技感十足。 配色 下面是从网上搜罗到的比较常用的配色方式: 具体的 RGB 值可以通过取色软件获取,网上这样的资源有很多, QQ 软件在截屏的时候也会显示 RGB 的值,哈哈,这样 QQ 软件也能为我们取色所用了。 图形化 通过使用 Echarts.js, G3,hicharts 这样的图形化技术,可以让原来静态的柱图,线图等图表,更加生动地将数据显示在用户面前。 动态效果 完美的 Dashboard 具有的特性是用户交互性,用户交互性一般又体现在哪些效果上呢? 滚屏 联动 定时刷新显示的时间 钻取 细节美化 (1) 适当使用图标 在标题、明细列表、图表中加上图标,不仅能形象直观地体现某一区块的主题,还有很好的装饰作用。 下面是一个可供参考的图标资源网站: http://iconfont.cn/repositories/10 (2)边框线 使区块明显分隔,数据显示更清晰。 (3) 标题 标题可以使主题显得清晰,一个页面中即使区块分隔清晰、动态图表再多,但如果没有一个标题的话,那也不会是一个成功的 dbd,因为标题的缺失会降低可读性。下面就是一个没有标题的效果图。 试想一下,如果各个区块都加上标题,我们在看到这个页面时,就不会茫然的寻找是否有应该关注的数据了。 希望以上的总结,可以在布局、配色、交互等方面帮助到你,相对高效地做出能让领导满意的高大上的 dashboard,为你的职场加分,加薪!除了上面列举的方式,还可以在网上多看些大屏的图片,从模仿开始。我觉得设计这种东西,多看多积累,慢慢就会沉淀下属于自己的方式方法了。 作者:shiguang链接:http://c.raqsoft.com.cn/article/1535420833071?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
近期,大屏展示再次把 ”统计图” 推向热搜榜。或许你会问为什么,这多半是因为大屏通过各种图形组件集中呈现了用户关心的数据,而其中每个组件基本都是一个呈现形态各异的统计图,有的体现了某时间段某维度的数据走向,有的则是表示了某部分数据在整体的占比,亦或是分布聚集情况,凡此种种,不一而足。 相信资深的制表绘图师都知道,早期在报表工具还未普及时,想要实现各种统计结果的图形化呈现,基本都得通过代码或者 excel 来做,不仅开发费时费力,而且灵活性很差。 这里就以 Excel 为例,看一看具体的操作过程。假设某软件公司年中会议时要求销售主管向公司领导层汇报这半年各个产品不同维度(按产品线、按月、按销售经理等)的销售情况。 当销售主管得到这个通知后,往往需要做以下几步操作: 首先,通过各个销售经理获取每个人的销售明细数据,然后再使用 excel 透视表来完成针对这些数据的报表制作和数据分析工作,接下来再按照要求绘图。 这个过程看似简单,其实工作量非常庞大。我们细细回顾一下这个过程,可以看到从取数到制表绘图,难以避免以下这几个问题: 取数响应不够及时和灵活:一般销售人员常常奔波于全国各地,很多时候并不能及时将明细数据进行汇总整理,以至于销售主管很可能要等好几天才能拿到数据。 需求沟通存在误差:销售主管最终拿到的数据结果可能并不是最初想要的,可能由于沟通表达导致存在一定的偏差。 Excel 的局限:Excel 看似万能,但一旦数据量庞大,要写的函数多,真是挺影响效率的。而且在某些数据分析统计场景下,表现的不够丰富灵活,需要很多冗余操作。 那么有没有可能能够让销售经理能够在奔波的间隙,将销售数据及时的整理到销售部门的数据库中,然后由销售主管直接从数据库中读取数据进行数据分析、制表以及绘图,真正做到响应高效及时、制表绘图轻松愉快呢? 答案是肯定的,只要你拥有一款神器——润乾报表工具,上面所提到的或没提到的沟沟坎坎都能轻松搞定: 首先,我们可以应用该神器的填报功能,来保证销售数据的及时入库。 其次,我们还可以通过简简单单的拖拖拽拽,来完成数据的分析制表。 最后,我们还可以轻松愉快的完成绘图工作。 好了,话不多说,接下来我们直奔今天的主题,get 一下通过此神器可以做出哪些图形。 注:本文重点说明绘图部分,数据处理部分一带而过。 线图 以线条直观地呈现出某时期,不同部门 2 个产品的销售量差异。 饼图 以饼图直观地表现出某时段各个销售经理的销售额在整个部门的占比。 3.柱图 以柱子的高度用来比较两个或以上的生产值间的差异 甘特图 清楚地标识出某项目在不同时间段的完成情况。 5.地图 以地图为底本,用各种几何图形、实物形象或不同线纹、颜色等表明指标的大小及其分布状况,可以突出说明某些现象在地域上的分布、对某些现象进行不同地区间的比较,以及展示现象所处的地理位置及与其他自然条件的关系等 6.柱线图 集柱图与线图的优势于一身,下图中既可以以柱图的形式表现出同一时间蒸发量与降水量的差异,又可以以平滑的曲线呈现出一年的气温变化。 等等。 怎么样,是不是瞬间感觉在老板面前能加分不少?接下来,就让我们看看怎样不写代码不用 Excel, 轻松搞定各种图形化展现。 搭建数据桥梁 取数(新建数据源、数据集); 2.拖拖拽拽 搞定数据分析; 3.选择统计图类型,指定分类轴、系列轴、系列名称取值; 其中: 左侧参数部分为右侧 javaScript 代码的变量,一般包含 3 个变量分别是分类名称、系列值、系列名称; 右侧部分为图形的 javaScript 脚本,可引入第三方图形(比如:echarts,Highcharts)也可以点击打开模板使用自带的图形模板。 确定,保存。 到此为止,我们就可以不写代码不用 Excel, 轻松搞定一个统计图形了,最后的呈现结果如下: 最最后,悄悄告诉您,虽然我们已经为每个统计图提供了丰富的样式风格,但可能还是入不了您的法眼,不过没关系,您还可以完全自定义样式风格奥!!! 作者:IBelieve链接:http://c.raqsoft.com.cn/article/1539653005660?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
自定义表格样式 多维分析展现报表时,润乾报表提供了一套默认的表格样式,统一的表格样式可以使业务人员减少报表美化的工作量。然而默认的样式不可能迎合所有用户的审美,为此润乾提供了自定义表格样式的功能,供用户实现个性化的需求,下面小编就来教你如何改变默认表格的样式。 先来看下默认的表格样式,下面是一个统计雇员完成订单情况的报表: 多维分析表格的样式实际上是通过一个模板报表来控制的,我们先来看下这个模板报表的内容,在设计器中打开 [安装根目录]reportwebwebappsdemoWEB-INFfiles 目录下的 style.rpx: 该 rpx 文件即默认的模板报表,其中 B2、D2、F2、H2 的单元格样式分别于与多维分析报表中的标题、分组、指标 1、指标 2 四个区域的样式一一对应。所以在 style.rpx 中设置以上几个单元格样式即可同步更改多维分析报表的样式。 下面我们修改下 style.rpx 单元格的样式,例如修改标题区与分组区的字体颜色,以及修改标题区、指标 1 与指标 2 区域的背景色: 此时报表预览如下: 多维分析表格样式的修改,其实也不止上面那一种方式,用户还可以通过修改 js 代码的方式,操作如下: 打开分析页面 Jsp:[安装根目录]reportwebwebappsdemoraqsoftguidejspolap.jsp,在 Jsp 中添加 js 代码: guideConf.style = [{“name”:“标题”,“backColor”:-1641217,“color”:-16777216,“hAlign”:-47},{“name”:“分组”,“backColor”:-1641217,“color”:-16777216,“hAlign”:-47},{“name”:“指标 1”,“backColor”:-1,“color”:-16777216,“hAlign”:-48},{“name”:“指标 2”,“backColor”:-853778,“color”:-16777216,“hAlign”:-48}]; _//_对不同种类报表单元格的显示属性设置 之后用户就可以通过设置属性值直接更改表格样式了。 预定义模板 除了默认的报表模板 style.rpx,润乾报表中还预定义了一些其他的模板报表供用户使用,我们先来看下如何使用预定义的模板报表: 首先在分析界面中添加报表,选择数据集,设置报表名称,勾选【使用报表模板】然后就可以在下拉框中选择报表模板了,这里我们选择饼图.rpx: 点击确定,进入数据分析设置器,如下图,可以看到左侧是数据集的字段,右侧蓝色框中的控件是模板下拉选择框,黄色框中“分类”“系列值”是模板报表里的参数名称,左侧的字段可直接拖拽至表达式框中,这里我们把货主地区作为分类,订单金额的汇总结果作为系列值: 字段表达式设置完成后,分析控件即可自动计算出报表,报表结果如下: 是不是觉得很神奇呢?想不想看下报表模板内部是怎样的设置呢,接下来给大家解析下我们在上例中用到的饼图.rpx。 超简单,就两步: 1、 增加参数: 刚才我们看到的数据设置分析器界面中栏目框里的“分类”“系列值”其实就是取自报表模板中的参数名称 2、 编辑单元格内容: 单元格中以 ${参数名} 的形式引用参数作为字段名,且报表模板中无需定义数据集,多维分析控件会根据用户在分析界面中选择的字段自动计算出一个数据集,在模板报表的单元格中,可以直接通过 ds1 来引用该数据集。 报表模板的统计图设置同普通报表一样: 最后隐藏 1-3 行,使模板中只显示统计图的效果。 看到这里你一定会想问下:润乾报表中预定义的报表模板并不适用本公司的实际业务场景 ,那可不可以自己定义报表模板来使用呢?当然可以的,下面就来教你怎么自定义报表模板~ 自定义模板 报表模板从制作到使用要分成三步走,先来跟我一起做一个简单报表模板,例如教育机构常用的统计学生成绩的报表模板,操作如下: 第一步:配置报表模板根目录 报表模板只有放在指定的目录下,在分析界面中才能够被引用到,这个目录可以是报表模板的根目录也可以是根目录的子目录,根目录的配置方式如下: 在分析页面 olap.jsp 中配置 rpxFolderOnServer 属性: guideConf.rpxFolderOnServer = “/WEB-INF/files/rpx/”; //服务器上报表模板的根目录,路径相对于主目录,默认为 /WEB-INF/files/rpx/ 第二步:制作模板报表 参数列表: 模板报表中需要先定义参数,字段名需通过参数的形式引用分析界面中的查询结果。 参数的个数由报表中要使用到的字段的个数决定的 ,该模板报表中,我们要用到学生姓名、考试科目、科目成绩这三个字段,所以此处增加 3 个参数,参数名用户可以自定义。 报表内容: 上面已经介绍过,在模板报表的单元格中,直接通过 ds1 作为数据集名引用。 D2 中计算年级平均分; D4 单元格中汇总学生所有科目总成绩,单元格中设置动态前景色,总成绩小于年级平均分的字体显示为红色,否则显示为黑色,前景色表达式为:if(value()<80,-65536,-16777216)。 保存报表: 将报表命名为 mb.rpx 并保存到报表模板根目录下。 第三步:使用预定义模板 在分析界面中添加报表,选择刚刚制作的模板报表 mb.rpx: 点击确定,进入数据分析设计器,设置如下: 预定义模板报表展现: 日常业务报表中,为了使报数据展现的更加直观、形象,通常会用到统计图。再举个例子,教你如何制作图表结合的报表模板。 接下来我们做一张订单年度汇总的模板报表,要求图表结合,可以直观的看到不同时间节点的订单个数、金额及增长率。 增加参数: 设计报表: A3 格表达式:=ds1.group(year(${ 订购日期}),${订购日期}!=null;year(${ 订购日期}):1) B3 格表达式:=ds1.group(month(${ 订购日期});month(${ 订购日期}):1) E3、E4 格值为空时用“-”填充,设置显示值表达式:if(value()==null,“-”,value()) F3 为三维饼形图,展现当年中各个月份的订单总额情况,左主格为 A3,并设置饼图的统计图标题为:=A3{}+“年”,统计图设置如下: A7 为双轴柱线图,展现历年的总订单数及总订单金额情况: 保存报表: 报表命名为“订单汇总表.rpx”并保存到报表模板根目录下。 使用报表模板: 预览报表: 自定义模板为报表展现的样式设置及管理提供了良好的解决方案。既可以方便的对报表样式进行设置,减少报表美化工作量,又能够通过更改报表使用的模板,轻松实现报表样式的统一维护和批量更新。还在等什么,马上来体验一下吧~ 作者:ddszm链接:http://c.raqsoft.com.cn/article/1535016470846?r=IBelieve来源:乾学院著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。