Browse Source

完成部分csv

developing
Jiaju Zhuang 3 years ago
parent
commit
d475f98b93
  1. 24
      src/main/java/com/alibaba/excel/constant/BuiltinFormats.java
  2. 231
      src/main/java/com/alibaba/excel/csv/CsvCell.java
  3. 15
      src/main/java/com/alibaba/excel/csv/CsvDataFormat.java
  4. 291
      src/main/java/com/alibaba/excel/metadata/csv/CsvCell.java
  5. 21
      src/main/java/com/alibaba/excel/metadata/csv/CsvCellStyle.java
  6. 65
      src/main/java/com/alibaba/excel/metadata/csv/CsvDataFormat.java
  7. 68
      src/main/java/com/alibaba/excel/metadata/csv/CsvRichTextString.java
  8. 73
      src/main/java/com/alibaba/excel/metadata/csv/CsvRow.java
  9. 146
      src/main/java/com/alibaba/excel/metadata/csv/CsvSheet.java
  10. 71
      src/main/java/com/alibaba/excel/metadata/csv/CsvWorkbook.java
  11. 15
      src/main/java/com/alibaba/excel/util/WorkBookUtil.java
  12. 18
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java
  13. 16
      src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java

24
src/main/java/com/alibaba/excel/constant/BuiltinFormats.java

