Skip to content

Quarterly target completion comparison (enterprise operations) — generate this PDF with Java (AREA)

JQuick-PdfBiz Demo

AREA2 页 A4 · 233 KB

Compares planned and actual quarterly values and uses an area chart to show the cumulative completion gap.

Download the PDFView raw template fileBack to all demos

Quarterly target completion comparison (enterprise operations) — AREA
Rendered output

Output specs

PDF pages
2
Chart type
AREA
Template lines
87
Source lines
90

Java source · JQuickBiz30QuarterCompletionTest.java

This is the complete test class that produced the PDF above — copy it and run as-is; see the quick-start section for the Maven dependency.

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright (c) [2025-2099] Martin ([email protected])
 */
package com.github.paohaijiao.demo.biz;

import com.github.paohaijiao.JOption;
import com.github.paohaijiao.combol.area.JAreaChartData;
import com.github.paohaijiao.combol.area.JSeriesData;
import com.github.paohaijiao.combol.area.JTheme;
import com.github.paohaijiao.config.JPdfConfig;
import com.github.paohaijiao.demo.constant.JQuickConstant;
import com.github.paohaijiao.enums.JChartType;
import com.github.paohaijiao.executor.JQuickPdfFactory;
import com.github.paohaijiao.factory.JChartRendererFactory;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

/**
 * 业务场景 Demo 30:季度指标完成度对比(企业运营)
 *
 * <p>业务场景:企业运营管理部按季度对比「计划目标」与「实际完成」的营业收入,
 * 用于观察季度指标完成度与经营节奏。</p>
 * <p>实际图表类型:{@link JChartType#AREA} 区域图(计划值与实际完成值的区域对比)。</p>
 *
 * <p>模板:{@code report/biz/30_quarter_completion.txt};图表以 SVG 文本形式绑定到模板的
 * {@code ${svg}} 占位符,输出到 {@code D:\test\biz\30_quarter_completion.pdf}。</p>
 *
 * <p>图表尺寸说明:图表按 700pt × 380pt(宽 × 高)的横版比例设计;模板中 {@code <svg>}
 * 只声明宽度、不声明高度,因此宽度被页面自动收窄时高度会按原比例同步缩放,不会纵向拉伸变形。</p>
 *
 * @author Martin
 * @version 1.0.0
 */
public class JQuickBiz30QuarterCompletionTest {

    public static final String path = JQuickConstant.path;

    @Test
    public void biz30QuarterCompletion() throws IOException {
        JAreaChartData data = new JAreaChartData();
        data.setTitle("季度营业收入完成度");
        data.setSubtitle("计划目标 vs 实际完成(单位:万元)");
        data.setXAxisTitle("季度");
        data.setYAxisTitle("金额(万元)");
        data.setLegendText("实际完成");
        data.setShowDataLabels(true);
        // 两个系列:实际完成与计划目标,形成区域对比
        data.setSeriesList(Arrays.asList(
                new JSeriesData("实际完成", Arrays.asList(3200.0, 3480.0, 3910.0, 4260.0)),
                new JSeriesData("计划目标", Arrays.asList(3000.0, 3400.0, 3800.0, 4100.0))
        ));
        data.setXAxisLabels(Arrays.asList("Q1", "Q2", "Q3", "Q4"));
        data.setTheme(JTheme.DEFAULT);
        JOption option = new JOption();
        option.setData(data);

        String svg = JChartRendererFactory.renderChart(JChartType.AREA, option);

        File dir = new File(path + "biz");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        FileOutputStream fileOutputStream = new FileOutputStream(path + "biz/30_quarter_completion.pdf");
        JPdfConfig config = new JPdfConfig();
        // 开启 flex 行布局,使模板中的 display:flex 生效(图表居中)
        config.getLayoutConfig().setFlexLayout(true);
        JQuickPdfFactory factory = new JQuickPdfFactory(config);
        factory.bind("svg", svg);
        byte[] bytes = factory.executeResource("report/biz/30_quarter_completion.txt");
        fileOutputStream.write(bytes);
        fileOutputStream.close();
    }
}

Minimal invocation (3 lines)

Skip the full test class — the core is these three lines: bind the chart SVG, execute the template, get the PDF bytes. Copy them straight into your project.

// config 可省略;svg 来自 JChartRendererFactory.renderChart(...),见下方完整源码
factory.bind("svg", svg);
byte[] pdf = new JQuickPdfFactory(config).executeResource("report/biz/30_quarter_completion.txt");

Template file · 30_quarter_completion.txt

An HTML-like template with inline CSS that renders to PDF once bound to data. The full template is below — copy it or download the raw file.

