forked from fanruan/easyexcel
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
794 lines
16 KiB
794 lines
16 KiB
package com.alibaba.excel.metadata.csv; |
|
|
|
import java.io.Closeable; |
|
import java.io.IOException; |
|
import java.util.Collection; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.Map; |
|
|
|
import com.alibaba.excel.constant.BuiltinFormats; |
|
import com.alibaba.excel.enums.NumericCellTypeEnum; |
|
import com.alibaba.excel.exception.ExcelGenerateException; |
|
import com.alibaba.excel.util.DateUtils; |
|
import com.alibaba.excel.util.ListUtils; |
|
import com.alibaba.excel.util.NumberDataFormatterUtils; |
|
import com.alibaba.excel.util.StringUtils; |
|
|
|
import lombok.Data; |
|
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.DateUtil; |
|
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; |
|
|
|
/** |
|
* csv sheet |
|
* |
|
* @author Jiaju Zhuang |
|
*/ |
|
@Data |
|
public class CsvSheet implements Sheet, Closeable { |
|
/** |
|
* workbook |
|
*/ |
|
private CsvWorkbook csvWorkbook; |
|
/** |
|
* output |
|
*/ |
|
private Appendable out; |
|
/** |
|
* row cache |
|
*/ |
|
private Integer rowCacheCount; |
|
/** |
|
* format |
|
*/ |
|
public CSVFormat csvFormat; |
|
|
|
/** |
|
* last row index |
|
*/ |
|
private Integer lastRowIndex; |
|
|
|
/** |
|
* row cache |
|
*/ |
|
private List<CsvRow> rowCache; |
|
/** |
|
* csv printer |
|
*/ |
|
private CSVPrinter csvPrinter; |
|
|
|
public CsvSheet(CsvWorkbook csvWorkbook, Appendable out) { |
|
this.csvWorkbook = csvWorkbook; |
|
this.out = out; |
|
this.rowCacheCount = 3000; |
|
this.csvFormat = CSVFormat.DEFAULT; |
|
this.lastRowIndex = -1; |
|
} |
|
|
|
@Override |
|
public Row createRow(int rownum) { |
|
// Initialize the data when the row is first created |
|
initSheet(); |
|
|
|
lastRowIndex++; |
|
assert rownum == lastRowIndex : "csv create row must be in order."; |
|
printData(); |
|
CsvRow csvRow = new CsvRow(csvWorkbook, this, rownum); |
|
rowCache.add(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 |
|
public void removeRow(Row row) { |
|
throw new UnsupportedOperationException("csv cannot move row."); |
|
} |
|
|
|
@Override |
|
public Row getRow(int rownum) { |
|
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 |
|
public int getPhysicalNumberOfRows() { |
|
return lastRowIndex - rowCache.size(); |
|
} |
|
|
|
@Override |
|
public int getFirstRowNum() { |
|
if (lastRowIndex < 0) { |
|
return -1; |
|
} |
|
return 0; |
|
} |
|
|
|
@Override |
|
public int getLastRowNum() { |
|
return lastRowIndex; |
|
} |
|
|
|
@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<Integer> indices) { |
|
|
|
} |
|
|
|
@Override |
|
public int getNumMergedRegions() { |
|
return 0; |
|
} |
|
|
|
@Override |
|
public CellRangeAddress getMergedRegion(int index) { |
|
return null; |
|
} |
|
|
|
@Override |
|
public List<CellRangeAddress> getMergedRegions() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public Iterator<Row> rowIterator() { |
|
return (Iterator<Row>)(Iterator<? extends Row>)rowCache.iterator(); |
|
} |
|
|
|
@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<CellAddress, ? extends Comment> getCellComments() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public Drawing<?> getDrawingPatriarch() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public Drawing<?> createDrawingPatriarch() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public Workbook getWorkbook() { |
|
return csvWorkbook; |
|
} |
|
|
|
@Override |
|
public String getSheetName() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public boolean isSelected() { |
|
return false; |
|
} |
|
|
|
@Override |
|
public CellRange<? extends Cell> setArrayFormula( |
|
String formula, CellRangeAddress range) { |
|
return null; |
|
} |
|
|
|
@Override |
|
public CellRange<? extends Cell> removeArrayFormula(Cell cell) { |
|
return null; |
|
} |
|
|
|
@Override |
|
public DataValidationHelper getDataValidationHelper() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public List<? extends DataValidation> 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<? extends Hyperlink> getHyperlinkList() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public CellAddress getActiveCell() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public void setActiveCell(CellAddress address) { |
|
|
|
} |
|
|
|
@Override |
|
public Iterator<Row> iterator() { |
|
return rowIterator(); |
|
} |
|
|
|
@Override |
|
public void close() throws IOException { |
|
// Avoid empty sheets |
|
initSheet(); |
|
|
|
flushData(); |
|
csvPrinter.flush(); |
|
csvPrinter.close(); |
|
} |
|
|
|
public void printData() { |
|
if (rowCache.size() >= rowCacheCount) { |
|
flushData(); |
|
} |
|
} |
|
|
|
public void flushData() { |
|
try { |
|
for (CsvRow row : rowCache) { |
|
Iterator<Cell> cellIterator = row.cellIterator(); |
|
while (cellIterator.hasNext()) { |
|
CsvCell csvCell = (CsvCell)cellIterator.next(); |
|
csvPrinter.print(buildCellValue(csvCell)); |
|
} |
|
csvPrinter.println(); |
|
} |
|
rowCache.clear(); |
|
} catch (IOException e) { |
|
throw new ExcelGenerateException(e); |
|
} |
|
} |
|
|
|
private String buildCellValue(CsvCell csvCell) { |
|
switch (csvCell.getCellType()) { |
|
case STRING: |
|
case ERROR: |
|
case FORMULA: |
|
return csvCell.getStringCellValue(); |
|
case NUMERIC: |
|
Short dataFormat = null; |
|
String dataFormatString = null; |
|
if (csvCell.getCellStyle() != null) { |
|
dataFormat = csvCell.getCellStyle().getDataFormat(); |
|
dataFormatString = csvCell.getCellStyle().getDataFormatString(); |
|
} |
|
if (csvCell.getNumericCellType() == NumericCellTypeEnum.DATE) { |
|
if (csvCell.getDateValue() == null) { |
|
return null; |
|
} |
|
// date |
|
if (dataFormat == null) { |
|
dataFormatString = DateUtils.defaultDateFormat; |
|
dataFormat = csvWorkbook.createDataFormat().getFormat(dataFormatString); |
|
} |
|
if (dataFormatString == null) { |
|
dataFormatString = csvWorkbook.createDataFormat().getFormat(dataFormat); |
|
} |
|
return NumberDataFormatterUtils.format( |
|
DateUtil.getExcelDate(csvCell.getDateValue(), csvWorkbook.getUse1904windowing()), |
|
dataFormat, dataFormatString, csvWorkbook.getUse1904windowing(), csvWorkbook.getLocale(), |
|
csvWorkbook.getUseScientificFormat()); |
|
} else { |
|
if (csvCell.getNumberValue() == null) { |
|
return null; |
|
} |
|
//number |
|
if (dataFormat == null) { |
|
dataFormat = BuiltinFormats.GENERAL; |
|
dataFormatString = csvWorkbook.createDataFormat().getFormat(dataFormat); |
|
} |
|
return NumberDataFormatterUtils.format(csvCell.getNumericCellValue(), dataFormat, dataFormatString, |
|
csvWorkbook.getUse1904windowing(), csvWorkbook.getLocale(), |
|
csvWorkbook.getUseScientificFormat()); |
|
} |
|
case BOOLEAN: |
|
return csvCell.getBooleanValue().toString(); |
|
case BLANK: |
|
return StringUtils.EMPTY; |
|
default: |
|
return null; |
|
} |
|
} |
|
|
|
}
|
|
|