package com.brightgenerous.poi.writer;
import static com.brightgenerous.poi.PoiMethods.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import com.brightgenerous.lang.Args;
import com.brightgenerous.poi.CellStyleRegister;
public class WorkbookWriter implements IWorkbookWriter {
private final IWorkbookWriterStrategy workbookStrategy;
private final TemplateLoader templateLoader;
public WorkbookWriter(IWorkbookWriterStrategy workbookStrategy, TemplateLoader templateLoader) {
Args.notNull(workbookStrategy, "workbookStrategy");
this.workbookStrategy = workbookStrategy;
this.templateLoader = templateLoader;
}
protected IWorkbookWriterStrategy getWorkbookStrategy() {
return workbookStrategy;
}
protected TemplateLoader getTemplateLoader() {
return templateLoader;
}
@Override
public void write(OutputStream outputStream) throws IOException {
Args.notNull(outputStream, "outputStream");
IWorkbookWriterStrategy strategy = getWorkbookStrategy();
boolean hasTemplate = false;
Workbook workbook;
TemplateLoader templateLoader = getTemplateLoader();
if (strategy.getXlsxFlag()) {
if (templateLoader != null) {
try (InputStream is = templateLoader.loadXSSF()) {
workbook = new XSSFWorkbook(is);
}
if (0 < workbook.getNumberOfSheets()) {
hasTemplate = true;
}
} else {
workbook = new XSSFWorkbook();
}
} else {
if (templateLoader != null) {
try (InputStream is = templateLoader.loadHSSF()) {
workbook = new HSSFWorkbook(is);
}
if (0 < workbook.getNumberOfSheets()) {
hasTemplate = true;
}
} else {
workbook = new HSSFWorkbook();
}
}
boolean empty = true;
int index = 0;
List<ISheetWriterStrategy> sheetStrategys = new ArrayList<>();
CellStyleRegister cellStyleRegister = newCellStyleRegister(workbook);
Set<String> sheetNameCache = new HashSet<>();
Iterator<ISheetWriterStrategy> itr = strategy.getSheetStrategys();
while (itr.hasNext()) {
ISheetWriterStrategy sheetStrategy = itr.next();
sheetStrategys.add(sheetStrategy);
writeSheet(workbook, index, sheetStrategy, cellStyleRegister, hasTemplate,
sheetNameCache);
index += 1;
if (empty) {
empty = false;
}
}
if (empty) {
ISheetWriterStrategy sheetStrategy = strategy.getEmptySheetStrategy();
writeSheet(workbook, index, sheetStrategy, cellStyleRegister, hasTemplate,
sheetNameCache);
}
if (hasTemplate) {
removeTemplate(workbook);
}
{
int sheetNum = sheetStrategys.size();
CreationHelper crateHelper = workbook.getCreationHelper();
FormulaEvaluator evaluator = crateHelper.createFormulaEvaluator();
for (int i = 0; i < sheetNum; i++) {
ISheetWriterStrategy sheetStrategy = sheetStrategys.get(i);
if (sheetStrategy.getConvertToString()) {
Sheet sheet = workbook.getSheetAt(i);
evaluateAllCell(evaluator, sheet);
}
}
DataFormatter dataFormatter = new DataFormatter();
for (int i = 0; i < sheetNum; i++) {
ISheetWriterStrategy sheetStrategy = sheetStrategys.get(i);
Sheet sheet = workbook.getSheetAt(i);
if (sheetStrategy.getConvertToString()) {
convertAllCellToString(dataFormatter, sheet,
sheetStrategy.getFormatterRegister());
}
}
}
{
// active
setSelectActive(workbook);
}
workbook.write(outputStream);
}
protected void writeSheet(Workbook workbook, int index, ISheetWriterStrategy sheetStrategy,
CellStyleRegister register, boolean hasTemplate, Set<String> sheetNameCache) {
String sheetName = sheetStrategy.getSheetName(workbook, index);
sheetName = escapeSheetName(sheetName);
if (sheetNameCache.contains(sheetName)) {
int idx = 0;
String tmp = sheetName;
while (sheetNameCache.contains(tmp)) {
idx++;
tmp = sheetName + " (" + idx + ")";
}
sheetName = tmp;
sheetNameCache.add(sheetName);
} else {
sheetNameCache.add(sheetName);
}
Sheet sheet;
if (hasTemplate) {
sheet = cloneSheetFromTemplate(workbook, sheetName);
} else {
sheet = workbook.createSheet(sheetName);
}
{
int idx = sheetStrategy.getWriter().getIndex();
if ((0 <= idx) && (idx < index)) {
index = idx;
workbook.setSheetOrder(sheetName, index);
}
}
sheetStrategy.getWriter().write(workbook, index, sheet, register);
}
protected Sheet cloneSheetFromTemplate(Workbook workbook, String sheetName) {
int lastIndex = workbook.getNumberOfSheets() - 1;
Sheet sheet = workbook.cloneSheet(lastIndex);
int index = workbook.getSheetIndex(sheet);
workbook.setSheetName(index, sheetName);
workbook.setSheetOrder(sheetName, lastIndex);
return workbook.getSheetAt(lastIndex);
}
protected void removeTemplate(Workbook workbook) {
if (workbook instanceof XSSFWorkbook) {
workbook.removeSheetAt(workbook.getNumberOfSheets() - 1);
} else {
workbook.setSheetHidden(workbook.getNumberOfSheets() - 1, true);
}
}
protected void setSelectActive(Workbook workbook) {
int num = workbook.getNumberOfSheets();
select: {
int first = -1;
for (int i = 0; i < num; i++) {
if (!workbook.isSheetHidden(i)) {
if (first != -1) {
first = i;
}
if (workbook.getSheetAt(i).isSelected()) {
break select;
}
}
}
if (first != -1) {
workbook.getSheetAt(first).setSelected(true);
}
}
{
int active = workbook.getActiveSheetIndex();
if ((active < 0) || (num <= active) || workbook.isSheetHidden(active)) {
for (int i = 0; i < num; i++) {
if (!workbook.isSheetHidden(i)) {
workbook.setActiveSheet(i);
break;
}
}
}
}
}
}