将 XLSM 转换为 XLSX

Posted

技术标签:

【中文标题】将 XLSM 转换为 XLSX【英文标题】:Convert XLSM to XLSX 【发布时间】:2012-06-24 06:06:49 【问题描述】:

我正在使用 EPPLUS 库从 Excel 中读取数据以创建另一个文件。不幸的是,它不支持 .XLSM 扩展文件。有没有一种很好的方法可以将 .XLSM 文件转换为 .XLSX 文件,以便使用 EPPLUS 读取文件?

(使用 EPPLUS 阅读会很好,因为我所有的代码都已经使用它编写了:))

【问题讨论】:

看起来不可能(还):epplus.codeplex.com/discussions/282220 澄清一下,不是问我是否可以使用 EPPlus 来读取文件。询问是否有任何方法/api/其他东西可以用来将 xlsm 文件转换为 xlsx,以便我可以使用 EPPlus 读取它 【参考方案1】:

为此,您需要使用Open XML SDK 2.0。以下是我尝试时对我有用的 sn-p 代码:

byte[] byteArray = File.ReadAllBytes("C:\\temp\\test.xlsm");
using (MemoryStream stream = new MemoryStream())

    stream.Write(byteArray, 0, (int)byteArray.Length);
    using (SpreadsheetDocument spreadsheetDoc = SpreadsheetDocument.Open(stream, true))
    
       // Change from template type to workbook type
       spreadsheetDoc.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
    
    File.WriteAllBytes("C:\\temp\\test.xlsx", stream.ToArray()); 

此代码的作用是获取启用宏的工作簿文件并将其打开到SpreadsheetDocument 对象中。该对象的类型是MacroEnabledWorkbook,但由于您希望它为Workbook,您调用ChangeDocumentType 方法将其从MacroEnabledWorkbook 更改为Workbook。这将起作用,因为 .xlsm 和 .xlsx 文件之间的底层 XML 是相同的。

【讨论】:

抱歉,我知道这是一篇旧帖子,但我似乎无法让它发挥作用。我能够获取输出文件(xlsx),但无法在 excel 中打开该文件。 "该文件是无宏文件,但包含启用宏的内容。" 我们如何使用相同的东西将 xls 转换为 xlsm,我收到错误“文件损坏”。 我不认为你可以,因为 xls 是办公室过去使用的旧格式 只是为像我一样迷路的人详细说明一下,我们需要添加这两个:using DocumentFormat.OpenXml.Packaging;using DocumentFormat.OpenXml; 似乎对我不起作用。我收到一条错误消息,指出文件“...是一个无宏文件,但包含启用宏的内容。”转换后没有数据显示,只有灰色背景。【参考方案2】:

使用Open XML SDK,就像在阿穆拉的回答中一样,但是 除了更改文档类型外,还应删除 VbaDataPart 和 VbaProjectPart,否则 Excel 将显示错误文件已损坏。

using (var inputStream = File.OpenRead("C:\\temp\\test.xlsm"))
using (var outStream = new MemoryStream()) 
    inputStream.CopyTo(outStream);
    using (var doc = SpreadsheetDocument.Open(outStream, true)) 
        doc.DeletePartsRecursivelyOfType<VbaDataPart>();
        doc.DeletePartsRecursivelyOfType<VbaProjectPart>();
        doc.ChangeDocumentType(DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook);
    
    File.WriteAllBytes("C:\\temp\\test.xlsx", outStream.ToArray());

【讨论】:

【参考方案3】:
package xlsbtoxlsx;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Pattern;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbookType;

public class XlsbToXlsxConvertor 

    public static void main(String[] args) throws Exception 
        
        String inputpath="C:\\Excel Data Files\\XLSB\\CSD_TDR_20200823";
        String outputpath="C:\\Excel Data Files\\XLSB\\output";
        
       new XlsbToXlsxConvertor().xlsmToxlsxFileConvertor(inputpath, outputpath);
    

    public void xlsmToxlsxFileConvertor(String inputpath, String outputpath) throws Exception 
        XSSFWorkbook workbook;
        FileOutputStream out;
        System.out.println("inputpath  " + inputpath);
        File directoryPath = new File(inputpath);
        // List of all files and directories
        String contents[] = directoryPath.list();
        System.out.println("List of files and directories in the specified directory:");
        for (int i = 0; i < contents.length; i++) 
            System.out.println(contents[i]);
            // create workbook from XLSM template
            workbook = (XSSFWorkbook) WorkbookFactory
                    .create(new FileInputStream(inputpath + File.separator + contents[i]));
            // save copy as XLSX ----------------START
            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);

            // write out the XLSX

            out = new FileOutputStream(outputpath + File.separator + contents[i].replace(".xlsm", "") + ".xlsx");
            workbook.write(out);
            out.close();
            System.out.println("done");
            workbook.close();
        
    


【讨论】:

以上是关于将 XLSM 转换为 XLSX的主要内容,如果未能解决你的问题,请参考以下文章

XLSX格式文件自动变成XLSM?

使用 VBA 将包含 Excel 文件 (.xlsm) 的宏保存为不包含宏的文件 (.xlsx) 时抑制对话框

保存时将 .xlsm 的副本创建为 .xlsx

将新工作表添加到XLSM宏Excel文件时出错

后缀为xlsm的文件打开密码忘记了,怎么样解锁

Python将csv转换为xlsx