PageRenderTime 67ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/org.adempiere.base/src/org/adempiere/impexp/AbstractExcelExporter.java

https://bitbucket.org/tbayen/idempiere
Java | 502 lines | 346 code | 39 blank | 117 comment | 63 complexity | 8e9a27ad157d0e20ab643ffb8c5b9d30 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /******************************************************************************
  2. * Product: Adempiere ERP & CRM Smart Business Solution *
  3. * Copyright (C) 2008 SC ARHIPAC SERVICE SRL. All Rights Reserved. *
  4. * This program is free software; you can redistribute it and/or modify it *
  5. * under the terms version 2 of the GNU General Public License as published *
  6. * by the Free Software Foundation. This program is distributed in the hope *
  7. * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
  8. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
  9. * See the GNU General Public License for more details. *
  10. * You should have received a copy of the GNU General Public License along *
  11. * with this program; if not, write to the Free Software Foundation, Inc., *
  12. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
  13. *****************************************************************************/
  14. package org.adempiere.impexp;
  15. import java.io.File;
  16. import java.io.FileOutputStream;
  17. import java.io.OutputStream;
  18. import java.sql.Timestamp;
  19. import java.text.DecimalFormat;
  20. import java.text.NumberFormat;
  21. import java.util.HashMap;
  22. import java.util.Properties;
  23. import java.util.logging.Level;
  24. import org.apache.poi.hssf.usermodel.HSSFCell;
  25. import org.apache.poi.hssf.usermodel.HSSFCellStyle;
  26. import org.apache.poi.hssf.usermodel.HSSFDataFormat;
  27. import org.apache.poi.hssf.usermodel.HSSFFont;
  28. import org.apache.poi.hssf.usermodel.HSSFFooter;
  29. import org.apache.poi.hssf.usermodel.HSSFHeader;
  30. import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
  31. import org.apache.poi.hssf.usermodel.HSSFRichTextString;
  32. import org.apache.poi.hssf.usermodel.HSSFRow;
  33. import org.apache.poi.hssf.usermodel.HSSFSheet;
  34. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  35. import org.compiere.util.CLogger;
  36. import org.compiere.util.DisplayType;
  37. import org.compiere.util.Env;
  38. import org.compiere.util.Ini;
  39. import org.compiere.util.Language;
  40. import org.compiere.util.Msg;
  41. import org.compiere.util.Util;
  42. /**
  43. * Abstract MS Excel Format (xls) Exporter
  44. * @author Teo Sarca, SC ARHIPAC SERVICE SRL
  45. */
  46. public abstract class AbstractExcelExporter
  47. {
  48. /**
  49. * Is the current Row a Function Row
  50. * @return true if function row
  51. */
  52. public abstract boolean isFunctionRow();
  53. /**
  54. * Get Columns Count
  55. * @return number of columns
  56. */
  57. public abstract int getColumnCount();
  58. /**
  59. * Get Rows Count
  60. * @return number of rows
  61. */
  62. public abstract int getRowCount();
  63. /**
  64. * Set current row
  65. * @param row row index
  66. */
  67. protected abstract void setCurrentRow(int row);
  68. /**
  69. * @return current row index
  70. */
  71. protected abstract int getCurrentRow();
  72. /**
  73. * Check if column is printed (displayed)
  74. * @param col column index
  75. * @return true if is visible
  76. */
  77. public abstract boolean isColumnPrinted(int col);
  78. /**
  79. * Get column header name
  80. * @param col column index
  81. * @return header name
  82. */
  83. public abstract String getHeaderName(int col);
  84. /**
  85. * Get cell display type (see {@link DisplayType})
  86. * @param row row index
  87. * @param col column index
  88. * @return display type
  89. */
  90. public abstract int getDisplayType(int row, int col);
  91. /**
  92. * Get cell value
  93. * @param row row index
  94. * @param col column index
  95. * @return cell value
  96. */
  97. public abstract Object getValueAt(int row, int col);
  98. /**
  99. * Check if there is a page break on given cell
  100. * @param row row index
  101. * @param col column index
  102. * @return true if there is a page break
  103. */
  104. public abstract boolean isPageBreak(int row, int col);
  105. /** Logger */
  106. protected final CLogger log = CLogger.getCLogger(getClass());
  107. //
  108. private HSSFWorkbook m_workbook;
  109. private HSSFDataFormat m_dataFormat;
  110. private HSSFFont m_fontHeader = null;
  111. private HSSFFont m_fontDefault = null;
  112. private Language m_lang = null;
  113. private int m_sheetCount = 0;
  114. //
  115. private int m_colSplit = 1;
  116. private int m_rowSplit = 1;
  117. private boolean currentRowOnly = false;
  118. /** Styles cache */
  119. private HashMap<String, HSSFCellStyle> m_styles = new HashMap<String, HSSFCellStyle>();
  120. public AbstractExcelExporter() {
  121. m_workbook = new HSSFWorkbook();
  122. m_dataFormat = m_workbook.createDataFormat();
  123. }
  124. protected Properties getCtx() {
  125. return Env.getCtx();
  126. }
  127. protected void setFreezePane(int colSplit, int rowSplit) {
  128. m_colSplit = colSplit;
  129. m_rowSplit = rowSplit;
  130. }
  131. private String fixString(String str)
  132. {
  133. // ms excel doesn't support UTF8 charset
  134. return Util.stripDiacritics(str);
  135. }
  136. protected Language getLanguage() {
  137. if (m_lang == null)
  138. m_lang = Env.getLanguage(getCtx());
  139. return m_lang;
  140. }
  141. private HSSFFont getFont(boolean isHeader) {
  142. HSSFFont font = null;
  143. if (isHeader) {
  144. if (m_fontHeader == null) {
  145. m_fontHeader = m_workbook.createFont();
  146. m_fontHeader.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  147. }
  148. font = m_fontHeader;
  149. }
  150. else if (isFunctionRow()) {
  151. font = m_workbook.createFont();
  152. font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
  153. font.setItalic(true);
  154. }
  155. else {
  156. if (m_fontDefault == null) {
  157. m_fontDefault = m_workbook.createFont();
  158. }
  159. font = m_fontDefault;
  160. }
  161. return font;
  162. }
  163. /**
  164. * Get Excel number format string by given {@link NumberFormat}
  165. * @param df number format
  166. * @param isHighlightNegativeNumbers highlight negative numbers using RED color
  167. * @return number excel format string
  168. */
  169. private String getFormatString(NumberFormat df, boolean isHighlightNegativeNumbers) {
  170. StringBuffer format = new StringBuffer();
  171. int integerDigitsMin = df.getMinimumIntegerDigits();
  172. int integerDigitsMax = df.getMaximumIntegerDigits();
  173. for (int i = 0; i < integerDigitsMax; i++) {
  174. if (i < integerDigitsMin)
  175. format.insert(0, "0");
  176. else
  177. format.insert(0, "#");
  178. if (i == 2) {
  179. format.insert(0, ",");
  180. }
  181. }
  182. int fractionDigitsMin = df.getMinimumFractionDigits();
  183. int fractionDigitsMax = df.getMaximumFractionDigits();
  184. for (int i = 0; i < fractionDigitsMax; i++) {
  185. if (i == 0)
  186. format.append(".");
  187. if (i < fractionDigitsMin)
  188. format.append("0");
  189. else
  190. format.append("#");
  191. }
  192. if (isHighlightNegativeNumbers) {
  193. String f = format.toString();
  194. format = new StringBuffer(f).append(";[RED]-").append(f);
  195. }
  196. //
  197. if (log.isLoggable(Level.FINEST)) log.finest("NumberFormat: "+format);
  198. return format.toString();
  199. }
  200. private HSSFCellStyle getStyle(int row, int col) {
  201. int displayType = getDisplayType(row, col);
  202. String key = "cell-"+col+"-"+displayType;
  203. HSSFCellStyle cs = m_styles.get(key);
  204. if (cs == null) {
  205. boolean isHighlightNegativeNumbers = true;
  206. cs = m_workbook.createCellStyle();
  207. HSSFFont font = getFont(false);
  208. cs.setFont(font);
  209. // Border
  210. cs.setBorderLeft((short)1);
  211. cs.setBorderTop((short)1);
  212. cs.setBorderRight((short)1);
  213. cs.setBorderBottom((short)1);
  214. //
  215. if (DisplayType.isDate(displayType)) {
  216. cs.setDataFormat(m_dataFormat.getFormat(DisplayType.getDateFormat(getLanguage()).toPattern()));
  217. }
  218. else if (DisplayType.isNumeric(displayType)) {
  219. DecimalFormat df = DisplayType.getNumberFormat(displayType, getLanguage());
  220. String format = getFormatString(df, isHighlightNegativeNumbers);
  221. cs.setDataFormat(m_dataFormat.getFormat(format));
  222. }
  223. m_styles.put(key, cs);
  224. }
  225. return cs;
  226. }
  227. private HSSFCellStyle getHeaderStyle(int col)
  228. {
  229. String key = "header-"+col;
  230. HSSFCellStyle cs_header = m_styles.get(key);
  231. if (cs_header == null) {
  232. HSSFFont font_header = getFont(true);
  233. cs_header = m_workbook.createCellStyle();
  234. cs_header.setFont(font_header);
  235. cs_header.setBorderLeft((short)2);
  236. cs_header.setBorderTop((short)2);
  237. cs_header.setBorderRight((short)2);
  238. cs_header.setBorderBottom((short)2);
  239. cs_header.setDataFormat(HSSFDataFormat.getBuiltinFormat("text"));
  240. cs_header.setWrapText(true);
  241. m_styles.put(key, cs_header);
  242. }
  243. return cs_header;
  244. }
  245. private void fixColumnWidth(HSSFSheet sheet, int lastColumnIndex)
  246. {
  247. for (short colnum = 0; colnum < lastColumnIndex; colnum++)
  248. {
  249. sheet.autoSizeColumn(colnum);
  250. }
  251. }
  252. private void closeTableSheet(HSSFSheet prevSheet, String prevSheetName, int colCount)
  253. {
  254. if (prevSheet == null)
  255. return;
  256. //
  257. fixColumnWidth(prevSheet, colCount);
  258. if (m_colSplit >= 0 || m_rowSplit >= 0)
  259. prevSheet.createFreezePane(m_colSplit >= 0 ? m_colSplit : 0, m_rowSplit >= 0 ? m_rowSplit : 0);
  260. if (!Util.isEmpty(prevSheetName, true) && m_sheetCount > 0) {
  261. int prevSheetIndex = m_sheetCount - 1;
  262. try {
  263. m_workbook.setSheetName(prevSheetIndex, prevSheetName);
  264. }
  265. catch (Exception e) {
  266. log.log(Level.WARNING, "Error setting sheet "+prevSheetIndex+" name to "+prevSheetName, e);
  267. }
  268. }
  269. }
  270. private HSSFSheet createTableSheet()
  271. {
  272. HSSFSheet sheet= m_workbook.createSheet();
  273. formatPage(sheet);
  274. createHeaderFooter(sheet);
  275. createTableHeader(sheet);
  276. m_sheetCount++;
  277. //
  278. return sheet;
  279. }
  280. private void createTableHeader(HSSFSheet sheet)
  281. {
  282. int colnumMax = 0;
  283. HSSFRow row = sheet.createRow(0);
  284. // for all columns
  285. int colnum = 0;
  286. for (int col = 0; col < getColumnCount(); col++)
  287. {
  288. if (colnum > colnumMax)
  289. colnumMax = colnum;
  290. //
  291. if (isColumnPrinted(col))
  292. {
  293. HSSFCell cell = row.createCell(colnum);
  294. // header row
  295. HSSFCellStyle style = getHeaderStyle(col);
  296. cell.setCellStyle(style);
  297. String str = fixString(getHeaderName(col));
  298. cell.setCellValue(new HSSFRichTextString(str));
  299. colnum++;
  300. } // printed
  301. } // for all columns
  302. // m_workbook.setRepeatingRowsAndColumns(m_sheetCount, 0, 0, 0, 0);
  303. }
  304. protected void createHeaderFooter(HSSFSheet sheet)
  305. {
  306. // Sheet Header
  307. HSSFHeader header = sheet.getHeader();
  308. header.setRight(HSSFHeader.page()+ " / "+HSSFHeader.numPages());
  309. // Sheet Footer
  310. HSSFFooter footer = sheet.getFooter();
  311. footer.setLeft(Env.getStandardReportFooterTrademarkText());
  312. footer.setCenter(Env.getHeader(getCtx(), 0));
  313. Timestamp now = new Timestamp(System.currentTimeMillis());
  314. footer.setRight(DisplayType.getDateFormat(DisplayType.DateTime, getLanguage()).format(now));
  315. }
  316. protected void formatPage(HSSFSheet sheet)
  317. {
  318. sheet.setFitToPage(true);
  319. // Print Setup
  320. HSSFPrintSetup ps = sheet.getPrintSetup();
  321. ps.setFitWidth((short)1);
  322. ps.setNoColor(true);
  323. ps.setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);
  324. ps.setLandscape(false);
  325. }
  326. protected boolean isCurrentRowOnly()
  327. {
  328. return currentRowOnly;
  329. }
  330. protected void setCurrentRowOnly(boolean b)
  331. {
  332. currentRowOnly = b;
  333. }
  334. /**
  335. * Export to given stream
  336. * @param out
  337. * @throws Exception
  338. */
  339. private void export(OutputStream out)
  340. throws Exception
  341. {
  342. HSSFSheet sheet= createTableSheet();
  343. String sheetName = null;
  344. //
  345. int colnumMax = 0;
  346. int rownum = isCurrentRowOnly() ? getCurrentRow() : 0;
  347. int lastRowNum = isCurrentRowOnly() ? getCurrentRow()+1 : getRowCount();
  348. for (int xls_rownum = 1; rownum < lastRowNum; rownum++, xls_rownum++)
  349. {
  350. if (!isCurrentRowOnly())
  351. setCurrentRow(rownum);
  352. boolean isPageBreak = false;
  353. HSSFRow row = sheet.createRow(xls_rownum);
  354. // for all columns
  355. int colnum = 0;
  356. for (int col = 0; col < getColumnCount(); col++)
  357. {
  358. if (colnum > colnumMax)
  359. colnumMax = colnum;
  360. //
  361. if (isColumnPrinted(col))
  362. {
  363. HSSFCell cell = row.createCell(colnum);
  364. // line row
  365. Object obj = getValueAt(rownum, col);
  366. int displayType = getDisplayType(rownum, col);
  367. if (obj == null)
  368. ;
  369. else if (DisplayType.isDate(displayType)) {
  370. Timestamp value = (Timestamp)obj;
  371. cell.setCellValue(value);
  372. }
  373. else if (DisplayType.isNumeric(displayType)) {
  374. double value = 0;
  375. if (obj instanceof Number) {
  376. value = ((Number)obj).doubleValue();
  377. }
  378. cell.setCellValue(value);
  379. }
  380. else if (DisplayType.YesNo == displayType) {
  381. boolean value = false;
  382. if (obj instanceof Boolean)
  383. value = (Boolean)obj;
  384. else
  385. value = "Y".equals(obj);
  386. cell.setCellValue(new HSSFRichTextString(Msg.getMsg(getLanguage(), value == true ? "Y" : "N")));
  387. }
  388. else {
  389. String value = fixString(obj.toString()); // formatted
  390. cell.setCellValue(new HSSFRichTextString(value));
  391. }
  392. //
  393. HSSFCellStyle style = getStyle(rownum, col);
  394. cell.setCellStyle(style);
  395. // Page break
  396. if (isPageBreak(rownum, col)) {
  397. isPageBreak = true;
  398. sheetName = fixString(cell.getRichStringCellValue().getString());
  399. }
  400. //
  401. colnum++;
  402. } // printed
  403. } // for all columns
  404. //
  405. // Page Break
  406. if (isPageBreak) {
  407. closeTableSheet(sheet, sheetName, colnumMax);
  408. sheet = createTableSheet();
  409. xls_rownum = 0;
  410. isPageBreak = false;
  411. }
  412. } // for all rows
  413. closeTableSheet(sheet, sheetName, colnumMax);
  414. //
  415. if(out!=null)
  416. {
  417. m_workbook.write(out);
  418. out.close();
  419. }
  420. //
  421. // Workbook Info
  422. if (log.isLoggable(Level.FINE)) {
  423. log.fine("Sheets #"+m_sheetCount);
  424. log.fine("Styles used #"+m_styles.size());
  425. }
  426. }
  427. /**
  428. * Export to file
  429. * @param file
  430. * @param language reporting language
  431. * @throws Exception
  432. */
  433. public void export(File file, Language language)
  434. throws Exception
  435. {
  436. export(file, language, true);
  437. }
  438. /**
  439. * Export to file
  440. * @param file
  441. * @param language reporting language
  442. * @param autoOpen auto open file after generated
  443. * @throws Exception
  444. */
  445. public void export(File file, Language language, boolean autoOpen)
  446. throws Exception
  447. {
  448. m_lang = language;
  449. if (file == null)
  450. file = File.createTempFile("Report_", ".xls");
  451. FileOutputStream out = new FileOutputStream(file);
  452. export(out);
  453. if (autoOpen && Ini.isClient())
  454. Env.startBrowser(file.toURI().toString());
  455. }
  456. public void exportToWorkbook(HSSFWorkbook workbook, Language language)
  457. throws Exception
  458. {
  459. m_lang = language;
  460. m_workbook = workbook;
  461. export(null);
  462. }
  463. }