Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请教如何设置超链接? #371

Open
FudanSE-Nick opened this issue Mar 7, 2024 · 6 comments
Open

请教如何设置超链接? #371

FudanSE-Nick opened this issue Mar 7, 2024 · 6 comments
Labels

Comments

@FudanSE-Nick
Copy link

你好,请问如何对某个单元格的值设置超链接?没有找到生成excel时配置Hyperlink的地方。

@wangguanquan
Copy link
Owner

wangguanquan commented Mar 7, 2024 via email

@wangguanquan
Copy link
Owner

自定义的话有点麻烦,如果不急用的话可以等待下一个版本,需要急用的话可以参照如下方式扩展

  1. 新建一个扩展目录eec.ext(非必须)
  2. 新建一个自定义注解Hyperlink(非必须)
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Hyperlink { }
  1. 新建ListSheet扩展类MyListSheet用来解析Hyperlink 注解
public class MyListSheet<T> extends ListSheet<T> {
    // 看情况覆写父类的Constructor
    public MyListSheet(List<T> data) {
        super(data);
    }

    @Override
    protected EntryColumn createColumn(AccessibleObject ao) {
        EntryColumn column = super.createColumn(ao);
        // 解析Hyperlink,只需要简单的设置一个标记位即可,标记该列为超链接
        Hyperlink Hyperlink = ao.getAnnotation(Hyperlink.class);
        if (Hyperlink != null) column.getTail().option |= 1 << 16;
        return column;
    }
}
  1. 内置Relationship设计有缺陷无法支持超链接,需要重写
public class Relationship extends org.ttzero.excel.entity.Relationship {
    private String targetMode,target,type,id;

    public Relationship(String target, String type, String targetMode) {
        super(target, type);
        this.target = target;
        this.type = type;
        this.targetMode = targetMode;
    }
}
  1. 新建XMLWorksheetWriter扩展类MyXMLWorksheetWriter用来处理Hyperlink列
public static class MyXMLWorksheetWriter extends XMLWorksheetWriter {
    Map<String, List<String>> hyperlinkMap;

    @Override
    protected void writeString(String s, int row, int column, int xf) throws IOException {
        // 超链接
        // 这里只适应单行表头,如果有多行需要改为row > startHeaderRow + 表头行数
        if (row > startHeaderRow && (columns[column].option >> 16) == 1) {
            Relationship myRelationship = new Relationship(s, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", "External");
            org.ttzero.excel.entity.Relationship relationship = sheet.getRelManager().add(myRelationship);
            myRelationship.id = relationship.getId();
            if (hyperlinkMap == null) hyperlinkMap = new HashMap<>();
            List<String> dim = hyperlinkMap.computeIfAbsent(relationship.getId(), k -> new ArrayList<>());
            dim.add(new String(int2Col(column + 1)) + row);

            // 添加超链接的样式
            int style = styles.getStyleByIndex(xf);
            Font font = styles.getFont(style).clone();
            font.setStyle(0).underLine(); // 先清除样式的其它附加属性
            font.setColor(ColorIndex.themeColors[10]); // 设置超链接颜色
            xf = styles.of(styles.modifyFont(style, font));
        }
        super.writeString(s, row, column, xf);
    }

    @Override
    protected void afterSheetData() throws IOException {
        super.afterSheetData();
        // 添加超链接
        if (hyperlinkMap != null) {
            bw.write("<hyperlinks>");
            for (Map.Entry<String, List<String>> entry : hyperlinkMap.entrySet()) {
                for (String dim : entry.getValue()) {
                    bw.write("<hyperlink ref=\"");
                    bw.write(dim);
                    bw.write("\" r:id=\"");
                    bw.write(entry.getKey());
                    bw.write("\"/>");
                }
            }
            bw.write("</hyperlinks>");
        }
    }
}

@wangguanquan
Copy link
Owner

测试代码

@Test public void hyperlinkTest() throws IOException {
    List<Item> list = new ArrayList<>();
    list.add(new Item("京东", "https://www.jd.com"));
    list.add(new Item("天猫", "https://www.tmall.com"));
    list.add(new Item("淘宝", "https://www.taobao.com"));

    new Workbook().addSheet(new MyListSheet<>(list).setSheetWriter(new MyXMLWorksheetWriter())).writeTo(Paths.get("./超连接测试.xlsx"));
}

@FudanSE-Nick
Copy link
Author

非常感谢!

另,请问如何在同一个sheet中,拼接两个List 的字段。 在同一行中展示数据呢?

@wangguanquan
Copy link
Owner

暂时不支持,只能在外部拼接好,模板工作表TemplateSheet开发好后可以使用模板。

暂时的话可以只能在对象中拼接,你可以定义一个对象,包含2个数组,在新对象中对值进行拼接

@ExcelColumn
public String join() {
return list1.get(0).getNmae() + list2.get(0).getNum();
}

@wangguanquan
Copy link
Owner

v0.5.14支持超设置超链接且新增模板文件导出,拼接两个List 的字段应该可以使用模板来实现

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants