Efficient Large-Scale Data Export to Excel in Java

Backend Implementation:

1. Maven Dependencies

<!-- EasyExcel for data export -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.2</version>
</dependency>

2. Configuration Package

Create a config folder and add an ExcelExporter class. Replace the entity class with your own data model:

package com.cloud.config;

import com.cloud.domain.StockData;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;
import java.util.List;

@Slf4j
public class ExcelExporter {

    public static void generateExcelReport(List<StockData> dataItems) {
        // Starting row index
        int currentRow = 0;
        // Sheet counter
        int sheetNumber = 1;

        // Create workbook with streaming support
        SXSSFWorkbook spreadsheet = new SXSSFWorkbook();
        // Get the first sheet
        Sheet dataSheet = spreadsheet.createSheet("Data_" + sheetNumber);

        // Create header row
        Row titleRow = dataSheet.createRow(0);

        titleRow.createCell(1).setCellValue("ID");
        titleRow.createCell(2).setCellValue("Symbol");
        titleRow.createCell(3).setCellValue("Name");
        titleRow.createCell(4).setCellValue("Exchange");
        titleRow.createCell(5).setCellValue("Sector");
        titleRow.createCell(6).setCellValue("Industry");
        titleRow.createCell(7).setCellValue("Country");
        titleRow.createCell(8).setCellValue("Currency");
        titleRow.createCell(9).setCellValue("Listing Date");

        // Populate data
        for (StockData item : dataItems) {
            if (currentRow >= 1048575) {
                sheetNumber++;
                dataSheet = spreadsheet.createSheet("Data_" + sheetNumber);
                currentRow = 0;
                
                // Recreate headers for new sheet
                titleRow = dataSheet.createRow(0);
                titleRow.createCell(1).setCellValue("ID");
                titleRow.createCell(2).setCellValue("Symbol");
                titleRow.createCell(3).setCellValue("Name");
                titleRow.createCell(4).setCellValue("Exchange");
                titleRow.createCell(5).setCellValue("Sector");
                titleRow.createCell(6).setCellValue("Industry");
                titleRow.createCell(7).setCellValue("Country");
                titleRow.createCell(8).setCellValue("Currency");
                titleRow.createCell(9).setCellValue("Listing Date");
            }
            
            Row dataRow = dataSheet.createRow(++currentRow);
            dataRow.createCell(1).setCellValue(item.getId());
            dataRow.createCell(2).setCellValue(item.getSymbol());
            dataRow.createCell(3).setCellValue(item.getName());
            dataRow.createCell(4).setCellValue(item.getExchange());
            dataRow.createCell(5).setCellValue(item.getSector());
            dataRow.createCell(6).setCellValue(item.getIndustry());
            dataRow.createCell(7).setCellValue(item.getCountry());
            dataRow.createCell(8).setCellValue(item.getCurrency());
            dataRow.createCell(9).setCellValue(item.getListingDate());
        }
        
        // Define output path
        String outputPath = "D:\\reports\\large_dataset.xlsx";

        // Write to file
        try (FileOutputStream fileOut = new FileOutputStream(outputPath)) {
            spreadsheet.write(fileOut);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Export error: ", e);
        }
        // Clean up resources
        spreadsheet.dispose();
    }
}

3. Controller Implementation

Add the fololwing method to your controller for handling large dataset exports using multithreading:

// Large dataset export endpoint
@GetMapping("/export-large-dataset")
public void handleLargeDatasetExport() {
    // Using WorkStealingPool for IO-intensive operations (2n+1 cores)
    ExecutorService threadPool = Executors.newWorkStealingPool(17);
    try {
        // Submit task to thread pool
        Future<?> taskResult = threadPool.submit(() -> {
            List<StockData> combinedData = new ArrayList<>();
            
            // Fetch data in batches
            List<StockData> batchOne = stockDataService.fetchBatchOne();
            List<StockData> batchTwo = stockDataService.fetchBatchTwo();
            List<StockData> batchThree = stockDataService.fetchBatchThree();
            
            // Combine all batches
            if (batchOne != null) combinedData.addAll(batchOne);
            if (batchTwo != null) combinedData.addAll(batchTwo);
            if (batchThree != null) combinedData.addAll(batchThree);
            
            // Generate Excel report
            ExcelExporter.generateExcelReport(combinedData);
        });
        
        // Wait for completion
        taskResult.get();
    } catch (Exception e) {
        e.printStackTrace();
        log.error("Export process error: ", e);
    } finally {
        // Shutdown thread pool
        threadPool.shutdown();
    }
}

4. Pagination SQL for Large Datasest

When dealing with millions of records, implement pagination in your SQL queries:

-- MySQL pagination
SELECT * FROM stock_data 
LIMIT 100000 OFFSET 0;

-- Oracle pagination
SELECT * FROM (
    SELECT a.*, ROWNUM rn FROM (
        SELECT * FROM stock_data ORDER BY id
    ) a WHERE ROWNUM <= 100000
) WHERE rn > 0;

-- PostgreSQL pagination
SELECT * FROM stock_data 
LIMIT 100000 OFFSET 0;

5. Annotations for Standard Excel Export

For regular Excel exports, add these annotations to your entity class fields:

@ExcelProperty("ID")
private Long id;

@ExcelProperty("Symbol")
private String symbol;

@ExcelProperty("Name")
private String name;

@ExcelProperty("Exchange")
private String exchange;

@ExcelProperty("Sector")
private String sector;

@ExcelProperty("Industry")
private String industry;

@ExcelProperty("Country")
private String country;

@ExcelProperty("Currency")
private String currency;

@ExcelProperty("Listing Date")
private String listingDate;

Tags: java EasyExcel ApachePOI DataExport multithreading

Posted on Wed, 15 Jul 2026 17:02:59 +0000 by kra