CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-alibaba--easyexcel

High-performance Java library for reading and writing Excel files with minimal memory usage

Pending
Overview
Eval results
Files

exception-handling.mddocs/

Exception Handling

Comprehensive exception hierarchy for different error scenarios during Excel processing. EasyExcel provides structured exception handling that allows for specific error recovery strategies and detailed error reporting.

Capabilities

Base Exception Classes

Core exception hierarchy providing foundation for all Excel-related errors.

/**
 * Base runtime exception for all Excel operations
 */
public class ExcelRuntimeException extends RuntimeException {
    /**
     * Create exception with message
     * @param message Error message
     */
    public ExcelRuntimeException(String message);
    
    /**
     * Create exception with message and cause
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelRuntimeException(String message, Throwable cause);
    
    /**
     * Create exception with cause
     * @param cause Root cause exception
     */
    public ExcelRuntimeException(Throwable cause);
}

/**
 * Common exception for general Excel processing errors
 */
public class ExcelCommonException extends ExcelRuntimeException {
    /**
     * Create exception with message
     * @param message Error message
     */
    public ExcelCommonException(String message);
    
    /**
     * Create exception with message and cause
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelCommonException(String message, Throwable cause);
    
    /**
     * Create exception with cause
     * @param cause Root cause exception
     */
    public ExcelCommonException(Throwable cause);
}

Reading Operation Exceptions

Exceptions specific to Excel reading operations.

/**
 * Exception during Excel analysis/reading operations
 */
public class ExcelAnalysisException extends ExcelRuntimeException {
    /**
     * Create exception with message
     * @param message Error message
     */
    public ExcelAnalysisException(String message);
    
    /**
     * Create exception with message and cause
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelAnalysisException(String message, Throwable cause);
    
    /**
     * Create exception with cause
     * @param cause Root cause exception
     */
    public ExcelAnalysisException(Throwable cause);
}

/**
 * Data type conversion errors during reading
 */
public class ExcelDataConvertException extends ExcelAnalysisException {
    /**
     * Row number where error occurred
     */
    private Integer rowIndex;
    
    /**
     * Column index where error occurred
     */
    private Integer columnIndex;
    
    /**
     * Cell data that failed conversion
     */
    private ReadCellData<?> cellData;
    
    /**
     * Create exception with basic information
     * @param message Error message
     */
    public ExcelDataConvertException(String message);
    
    /**
     * Create exception with cell location information
     * @param rowIndex Row number (0-based)
     * @param columnIndex Column number (0-based)
     * @param cellData Cell data that failed conversion
     * @param message Error message
     */
    public ExcelDataConvertException(Integer rowIndex, Integer columnIndex, 
                                   ReadCellData<?> cellData, String message);
    
    /**
     * Create exception with cell location and cause
     * @param rowIndex Row number (0-based)
     * @param columnIndex Column number (0-based)
     * @param cellData Cell data that failed conversion
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelDataConvertException(Integer rowIndex, Integer columnIndex,
                                   ReadCellData<?> cellData, String message, Throwable cause);
    
    // Getters for accessing error details
    public Integer getRowIndex();
    public Integer getColumnIndex();
    public ReadCellData<?> getCellData();
}

Writing Operation Exceptions

Exceptions specific to Excel writing operations.

/**
 * Exception during Excel generation/writing operations
 */
public class ExcelGenerateException extends ExcelRuntimeException {
    /**
     * Create exception with message
     * @param message Error message
     */
    public ExcelGenerateException(String message);
    
    /**
     * Create exception with message and cause
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelGenerateException(String message, Throwable cause);
    
    /**
     * Create exception with cause
     * @param cause Root cause exception
     */
    public ExcelGenerateException(Throwable cause);
}

/**
 * Data conversion errors during writing
 */
public class ExcelWriteDataConvertException extends ExcelGenerateException {
    /**
     * Row number where error occurred
     */
    private Integer rowIndex;
    
    /**
     * Column index where error occurred
     */
    private Integer columnIndex;
    
    /**
     * Data that failed conversion
     */
    private Object data;
    
    /**
     * Create exception with basic information
     * @param message Error message
     */
    public ExcelWriteDataConvertException(String message);
    
