[英]Apache poi : setting custom properties at worksheet level using apache poi
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("D://New Microsoft Excel Worksheet.xlsx"));
XSSFWorkbook wb = new XSSFWorkbook(file);
XSSFSheet sheet = wb.createSheet("newsheet5");
CTWorksheet ctSheet = sheet.getCTWorksheet();
CTCustomProperties props = ctSheet.addNewCustomProperties();
props.addNewCustomPr().setId("APACHE POI");
props.addNewCustomPr().setName("Tender no = 48");
props.addNewCustomPr().setId("APACHE POI 2");
props.addNewCustomPr().setName("tender no = 58");
ctSheet.setCustomProperties(props);
FileOutputStream out = new FileOutputStream("D://New Microsoft Excel Worksheet.xlsx");
wb.write(out);
out.close();
wb.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Xlsx 文件在工作表级别写入自定义属性后损坏。
我收到一条错误消息,因为“excel 无法打开文件,因为文件格式或文件扩展名无效。 尝试打开 excel 文件时,验证文件没有损坏并且文件扩展名与文件格式匹配。
工作表自定义属性仅可使用VBA
使用。 它们存储在Excel
文件中,但值在二进制文档部分customProperty1.bin
, customProperty2.bin
,...这不是apache poi
提供的访问权限。
使用XSSF
需要创建二进制文档部分,然后获取到该二进制文档部分的关系 ID。 然后设置CTCustomProperties
- CTCustomProperty
。 那里的 Id 指向包含值的二进制文档部分,名称是属性名称。
以下完整示例显示了这一点。 它使用当前的apache poi 4.1.2
进行测试和工作。 它需要ooxml-schemas-1.4.jar
位于 class 路径中,因为默认poi-ooxml-schemas-4.1.2.jar
CT*
CTclasses 不包含所有需要的低级别。
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import java.nio.charset.StandardCharsets;
class CreateExcelSheetCustomProperties {
static void setSheetCustomProperty(XSSFSheet sheet, String customPropertyName, String customPropertyValue) throws Exception {
OPCPackage opcpackage = sheet.getWorkbook().getPackage();
int i = opcpackage.getUnusedPartIndex("/customProperty#.bin");
PackagePartName partname = PackagingURIHelper.createPartName("/customProperty" + i + ".bin");
PackagePart part = opcpackage.createPart(partname, "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty");
POIXMLDocumentPart customProperty = new POIXMLDocumentPart(part) {
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
try {
out.write(customPropertyValue.getBytes(StandardCharsets.UTF_16LE));
out.close();
} catch (Exception ex) {
ex.printStackTrace();
};
}
};
String rId = sheet.addRelation(null, XSSFRelation.CUSTOM_PROPERTIES, customProperty).getRelationship().getId();
CTWorksheet ctSheet = sheet.getCTWorksheet();
CTCustomProperties props = ctSheet.getCustomProperties();
if (props == null) props = ctSheet.addNewCustomProperties();
CTCustomProperty prop = props.addNewCustomPr();
prop.setId(rId);
prop.setName(customPropertyName);
}
public static void main(String[] args) throws Exception {
try (XSSFWorkbook workbook = new XSSFWorkbook();
FileOutputStream fileout = new FileOutputStream("./Excel.xlsx") ) {
XSSFSheet sheet = workbook.createSheet();
setSheetCustomProperty(sheet, "APACHE POI", "Tender no = 48");
setSheetCustomProperty(sheet, "APACHE POI 2", "tender no = 58");
workbook.write(fileout);
}
}
}
我一直在为同样的问题而苦苦挣扎,并找到了一种使它起作用的方法,但这远非最佳。 无论如何,希望你或其他人能想出一个更好的方法。
package temp.temp;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCustomProperties;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCustomProperty;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
public class Temp2 {
public static void main(String[] args) {
File inputFile = new File("C:\\myspreadsheet.xlsx");
try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(inputFile))) {
XSSFWorkbook wb = new XSSFWorkbook(fis);
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
XSSFSheet sheet = wb.getSheetAt(i);
System.out.println("\nSheetName=" + sheet.getSheetName());
CTWorksheet ctSheet = sheet.getCTWorksheet();
CTCustomProperties props = ctSheet.getCustomProperties();
if (props != null) {
List<CTCustomProperty> propList = props.getCustomPrList();
propList.stream().forEach((prop) -> {
POIXMLDocumentPart rel = sheet.getRelationById(prop.getId());
if (rel != null) {
try (InputStream inp = rel.getPackagePart().getInputStream()) {
byte[] inBytes = inp.readAllBytes();
// By experimentation, byte array has two bytes per character with least
// significant in first byte which is UTF-16LE encoding. Don't know why!
String value = new String(inBytes, "UTF-16LE");
System.out.println(" " + prop.getName() + "=" + value);
} catch (IOException ioe) {
//Error
}
}
});
}
}
wb.close();
} catch (Exception e) {
System.out.println(e);
}
System.out.println("End");
}
}
请注意,CTWorksheet 来自 poi-ooxml-schemas-xx.jar 和 CustomProperties 来自 ooxml-schemas-yy.jar,因此两者都必须在类路径中。 如果您正在使用模块(就像我一样),这会带来很大的问题! 祝你好运
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.