diff --git a/example/pom.xml b/example/pom.xml index 9e32182d..e9d0fc86 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -59,7 +59,7 @@ com.github.liaochong myexcel - 4.3.0.RC5 + 4.3.3 org.apache.logging.log4j diff --git a/pom.xml b/pom.xml index 2776b106..1d486d69 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.github.liaochong myexcel - 4.3.2 + 4.3.3 jar myexcel @@ -22,8 +22,8 @@ UTF-8 UTF-8 1.8 - 5.2.3 - 1.16.1 + 5.2.4 + 1.16.2 1.18.22 3.15.4.RELEASE 2.3 @@ -32,6 +32,7 @@ 3.1.1.RELEASE 5.0.3 4.0.1 + 5.0.0 5.8.2 3.9.4 1.10.0 @@ -111,6 +112,12 @@ ${javax.servlet-api.version} provided + + jakarta.servlet + jakarta.servlet-api + ${jakarta.servlet-api.version} + provided + org.junit.jupiter junit-jupiter-api diff --git a/src/main/java/com/github/liaochong/myexcel/core/AbstractSimpleExcelBuilder.java b/src/main/java/com/github/liaochong/myexcel/core/AbstractSimpleExcelBuilder.java index d8c7a434..ce99e189 100644 --- a/src/main/java/com/github/liaochong/myexcel/core/AbstractSimpleExcelBuilder.java +++ b/src/main/java/com/github/liaochong/myexcel/core/AbstractSimpleExcelBuilder.java @@ -495,10 +495,12 @@ protected List getPreElectionFields(ClassFieldContainer classFi } else { if (configuration.excludeParent) { preElectionFields = classFieldContainer.getDeclaredFields().stream() - .filter(fieldDefinition -> fieldDefinition.getField().isAnnotationPresent(ExcelColumn.class)) + .filter(fieldDefinition -> + fieldDefinition.getField().isAnnotationPresent(ExcelColumn.class) + || fieldDefinition.getField().isAnnotationPresent(MultiColumn.class)) .collect(Collectors.toList()); } else { - preElectionFields = classFieldContainer.getFieldsByAnnotation(ExcelColumn.class); + preElectionFields = classFieldContainer.getFieldsByAnnotation(ExcelColumn.class, MultiColumn.class); } } if (configuration.ignoreStaticFields) { @@ -506,9 +508,36 @@ protected List getPreElectionFields(ClassFieldContainer classFi .filter(fieldDefinition -> !Modifier.isStatic(fieldDefinition.getField().getModifiers())) .collect(Collectors.toList()); } + this.extractedMultiFieldDefinitions(preElectionFields); return preElectionFields; } + /** + * 提取嵌套的MultiColumn中导出列到顶层 + * + * @param preElectionFields 预选字段 + */ + private void extractedMultiFieldDefinitions(List preElectionFields) { + List multiFieldDefinitions = preElectionFields.stream() + .filter(preElectionField -> preElectionField.getField().isAnnotationPresent(MultiColumn.class) && preElectionField.getField().getType() != List.class) + .flatMap(preElectionField -> + // 这种方式会导致缺失第一个父字段,需要补全 + ReflectUtil.getWriteFieldDefinitionsOfExcelColumn(preElectionField.getField().getType()).stream() + .peek(fieldDefinition -> { + if (fieldDefinition.getParentFields() == null || fieldDefinition.getParentFields().isEmpty()) { + fieldDefinition.setParentFields(Collections.singletonList(preElectionField.getField())); + } else { + fieldDefinition.getParentFields().add(0, preElectionField.getField()); + } + }) + ).collect(Collectors.toList()); + if (multiFieldDefinitions.isEmpty()) { + return; + } + preElectionFields.removeIf(preElectionField -> preElectionField.getField().isAnnotationPresent(MultiColumn.class) && preElectionField.getField().getType() != List.class); + preElectionFields.addAll(multiFieldDefinitions); + } + /** * 展示字段order与标题title长度一致性自适应 */ diff --git a/src/main/java/com/github/liaochong/myexcel/core/converter/WriteConverterContext.java b/src/main/java/com/github/liaochong/myexcel/core/converter/WriteConverterContext.java index 271c93af..e27704bc 100644 --- a/src/main/java/com/github/liaochong/myexcel/core/converter/WriteConverterContext.java +++ b/src/main/java/com/github/liaochong/myexcel/core/converter/WriteConverterContext.java @@ -75,7 +75,7 @@ public static synchronized void registering(WriteConverter... writeConverters) { } public static Pair convert(FieldDefinition fieldDefinition, Object object, ConvertContext convertContext) { - Object result = ReflectUtil.getFieldValue(object, fieldDefinition); + Object result = getFieldVal(fieldDefinition, object); if (result == null) { return Constants.NULL_PAIR; } @@ -83,6 +83,30 @@ public static Pair convert(FieldDefinition fieldDefinit return writeConverter.convert(fieldDefinition.getField(), fieldDefinition.getField().getType(), result, convertContext); } + private static Object getFieldVal(FieldDefinition fieldDefinition, Object object) { + Object result; + if (fieldDefinition.getParentFields() == null + || fieldDefinition.getParentFields().isEmpty()) { + result = ReflectUtil.getFieldValue(object, fieldDefinition); + } else { + Object prevObj; + try { + prevObj = object; + for (int i = 0, size = fieldDefinition.getParentFields().size(); i < size; i++) { + Field parentField = fieldDefinition.getParentFields().get(i); + prevObj = parentField.get(prevObj); + } + if (prevObj == null) { + return null; + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + result = ReflectUtil.getFieldValue(prevObj, fieldDefinition); + } + return result; + } + public static WriteConverter getWriteConverter(Field field, Class fieldType, Object result, ConvertContext convertContext, List> writeConverterContainer) { WriteConverter writeConverter = convertContext.isConvertCsv ? CSV_CONVERTER_CACHE.get(Pair.of(field, fieldType)) : EXCEL_CONVERTER_CACHE.get(Pair.of(field, fieldType)); if (writeConverter != null) { diff --git a/src/main/java/com/github/liaochong/myexcel/utils/AttachmentV2ExportUtil.java b/src/main/java/com/github/liaochong/myexcel/utils/AttachmentV2ExportUtil.java new file mode 100644 index 00000000..bd9f80fb --- /dev/null +++ b/src/main/java/com/github/liaochong/myexcel/utils/AttachmentV2ExportUtil.java @@ -0,0 +1,154 @@ +/* + * Copyright 2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.liaochong.myexcel.utils; + +import com.github.liaochong.myexcel.core.constant.Constants; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.codec.CharEncoding; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.crypt.EncryptionMode; +import org.apache.poi.poifs.crypt.Encryptor; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.GeneralSecurityException; + +/** + * 附件导出工具类 + * + * @author liaochong + * @version 1.0 + */ +public final class AttachmentV2ExportUtil { + + /** + * 导出 + * + * @param workbook workbook + * @param fileName file name,suffix is not required,and it is not recommended to carry a suffix + * @param response HttpServletResponse + */ + public static void export(Workbook workbook, String fileName, HttpServletResponse response) { + try { + String suffix = Constants.XLSX; + if (workbook instanceof HSSFWorkbook) { + if (fileName.endsWith(suffix)) { + fileName = fileName.substring(0, fileName.length() - 1); + } + suffix = Constants.XLS; + response.setContentType("application/vnd.ms-excel"); + } else { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + } + if (!fileName.endsWith(suffix)) { + fileName += suffix; + } + setAttachmentConfig(fileName, response); + workbook.write(response.getOutputStream()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + clear(workbook); + } + } + + /** + * 加密导出 + * + * @param workbook workbook + * @param fileName fileName + * @param response response + * @param password password + */ + public static void encryptExport(final Workbook workbook, String fileName, HttpServletResponse response, final String password) { + if (workbook instanceof HSSFWorkbook) { + throw new IllegalArgumentException("Document encryption for.xls is not supported"); + } + Path path = null; + try { + String suffix = Constants.XLSX; + path = TempFileOperator.createTempFile("encrypt_temp", suffix); + workbook.write(Files.newOutputStream(path)); + + final POIFSFileSystem fs = new POIFSFileSystem(); + final EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard); + final Encryptor enc = info.getEncryptor(); + enc.confirmPassword(password); + + try (OPCPackage opc = OPCPackage.open(path.toFile(), PackageAccess.READ_WRITE); + OutputStream os = enc.getDataStream(fs)) { + opc.save(os); + } + if (!fileName.endsWith(suffix)) { + fileName += suffix; + } + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + setAttachmentConfig(fileName, response); + fs.writeFilesystem(response.getOutputStream()); + } catch (IOException | InvalidFormatException | GeneralSecurityException e) { + throw new RuntimeException(e); + } finally { + clear(workbook); + TempFileOperator.deleteTempFile(path); + } + } + + private static void clear(Workbook workbook) { + if (workbook instanceof SXSSFWorkbook) { + ((SXSSFWorkbook) workbook).dispose(); + } + try { + workbook.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 一般文件导出接口 + * + * @param path 文件 + * @param fileName 导出后文件名称 + * @param response 响应流 + */ + public static void export(Path path, String fileName, HttpServletResponse response) { + try { + response.setContentType("application/octet-stream"); + setAttachmentConfig(fileName, response); + response.getOutputStream().write(Files.readAllBytes(path)); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + TempFileOperator.deleteTempFile(path); + } + } + + private static void setAttachmentConfig(String fileName, HttpServletResponse response) throws UnsupportedEncodingException { + response.setCharacterEncoding(CharEncoding.UTF_8); + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, CharEncoding.UTF_8).replace("+", "%20")); + } +} diff --git a/src/main/java/com/github/liaochong/myexcel/utils/ReflectUtil.java b/src/main/java/com/github/liaochong/myexcel/utils/ReflectUtil.java index db3b679c..2812d21c 100644 --- a/src/main/java/com/github/liaochong/myexcel/utils/ReflectUtil.java +++ b/src/main/java/com/github/liaochong/myexcel/utils/ReflectUtil.java @@ -28,6 +28,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -60,6 +61,56 @@ public static ClassFieldContainer getAllFieldsOfClass(Class clazz) { return container; } + public static List getWriteFieldDefinitionsOfExcelColumn(Class dataType) { + if (dataType == Map.class) { + return Collections.emptyList(); + } + List fieldDefinitions = new ArrayList<>(); + getWriteFieldDefinition(dataType, fieldDefinitions, null, 0); + return fieldDefinitions; + } + + private static void getWriteFieldDefinition(Class dataType, List fieldDefinitions, List parentFields, int level) { + ClassFieldContainer classFieldContainer = ReflectUtil.getAllFieldsOfClass(dataType); + List fields = classFieldContainer.getFieldsByAnnotation(ExcelColumn.class, MultiColumn.class); + if (level == 0 && fields.isEmpty()) { + // If no field contains an ExcelColumn annotation, all fields are read in the default order + List allFields = classFieldContainer.getFields(); + for (int i = 0, size = allFields.size(); i < size; i++) { + fieldDefinitions.add(allFields.get(i)); + } + } else { + List topParentFields = new LinkedList<>(); + if (parentFields != null) { + topParentFields.addAll(parentFields); + } + for (FieldDefinition fieldDefinition : fields) { + if (level == 0) { + parentFields = new LinkedList<>(); + } + Field field = fieldDefinition.getField(); + if (field.isAnnotationPresent(MultiColumn.class)) { + MultiColumn multiColumn = field.getAnnotation(MultiColumn.class); + List childrenParentFields = new LinkedList<>(topParentFields); + childrenParentFields.add(field); + if (ReadConverterContext.support(multiColumn.classType())) { + field.setAccessible(true); + fieldDefinition = new FieldDefinition(field); + fieldDefinition.setParentFields(parentFields.isEmpty() ? Collections.emptyList() : parentFields); + fieldDefinitions.add(fieldDefinition); + } else { + getWriteFieldDefinition(multiColumn.classType(), fieldDefinitions, childrenParentFields, level + 1); + } + } else { + field.setAccessible(true); + fieldDefinition = new FieldDefinition(field); + fieldDefinition.setParentFields(parentFields.isEmpty() ? Collections.emptyList() : parentFields); + fieldDefinitions.add(fieldDefinition); + } + } + } + } + public static Map getFieldDefinitionMapOfExcelColumn(Class dataType) { if (dataType == Map.class) { return Collections.emptyMap(); diff --git a/src/test/java/com/github/liaochong/myexcel/core/DefaultExcelReaderTest.java b/src/test/java/com/github/liaochong/myexcel/core/DefaultExcelReaderTest.java index de7b9809..5f7cfcb6 100644 --- a/src/test/java/com/github/liaochong/myexcel/core/DefaultExcelReaderTest.java +++ b/src/test/java/com/github/liaochong/myexcel/core/DefaultExcelReaderTest.java @@ -34,7 +34,7 @@ public void readXlsxPicture() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/picture.xlsx"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); List pictures = DefaultExcelReader.of(Picture.class).read(path.toFile()); - System.out.println(""); + System.out.println(); } @Test @@ -42,7 +42,7 @@ public void readXlsPicture() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/picture.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); List pictures = DefaultExcelReader.of(Picture.class).read(path.toFile()); - System.out.println(""); + System.out.println(); } @Test @@ -50,8 +50,8 @@ public void readWithSheetName() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/common_build.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); - List list = DefaultExcelReader.of(CommonPeople.class).sheet("工作表2").rowFilter(row -> row.getRowNum() > 0).read(path.toFile()); - System.out.println(""); + List list = DefaultExcelReader.of(CommonPeople.class).sheet("工作表2").rowFilter(row -> row.getRowNum() > 1).read(path.toFile()); + System.out.println(); } @Test @@ -61,8 +61,8 @@ public void readStartSheet() throws Exception { List list = DefaultExcelReader.of(CommonPeople.class).sheet("工作表2") .startSheet(sheet -> System.out.println(sheet.getLastRowNum())) - .rowFilter(row -> row.getRowNum() > 0).read(path.toFile()); - System.out.println(""); + .rowFilter(row -> row.getRowNum() > 2).read(path.toFile()); + System.out.println(); } @Test @@ -72,9 +72,9 @@ public void readThenStartSheet() throws Exception { DefaultExcelReader.of(CommonPeople.class).sheet("工作表2") .startSheet(sheet -> System.out.println(sheet.getLastRowNum())) - .rowFilter(row -> row.getRowNum() > 0).readThen(path.toFile(), d -> { + .rowFilter(row -> row.getRowNum() > 1).readThen(path.toFile(), d -> { System.out.println(d.getCats()); }); - System.out.println(""); + System.out.println(); } } diff --git a/src/test/java/com/github/liaochong/myexcel/core/DefaultStreamExcelBuilderTest.java b/src/test/java/com/github/liaochong/myexcel/core/DefaultStreamExcelBuilderTest.java index fae089c9..cc06ba9d 100644 --- a/src/test/java/com/github/liaochong/myexcel/core/DefaultStreamExcelBuilderTest.java +++ b/src/test/java/com/github/liaochong/myexcel/core/DefaultStreamExcelBuilderTest.java @@ -2,6 +2,7 @@ import com.github.liaochong.myexcel.core.pojo.CommonPeople; import com.github.liaochong.myexcel.core.pojo.CustomStylePeople; +import com.github.liaochong.myexcel.core.pojo.Extention; import com.github.liaochong.myexcel.core.pojo.Formula; import com.github.liaochong.myexcel.core.pojo.MultiPeople; import com.github.liaochong.myexcel.core.pojo.OddEvenStylePeople; @@ -25,7 +26,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; /** @@ -63,6 +63,7 @@ void mapBuild() throws Exception { void commonBuild() throws Exception { try (DefaultStreamExcelBuilder excelBuilder = DefaultStreamExcelBuilder.of(CommonPeople.class) .fixedTitles() + .autoMerge() // .hideColumns(0, 1) // .globalStyle("background-color:red;", "title->background-color:yellow;") .start()) { @@ -288,29 +289,32 @@ private void multiData(DefaultStreamExcelBuilder excelBuilder) { private void data(DefaultStreamExcelBuilder excelBuilder, int size) { BigDecimal oddMoney = new BigDecimal(109898); BigDecimal evenMoney = new BigDecimal(66666); - List futures = new LinkedList<>(); List ss = new ArrayList<>(); ss.add("1"); ss.add("2"); for (int i = 0; i < size; i++) { int index = i; - CompletableFuture future = CompletableFuture.runAsync(() -> { - CommonPeople commonPeople = new CommonPeople(); - boolean odd = index % 2 == 0; - commonPeople.setName(odd ? "张三" : "李四"); - commonPeople.setAge(odd ? 18 : 24); - commonPeople.setDance(odd); - commonPeople.setMoney(odd ? oddMoney : evenMoney); - commonPeople.setBirthday(new Date()); - commonPeople.setLocalDate(LocalDate.now()); - commonPeople.setLocalDateTime(LocalDateTime.now()); - commonPeople.setCats(100L); - commonPeople.setMarried(odd); - excelBuilder.append(commonPeople); - }); - futures.add(future); + CommonPeople commonPeople = new CommonPeople(); + boolean odd = index % 2 == 0; + commonPeople.setName(odd ? "张三" : "李四"); + commonPeople.setAge(odd ? 18 : 24); + commonPeople.setDance(odd); + commonPeople.setMoney(odd ? oddMoney : evenMoney); + commonPeople.setBirthday(new Date()); + commonPeople.setLocalDate(LocalDate.now()); + commonPeople.setLocalDateTime(LocalDateTime.now()); + commonPeople.setCats(100L); + commonPeople.setMarried(odd); + Extention extention = new Extention(); + commonPeople.setExtention(extention); + extention.setName1("name1" + index); + List list = new LinkedList<>(); + for (int j = 0; j < 10; j++) { + list.add(j * 20); + } + extention.setAge1(list); + excelBuilder.append(commonPeople); } - futures.forEach(CompletableFuture::join); } private List dataList() { diff --git a/src/test/java/com/github/liaochong/myexcel/core/SaxExcelReaderTest.java b/src/test/java/com/github/liaochong/myexcel/core/SaxExcelReaderTest.java index d5ab3ad4..5059c1a9 100644 --- a/src/test/java/com/github/liaochong/myexcel/core/SaxExcelReaderTest.java +++ b/src/test/java/com/github/liaochong/myexcel/core/SaxExcelReaderTest.java @@ -83,7 +83,7 @@ void readXlsFile() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/common_build.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); - List commonPeoples = SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 0) + List commonPeoples = SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 1) .sheets(0, 1) .read(path.toFile()); System.out.println(commonPeoples.size()); @@ -106,7 +106,7 @@ void readXlsFileWithName() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/common_build.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); - List commonPeoples = SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 0) + List commonPeoples = SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 1) .sheets("人员信息", "工作表2") .read(path.toFile()); System.out.println(commonPeoples.size()); @@ -250,7 +250,7 @@ void readWithContextCustomer() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/common_build.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); - SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 0).readThen(Files.newInputStream(path), (d, context) -> { + SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 1).readThen(Files.newInputStream(path), (d, context) -> { System.out.println(d); }); } @@ -260,7 +260,7 @@ void readWithContextFunction() throws Exception { URL htmlToExcelEampleURL = this.getClass().getResource("/common_build.xls"); Path path = Paths.get(htmlToExcelEampleURL.toURI()); - SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 0).readThen(Files.newInputStream(path), (d, context) -> { + SaxExcelReader.of(CommonPeople.class).rowFilter(row -> row.getRowNum() > 1).readThen(Files.newInputStream(path), (d, context) -> { System.out.println(d); return true; }); diff --git a/src/test/java/com/github/liaochong/myexcel/core/pojo/CommonPeople.java b/src/test/java/com/github/liaochong/myexcel/core/pojo/CommonPeople.java index 751aae84..d6b836c6 100644 --- a/src/test/java/com/github/liaochong/myexcel/core/pojo/CommonPeople.java +++ b/src/test/java/com/github/liaochong/myexcel/core/pojo/CommonPeople.java @@ -15,6 +15,7 @@ package com.github.liaochong.myexcel.core.pojo; import com.github.liaochong.myexcel.core.annotation.ExcelColumn; +import com.github.liaochong.myexcel.core.annotation.MultiColumn; import com.github.liaochong.myexcel.core.annotation.Prompt; import lombok.AccessLevel; import lombok.Data; @@ -39,4 +40,8 @@ public class CommonPeople extends Person { @ExcelColumn(prompt = @Prompt(title = "提示", text = "这是我的提示哦")) Long cats; + + @MultiColumn(classType = Extention.class) + Extention extention; + } diff --git a/src/test/java/com/github/liaochong/myexcel/core/pojo/Extention.java b/src/test/java/com/github/liaochong/myexcel/core/pojo/Extention.java new file mode 100644 index 00000000..19de7da0 --- /dev/null +++ b/src/test/java/com/github/liaochong/myexcel/core/pojo/Extention.java @@ -0,0 +1,38 @@ +/* + * Copyright 2019 liaochong + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.liaochong.myexcel.core.pojo; + +import com.github.liaochong.myexcel.core.annotation.ExcelColumn; +import com.github.liaochong.myexcel.core.annotation.MultiColumn; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +/** + * @author liaochong + * @version 1.0 + */ +@Setter +@Getter +public class Extention { + + @ExcelColumn(title = "name1") + private String name1; + + @MultiColumn(classType = Integer.class) + @ExcelColumn(title = "age1") + private List age1; +} diff --git a/src/test/resources/common_build.xls b/src/test/resources/common_build.xls index 8393af02..28f3820b 100644 Binary files a/src/test/resources/common_build.xls and b/src/test/resources/common_build.xls differ diff --git a/src/test/resources/templates/freemarkerToExcelExample.ftl b/src/test/resources/templates/freemarkerToExcelExample.ftl index ae32acd9..c09e260b 100644 --- a/src/test/resources/templates/freemarkerToExcelExample.ftl +++ b/src/test/resources/templates/freemarkerToExcelExample.ftl @@ -2,7 +2,7 @@ ${sheetName} - 产品介绍 + *产品介绍 <#list titles as title> diff --git "a/src/test/resources/\346\212\245\345\220\215\350\241\250.xls" "b/src/test/resources/\346\212\245\345\220\215\350\241\250.xls" new file mode 100644 index 00000000..8518c9b7 Binary files /dev/null and "b/src/test/resources/\346\212\245\345\220\215\350\241\250.xls" differ