我在Java应用程序中具有Excel报表生成功能。
我终于用以下代码成功地将超链接添加到图片中。
buildHyperLinksMenu 是设置超链接的主要功能
createHyperLinkWithUri 是创建Uri超链接的子函数
public void buildHyperLinksMenu(String linkName, XSSFSheet sheet, String tabLinked, String referencedCell) {
List<XSSFShape> shapes = sheet.getDrawingPatriarch().getShapes();
Iterator<XSSFShape> elementsIterator = shapes.iterator();
while (elementsIterator.hasNext()) {
XSSFShape shape = elementsIterator.next();
if (shape instanceof XSSFPicture) {
CTPicture ctPicture = ((XSSFPicture) shape).getCTPicture();
CTPictureNonVisual ctpicturenonvisual = ctPicture.getNvPicPr();
CTNonVisualDrawingProps ctnonvisualdrawingprops = ctpicturenonvisual.getCNvPr();
String finalname = ctnonvisualdrawingprops.getName();
//HomeLink is the name of the picture assigned in the sheet to
//the image when uploading the Excel template
if (finalname.equals("HomeLink")) {
CTHyperlink link = createHyperLinkWithUri(linkName, sheet, tabLinked, referencedCell);
((XSSFPicture) shape).getCTPicture().getNvPicPr().getCNvPr().setHlinkClick(link);
}
}
}
}
private CTHyperlink createHyperLinkWithUri(String linkName, XSSFSheet sheet, String tabLinked, String referencedCell) {
CTHyperlink link = CTHyperlink.Factory.newInstance();
try {
String hyperlinkAddress = sheet.getPackagePart().getPartName() + "/#'" + tabLinked + "'!" + referencedCell + "";
URI uri = new URI(null, null, hyperlinkAddress, null, null);
sheet.getDrawingPatriarch().getPackagePart().addRelationship(uri, TargetMode.INTERNAL, XSSFRelation.SHEET_HYPERLINKS.getRelation());
String relationshipId = null;
PackageRelationshipCollection prc = sheet.getDrawingPatriarch().getPackagePart().getRelationships();
for (PackageRelationship pr : prc) {
URI targetURI = pr.getTargetURI();
String target = targetURI.getPath();
if (target.equals(hyperlinkAddress)) {
relationshipId = pr.getId();
break;
}
}
CTHyperlink hyperlink = CTHyperlink.Factory.newInstance();
// Set ID of hyperlink to be the same as Relationship ID
hyperlink.setId(relationshipId);
return hyperlink;
} catch (URISyntaxException | InvalidFormatException e) {
return link;
}
}
现在的问题是,生成后,excel(打开时)将提示“内容不可读”消息,并且未添加超链接。
我想了解这是我丢失的一段代码的问题还是更令人讨厌的问题,例如库的版本等。
我确认if (finalname.equals("HomeLink"))
一次也只有一次满足。
这是一个简单的函数,用于在输出中写入文件:
protected byte[] workbookToByteArray(XSSFWorkbook workbook) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
workbook.write(byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
谢谢
Davide
UDPATE
我生成了一个带有或不带有添加HyperLink(基本上是上面的代码)功能的Excel文档。
损坏的Excel表示文件xl \ drawings \ drawing4.xml是损坏的文件。 因此,我将这两个优点,解压缩并比较了xml文件。两者之间的唯一区别是:
更正文件
<a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="rId2">
vs
文件错误
<a:blip r:embed="rId2">
这种差异多次以类似的方式发生。很多别的
UDPATE
似乎是造成问题的那一行是在将关系添加到包中时
sheet.getDrawingPatriarch().getPackagePart().addRelationship(uri, TargetMode.INTERNAL, XSSFRelation.SHEET_HYPERLINKS.getRelation());
解决方案代码
public void buildHyperLinksMenu(String linkName, XSSFSheet sheet, String tabLinked, String referencedCell) {
List<XSSFShape> shapes = sheet.getDrawingPatriarch().getShapes();
Iterator<XSSFShape> elementsIterator = shapes.iterator();
while (elementsIterator.hasNext()) {
XSSFShape shape = elementsIterator.next();
if (shape instanceof XSSFPicture) {
CTPicture ctPicture = ((XSSFPicture) shape).getCTPicture();
CTPictureNonVisual ctpicturenonvisual = ctPicture.getNvPicPr();
CTNonVisualDrawingProps ctnonvisualdrawingprops = ctpicturenonvisual.getCNvPr();
String finalname = ctnonvisualdrawingprops.getName();
if (finalname.equals("HomeLink")) {
CTHyperlink link = createHyperLinkWithUri(linkName, sheet, tabLinked, referencedCell);
((XSSFPicture) shape).getCTPicture().getNvPicPr().getCNvPr().setHlinkClick(link);
}
}
}
}
private CTHyperlink createHyperLinkWithUri(String linkName, XSSFSheet sheet, String tabLinked, String referencedCell) {
CTHyperlink link = CTHyperlink.Factory.newInstance();
try {
CTHyperlink hyperlink = CTHyperlink.Factory.newInstance();
String hyperlinkAddress = "#'" + tabLinked + "'!" + referencedCell + "";
sheet.getDrawingPatriarch().getPackagePart().addExternalRelationship(hyperlinkAddress, PackageRelationshipTypes.HYPERLINK_PART);
String relationshipId = null;
PackageRelationshipCollection prc = sheet.getDrawingPatriarch().getPackagePart().getRelationships();
for (PackageRelationship pr : prc) {
String targetURI = pr.getTargetURI().toString();
if (targetURI.equals(hyperlinkAddress)) {
relationshipId = pr.getId();
break;
}
}
// Set ID of hyperlink to be the same as Relationship ID
hyperlink.setId(relationshipId);
return hyperlink;
} catch (InvalidFormatException e) {
return link;
}
}