Poi:从 xlsm 打开后将 excel 文件另存为 xlsx
Poi: Saving an excel file as xlsx after opening it from xlsm
我正在编写一个 java 程序,它打开一个用户定义的 excel 文件,用数据填充它,然后将它保存在用户指定的路径、文件名和扩展名下。应该可以,但不可能将输出声明为 xlsx,即使输入文件是 xlsm。如果我尝试使用下面的代码,打开文件会出现错误:
The file 'FileName.xlsx' is a macro-free file, but contains
macro-enabled content
关键代码段:
打开工作簿:
try (Workbook workbook = WorkbookFactory.create( new FileInputStream( templateFile ) )) {
// ...processing the file here,
// including a call of stripMacros, c.f. below
} catch ( IOException | EncryptedDocumentException | InvalidFormatException ex ) {
throw new TemplateNotFoundException( "Template not found. Please check property templatePath: " + templateFile, ex );
}
正在将工作簿设置为正确的类型:
private Workbook stripMacros( final Workbook wb, final String outputFormat ) {
Workbook workbook = wb;
if ( "xlsx".equals( outputFormat ) && ( workbook.getClass() == XSSFWorkbook.class ) ) {
XSSFWorkbook wbx = (XSSFWorkbook) workbook;
wbx.setWorkbookType( XSSFWorkbookType.valueOf( "XLSX" ) );
return wbx;
} else if ( "xlsm".equals( outputFormat ) && ( workbook.getClass() == XSSFWorkbook.class ) ) {
XSSFWorkbook wbm = (XSSFWorkbook) workbook;
wbm.setWorkbookType( XSSFWorkbookType.valueOf( "XLSM" ) );
return wbm;
} else {
return wb;
}
}
正在保存工作簿:
File outFile = new File( destinationPath, fileName + "." + outputFormat );
outFile.getParentFile().mkdirs();
if ( workbook != null ) {
try {
workbook.write( new FileOutputStream( outFile ) );
workbook.close();
} catch ( IOException ex ) {
throw new FileInaccessibleException( "Workbook could not be saved. Please check if the workbook under " + destinationPath + fileName + "." + outputFormat + " is not open in any program.", ex );
}
}
我需要添加什么才能正确打开我的文件?我是否需要手动删除宏,如果需要,如何删除?
设置 WorkbookType
仅更改内容类型,但不会从 XLSM
文件内容中删除 VBA
项目。
以下代码通过从包中获取和删除 vbaProject.bin 部分来完成此操作。此外,它还会从包中获取并删除与已删除 vbaProject.bin 部分的关系。
在此之后,新的 XLSX
文件不再包含 VBA
代码。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.regex.Pattern;
class ReadXSLMWriteXLSXWorkbook {
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("Workbook.xlsm"));
OPCPackage opcpackage = workbook.getPackage();
//get and remove the vbaProject.bin part from the package
PackagePart vbapart = opcpackage.getPartsByName(Pattern.compile("/xl/vbaProject.bin")).get(0);
opcpackage.removePart(vbapart);
//get and remove the relationship to the removed vbaProject.bin part from the package
PackagePart wbpart = workbook.getPackagePart();
PackageRelationshipCollection wbrelcollection = wbpart.getRelationshipsByType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
for (PackageRelationship relship : wbrelcollection) {
wbpart.removeRelationship(relship.getId());
}
//set content type to XLSX
workbook.setWorkbookType(XSSFWorkbookType.XLSX);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
if (row == null) row = sheet.createRow(0);
Cell cell = row.getCell(0);
if (cell == null) cell = row.createCell(0);
cell.setCellValue("changed");
workbook.write(new FileOutputStream("Workbook.xlsx"));
workbook.close();
}
}
我正在编写一个 java 程序,它打开一个用户定义的 excel 文件,用数据填充它,然后将它保存在用户指定的路径、文件名和扩展名下。应该可以,但不可能将输出声明为 xlsx,即使输入文件是 xlsm。如果我尝试使用下面的代码,打开文件会出现错误:
The file 'FileName.xlsx' is a macro-free file, but contains macro-enabled content
关键代码段:
打开工作簿:
try (Workbook workbook = WorkbookFactory.create( new FileInputStream( templateFile ) )) {
// ...processing the file here,
// including a call of stripMacros, c.f. below
} catch ( IOException | EncryptedDocumentException | InvalidFormatException ex ) {
throw new TemplateNotFoundException( "Template not found. Please check property templatePath: " + templateFile, ex );
}
正在将工作簿设置为正确的类型:
private Workbook stripMacros( final Workbook wb, final String outputFormat ) {
Workbook workbook = wb;
if ( "xlsx".equals( outputFormat ) && ( workbook.getClass() == XSSFWorkbook.class ) ) {
XSSFWorkbook wbx = (XSSFWorkbook) workbook;
wbx.setWorkbookType( XSSFWorkbookType.valueOf( "XLSX" ) );
return wbx;
} else if ( "xlsm".equals( outputFormat ) && ( workbook.getClass() == XSSFWorkbook.class ) ) {
XSSFWorkbook wbm = (XSSFWorkbook) workbook;
wbm.setWorkbookType( XSSFWorkbookType.valueOf( "XLSM" ) );
return wbm;
} else {
return wb;
}
}
正在保存工作簿:
File outFile = new File( destinationPath, fileName + "." + outputFormat );
outFile.getParentFile().mkdirs();
if ( workbook != null ) {
try {
workbook.write( new FileOutputStream( outFile ) );
workbook.close();
} catch ( IOException ex ) {
throw new FileInaccessibleException( "Workbook could not be saved. Please check if the workbook under " + destinationPath + fileName + "." + outputFormat + " is not open in any program.", ex );
}
}
我需要添加什么才能正确打开我的文件?我是否需要手动删除宏,如果需要,如何删除?
设置 WorkbookType
仅更改内容类型,但不会从 XLSM
文件内容中删除 VBA
项目。
以下代码通过从包中获取和删除 vbaProject.bin 部分来完成此操作。此外,它还会从包中获取并删除与已删除 vbaProject.bin 部分的关系。
在此之后,新的 XLSX
文件不再包含 VBA
代码。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.regex.Pattern;
class ReadXSLMWriteXLSXWorkbook {
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("Workbook.xlsm"));
OPCPackage opcpackage = workbook.getPackage();
//get and remove the vbaProject.bin part from the package
PackagePart vbapart = opcpackage.getPartsByName(Pattern.compile("/xl/vbaProject.bin")).get(0);
opcpackage.removePart(vbapart);
//get and remove the relationship to the removed vbaProject.bin part from the package
PackagePart wbpart = workbook.getPackagePart();
PackageRelationshipCollection wbrelcollection = wbpart.getRelationshipsByType("http://schemas.microsoft.com/office/2006/relationships/vbaProject");
for (PackageRelationship relship : wbrelcollection) {
wbpart.removeRelationship(relship.getId());
}
//set content type to XLSX
workbook.setWorkbookType(XSSFWorkbookType.XLSX);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
if (row == null) row = sheet.createRow(0);
Cell cell = row.getCell(0);
if (cell == null) cell = row.createCell(0);
cell.setCellValue("changed");
workbook.write(new FileOutputStream("Workbook.xlsx"));
workbook.close();
}
}