Microsoft Excel supports two primary formats for storing spreadsheets: XLS (the older binary format used in Excel 97-2003) and XLSX (the newer XML-based format introduced in Excel 2007). As more applications and APIs move toward supporting modern formats, converting legacy XLS files to XLSX has become a common requirement in enterprise Java applications.

In this article, we will walk through how to convert .xls to .xlsx in Java using Apache POI, a robust open-source library for working with Microsoft Office documents. We’ll include coding examples and cover best practices for safe and reliable conversions.

Why Convert XLS to XLSX?

There are several compelling reasons to convert .xls to .xlsx in modern applications:

  • Compatibility: Newer Excel features like large row limits, data validation, and modern charting options are only available in XLSX.

  • Performance: XLSX files are generally smaller and faster to open since they are based on the Open XML format.

  • Security: XLSX supports better data encryption and validation options.

  • Deprecation of old formats: Many tools and APIs (especially cloud-based ones like Google Sheets and Microsoft Graph) are dropping support for the binary XLS format.

Introduction to Apache POI

Apache POI is the go-to Java library for working with Microsoft Office formats. It provides two key components:

  • HSSF (Horrible Spreadsheet Format) – for reading .xls files

  • XSSF (XML Spreadsheet Format) – for writing .xlsx files

To convert an XLS file to XLSX, we read it using HSSFWorkbook and write it using XSSFWorkbook.

Maven Dependency for Apache POI

To get started, add the following dependencies to your pom.xml if you’re using Maven:

xml
<dependencies>
<!-- Apache POI for XLS -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<!– Apache POI for XLSX –>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>

Make sure you use the latest version available at the time of your implementation.

Step-by-Step Code Example: Convert XLS to XLSX

Here is a complete Java program that converts an .xls file to .xlsx:

java
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;public class XlsToXlsxConverter {public static void convertXlsToXlsx(String inputFilePath, String outputFilePath) throws IOException {
// Load the XLS workbook
try (InputStream inputStream = new FileInputStream(inputFilePath);
Workbook oldWorkbook = new HSSFWorkbook(inputStream);
Workbook newWorkbook = new XSSFWorkbook()) {for (int i = 0; i < oldWorkbook.getNumberOfSheets(); i++) {
Sheet oldSheet = oldWorkbook.getSheetAt(i);
Sheet newSheet = newWorkbook.createSheet(oldSheet.getSheetName());copySheetContent(oldSheet, newSheet);
}// Write to the new XLSX file
try (OutputStream outputStream = new FileOutputStream(outputFilePath)) {
newWorkbook.write(outputStream);
System.out.println(“Successfully converted to XLSX: “ + outputFilePath);
}
}
}private static void copySheetContent(Sheet oldSheet, Sheet newSheet) {
for (int rowIndex = oldSheet.getFirstRowNum(); rowIndex <= oldSheet.getLastRowNum(); rowIndex++) {
Row oldRow = oldSheet.getRow(rowIndex);
if (oldRow != null) {
Row newRow = newSheet.createRow(rowIndex);
copyRowContent(oldRow, newRow);
}
}
}

private static void copyRowContent(Row oldRow, Row newRow) {
for (int cellIndex = oldRow.getFirstCellNum(); cellIndex < oldRow.getLastCellNum(); cellIndex++) {
Cell oldCell = oldRow.getCell(cellIndex);
if (oldCell != null) {
Cell newCell = newRow.createCell(cellIndex);
copyCellValue(oldCell, newCell);
}
}
}

private static void copyCellValue(Cell oldCell, Cell newCell) {
switch (oldCell.getCellType()) {
case STRING:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case BLANK:
newCell.setBlank();
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
default:
break;
}
}

public static void main(String[] args) {
String inputPath = “example.xls”;
String outputPath = “example_converted.xlsx”;

try {
convertXlsToXlsx(inputPath, outputPath);
} catch (IOException e) {
System.err.println(“Conversion failed: “ + e.getMessage());
}
}
}

Key Notes on the Conversion Process

  • Formula Handling: The code preserves formulas, but they might need to be re-evaluated by Excel on the first open.

  • Formatting: Apache POI doesn’t transfer all formatting properties perfectly. You might need additional code to handle cell styles and fonts if preserving appearance is important.

  • Sheet Limits: .xls supports a max of 65,536 rows and 256 columns; .xlsx supports 1,048,576 rows and 16,384 columns. This means .xls files are always safe to upgrade without truncation.

Improving The Conversion With Style Preservation

To preserve cell styles during conversion, use the following enhanced logic in copyCellValue:

java
CellStyle newCellStyle = newSheet.getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);

Be aware that too many styles can crash Excel. Apache POI has limits on the number of unique styles due to the underlying format limits.

Batch Conversion of Multiple Files

If you have a folder of .xls files to convert, use the following logic:

java
File folder = new File("xls_folder");
File[] files = folder.listFiles((dir, name) -> name.endsWith(".xls"));
if (files != null) {
for (File xlsFile : files) {
String xlsxFile = xlsFile.getAbsolutePath().replace(“.xls”, “.xlsx”);
convertXlsToXlsx(xlsFile.getAbsolutePath(), xlsxFile);
}
}

Handling Exceptions and Resource Management

Using Java’s try-with-resources ensures that all file streams are properly closed. You should also handle:

  • Invalid file format exceptions

  • Empty sheets or rows

  • File I/O errors like permission denied or disk full

Integration with Web Applications

If you’re converting files as part of a web service, consider accepting uploaded files via a Spring Boot REST endpoint:

java
@PostMapping("/convert")
public ResponseEntity<Resource> convertXls(@RequestParam("file") MultipartFile file) {
// Save, convert, and return as ResponseEntity with XLSX content
}

Don’t forget to sanitize input, restrict file size, and validate MIME types.

When Not To Use Apache POI

For very large .xls files, Apache POI’s in-memory model can cause OutOfMemoryError. In such cases, consider using:

  • Streaming API (SXSSFWorkbook) – optimized for writing large .xlsx files

  • JExcelAPI – an alternative lightweight XLS library (but it doesn’t support XLSX)

  • LibreOffice in headless mode – useful for large file batch conversions outside the JVM

Conclusion

Converting XLS to XLSX in Java using Apache POI is straightforward, reliable, and fits well within most Java applications. The process involves reading the old file with HSSFWorkbook and writing it out with XSSFWorkbook, manually copying each cell, value, and optionally styles and formulas.

This conversion is essential for maintaining compatibility with modern Excel features and cloud-based tools. By following the examples in this article, Java developers can easily build utilities or web services to batch upgrade their spreadsheet formats and future-proof their data processing workflows.

In summary:

  • Apache POI supports both .xls and .xlsx formats.

  • Proper resource management and error handling are critical for production use.

  • Optional enhancements like style copying and batch conversion provide robustness.

  • For large files, consider streaming or external tools.

With the code and best practices covered in this guide, you should be well-equipped to handle Excel format conversions in your Java projects.