PageRenderTime 65ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

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

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