JasperReport实现动态列

本文介绍如何使用Java Swing和JasperReports库创建自定义报表。通过动态调整表格列宽,实现报表标题、表头及详细数据部分的设计,并提供报表预览功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.Enumeration;

import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import net.sf.jasperreports.engine.JRAlignment;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRTableModelDataSource;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignFrame;
import net.sf.jasperreports.engine.design.JRDesignLine;
import net.sf.jasperreports.engine.design.JRDesignParameter;
import net.sf.jasperreports.engine.design.JRDesignStaticText;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.view.JasperViewer;

/**
 *
 */

/**
 * @author wenliang
 *
 */
public class JDesign {
 static JRDesignBand tIband =null;
 static JRDesignBand cHband =null;
 static JRDesignBand dEband =null;
 static JRDesignStaticText staticText=null;
 static JRDesignFrame frame =null;
 static JRDesignLine line=null;
 static JRDesignTextField textField =null;
 static JRDesignExpression expression=null;
 static int jDWidth=595;   //default width
 static int jDHeight=842;  //default height
 static int cWidth=555;    //default columnWidth
 static JRDesignField field;
 static int width=0;
 static DefaultTableModel dtm=new DefaultTableModel();
 static JasperDesign jasperDesign = null;
 static JasperReport jasperReport = null;
 static JasperPrint jasperPrint = null;
 public static void Preview(String rTitle,JTable tb){
  String colName[] = new String[tb.getColumnCount()];
  for (int i = 0; i < tb.getColumnCount(); i++) {
   colName[i] = tb.getColumnName(i);
  }
  String data[][] = new String[tb.getRowCount()][tb.getColumnCount()];
  for (int i = 0; i < tb.getRowCount(); i++) {
   for (int j = 0; j <tb.getColumnCount(); j++) {
    data[i][j] = String.valueOf(tb.getValueAt(i, j));
   }
  }
  dtm.setDataVector(data, colName);
  try {
   jasperDesign = JDesign.getJasperDesign(rTitle,tb);
  } catch (JRException e) {
   System.out.println("获取生成报表模板信息失败");
   e.printStackTrace();
  }
  try {
   jasperReport = JasperCompileManager
     .compileReport(jasperDesign);
  } catch (JRException e) {
   System.out.println("生成报表模板失败");
   e.printStackTrace();
  }
  try {
   jasperPrint = JasperFillManager.fillReport(
     jasperReport, null, new JRTableModelDataSource(dtm));
  } catch (JRException e) {
   System.out.println("填充报表模板数据失败");
   e.printStackTrace();
  }
  boolean isExitOnClose=false;
  JasperViewer.viewReport(jasperPrint,isExitOnClose);
  tb.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
 }
 public static JasperDesign getJasperDesign(String rTitle,JTable tb) throws JRException {
  JDesign.FitTableColumns(tb);//自动调整列宽
  if (width>555) {
   jDWidth=842;
   jDHeight=595;
   cWidth=802;
  }else {
   width=555;
  }
  
  // JasperDesign
  JasperDesign jasperDesign = new JasperDesign();
  jasperDesign.setName(rTitle);
  jasperDesign.setPageWidth(jDWidth);
  jasperDesign.setPageHeight(jDHeight);
  jasperDesign.setColumnWidth(cWidth);
  jasperDesign.setColumnSpacing(0);
  jasperDesign.setLeftMargin(20);
  jasperDesign.setRightMargin(20);
  jasperDesign.setTopMargin(20);
  jasperDesign.setBottomMargin(20);
  
  //Title
  tIband = new JRDesignBand();
  tIband.setHeight(50);
     staticText = new JRDesignStaticText();
  staticText.setX(0);
  staticText.setY(0);
  staticText.setWidth(cWidth);
  staticText.setHeight(50);
  staticText.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
  staticText.setText(rTitle);
  staticText.setFontSize(22);
  staticText.setBold(true);
  tIband.addElement(staticText);
  jasperDesign.setTitle(tIband);
  
  cHband = new JRDesignBand();
  cHband.setHeight(20);
  frame = new JRDesignFrame();
  frame.setX(0);
  frame.setY(0);
  frame.setWidth(cWidth);
  frame.setHeight(20);
  cHband.addElement(frame);
  
  dEband = new JRDesignBand();
  dEband.setHeight(20);
  
  for (int i = 0; i <tb.getColumnCount(); i++) {
   
   field = new JRDesignField();
   field.setName(tb.getColumnName(i));
   field.setValueClass(java.lang.String.class);
   jasperDesign.addField(field);
   
   staticText = new JRDesignStaticText();
   staticText.setX((width/tb.getColumnCount())*i);
   staticText.setY(0);
   staticText.setWidth(tb.getColumnModel().getColumn(i).getWidth());
   staticText.setHeight(15);
   staticText.setText(tb.getColumnName(i));
   staticText.setBold(true);
   frame.addElement(staticText);
   
   textField = new JRDesignTextField();
   textField.setX((width/tb.getColumnCount())*i);
   textField.setY(0);
   textField.setWidth(tb.getColumnModel().getColumn(i).getWidth());
   textField.setHeight(15);
      expression = new JRDesignExpression();
   expression.setValueClass(java.lang.String.class);
   expression.setText("$F{"+tb.getColumnName(i)+"}");
   textField.setExpression(expression);
   dEband.addElement(textField);
  }
  line = new JRDesignLine();
  line.setX(0);
  line.setY(19);
  line.setWidth(cWidth);
  line.setHeight(0);
  frame.addElement(line);
  
  jasperDesign.setColumnHeader(cHband);

     line = new JRDesignLine();
  line.setX(0);
  line.setY(19);
  line.setWidth(cWidth);
  line.setHeight(0);
  dEband.addElement(line);
  jasperDesign.setDetail(dEband);


  return jasperDesign;

 }
 public static void FitTableColumns(JTable myTable) //这个方法由网上采集,感谢此方法的作者