<pdf>
<body>
  <div style="display:flex; justifyContent:space-between; marginBottom:10px; keepTogether:true">
    <div style="width:300px">
      <h1 style="color:#1B5E20; fontSize:18pt; bold:true; marginBottom:4pt">'季度指标完成度分析'</h1>
      <p style="color:#5A6B7C; fontSize:9pt">'计划目标 vs 实际完成(营业收入,单位:万元)'</p>
    </div>
    <div style="width:240px; textAlignment:right; borderLeft:1px solid #B9C2CC; paddingLeft:10px">
      <p style="color:#5A6B7C; fontSize:9pt">'统计周期:2024年1月 - 12月'</p>
      <p style="color:#5A6B7C; fontSize:9pt">'编制单位:企业运营管理部'</p>
      <p style="color:#5A6B7C; fontSize:9pt">'报送对象:年度经营分析会'</p>
    </div>
  </div>

  <div style="marginBottom:10px">
    <h2 style="color:#1B5E20; fontSize:13pt; bold:true; underline:true; marginBottom:6pt">'一、季度完成情况'</h2>
    <table style="width:540px; fontSize:10pt">
      <tr>
        <th style="backgroundColor:#1B5E20; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'季度'</th>
        <th style="backgroundColor:#1B5E20; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'计划目标(万元)'</th>
        <th style="backgroundColor:#1B5E20; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'实际完成(万元)'</th>
        <th style="backgroundColor:#1B5E20; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'完成率'</th>
        <th style="backgroundColor:#1B5E20; color:white; padding:6px; textAlign:center; border:1px solid #DCE3EC">'差额(万元)'</th>
      </tr>
      <tr>
        <td style="padding:5px; border:1px solid #DCE3EC">'Q1'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3,000'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3,200'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'106.7%'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'+200'</td>
      </tr>
      <tr>
        <td style="padding:5px; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'Q2'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'3,400'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'3,480'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'102.4%'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'+80'</td>
      </tr>
      <tr>
        <td style="padding:5px; border:1px solid #DCE3EC">'Q3'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3,800'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'3,910'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'102.9%'</td>
        <td style="padding:5px; textAlign:right; border:1px solid #DCE3EC">'+110'</td>
      </tr>
      <tr>
        <td style="padding:5px; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'Q4'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'4,100'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'4,260'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'103.9%'</td>
        <td style="padding:5px; textAlign:right; backgroundColor:#EDF3ED; border:1px solid #DCE3EC">'+160'</td>
      </tr>
      <tr>
        <td style="padding:6px; backgroundColor:#1B5E20; color:white; bold:true; border:1px solid #1B5E20">'全年合计'</td>
        <td style="padding:6px; textAlign:right; backgroundColor:#1B5E20; color:white; bold:true; border:1px solid #1B5E20">'14,300'</td>
        <td style="padding:6px; textAlign:right; backgroundColor:#1B5E20; color:white; bold:true; border:1px solid #1B5E20">'14,850'</td>
        <td style="padding:6px; textAlign:right; backgroundColor:#1B5E20; color:white; bold:true; border:1px solid #1B5E20">'103.8%'</td>
        <td style="padding:6px; textAlign:right; backgroundColor:#1B5E20; color:white; bold:true; border:1px solid #1B5E20">'+550'</td>
      </tr>
    </table>
  </div>

  <div style="marginBottom:10px; padding:10px; backgroundColor:#F7FAF7; borderRadius:4px">
    <h2 style="color:#1B5E20; fontSize:13pt; bold:true; underline:true; marginTop:0; marginBottom:6pt">'二、目标达成走势'</h2>
    <div style="display:flex; justifyContent:center">
      <svg style="width:700pt">${svg}</svg>
    </div>
    <p style="fontSize:9pt; color:#6c757d; italic:true; marginTop:6pt">'图 1  2024年季度营业收入计划目标与实际完成对比(数据来源:财务共享中心)'</p>
  </div>

  <div style="marginBottom:10px">
    <h2 style="color:#1B5E20; fontSize:13pt; bold:true; underline:true; marginBottom:6pt">'三、经营分析与结论'</h2>
    <list style="paddingLeft:18px; fontSize:10pt" listType="ordered">
      <li style="marginBottom:5px">'全年营业收入实际完成 14,850 万元,高于计划目标 14,300 万元 550 万元,整体完成率 103.8%,四个季度均超额达成。'</li>
      <li style="marginBottom:5px">'实际完成额逐季走高:由 Q1 的 3,200 万元增至 Q4 的 4,260 万元,Q4 较 Q1 增长 33.1%,规模扩张趋势明确。'</li>
      <li style="marginBottom:5px">'Q2 完成率 102.4% 为四个季度最低,主因二季度供应链交付延迟影响部分收入确认,缺口已在 Q3 补齐。'</li>
      <li style="marginBottom:5px">'建议:将下年度计划目标适度前移至上半年,避免年末集中冲刺带来的产能与资源紧张。'</li>
    </list>
  </div>

  <div style="textAlignment:center; marginTop:10px; paddingTop:10px; borderTop:1px solid #dee2e6; color:#6c757d; fontSize:8pt">
    <p>'数据来源:企业运营管理系统(ERP) | 生成时间:2025年1月15日'</p>
    <p>'内部资料 · 未经许可请勿外传'</p>
  </div>
</body>
</pdf>

More demos in this group

The PDF, preview image, template and source code on this page were all produced by a real JQuick-Pdf run and are free to copy into your own project.