5

I'm using the EPPLUS library to read data from Excel to create another file. Unfortunately it does not support the .XLSM extension file. Is there a nice way to convert .XLSM files to .XLSX file for the purpose of reading the file with EPPLUS?

(using EPPLUS for reading would be nice because all my code is already written using it :) )

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
user1167650
  • 3,177
  • 11
  • 34
  • 46
  • looks like it's not possible (yet): https://epplus.codeplex.com/discussions/282220 – SeanC Jun 25 '12 at 14:27
  • To clarify, not asking if I can use EPPlus to read the file. Asking if there are any methods / api's / other things I can use to convert an xlsm file to xlsx so that I can read it using EPPlus – user1167650 Jun 25 '12 at 22:03

3 Answers3

10

In order to do this you will need to use the Open XML SDK 2.0. Below is a snippet of code that worked for me when I tried it:

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()); 
}

What this code does is it takes your macro enabled workbook file and opens it into a SpreadsheetDocument object. The type of this object is MacroEnabledWorkbook, but since you want it as a Workbook you call the ChangeDocumentType method to change it from a MacroEnabledWorkbook to a Workbook. This will work since the underlying XML is the same between a .xlsm and a .xlsx file.

amurra
  • 15,221
  • 4
  • 70
  • 87
  • sorry, I know this is a old post, but I can't seem to get this to work. I was able to get the output file (xlsx), but was not able to open the file in excel. "The file is a macro-free file, but contains macro-enable content." – sora0419 Mar 11 '14 at 15:12
  • how we can convert xls to xlsm using same stuff, I got an error "File with corruption". – Razack Aug 19 '14 at 09:39
  • I don't think you can since xls is the old format office used to use – amurra Aug 19 '14 at 15:21
  • Just to detail a bit for people who were lost like I was, we need to add both those: `using DocumentFormat.OpenXml.Packaging;` `using DocumentFormat.OpenXml;` – Carol Mar 04 '15 at 22:56
  • Doesn't seem to work for me. I'm getting an error that says the file "...is a macro-free file, but contains macro-enabled content." No data displays after the conversion, just a gray background. – midoriha_senpai Jan 15 '18 at 21:31
  • please go through the link,(https://stackoverflow.com/questions/54124371/cannot-run-the-macro-from-ssis) as I received the similar error message when used the above one – Smart003 Jan 10 '19 at 09:33
4

Using the Open XML SDK, like in amurra's answer, but in addition to changing doc type, VbaDataPart and VbaProjectPart should be removed, otherwise Excel will show error a file is corrupted.

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());
}
eren
  • 708
  • 8
  • 20
lekrus
  • 41
  • 3
0
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();
        }
    }

}
Govind Sharma
  • 127
  • 1
  • 4