@ -1,6 +1,9 @@
package com.alibaba.excel.constant; package com.alibaba.excel.constant;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import com.alibaba.excel.util.MapUtils;
/** /**
* Excel's built-in format conversion.Currently only supports Chinese. * Excel's built-in format conversion.Currently only supports Chinese.
@ -363,6 +366,10 @@ public class BuiltinFormats {
// end // end
}; };
public static final Map<String, Short> BUILTIN_FORMATS_MAP_CN = buildMap(BUILTIN_FORMATS_CN);
public static final Map<String, Short> BUILTIN_FORMATS_MAP_US = buildMap(BUILTIN_FORMATS_US);
public static final short MIN_CUSTOM_DATA_FORMAT_INDEX = 82;
public static String getBuiltinFormat(Short index, String defaultFormat, Locale locale) { public static String getBuiltinFormat(Short index, String defaultFormat, Locale locale) {
String[] builtinFormat = switchBuiltinFormats(locale); String[] builtinFormat = switchBuiltinFormats(locale);
if (index == null || index < 0 || index >= builtinFormat.length) { if (index == null || index < 0 || index >= builtinFormat.length) {
@ -371,11 +378,26 @@ public class BuiltinFormats {
return builtinFormat[index]; return builtinFormat[index];
} }
private static String[] switchBuiltinFormats(Locale locale) { public static String[] switchBuiltinFormats(Locale locale) {
if (locale != null && Locale.US.getCountry().equals(locale.getCountry())) { if (locale != null && Locale.US.getCountry().equals(locale.getCountry())) {
return BUILTIN_FORMATS_US; return BUILTIN_FORMATS_US;
} }
return BUILTIN_FORMATS_CN; return BUILTIN_FORMATS_CN;
} }
public static Map<String, Short> switchBuiltinFormatsMap(Locale locale) {
if (locale != null && Locale.US.getCountry().equals(locale.getCountry())) {
return BUILTIN_FORMATS_MAP_US;
}
return BUILTIN_FORMATS_MAP_CN;
}
private static Map<String, Short> buildMap(String[] builtinFormats) {
Map<String, Short> map = MapUtils.newHashMapWithExpectedSize(builtinFormats.length);
for (int i = 0; i < builtinFormats.length; i++) {
map.put(builtinFormats[i], (short)i);
}
return map;
}
} }

231
src/main/java/com/alibaba/excel/csv/CsvCell.java

@ -1,231 +0,0 @@
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 {
private String value;
@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) {
this.value = value + "";
}
@Override
public void setCellValue(Date value) {
this.value = value.toString();
}
@Override
public void setCellValue(LocalDateTime value) {
}
@Override
public void setCellValue(Calendar value) {
}
@Override
public void setCellValue(RichTextString value) {
}
@Override
public void setCellValue(String value) {
this.value = 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 value;
}
@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;
}
}

15
src/main/java/com/alibaba/excel/csv/CsvDataFormat.java

@ -1,15 +0,0 @@
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;
}
}

291
src/main/java/com/alibaba/excel/metadata/csv/CsvCell.java

@ -0,0 +1,291 @@
package com.alibaba.excel.metadata.csv;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import com.alibaba.excel.metadata.data.FormulaData;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.CellBase;
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.CellRangeAddress;
/**
* csv cell
*
* @author Jiaju Zhuang
*/
public class CsvCell extends CellBase {
/**
* column index
*/
private Integer columnIndex;
/**
* cell type
*/
private CellType cellType;
/**
* row
*/
private final CsvRow csvRow;
/**
* {@link CellType#NUMERIC}
*/
private BigDecimal numberValue;
/**
* {@link CellType#STRING} and {@link CellType#ERROR} {@link CellType#FORMULA}
*/
private String stringValue;
/**
* {@link CellType#BOOLEAN}
*/
private Boolean booleanValue;
/**
* {@link CellType#NUMERIC}
*/
private LocalDateTime dateValue;
/**
* formula
*/
private FormulaData formulaData;
/**
* rich text string
*/
private RichTextString richTextString;
/**
* style
*/
private CellStyle cellStyle;
public CsvCell(CsvRow csvRow, Integer columnIndex, CellType cellType) {
this.csvRow = csvRow;
this.columnIndex = columnIndex;
this.cellType = cellType;
}
@Override
protected void setCellTypeImpl(CellType cellType) {
this.cellType = cellType;
}
@Override
protected void setCellFormulaImpl(String formula) {
FormulaData formulaData = new FormulaData();
formulaData.setFormulaValue(formula);
this.formulaData = formulaData;
}
@Override
protected void removeFormulaImpl() {
this.formulaData = null;
}
@Override
protected void setCellValueImpl(double value) {
numberValue = BigDecimal.valueOf(value);
}
@Override
protected void setCellValueImpl(Date value) {
if (value == null) {
return;
}
this.dateValue = LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault());
}
@Override
protected void setCellValueImpl(LocalDateTime value) {
this.dateValue = value;
}
@Override
protected void setCellValueImpl(Calendar value) {
if (value == null) {
return;
}
this.dateValue = LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault());
}
@Override
protected void setCellValueImpl(String value) {
this.stringValue = value;
}
@Override
protected void setCellValueImpl(RichTextString value) {
richTextString = value;
}
@Override
protected SpreadsheetVersion getSpreadsheetVersion() {
return null;
}
@Override
public int getColumnIndex() {
return columnIndex;
}
@Override
public int getRowIndex() {
return csvRow.getRowNum();
}
@Override
public Sheet getSheet() {
return csvRow.getSheet();
}
@Override
public Row getRow() {
return csvRow;
}
@Override
public CellType getCellType() {
return cellType;
}
@Override
public CellType getCachedFormulaResultType() {
return getCellType();
}
@Override
public CellType getCachedFormulaResultTypeEnum() {
return getCellType();
}
@Override
public String getCellFormula() {
if (formulaData == null) {
return null;
}
return formulaData.getFormulaValue();
}
@Override
public double getNumericCellValue() {
if (numberValue == null) {
return 0;
}
return numberValue.doubleValue();
}
@Override
public Date getDateCellValue() {
if (dateValue == null) {
return null;
}
return Date.from(dateValue.atZone(ZoneId.systemDefault()).toInstant());
}
@Override
public LocalDateTime getLocalDateTimeCellValue() {
return dateValue;
}
@Override
public RichTextString getRichStringCellValue() {
return richTextString;
}
@Override
public String getStringCellValue() {
return stringValue;
}
@Override
public void setCellValue(boolean value) {
this.booleanValue = value;
}
@Override
public void setCellErrorValue(byte value) {
this.numberValue = BigDecimal.valueOf(value);
}
@Override
public boolean getBooleanCellValue() {
return booleanValue;
}
@Override
public byte getErrorCellValue() {
if (numberValue == null) {
return 0;
}
return numberValue.byteValue();
}
@Override
public void setCellStyle(CellStyle style) {
this.cellStyle = style;
}
@Override
public CellStyle getCellStyle() {
return cellStyle;
}
@Override
public void setAsActiveCell() {
}
@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;
}
}

