or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations-and-mapping.mddata-conversion.mdevent-system.mdexception-handling.mdindex.mdreading-operations.mdwriting-operations.md

data-conversion.mddocs/

0

# Data Conversion

1

2

Type conversion system for transforming between Java objects and Excel cell values. EasyExcel provides a pluggable converter system that handles automatic type detection and custom conversion logic for complex data transformations.

3

4

## Capabilities

5

6

### Core Converter Interface

7

8

Primary interface for implementing custom data converters.

9

10

```java { .api }

11

/**

12

* Interface for converting between Java objects and Excel cell values

13

* @param <T> Java type that this converter handles

14

*/

15

public interface Converter<T> {

16

/**

17

* Get the Java type that this converter supports

18

* @return Class of supported Java type

19

*/

20

Class<?> supportJavaTypeKey();

21

22

/**

23

* Get the Excel cell data type that this converter supports

24

* @return CellDataTypeEnum of supported Excel type

25

*/

26

CellDataTypeEnum supportExcelTypeKey();

27

28

/**

29

* Convert Excel cell data to Java object (for reading)

30

* @param cellData Cell data from Excel

31

* @param contentProperty Content property configuration

32

* @param globalConfiguration Global configuration settings

33

* @return Converted Java object

34

* @throws Exception if conversion fails

35

*/

36

T convertToJavaData(ReadCellData<?> cellData,

37

ExcelContentProperty contentProperty,

38

GlobalConfiguration globalConfiguration) throws Exception;

39

40

/**

41

* Convert Java object to Excel cell data (for writing)

42

* @param value Java object to convert

43

* @param contentProperty Content property configuration

44

* @param globalConfiguration Global configuration settings

45

* @return Cell data for Excel

46

* @throws Exception if conversion fails

47

*/

48

WriteCellData<?> convertToExcelData(T value,

49

ExcelContentProperty contentProperty,

50

GlobalConfiguration globalConfiguration) throws Exception;

51

}

52

```

53

54

### Built-in Converter Classes

55

56

Pre-built converters for automatic type handling.

57

58

```java { .api }

59

/**

60

* Automatic converter that detects appropriate converter based on type

61

*/

62

public class AutoConverter implements Converter<Object> {

63

@Override

64

public Class<?> supportJavaTypeKey() {

65

return null; // Supports all types

66

}

67

68

@Override

69

public CellDataTypeEnum supportExcelTypeKey() {

70

return null; // Supports all cell types

71

}

72

73

@Override

74

public Object convertToJavaData(ReadCellData<?> cellData,

75

ExcelContentProperty contentProperty,

76

GlobalConfiguration globalConfiguration) throws Exception {

77

// Automatic type detection and conversion

78

return null; // Implementation handles detection

79

}

80

81

@Override

82

public WriteCellData<?> convertToExcelData(Object value,

83

ExcelContentProperty contentProperty,

84

GlobalConfiguration globalConfiguration) throws Exception {

85

// Automatic type detection and conversion

86

return null; // Implementation handles detection

87

}

88

}

89

90

/**

91

* Converter for handling null values

92

*/

93

public class NullableObjectConverter implements Converter<Object> {

94

@Override

95

public Class<?> supportJavaTypeKey() {

96

return Object.class;

97

}

98

99

@Override

100

public CellDataTypeEnum supportExcelTypeKey() {

101

return CellDataTypeEnum.EMPTY;

102

}

103

104

@Override

105

public Object convertToJavaData(ReadCellData<?> cellData,

106

ExcelContentProperty contentProperty,

107

GlobalConfiguration globalConfiguration) {

108

if (cellData == null || cellData.getData() == null) {

109

return null;

110

}

111

// Delegate to appropriate converter

112

return cellData.getData();

113

}

114

115

@Override

116

public WriteCellData<?> convertToExcelData(Object value,

117

ExcelContentProperty contentProperty,

118

GlobalConfiguration globalConfiguration) {

119

if (value == null) {

120

return new WriteCellData<>("");

121

}

122

// Delegate to appropriate converter

123

return new WriteCellData<>(value);

124

}

125

}

126

```

127

128

### Converter Management

129

130

Classes for loading and managing converters.

131

132