    /**
     * Create exception with cell location information
     * @param rowIndex Row number (0-based)
     * @param columnIndex Column number (0-based)
     * @param data Data that failed conversion
     * @param message Error message
     */
    public ExcelWriteDataConvertException(Integer rowIndex, Integer columnIndex,
                                        Object data, String message);
    
    /**
     * Create exception with cell location and cause
     * @param rowIndex Row number (0-based)
     * @param columnIndex Column number (0-based)
     * @param data Data that failed conversion
     * @param message Error message
     * @param cause Root cause exception
     */
    public ExcelWriteDataConvertException(Integer rowIndex, Integer columnIndex,
                                        Object data, String message, Throwable cause);
    
    // Getters for accessing error details
    public Integer getRowIndex();
    public Integer getColumnIndex();
    public Object getData();
}

Flow Control Exceptions

Special exceptions used for controlling execution flow during processing.

/**
 * Exception to stop entire reading process
 * This is not an error but a control mechanism
 */
public class ExcelAnalysisStopException extends ExcelAnalysisException {
    /**
     * Create stop exception with message
     * @param message Reason for stopping
     */
    public ExcelAnalysisStopException(String message);
    
    /**
     * Create stop exception without message
     */
    public ExcelAnalysisStopException();
}

/**
 * Exception to stop current sheet reading and continue to next sheet
 * This is not an error but a control mechanism
 */
public class ExcelAnalysisStopSheetException extends ExcelAnalysisStopException {
    /**
     * Create sheet stop exception with message
     * @param message Reason for stopping sheet
     */
    public ExcelAnalysisStopSheetException(String message);
    
    /**
     * Create sheet stop exception without message
     */
    public ExcelAnalysisStopSheetException();
}

Usage Examples

Basic Exception Handling in Listeners

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;

public class RobustUserDataListener extends AnalysisEventListener<UserData> {
    private List<UserData> validUsers = new ArrayList<>();
    private List<String> errors = new ArrayList<>();
    
    @Override
    public void invoke(UserData data, AnalysisContext context) {
        try {
            // Validate and process data
            validateUserData(data);
            validUsers.add(data);
        } catch (Exception e) {
            String error = String.format("Row %d: %s", 
                context.getCurrentRowNum(), e.getMessage());
            errors.add(error);
            System.err.println(error);
        }
    }
    
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException convertException = (ExcelDataConvertException) exception;
            String error = String.format("Data conversion error at row %d, column %d: %s",
                convertException.getRowIndex(),
                convertException.getColumnIndex(),
                convertException.getMessage());
            errors.add(error);
            System.err.println(error);
            
            // Continue processing instead of stopping
            return;
        }
        
        // For other exceptions, log and continue
        String error = String.format("Error at row %d: %s", 
            context.getCurrentRowNum(), exception.getMessage());
        errors.add(error);
        System.err.println(error);
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("Processing completed:");
        System.out.println("- Valid users: " + validUsers.size());
        System.out.println("- Errors: " + errors.size());
        
        if (!errors.isEmpty()) {
            System.out.println("Error details:");
            errors.forEach(System.out::println);
        }
    }
    
    private void validateUserData(UserData data) {
        if (data.getName() == null || data.getName().trim().isEmpty()) {
            throw new IllegalArgumentException("Name is required");
        }
        if (data.getEmail() == null || !data.getEmail().contains("@")) {
            throw new IllegalArgumentException("Valid email is required");
        }
        if (data.getAge() != null && (data.getAge() < 0 || data.getAge() > 150)) {
            throw new IllegalArgumentException("Age must be between 0 and 150");
        }
    }
}

Controlled Reading Termination

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisStopException;
import com.alibaba.excel.exception.ExcelAnalysisStopSheetException;

public class ConditionalStopListener extends AnalysisEventListener<UserData> {
    private int maxErrors = 10;
    private int errorCount = 0;
    private int maxRows = 1000;
    private int rowCount = 0;
    
