0
# Exception Handling
1
2
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.
3
4
## Capabilities
5
6
### Base Exception Classes
7
8
Core exception hierarchy providing foundation for all Excel-related errors.
9
10
```java { .api }
11
/**
12
* Base runtime exception for all Excel operations
13
*/
14
public class ExcelRuntimeException extends RuntimeException {
15
/**
16
* Create exception with message
17
* @param message Error message
18
*/
19
public ExcelRuntimeException(String message);
20
21
/**
22
* Create exception with message and cause
23
* @param message Error message
24
* @param cause Root cause exception
25
*/
26
public ExcelRuntimeException(String message, Throwable cause);
27
28
/**
29
* Create exception with cause
30
* @param cause Root cause exception
31
*/
32
public ExcelRuntimeException(Throwable cause);
33
}
34
35
/**
36
* Common exception for general Excel processing errors
37
*/
38
public class ExcelCommonException extends ExcelRuntimeException {
39
/**
40
* Create exception with message
41
* @param message Error message
42
*/
43
public ExcelCommonException(String message);
44
45
/**
46
* Create exception with message and cause
47
* @param message Error message
48
* @param cause Root cause exception
49
*/
50
public ExcelCommonException(String message, Throwable cause);
51
52
/**
53
* Create exception with cause
54
* @param cause Root cause exception
55
*/
56
public ExcelCommonException(Throwable cause);
57
}
58
```
59
60
### Reading Operation Exceptions
61
62
Exceptions specific to Excel reading operations.
63
64
```java { .api }
65
/**
66
* Exception during Excel analysis/reading operations
67
*/
68
public class ExcelAnalysisException extends ExcelRuntimeException {
69
/**
70
* Create exception with message
71
* @param message Error message
72
*/
73
public ExcelAnalysisException(String message);
74
75
/**
76
* Create exception with message and cause
77
* @param message Error message
78
* @param cause Root cause exception
79
*/
80
public ExcelAnalysisException(String message, Throwable cause);
81
82
/**
83
* Create exception with cause
84
* @param cause Root cause exception
85
*/
86
public ExcelAnalysisException(Throwable cause);
87
}
88
89
/**
90
* Data type conversion errors during reading
91
*/
92
public class ExcelDataConvertException extends ExcelAnalysisException {
93
/**
94
* Row number where error occurred
95
*/
96
private Integer rowIndex;
97
98
/**
99
* Column index where error occurred
100
*/
101
private Integer columnIndex;
102
103
/**
104
* Cell data that failed conversion
105
*/
106
private ReadCellData<?> cellData;
107
108
/**
109
* Create exception with basic information
110
* @param message Error message
111
*/
112
public ExcelDataConvertException(String message);
113
114
/**
115
* Create exception with cell location information
116
* @param rowIndex Row number (0-based)
117
* @param columnIndex Column number (0-based)
118
* @param cellData Cell data that failed conversion
119
* @param message Error message
120
*/
121
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex,
122
ReadCellData<?> cellData, String message);
123
124
/**
125
* Create exception with cell location and cause
126
* @param rowIndex Row number (0-based)
127
* @param columnIndex Column number (0-based)
128
* @param cellData Cell data that failed conversion
129
* @param message Error message
130
* @param cause Root cause exception
131
*/
132
public ExcelDataConvertException(Integer rowIndex, Integer columnIndex,
133
ReadCellData<?> cellData, String message, Throwable cause);
134
135
// Getters for accessing error details
136
public Integer getRowIndex();
137
public Integer getColumnIndex();
138
public ReadCellData<?> getCellData();
139
}
140
```
141
142
### Writing Operation Exceptions
143
144
Exceptions specific to Excel writing operations.
145
146
```java { .api }
147
/**
148
* Exception during Excel generation/writing operations
149
*/
150
public class ExcelGenerateException extends ExcelRuntimeException {
151
/**
152
* Create exception with message
153
* @param message Error message
154
*/
155
public ExcelGenerateException(String message);
156
157
/**
158
* Create exception with message and cause
159
* @param message Error message
160
* @param cause Root cause exception
161
*/
162
public ExcelGenerateException(String message, Throwable cause);
163
164
/**
165
* Create exception with cause
166
* @param cause Root cause exception
167
*/
168
public ExcelGenerateException(Throwable cause);
169
}
170
171
/**
172
* Data conversion errors during writing
173
*/
174
public class ExcelWriteDataConvertException extends ExcelGenerateException {
175
/**
176
* Row number where error occurred
177
*/
178
private Integer rowIndex;
179
180
/**
181
* Column index where error occurred
182
*/
183
private Integer columnIndex;
184
185
/**
186
* Data that failed conversion
187
*/
188
private Object data;
189
190
/**
191
* Create exception with basic information
192
* @param message Error message
193
*/
194
public ExcelWriteDataConvertException(String message);
195
196
/**
197
* Create exception with cell location information
198
* @param rowIndex Row number (0-based)
199
* @param columnIndex Column number (0-based)
200
* @param data Data that failed conversion
201
* @param message Error message
202
*/
203
public ExcelWriteDataConvertException(Integer rowIndex, Integer columnIndex,
204
Object data, String message);
205
206
/**
207
* Create exception with cell location and cause
208
* @param rowIndex Row number (0-based)
209
* @param columnIndex Column number (0-based)
210
* @param data Data that failed conversion
211
* @param message Error message
212
* @param cause Root cause exception
213
*/
214
public ExcelWriteDataConvertException(Integer rowIndex, Integer columnIndex,
215
Object data, String message, Throwable cause);
216
217
// Getters for accessing error details
218
public Integer getRowIndex();
219
public Integer getColumnIndex();
220
public Object getData();
221
}
222
```
223
224
### Flow Control Exceptions
225
226
Special exceptions used for controlling execution flow during processing.
227
228
```java { .api }
229
/**
230
* Exception to stop entire reading process
231
* This is not an error but a control mechanism
232
*/
233
public class ExcelAnalysisStopException extends ExcelAnalysisException {
234
/**
235
* Create stop exception with message
236
* @param message Reason for stopping
237
*/
238
public ExcelAnalysisStopException(String message);
239
240
/**
241
* Create stop exception without message
242
*/
243
public ExcelAnalysisStopException();
244
}
245
246
/**
247
* Exception to stop current sheet reading and continue to next sheet
248
* This is not an error but a control mechanism
249
*/
250
public class ExcelAnalysisStopSheetException extends ExcelAnalysisStopException {
251
/**
252
* Create sheet stop exception with message
253
* @param message Reason for stopping sheet
254
*/
255
public ExcelAnalysisStopSheetException(String message);
256
257
/**
258
* Create sheet stop exception without message
259
*/
260
public ExcelAnalysisStopSheetException();
261
}
262
```
263
264
## Usage Examples
265
266
### Basic Exception Handling in Listeners
267
```java
268
import com.alibaba.excel.context.AnalysisContext;
269
import com.alibaba.excel.event.AnalysisEventListener;
270
import com.alibaba.excel.exception.ExcelDataConvertException;
271
272
public class RobustUserDataListener extends AnalysisEventListener<UserData> {
273
private List<UserData> validUsers = new ArrayList<>();
274
private List<String> errors = new ArrayList<>();
275
276
@Override
277
public void invoke(UserData data, AnalysisContext context) {
278
try {
279
// Validate and process data
280
validateUserData(data);
281
validUsers.add(data);
282
} catch (Exception e) {
283
String error = String.format("Row %d: %s",
284
context.getCurrentRowNum(), e.getMessage());
285
errors.add(error);
286
System.err.println(error);
287
}
288
}
289
290
@Override
291
public void onException(Exception exception, AnalysisContext context) throws Exception {
292
if (exception instanceof ExcelDataConvertException) {
293
ExcelDataConvertException convertException = (ExcelDataConvertException) exception;
294
String error = String.format("Data conversion error at row %d, column %d: %s",
295
convertException.getRowIndex(),
296
convertException.getColumnIndex(),
297
convertException.getMessage());
298
errors.add(error);
299
System.err.println(error);
300
301
// Continue processing instead of stopping
302
return;
303
}
304
305
// For other exceptions, log and continue
306
String error = String.format("Error at row %d: %s",
307
context.getCurrentRowNum(), exception.getMessage());
308
errors.add(error);
309
System.err.println(error);
310
}
311
312
@Override
313
public void doAfterAllAnalysed(AnalysisContext context) {
314
System.out.println("Processing completed:");
315
System.out.println("- Valid users: " + validUsers.size());
316
System.out.println("- Errors: " + errors.size());
317
318
if (!errors.isEmpty()) {
319
System.out.println("Error details:");
320
errors.forEach(System.out::println);
321
}
322
}
323
324
private void validateUserData(UserData data) {
325
if (data.getName() == null || data.getName().trim().isEmpty()) {
326
throw new IllegalArgumentException("Name is required");
327
}
328
if (data.getEmail() == null || !data.getEmail().contains("@")) {
329
throw new IllegalArgumentException("Valid email is required");
330
}
331
if (data.getAge() != null && (data.getAge() < 0 || data.getAge() > 150)) {
332
throw new IllegalArgumentException("Age must be between 0 and 150");
333
}
334
}
335
}
336
```
337
338
### Controlled Reading Termination
339
```java
340
import com.alibaba.excel.context.AnalysisContext;
341
import com.alibaba.excel.event.AnalysisEventListener;
342
import com.alibaba.excel.exception.ExcelAnalysisStopException;
343
import com.alibaba.excel.exception.ExcelAnalysisStopSheetException;
344
345
public class ConditionalStopListener extends AnalysisEventListener<UserData> {
346
private int maxErrors = 10;
347
private int errorCount = 0;
348
private int maxRows = 1000;
349
private int rowCount = 0;
350
351
@Override
352
public void invoke(UserData data, AnalysisContext context) {
353
rowCount++;
354
355
try {
356
// Process data
357
processUserData(data);
358
} catch (Exception e) {
359
errorCount++;
360
System.err.println("Error at row " + context.getCurrentRowNum() + ": " + e.getMessage());
361
362
// Stop if too many errors
363
if (errorCount >= maxErrors) {
364
throw new ExcelAnalysisStopException(
365
"Stopping analysis: too many errors (" + errorCount + ")");
366
}
367
}
368
369
// Stop if processed enough rows
370
if (rowCount >= maxRows) {
371
throw new ExcelAnalysisStopException(
372
"Stopping analysis: reached maximum rows (" + maxRows + ")");
373
}
374
375
// Example of stopping current sheet based on data content
376
if ("END_SHEET".equals(data.getName())) {
377
throw new ExcelAnalysisStopSheetException(
378
"Found end marker, moving to next sheet");
379
}
380
}
381
382
@Override
383
public void doAfterAllAnalysed(AnalysisContext context) {
384
System.out.println("Analysis completed or stopped");
385
System.out.println("Rows processed: " + rowCount);
386
System.out.println("Errors encountered: " + errorCount);
387
}
388
389
@Override
390
public void onException(Exception exception, AnalysisContext context) throws Exception {
391
if (exception instanceof ExcelAnalysisStopException) {
392
System.out.println("Controlled stop: " + exception.getMessage());
393
throw exception; // Re-throw to actually stop
394
}
395
396
// Handle other exceptions without stopping
397
errorCount++;
398
System.err.println("Handled exception: " + exception.getMessage());
399
}
400
401
private void processUserData(UserData data) {
402
// Processing logic that might throw exceptions
403
if (data.getName() == null) {
404
throw new IllegalArgumentException("Name cannot be null");
405
}
406
// Additional processing...
407
}
408
}
409
```
410
411
### Writing Exception Handling
412
```java
413
import com.alibaba.excel.EasyExcel;
414
import com.alibaba.excel.exception.ExcelGenerateException;
415
import com.alibaba.excel.exception.ExcelWriteDataConvertException;
416
417
public class SafeExcelWriter {
418
419
public void writeUsersWithErrorHandling(List<UserData> users, String fileName) {
420
try {
421
EasyExcel.write(fileName, UserData.class)
422
.writeExcelOnException(true) // Write partial data on exception
423
.sheet("Users")
424
.doWrite(users);
425
426
System.out.println("Successfully wrote " + users.size() + " users to " + fileName);
427
428
} catch (ExcelWriteDataConvertException convertException) {
429
System.err.println("Data conversion error during writing:");
430
System.err.println("- Row: " + convertException.getRowIndex());
431
System.err.println("- Column: " + convertException.getColumnIndex());
432
System.err.println("- Data: " + convertException.getData());
433
System.err.println("- Message: " + convertException.getMessage());
434
435
// Try writing with different strategy
436
writeWithFallback(users, fileName);
437
438
} catch (ExcelGenerateException generateException) {
439
System.err.println("Excel generation error: " + generateException.getMessage());
440
441
// Try alternative format
442
writeAsCsv(users, fileName.replace(".xlsx", ".csv"));
443
444
} catch (Exception e) {
445
System.err.println("Unexpected error during writing: " + e.getMessage());
446
e.printStackTrace();
447
}
448
}
449
450
private void writeWithFallback(List<UserData> users, String fileName) {
451
// Implement fallback strategy (e.g., write as plain data without formatting)
452
try {
453
String fallbackName = fileName.replace(".xlsx", "_fallback.xlsx");
454
EasyExcel.write(fallbackName)
455
.sheet("Users")
456
.doWrite(convertToBasicData(users));
457
System.out.println("Fallback write completed: " + fallbackName);
458
} catch (Exception e) {
459
System.err.println("Fallback write also failed: " + e.getMessage());
460
}
461
}
462
463
private void writeAsCsv(List<UserData> users, String fileName) {
464
// Implement CSV writing as alternative
465
try {
466
EasyExcel.write(fileName, UserData.class)
467
.sheet()
468
.doWrite(users);
469
System.out.println("CSV write completed: " + fileName);
470
} catch (Exception e) {
471
System.err.println("CSV write failed: " + e.getMessage());
472
}
473
}
474
475
private List<Map<String, Object>> convertToBasicData(List<UserData> users) {
476
// Convert to simple Map structure for fallback writing
477
return users.stream()
478
.map(user -> {
479
Map<String, Object> map = new HashMap<>();
480
map.put("Name", user.getName());
481
map.put("Email", user.getEmail());
482
map.put("Age", user.getAge());
483
return map;
484
})
485
.collect(Collectors.toList());
486
}
487
}
488
```
489
490
### Custom Exception in Converters
491
```java
492
import com.alibaba.excel.converters.Converter;
493
import com.alibaba.excel.enums.CellDataTypeEnum;
494
import com.alibaba.excel.exception.ExcelDataConvertException;
495
496
public class StrictEmailConverter implements Converter<String> {
497
private static final Pattern EMAIL_PATTERN =
498
Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
499
500
@Override
501
public Class<?> supportJavaTypeKey() {
502
return String.class;
503
}
504
505
@Override
506
public CellDataTypeEnum supportExcelTypeKey() {
507
return CellDataTypeEnum.STRING;
508
}
509
510
@Override
511
public String convertToJavaData(ReadCellData<?> cellData,
512
ExcelContentProperty contentProperty,
513
GlobalConfiguration globalConfiguration) throws Exception {
514
String email = cellData.getStringValue();
515
516
if (email == null || email.trim().isEmpty()) {
517
return null;
518
}
519
520
email = email.trim().toLowerCase();
521
522
if (!EMAIL_PATTERN.matcher(email).matches()) {
523
throw new ExcelDataConvertException(
524
"Invalid email format: " + email + ". Expected format: user@domain.com");
525
}
526
527
return email;
528
}
529
530
@Override
531
public WriteCellData<?> convertToExcelData(String value,
532
ExcelContentProperty contentProperty,
533
GlobalConfiguration globalConfiguration) throws Exception {
534
if (value != null && !EMAIL_PATTERN.matcher(value).matches()) {
535
throw new ExcelWriteDataConvertException(
536
"Invalid email format for writing: " + value);
537
}
538
539
return new WriteCellData<>(value);
540
}
541
}
542
```
543
544
### Exception Aggregation and Reporting
545
```java
546
import com.alibaba.excel.context.AnalysisContext;
547
import com.alibaba.excel.event.AnalysisEventListener;
548
import com.alibaba.excel.exception.ExcelDataConvertException;
549
550
public class ErrorReportingListener extends AnalysisEventListener<UserData> {
551
private List<UserData> validData = new ArrayList<>();
552
private List<ErrorRecord> errors = new ArrayList<>();
553
554
@Override
555
public void invoke(UserData data, AnalysisContext context) {
556
try {
557
validateAndProcess(data, context);
558
validData.add(data);
559
} catch (Exception e) {
560
recordError(e, context, data);
561
}
562
}
563
564
@Override
565
public void onException(Exception exception, AnalysisContext context) throws Exception {
566
recordError(exception, context, null);
567
// Continue processing
568
}
569
570
@Override
571
public void doAfterAllAnalysed(AnalysisContext context) {
572
generateErrorReport();
573
processValidData();
574
}
575
576
private void validateAndProcess(UserData data, AnalysisContext context) {
577
if (data.getName() == null || data.getName().trim().isEmpty()) {
578
throw new IllegalArgumentException("Name is required");
579
}
580
581
if (data.getEmail() == null || !data.getEmail().contains("@")) {
582
throw new IllegalArgumentException("Valid email is required");
583
}
584
585
if (data.getAge() != null && data.getAge() < 0) {
586
throw new IllegalArgumentException("Age cannot be negative");
587
}
588
}
589
590
private void recordError(Exception exception, AnalysisContext context, UserData data) {
591
ErrorRecord error = new ErrorRecord();
592
error.setRowNumber(context.getCurrentRowNum());
593
error.setSheetName(context.getCurrentSheet().getSheetName());
594
error.setErrorMessage(exception.getMessage());
595
error.setExceptionType(exception.getClass().getSimpleName());
596
597
if (exception instanceof ExcelDataConvertException) {
598
ExcelDataConvertException convertEx = (ExcelDataConvertException) exception;
599
error.setColumnIndex(convertEx.getColumnIndex());
600
error.setCellData(convertEx.getCellData() != null ?
601
convertEx.getCellData().toString() : null);
602
}
603
604
if (data != null) {
605
error.setRawData(data.toString());
606
}
607
608
errors.add(error);
609
}
610
611
private void generateErrorReport() {
612
System.out.println("=== Error Report ===");
613
System.out.println("Total valid records: " + validData.size());
614
System.out.println("Total errors: " + errors.size());
615
System.out.println();
616
617
if (!errors.isEmpty()) {
618
System.out.println("Error Details:");
619
for (ErrorRecord error : errors) {
620
System.out.println(String.format(
621
"Row %d%s: %s - %s",
622
error.getRowNumber(),
623
error.getColumnIndex() != null ? " Col " + error.getColumnIndex() : "",
624
error.getExceptionType(),
625
error.getErrorMessage()
626
));
627
628
if (error.getCellData() != null) {
629
System.out.println(" Cell data: " + error.getCellData());
630
}
631
if (error.getRawData() != null) {
632
System.out.println(" Raw data: " + error.getRawData());
633
}
634
System.out.println();
635
}
636
}
637
}
638
639
private void processValidData() {
640
// Process the valid data
641
System.out.println("Processing " + validData.size() + " valid records...");
642
}
643
644
// Error record class for collecting error information
645
private static class ErrorRecord {
646
private Integer rowNumber;
647
private String sheetName;
648
private Integer columnIndex;
649
private String cellData;
650
private String rawData;
651
private String errorMessage;
652
private String exceptionType;
653
654
// Getters and setters...
655
public Integer getRowNumber() { return rowNumber; }
656
public void setRowNumber(Integer rowNumber) { this.rowNumber = rowNumber; }
657
658
public String getSheetName() { return sheetName; }
659
public void setSheetName(String sheetName) { this.sheetName = sheetName; }
660
661
public Integer getColumnIndex() { return columnIndex; }
662
public void setColumnIndex(Integer columnIndex) { this.columnIndex = columnIndex; }
663
664
public String getCellData() { return cellData; }
665
public void setCellData(String cellData) { this.cellData = cellData; }
666
667
public String getRawData() { return rawData; }
668
public void setRawData(String rawData) { this.rawData = rawData; }
669
670
public String getErrorMessage() { return errorMessage; }
671
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
672
673
public String getExceptionType() { return exceptionType; }
674
public void setExceptionType(String exceptionType) { this.exceptionType = exceptionType; }
675
}
676
}
677
```