IDEMPIERE-2924: Adding XLSX Export support (#6)

This commit is contained in:
Deepak Pansheriya 2020-01-04 19:49:48 +05:30 committed by Carlos Ruiz
parent 9ec91aa1d9
commit 503ca8eb62
12 changed files with 1119 additions and 2 deletions

View File

@ -0,0 +1,11 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Excel 2007 support in idempiere
-- Apr 12, 2018 3:12:17 PM IST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','xlsx - Excel file',0,0,'Y',TO_DATE('2018-04-12 15:12:16','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2018-04-12 15:12:16','YYYY-MM-DD HH24:MI:SS'),100,200451,'FileXLSX','D','48cc5032-f2c7-4b27-99bc-05c6269d032b')
;
SELECT register_migration_script('201804121850_Extend_Export_Feature.sql') FROM dual
;

View File

@ -0,0 +1,8 @@
-- Excel 2007 support in idempiere
-- Apr 12, 2018 3:12:17 PM IST
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','xlsx - Excel file',0,0,'Y',TO_TIMESTAMP('2018-04-12 15:12:16','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2018-04-12 15:12:16','YYYY-MM-DD HH24:MI:SS'),100,200451,'FileXLSX','D','48cc5032-f2c7-4b27-99bc-05c6269d032b')
;
SELECT register_migration_script('201804121850_Extend_Export_Feature.sql') FROM dual
;

View File

@ -517,4 +517,11 @@
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.poi.poi-ooxml"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View File

@ -140,4 +140,13 @@
</run>
</application>
</extension>
<extension
id="org.adempiere.impexp.GridTabXLSXExporter"
name="Grid data excel exporter"
point="org.adempiere.base.IGridTabExporter">
<exporter
class="org.adempiere.impexp.GridTabXLSXExporter"
priority="0">
</exporter>
</extension>
</plugin>

View File

@ -0,0 +1,570 @@
/******************************************************************************
* Copyright (C) 2018 Logilite Technologies LLP *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.impexp;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFHeader;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFPrintSetup;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.compiere.util.CLogger;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Ini;
import org.compiere.util.Language;
import org.compiere.util.Msg;
import org.compiere.util.Util;
/**
* Abstract MS Excel Format (xlsx) Exporter
*
* @author Deepak Pansheriya
*/
public abstract class AbstractXLSXExporter
{
/**
* Is the current Row a Function Row
*
* @return true if function row
*/
public abstract boolean isFunctionRow();
/**
* Get Columns Count
*
* @return number of columns
*/
public abstract int getColumnCount();
/**
* Get Rows Count
*
* @return number of rows
*/
public abstract int getRowCount();
/**
* Set current row
*
* @param row row index
*/
protected abstract void setCurrentRow(int row);
/**
* @return current row index
*/
protected abstract int getCurrentRow();
/**
* Check if column is printed (displayed)
*
* @param col column index
* @return true if is visible
*/
public abstract boolean isColumnPrinted(int col);
/**
* Get column header name
*
* @param col column index
* @return header name
*/
public abstract String getHeaderName(int col);
/**
* Get cell display type (see {@link DisplayType})
*
* @param row row index
* @param col column index
* @return display type
*/
public abstract int getDisplayType(int row, int col);
/**
* Get cell value
*
* @param row row index
* @param col column index
* @return cell value
*/
public abstract Object getValueAt(int row, int col);
/**
* Check if there is a page break on given cell
*
* @param row row index
* @param col column index
* @return true if there is a page break
*/
public abstract boolean isPageBreak(int row, int col);
/** Logger */
protected final CLogger log = CLogger.getCLogger(getClass());
//
private XSSFWorkbook m_workbook;
private XSSFDataFormat m_dataFormat;
private XSSFFont m_fontHeader = null;
private XSSFFont m_fontDefault = null;
private Language m_lang = null;
private int m_sheetCount = 0;
//
private int m_colSplit = 1;
private int m_rowSplit = 1;
private boolean currentRowOnly = false;
/** Styles cache */
private HashMap<String, XSSFCellStyle> m_styles = new HashMap<String, XSSFCellStyle>();
protected Boolean[] colSuppressRepeats;
public AbstractXLSXExporter()
{
m_workbook = new XSSFWorkbook();
m_dataFormat = m_workbook.createDataFormat();
}
protected Properties getCtx()
{
return Env.getCtx();
}
protected void setFreezePane(int colSplit, int rowSplit)
{
m_colSplit = colSplit;
m_rowSplit = rowSplit;
}
private String fixString(String str)
{
// ms excel doesn't support UTF8 charset
return Util.stripDiacritics(str);
}
protected Language getLanguage()
{
if (m_lang == null)
m_lang = Env.getLanguage(getCtx());
return m_lang;
}
private XSSFFont getFont(boolean isHeader)
{
XSSFFont font = null;
if (isHeader)
{
if (m_fontHeader == null)
{
m_fontHeader = m_workbook.createFont();
m_fontHeader.setBold(true);
}
font = m_fontHeader;
}
else if (isFunctionRow())
{
font = m_workbook.createFont();
font.setBold(true);
font.setItalic(true);
}
else
{
if (m_fontDefault == null)
{
m_fontDefault = m_workbook.createFont();
}
font = m_fontDefault;
}
return font;
}
/**
* Get Excel number format string by given {@link NumberFormat}
*
* @param df number format
* @param isHighlightNegativeNumbers highlight negative numbers using RED
* color
* @return number excel format string
*/
private String getFormatString(NumberFormat df, boolean isHighlightNegativeNumbers)
{
StringBuffer format = new StringBuffer();
int integerDigitsMin = df.getMinimumIntegerDigits();
int integerDigitsMax = df.getMaximumIntegerDigits();
for (int i = 0; i < integerDigitsMax; i++)
{
if (i < integerDigitsMin)
format.insert(0, "0");
else
format.insert(0, "#");
if (i == 2)
{
format.insert(0, ",");
}
}
int fractionDigitsMin = df.getMinimumFractionDigits();
int fractionDigitsMax = df.getMaximumFractionDigits();
for (int i = 0; i < fractionDigitsMax; i++)
{
if (i == 0)
format.append(".");
if (i < fractionDigitsMin)
format.append("0");
else
format.append("#");
}
if (isHighlightNegativeNumbers)
{
String f = format.toString();
format = new StringBuffer(f).append(";[RED]-").append(f);
}
//
if (log.isLoggable(Level.FINEST))
log.finest("NumberFormat: " + format);
return format.toString();
}
private XSSFCellStyle getStyle(int row, int col)
{
int displayType = getDisplayType(row, col);
String key = "cell-" + col + "-" + displayType;
XSSFCellStyle cs = m_styles.get(key);
if (cs == null)
{
boolean isHighlightNegativeNumbers = true;
cs = m_workbook.createCellStyle();
XSSFFont font = getFont(false);
cs.setFont(font);
// Border
cs.setBorderLeft(BorderStyle.THIN);
cs.setBorderTop(BorderStyle.THIN);
cs.setBorderRight(BorderStyle.THIN);
cs.setBorderBottom(BorderStyle.THIN);
//
if (DisplayType.isDate(displayType))
{
cs.setDataFormat(m_dataFormat.getFormat(DisplayType.getDateFormat(getLanguage()).toPattern()));
}
else if (DisplayType.isNumeric(displayType))
{
DecimalFormat df = DisplayType.getNumberFormat(displayType, getLanguage());
String format = getFormatString(df, isHighlightNegativeNumbers);
cs.setDataFormat(m_dataFormat.getFormat(format));
}
m_styles.put(key, cs);
}
return cs;
}
private XSSFCellStyle getHeaderStyle(int col)
{
String key = "header-" + col;
XSSFCellStyle cs_header = m_styles.get(key);
if (cs_header == null)
{
XSSFFont font_header = getFont(true);
cs_header = m_workbook.createCellStyle();
cs_header.setFont(font_header);
cs_header.setBorderLeft(BorderStyle.MEDIUM);
cs_header.setBorderTop(BorderStyle.MEDIUM);
cs_header.setBorderRight(BorderStyle.MEDIUM);
cs_header.setBorderBottom(BorderStyle.MEDIUM);
cs_header.setDataFormat(HSSFDataFormat.getBuiltinFormat("text"));
cs_header.setWrapText(true);
m_styles.put(key, cs_header);
}
return cs_header;
}
private void fixColumnWidth(XSSFSheet sheet, int lastColumnIndex)
{
for (short colnum = 0; colnum < lastColumnIndex; colnum++)
{
sheet.autoSizeColumn(colnum);
}
}
private void closeTableSheet(XSSFSheet prevSheet, String prevSheetName, int colCount)
{
if (prevSheet == null)
return;
//
fixColumnWidth(prevSheet, colCount);
if (m_colSplit >= 0 || m_rowSplit >= 0)
prevSheet.createFreezePane(m_colSplit >= 0 ? m_colSplit : 0, m_rowSplit >= 0 ? m_rowSplit : 0);
if (!Util.isEmpty(prevSheetName, true) && m_sheetCount > 0)
{
int prevSheetIndex = m_sheetCount - 1;
try
{
m_workbook.setSheetName(prevSheetIndex, prevSheetName);
}
catch (Exception e)
{
log.log(Level.WARNING, "Error setting sheet " + prevSheetIndex + " name to " + prevSheetName, e);
}
}
}
private XSSFSheet createTableSheet()
{
XSSFSheet sheet = m_workbook.createSheet();
formatPage(sheet);
createHeaderFooter(sheet);
createTableHeader(sheet);
m_sheetCount++;
//
return sheet;
}
private void createTableHeader(XSSFSheet sheet)
{
int colnumMax = 0;
XSSFRow row = sheet.createRow(0);
// for all columns
int colnum = 0;
for (int col = 0; col < getColumnCount(); col++)
{
if (colnum > colnumMax)
colnumMax = colnum;
//
if (isColumnPrinted(col))
{
XSSFCell cell = row.createCell(colnum);
// header row
XSSFCellStyle style = getHeaderStyle(col);
cell.setCellStyle(style);
String str = fixString(getHeaderName(col));
cell.setCellValue(new XSSFRichTextString(str));
colnum++;
} // printed
} // for all columns
}
protected void createHeaderFooter(XSSFSheet sheet)
{
// Sheet Header
Header header = sheet.getHeader();
header.setRight(HSSFHeader.page() + " / " + HSSFHeader.numPages());
// Sheet Footer
Footer footer = sheet.getFooter();
footer.setLeft(Env.getStandardReportFooterTrademarkText());
footer.setCenter(Env.getHeader(getCtx(), 0));
Timestamp now = new Timestamp(System.currentTimeMillis());
footer.setRight(DisplayType.getDateFormat(DisplayType.DateTime, getLanguage()).format(now));
}
protected void formatPage(XSSFSheet sheet)
{
sheet.setFitToPage(true);
// Print Setup
XSSFPrintSetup ps = sheet.getPrintSetup();
ps.setFitWidth((short) 1);
ps.setNoColor(true);
ps.setPaperSize(XSSFPrintSetup.A4_PAPERSIZE);
ps.setLandscape(false);
}
protected boolean isCurrentRowOnly()
{
return currentRowOnly;
}
protected void setCurrentRowOnly(boolean b)
{
currentRowOnly = b;
}
/**
* Export to given stream
*
* @param out
* @throws Exception
*/
private void export(OutputStream out) throws Exception
{
XSSFSheet sheet = createTableSheet();
String sheetName = null;
//
int colnumMax = 0;
int rownum = isCurrentRowOnly() ? getCurrentRow() : 0;
int lastRowNum = isCurrentRowOnly() ? getCurrentRow() + 1 : getRowCount();
Object[] preValues = null;
int printColIndex = -1;
if (colSuppressRepeats != null)
{
preValues = new Object[colSuppressRepeats.length];
}
for (int xls_rownum = 1; rownum < lastRowNum; rownum++, xls_rownum++)
{
if (!isCurrentRowOnly())
setCurrentRow(rownum);
boolean isPageBreak = false;
XSSFRow row = sheet.createRow(xls_rownum);
printColIndex = -1;
// for all columns
int colnum = 0;
for (int col = 0; col < getColumnCount(); col++)
{
if (colnum > colnumMax)
colnumMax = colnum;
//
if (isColumnPrinted(col))
{
printColIndex++;
XSSFCell cell = row.createCell(colnum);
// line row
Object obj = getValueAt(rownum, col);
int displayType = getDisplayType(rownum, col);
if (obj == null)
{
if (colSuppressRepeats != null && colSuppressRepeats[printColIndex])
{
preValues[printColIndex] = null;
}
}
else if (colSuppressRepeats != null && colSuppressRepeats[printColIndex]
&& obj.equals(preValues[printColIndex]))
{
// suppress
}
else if (DisplayType.isDate(displayType))
{
Timestamp value = (Timestamp) obj;
cell.setCellValue(value);
}
else if (DisplayType.isNumeric(displayType))
{
double value = 0;
if (obj instanceof Number)
{
value = ((Number) obj).doubleValue();
}
cell.setCellValue(value);
}
else if (DisplayType.YesNo == displayType)
{
boolean value = false;
if (obj instanceof Boolean)
value = (Boolean) obj;
else
value = "Y".equals(obj);
cell.setCellValue(new XSSFRichTextString(Msg.getMsg(getLanguage(), value == true ? "Y" : "N")));
}
else
{
String value = fixString(obj.toString()); // formatted
cell.setCellValue(new XSSFRichTextString(value));
}
//
XSSFCellStyle style = getStyle(rownum, col);
cell.setCellStyle(style);
// Page break
if (isPageBreak(rownum, col))
{
isPageBreak = true;
sheetName = fixString(cell.getRichStringCellValue().getString());
}
//
colnum++;
if (colSuppressRepeats != null)
preValues[printColIndex] = obj;
} // printed
} // for all columns
//
// Page Break
if (isPageBreak)
{
closeTableSheet(sheet, sheetName, colnumMax);
sheet = createTableSheet();
xls_rownum = 0;
isPageBreak = false;
}
} // for all rows
closeTableSheet(sheet, sheetName, colnumMax);
//
if (out != null)
{
m_workbook.write(out);
out.close();
}
//
// Workbook Info
if (log.isLoggable(Level.FINE))
{
log.fine("Sheets #" + m_sheetCount);
log.fine("Styles used #" + m_styles.size());
}
}
/**
* Export to file
*
* @param file
* @param language reporting language
* @throws Exception
*/
public void export(File file, Language language) throws Exception
{
export(file, language, true);
}
/**
* Export to file
*
* @param file
* @param language reporting language
* @param autoOpen auto open file after generated
* @throws Exception
*/
public void export(File file, Language language, boolean autoOpen) throws Exception
{
m_lang = language;
if (file == null)
file = File.createTempFile("Report_", ".xlsx");
FileOutputStream out = new FileOutputStream(file);
export(out);
if (autoOpen && Ini.isClient())
Env.startBrowser(file.toURI().toString());
}
public void exportToWorkbook(XSSFWorkbook workbook, Language language) throws Exception
{
m_lang = language;
m_workbook = workbook;
export(null);
}
}

View File

@ -0,0 +1,202 @@
/******************************************************************************
* Copyright (C) 2018 Logilite Technologies LLP *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.impexp;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import org.adempiere.base.IGridTabExporter;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
import org.compiere.model.Lookup;
import org.compiere.model.MLookup;
import org.compiere.model.MLookupFactory;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
/**
* Excel Exporter Adapter for GridTab
*
* @author Deepak Pansheriya
*/
public class GridTabXLSXExporter extends AbstractXLSXExporter implements IGridTabExporter
{
private GridTab m_tab = null;
public GridTabXLSXExporter()
{
setFreezePane(0, 1);
}
@Override
public int getColumnCount()
{
return m_tab.getFieldCount();
}
@Override
public int getDisplayType(int row, int col)
{
return m_tab.getField(col).getDisplayType();
}
@Override
public String getHeaderName(int col)
{
return m_tab.getField(col).getHeader();
}
@Override
public int getRowCount()
{
return m_tab.getRowCount();
}
@Override
public Object getValueAt(int row, int col)
{
GridField f = m_tab.getField(col);
Object key = m_tab.getValue(row, f.getColumnName());
Object value = key;
Lookup lookup = f.getLookup();
if (lookup != null)
{
;
}
else if (f.getDisplayType() == DisplayType.Button)
{
lookup = getButtonLookup(f);
}
if (lookup != null)
{
value = lookup.getDisplay(key);
}
return value;
}
@Override
public boolean isColumnPrinted(int col)
{
GridField f = m_tab.getField(col);
// Hide not displayed fields
if (!f.isDisplayed())
return false;
// Hide encrypted fields
if (f.isEncrypted())
return false;
// Hide simple button fields without a value
if (f.getDisplayType() == DisplayType.Button && f.getAD_Reference_Value_ID() == 0)
return false;
return true;
}
@Override
public boolean isFunctionRow()
{
return false;
}
@Override
public boolean isPageBreak(int row, int col)
{
return false;
}
@Override
protected void setCurrentRow(int row)
{
; // nothing
}
protected int getCurrentRow()
{
return m_tab.getCurrentRow();
}
private HashMap<String, MLookup> m_buttonLookups = new HashMap<String, MLookup>();
private MLookup getButtonLookup(GridField mField)
{
MLookup lookup = m_buttonLookups.get(mField.getColumnName());
if (lookup != null)
return lookup;
// TODO: refactor with org.compiere.grid.ed.VButton.setField(GridField)
if (mField.getColumnName().endsWith("_ID") && !mField.getColumnName().equals("Record_ID"))
{
lookup = MLookupFactory.get(Env.getCtx(), mField.getWindowNo(), 0, mField.getAD_Column_ID(),
DisplayType.Search);
}
else if (mField.getAD_Reference_Value_ID() != 0)
{
// Assuming List
lookup = MLookupFactory.get(Env.getCtx(), mField.getWindowNo(), 0, mField.getAD_Column_ID(),
DisplayType.List);
}
//
m_buttonLookups.put(mField.getColumnName(), lookup);
return lookup;
}
@Override
public void export(GridTab gridTab, List<GridTab> childs, boolean currentRowOnly, File file, int indxDetailSelected)
{
m_tab = gridTab;
setCurrentRowOnly(currentRowOnly);
try
{
export(file, null);
}
catch (Exception e)
{
throw new AdempiereException(e);
}
}
@Override
public String getFileExtension()
{
return "xlsx";
}
@Override
public String getFileExtensionLabel()
{
return Msg.getMsg(Env.getCtx(), "FileXLSX");
}
@Override
public String getContentType()
{
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
@Override
public String getSuggestedFileName(GridTab gridTab)
{
return gridTab.getName() + "." + getFileExtension();
}
/**
* {@inheritDoc} no detail tab is support to export with excel
*/
@Override
public boolean isExportableTab(GridTab gridTab)
{
return false;
}
}

View File

@ -0,0 +1,216 @@
/******************************************************************************
* Copyright (C) 2018 Logilite Technologies LLP *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.print.export;
import java.sql.Timestamp;
import java.util.Date;
import javax.print.attribute.standard.MediaSizeName;
import org.adempiere.impexp.AbstractXLSXExporter;
import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.compiere.print.MPrintFormat;
import org.compiere.print.MPrintFormatItem;
import org.compiere.print.MPrintPaper;
import org.compiere.print.PrintData;
import org.compiere.print.PrintDataElement;
/**
* Export PrintData to Excel (XLSX) file
*
* @author Deepak Pansheriya
*/
public class PrintDataXLSXExporter extends AbstractXLSXExporter
{
private PrintData m_printData;
private MPrintFormat m_printFormat;
public PrintDataXLSXExporter(PrintData printData, MPrintFormat printFormat, Boolean[] colSuppressRepeats)
{
super();
this.m_printData = printData;
this.m_printFormat = printFormat;
this.colSuppressRepeats = colSuppressRepeats;
}
@Override
public int getColumnCount()
{
return m_printFormat.getItemCount();
}
private PrintDataElement getPDE(int row, int col)
{
if (m_printData.getRowIndex() != row)
m_printData.setRowIndex(row);
//
MPrintFormatItem item = m_printFormat.getItem(col);
int AD_Column_ID = item.getAD_Column_ID();
Object obj = null;
if (AD_Column_ID > 0)
obj = m_printData.getNode(Integer.valueOf(AD_Column_ID));
if (obj != null && obj instanceof PrintDataElement)
{
return (PrintDataElement) obj;
}
return null;
}
@Override
public int getDisplayType(int row, int col)
{
PrintDataElement pde = getPDE(row, col);
if (pde != null)
{
return pde.getDisplayType();
}
return -1;
//
}
@Override
public Object getValueAt(int row, int col)
{
PrintDataElement pde = getPDE(row, col);
Object value = null;
if (pde == null)
;
else if (pde.isDate())
{
Object o = pde.getValue();
if (o instanceof Date)
value = new Timestamp(((Date) o).getTime());
else
value = (Timestamp) pde.getValue();
}
else if (pde.isNumeric())
{
Object o = pde.getValue();
if (o instanceof Number)
{
value = ((Number) o).doubleValue();
}
}
else if (pde.isYesNo())
{
value = pde.getValue();
}
else if (pde.isPKey())
{
value = pde.getValueAsString();
}
else
{
value = pde.getValueDisplay(getLanguage());
}
//
return value;
}
@Override
public String getHeaderName(int col)
{
return m_printFormat.getItem(col).getPrintName(getLanguage());
}
@Override
public int getRowCount()
{
return m_printData.getRowCount();
}
@Override
public boolean isColumnPrinted(int col)
{
MPrintFormatItem item = m_printFormat.getItem(col);
return item.isPrinted();
}
@Override
public boolean isPageBreak(int row, int col)
{
PrintDataElement pde = getPDE(row, col);
return pde != null ? pde.isPageBreak() : false;
}
@Override
protected void setCurrentRow(int row)
{
m_printData.setRowIndex(row);
}
protected int getCurrentRow()
{
return m_printData.getRowIndex();
}
@Override
public boolean isFunctionRow()
{
return m_printData.isFunctionRow();
}
@Override
protected void formatPage(XSSFSheet sheet)
{
super.formatPage(sheet);
MPrintPaper paper = MPrintPaper.get(this.m_printFormat.getAD_PrintPaper_ID());
// Set paper size:
short paperSize = -1;
MediaSizeName mediaSizeName = paper.getMediaSize().getMediaSizeName();
if (MediaSizeName.NA_LETTER.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.LETTER_PAPERSIZE;
}
else if (MediaSizeName.NA_LEGAL.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.LEGAL_PAPERSIZE;
}
else if (MediaSizeName.EXECUTIVE.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.EXECUTIVE_PAPERSIZE;
}
else if (MediaSizeName.ISO_A4.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.A4_PAPERSIZE;
}
else if (MediaSizeName.ISO_A5.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.A5_PAPERSIZE;
}
else if (MediaSizeName.NA_NUMBER_10_ENVELOPE.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.ENVELOPE_10_PAPERSIZE;
}
else if (MediaSizeName.MONARCH_ENVELOPE.equals(mediaSizeName))
{
paperSize = HSSFPrintSetup.ENVELOPE_MONARCH_PAPERSIZE;
}
if (paperSize != -1)
{
sheet.getPrintSetup().setPaperSize(paperSize);
}
// Set Landscape/Portrait:
sheet.getPrintSetup().setLandscape(paper.isLandscape());
// Set Paper Margin:
sheet.setMargin(HSSFSheet.TopMargin, ((double) paper.getMarginTop()) / 72);
sheet.setMargin(HSSFSheet.RightMargin, ((double) paper.getMarginRight()) / 72);
sheet.setMargin(HSSFSheet.LeftMargin, ((double) paper.getMarginLeft()) / 72);
sheet.setMargin(HSSFSheet.BottomMargin, ((double) paper.getMarginBottom()) / 72);
}
}

View File

@ -63,6 +63,7 @@ import javax.xml.transform.stream.StreamResult;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.pdf.Document;
import org.adempiere.print.export.PrintDataExcelExporter;
import org.adempiere.print.export.PrintDataXLSXExporter;
import org.apache.ecs.XhtmlDocument;
import org.apache.ecs.xhtml.a;
import org.apache.ecs.xhtml.script;
@ -1483,6 +1484,20 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount)
exp.export(outFile, language);
}
/**
* Create ExcelX file
* @param outFile output file
* @param language
* @throws Exception if error
*/
public void createXLSX(File outFile, Language language)
throws Exception
{
Boolean [] colSuppressRepeats = m_layout == null || m_layout.colSuppressRepeats == null? LayoutEngine.getColSuppressRepeats(m_printFormat):m_layout.colSuppressRepeats;
PrintDataXLSXExporter exp = new PrintDataXLSXExporter(getPrintData(), getPrintFormat(), colSuppressRepeats);
exp.export(outFile, language);
}
/**************************************************************************
* Get Report Engine for process info
* @param ctx context

View File

@ -67,7 +67,8 @@ osgi.bundles=org.eclipse.equinox.ds@1:start,\
com.google.zxing.core,\
org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec,\
jakarta.xml.bind-api,\
org.eclipse.osgi@start
org.eclipse.osgi@start,\
org.dom4j
osgi.framework.extensions=
osgi.bundles.defaultStartLevel=4
osgi.compatibility.bootdelegation=true

View File

@ -470,6 +470,7 @@ public class WReportCustomization implements IFormController,EventListener<Even
cboType.appendItem("ssv" + " - " + Msg.getMsg(Env.getCtx(), "FileSSV"), "ssv");
cboType.appendItem("csv" + " - " + Msg.getMsg(Env.getCtx(), "FileCSV"), "csv");
cboType.appendItem("xls" + " - " + Msg.getMsg(Env.getCtx(), "FileXLS"), "xls");
cboType.appendItem("xlsx" + " - " + Msg.getMsg(Env.getCtx(), "FileXLSX"), "xlsx");
cboType.setSelectedItem(li);
Hbox hb = new Hbox();
@ -565,6 +566,11 @@ public class WReportCustomization implements IFormController,EventListener<Even
inputFile = File.createTempFile("Export", ".xls");
m_reportEngine.createXLS(inputFile, m_reportEngine.getPrintFormat().getLanguage());
}
else if (ext.equals("xlsx"))
{
inputFile = File.createTempFile("Export", ".xlsx");
m_reportEngine.createXLSX(inputFile, m_reportEngine.getPrintFormat().getLanguage());
}
else
{
FDialog.error(m_WindowNo, winExportFile, "FileInvalidExtension");

View File

@ -118,6 +118,7 @@ public class ReportAction implements EventListener<Event>
cboExportType.appendItem("txt" + " - " + Msg.getMsg(Env.getCtx(), "FileTXT"), "txt");
cboExportType.appendItem("ssv" + " - " + Msg.getMsg(Env.getCtx(), "FileSSV"), "ssv");
cboExportType.appendItem("csv" + " - " + Msg.getMsg(Env.getCtx(), "FileCSV"), "csv");
cboExportType.appendItem("xlsx" + " - " + Msg.getMsg(Env.getCtx(), "FileXLSX"), "xlsx");
ListItem li = cboExportType.appendItem("xls" + " - " + Msg.getMsg(Env.getCtx(), "FileXLS"), "xls");
cboExportType.setSelectedItem(li);
cboExportType.setVisible(false);
@ -440,6 +441,11 @@ public class ReportAction implements EventListener<Event>
inputFile = File.createTempFile("Export", ".xls");
re.createXLS(inputFile, re.getPrintFormat().getLanguage());
}
else if (ext.equals("xlsx"))
{
inputFile = File.createTempFile("Export", ".xlsx");
re.createXLSX(inputFile, re.getPrintFormat().getLanguage());
}
else
{
FDialog.error(0, winReport, "FileInvalidExtension");

View File

@ -280,6 +280,7 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
{
previewType.appendItem("Excel", "XLS");
previewType.appendItem("CSV", "CSV");
previewType.appendItem("Excel X", "XLSX");
}
toolBar.appendChild(previewType);
@ -658,7 +659,9 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new XLSRendererRunnable(this),getDesktop()));
} else if ("CSV".equals(previewType.getSelectedItem().getValue())) {
future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new CSVRendererRunnable(this),getDesktop()));
}
} else if ("XLSX".equals(previewType.getSelectedItem().getValue())) {
future = Adempiere.getThreadPoolExecutor().submit(new DesktopRunnable(new XLSXRendererRunnable(this),getDesktop()));
}
}
private void onPreviewReport() {
@ -1135,6 +1138,7 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
cboType.appendItem("ssv" + " - " + Msg.getMsg(Env.getCtx(), "FileSSV"), "ssv");
cboType.appendItem("csv" + " - " + Msg.getMsg(Env.getCtx(), "FileCSV"), "csv");
cboType.appendItem("xls" + " - " + Msg.getMsg(Env.getCtx(), "FileXLS"), "xls");
cboType.appendItem("xlsx" + " - " + Msg.getMsg(Env.getCtx(), "FileXLSX"), "xlsx");
cboType.setSelectedItem(li);
Hbox hb = new Hbox();
@ -1218,6 +1222,11 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
m_reportEngine.createHTML(sw, false, m_reportEngine.getPrintFormat().getLanguage(), new HTMLExtension(contextPath, "rp", this.getUuid()), true);
data = sw.getBuffer().toString().getBytes();
}
else if (ext.equals("xlsx"))
{
inputFile = File.createTempFile("Export", ".xlsx");
m_reportEngine.createXLSX(inputFile, m_reportEngine.getPrintFormat().getLanguage());
}
else if (ext.equals("xls"))
{
inputFile = File.createTempFile("Export", ".xls");
@ -1724,4 +1733,61 @@ public class ZkReportViewer extends Window implements EventListener<Event>, ITab
}
}
protected static class XLSXRendererRunnable extends ContextRunnable implements IServerPushCallback
{
private ZkReportViewer viewer;
public XLSXRendererRunnable(ZkReportViewer viewer)
{
super();
this.viewer = viewer;
}
@Override
protected void doRun()
{
try
{
if (!ArchiveEngine.isValid(viewer.m_reportEngine.getLayout()))
log.warning("Cannot archive Document");
String path = System.getProperty("java.io.tmpdir");
String prefix = viewer.makePrefix(viewer.m_reportEngine.getName());
if (log.isLoggable(Level.FINE))
{
log.log(Level.FINE, "Path=" + path + " Prefix=" + prefix);
}
File file = File.createTempFile(prefix, ".xlsx", new File(path));
viewer.m_reportEngine.createXLSX(file, viewer.m_reportEngine.getPrintFormat().getLanguage());
viewer.media = new AMedia(file.getName(), "xlsx",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", file, true);
}
catch (Exception e)
{
if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
throw new RuntimeException(e);
}
finally
{
Desktop desktop = AEnv.getDesktop();
if (desktop != null && desktop.isAlive())
{
new ServerPushTemplate(desktop).executeAsync(this);
}
}
}
@Override
public void updateUI()
{
viewer.labelDrill.setVisible(false);
viewer.comboDrill.setVisible(false);
viewer.onPreviewReport();
}
}
}