[英]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.