            //(此方法主要用来动态调整单元格列宽)
 {
     JTableHeader header = myTable.getTableHeader();//获取表头
     int rowCount = myTable.getRowCount();//获取行数
     Enumeration columns = myTable.getColumnModel().getColumns();//获取所有列
     while(columns.hasMoreElements())
     {
         TableColumn column = (TableColumn)columns.nextElement();
         int col = header.getColumnModel().getColumnIndex(column.getIdentifier());
         int width = (int)myTable.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(myTable, column.getIdentifier(), false, false, -1, col).getPreferredSize().getWidth();               
         for(int row = 0; row<rowCount; row++)
          {
              int preferedWidth = (int)myTable.getCellRenderer(row, col).getTableCellRendererComponent(myTable,
              myTable.getValueAt(row, col), false, false, row, col).getPreferredSize().getWidth();
              width = Math.max(width, preferedWidth);
          }
          header.setResizingColumn(column); 
          column.setWidth(width+myTable.getIntercellSpacing().width);
          if(width+myTable.getIntercellSpacing().width<50){
           column.setWidth(50);
          }
      }
 }

}

 

 

可以自己写个测试类。把你的jtable放到上面方法进行测试。在打印预览的时候你可以自己写列的选择功能。

<think>好的,用户现在询问的是关于Jasper动态合并序号的步骤。首先,我需要明确用户提到的“Jasper”具体指的是什么。通常来说,Jasper可能指的是JasperReports,这是一个广泛使用的开源报表生成工具,常用于Java应用中生成PDF、Excel等格式的报表。动态合并序号可能是指在生成报表时,根据数据的分组或其他条件,动态地合并单元格并生成相应的序号,比如在分组内重新开始编号。 接下来,我需要考虑用户的使用场景。用户可能是开发人员或者报表设计者,他们在使用JasperReports时遇到了需要动态生成序号并合并单元格的需求。例如,在生成分组报表时,每个分组内的数据需要独立的序号,或者需要跨行合并某些单元格显示序号。用户可能已经尝试过一些方法但遇到了问题,或者刚开始接触JasperReports,需要指导如何实现这一功能。 用户的真实需求可能不仅仅是步骤,而是如何高效地在JasperReports中实现动态合并和序号生成。他们可能需要具体的操作步骤,包括变量定义、表达式编写以及属性设置。此外,用户可能希望了解如何根据不同的条件动态调整序号,比如分组变化时重置序号,或者在合并单元格时保持序号的正确显示。 现在,我需要整理实现这一功能的步骤。首先,动态序号通常需要使用变量(Variables)来计数,并在分组变化时重置。其次,合并单元格可能需要使用JasperReports的合并属性,比如设置`colspan`或`rowspan`,或者利用组件的`printWhenExpression`来控制显示。另外,可能需要结合条件判断来动态调整合并的单元格数量。 可能的步骤包括: 1. 创建分组:根据数据中的某个字段(如部门、类别)创建分组,以便在分组内重置序号。 2. 定义变量:定义一个变量来保存当前序号,初始值为0,每次在分组内递增。 3. 设置变量的重置条件:当分组变化时,变量重置为初始值(如1或0)。 4. 在单元格中使用变量:在报表的相应位置显示变量的值作为序号。 5. 合并单元格:通过设置单元格的合并属性或使用子报表等方式实现动态合并,可能需要使用表达式来控制合并的范围。 需要注意的是,JasperReports中合并单元格相对复杂,通常需要在设计报表模板时使用`rowspan`属性,或者通过调整相邻单元格的显示与隐藏来实现合并效果。例如,可以在第一个数据行显示序号并设置`rowspan`为分组内的记录数,后续行隐藏该序号单元格。这需要计算分组内的记录数,可能需要使用组变量来统计。 此外,动态合并还可能涉及到在预览或导出时保持布局正确,需要确保表达式和变量的计算顺序正确,避免因为分页或数据变化导致合并错误。可能需要使用`Evaluation Time`属性来控制变量计算的时机,确保在需要的时候获取正确的值。 在实施过程中,用户可能会遇到变量未重置、合并范围不正确、序号重复或跳跃等问题。需要检查分组的定义是否正确,变量的重置条件和计算表达式是否准确,以及合并属性的设置是否符合预期。 总结来说,回答需要分步骤详细说明如何创建分组、定义变量、设置合并属性,并提供示例表达式和配置,帮助用户逐步实现动态合并序号的功能。同时,可能需要提醒用户注意常见问题及解决方法,确保他们能够顺利应用这些步骤到实际项目中。</think>以下是关于在JasperReports中实现动态合并序号的分步说明: --- ### **步骤1:创建分组** 若需按特定字段分组重置序号(例如按部门分组),需先定义数据组: 1. 在JasperSoft Studio中右键点击报表 → **Create Group** 2. 选择分组字段(如`department`) 3. 设置分组逻辑(默认按字段值变化触发分组) --- ### **步骤2:定义序号变量** 通过变量实现动态计数: 1. **新建变量**:右键`Variables` → **Create Variable** - **Name**: `groupIndex` - **Class Type**: `java.lang.Integer` - **Calculation**: `System` - **Reset Type**: `Group` → 选择步骤1创建的分组名 - **Variable Expression**: ```java $V{groupIndex} == null ? 1 : $V{groupIndex} + 1 ``` - **Initial Value Expression**: `0` --- ### **步骤3:设计序号列** 在Detail区域插入文本框显示序号: 1. 拖拽`Text Field`至表格列 2. 设置表达式: ```java $V{groupIndex} ``` 3. 配置文本框属性: - **Evaluation Time**: `Now`(默认) - 勾选**Stretch With Overflow** --- ### **步骤4:动态合并单元格** 通过条件表达式控制合并范围(以垂直合并为例): 1. **在第一个单元格中**: - 设置`rowspan`属性为分组内的总行数: ```java $V{yourGroup_COUNT} // 使用Jasper内置的组计数变量 ``` - **Print When Expression**: ```java $V{groupIndex} == 1 // 仅在第一行显示 ``` 2. **在后续单元格中**: - 留空并设置**Print When Expression**为`false`,隐藏重复序号。 --- ### **步骤5:验证与调试** 1. 预览报表,检查: - 分组变化时序号是否重置 - 合并单元格是否覆盖正确行数 2. 常见问题处理: - **序号不连续**:检查变量重置条件与分组匹配性 - **合并错位**:确认`rowspan`计算是否准确 --- ### **示例效果** 假设数据按`department`分组: | 序号 | 部门 | 员工 | |------|----------|--------| | 1 | 技术部 | 张三 | | | | 李四 | | 1 | 市场部 | 王五 | --- 通过以上步骤,可实现动态分组序号与单元格合并。实际应用中需根据数据结构和需求调整表达式逻辑。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值