    @Override
    public void invoke(UserData data, AnalysisContext context) {
        rowCount++;
        
        try {
            // Process data
            processUserData(data);
        } catch (Exception e) {
            errorCount++;
            System.err.println("Error at row " + context.getCurrentRowNum() + ": " + e.getMessage());
            
            // Stop if too many errors
            if (errorCount >= maxErrors) {
                throw new ExcelAnalysisStopException(
                    "Stopping analysis: too many errors (" + errorCount + ")");
            }
        }
        
        // Stop if processed enough rows
        if (rowCount >= maxRows) {
            throw new ExcelAnalysisStopException(
                "Stopping analysis: reached maximum rows (" + maxRows + ")");
        }
        
        // Example of stopping current sheet based on data content
        if ("END_SHEET".equals(data.getName())) {
            throw new ExcelAnalysisStopSheetException(
                "Found end marker, moving to next sheet");
        }
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        System.out.println("Analysis completed or stopped");
        System.out.println("Rows processed: " + rowCount);
        System.out.println("Errors encountered: " + errorCount);
    }
    
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelAnalysisStopException) {
            System.out.println("Controlled stop: " + exception.getMessage());
            throw exception; // Re-throw to actually stop
        }
        
        // Handle other exceptions without stopping
        errorCount++;
        System.err.println("Handled exception: " + exception.getMessage());
    }
    
    private void processUserData(UserData data) {
        // Processing logic that might throw exceptions
        if (data.getName() == null) {
            throw new IllegalArgumentException("Name cannot be null");
        }
        // Additional processing...
    }
}

Writing Exception Handling

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.exception.ExcelWriteDataConvertException;

public class SafeExcelWriter {
    
    public void writeUsersWithErrorHandling(List<UserData> users, String fileName) {
        try {
            EasyExcel.write(fileName, UserData.class)
                .writeExcelOnException(true) // Write partial data on exception
                .sheet("Users")
                .doWrite(users);
                
            System.out.println("Successfully wrote " + users.size() + " users to " + fileName);
            
        } catch (ExcelWriteDataConvertException convertException) {
            System.err.println("Data conversion error during writing:");
            System.err.println("- Row: " + convertException.getRowIndex());
            System.err.println("- Column: " + convertException.getColumnIndex());
            System.err.println("- Data: " + convertException.getData());
            System.err.println("- Message: " + convertException.getMessage());
            
            // Try writing with different strategy
            writeWithFallback(users, fileName);
            
        } catch (ExcelGenerateException generateException) {
            System.err.println("Excel generation error: " + generateException.getMessage());
            
            // Try alternative format
            writeAsCsv(users, fileName.replace(".xlsx", ".csv"));
            
        } catch (Exception e) {
            System.err.println("Unexpected error during writing: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private void writeWithFallback(List<UserData> users, String fileName) {
        // Implement fallback strategy (e.g., write as plain data without formatting)
        try {
            String fallbackName = fileName.replace(".xlsx", "_fallback.xlsx");
            EasyExcel.write(fallbackName)
                .sheet("Users")
                .doWrite(convertToBasicData(users));
            System.out.println("Fallback write completed: " + fallbackName);
        } catch (Exception e) {
            System.err.println("Fallback write also failed: " + e.getMessage());
        }
    }
    
    private void writeAsCsv(List<UserData> users, String fileName) {
        // Implement CSV writing as alternative
        try {
            EasyExcel.write(fileName, UserData.class)
                .sheet()
                .doWrite(users);
            System.out.println("CSV write completed: " + fileName);
        } catch (Exception e) {
            System.err.println("CSV write failed: " + e.getMessage());
        }
    }
    
    private List<Map<String, Object>> convertToBasicData(List<UserData> users) {
        // Convert to simple Map structure for fallback writing
        return users.stream()
            .map(user -> {
                Map<String, Object> map = new HashMap<>();
                map.put("Name", user.getName());
                map.put("Email", user.getEmail());
                map.put("Age", user.getAge());
                return map;
            })
            .collect(Collectors.toList());
    }
}

Custom Exception in Converters

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.exception.ExcelDataConvertException;

public class StrictEmailConverter implements Converter<String> {
    private static final Pattern EMAIL_PATTERN = 
        Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
    
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }
    
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
    
    @Override
    public String convertToJavaData(ReadCellData<?> cellData, 
                                   ExcelContentProperty contentProperty,
                                   GlobalConfiguration globalConfiguration) throws Exception {
        String email = cellData.getStringValue();
        
        if (email == null || email.trim().isEmpty()) {
            return null;
        }
        
        email = email.trim().toLowerCase();
        
        if (!EMAIL_PATTERN.matcher(email).matches()) {
            throw new ExcelDataConvertException(
                "Invalid email format: " + email + ". Expected format: user@domain.com");
        }
        
        return email;
    }
    
    @Override
    public WriteCellData<?> convertToExcelData(String value, 
                                              ExcelContentProperty contentProperty,
                                              GlobalConfiguration globalConfiguration) throws Exception {
        if (value != null && !EMAIL_PATTERN.matcher(value).matches()) {
            throw new ExcelWriteDataConvertException(
                "Invalid email format for writing: " + value);
        }
        
        return new WriteCellData<>(value);
    }
}

Exception Aggregation and Reporting

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;

public class ErrorReportingListener extends AnalysisEventListener<UserData> {
    private List<UserData> validData = new ArrayList<>();
    private List<ErrorRecord> errors = new ArrayList<>();
    
