简介面向使用 Jasper 报表工具进行业务报表设计与打印输出的 IT 从业人员和报表初学者这份文档围绕报表基础结构与常见制作技巧展开帮助读者理解标题、页眉页脚、明细、汇总、分组等区域的作用并覆盖 JSON 数据源、PDF 中文字段、手工补充字段、明细分组、序号列、自定义纸张及交叉报表等实用主题。包内共 1 个 docx 文件约 599KB以文字讲解和要点整理为主内容兼顾结构说明与场景提示便于在遇到字段缺失、中文打印异常、分组分页和面单纸张设置等问题时快速定位思路。当前已有 242 人学习适合作为日常报表设计时的参考笔记也可用于查漏补缺提升报表排版与数据展示效率。文档篇幅精简、重点明确适合放在手边随时翻阅并沉淀为团队可复用的报表制作经验。1. 中文标签在预览里好好的传到系统里就没了Jasper 报表制作这活儿装环境那一步很少有人认真记录等出事才发现坑全埋在配置里。我见过最常见的一幕Jaspersoft Studio 里预览中文正常编译、上传、挂进菜单业务点一下 PDF 下载打开一看中文标签全空白只剩数字和英文活着。这不是报表画错了是 PDF 字体和编码没配。下面按一台干净机器的顺序走先把 Studio 6.x 和 JDK 装对再讲 JSON 数据源、字段类型、分组、序号列、面单纸张和交叉表最后是上传挂载与出事怎么救。适合要出 PDF 面单和管理报表的开发者也适合接手别人模板、被一句“照着改改”丢进项目的运维。2. 装 Jaspersoft Studio 6.xJDK、工作空间和九个 Band 先对上装 Studio 之前在纸上写下来你打算用哪个 JDK、工作空间放哪、数据源是本地 JSON 文件还是接口地址。三件事没定后面一定返工。这一章先把运行环境和界面结构固定住后面两章的配置才有参照物。2.1 版本与 JDK 怎么搭Jaspersoft Studio 6.x 这条主线社区版和企业版界面几乎一样做报表模板用社区版就够。要留意的是 JDK6.x 早期分发包自带 JRE双击就能开后来的 6.x 版本默认吃本机 JDK机器上没装、或者装的是太新的版本双击后闪一下就没日志里常见Unsupported class file major version这类字样。我一般固定用 JDK 8 跑 6.x稳遇到需要更高版本 JDK 的 6.x 包再单独切不在一台机器上混着来。# 先看当前 PATH 里生效的是哪个 JDK java -version # Linux / macOS 再看 JAVA_HOME 指向Windows 在系统属性里查 echo $JAVA_HOMEjava -version输出1.8.0_xxx说明 PATH 里是 JDK 8可直接配 6.x 主线输出 11、17 而手上的 Studio 是吃 JDK 8 的版本就得回去改JAVA_HOME和 PATH 顺序而不是反复重装 Studio。JAVA_HOME指向的是 JDK 根目录里面有bin、lib那层不是bin目录本身这一条写错的人不少。装完 Studio 再改 JDK记得重启 Studio只重开报表窗口不会重新加载 JVM。还有一种情况机器上装了多个 JDK 给不同项目用。常见做法是不动全局 PATH给 Studio 的启动参数或安装目录下的配置文件单独指定 JVM或者在启动前临时切JAVA_HOME。混着用的后果是同一份 jrxml 在你这能跑、在测试机报错排查起来很费时间。2.2 安装与首次启动工作空间别放同步盘Windows 拿安装包一路下一步macOS 拖 dmgLinux 解压后跑目录里的可执行文件三条路殊途同归。真正要小心的是首次启动弹出来的那个 Workspace 选择框。工作空间路径要求三条全英文、不带空格、不在任何同步盘里。OneDrive、iCloud、坚果云这类目录会实时锁文件Studio 自动保存和编译时会撞上文件占用表现是随机报Resource is out of sync或者保存后内容回退很难复现也很难查。路径里带中文或空格某些版本的资源解析会直接失败报的错还跟路径无关属于玄学级排错。# 推荐的工作空间路径长这样纯英文、无空格、本地盘 /Users/dev/workspace-jasper D:\workspace\jasper选好路径后勾上“Use this as the default and do not ask again”省得每次启动都弹。进主界面第一件事改编码Window Preferences General Workspace Text file encoding选 UTF-8。这一步不做模板里的中文标签在别的机器上打开可能是乱码尤其是团队协作、模板要进版本库的时候。改完编码再新建报表顺序不能反。2.3 界面分区与 Band 结构一张表看清谁该放什么主界面实际就四块在用中间是设计区Design 页签和源码区Source 页签左边是 Outline 大纲树Fields、Variables、Parameters、Groups 都在这右边是 Properties 属性面板下边或右侧是 Preview 预览。Studio 基于 Eclipse快捷键那套直接继承CtrlS 保存、CtrlZ 撤销、CtrlShiftR 找资源文件切 Design 和 Source 两个页签是全天最高频的动作。批量改样式我基本不在面板里点直接切 Source 改 XML改完切回来比一个个字段点属性快一个数量级。但要注意 Source 里手改过的内容面板不一定会同步刷新改完保存再切页签一次比较稳妥。设计区那些横条叫 Band决定了内容出现在哪一页、哪个位置。这是整篇里最该先背下来的东西Band出现位置适合放什么常见误用Title只在第一页最上方报表大标题、单位名把每页都要的表头放进来pageHeader每页上部第一页在 Title 下方页码、打印时间、打印人塞业务数据字段columnHeader每页列标题行列名不是列数据把明细字段拖进来Detail每页重复出现明细行如逐条收货记录放合计公式columnFooter每页列级统计本页列小计放整表合计pageFooter每页最下端页脚说明、页码放跨页统计Summary最后一页 Detail 之后整表合计、交叉表只留几行空 bandgroupHeader每个分组开头分组说明如店铺名、月份高度没归零导致空白页groupFooter每个分组结尾组内小计与 columnFooter 统计口径混淆lastPageFooter最后一页最下端末页专属说明与 pageFooter 同时启用导致重复新建报表向导默认给的是 Title、pageHeader、columnHeader、Detail、columnFooter、pageFooter、Summary 这一套groupHeader 和 groupFooter 要建分组才出现lastPageFooter 需要手动在大纲里加。做快递面单时我用到的只有 Detail 一个 band其余全部高度设 0这个后面单独讲。3. 接 JSON 数据源字段、类型和中文字体一次配到位工作室装好了下一步是把数据接进来。用 JSON 当数据源的场景比 JDBC 多接口返回什么直接拿来用少一层数据库驱动。顺序错了会出现“预览没数据”“字段拖不出来”这类问题其实都不是 bug是步骤跳了。3.1 从空白报表到能预览的固定顺序我固定按这七步走一步都不省建数据源适配器Repository Explorer 里右键Data Adapters Create Data Adapter选 JSON File 或 JSON 从远程地址指向 JSON 文件或填接口地址。新建报表Blank A4向导里选刚建好的适配器让它自动读字段。关联数据源设计区点空白处属性面板确认Dataset引用的是这个适配器。把 Fields 从 Outline 拖到 DetailStudio 会自动生成“标签 文本字段”配对。改标签文字中文标签在这一步写进去。分组、算合计、调列宽。Preview 里选数据源预览确认有行、中文正常再保存 jrxml。JSON 适配器里有个XPath expression容易被忽略。根节点直接是对象或数组时填/数据被包在某个数组里比如{items: [...]}就填/items。填错了预览显示“无记录”但字段列表是空的还是齐的能帮你快速判断问题出在哪一层。一份最小可用的 JSON 数据长这样字段名后面会和 field 的 Name 严格对应{ receiptCode: RK202401001, shipFromName: 某供应商, closedAt: 2024-01-18 10:22:00, itemCode: IT-0001, totalQty: 120, openQty: 20 }字段名receiptCode、totalQty这类大小写必须和 JSON 里一模一样。JSON 本身区分大小写Studio 生成的 field 名也照抄改一个字母就查不到值报错时只提示字段找不到不会告诉你差了个大小写。3.2 漏字段、类型错手工补 field 的规矩接口字段是别人维护的今天加一个、明天改个名很正常。发现某个字段没在 Fields 里不用重建报表Outline 里右键Fields Create Field手工补一个就行。规矩有三条Name必须与 JSON 键或查询结果列名完全一致大小写敏感不能用中文。中文写在Description里给人看。Class按实际类型选String 用java.lang.String整数用java.lang.Integer日期用java.util.Date。JSON 里totalQty: 120不带引号时向导一般能识别成整数带了引号就是字符串后面做 Sum 会翻车。补完字段Detail 区里还要拖一个文本字段出来属性面板的Expression改成$F{你的字段名}不拖控件只加 field 是显示不出来的。日期字段还有一层坑JSON 里是2024-01-18 10:22:00这种字符串Class 选了java.util.Date直接预览会抛格式异常。常见做法是先用java.lang.String接显示时用SimpleDateFormat转或者属性面板的Pattern里配对应格式。类型选错在明细里不太看得出来一到分组统计和交叉表才炸属于典型的埋伏。3.3 PDF 中文不显示pdfStyle 全局样式的写法回到开头那个翻车现场。Studio 预览用的是屏幕渲染字体随便调导出 PDF 走的是另一套渲染链没指定 PDF 字体和编码中文就是空白。原文给的做法是对每个中文标签在Advanced面板里设三项标签一多就是体力活所以更省事的是加一段全局样式。!-- 放在 jasperReport 根节点下所有 band 之前 -- style namepdfStyle isDefaulttrue pdfFontNameSTSong-Light pdfEncodingUniGB-UCS2-H isPdfEmbeddedtrue/三个属性各管一件事pdfFontName指定 PDF 里用的中文字体STSong-Light是 iText 内置的宋体类字体不用额外装字体文件pdfEncoding必须是UniGB-UCS2-H这是中文 Unicode 编码写错成Identity-H之类的会出现方块或者直接丢字isPdfEmbedded为 true 表示把字体信息嵌进 PDF换台机器打开也不变形。isDefaulttrue让所有文本字段默认继承这套设置新拖的控件不用再逐个配。注意如果模板是老版本传下来的里面可能已经对单个字段设过 PDF 字体字段级设置的优先级高于全局 style只加全局那段是不生效的。要先把字段级的清掉或者干脆在 Source 里全局搜pdfFontName统一替换。4. 版式调优分组、序号列、面单纸张和交叉表数据通了、中文能出了接下来是让报表长得像那么回事。这一章四个动作都属于“不做也能出 PDF、做了才像成品”的类型每一个都有对应的踩坑点。4.1 分组两种做法band 高度归零与表头搬家按店铺、按月份分组打印是高频需求。做法一Outline 里右键报表名Create Group选中分组字段然后在属性面板把 groupHeader 的Band Properties Height设成 0同时勾上Start New Column和Start New Page。这样组标题本身不占高度但每组强制从新页开始效果就是同店铺的明细归在同一页。做法二适合不想新建分组的情况直接把 columnHeader 的高度设成 0把原来放在 columnHeader 里的列名全部拖到 groupHeader 里。列名只在每组开头打一次明细跟在下面视觉上同样是分组分页。两种做法的差别在维护成本上。做法一保留了完整的 group 结构后面要加组内小计、组内计数直接往 groupFooter 里拖字段就行做法二结构简单但扩展性差groupFooter 不存在想算组小计还得回头补分组。我一般按“以后还要不要改”来选一次性报表用做法二长期维护的用做法一。高度归零这件事有个前提band 里的控件也要一起清掉或者移走。只把高度改成 0 但控件还留在里面Studio 不报错导出时会出现莫名其妙的空白页或者内容被裁切属于典型的血泪经验。4.2 序号列用 Variable不要手写死数字明细行前面加序号肉眼一看是小事但 Detail 是重复渲染的写死 1、2、3 等于每行都打 1。正确做法是建变量Outline 里右键Variables Create Variable属性面板里设这几项属性值说明NameseqNo变量名后面表达式引用Value Classjava.lang.Integer计数结果类型CalculationCount每命中一次表达式加一Reset TypeReport整个报表从头计到尾不随页重置Increment TypeNone不按页或分组自增跟 Calculation 配合Expression$F{itemCode}用某个必然有值的字段做计数依据配完把变量从 Outline 拖到 Detail 第一列属性面板的 Expression 确认为$V{seqNo}。如果希望每页重新从 1 开始Reset Type改成 Page按组分页编号就改成 Group并指定组名。这个变量跟分页是联动的改完一定要翻到 Preview 里的第二页、第三页确认重置行为符合预期。有一种偷懒写法是直接用内置的$V{REPORT_COUNT}它确实存在但含义是“报表已处理的记录数”在分组和分页场景里容易和业务序号对不上尤其是分组后每组想重新编号的时候。自己建一个变量控制权在自己手上。4.3 自定义纸张与 EQUALS 条件打印快递面单、小票这类不是 A4 的报表先在新建报表时选 A4然后点设计区最外侧的页面边框不是点 band属性面板出现 Report 级别的设置进Edit Page Format Format Custom宽高手动填。单位在下面的Units里选面单场景一定选 mm选成英寸或者像素打印机出来的尺寸会差一大截还查不出原因。面单一般只用 Detail 区其他 band 高度全设 0Title、pageHeader、columnHeader、columnFooter、pageFooter、Summary 一个不留。同时把 Detail 的宽高调成面单实际尺寸打印时位置才正。面单上还有一类需求某个字段等于特定值时才打印比如陆运件和航空件用不同标记区分。属性面板里找到该控件的Print When Expression写// 只有运输方式为 E 时才打印该控件 new Boolean($F{shipType} ! null $F{shipType}.equals(E))两个细节不能少返回值要包成Boolean对象老版本 JasperReports 表达式里不做自动装箱shipType为 null 时直接调.equals()会空指针所以判空要放在前面。等值判断还有EQUALS()这类函数写法效果一样但同样要处理 null别只测有值的数据空值那行才是最容易翻车的地方。4.4 Crosstab 交叉表的三条硬性条件交叉表用来做行列汇总比如按仓库和商品类别统计收发数量。它有三条硬性条件任何一条不满足都是白忙第一参与统计的字段必须是数值类型。JSON 读进来的数量字段默认是 String先在 Outline 里把对应 field 的 Class 改成java.lang.Integer或java.math.BigDecimal再进向导否则求和结果全是 0 或者直接报类型转换错。第二Crosstab 只能放在 Summary 区。拖到别的 bandStudio 会拒绝或者在编译时报错。所以做交叉表前先确认 Summary 还在如果之前为了面单把这个 band 删了得先加回来。第三向导里加明细字段时Calculation要手动改成Sum。默认是 Nothing出来的就是原值罗列不是汇总。加完向导点完成把 Crosstab 拖大覆盖到整个 Summary 区双击进去改深蓝色 Static Text 的行列标题。默认字号偏大明细通常显示不全选中所有明细字段统一改成 6 号、居中这一条几乎是每次都要做的收尾动作。5. 上传挂载与常见问题排查条件 JSON、SQL 占位符、View JSON 三处要对齐模板在 Studio 里只是半成品。编译通过的 jrxml 上传到系统之后还要在打印配置里登记、写查询条件、配 SQL、挂到菜单这四步里任何一处名字对不上前端就是点了没反应或者一片空白。这一章按配置顺序写最后把反复出现的五类问题按“现象、原因、解决”列出来。5.1 打印配置代码标识与条件数组后台路径一般是“配置 打印配置 报表 新增报表”要填代码标识、描述、报表类型再贴一段条件 JSON 和一段 SQL 模板。代码标识是这套配置的唯一名字模板名称尽量和它保持一致后面菜单挂载要引用它。条件 JSON 决定了前端弹出什么查询框[ {field: , id: h1_basic, name: 基本信息, type: h1}, {field: beg, id: beg, name: 起始日期, required: true, type: date}, {field: end, id: end, name: 结束日期, required: true, type: date}, {field: itemCode, id: itemCode, name: 商品编码, type: string}, {field: code, id: code, name: 入库单号, type: string}, {field: shipFromName, id: shipFromName, name: 供应商名, type: string} ]field、id、name、type四个必填field和id尽量写成一样后面 SQL 里的占位符用的是这个名字。type决定控件形态date弹日期选择器string是输入框integer只收数字required为 true 时前端会拦空值。type为h1的那条是分组标题field留空用来把条件分块显示纯作业报表其实只留标题加一个装载号就够管理报表才需要把日期、单号、供应商这些都加上。5.2 SQL 模板里的占位符和 null 判断SQL 模板的占位符必须与条件 JSON 的id一一对应大小写一致select rh.closedAt, rd.receiptCode, rh.shipFromName, it.name, rd.totalQty, rd.openQty, (rd.totalQty - rd.openQty) as redQty from RECEIPT_HEADER rh inner join RECEIPT_DETAIL rd on rh.id rd.receiptId inner join ITEM it on rd.itemCode it.code where rh.leadingSts 900 and rh.trailingSts 900 and (:code is null or rh.code :code) and (:itemCode is null or rd.itemCode :itemCode) and (:shipFromName is null or rh.shipFromName :shipFromName) and (:beg is null or rh.closedAt :beg) and (:end is null or rh.closedAt :end) order by rh.closedAt desc每一行过滤都写成“参数为空就不过滤”的形态用户不填单号就查全部填了就精确匹配。这种写法比把条件拼成字符串安全也不用手动判断要不要加and。注意部分数据库驱动对:beg is null这种判断推断不出参数类型会报参数类型无法确定。遇到这种情况常见做法是把日期参数在执行前补一个默认值比如很早的日期或者改成字符串比较先让语句能编译通过再回头调参数类型。(rd.totalQty - rd.openQty) as redQty这种计算列在 SQL 里算完报表里直接当普通字段用比在报表表达式里再写一遍公式好维护两边口径也不会打架。5.3 菜单配置 View JSON 与管理报表查询作业报表要在前端菜单上点得出来得去“开发 菜单配置”找到对应的界面类型和界面名称在 View JSON 里找到打印区域把报表挂上去{ print: [ {name: 入库商品明细表, id: receiptDetailReport} ] }name对应上传的模板名称id对应打印配置里的代码标识两个都填错或者只错一个前端按钮就在但点了没反应。改完点更新重新打开页面才生效别在原地刷新等。管理报表不走这条路它在“管理 报表查询”里直接列出来双击就是预览界面选好自定义期间、填完其他条件点 PDF 下载即可。作业报表和管理报表的差别就在这前者挂在具体业务单据的详情页上带单据主键后者是独立查询入口条件是用户自己选的。5.4 五条踩坑记录从现象倒推原因现象一Studio 里预览中文正常系统里下载的 PDF 中文全空白。原因模板没设 PDF 字体和编码屏幕渲染能显示导出就丢。 解决加全局pdfStyle那段或者逐字段在 Advanced 面板设pdfFontName、pdfEncoding、isPdfEmbedded三项老模板记得先清掉字段级覆盖。现象二编译通过预览或运行时报字段找不到、空指针。原因JSON 里漏了字段或者手补的 field 名字大小写、拼写与数据源不一致。 解决Outline 里Create Field补上Name 严格照抄数据源Class 选对补完确认 Detail 里有控件引用$F{...}。现象三分组后每页多一张空白页或者组标题不换页。原因groupHeader 的 Height 改了 0但里面的控件没清或者没勾Start New Page。 解决band 高度归零前先把内容移到 groupFooter 或 Detail勾选Start New Column、Start New Page预览翻三页确认。现象四交叉表空白、合计全是 0。原因统计字段还是 String 类型或者向导里 Calculation 没改成 Sum或者 Crosstab 放错了 band。 解决field 的 Class 改成 Integer向导中明细字段的 Calculation 统一 Sum确认 Crosstab 在 Summary 区最后把明细字号调到 6 号居中。现象五面单打印位置偏、内容被裁。原因页面格式没设 Custom单位不是 mm或者非 Detail 的 band 高度没清零。 解决Report 属性进Edit Page Format Custom单位选 mm 填实际尺寸其余 band 高度全部设 0打印机纸张同步设成一样大小。6. 装完怎么验证跑通一份最小 JSON 报表的四步验收装完不要直接上手改正式模板先做一份最小报表把链路走通。我一般用一份三行数据的 JSON、只保留 Title、columnHeader、Detail、Summary 四个 band字段就三个单号、供应商、数量。小到极致出问题一眼能定位。验收分四步每步都拿结果说话步骤操作通过标准不通过先查什么1. 数据接入Preview 选 JSON 适配器出现三行记录无空字段XPath 表达式、字段名大小写2. 中文 PDFPreview 里用 PDF 预览模式中文标签完整无方块无空白pdfStyle 全局样式是否生效3. 分组换页按供应商建组band 高度归零每组从新页开始无空白页Height 是否为 0、是否勾 Start New Page4. 系统下载上传模板、配条件、挂菜单、PDF 下载条件生效中文正常合计对得上代码标识与 View JSON 的 id 是否一致第 2 步有个技巧别用屏幕预览判断中文是否正常。Studio 的屏幕预览用的是本机字体即使 PDF 配置全错也能显示得好好的。切到 PDF 预览模式再看走的是和系统同一套渲染这一步能提前拦下八成的中文字体问题。第 4 步之前我还会先在“报表查询”里用管理报表入口试跑一次因为那里能直接选参数、直接 PDF 下载不依赖菜单配置能把“SQL 和条件 JSON 对不上”和“菜单挂载写错”这两类问题分开看。全都通了再去挂菜单顺序反了就会在两个错误之间来回猜。从那以后我每次新装一套环境都强制走一遍这四步哪怕只是换台机器重装 Studio也要拿这份三行数据的小报表验一遍手。省下的不是这十分钟而是后面在业务面前打不开 PDF 的那半小时。希望帮到你。本文还有配套的精品资源点击获取