21
src/main/java/com/alibaba/excel/csv/CsvCellStyle.java → src/main/java/com/alibaba/excel/metadata/csv/CsvCellStyle.java

@ -1,4 +1,6 @@
package com.alibaba.excel.csv; package com.alibaba.excel.metadata.csv;
import com.alibaba.excel.metadata.data.DataFormatData;
import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
@ -9,11 +11,26 @@ import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment;
/** /**
* TODO * csv cell style
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class CsvCellStyle implements CellStyle { public class CsvCellStyle implements CellStyle {
/**
* data format
*/
private DataFormatData dataFormatData;
/**
* index
*/
private Short index;
public CsvCellStyle(Short index) {
this.index = index;
}
@Override @Override
public short getIndex() { public short getIndex() {
return 0; return 0;

65
src/main/java/com/alibaba/excel/metadata/csv/CsvDataFormat.java

@ -0,0 +1,65 @@
package com.alibaba.excel.metadata.csv;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.MapUtils;
import org.apache.poi.ss.usermodel.DataFormat;
/**
* format data
*
* @author Jiaju Zhuang
*/
public class CsvDataFormat implements DataFormat {
/**
* It is stored in both map and list for easy retrieval
*/
private final Map<String, Short> formatMap;
private final List<String> formatList;
/**
* Excel's built-in format conversion.
*/
private final Map<String, Short> builtinFormatsMap;
private final String[] builtinFormats;
public CsvDataFormat(Locale locale) {
formatMap = MapUtils.newHashMap();
formatList = ListUtils.newArrayList();
builtinFormatsMap = BuiltinFormats.switchBuiltinFormatsMap(locale);
builtinFormats = BuiltinFormats.switchBuiltinFormats(locale);
}
@Override
public short getFormat(String format) {
Short index = builtinFormatsMap.get(format);
if (index != null) {
return index;
}
index = formatMap.get(format);
if (index != null) {
return index;
}
formatList.add(format);
index = (short)formatList.size();
formatMap.put(format, index);
return index;
}
@Override
public String getFormat(short index) {
if (index < BuiltinFormats.MIN_CUSTOM_DATA_FORMAT_INDEX) {
return builtinFormats[index];
}
int actualIndex = index - BuiltinFormats.MIN_CUSTOM_DATA_FORMAT_INDEX;
if (actualIndex >= 0 && actualIndex < formatList.size()) {
return formatList.get(actualIndex);
}
return null;
}
}

68
src/main/java/com/alibaba/excel/metadata/csv/CsvRichTextString.java

@ -0,0 +1,68 @@
package com.alibaba.excel.metadata.csv;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.RichTextString;
/**
* rich text string
*
* @author Jiaju Zhuang
*/
public class CsvRichTextString implements RichTextString {
/**
* string
*/
private final String string;
public CsvRichTextString(String string) {
this.string = string;
}
@Override
public void applyFont(int startIndex, int endIndex, short fontIndex) {
}
@Override
public void applyFont(int startIndex, int endIndex, Font font) {
}
@Override
public void applyFont(Font font) {
}
@Override
public void clearFormatting() {
}
@Override
public String getString() {
return string;
}
@Override
public int length() {
if (string == null) {
return 0;
}
return string.length();
}
@Override
public int numFormattingRuns() {
return 0;
}
@Override
public int getIndexOfFormattingRun(int index) {
return 0;
}
@Override
public void applyFont(short fontIndex) {
}
}

73
src/main/java/com/alibaba/excel/csv/CsvRow.java → src/main/java/com/alibaba/excel/metadata/csv/CsvRow.java

@ -1,9 +1,10 @@
package com.alibaba.excel.csv; package com.alibaba.excel.metadata.csv;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellType;
@ -11,64 +12,98 @@ import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Sheet;
/** /**
* TODO * csv row
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class CsvRow implements Row { public class CsvRow implements Row {
public List<CsvCell> list = new ArrayList<>(); /**
* cell list
*/
private final List<CsvCell> cellList;
/**
* sheet
*/
private final CsvSheet csvSheet;
/**
* row index
*/
private Integer rowIndex;
/**
* style
*/
private CellStyle cellStyle;
public CsvRow(CsvSheet csvSheet, Integer rowIndex) {
cellList = Lists.newArrayList();
this.csvSheet = csvSheet;
this.rowIndex = rowIndex;
}
@Override @Override
public Cell createCell(int column) { public Cell createCell(int column) {
CsvCell cell = new CsvCell(); CsvCell cell = new CsvCell(this, column, null);
list.add(cell); cellList.add(cell);
return cell; return cell;
} }
@Override @Override
public Cell createCell(int column, CellType type) { public Cell createCell(int column, CellType type) {
return null; CsvCell cell = new CsvCell(this, column, type);
cellList.add(cell);
return cell;
} }
@Override @Override
public void removeCell(Cell cell) { public void removeCell(Cell cell) {
cellList.remove(cell);
} }
@Override @Override
public void setRowNum(int rowNum) { public void setRowNum(int rowNum) {
this.rowIndex = rowNum;
} }
@Override @Override
public int getRowNum() { public int getRowNum() {
return 0; return rowIndex;
} }
@Override @Override
public Cell getCell(int cellnum) { public Cell getCell(int cellnum) {
return list.get(cellnum); if (cellnum >= cellList.size()) {
return null;
}
return cellList.get(cellnum - 1);
} }
@Override @Override
public Cell getCell(int cellnum, MissingCellPolicy policy) { public Cell getCell(int cellnum, MissingCellPolicy policy) {
return null; return getCell(cellnum);
} }
@Override @Override
public short getFirstCellNum() { public short getFirstCellNum() {
if (CollectionUtils.isEmpty(cellList)) {
return -1;
}
return 0; return 0;
} }
@Override @Override
public short getLastCellNum() { public short getLastCellNum() {
return (short)list.size(); if (CollectionUtils.isEmpty(cellList)) {
return -1;
}
return (short)cellList.size();
} }
@Override @Override
public int getPhysicalNumberOfCells() { public int getPhysicalNumberOfCells() {
return 0; return getRowNum();
} }
@Override @Override
@ -108,22 +143,22 @@ public class CsvRow implements Row {
@Override @Override
public CellStyle getRowStyle() { public CellStyle getRowStyle() {
return null; return cellStyle;
} }
@Override @Override
public void setRowStyle(CellStyle style) { public void setRowStyle(CellStyle style) {
this.cellStyle = style;
} }
@Override @Override
public Iterator<Cell> cellIterator() { public Iterator<Cell> cellIterator() {
return null; return (Iterator<Cell>)(Iterator<? extends Cell>)cellList.iterator();
} }
@Override @Override
public Sheet getSheet() { public Sheet getSheet() {
return null; return csvSheet;
} }
@Override @Override
@ -143,6 +178,6 @@ public class CsvRow implements Row {
@Override @Override
public Iterator<Cell> iterator() { public Iterator<Cell> iterator() {
return null; return cellIterator();
} }
} }

146
src/main/java/com/alibaba/excel/csv/CsvSheet.java → src/main/java/com/alibaba/excel/metadata/csv/CsvSheet.java

@ -1,6 +1,9 @@
package com.alibaba.excel.csv; package com.alibaba.excel.metadata.csv;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
@ -9,10 +12,11 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import com.alibaba.excel.exception.ExcelGenerateException;
import com.alibaba.excel.util.ListUtils; import com.alibaba.excel.util.ListUtils;
import lombok.Data;
import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter; import org.apache.commons.csv.CSVPrinter;
import org.apache.poi.ss.usermodel.AutoFilter; import org.apache.poi.ss.usermodel.AutoFilter;
@ -36,62 +40,122 @@ import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.PaneInformation; import org.apache.poi.ss.util.PaneInformation;
/** /**
* TODO * csv sheet
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class CsvSheet implements Sheet { @Data
public class CsvSheet implements Sheet, Closeable {
public static int rowCacheCount = 500;
public static Charset defaultCharset = Charset.defaultCharset(); /**
* workbook
public CSVPrinter csvPrinter; */
private CsvWorkbook csvWorkbook;
private int lastRowNum = -1; /**
* output
private List<CsvRow> rowCache = ListUtils.newArrayListWithExpectedSize(rowCacheCount); */
private Appendable out;
public CsvSheet(File file) throws IOException { /**
csvPrinter = CSVFormat.DEFAULT.print(file, defaultCharset); * row cache
} */
private Integer rowCacheCount;
public CsvSheet(OutputStream outputStream) throws IOException { /**
csvPrinter = CSVFormat.DEFAULT.print(new OutputStreamWriter(outputStream)); * format
*/
public CSVFormat csvFormat;
/**
* last row index
*/
private int lastRowIndex;
/**
* row cache
*/
private List<CsvRow> rowCache;
/**
* csv printer
*/
private CSVPrinter csvPrinter;
public CsvSheet(CsvWorkbook csvWorkbook, File file, Charset charset) throws FileNotFoundException {
this.csvWorkbook = csvWorkbook;
this.out = new OutputStreamWriter(new FileOutputStream(file), charset);
this.rowCacheCount = 500;
this.csvFormat = CSVFormat.DEFAULT;
this.lastRowIndex = -1;
}
public CsvSheet(CsvWorkbook csvWorkbook, OutputStream outputStream) {
this.csvWorkbook = csvWorkbook;
this.out = new OutputStreamWriter(outputStream);
this.rowCacheCount = 500;
this.csvFormat = CSVFormat.DEFAULT;
this.lastRowIndex = -1;
}
public CsvSheet(CsvWorkbook csvWorkbook, Appendable out) {
this.csvWorkbook = csvWorkbook;
this.out = out;
this.rowCacheCount = 500;
this.csvFormat = CSVFormat.DEFAULT;
this.lastRowIndex = -1;
} }
@Override @Override
public Row createRow(int rownum) { public Row createRow(int rownum) {
lastRowNum++; // Initialize the data when the row is first created
assert rownum == lastRowNum : "csv create row must be in order."; initSheet();
lastRowIndex++;
assert rownum == lastRowIndex : "csv create row must be in order.";
printData(); printData();
CsvRow csvRow = new CsvRow(); CsvRow csvRow = new CsvRow(this, rownum);
rowCache.add(csvRow); rowCache.add(csvRow);
return csvRow; return csvRow;
} }
private void initSheet() {
if (csvPrinter != null) {
return;
}
rowCache = ListUtils.newArrayListWithExpectedSize(rowCacheCount);
try {
csvPrinter = csvFormat.print(out);
} catch (IOException e) {
throw new ExcelGenerateException(e);
}
}
@Override @Override
public void removeRow(Row row) { public void removeRow(Row row) {
throw new UnsupportedOperationException("csv cannot move row.");
} }
@Override @Override
public Row getRow(int rownum) { public Row getRow(int rownum) {
return null; int actualRowIndex = rownum - (lastRowIndex - rowCache.size()) - 1;
if (actualRowIndex < 0 || actualRowIndex > rowCache.size() - 1) {
throw new UnsupportedOperationException("The current data does not exist or has been flushed to disk\n.");
}
return rowCache.get(actualRowIndex);
} }
@Override @Override
public int getPhysicalNumberOfRows() { public int getPhysicalNumberOfRows() {
return 0; return lastRowIndex - rowCache.size();
} }
@Override @Override
public int getFirstRowNum() { public int getFirstRowNum() {
if (lastRowIndex < 0) {
return -1;
}
return 0; return 0;
} }
@Override @Override
public int getLastRowNum() { public int getLastRowNum() {
return 0; return lastRowIndex;
} }
@Override @Override
@ -226,7 +290,7 @@ public class CsvSheet implements Sheet {
@Override @Override
public Iterator<Row> rowIterator() { public Iterator<Row> rowIterator() {
return null; return (Iterator<Row>)(Iterator<? extends Row>)rowCache.iterator();
} }
@Override @Override
@ -556,7 +620,7 @@ public class CsvSheet implements Sheet {
@Override @Override
public Workbook getWorkbook() { public Workbook getWorkbook() {
return null; return csvWorkbook;
} }
@Override @Override
@ -657,23 +721,39 @@ public class CsvSheet implements Sheet {
@Override @Override
public Iterator<Row> iterator() { public Iterator<Row> iterator() {
return null; return rowIterator();
}
@Override
public void close() throws IOException {
// Avoid empty sheets
initSheet();
flushData();
csvPrinter.flush();
csvPrinter.close();
} }
public void printData() { public void printData() {
if (rowCache.size() >= rowCacheCount) { if (rowCache.size() >= rowCacheCount) {
flushData(); flushData();
rowCache.clear();
} }
} }
public void flushData() { public void flushData() {
try { try {
for (CsvRow row : rowCache) { for (CsvRow row : rowCache) {
csvPrinter.printRecord(row.list.stream().map(CsvCell::getStringCellValue).collect(Collectors.toList())); Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
CsvCell csvCell = (CsvCell)cellIterator.next();
csvPrinter.print(csvCell.getStringCellValue());
}
csvPrinter.println();
} }
rowCache.clear();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); throw new ExcelGenerateException(e);
} }
} }
} }

71
src/main/java/com/alibaba/excel/csv/CsvWorkbook.java → src/main/java/com/alibaba/excel/metadata/csv/CsvWorkbook.java

@ -1,13 +1,13 @@
package com.alibaba.excel.csv; package com.alibaba.excel.metadata.csv;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import lombok.Data; import lombok.Data;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
@ -22,21 +22,37 @@ import org.apache.poi.ss.usermodel.SheetVisibility;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
/** /**
* TODO * csv workbook
* *
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
@Data @Data
public class CsvWorkbook implements Workbook { public class CsvWorkbook implements Workbook {
/**
* output
*/
private Appendable out;
/**
* locale
*/
private Locale locale;
/**
* data format
*/
private CsvDataFormat csvDataFormat;
/**
* sheet
*/
private CsvSheet csvSheet; private CsvSheet csvSheet;
/**
* cell style
*/
private List<CsvCellStyle> csvCellStyleList;
public CsvWorkbook(InputStream inputStream, File file) { public CsvWorkbook(Appendable out, Locale locale) {
try { this.out = out;
this.csvSheet = new CsvSheet(file); this.locale = locale;
} catch (IOException e) {
e.printStackTrace();
}
} }
@Override @Override
@ -91,11 +107,15 @@ public class CsvWorkbook implements Workbook {
@Override @Override
public Sheet createSheet() { public Sheet createSheet() {
assert csvSheet == null : "CSV repeat creation is not allowed.";
csvSheet = new CsvSheet(this, out);
return csvSheet; return csvSheet;
} }
@Override @Override
public Sheet createSheet(String sheetname) { public Sheet createSheet(String sheetname) {
assert csvSheet == null : "CSV repeat creation is not allowed.";
csvSheet = new CsvSheet(this, out);
return csvSheet; return csvSheet;
} }
@ -116,12 +136,13 @@ public class CsvWorkbook implements Workbook {
@Override @Override
public Sheet getSheetAt(int index) { public Sheet getSheetAt(int index) {
return null; assert index == 0 : "CSV exists only in one sheet.";
return csvSheet;
} }
@Override @Override
public Sheet getSheet(String name) { public Sheet getSheet(String name) {
return null; return csvSheet;
} }
@Override @Override
@ -162,24 +183,30 @@ public class CsvWorkbook implements Workbook {
@Override @Override
public CellStyle createCellStyle() { public CellStyle createCellStyle() {
return new CsvCellStyle(); if (csvCellStyleList == null) {
csvCellStyleList = Lists.newArrayList();
}
CsvCellStyle csvCellStyle = new CsvCellStyle((short)csvCellStyleList.size());
csvCellStyleList.add(csvCellStyle);
return csvCellStyle;
} }
@Override @Override
public int getNumCellStyles() { public int getNumCellStyles() {
return 0; return csvCellStyleList.size();
} }
@Override @Override
public CellStyle getCellStyleAt(int idx) { public CellStyle getCellStyleAt(int idx) {
return null; if (idx < 0 || idx >= csvCellStyleList.size()) {
return null;
}
return csvCellStyleList.get(idx);
} }
@Override @Override
public void write(OutputStream stream) throws IOException { public void write(OutputStream stream) throws IOException {
csvSheet.flushData(); csvSheet.close();
csvSheet.csvPrinter.flush();
csvSheet.csvPrinter.close();
} }
@Override @Override
@ -274,7 +301,11 @@ public class CsvWorkbook implements Workbook {
@Override @Override
public DataFormat createDataFormat() { public DataFormat createDataFormat() {
return new CsvDataFormat(); if (csvDataFormat != null) {
return csvDataFormat;
}
csvDataFormat = new CsvDataFormat(locale);
return csvDataFormat;
} }
@Override @Override

15
src/main/java/com/alibaba/excel/util/WorkBookUtil.java

@ -1,8 +1,10 @@
package com.alibaba.excel.util; package com.alibaba.excel.util;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter;
import com.alibaba.excel.csv.CsvWorkbook; import com.alibaba.excel.metadata.csv.CsvWorkbook;
import com.alibaba.excel.metadata.data.DataFormatData; import com.alibaba.excel.metadata.data.DataFormatData;
import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
@ -67,12 +69,15 @@ public class WorkBookUtil {
return; return;
case CSV: case CSV:
CsvWorkbook csvWorkbook; CsvWorkbook csvWorkbook;
if (writeWorkbookHolder.getTempTemplateInputStream() != null) { if (writeWorkbookHolder.getFile() != null) {
csvWorkbook = new CsvWorkbook(writeWorkbookHolder.getTempTemplateInputStream(), csvWorkbook = new CsvWorkbook(
writeWorkbookHolder.getFile()); new OutputStreamWriter(new FileOutputStream(writeWorkbookHolder.getFile()),
writeWorkbookHolder.getFileCharset()),
writeWorkbookHolder.getGlobalConfiguration().getLocale());
} else { } else {
csvWorkbook = new CsvWorkbook(null, writeWorkbookHolder.getFile()); csvWorkbook = new CsvWorkbook(null, writeWorkbookHolder.getGlobalConfiguration().getLocale());
} }
CsvWorkbook csvWorkbook = new CsvWorkbook(writeWorkbookHolder);
writeWorkbookHolder.setCachedWorkbook(csvWorkbook); writeWorkbookHolder.setCachedWorkbook(csvWorkbook);
writeWorkbookHolder.setWorkbook(csvWorkbook); writeWorkbookHolder.setWorkbook(csvWorkbook);
return; return;

18
src/main/java/com/alibaba/excel/write/metadata/holder/WriteWorkbookHolder.java

@ -7,6 +7,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -64,6 +65,10 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
* If 'outputStream' and 'file' all not empty,file first * If 'outputStream' and 'file' all not empty,file first
*/ */
private File file; private File file;
/**
* charset of final output file
*/
private Charset fileCharset;
/** /**
* Final output stream * Final output stream
*/ */
@ -152,11 +157,6 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
} else { } else {
this.autoCloseStream = writeWorkbook.getAutoCloseStream(); this.autoCloseStream = writeWorkbook.getAutoCloseStream();
} }
try {
copyTemplate();
} catch (IOException e) {
throw new ExcelGenerateException("Copy template failure.", e);
}
if (writeWorkbook.getExcelType() == null) { if (writeWorkbook.getExcelType() == null) {
boolean isXls = (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue())) boolean isXls = (file != null && file.getName().endsWith(ExcelTypeEnum.XLS.getValue()))
|| (writeWorkbook.getTemplateFile() != null || (writeWorkbook.getTemplateFile() != null
@ -176,6 +176,11 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
} else { } else {
this.excelType = writeWorkbook.getExcelType(); this.excelType = writeWorkbook.getExcelType();
} }
try {
copyTemplate();
} catch (IOException e) {
throw new ExcelGenerateException("Copy template failure.", e);
}
if (writeWorkbook.getMandatoryUseInputStream() == null) { if (writeWorkbook.getMandatoryUseInputStream() == null) {
this.mandatoryUseInputStream = Boolean.FALSE; this.mandatoryUseInputStream = Boolean.FALSE;
} else { } else {
@ -203,6 +208,9 @@ public class WriteWorkbookHolder extends AbstractWriteHolder {
if (writeWorkbook.getTemplateFile() == null && writeWorkbook.getTemplateInputStream() == null) { if (writeWorkbook.getTemplateFile() == null && writeWorkbook.getTemplateInputStream() == null) {
return; return;
} }
if (this.excelType == ExcelTypeEnum.CSV) {
throw new ExcelGenerateException("csv cannot use template.");
}
byte[] templateFileByte = null; byte[] templateFileByte = null;
if (writeWorkbook.getTemplateFile() != null) { if (writeWorkbook.getTemplateFile() != null) {
templateFileByte = FileUtils.readFileToByteArray(writeWorkbook.getTemplateFile()); templateFileByte = FileUtils.readFileToByteArray(writeWorkbook.getTemplateFile());

16
src/test/java/com/alibaba/easyexcel/test/core/annotation/AnnotationDataTest.java

@ -4,26 +4,27 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.DateUtils; import com.alibaba.excel.util.DateUtils;
import org.junit.BeforeClass;
import org.junit.Test;
/** /**
*
* @author Jiaju Zhuang * @author Jiaju Zhuang
*/ */
public class AnnotationDataTest { public class AnnotationDataTest {
private static File file07; private static File file07;
private static File file03; private static File file03;
private static File fileCsv;
@BeforeClass @BeforeClass
public static void init() { public static void init() {
file07 = TestFileUtil.createNewFile("annotation07.xlsx"); file07 = TestFileUtil.createNewFile("annotation07.xlsx");
file03 = TestFileUtil.createNewFile("annotation03.xls"); file03 = TestFileUtil.createNewFile("annotation03.xls");
fileCsv = TestFileUtil.createNewFile("annotation.csv");
} }
@Test @Test
@ -36,6 +37,11 @@ public class AnnotationDataTest {
readAndWrite(file03); readAndWrite(file03);
} }
@Test
public void t02ReadAndWriteCsv() throws Exception {
readAndWrite(fileCsv);
}
private void readAndWrite(File file) throws Exception { private void readAndWrite(File file) throws Exception {
EasyExcel.write().file(file).head(AnnotationData.class).sheet().doWrite(data()); EasyExcel.write().file(file).head(AnnotationData.class).sheet().doWrite(data());
EasyExcel.read().file(file).head(AnnotationData.class).registerReadListener(new AnnotationDataListener()) EasyExcel.read().file(file).head(AnnotationData.class).registerReadListener(new AnnotationDataListener())
@ -43,7 +49,7 @@ public class AnnotationDataTest {
} }
private List<AnnotationData> data() throws Exception { private List<AnnotationData> data() throws Exception {
List<AnnotationData> list = new ArrayList<AnnotationData>(); List<AnnotationData> list = new ArrayList<>();
AnnotationData data = new AnnotationData(); AnnotationData data = new AnnotationData();
data.setDate(DateUtils.parseDate("2020-01-01 01:01:01")); data.setDate(DateUtils.parseDate("2020-01-01 01:01:01"));
data.setNumber(99.99); data.setNumber(99.99);

Loading…
Cancel
Save