```java { .api }

133

/**

134

* Default converter loader and registry

135

*/

136

public class DefaultConverterLoader {

137

/**

138

* Load all default converters

139

* @return Map of converter configurations

140

*/

141

public static Map<String, Converter<?>> loadDefaultReadConverter() {

142

// Returns map of all built-in read converters

143

return null; // Implementation loads converters

144

}

145

146

/**

147

* Load all default write converters

148

* @return Map of converter configurations

149

*/

150

public static Map<String, Converter<?>> loadDefaultWriteConverter() {

151

// Returns map of all built-in write converters

152

return null; // Implementation loads converters

153

}

154

155

/**

156

* Load converters for specific type

157

* @param clazz Java class to load converters for

158

* @return Map of converters for the class

159

*/

160

public static Map<String, Converter<?>> loadConverter(Class<?> clazz) {

161

// Returns converters specific to the class

162

return null; // Implementation loads converters

163

}

164

}

165

166

/**

167

* Converter holder for managing converter instances

168

*/

169

public class ConverterHolder {

170

/**

171

* Register a custom converter

172

* @param converter Converter to register

173

*/

174

public void registerConverter(Converter<?> converter);

175

176

/**

177

* Get converter for Java type and Excel type combination

178

* @param javaType Java class

179

* @param excelType Excel cell data type

180

* @return Appropriate converter or null

181

*/

182

public Converter<?> getConverter(Class<?> javaType, CellDataTypeEnum excelType);

183

184

/**

185

* Get all registered converters

186

* @return Map of all converters

187

*/

188

public Map<String, Converter<?>> getAllConverter();

189

}

190

```

191

192

### Cell Data Classes

193

194

Classes representing cell data during conversion.

195

196

```java { .api }

197

/**

198

* Cell data structure used during reading operations

199

* @param <T> Type of data contained in the cell

200

*/

201

public class ReadCellData<T> {

202

/**

203

* Cell data type

204

*/

205

private CellDataTypeEnum type;

206

207

/**

208

* Cell data value

209

*/

210

private T data;

211

212

/**

213

* Cell formula (if applicable)

214

*/

215

private String formula;

216

217

/**

218

* String representation of cell value

219

*/

220

private String stringValue;

221

222

/**

223

* Number representation of cell value

224

*/

225

private BigDecimal numberValue;

226

227

/**

228

* Boolean representation of cell value

229

*/

230

private Boolean booleanValue;

231

232

/**

233

* Date representation of cell value

234

*/

235

private Date dateValue;

236

237

// Getters and setters...

238

}

239

240

/**

241

* Cell data structure used during writing operations

242

* @param <T> Type of data to write to the cell

243

*/

244

public class WriteCellData<T> {

245

/**

246

* Cell data type

247

*/

248

private CellDataTypeEnum type;

249

250

/**

251

* Cell data value

252

*/

253

private T data;

254

255

/**

256

* Cell formula (if applicable)

257

*/

258

private String formula;

259

260

/**

261

* Data format for the cell

262

*/

263

private String dataFormat;

264

265

/**

266

* Data format index

267

*/

268

private Short dataFormatIndex;

269

270

// Constructors

271

public WriteCellData();

272

public WriteCellData(T data);

273

public WriteCellData(String formula, T data);

274

275

// Getters and setters...

276

}

277

```

278

279

### Content Property Classes

280

281

Classes providing configuration context for converters.

282

283

```java { .api }

284

/**

285

* Excel content property containing field configuration

286

*/

287

public class ExcelContentProperty {

288

/**

289

* Field information

290

*/

291

private Field field;

292

293

/**

294

* Date format configuration

295

*/

296

private DateTimeFormatProperty dateTimeFormatProperty;

297

298

/**

299

* Number format configuration

300

*/

301

private NumberFormatProperty numberFormatProperty;

302

303

/**

304

* Custom converter class

305

*/

306

private Class<? extends Converter<?>> converter;

307

308

/**

309

* Column index

310

*/

311

private Integer index;

312

313

/**

314

* Column order

315

*/

316

private Integer order;

317

318

// Getters and setters...

319

}

320

321

/**

322

* Date/time format property

323

*/

324

public class DateTimeFormatProperty {

325

/**

326

* Date format pattern

327

*/

328

private String format;

329

330

/**

331

* Use 1904 date windowing

332

*/

333

private Boolean use1904windowing;

334

335

// Getters and setters...

336

}

337

338

/**

339

* Number format property

340

*/

341

public class NumberFormatProperty {

342

/**

343

* Number format pattern

344

*/

345

private String format;

346

347

/**

348

* Number format index

349

*/

350

private Short index;

351

352

// Getters and setters...

353

}

354

```

