From 5a9f073643053358756a0f4fe6051de29d41d13f Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Tue, 7 Sep 2021 18:36:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=83=A8=E5=88=86=E6=94=AF?= =?UTF-8?q?=E6=8C=81csv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../java/com/alibaba/excel/csv/CsvCell.java | 225 ++++++ .../com/alibaba/excel/csv/CsvCellStyle.java | 301 ++++++++ .../com/alibaba/excel/csv/CsvDataFormat.java | 15 + .../java/com/alibaba/excel/csv/CsvRow.java | 143 ++++ .../java/com/alibaba/excel/csv/CsvSheet.java | 676 ++++++++++++++++++ .../com/alibaba/excel/csv/CsvWorkbook.java | 358 ++++++++++ .../alibaba/excel/support/ExcelTypeEnum.java | 6 + .../com/alibaba/excel/util/WorkBookUtil.java | 76 +- .../excel/write/metadata/WriteSheet.java | 59 +- .../metadata/holder/WriteWorkbookHolder.java | 17 +- .../easyexcel/test/demo/web/WebTest.java | 15 +- .../alibaba/easyexcel/test/temp/LockTest.java | 10 +- .../easyexcel/test/temp/csv/CsvData.java | 28 + .../easyexcel/test/temp/csv/CsvReadTest.java | 86 +++ .../test/temp/read/HeadReadTest.java | 1 + 16 files changed, 1919 insertions(+), 102 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/csv/CsvCell.java create mode 100644 src/main/java/com/alibaba/excel/csv/CsvCellStyle.java create mode 100644 src/main/java/com/alibaba/excel/csv/CsvDataFormat.java create mode 100644 src/main/java/com/alibaba/excel/csv/CsvRow.java create mode 100644 src/main/java/com/alibaba/excel/csv/CsvSheet.java create mode 100644 src/main/java/com/alibaba/excel/csv/CsvWorkbook.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java create mode 100644 src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java diff --git a/pom.xml b/pom.xml index 6477cfef..2466e22f 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,11 @@ poi-ooxml-schemas 4.1.2 + + org.apache.commons + commons-csv + 1.8 + cglib cglib diff --git a/src/main/java/com/alibaba/excel/csv/CsvCell.java b/src/main/java/com/alibaba/excel/csv/CsvCell.java new file mode 100644 index 00000000..9c3a5d22 --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvCell.java @@ -0,0 +1,225 @@ +package com.alibaba.excel.csv; + +import java.time.LocalDateTime; +import java.util.Calendar; +import java.util.Date; + +import org.apache.poi.ss.formula.FormulaParseException; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.Hyperlink; +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.CellAddress; +import org.apache.poi.ss.util.CellRangeAddress; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +public class CsvCell implements Cell { + + @Override + public int getColumnIndex() { + return 0; + } + + @Override + public int getRowIndex() { + return 0; + } + + @Override + public Sheet getSheet() { + return null; + } + + @Override + public Row getRow() { + return null; + } + + @Override + public void setCellType(CellType cellType) { + + } + + @Override + public void setBlank() { + + } + + @Override + public CellType getCellType() { + return null; + } + + @Override + public CellType getCellTypeEnum() { + return null; + } + + @Override + public CellType getCachedFormulaResultType() { + return null; + } + + @Override + public CellType getCachedFormulaResultTypeEnum() { + return null; + } + + @Override + public void setCellValue(double value) { + + } + + @Override + public void setCellValue(Date value) { + + } + + @Override + public void setCellValue(LocalDateTime value) { + + } + + @Override + public void setCellValue(Calendar value) { + + } + + @Override + public void setCellValue(RichTextString value) { + + } + + @Override + public void setCellValue(String value) { + + } + + @Override + public void setCellFormula(String formula) throws FormulaParseException, IllegalStateException { + + } + + @Override + public void removeFormula() throws IllegalStateException { + + } + + @Override + public String getCellFormula() { + return null; + } + + @Override + public double getNumericCellValue() { + return 0; + } + + @Override + public Date getDateCellValue() { + return null; + } + + @Override + public LocalDateTime getLocalDateTimeCellValue() { + return null; + } + + @Override + public RichTextString getRichStringCellValue() { + return null; + } + + @Override + public String getStringCellValue() { + return null; + } + + @Override + public void setCellValue(boolean value) { + + } + + @Override + public void setCellErrorValue(byte value) { + + } + + @Override + public boolean getBooleanCellValue() { + return false; + } + + @Override + public byte getErrorCellValue() { + return 0; + } + + @Override + public void setCellStyle(CellStyle style) { + + } + + @Override + public CellStyle getCellStyle() { + return null; + } + + @Override + public void setAsActiveCell() { + + } + + @Override + public CellAddress getAddress() { + return null; + } + + @Override + public void setCellComment(Comment comment) { + + } + + @Override + public Comment getCellComment() { + return null; + } + + @Override + public void removeCellComment() { + + } + + @Override + public Hyperlink getHyperlink() { + return null; + } + + @Override + public void setHyperlink(Hyperlink link) { + + } + + @Override + public void removeHyperlink() { + + } + + @Override + public CellRangeAddress getArrayFormulaRange() { + return null; + } + + @Override + public boolean isPartOfArrayFormulaGroup() { + return false; + } +} diff --git a/src/main/java/com/alibaba/excel/csv/CsvCellStyle.java b/src/main/java/com/alibaba/excel/csv/CsvCellStyle.java new file mode 100644 index 00000000..318b42a4 --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvCellStyle.java @@ -0,0 +1,301 @@ +package com.alibaba.excel.csv; + +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Color; +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.VerticalAlignment; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +public class CsvCellStyle implements CellStyle { + @Override + public short getIndex() { + return 0; + } + + @Override + public void setDataFormat(short fmt) { + + } + + @Override + public short getDataFormat() { + return 0; + } + + @Override + public String getDataFormatString() { + return null; + } + + @Override + public void setFont(Font font) { + + } + + @Override + public short getFontIndex() { + return 0; + } + + @Override + public int getFontIndexAsInt() { + return 0; + } + + @Override + public void setHidden(boolean hidden) { + + } + + @Override + public boolean getHidden() { + return false; + } + + @Override + public void setLocked(boolean locked) { + + } + + @Override + public boolean getLocked() { + return false; + } + + @Override + public void setQuotePrefixed(boolean quotePrefix) { + + } + + @Override + public boolean getQuotePrefixed() { + return false; + } + + @Override + public void setAlignment(HorizontalAlignment align) { + + } + + @Override + public HorizontalAlignment getAlignment() { + return null; + } + + @Override + public HorizontalAlignment getAlignmentEnum() { + return null; + } + + @Override + public void setWrapText(boolean wrapped) { + + } + + @Override + public boolean getWrapText() { + return false; + } + + @Override + public void setVerticalAlignment(VerticalAlignment align) { + + } + + @Override + public VerticalAlignment getVerticalAlignment() { + return null; + } + + @Override + public VerticalAlignment getVerticalAlignmentEnum() { + return null; + } + + @Override + public void setRotation(short rotation) { + + } + + @Override + public short getRotation() { + return 0; + } + + @Override + public void setIndention(short indent) { + + } + + @Override + public short getIndention() { + return 0; + } + + @Override + public void setBorderLeft(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderLeft() { + return null; + } + + @Override + public BorderStyle getBorderLeftEnum() { + return null; + } + + @Override + public void setBorderRight(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderRight() { + return null; + } + + @Override + public BorderStyle getBorderRightEnum() { + return null; + } + + @Override + public void setBorderTop(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderTop() { + return null; + } + + @Override + public BorderStyle getBorderTopEnum() { + return null; + } + + @Override + public void setBorderBottom(BorderStyle border) { + + } + + @Override + public BorderStyle getBorderBottom() { + return null; + } + + @Override + public BorderStyle getBorderBottomEnum() { + return null; + } + + @Override + public void setLeftBorderColor(short color) { + + } + + @Override + public short getLeftBorderColor() { + return 0; + } + + @Override + public void setRightBorderColor(short color) { + + } + + @Override + public short getRightBorderColor() { + return 0; + } + + @Override + public void setTopBorderColor(short color) { + + } + + @Override + public short getTopBorderColor() { + return 0; + } + + @Override + public void setBottomBorderColor(short color) { + + } + + @Override + public short getBottomBorderColor() { + return 0; + } + + @Override + public void setFillPattern(FillPatternType fp) { + + } + + @Override + public FillPatternType getFillPattern() { + return null; + } + + @Override + public FillPatternType getFillPatternEnum() { + return null; + } + + @Override + public void setFillBackgroundColor(short bg) { + + } + + @Override + public short getFillBackgroundColor() { + return 0; + } + + @Override + public Color getFillBackgroundColorColor() { + return null; + } + + @Override + public void setFillForegroundColor(short bg) { + + } + + @Override + public short getFillForegroundColor() { + return 0; + } + + @Override + public Color getFillForegroundColorColor() { + return null; + } + + @Override + public void cloneStyleFrom(CellStyle source) { + + } + + @Override + public void setShrinkToFit(boolean shrinkToFit) { + + } + + @Override + public boolean getShrinkToFit() { + return false; + } +} diff --git a/src/main/java/com/alibaba/excel/csv/CsvDataFormat.java b/src/main/java/com/alibaba/excel/csv/CsvDataFormat.java new file mode 100644 index 00000000..2961fbf1 --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvDataFormat.java @@ -0,0 +1,15 @@ +package com.alibaba.excel.csv; + +import org.apache.poi.ss.usermodel.DataFormat; + +public class CsvDataFormat implements DataFormat { + @Override + public short getFormat(String format) { + return 0; + } + + @Override + public String getFormat(short index) { + return null; + } +} diff --git a/src/main/java/com/alibaba/excel/csv/CsvRow.java b/src/main/java/com/alibaba/excel/csv/CsvRow.java new file mode 100644 index 00000000..6a979417 --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvRow.java @@ -0,0 +1,143 @@ +package com.alibaba.excel.csv; + +import java.util.Iterator; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +public class CsvRow implements Row { + + + @Override + public Cell createCell(int column) { + return new CsvCell(); + } + + @Override + public Cell createCell(int column, CellType type) { + return null; + } + + @Override + public void removeCell(Cell cell) { + + } + + @Override + public void setRowNum(int rowNum) { + + } + + @Override + public int getRowNum() { + return 0; + } + + @Override + public Cell getCell(int cellnum) { + return null; + } + + @Override + public Cell getCell(int cellnum, MissingCellPolicy policy) { + return null; + } + + @Override + public short getFirstCellNum() { + return 0; + } + + @Override + public short getLastCellNum() { + return 0; + } + + @Override + public int getPhysicalNumberOfCells() { + return 0; + } + + @Override + public void setHeight(short height) { + + } + + @Override + public void setZeroHeight(boolean zHeight) { + + } + + @Override + public boolean getZeroHeight() { + return false; + } + + @Override + public void setHeightInPoints(float height) { + + } + + @Override + public short getHeight() { + return 0; + } + + @Override + public float getHeightInPoints() { + return 0; + } + + @Override + public boolean isFormatted() { + return false; + } + + @Override + public CellStyle getRowStyle() { + return null; + } + + @Override + public void setRowStyle(CellStyle style) { + + } + + @Override + public Iterator cellIterator() { + return null; + } + + @Override + public Sheet getSheet() { + return null; + } + + @Override + public int getOutlineLevel() { + return 0; + } + + @Override + public void shiftCellsRight(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { + + } + + @Override + public void shiftCellsLeft(int firstShiftColumnIndex, int lastShiftColumnIndex, int step) { + + } + + @Override + public Iterator iterator() { + return null; + } +} diff --git a/src/main/java/com/alibaba/excel/csv/CsvSheet.java b/src/main/java/com/alibaba/excel/csv/CsvSheet.java new file mode 100644 index 00000000..eda6484a --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvSheet.java @@ -0,0 +1,676 @@ +package com.alibaba.excel.csv; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.util.ListUtils; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.poi.ss.usermodel.AutoFilter; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellRange; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.Footer; +import org.apache.poi.ss.usermodel.Header; +import org.apache.poi.ss.usermodel.Hyperlink; +import org.apache.poi.ss.usermodel.PrintSetup; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetConditionalFormatting; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellAddress; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.PaneInformation; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +public class CsvSheet implements Sheet { + + public static int rowCacheCount = 500; + public static Charset defaultCharset = Charset.defaultCharset(); + + public CSVPrinter csvPrinter; + + private int lastRowNum = -1; + + private List rowCache = ListUtils.newArrayListWithExpectedSize(rowCacheCount); + + public CsvSheet(File file) throws IOException { + csvPrinter = CSVFormat.DEFAULT.print(file, defaultCharset); + } + + public CsvSheet(OutputStream outputStream) throws IOException { + csvPrinter = CSVFormat.DEFAULT.print(new OutputStreamWriter(outputStream)); + } + + @Override + public Row createRow(int rownum) { + lastRowNum++; + assert rownum == lastRowNum : "csv create row must be in order."; + printData(); + CsvRow csvRow = new CsvRow(); + rowCache.add(csvRow); + return csvRow; + } + + @Override + public void removeRow(Row row) { + + } + + @Override + public Row getRow(int rownum) { + return null; + } + + @Override + public int getPhysicalNumberOfRows() { + return 0; + } + + @Override + public int getFirstRowNum() { + return 0; + } + + @Override + public int getLastRowNum() { + return 0; + } + + @Override + public void setColumnHidden(int columnIndex, boolean hidden) { + + } + + @Override + public boolean isColumnHidden(int columnIndex) { + return false; + } + + @Override + public void setRightToLeft(boolean value) { + + } + + @Override + public boolean isRightToLeft() { + return false; + } + + @Override + public void setColumnWidth(int columnIndex, int width) { + + } + + @Override + public int getColumnWidth(int columnIndex) { + return 0; + } + + @Override + public float getColumnWidthInPixels(int columnIndex) { + return 0; + } + + @Override + public void setDefaultColumnWidth(int width) { + + } + + @Override + public int getDefaultColumnWidth() { + return 0; + } + + @Override + public short getDefaultRowHeight() { + return 0; + } + + @Override + public float getDefaultRowHeightInPoints() { + return 0; + } + + @Override + public void setDefaultRowHeight(short height) { + + } + + @Override + public void setDefaultRowHeightInPoints(float height) { + + } + + @Override + public CellStyle getColumnStyle(int column) { + return null; + } + + @Override + public int addMergedRegion(CellRangeAddress region) { + return 0; + } + + @Override + public int addMergedRegionUnsafe(CellRangeAddress region) { + return 0; + } + + @Override + public void validateMergedRegions() { + + } + + @Override + public void setVerticallyCenter(boolean value) { + + } + + @Override + public void setHorizontallyCenter(boolean value) { + + } + + @Override + public boolean getHorizontallyCenter() { + return false; + } + + @Override + public boolean getVerticallyCenter() { + return false; + } + + @Override + public void removeMergedRegion(int index) { + + } + + @Override + public void removeMergedRegions(Collection indices) { + + } + + @Override + public int getNumMergedRegions() { + return 0; + } + + @Override + public CellRangeAddress getMergedRegion(int index) { + return null; + } + + @Override + public List getMergedRegions() { + return null; + } + + @Override + public Iterator rowIterator() { + return null; + } + + @Override + public void setForceFormulaRecalculation(boolean value) { + + } + + @Override + public boolean getForceFormulaRecalculation() { + return false; + } + + @Override + public void setAutobreaks(boolean value) { + + } + + @Override + public void setDisplayGuts(boolean value) { + + } + + @Override + public void setDisplayZeros(boolean value) { + + } + + @Override + public boolean isDisplayZeros() { + return false; + } + + @Override + public void setFitToPage(boolean value) { + + } + + @Override + public void setRowSumsBelow(boolean value) { + + } + + @Override + public void setRowSumsRight(boolean value) { + + } + + @Override + public boolean getAutobreaks() { + return false; + } + + @Override + public boolean getDisplayGuts() { + return false; + } + + @Override + public boolean getFitToPage() { + return false; + } + + @Override + public boolean getRowSumsBelow() { + return false; + } + + @Override + public boolean getRowSumsRight() { + return false; + } + + @Override + public boolean isPrintGridlines() { + return false; + } + + @Override + public void setPrintGridlines(boolean show) { + + } + + @Override + public boolean isPrintRowAndColumnHeadings() { + return false; + } + + @Override + public void setPrintRowAndColumnHeadings(boolean show) { + + } + + @Override + public PrintSetup getPrintSetup() { + return null; + } + + @Override + public Header getHeader() { + return null; + } + + @Override + public Footer getFooter() { + return null; + } + + @Override + public void setSelected(boolean value) { + + } + + @Override + public double getMargin(short margin) { + return 0; + } + + @Override + public void setMargin(short margin, double size) { + + } + + @Override + public boolean getProtect() { + return false; + } + + @Override + public void protectSheet(String password) { + + } + + @Override + public boolean getScenarioProtect() { + return false; + } + + @Override + public void setZoom(int scale) { + + } + + @Override + public short getTopRow() { + return 0; + } + + @Override + public short getLeftCol() { + return 0; + } + + @Override + public void showInPane(int topRow, int leftCol) { + + } + + @Override + public void shiftRows(int startRow, int endRow, int n) { + + } + + @Override + public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { + + } + + @Override + public void shiftColumns(int startColumn, int endColumn, int n) { + + } + + @Override + public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) { + + } + + @Override + public void createFreezePane(int colSplit, int rowSplit) { + + } + + @Override + public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) { + + } + + @Override + public PaneInformation getPaneInformation() { + return null; + } + + @Override + public void setDisplayGridlines(boolean show) { + + } + + @Override + public boolean isDisplayGridlines() { + return false; + } + + @Override + public void setDisplayFormulas(boolean show) { + + } + + @Override + public boolean isDisplayFormulas() { + return false; + } + + @Override + public void setDisplayRowColHeadings(boolean show) { + + } + + @Override + public boolean isDisplayRowColHeadings() { + return false; + } + + @Override + public void setRowBreak(int row) { + + } + + @Override + public boolean isRowBroken(int row) { + return false; + } + + @Override + public void removeRowBreak(int row) { + + } + + @Override + public int[] getRowBreaks() { + return new int[0]; + } + + @Override + public int[] getColumnBreaks() { + return new int[0]; + } + + @Override + public void setColumnBreak(int column) { + + } + + @Override + public boolean isColumnBroken(int column) { + return false; + } + + @Override + public void removeColumnBreak(int column) { + + } + + @Override + public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) { + + } + + @Override + public void groupColumn(int fromColumn, int toColumn) { + + } + + @Override + public void ungroupColumn(int fromColumn, int toColumn) { + + } + + @Override + public void groupRow(int fromRow, int toRow) { + + } + + @Override + public void ungroupRow(int fromRow, int toRow) { + + } + + @Override + public void setRowGroupCollapsed(int row, boolean collapse) { + + } + + @Override + public void setDefaultColumnStyle(int column, CellStyle style) { + + } + + @Override + public void autoSizeColumn(int column) { + + } + + @Override + public void autoSizeColumn(int column, boolean useMergedCells) { + + } + + @Override + public Comment getCellComment(CellAddress ref) { + return null; + } + + @Override + public Map getCellComments() { + return null; + } + + @Override + public Drawing getDrawingPatriarch() { + return null; + } + + @Override + public Drawing createDrawingPatriarch() { + return null; + } + + @Override + public Workbook getWorkbook() { + return null; + } + + @Override + public String getSheetName() { + return null; + } + + @Override + public boolean isSelected() { + return false; + } + + @Override + public CellRange setArrayFormula( + String formula, CellRangeAddress range) { + return null; + } + + @Override + public CellRange removeArrayFormula(Cell cell) { + return null; + } + + @Override + public DataValidationHelper getDataValidationHelper() { + return null; + } + + @Override + public List getDataValidations() { + return null; + } + + @Override + public void addValidationData(DataValidation dataValidation) { + + } + + @Override + public AutoFilter setAutoFilter(CellRangeAddress range) { + return null; + } + + @Override + public SheetConditionalFormatting getSheetConditionalFormatting() { + return null; + } + + @Override + public CellRangeAddress getRepeatingRows() { + return null; + } + + @Override + public CellRangeAddress getRepeatingColumns() { + return null; + } + + @Override + public void setRepeatingRows(CellRangeAddress rowRangeRef) { + + } + + @Override + public void setRepeatingColumns(CellRangeAddress columnRangeRef) { + + } + + @Override + public int getColumnOutlineLevel(int columnIndex) { + return 0; + } + + @Override + public Hyperlink getHyperlink(int row, int column) { + return null; + } + + @Override + public Hyperlink getHyperlink(CellAddress addr) { + return null; + } + + @Override + public List getHyperlinkList() { + return null; + } + + @Override + public CellAddress getActiveCell() { + return null; + } + + @Override + public void setActiveCell(CellAddress address) { + + } + + @Override + public Iterator iterator() { + return null; + } + + public void printData() { + if (rowCache.size() >= rowCacheCount) { + flushData(); + rowCache.clear(); + } + } + + public void flushData() { + try { + csvPrinter.printRecord(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/alibaba/excel/csv/CsvWorkbook.java b/src/main/java/com/alibaba/excel/csv/CsvWorkbook.java new file mode 100644 index 00000000..20002d83 --- /dev/null +++ b/src/main/java/com/alibaba/excel/csv/CsvWorkbook.java @@ -0,0 +1,358 @@ +package com.alibaba.excel.csv; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; + +import lombok.Data; +import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.formula.udf.UDFFinder; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.DataFormat; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.SheetVisibility; +import org.apache.poi.ss.usermodel.Workbook; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +@Data +public class CsvWorkbook implements Workbook { + + private CsvSheet csvSheet; + + public CsvWorkbook(InputStream inputStream, File file) { + try { + this.csvSheet = new CsvSheet(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public int getActiveSheetIndex() { + return 0; + } + + @Override + public void setActiveSheet(int sheetIndex) { + + } + + @Override + public int getFirstVisibleTab() { + return 0; + } + + @Override + public void setFirstVisibleTab(int sheetIndex) { + + } + + @Override + public void setSheetOrder(String sheetname, int pos) { + + } + + @Override + public void setSelectedTab(int index) { + + } + + @Override + public void setSheetName(int sheet, String name) { + + } + + @Override + public String getSheetName(int sheet) { + return null; + } + + @Override + public int getSheetIndex(String name) { + return 0; + } + + @Override + public int getSheetIndex(Sheet sheet) { + return 0; + } + + @Override + public Sheet createSheet() { + return csvSheet; + } + + @Override + public Sheet createSheet(String sheetname) { + return csvSheet; + } + + @Override + public Sheet cloneSheet(int sheetNum) { + return null; + } + + @Override + public Iterator sheetIterator() { + return null; + } + + @Override + public int getNumberOfSheets() { + return 0; + } + + @Override + public Sheet getSheetAt(int index) { + return null; + } + + @Override + public Sheet getSheet(String name) { + return null; + } + + @Override + public void removeSheetAt(int index) { + + } + + @Override + public Font createFont() { + return null; + } + + @Override + public Font findFont(boolean bold, short color, short fontHeight, String name, boolean italic, boolean strikeout, + short typeOffset, byte underline) { + return null; + } + + @Override + public short getNumberOfFonts() { + return 0; + } + + @Override + public int getNumberOfFontsAsInt() { + return 0; + } + + @Override + public Font getFontAt(short idx) { + return null; + } + + @Override + public Font getFontAt(int idx) { + return null; + } + + @Override + public CellStyle createCellStyle() { + return new CsvCellStyle(); + } + + @Override + public int getNumCellStyles() { + return 0; + } + + @Override + public CellStyle getCellStyleAt(int idx) { + return null; + } + + @Override + public void write(OutputStream stream) throws IOException { + csvSheet.csvPrinter.flush(); + csvSheet.csvPrinter.close(); + } + + @Override + public void close() throws IOException { + + } + + @Override + public int getNumberOfNames() { + return 0; + } + + @Override + public Name getName(String name) { + return null; + } + + @Override + public List getNames(String name) { + return null; + } + + @Override + public List getAllNames() { + return null; + } + + @Override + public Name getNameAt(int nameIndex) { + return null; + } + + @Override + public Name createName() { + return null; + } + + @Override + public int getNameIndex(String name) { + return 0; + } + + @Override + public void removeName(int index) { + + } + + @Override + public void removeName(String name) { + + } + + @Override + public void removeName(Name name) { + + } + + @Override + public int linkExternalWorkbook(String name, Workbook workbook) { + return 0; + } + + @Override + public void setPrintArea(int sheetIndex, String reference) { + + } + + @Override + public void setPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) { + + } + + @Override + public String getPrintArea(int sheetIndex) { + return null; + } + + @Override + public void removePrintArea(int sheetIndex) { + + } + + @Override + public MissingCellPolicy getMissingCellPolicy() { + return null; + } + + @Override + public void setMissingCellPolicy(MissingCellPolicy missingCellPolicy) { + + } + + @Override + public DataFormat createDataFormat() { + return new CsvDataFormat(); + } + + @Override + public int addPicture(byte[] pictureData, int format) { + return 0; + } + + @Override + public List getAllPictures() { + return null; + } + + @Override + public CreationHelper getCreationHelper() { + return null; + } + + @Override + public boolean isHidden() { + return false; + } + + @Override + public void setHidden(boolean hiddenFlag) { + + } + + @Override + public boolean isSheetHidden(int sheetIx) { + return false; + } + + @Override + public boolean isSheetVeryHidden(int sheetIx) { + return false; + } + + @Override + public void setSheetHidden(int sheetIx, boolean hidden) { + + } + + @Override + public SheetVisibility getSheetVisibility(int sheetIx) { + return null; + } + + @Override + public void setSheetVisibility(int sheetIx, SheetVisibility visibility) { + + } + + @Override + public void addToolPack(UDFFinder toopack) { + + } + + @Override + public void setForceFormulaRecalculation(boolean value) { + + } + + @Override + public boolean getForceFormulaRecalculation() { + return false; + } + + @Override + public SpreadsheetVersion getSpreadsheetVersion() { + return null; + } + + @Override + public int addOlePackage(byte[] oleData, String label, String fileName, String command) throws IOException { + return 0; + } + + @Override + public Iterator iterator() { + return null; + } +} diff --git a/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java b/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java index 7158a69c..eb4c4cbd 100644 --- a/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java +++ b/src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java @@ -16,6 +16,10 @@ import org.apache.poi.poifs.filesystem.FileMagic; * @author jipengfei */ public enum ExcelTypeEnum { + /** + * csv + */ + CSV(".csv"), /** * xls */ @@ -58,6 +62,8 @@ public enum ExcelTypeEnum { return XLSX; } else if (fileName.endsWith(XLS.getValue())) { return XLS; + } else if (fileName.endsWith(CSV.getValue())) { + return CSV; } if (StringUtils.isEmpty(readWorkbook.getPassword())) { try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file))) { diff --git a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java index 8aa2bfbf..0760e895 100644 --- a/src/main/java/com/alibaba/excel/util/WorkBookUtil.java +++ b/src/main/java/com/alibaba/excel/util/WorkBookUtil.java @@ -2,9 +2,9 @@ package com.alibaba.excel.util; import java.io.IOException; +import com.alibaba.excel.csv.CsvWorkbook; import com.alibaba.excel.metadata.data.DataFormatData; import com.alibaba.excel.metadata.data.WriteCellData; -import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import com.alibaba.excel.write.metadata.style.WriteCellStyle; @@ -29,39 +29,57 @@ public class WorkBookUtil { private WorkBookUtil() {} public static void createWorkBook(WriteWorkbookHolder writeWorkbookHolder) throws IOException { - if (ExcelTypeEnum.XLSX.equals(writeWorkbookHolder.getExcelType())) { - if (writeWorkbookHolder.getTempTemplateInputStream() != null) { - XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream()); - writeWorkbookHolder.setCachedWorkbook(xssfWorkbook); + switch (writeWorkbookHolder.getExcelType()) { + case XLSX: + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + XSSFWorkbook xssfWorkbook = new XSSFWorkbook(writeWorkbookHolder.getTempTemplateInputStream()); + writeWorkbookHolder.setCachedWorkbook(xssfWorkbook); + if (writeWorkbookHolder.getInMemory()) { + writeWorkbookHolder.setWorkbook(xssfWorkbook); + } else { + writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE)); + } + return; + } + Workbook workbook; if (writeWorkbookHolder.getInMemory()) { - writeWorkbookHolder.setWorkbook(xssfWorkbook); + workbook = new XSSFWorkbook(); } else { - writeWorkbookHolder.setWorkbook(new SXSSFWorkbook(xssfWorkbook, ROW_ACCESS_WINDOW_SIZE)); + workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE); } + writeWorkbookHolder.setCachedWorkbook(workbook); + writeWorkbookHolder.setWorkbook(workbook); return; - } - Workbook workbook = null; - if (writeWorkbookHolder.getInMemory()) { - workbook = new XSSFWorkbook(); - } else { - workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE); - } - writeWorkbookHolder.setCachedWorkbook(workbook); - writeWorkbookHolder.setWorkbook(workbook); - return; - } - HSSFWorkbook hssfWorkbook; - if (writeWorkbookHolder.getTempTemplateInputStream() != null) { - hssfWorkbook = new HSSFWorkbook(new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream())); - } else { - hssfWorkbook = new HSSFWorkbook(); - } - writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); - writeWorkbookHolder.setWorkbook(hssfWorkbook); - if (writeWorkbookHolder.getPassword() != null) { - Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword()); - hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY); + case XLS: + HSSFWorkbook hssfWorkbook; + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + hssfWorkbook = new HSSFWorkbook( + new POIFSFileSystem(writeWorkbookHolder.getTempTemplateInputStream())); + } else { + hssfWorkbook = new HSSFWorkbook(); + } + writeWorkbookHolder.setCachedWorkbook(hssfWorkbook); + writeWorkbookHolder.setWorkbook(hssfWorkbook); + if (writeWorkbookHolder.getPassword() != null) { + Biff8EncryptionKey.setCurrentUserPassword(writeWorkbookHolder.getPassword()); + hssfWorkbook.writeProtectWorkbook(writeWorkbookHolder.getPassword(), StringUtils.EMPTY); + } + return; + case CSV: + CsvWorkbook csvWorkbook; + if (writeWorkbookHolder.getTempTemplateInputStream() != null) { + csvWorkbook = new CsvWorkbook(writeWorkbookHolder.getTempTemplateInputStream(), + writeWorkbookHolder.getFile()); + } else { + csvWorkbook = new CsvWorkbook(null, writeWorkbookHolder.getFile()); + } + writeWorkbookHolder.setCachedWorkbook(csvWorkbook); + writeWorkbookHolder.setWorkbook(csvWorkbook); + return; + default: + throw new UnsupportedOperationException("Wrong excel type."); } + } public static Sheet createSheet(Workbook workbook, String sheetName) { diff --git a/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java b/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java index 96e88c2e..04bfb822 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java +++ b/src/main/java/com/alibaba/excel/write/metadata/WriteSheet.java @@ -1,18 +1,13 @@ package com.alibaba.excel.write.metadata; -import java.util.HashMap; -import java.util.Map; - -import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; -import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy; - -import org.apache.poi.ss.usermodel.TableStyle; +import lombok.Data; /** * Write sheet * * @author jipengfei */ +@Data public class WriteSheet extends WriteBasicParameter { /** * Starting from 0 @@ -22,54 +17,4 @@ public class WriteSheet extends WriteBasicParameter { * sheet name */ private String sheetName; - /** - * column with - * - * @deprecated please use {@link SimpleColumnWidthStyleStrategy} - */ - @Deprecated - private Map columnWidthMap = new HashMap(); - /** - * - * @deprecated please use{@link HorizontalCellStyleStrategy} - */ - @Deprecated - private TableStyle tableStyle; - - public Integer getSheetNo() { - return sheetNo; - } - - public void setSheetNo(Integer sheetNo) { - this.sheetNo = sheetNo; - } - - public String getSheetName() { - return sheetName; - } - - public void setSheetName(String sheetName) { - this.sheetName = sheetName; - } - - public Map getColumnWidthMap() { - return columnWidthMap; - } - - public void setColumnWidthMap(Map columnWidthMap) { - this.columnWidthMap = columnWidthMap; - } - - public TableStyle getTableStyle() { - return tableStyle; - } - - public void setTableStyle(TableStyle tableStyle) { - this.tableStyle = tableStyle; - } - - @Override - public String toString() { - return "WriteSheet{" + "sheetNo=" + sheetNo + ", sheetName='" + sheetName + '\'' + "} " + super.toString(); - } } 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 cfbfcf4d..a2a0d113 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 @@ -164,7 +164,14 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { if (isXls) { this.excelType = ExcelTypeEnum.XLS; } else { - this.excelType = ExcelTypeEnum.XLSX; + boolean isCsv = (file != null && file.getName().endsWith(ExcelTypeEnum.CSV.getValue())) + || (writeWorkbook.getTemplateFile() != null + && writeWorkbook.getTemplateFile().getName().endsWith(ExcelTypeEnum.CSV.getValue())); + if (isCsv) { + this.excelType = ExcelTypeEnum.CSV; + } else { + this.excelType = ExcelTypeEnum.XLSX; + } } } else { this.excelType = writeWorkbook.getExcelType(); @@ -174,8 +181,8 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { } else { this.mandatoryUseInputStream = writeWorkbook.getMandatoryUseInputStream(); } - this.hasBeenInitializedSheetIndexMap = new HashMap(); - this.hasBeenInitializedSheetNameMap = new HashMap(); + this.hasBeenInitializedSheetIndexMap = new HashMap<>(); + this.hasBeenInitializedSheetNameMap = new HashMap<>(); this.password = writeWorkbook.getPassword(); if (writeWorkbook.getInMemory() == null) { this.inMemory = Boolean.FALSE; @@ -188,8 +195,8 @@ public class WriteWorkbookHolder extends AbstractWriteHolder { this.writeExcelOnException = writeWorkbook.getWriteExcelOnException(); } this.cellStyleMap = MapUtils.newHashMap(); - this.fontMap= MapUtils.newHashMap(); - this.dataFormatMap=MapUtils.newHashMap(); + this.fontMap = MapUtils.newHashMap(); + this.dataFormatMap = MapUtils.newHashMap(); } private void copyTemplate() throws IOException { diff --git a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java index 0a147564..af2dfce5 100644 --- a/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java @@ -10,6 +10,9 @@ import java.util.Map; import javax.servlet.http.HttpServletResponse; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @@ -17,10 +20,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.support.ExcelTypeEnum; -import com.alibaba.fastjson.JSON; - /** * web读写案例 * @@ -49,7 +48,13 @@ public class WebTest { // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); - EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data()); + + ArrayList> list = new ArrayList<>(); + ArrayList sublist = new ArrayList(); + sublist.add("t1"); + sublist.add("t2"); + list.add(sublist); + EasyExcel.write(response.getOutputStream()).sheet("模板").doWrite(list); } /** diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java index ad09717f..031e5114 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/LockTest.java @@ -1,18 +1,17 @@ package com.alibaba.easyexcel.test.temp; -import java.io.File; import java.io.FileInputStream; import java.util.List; import java.util.Map; +import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; + import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.alibaba.excel.EasyExcel; -import com.alibaba.fastjson.JSON; - /** * 临时测试 * @@ -24,9 +23,8 @@ public class LockTest { @Test public void test() throws Exception { - List list = - EasyExcel.read(new FileInputStream("/Users/zhuangjiaju/Downloads/点位配置表 (1).xlsx")).doReadAllSync(); + EasyExcel.read(new FileInputStream("/Users/zhuangjiaju/test/pic.xls")).doReadAllSync(); for (Object data : list) { LOGGER.info("返回数据:{}", JSON.toJSONString(data)); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java new file mode 100644 index 00000000..2f645339 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvData.java @@ -0,0 +1,28 @@ +package com.alibaba.easyexcel.test.temp.csv; + +import java.util.Date; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; + +import lombok.Data; + +/** + * TODO + * + * @author Jiaju Zhuang + */ +@Data +public class CsvData { + @ExcelProperty("字符串标题") + private String string; + @ExcelProperty("日期标题") + private Date date; + @ExcelProperty("数字标题") + private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java new file mode 100644 index 00000000..b9af89e4 --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java @@ -0,0 +1,86 @@ +package com.alibaba.easyexcel.test.temp.csv; + +import java.io.File; +import java.io.FileInputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.alibaba.easyexcel.test.util.TestFileUtil; +import com.alibaba.excel.EasyExcel; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.poi.poifs.filesystem.FileMagic; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +@Slf4j +public class CsvReadTest { + + @Test + public void write() throws Exception { + Appendable out = new PrintWriter(TestFileUtil.createNewFile("csvWrite.csv")); + CSVPrinter printer = CSVFormat.DEFAULT.withHeader("userId", "userName") + .print(out); + for (int i = 0; i < 10; i++) { + printer.printRecord("userId" + i, "userName" + i); + } + printer.flush(); + printer.close(); + } + + @Test + public void csvWrite() throws Exception { + // 写法1 + String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".csv"; + // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName, CsvData.class).sheet().doWrite(data()); + } + + @Test + public void writev2() throws Exception { + // 写法1 + String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".csv"; + // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 + // 如果这里想使用03 则 传入excelType参数即可 + EasyExcel.write(fileName, CsvData.class).sheet().doWrite(data()); + } + + @Test + public void writeFile() throws Exception { + FileInputStream fileInputStream = new FileInputStream(new File("/Users/zhuangjiaju/test/test1.csv")); + FileMagic fileMagic = FileMagic.valueOf(fileInputStream); + log.info("{}", fileMagic); + } + + private List data() { + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + CsvData data = new CsvData(); + data.setString("字符串" + i); + data.setDate(new Date()); + data.setDoubleData(0.56); + data.setIgnore("忽略" + i); + list.add(data); + } + return list; + } + + @Test + public void read() { + // + //Iterable records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(in); + //for (CSVRecord record : records) { + // String lastName = record.get("id"); + // String firstName = record.get("name"); + // System.out.println(lastName); + // System.out.println(firstName); + //} + + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java index 99fccd70..6649c2fe 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java @@ -38,4 +38,5 @@ public class HeadReadTest { EasyExcel.read(file, HeadReadData.class, new HDListener()).readCache(new Ehcache(20)).sheet(0).doRead(); } + }