PageRenderTime 144ms CodeModel.GetById 37ms RepoModel.GetById 1ms app.codeStats 0ms

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

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