355

356

## Usage Examples

357

358

### Custom Enum Converter

359

```java

360

import com.alibaba.excel.converters.Converter;

361

import com.alibaba.excel.enums.CellDataTypeEnum;

362

import com.alibaba.excel.metadata.GlobalConfiguration;

363

import com.alibaba.excel.metadata.data.ReadCellData;

364

import com.alibaba.excel.metadata.data.WriteCellData;

365

import com.alibaba.excel.metadata.property.ExcelContentProperty;

366

367

// Enum definition

368

public enum UserStatus {

369

ACTIVE("Active"),

370

INACTIVE("Inactive"),

371

PENDING("Pending"),

372

SUSPENDED("Suspended");

373

374

private final String displayName;

375

376

UserStatus(String displayName) {

377

this.displayName = displayName;

378

}

379

380

public String getDisplayName() {

381

return displayName;

382

}

383

384

public static UserStatus fromDisplayName(String displayName) {

385

for (UserStatus status : values()) {

386

if (status.displayName.equals(displayName)) {

387

return status;

388

}

389

}

390

throw new IllegalArgumentException("Unknown status: " + displayName);

391

}

392

}

393

394

// Custom converter implementation

395

public class UserStatusConverter implements Converter<UserStatus> {

396

@Override

397

public Class<?> supportJavaTypeKey() {

398

return UserStatus.class;

399

}

400

401

@Override

402

public CellDataTypeEnum supportExcelTypeKey() {

403

return CellDataTypeEnum.STRING;

404

}

405

406

@Override

407

public UserStatus convertToJavaData(ReadCellData<?> cellData,

408

ExcelContentProperty contentProperty,

409

GlobalConfiguration globalConfiguration) throws Exception {

410

String cellValue = cellData.getStringValue();

411

if (cellValue == null || cellValue.trim().isEmpty()) {

412

return null;

413

}

414

415

try {

416

return UserStatus.fromDisplayName(cellValue.trim());

417

} catch (IllegalArgumentException e) {

418

throw new ExcelDataConvertException(

419

"Cannot convert '" + cellValue + "' to UserStatus", e);

420

}

421

}

422

423

@Override

424

public WriteCellData<?> convertToExcelData(UserStatus value,

425

ExcelContentProperty contentProperty,

426

GlobalConfiguration globalConfiguration) throws Exception {

427

if (value == null) {

428

return new WriteCellData<>("");

429

}

430

return new WriteCellData<>(value.getDisplayName());

431

}

432

}

433

434

// Data class using custom converter

435

public class UserData {

436

@ExcelProperty("Name")

437

private String name;

438

439

@ExcelProperty(value = "Status", converter = UserStatusConverter.class)

440

private UserStatus status;

441

442

@ExcelProperty("Email")

443

private String email;

444

445

// Getters and setters...

446

}

447

```

448

449

### Custom Date Converter

450

```java

451

import com.alibaba.excel.converters.Converter;

452

import com.alibaba.excel.enums.CellDataTypeEnum;

453

import java.time.LocalDateTime;

454

import java.time.format.DateTimeFormatter;

455

456

public class LocalDateTimeConverter implements Converter<LocalDateTime> {

457

private static final DateTimeFormatter FORMATTER =

458

DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

459

460

@Override

461

public Class<?> supportJavaTypeKey() {

462

return LocalDateTime.class;

463

}

464

465

@Override

466

public CellDataTypeEnum supportExcelTypeKey() {

467

return CellDataTypeEnum.STRING;

468

}

469

470

@Override

471

public LocalDateTime convertToJavaData(ReadCellData<?> cellData,

472

ExcelContentProperty contentProperty,

473

GlobalConfiguration globalConfiguration) throws Exception {

474

String cellValue = cellData.getStringValue();

475

if (cellValue == null || cellValue.trim().isEmpty()) {

476

return null;

477

}

478

479

try {

480

return LocalDateTime.parse(cellValue.trim(), FORMATTER);

481

} catch (Exception e) {

482

throw new ExcelDataConvertException(

483

"Cannot parse date: " + cellValue, e);

484

}

485

}

486

487

@Override

488

public WriteCellData<?> convertToExcelData(LocalDateTime value,

489

ExcelContentProperty contentProperty,

490

GlobalConfiguration globalConfiguration) throws Exception {

491

if (value == null) {

492

return new WriteCellData<>("");

493

}

494

return new WriteCellData<>(value.format(FORMATTER));

495

}

496

}

497

498

// Usage in data class

499

public class EventData {

500

@ExcelProperty("Event Name")

501

private String name;

502

503

@ExcelProperty(value = "Event Date", converter = LocalDateTimeConverter.class)

504

private LocalDateTime eventDate;

505

506

@ExcelProperty("Description")

507

private String description;

508

509

// Getters and setters...

510

}

511

```

