From d2c8d205dea5a36196a3656f41c47c32c855055e Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Mon, 23 Sep 2019 19:56:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=80=9A=E8=BF=87=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=A1=AB=E5=85=85=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/alibaba/excel/ExcelWriter.java | 12 +++ .../com/alibaba/excel/util/WorkBookUtil.java | 1 + .../com/alibaba/excel/write/ExcelBuilder.java | 8 ++ .../alibaba/excel/write/ExcelBuilderImpl.java | 62 +++++++----- .../builder/ExcelWriterSheetBuilder.java | 8 ++ .../metadata/holder/WriteWorkbookHolder.java | 16 +++- .../easyexcel/test/core/fill/FillData.java | 15 +++ .../test/core/fill/FillDataTest.java | 90 ++++++++++++++++++ .../easyexcel/test/temp/poi/PoiTest.java | 69 ++++++++++++++ src/test/resources/fill/simple.xlsx | Bin 0 -> 10112 bytes 10 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java create mode 100644 src/test/resources/fill/simple.xlsx diff --git a/src/main/java/com/alibaba/excel/ExcelWriter.java b/src/main/java/com/alibaba/excel/ExcelWriter.java index c99787d..d32d7ee 100644 --- a/src/main/java/com/alibaba/excel/ExcelWriter.java +++ b/src/main/java/com/alibaba/excel/ExcelWriter.java @@ -155,6 +155,18 @@ public class ExcelWriter { return this; } + /** + * Fill value to a sheet + * + * @param data + * @param writeSheet + * @return + */ + public ExcelWriter fill(Object data, WriteSheet writeSheet) { + excelBuilder.fill(data, writeSheet); + return this; + } + /** * Write data to a sheet * diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index b9579b1..78cbd27 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -37,6 +37,7 @@ public class WorkBookUtil { // When using SXSSFWorkbook, you can't get the actual last line.But we need to read the last line when we // are using the template, so we cache it if (xssfWorkbook != null) { + writeWorkbookHolder.setXssfWorkbook(xssfWorkbook); for (int i = 0; i < xssfWorkbook.getNumberOfSheets(); i++) { writeWorkbookHolder.getTemplateLastRowMap().put(i, xssfWorkbook.getSheetAt(i).getLastRowNum()); } diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java index 119854a..0570d64 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilder.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilder.java @@ -35,6 +35,14 @@ public interface ExcelBuilder { */ void addContent(List data, WriteSheet writeSheet, WriteTable writeTable); + /** + * WorkBook fill value + * + * @param data + * @param writeSheet + */ + void fill(Object data, WriteSheet writeSheet); + /** * Creates new cell range. Indexes are zero-based. * diff --git a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java index a7cc6b5..cedec44 100644 --- a/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java +++ b/src/main/java/com/alibaba/excel/write/ExcelBuilderImpl.java @@ -2,12 +2,13 @@ package com.alibaba.excel.write; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -15,7 +16,6 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; @@ -109,6 +109,7 @@ public class ExcelBuilderImpl implements ExcelBuilder { } } + @Override public void fill(Object data, WriteSheet writeSheet) { try { if (context.writeWorkbookHolder().getTemplateFile() == null @@ -127,17 +128,14 @@ public class ExcelBuilderImpl implements ExcelBuilder { } private void doFill(Object data) { - BeanMap beanMap = BeanMap.create(data); WriteSheetHolder writeSheetHolder = context.writeSheetHolder(); - Sheet sheet = writeSheetHolder.getSheet(); Map templateLastRowMap = context.writeWorkbookHolder().getTemplateLastRowMap(); - if (!templateLastRowMap.containsKey(writeSheetHolder.getSheetNo())) { + if (sheet == null) { throw new ExcelGenerateException( "The corresponding table cannot be found,sheetNo:" + writeSheetHolder.getSheetNo()); } - Map analysisCellMap = new HashMap(16); - + List analysisCellList = new ArrayList(); for (int i = 0; i < templateLastRowMap.get(writeSheetHolder.getSheetNo()); i++) { Row row = sheet.getRow(i); for (int j = 0; j < row.getLastCellNum(); j++) { @@ -150,29 +148,49 @@ public class ExcelBuilderImpl implements ExcelBuilder { List variableList = new ArrayList(); analysisCell.setVariableList(variableList); boolean matches = true; + int index = 0; while (matches) { - + Matcher matcher = FILL_PATTERN.matcher(value); + String variable = value.substring(matcher.start(), matcher.end()); + variableList.add(variable); + value = matcher.replaceFirst("{" + index++ + "}"); matches = FILL_PATTERN.matcher(value).matches(); + analysisCellList.add(analysisCell); } - } } - } - if (CollectionUtils.isEmpty(data)) { - return; - } - WriteSheetHolder writeSheetHolder = context.writeSheetHolder(); - int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); - if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) { - newRowIndex += context.currentWriteHolder().relativeHeadRowIndex(); + if (data instanceof Collection) { + + } else if (data instanceof Map) { + + } else { + } - // BeanMap is out of order,so use fieldList - List fieldList = new ArrayList(); - for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) { - int n = relativeRowIndex + newRowIndex; - addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList); + BeanMap beanMap = BeanMap.create(data); + + for (AnalysisCell analysisCell : analysisCellList) { + Cell cell = sheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex()); + if (analysisCell.getVariableList().size() == 1) { + Object value = beanMap.get(analysisCell.getVariableList().get(0)); + if (value == null) { + continue; + } + converterAndSet(writeSheetHolder, value.getClass(), cell, value, null); + } else { + List fileDataStringList = new ArrayList(); + for (String variable : analysisCell.getVariableList()) { + Object value = beanMap.get(variable); + CellData cellData = convert(writeSheetHolder, String.class, cell, value, null); + String fillDataString = cellData.getStringValue(); + if (fillDataString == null) { + fillDataString = ""; + } + fileDataStringList.add(fillDataString); + } + cell.setCellValue(String.format(analysisCell.getPrepareData(), fileDataStringList)); + } } } diff --git a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java index bab837d..29e8277 100644 --- a/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java +++ b/src/main/java/com/alibaba/excel/write/builder/ExcelWriterSheetBuilder.java @@ -135,6 +135,14 @@ public class ExcelWriterSheetBuilder { excelWriter.finish(); } + public void doFill(Object data) { + if (excelWriter == null) { + throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); + } + excelWriter.fill(data, build()); + excelWriter.finish(); + } + public ExcelWriterTableBuilder table() { return table(null); } diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java index d3c07f5..20e1f1f 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,12 +25,15 @@ import com.alibaba.excel.write.metadata.WriteWorkbook; * @author Jiaju Zhuang */ public class WriteWorkbookHolder extends AbstractWriteHolder { - private static final Logger LOGGER = LoggerFactory.getLogger(WriteWorkbookHolder.class); /*** * poi Workbook */ private Workbook workbook; - + /** + * When reading version 07 with the template, the workbook cannot get the specific line number, so it + * needs to get the specific line number. + */ + private XSSFWorkbook xssfWorkbook; /** * current param */ @@ -130,6 +134,14 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.workbook = workbook; } + public XSSFWorkbook getXssfWorkbook() { + return xssfWorkbook; + } + + public void setXssfWorkbook(XSSFWorkbook xssfWorkbook) { + this.xssfWorkbook = xssfWorkbook; + } + public Map getHasBeenInitializedSheet() { return hasBeenInitializedSheet; } diff --git a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java new file mode 100644 index 0000000..92e18a8 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillData.java @@ -0,0 +1,15 @@ +package com.alibaba.easyexcel.test.core.fill; + +import com.alibaba.excel.annotation.format.NumberFormat; + +import lombok.Data; + +/** + * @author Jiaju Zhuang + */ +@Data +public class FillData { + private String name; + @NumberFormat("0#") + private double number; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java new file mode 100644 index 0000000..06236ca --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java @@ -0,0 +1,90 @@ +package com.alibaba.easyexcel.test.core.fill; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.alibaba.easyexcel.test.core.style.StyleData; +import com.alibaba.easyexcel.test.core.style.StyleDataListener; +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.merge.LoopMergeStrategy; +import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.metadata.style.WriteFont; +import com.alibaba.excel.write.style.AbstractVerticalCellStyleStrategy; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; +import com.alibaba.excel.write.style.row.SimpleRowHeightStyleStrategy; + +/** + * + * @author Jiaju Zhuang + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class FillDataTest { + + private static File file07; + private static File file03; + private static File simpleTemplate07; + + @BeforeClass + public static void init() { + file07 = TestFileUtil.createNewFile("fill07.xlsx"); + file03 = TestFileUtil.createNewFile("fill03.xls"); + simpleTemplate07 = TestFileUtil.readFile("fill" + File.separator + "simple.xlsx"); + } + + @Test + public void t01Fill07() { + fill(file07); + } + + @Test + public void t02Fill03() { + fill(file03); + } + + private void fill(File file) { + FillData fillData = new FillData(); + fillData.setName("张三"); + fillData.setNumber(5.2); + EasyExcel.write(file).withTemplate(simpleTemplate07).sheet().doFill(fillData); + } + + private List data() { + List list = new ArrayList(); + StyleData data = new StyleData(); + data.setString("字符串0"); + data.setString1("字符串01"); + StyleData data1 = new StyleData(); + data1.setString("字符串1"); + data1.setString1("字符串11"); + list.add(data); + list.add(data1); + return list; + } + + private List data10() { + List list = new ArrayList(); + for (int i = 0; i < 10; i++) { + StyleData data = new StyleData(); + data.setString("字符串0"); + data.setString1("字符串01"); + list.add(data); + } + return list; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java index ea6dba1..5f48760 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/poi/PoiTest.java @@ -1,8 +1,12 @@ package com.alibaba.easyexcel.test.temp.poi; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.streaming.SXSSFRow; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; @@ -49,4 +53,69 @@ public class PoiTest { xssfSheet.createRow(20); LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); } + + @Test + public void lastRowNum233() throws IOException { + String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; + Workbook xx=new XSSFWorkbook(file); + + SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(); + Sheet xssfSheet = xssfWorkbook.getXSSFWorkbook().getSheetAt(0); + + Cell cell = xssfSheet.getRow(0).createCell(9); + cell.setCellValue("testssdf是士大夫否t"); + + FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx"); + xssfWorkbook.write(fileout); + xssfWorkbook.close(); + } + + + @Test + public void lastRowNum2332222() throws IOException { + String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; + Workbook xx=new XSSFWorkbook(file); + SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(); + Sheet xssfSheet = xssfWorkbook.getXSSFWorkbook().getSheetAt(0); + + Cell cell = xssfSheet.getRow(0).createCell(9); + cell.setCellValue("testssdf是士大夫否t"); + + FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx"); + xssfWorkbook.write(fileout); + } + + @Test + public void lastRowNum23443() throws IOException { + String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; + SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(file)); + Sheet xssfSheet = xssfWorkbook.getSheetAt(0); + + FileOutputStream fileout = new FileOutputStream("d://test/r2" + System.currentTimeMillis() + ".xlsx"); + xssfWorkbook.write(fileout); + xssfWorkbook.close(); + } + + @Test + public void lastRowNum2() throws IOException { + String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; + SXSSFWorkbook xssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(file)); + Sheet xssfSheet = xssfWorkbook.getXSSFWorkbook().getSheetAt(0); + LOGGER.info("一共行数:{}", xssfSheet.getPhysicalNumberOfRows()); + LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); + LOGGER.info("一共行数:{}", xssfSheet.getFirstRowNum()); + + } + + @Test + public void lastRowNumXSSF2() throws IOException { + String file = TestFileUtil.getPath() + "fill" + File.separator + "simple.xlsx"; + XSSFWorkbook xssfWorkbook = new XSSFWorkbook(file); + LOGGER.info("一共:{}个sheet", xssfWorkbook.getNumberOfSheets()); + XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0); + LOGGER.info("一共行数:{}", xssfSheet.getLastRowNum()); + XSSFRow row = xssfSheet.getRow(0); + LOGGER.info("第一行数据:{}", row); + } + } diff --git a/src/test/resources/fill/simple.xlsx b/src/test/resources/fill/simple.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b5d7e19a6dec1887a13c7f9cade7b82eaad3b360 GIT binary patch literal 10112 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 literal 0 HcmV?d00001