代码拉取完成,页面将自动刷新
从你这个图片里没看到有树结构,方便的话可以将示例文件发到我邮箱,我研究下。
点右上角可以看到我的邮箱
发了
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
已收,我看了下示例文件,现在肯定是不支持的。可以通过继承XMLWorksheetWriter类来支持,我空了可以写一段示例代码。
大致分如下几个步骤:
@Test public void testTree() throws IOException {
List<TreeNode> root = new ArrayList<>();
TreeNode class1 = new TreeNode("一年级", (94 + 97) / 2.0D);
root.add(class1);
class1.children = (Arrays.asList(new TreeNode("张一", 94), new TreeNode("李一", 97)));
TreeNode class2 = new TreeNode("二年级", (75 + 100 + 90) / 3.0D);
root.add(class2);
class2.children = (Arrays.asList(new TreeNode("张二", 75), new TreeNode("李二", 100), new TreeNode("王二", 90)));
new Workbook().addSheet(new ListSheet<TreeNode>(root) {
@Override
protected EntryColumn createColumn(AccessibleObject ao) {
EntryColumn column = super.createColumn(ao);
if (column == null && ao.isAnnotationPresent(TreeLevel.class)) {
column = new EntryColumn();
column.setColIndex(99); // <- 设置一个不存在特殊列
}
return column;
}
@Override
protected void mergeGlobalSetting(Class<?> clazz) {
super.mergeGlobalSetting(clazz);
// 如果对象头有TreeStyle注解则添加一个扩展参数,参数名随意,在worksheetWriter能取就行
if (clazz.isAnnotationPresent(TreeStyle.class)) {
putExtProp("tree_style", "1");
}
}
@Override
protected void calculateRealColIndex() {
super.calculateRealColIndex();
// 将上面设置的特殊列号改到尾列
columns[columns.length - 1].getTail().colIndex = columns[columns.length - 2].getTail().colIndex + 1;
columns[columns.length - 1].getTail().realColIndex = columns[columns.length - 2].getTail().realColIndex + 1;
}
// 将树结构降维,如果由level区分等级则不需要这一步
@Override
public void resetBlockData() {
if (!eof && left() < rowBlock.capacity()) {
append();
}
// EOF
int left = left();
if (left == 0) return;
List<TreeNode> nodes = new ArrayList<>(left);
for (TreeNode e : data) {
nodes.add(e);
e.level = 0;
List<TreeNode> sub = e.children;
e.children = null;
for (TreeNode o : sub) {
nodes.add(o);
o.level = 1;
o.children = null;
}
}
this.data = nodes; // <- 替换原有数据
this.start = 0;
this.end += nodes.size() - left; // <- 重置尾下标
super.resetBlockData();
}
}.setSheetWriter(new XMLWorksheetWriter() {
boolean isTreeStyle;
@Override
protected void writeBefore() throws IOException {
super.writeBefore();
// 判断是否以tree结构输出
isTreeStyle = "1".equals(sheet.getExtPropValue("tree_style"));
}
protected int startRow(int rows, int columns, Double rowHeight, int level) throws IOException {
// Row number
int r = rows + startRow;
bw.write("<row r=\"");
bw.writeInt(r);
// default data row height 16.5
if (rowHeight != null && rowHeight >= 0D) {
bw.write("\" customHeight=\"1\" ht=\"");
bw.write(rowHeight);
}
if (this.columns.length > 0) {
bw.write("\" spans=\"");
bw.writeInt(this.columns[0].realColIndex);
bw.write(':');
bw.writeInt(this.columns[this.columns.length - 1].realColIndex);
} else {
bw.write("\" spans=\"1:");
bw.writeInt(columns);
}
// 除root节点外,其余节点需要添加level属性
if (isTreeStyle && level > 0) {
bw.write("\" outlineLevel=\"");
bw.writeInt(level);
}
bw.write("\">");
return r;
}
@Override
protected int writeHeaderRow() throws IOException {
// Write header
int rowIndex = 0, subColumnSize = columns[0].subColumnSize(), defaultStyleIndex = sheet.defaultHeadStyleIndex();
int realColumnLen = isTreeStyle ? columns.length - 1 : columns.length;
Column[][] columnsArray = new Column[realColumnLen][];
for (int i = 0; i < realColumnLen; i++) {
columnsArray[i] = columns[i].toArray();
}
// Merge cells if exists
@SuppressWarnings("unchecked")
List<Dimension> mergeCells = (List<Dimension>) sheet.getExtPropValue(Const.ExtendPropertyKey.MERGE_CELLS);
Grid mergedGrid = mergeCells != null && !mergeCells.isEmpty() ? GridFactory.create(mergeCells) : null;
for (int i = subColumnSize - 1; i >= 0; i--) {
// Custom row height
double ht = getHeaderHeight(columnsArray, i);
if (ht < 0) ht = sheet.getHeaderRowHeight();
int row = startRow(rowIndex++, realColumnLen, ht);
String name;
for (int j = 0, c = 0; j < realColumnLen; j++) {
Column hc = columnsArray[j][i];
name = isNotEmpty(hc.getName()) ? hc.getName() : mergedGrid != null && mergedGrid.test(i + 1, hc.getRealColIndex()) && !isFirstMergedCell(mergeCells, i + 1, hc.getRealColIndex()) ? null : hc.key;
writeString(name, row, c++, hc.getHeaderStyleIndex() == -1 ? defaultStyleIndex : hc.getHeaderStyleIndex());
}
// Write header comments
for (int j = 0; j < realColumnLen; j++) {
Column hc = columnsArray[j][i];
if (hc.headerComment != null) {
if (comments == null) comments = sheet.createComments();
comments.addComment(new String(int2Col(hc.getRealColIndex())) + row, hc.headerComment);
}
}
bw.write("</row>");
}
return subColumnSize;
}
@Override
protected void writeRow(Row row) throws IOException {
Cell[] cells = row.getCells();
int len = isTreeStyle ? cells.length - 1 : cells.length;
int r = isTreeStyle ? startRow(row.getIndex(), len, row.getHeight(), cells[columns.length - 1].intVal) : startRow(row.getIndex(), len, row.getHeight());
// 以下代码为父类不变
for (int i = 0; i < len; i++) {
Cell cell = cells[i];
int xf = cell.xf;
switch (cell.t) {
case INLINESTR:
case SST: writeString(cell.stringVal, r, i, xf); break;
case NUMERIC: writeNumeric(cell.intVal, r, i, xf); break;
case LONG: writeNumeric(cell.longVal, r, i, xf); break;
case DATE:
case DATETIME:
case DOUBLE:
case TIME: writeDouble(cell.doubleVal, r, i, xf); break;
case BOOL: writeBool(cell.boolVal, r, i, xf); break;
case DECIMAL: writeDecimal(cell.decimal, r, i, xf); break;
case CHARACTER: writeChar(cell.charVal, r, i, xf); break;
case REMOTE_URL: writeRemoteMedia(cell.stringVal, r, i, xf); break;
case BINARY: writeBinary(cell.binary, r, i, xf); break;
case FILE: writeFile(cell.path, r, i, xf); break;
case INPUT_STREAM: writeStream(cell.isv, r, i, xf); break;
case BYTE_BUFFER: writeBinary(cell.byteBuffer, r, i, xf); break;
case BLANK:
case EMPTY_TAG: writeNull(r, i, xf); break;
default:
}
}
bw.write("</row>");
}
})).writeTo(Paths.get("d://tree style.xlsx"));
}
@TreeStyle
public static class TreeNode {
@ExcelColumn
String name;
@ExcelColumn
double score; // <- root节点表示平均成绩
@TreeLevel // <- 层级
int level;
public TreeNode() { }
public TreeNode(String name, double score) {
this.name = name;
this.score = score;
}
List<TreeNode> children;
}
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public static @interface TreeStyle { }
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public static @interface TreeLevel {}
还有那种财务报表之类的,能不能加入模板导出,感觉写样式合并之类的太过于麻烦
方便的话你可以将类似的模板和Java实体发我一份,点右上角头像可以查看邮箱地址。
发送到大佬邮箱了,希望能看到
已收
模板表格好做,代码调样式不好调
feature/template分支临时提交了一版,使用你的模板自测可用,急用的话可以拉取该分支自用,有问题再反馈。目前只适用你的示例模板远达不到可以发版的程度
new Workbook()
.addSheet(new TemplateSheet(testResourceRoot().resolve("template2.xlsx"))
.setData(YzEntity.mock()) // 绑定对象
.setData("YzEntity", YzOrderEntity.randomData()) // 绑定数组对象到YzEntity命名空间
).writeTo(Paths.get("./模板测试.xlsx"));
效果
模板工作表正在开发中,会新增一个TemplateSheet以支持模板,开发分支 feature/template
测试示例
@Test public void testSimpleTemplate() throws IOException {
new Workbook()
.addSheet(new TemplateSheet("模板 1.xlsx", Paths.get("template/1.xlsx"))) // <- 模板工作表
.addSheet(new ListSheet<>("普通工作表",Item.randomTestData())) // <- 普通工作表
.addSheet(new TemplateSheet("模板 fracture merged.xlsx", Paths.get("template/fracture.xlsx"))) // <- 模板工作表
.writeTo(Paths.get("模板excel.xlsx"));
}
万能通用版的不好做,大佬已经很厉害了,崇拜
登录 后才可以发表评论