512

513

### Complex Object Converter

514

```java

515

import com.alibaba.excel.converters.Converter;

516

import com.alibaba.excel.enums.CellDataTypeEnum;

517

import com.fasterxml.jackson.databind.ObjectMapper;

518

519

// Complex object to convert

520

public class Address {

521

private String street;

522

private String city;

523

private String zipCode;

524

private String country;

525

526

// Constructors, getters, setters...

527

528

@Override

529

public String toString() {

530

return street + ", " + city + ", " + zipCode + ", " + country;

531

}

532

}

533

534

// JSON-based converter for complex objects

535

public class AddressConverter implements Converter<Address> {

536

private static final ObjectMapper objectMapper = new ObjectMapper();

537

538

@Override

539

public Class<?> supportJavaTypeKey() {

540

return Address.class;

541

}

542

543

@Override

544

public CellDataTypeEnum supportExcelTypeKey() {

545

return CellDataTypeEnum.STRING;

546

}

547

548

@Override

549

public Address convertToJavaData(ReadCellData<?> cellData,

550

ExcelContentProperty contentProperty,

551

GlobalConfiguration globalConfiguration) throws Exception {

552

String cellValue = cellData.getStringValue();

553

if (cellValue == null || cellValue.trim().isEmpty()) {

554

return null;

555

}

556

557

try {

558

// Try parsing as JSON first

559

if (cellValue.startsWith("{")) {

560

return objectMapper.readValue(cellValue, Address.class);

561

}

562

563

// Fallback to simple comma-separated format

564

String[] parts = cellValue.split(",");

565

if (parts.length >= 4) {

566

Address address = new Address();

567

address.setStreet(parts[0].trim());

568

address.setCity(parts[1].trim());

569

address.setZipCode(parts[2].trim());

570

address.setCountry(parts[3].trim());

571

return address;

572

}

573

574

throw new IllegalArgumentException("Invalid address format");

575

} catch (Exception e) {

576

throw new ExcelDataConvertException(

577

"Cannot convert address: " + cellValue, e);

578

}

579

}

580

581

@Override

582

public WriteCellData<?> convertToExcelData(Address value,

583

ExcelContentProperty contentProperty,

584

GlobalConfiguration globalConfiguration) throws Exception {

585

if (value == null) {

586

return new WriteCellData<>("");

587

}

588

589

// Write as JSON for full fidelity

590

try {

591

String json = objectMapper.writeValueAsString(value);

592

return new WriteCellData<>(json);

593

} catch (Exception e) {

594

// Fallback to string representation

595

return new WriteCellData<>(value.toString());

596

}

597

}

598

}

599

```

600

601

### Currency Converter with Localization

602