    @Override
    public void invoke(UserData data, AnalysisContext context) {
        try {
            validateAndProcess(data, context);
            validData.add(data);
        } catch (Exception e) {
            recordError(e, context, data);
        }
    }
    
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        recordError(exception, context, null);
        // Continue processing
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        generateErrorReport();
        processValidData();
    }
    
    private void validateAndProcess(UserData data, AnalysisContext context) {
        if (data.getName() == null || data.getName().trim().isEmpty()) {
            throw new IllegalArgumentException("Name is required");
        }
        
        if (data.getEmail() == null || !data.getEmail().contains("@")) {
            throw new IllegalArgumentException("Valid email is required");
        }
        
        if (data.getAge() != null && data.getAge() < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
    
    private void recordError(Exception exception, AnalysisContext context, UserData data) {
        ErrorRecord error = new ErrorRecord();
        error.setRowNumber(context.getCurrentRowNum());
        error.setSheetName(context.getCurrentSheet().getSheetName());
        error.setErrorMessage(exception.getMessage());
        error.setExceptionType(exception.getClass().getSimpleName());
        
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException convertEx = (ExcelDataConvertException) exception;
            error.setColumnIndex(convertEx.getColumnIndex());
            error.setCellData(convertEx.getCellData() != null ? 
                convertEx.getCellData().toString() : null);
        }
        
        if (data != null) {
            error.setRawData(data.toString());
        }
        
        errors.add(error);
    }
    
    private void generateErrorReport() {
        System.out.println("=== Error Report ===");
        System.out.println("Total valid records: " + validData.size());
        System.out.println("Total errors: " + errors.size());
        System.out.println();
        
        if (!errors.isEmpty()) {
            System.out.println("Error Details:");
            for (ErrorRecord error : errors) {
                System.out.println(String.format(
                    "Row %d%s: %s - %s",
                    error.getRowNumber(),
                    error.getColumnIndex() != null ? " Col " + error.getColumnIndex() : "",
                    error.getExceptionType(),
                    error.getErrorMessage()
                ));
                
                if (error.getCellData() != null) {
                    System.out.println("  Cell data: " + error.getCellData());
                }
                if (error.getRawData() != null) {
                    System.out.println("  Raw data: " + error.getRawData());
                }
                System.out.println();
            }
        }
    }
    
    private void processValidData() {
        // Process the valid data
        System.out.println("Processing " + validData.size() + " valid records...");
    }
    
    // Error record class for collecting error information
    private static class ErrorRecord {
        private Integer rowNumber;
        private String sheetName;
        private Integer columnIndex;
        private String cellData;
        private String rawData;
        private String errorMessage;
        private String exceptionType;
        
        // Getters and setters...
        public Integer getRowNumber() { return rowNumber; }
        public void setRowNumber(Integer rowNumber) { this.rowNumber = rowNumber; }
        
        public String getSheetName() { return sheetName; }
        public void setSheetName(String sheetName) { this.sheetName = sheetName; }
        
        public Integer getColumnIndex() { return columnIndex; }
        public void setColumnIndex(Integer columnIndex) { this.columnIndex = columnIndex; }
        
        public String getCellData() { return cellData; }
        public void setCellData(String cellData) { this.cellData = cellData; }
        
        public String getRawData() { return rawData; }
        public void setRawData(String rawData) { this.rawData = rawData; }
        
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
        
        public String getExceptionType() { return exceptionType; }
        public void setExceptionType(String exceptionType) { this.exceptionType = exceptionType; }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-alibaba--easyexcel

docs

annotations-and-mapping.md

data-conversion.md

event-system.md

exception-handling.md

index.md

reading-operations.md

writing-operations.md

tile.json