📄 reportmanager.java
字号:
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 + -