```java

603

import com.alibaba.excel.converters.Converter;

604

import com.alibaba.excel.enums.CellDataTypeEnum;

605

import java.math.BigDecimal;

606

import java.text.NumberFormat;

607

import java.util.Currency;

608

import java.util.Locale;

609

610

public class CurrencyConverter implements Converter<BigDecimal> {

611

private final Currency currency;

612

private final Locale locale;

613

private final NumberFormat currencyFormat;

614

615

public CurrencyConverter() {

616

this(Currency.getInstance("USD"), Locale.US);

617

}

618

619

public CurrencyConverter(Currency currency, Locale locale) {

620

this.currency = currency;

621

this.locale = locale;

622

this.currencyFormat = NumberFormat.getCurrencyInstance(locale);

623

this.currencyFormat.setCurrency(currency);

624

}

625

626

@Override

627

public Class<?> supportJavaTypeKey() {

628

return BigDecimal.class;

629

}

630

631

@Override

632

public CellDataTypeEnum supportExcelTypeKey() {

633

return CellDataTypeEnum.STRING; // Handle formatted currency strings

634

}

635

636

@Override

637

public BigDecimal convertToJavaData(ReadCellData<?> cellData,

638

ExcelContentProperty contentProperty,

639

GlobalConfiguration globalConfiguration) throws Exception {

640

String cellValue = cellData.getStringValue();

641

if (cellValue == null || cellValue.trim().isEmpty()) {

642

return null;

643

}

644

645

try {

646

// Remove currency symbols and parse

647

String cleanValue = cellValue.replaceAll("[^\\d.,+-]", "");

648

return new BigDecimal(cleanValue);

649

} catch (Exception e) {

650

throw new ExcelDataConvertException(

651

"Cannot parse currency: " + cellValue, e);

652

}

653

}

654

655

@Override

656

public WriteCellData<?> convertToExcelData(BigDecimal value,

657

ExcelContentProperty contentProperty,

658

GlobalConfiguration globalConfiguration) throws Exception {

659

if (value == null) {

660

return new WriteCellData<>("");

661

}

662

663

String formattedValue = currencyFormat.format(value);

664

return new WriteCellData<>(formattedValue);

665

}

666

}

667

668

// Usage with custom currency

669

public class SalesData {

670

@ExcelProperty("Product")

671

private String product;

672

673

@ExcelProperty(value = "Price", converter = CurrencyConverter.class)

674

private BigDecimal price;

675

676

@ExcelProperty("Quantity")

677

private Integer quantity;

678

679

// Getters and setters...

680

}

681

```

682

683

### Registering Custom Converters Globally

684

```java

685

import com.alibaba.excel.EasyExcel;

686

import com.alibaba.excel.write.builder.ExcelWriterBuilder;

687

688

// Register converters globally for reading

689

ExcelReaderBuilder readerBuilder = EasyExcel.read("data.xlsx", UserData.class, listener);

690

691

// Register custom converter (would be done through configuration in actual implementation)

692

// readerBuilder.registerConverter(new UserStatusConverter());

693

694

// For writing with custom converters

695

ExcelWriterBuilder writerBuilder = EasyExcel.write("output.xlsx", UserData.class);

696

697

// Register custom converter (would be done through configuration in actual implementation)

698

// writerBuilder.registerConverter(new UserStatusConverter());

699

700

writerBuilder.sheet("Users").doWrite(userData);

701

```

702

703

### Conditional Conversion Logic

704

```java

705

import com.alibaba.excel.converters.Converter;

706

import com.alibaba.excel.enums.CellDataTypeEnum;

707

708

public class SmartNumberConverter implements Converter<Number> {

709

@Override

710

public Class<?> supportJavaTypeKey() {

711

return Number.class;

712

}

713

714

@Override

715

public CellDataTypeEnum supportExcelTypeKey() {

716

return CellDataTypeEnum.STRING;

717

}

718

719

@Override

720

public Number convertToJavaData(ReadCellData<?> cellData,

721

ExcelContentProperty contentProperty,

722

GlobalConfiguration globalConfiguration) throws Exception {

723

String cellValue = cellData.getStringValue();

724

if (cellValue == null || cellValue.trim().isEmpty()) {

725

return null;

726

}

727

728

cellValue = cellValue.trim();

729

730

try {

731

// Detect if it's a percentage

732

if (cellValue.endsWith("%")) {

733

double value = Double.parseDouble(cellValue.substring(0, cellValue.length() - 1));

734

return value / 100.0; // Convert percentage to decimal

735

}

736

737

// Detect if it contains decimal point

738

if (cellValue.contains(".")) {

739

return Double.parseDouble(cellValue);

740

}

741

742

// Try as integer first

743

long longValue = Long.parseLong(cellValue);

744

if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {

745

return (int) longValue;

746

}

747

return longValue;

748

749

} catch (NumberFormatException e) {

750

throw new ExcelDataConvertException(

751

"Cannot parse number: " + cellValue, e);

752

}

753

}

754

755

@Override

756

public WriteCellData<?> convertToExcelData(Number value,

757

ExcelContentProperty contentProperty,

758

GlobalConfiguration globalConfiguration) throws Exception {

759

if (value == null) {

760

return new WriteCellData<>("");

761

}

762

763

// Format based on type

764

if (value instanceof Double || value instanceof Float) {

765

BigDecimal bd = BigDecimal.valueOf(value.doubleValue());

766

return new WriteCellData<>(bd.toPlainString());

767

}

768

769

return new WriteCellData<>(value.toString());

770

}

771

}

772

```