⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reportmanager.java

📁 sample目录下是例子程序。 1.分组汇总例子 TestGroupReport.java 2.交叉报表例子 TestCrossReport.java 需要使用crossTabSample.x
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		for (int i = 0; i < cols.length; i++) {
			cols[i] = i + crossTab.getColHeader().length;
		}
		Table result = CssEngine.applyCss(t);
		result = result.getRotateTable();

		result = generateRowTotal(result, crossTab.getRowHeader().length,
				result.getRowCount(), cols, isSubTotal, arith);
		result = CssEngine.applyCss(result);
		result = result.getRotateTable();
		return result;
	}

	/**
	 * 对交叉表做行汇总统计。
	 * 
	 * @param t
	 *            数据表
	 * @param crossTab
	 *            交叉表
	 * @param isSubTotal
	 *            是否小计,true则小计
	 * @param arith
	 *            统计算法
	 * @return 处理后的表格
	 * @throws ReportException
	 */
	public Table generateCrossTabRowTotal(Table t, CrossTable crossTab,
			boolean isSubTotal, GroupArithmetic arith) throws ReportException {
		int[] totalCols = new int[t.getColCount()
				- crossTab.getRowHeader().length];
		for (int i = 0; i < totalCols.length; i++) {
			totalCols[i] = i + crossTab.getRowHeader().length;
		}

		Table result = generateRowTotal(t, crossTab.getColHeader().length, t
				.getRowCount(), totalCols, isSubTotal, arith);
		return result;
	}

	/**
	 * 生成行汇总统计。包括小计、总计。
	 * 
	 * @param t
	 *            数据表
	 * @param totalCols
	 *            统计的列
	 * @param isSubTotal
	 *            是否小计
	 * @param arith
	 *            统计算法
	 * @return 处理后的数据表
	 * @throws ReportException
	 */
	public Table generateRowTotal(Table t, int[] totalCols, boolean isSubTotal,
			GroupArithmetic arith) throws ReportException {
		return generateRowTotal(t, 0, t.getRowCount(), totalCols, isSubTotal,
				arith);
	}

	/**
	 * 生成行汇总统计。包括小计、总计。
	 * 
	 * @param t
	 *            数据表
	 * @param fromRow
	 *            要统计的行开始的行号,包括此行。
	 * @param toRow
	 *            要统计的行结束的行号,不包括此行。
	 * @param totalCols
	 *            统计的列
	 * @param isSubTotal
	 *            是否小计
	 * @param arith
	 *            统计算法
	 * @return 处理后的数据表
	 * @throws ReportException
	 */
	private Table generateRowTotal(Table t, int fromRow, int toRow,
			int[] totalCols, boolean isSubTotal, GroupArithmetic arith)
			throws ReportException {
		if (t == null || t.getRowCount() == 0) {
			return t;
		}
		Table tempTable = (Table) t.cloneAll(); // 用来生成总计
		int count = t.getRowCount();
		int tempToRow = toRow; // 截止行号。由于会动态插入行,所以这个行号是要不断增大的。

		// 生成小计
		if (isSubTotal) {
			int pointer = fromRow; // 扫描行时的指针
			int prePointer = pointer; // 指向当前组的第一个元素的指针
			while (pointer <= tempToRow) { // 从上至下扫描
				if (debug)
					System.out.println("p:" + pointer + " pre:" + prePointer
							+ " rowCount:" + t.getRowCount());
				TableColumn tc = t.getCol(0); // 由于t是动态增长的(后面要添加行),所以这个语句放在循环里
				if (pointer > 0) {
					// 如果到了最后一行,则得到一组
					if (pointer == t.getRowCount()) {
						TableRow insertTR = getTotalRow(t, prePointer, pointer,
								"小计", totalCols, arith);
						insertTR.setType(Report.GROUP_TOTAL_TYPE);
						t.insertRow(pointer, insertTR);
						if (debug)
							System.out.println("get one group while pre="
									+ prePointer + " and p=" + pointer);
						break; // 结束扫描
					}
					// 如果当前单元不等于前一行同列的单元,则得到一组
					else if (!ObjectUtils.equals(tc.getCell(pointer)
							.getContent(), tc.getCell(prePointer).getContent())) {
						TableRow insertTR = getTotalRow(t, prePointer, pointer,
								"小计", totalCols, arith);
						insertTR.setType(Report.GROUP_TOTAL_TYPE);
						t.insertRow(pointer, insertTR);

						if (debug)
							System.out.println("get one group while pre="
									+ prePointer + " and p=" + pointer);
						// 准备开始新一轮扫描。由于前面插入了一行,所以要跳到下一条的记录
						tempToRow++; // 已经加了行,所以截止行号也要加1
						pointer++;
						prePointer = pointer;
					}
				}
				pointer++;
			}
		}

		// 生成总计
		TableRow insertTR = getTotalRow(tempTable, fromRow, toRow, "总计",
				totalCols, arith);
		insertTR.setType(Report.TOTAL_TYPE);
		t.addRow(insertTR);
		return t;
	}

	/**
	 * 生成交叉表。
	 * 
	 * @param srcTab
	 *            原始数据表
	 * @param crossTab
	 *            交叉表定义对象。
	 * @return 结果表
	 */
	public Table generateCrossTab(Table srcTab, CrossTable crossTab)
			throws ReportException {
		Table result = new Table();
		// 生成交叉表的行头和列头
		// 获得distinct的行头,如果有多个行头,则生成迪卡尔积
		Vector tempRH = new Vector(); // 保存行头信息
		for (int i = 0; i < crossTab.getRowHeader().length; i++) {
			tempRH.add(getDistinctSet(srcTab.getCol(crossTab.getRowHeader()[i]
					.getIndex()), crossTab.getRowHeader()[i].getSortSeq()));
		}
		// 获得distinct的列头
		Vector tempCH = new Vector(); // 保存列头信息
		for (int i = 0; i < crossTab.getColHeader().length; i++) {
			tempCH.add(getDistinctSet(srcTab.getCol(crossTab.getColHeader()[i]
					.getIndex()), crossTab.getColHeader()[i].getSortSeq()));
		}

		TableLine[] rowHead = getHeadForCross(tempRH, TableColumn.class);
		TableLine[] colHead = getHeadForCross(tempCH, TableRow.class);

		// 加行头;
		for (int i = 0; i < rowHead.length; i++) {
			result.addCol((TableColumn) rowHead[i]);
		}

		// 补齐空白列、数据区域;
		for (int i = 0; i < ((TableLine) colHead[0]).getCellCount(); i++) {
			result.addCol(new TableColumn(rowHead[0].getCellCount()));
		}

		// 再加列头;(要从后往前加,才能获得正确的顺序)
		for (int i = colHead.length - 1; i >= 0; i--) {
			TableRow tempTR = (TableRow) colHead[i];
			for (int j = 0; j < rowHead.length; j++) {
				TableCell cell = new TableCell("");
				tempTR.insertCell(cell, 0);
			}
			result.insertRow(0, tempTR);
		}

		// 按行头列头生成交叉部分数据
		for (int i = colHead.length; i < result.getRowCount(); i++) {
			for (int j = rowHead.length; j < result.getColCount(); j++) {
				result.getCell(i, j).setContent(
						getCrossValByHead(srcTab, result, crossTab, i, j));
			}
		}
		// 设置行头和列头的说明文字。
		for (int i = 0; i < colHead.length; i++) {
			for (int j = 0; j < rowHead.length; j++) {
				if (!(i == 0 && j == 0)) {
					result.getCell(i, j).setIsHidden(true);
				}
			}
		}
		int len = crossTab.getColHeader().length
				+ crossTab.getRowHeader().length;

		// Table headHeadTable = new Table(len, len);//交叉表头的表头
		// headHeadTable.setType(Report.CROSS_HEAD_HEAD_TYPE);
		// headHeadTable.setBorder(0);
		// headHeadTable.setWidth(100);
		// headHeadTable.setHeight(100);
		// headHeadTable.setCellpadding(0);
		// headHeadTable.setCellspacing(0);
		// HeadCol[] hhVal = new HeadCol[len];
		// System.arraycopy(crossTab.getColHeader(), 0, hhVal, 0,
		// crossTab.getColHeader().length);
		// System.arraycopy(crossTab.getRowHeader(), 0, hhVal,
		// crossTab.getColHeader().length,
		// crossTab.getRowHeader().length);
		// for (int i = 0; i < len; i++) {
		// headHeadTable.getCell(i, len - 1 -
		// i).setContent(hhVal[i].getHeaderText());
		// }
		TableCell headHeadCell = result.getCell(0, 0);
		headHeadCell.setColSpan(rowHead.length);
		headHeadCell.setRowSpan(colHead.length);
		headHeadCell.setCssStyle("margin: 0px;padding: 0px;");
		headHeadCell.setCssClass(Report.CROSS_HEAD_HEAD_TYPE);
		headHeadCell.setContent(crossTab);

		// 在本方法完毕后,可以进行行、列汇总。

		return result;
	}

	/**
	 * 找出符合条件的行,返回所有行中要取的值。可以在子类覆盖,以使用别的查找算法。
	 * 
	 * @param t
	 *            原始数据表
	 * @param cols
	 *            列的序号
	 * @param cmpVals
	 *            进行比较的值,应该跟cols大小一样。1
	 * @param valueCol
	 *            要取得的值的列号.
	 * @return
	 */
	private double[] findRows(Table t, int[] cols, String[] cmpVals,
			int valueCol) throws ReportException {
		if (cols == null || cmpVals == null) {
			throw new ReportException("cols或cmpValues为空。");
		}
		if (cols.length != cmpVals.length) {
			throw new ReportException("cols和cmpVals的大小应该一致。");
		}
		Vector tmpResult = new Vector();
		for (int i = 0; i < t.getRowCount(); i++) {
			boolean pass = true;
			for (int j = 0; j < cols.length; j++) {
				if (!ObjectUtils.equals(t.getCell(i, cols[j]).getContent(),
						cmpVals[j])) {
					// 默认为通过,执行一票否决制
					pass = false;
					break;
				}
			}
			if (pass) {
				tmpResult.add(t.getRow(i).getCell(valueCol).getContent());
			}
		}
		double[] result = new double[tmpResult.size()];
		for (int i = 0; i < result.length; i++) {
			result[i] = Double.parseDouble((String) tmpResult.elementAt(i));
		}

		return result;
	}

	/**
	 * 获得目标表中某行某列的交叉值。
	 * 
	 * @param srcTab
	 *            数据表
	 * @param destTab
	 *            目标表,是一个数据交叉表。
	 * @param crossTab
	 *            交叉表定义对象
	 * @param row
	 *            行号
	 * @param col
	 *            列号
	 * @return 行号列号的交叉值
	 * @throws ReportException
	 */
	private String getCrossValByHead(Table srcTab, Table destTab,
			CrossTable crossTab, int row, int col) throws ReportException {
		// 确定查找条件
		HeadCol[] headCols = crossTab.getColHeader();
		HeadCol[] headRows = crossTab.getRowHeader();

		String[] cmpVals = new String[headCols.length + headRows.length];
		int[] cols = new int[headCols.length + headRows.length];

		for (int i = 0; i < headCols.length; i++) {
			cols[i] = headCols[i].getIndex();
			cmpVals[i] = (String) destTab.getCell(i, col).getContent();

		}
		for (int i = 0; i < headRows.length; i++) {
			cols[i + headCols.length] = headRows[i].getIndex();

			cmpVals[i + headCols.length] = (String) destTab.getCell(row, i)
					.getContent();

		}

		// 找出符合条件的所有单元
		double[] values = findRows(srcTab, cols, cmpVals, crossTab
				.getCrossCol().getIndex());

		return crossTab.getCrossCol().getArith().getResult(values);

	}

	/**
	 * 为交叉表生成行头或列头。
	 * 
	 * @param orglLine
	 *            原始数据序列。包含多个序列,每个序列都是一个不重复值的集合。
	 * @param cls
	 *            指定返回值数组中的类型。
	 * @return 行头或列头。
	 * @throws ReportException
	 */
	private TableLine[] getHeadForCross(Vector orglLine, Class cls)
			throws ReportException {
		TableLine[] lines = new TableLine[orglLine.size()];
		try {
			for (int i = 0; i < orglLine.size(); i++) {

				int span = 1; // 单元格的跨越数
				// 跨越数等于本序列后的所有序列包含单元数的乘积
				for (int j = i + 1; j < orglLine.size(); j++) {
					span *= ((Set) orglLine.elementAt(j)).size();
				}

				int repeat = 1; // 序列重复的次数。
				// 重复次数等于本序列之前所有序列包含单元数的乘积
				for (int j = 0; j < i; j++) {
					repeat *= ((Set) orglLine.elementAt(j)).size();
				}

				lines[i] = (TableLine) cls.newInstance();

				// 按重复数添加重复序列
				for (int j = 0; j < repeat; j++) {
					Iterator itr = ((Set) orglLine.elementAt(i)).iterator();
					while (itr.hasNext()) {
						String value = (String) itr.next();
						TableCell cell = new TableCell(value);
						lines[i].setSpan(cell, span);
						lines[i].addCell(cell);
						// 创建隐藏的cell,补足cell的个数。
						for (int k = 0; k < span - 1; k++) {
							TableCell hiddenCell = new TableCell(value);
							hiddenCell.setIsHidden(true);
							lines[i].addCell(hiddenCell);
						} // for
					} // while
				} // for
				lines[i].setType(Report.HEAD_TYPE); // 一定要放在所有单元都加入后再设置

				// 由于交叉表有翻转的方法,所以要将样式赋给单元
				for (int k = 0; k < lines[i].getCellCount(); k++) {
					lines[i].getCell(k).setCssClass(lines[i].getType());
				}

				if (debug)
					System.out.println("count:" + lines[i].getCellCount()
							+ " repeat:" + repeat + " span:" + span + " size:"
							+ ((Set) orglLine.elementAt(i)).size());
			} // for
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new ReportException(ex.toString());
		}
		return lines;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -