All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.scudata.excel.XlsxSExporter Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20241126
Show newest version
package com.scudata.excel;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;

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.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.scudata.common.Logger;
import com.scudata.common.RQException;
import com.scudata.common.StringUtils;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;

/**
 * Implementation of streaming excel export function
 */
public class XlsxSExporter implements IExcelTool {
	/**
	 * SXSSFWorkbook
	 */
	private SXSSFWorkbook wb = null;
	/**
	 * Sheet
	 */
	private Sheet sheet = null;
	/**
	 * FileObject
	 */
	private FileObject fo = null;
	/**
	 * The styles used when exporting the sheet
	 */
	private HashMap styles = new HashMap();
	/**
	 * Has title line
	 */
	private boolean hasTitle;
	/**
	 * Export title line
	 */
	private boolean writeTitle;
	/**
	 * Whether to append export
	 */
	private boolean isAppend;

	private boolean isK;
	/**
	 * After the first row of data is written out, save the style and use it
	 * directly later.
	 */
	private boolean resetDataStyle = true;
	/**
	 * Next line to write
	 */
	private int currRow = 0;
	/**
	 * Maximum number of rows
	 */
	private int maxWriteCount = MAX_XLSX_LINECOUNT;
	/**
	 * Styles of the row and cells
	 */
	private RowAndCellStyle dataStyle;
	/**
	 * Column styles
	 */
	private CellStyle[] colStyles;
	/**
	 * Excel password
	 */
	private String pwd;
	/**
	 * Whether the sheet exists
	 */
	private boolean sheetExists = false;

	/**
	 * Constructor
	 * 
	 * @param fo
	 *            FileObject
	 * @param hasTitle
	 *            Has title line
	 * @param isAppend
	 *            Whether to append export
	 * @param sheetName
	 *            Sheet name
	 * @param pwd
	 *            Excel password
	 */
	public XlsxSExporter(FileObject fo, boolean hasTitle, boolean isAppend,
			Object sheetName, String pwd, boolean isK) {
		this.fo = fo;
		this.hasTitle = hasTitle;
		writeTitle = hasTitle;
		this.isAppend = isAppend;
		this.isK = isK;
		this.pwd = pwd;
		try {
			wb = new SXSSFWorkbook(500);
			sheet = wb.createSheet();
			loadSheet(StringUtils.isValidString(sheetName) ? (String) sheetName
					: "");
		} catch (Exception e) {
			throw new RQException(e.getMessage());
		}
	}

	/**
	 * Get the maximum number of rows
	 */
	public int getMaxLineCount() {
		return maxWriteCount;
	}

	/**
	 * Write a row of data
	 * 
	 * @param items
	 *            Object[]
	 */
	public void writeLine(Object[] items) {
		if (sheet == null)
			return;
		Row row = null;
		if (currRow <= sheet.getLastRowNum())
			row = sheet.getRow(currRow);
		if (row == null)
			row = sheet.createRow(currRow);
		RowAndCellStyle rowStyle;
		if (writeTitle) {
			rowStyle = getRowStyle(currRow);
		} else {
			rowStyle = dataStyle;
		}
		writeRowData(row, items, rowStyle == null ? null : rowStyle.rowStyle,
				rowStyle == null ? null : rowStyle.cellStyles);
		if (writeTitle) {
			writeTitle = false;
		} else {
			if (sheetExists && resetDataStyle) {
				resetDataStyle(row);
			}
		}
		currRow++;
	}

	/**
	 * Reset data styles
	 * 
	 * @param row
	 *            Row
	 */
	private void resetDataStyle(Row row) {
		if (dataStyle == null) {
			dataStyle = new RowAndCellStyle();
		}
		int lastCol = row.getLastCellNum();
		if (lastCol > 0) {
			CellStyle[] cellStyles = new CellStyle[lastCol];
			Cell cell;
			for (int c = 0; c < lastCol; c++) {
				cell = row.getCell(c);
				if (cell != null)
					cellStyles[c] = cell.getCellStyle();
			}
			dataStyle.cellStyles = cellStyles;
		}
		resetDataStyle = false;
	}

	/**
	 * Write a row of data
	 * 
	 * @param row
	 *            XSSFRow
	 * @param items
	 *            Row datas
	 * @param rowStyle
	 *            CellStyle
	 * @param cellStyles
	 *            Cell styles
	 */
	private void writeRowData(Row row, Object[] items, CellStyle rowStyle,
			CellStyle[] cellStyles) {
		if (items == null || items.length == 0)
			return;
		CellStyle cellStyle, rowOrColStyle = null;
		for (int currCol = 0, maxCol = items.length; currCol < maxCol; currCol++) {
			Cell cell = row.getCell(currCol);
			if (cell == null) {
				cellStyle = null;
				cell = row.createCell(currCol);
				if (cellStyles != null && cellStyles.length > currCol) {
					cellStyle = cellStyles[currCol];
					cell.setCellStyle(cellStyle);
				}
			} else {
				cellStyle = cell.getCellStyle();
			}

			if (cellStyle == null) {
				if (rowStyle != null) {
					cell.setCellStyle(rowStyle);
					rowOrColStyle = rowStyle;
				} else if (colStyles != null) {
					if (currCol < colStyles.length) {
						if (colStyles[currCol] != null) {
							cell.setCellStyle(colStyles[currCol]);
							rowOrColStyle = colStyles[currCol];
						}
					}
				}
			}
			Object value = items[currCol];
			if (value instanceof Date) {
				if (value instanceof Time) {
					cell.setCellValue(ExcelUtils.getExcelTimeDouble((Time) value));
				} else {
					cell.setCellValue((Date) value);
				}
				DataFormat dFormat = wb.createDataFormat();
				if (cellStyle == null
						&& !ExcelUtils.isCellDateFormatted(cell, dFormat)) {
					CellStyle style = null;
					short format = 49;
					if (value instanceof Timestamp) {
						format = dFormat.getFormat(Env.getDateTimeFormat());
					} else if (value instanceof Time) {
						format = dFormat.getFormat(Env.getTimeFormat());
					} else {
						format = dFormat.getFormat(Env.getDateFormat());
					}
					style = styles.get(new Integer(currCol));
					if (style == null) {
						style = wb.createCellStyle();
						if (rowOrColStyle != null)
							style.cloneStyleFrom(rowOrColStyle);
						style.setDataFormat(format);
						styles.put(new Integer(currCol), style);
					}
					cell.setCellStyle(style);
				}
			} else if (value instanceof String) {
				String sValue = (String) value;
				if (ExcelUtils.isNumeric(sValue)) {
					cell.setCellType(CellType.STRING);
				}
				cell.setCellValue(sValue);
			} else if (value instanceof Boolean) {
				cell.setCellValue(((Boolean) value).booleanValue());
			} else if (value == null) {
			} else {
				String s = value.toString();
				try {
					double d = Double.parseDouble(s);
					cell.setCellValue(d);
				} catch (Throwable e1) {
					cell.setCellValue(s);
				}
			}
		}
		if (rowStyle != null) {
			row.setRowStyle(rowStyle);
		}
	}

	/**
	 * If the cell has style, return it, otherwise return the style of the row.
	 * 
	 * @param r
	 *            Row number
	 * @return
	 */
	private RowAndCellStyle getRowStyle(int r) {
		Row hr = sheet.getRow(r);
		if (hr == null)
			return null;
		RowAndCellStyle style = new RowAndCellStyle();
		style.rowStyle = hr.getRowStyle();
		short lastCol = hr.getLastCellNum();
		if (lastCol > 0) {
			CellStyle[] cellStyles = new CellStyle[lastCol];
			for (int c = 0; c < lastCol; c++) {
				Cell cell = hr.getCell(c);
				if (cell != null)
					cellStyles[c] = cell.getCellStyle();
			}
			style.cellStyles = cellStyles;
		}
		style.rowHeight = hr.getHeightInPoints();
		return style;
	}

	/**
	 * Set the name of the sheet to be operated
	 * 
	 * @param name
	 */
	public void setSheet(String sheetName) {
		currRow = 0;
		int index = 1;
		while (wb.getSheet(DEFAULT_SHEET_NAME_PRE + index) != null) {
			index++;
		}
		String newName = DEFAULT_SHEET_NAME_PRE + index;
		sheet = wb.createSheet();
		int sheetIndex = wb.getSheetIndex(sheet);
		wb.setSheetName(sheetIndex, newName);
	}

	/**
	 * Set the sequence number of the sheet to be operated.
	 * 
	 * @param name
	 */
	public void setSheet(int index) {
	}

	/**
	 * Total number of rows
	 * 
	 * @return
	 */
	public int totalCount() {
		return 0;
	}

	/**
	 * Set start line
	 * 
	 * @param start
	 */
	public void setStartRow(int start) {
	}

	/**
	 * Set the number of rows to be fetched
	 * 
	 * @param fetchCount
	 */
	public void setFetchCount(int fetchCount) {
	}

	/**
	 * Complete the read and write operations, if it is to write a file, then
	 * output the file at this time.
	 */
	public void output() {
		if (wb != null && fo != null) {
			OutputStream out = null;
			try {
				out = fo.getBufferedOutputStream(false);
				wb.write(out);
			} catch (Exception e) {
				throw new RQException(e.getMessage());
			} finally {
				try {
					wb.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if (out != null)
					try {
						out.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
			}
			if (pwd != null) {
				ExcelUtils.encrypt(fo, pwd);
			}
		}
	}

	/**
	 * Close
	 * 
	 * @throws IOException
	 */
	public void close() throws IOException {
		output();
	}

	/**
	 * Read a row of data
	 */
	public Object[] readLine() {
		return null;
	}

	/**
	 * Load styles from sheet
	 * 
	 * @param sheetName
	 *            Sheet name
	 */
	private void loadSheet(String sheetName) {
		InputStream is = null;
		XSSFWorkbook wbOld = null;
		try {
			if (fo.isExists() && (isAppend || isK)) {
				is = fo.getInputStream();
				wbOld = new XSSFWorkbook(is);
				XSSFSheet oldSheet = null;
				if (StringUtils.isValidString(sheetName)) {
					wb.setSheetName(wb.getSheetIndex(sheet), (String) sheetName);
					oldSheet = wbOld.getSheet((String) sheetName);
				} else {
					int sheetCount = ExcelVersionCompatibleUtilGetter
							.getInstance().getNumberOfSheets(wbOld);
					if (sheetCount > 0) {
						oldSheet = wbOld.getSheetAt(0);
					}
				}
				if (oldSheet != null) {
					sheetExists = true;
					loadSheet(oldSheet);
					if (isAppend) {
						loadStylesA(oldSheet);
					} else if (isK) {
						loadStylesK(oldSheet);
					}
				}
			} else {
				String name = DEFAULT_SHEET_NAME;
				if (StringUtils.isValidString(sheetName)) {
					name = sheetName;
				}
				wb.setSheetName(wb.getSheetIndex(sheet), name);
			}
		} catch (Exception e) {
			Logger.error("Error while reading the file: " + fo.getFileName());
			e.getMessage();
		} finally {
			if (wbOld != null)
				try {
					wbOld.close();
				} catch (IOException e) {
				}
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}
	}

	/**
	 * Load the sheet styles in the file
	 * 
	 * @param oldSheet
	 *            XSSFSheet
	 */
	private void loadSheet(XSSFSheet oldSheet) {
		int lastRow = oldSheet.getLastRowNum();
		int totalColCount = 0;
		XSSFRow oldRow;
		for (int r = 0; r <= lastRow; r++) {
			oldRow = oldSheet.getRow(r);
			if (oldRow == null)
				continue;
			totalColCount = Math.max(oldRow.getLastCellNum(), totalColCount);
		}
		Row row;
		XSSFCellStyle oldRowStyle, oldCellStyle;
		CellStyle rowStyle, cellStyle;
		Cell cell;
		XSSFCell oldCell;
		CellType cellType;
		HashMap styleMap = new HashMap();
		if (totalColCount > 0) {
			try {
				colStyles = new CellStyle[totalColCount];
				CellStyle oldColStyle;
				for (int c = 0; c < totalColCount; c++) {
					sheet.setColumnWidth(c, oldSheet.getColumnWidth(c));
					oldColStyle = oldSheet.getColumnStyle(c);
					colStyles[c] = cloneCellStyle(styleMap, oldColStyle);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		for (int r = 0; r <= lastRow; r++) {
			row = sheet.createRow(r);
			oldRow = oldSheet.getRow(r);
			row.setHeightInPoints(oldRow.getHeightInPoints());
			oldRowStyle = oldRow.getRowStyle();
			if (oldRowStyle != null) {
				rowStyle = styleMap.get(oldRowStyle);
				if (rowStyle == null) {
					rowStyle = wb.createCellStyle();
					rowStyle.cloneStyleFrom(oldRowStyle);
					styleMap.put(oldRowStyle, rowStyle);
				}
				row.setRowStyle(rowStyle);
			}
			for (int c = 0; c < oldRow.getLastCellNum(); c++) {
				cell = row.createCell(c);
				oldCell = oldRow.getCell(c);
				oldCellStyle = oldCell.getCellStyle();
				if (oldCellStyle != null) {
					cellStyle = cloneCellStyle(styleMap, oldCellStyle);
					cell.setCellStyle(cellStyle);
				} else if (colStyles[c] != null) {
					cell.setCellStyle(colStyles[c]);
				}
				cellType = ExcelVersionCompatibleUtilGetter.getInstance()
						.getCellType(oldCell);
				cell.setCellType(cellType);
				if (CellType.BLANK.compareTo(cellType) == 0) {
				} else if (CellType.BOOLEAN.compareTo(cellType) == 0) {
					cell.setCellValue(oldCell.getBooleanCellValue());
				} else if (CellType.ERROR.compareTo(cellType) == 0) {
					cell.setCellErrorValue(oldCell.getErrorCellValue());
				} else if (CellType.FORMULA.compareTo(cellType) == 0) {
					cell.setCellFormula(oldCell.getCellFormula());
				} else if (CellType.NUMERIC.compareTo(cellType) == 0) {
					cell.setCellValue(oldCell.getNumericCellValue());
				} else if (CellType.STRING.compareTo(cellType) == 0) {
					cell.setCellValue(oldCell.getStringCellValue());
				}
			}
		}
	}

	/**
	 * Load styles from sheet
	 * 
	 * @param sheet
	 *            XSSFSheet
	 */
	private void loadStylesA(XSSFSheet sheet) {
		if (sheet == null)
			return;
		try {
			int lastRow = sheet.getLastRowNum();
			if (lastRow < 0) {
				return;
			}
			int lastContentRow = -1;
			XSSFRow hr;
			// int colCount = 0;
			for (int r = lastRow; r >= 0; r--) {
				hr = sheet.getRow(r);
				if (hr == null)
					continue;
				int lastCol = hr.getLastCellNum();
				// colCount = Math.max(lastCol, colCount);
				if (!ExcelUtils.isEmptyRow(hr, lastCol)) {
					lastContentRow = r;
					break;
				}
			}
			if (hasTitle) {
				if (lastContentRow == -1) {
					lastContentRow = 0;
				}
				currRow = lastContentRow;
				dataStyle = getRowStyle(lastContentRow + 1);
			} else {
				if (lastContentRow == -1) {
					currRow = 0;
				} else {
					currRow = lastContentRow + 1;
				}
				if (lastContentRow < lastRow) {
					dataStyle = getRowStyle(lastContentRow + 1);
				} else {
					dataStyle = getRowStyle(lastContentRow);
				}
			}

			maxWriteCount -= currRow + 1;

			// colStyles = new CellStyle[colCount];
			// for (int c = 0; c < colCount; c++) {
			// colStyles[c] = sheet.getColumnStyle(c);
			// }

		} catch (Exception e) {
			Logger.error(e);
		}
	}

	/**
	 * Clone cell styles
	 * 
	 * @param styleMap
	 * @param oldCellStyle
	 * @return
	 */
	private CellStyle cloneCellStyle(HashMap styleMap,
			CellStyle oldCellStyle) {
		CellStyle cellStyle = styleMap.get(oldCellStyle);
		if (cellStyle == null) {
			cellStyle = wb.createCellStyle();
			cellStyle.cloneStyleFrom(oldCellStyle);
			styleMap.put(oldCellStyle, cellStyle);
		}
		return cellStyle;
	}

	/**
	 * Load styles from sheet
	 * 
	 * @param sheet
	 *            XSSFSheet
	 */
	private void loadStylesK(XSSFSheet sheet) {
		if (sheet == null)
			return;
		try {
			int lastRow = sheet.getLastRowNum();
			if (lastRow < 0) {
				return;
			}
			currRow = 0;
			if (hasTitle) {
				dataStyle = getRowStyle(1);
			} else {
				dataStyle = getRowStyle(0);
			}
			maxWriteCount -= currRow + 1;
		} catch (Exception e) {
			Logger.error(e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy