PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/components/src/main/java/org/comsoft/system/excel/ExcelParser.java

https://bitbucket.org/openicar/core
Java | 340 lines | 238 code | 46 blank | 56 comment | 39 complexity | d4792e09c1e402da2a4e8a4d9e7a83b6 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*-
  2. * #%L
  3. * OpenIcar Core Components
  4. * %%
  5. * Copyright (C) 2009 - 2017 COMSOFT, JSC
  6. * %%
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * #L%
  19. */
  20. package org.comsoft.system.excel;
  21. import java.io.ByteArrayOutputStream;
  22. import java.io.FileOutputStream;
  23. import java.io.IOException;
  24. import java.io.InputStream;
  25. import java.io.OutputStream;
  26. import java.text.DecimalFormat;
  27. import java.text.DecimalFormatSymbols;
  28. import java.text.SimpleDateFormat;
  29. import java.util.Date;
  30. import java.util.HashMap;
  31. import java.util.Iterator;
  32. import java.util.LinkedList;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.regex.Pattern;
  36. import org.apache.commons.beanutils.PropertyUtils;
  37. import org.apache.poi.hssf.usermodel.HSSFCell;
  38. import org.apache.poi.hssf.usermodel.HSSFCellStyle;
  39. import org.apache.poi.hssf.usermodel.HSSFDataFormat;
  40. import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
  41. import org.apache.poi.hssf.usermodel.HSSFRichTextString;
  42. import org.apache.poi.hssf.usermodel.HSSFRow;
  43. import org.apache.poi.hssf.usermodel.HSSFSheet;
  44. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  45. import org.apache.poi.poifs.filesystem.POIFSFileSystem;
  46. import org.jboss.seam.Component;
  47. import org.jboss.seam.annotations.Logger;
  48. import org.jboss.seam.annotations.Name;
  49. import org.jboss.seam.log.Log;
  50. @Name("excelParser")
  51. public class ExcelParser {
  52. private static final String DATE_FORMAT_STRING = "dd.MM.yyyy"; //$NON-NLS-1$
  53. @Logger
  54. Log log;
  55. private String result;
  56. public String getResult() {
  57. return result;
  58. }
  59. public void setResult(String result) {
  60. this.result = result;
  61. }
  62. public List<Object[]> parse(InputStream is) throws IOException {
  63. List<Object[]> res = new LinkedList<Object[]>();
  64. HSSFWorkbook wb = null;
  65. log.info("parsing workbook...."); //$NON-NLS-1$
  66. POIFSFileSystem fs = new POIFSFileSystem(is);
  67. wb = new HSSFWorkbook(fs);
  68. log.debug("parsing workbook - done"); //$NON-NLS-1$
  69. HSSFDataFormat formatter = wb.createDataFormat();
  70. //StringBuffer sb = new StringBuffer();
  71. // loop for every worksheet in the workbook
  72. int numOfSheets = wb.getNumberOfSheets();
  73. log.debug("#0 worksheets found", numOfSheets); //$NON-NLS-1$
  74. // Будем вычислять формулы
  75. HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
  76. // ПОКА обрабатываем только первый лист
  77. numOfSheets = Math.min(1, numOfSheets);
  78. for (int i = 0; i < numOfSheets; i++) {
  79. HSSFSheet sheet = wb.getSheetAt(i);
  80. int rowcount = 0;
  81. //sb.append("Sheet " + i);
  82. // loop for every row in each worksheet
  83. for (Iterator rows = sheet.rowIterator(); rows.hasNext();) {
  84. HSSFRow row = (HSSFRow) rows.next();
  85. short c1 = row.getFirstCellNum();
  86. short c2 = row.getLastCellNum();
  87. // loop for every cell in each row
  88. Object[] r = new Object[c2 - c1];
  89. for (short c = c1; c < c2; c++) {
  90. Object obj = null;
  91. HSSFCell cell = row.getCell(c);
  92. if (cell != null) {
  93. obj = getCellValue(evaluator.evaluateInCell(cell), formatter);
  94. }
  95. r[c - c1] = obj;
  96. }
  97. //sb.append(TextFilter.CH13);
  98. //sb.append(TextFilter.CH10);
  99. res.add(r);
  100. rowcount++;
  101. }
  102. log.debug("Sheet #0 : #1 rows", i, rowcount); //$NON-NLS-1$
  103. }
  104. // store the parsed Text
  105. //result = sb.toString().trim();
  106. //log.debug(sb.toString().trim());
  107. return res;
  108. }
  109. private static DecimalFormatSymbols symbols = new DecimalFormatSymbols();
  110. private static SimpleDateFormat dfmt = new SimpleDateFormat(DATE_FORMAT_STRING);
  111. private static DecimalFormat fmt = new DecimalFormat();
  112. static {
  113. symbols.setDecimalSeparator('.');
  114. symbols.setGroupingSeparator(' ');
  115. fmt.setDecimalFormatSymbols(symbols);
  116. fmt.setGroupingUsed(false);
  117. fmt.setMaximumIntegerDigits(20);
  118. }
  119. private static Pattern dateFormatPattern = Pattern.compile("(\\s*[dDдДmMмМyYгГ]{1,4}\\s*[\\.,/-]{0,1}\\s*){3}"); //$NON-NLS-1$
  120. private Object getCellValue(HSSFCell cell, HSSFDataFormat formatter) {
  121. if (cell == null)
  122. return null;
  123. Object result = null;
  124. int cellType = cell.getCellType();
  125. HSSFCellStyle cellStyle = cell.getCellStyle();
  126. short dataFormat = cellStyle.getDataFormat();
  127. String fmt = formatter.getFormat(dataFormat);
  128. log.debug("Cell #0 #1, type = #2, format = #3, fmt = #4", cell.getRowIndex(), cell.getColumnIndex(), cell.getCellType(), dataFormat, fmt); //$NON-NLS-1$
  129. if ("@".equals(fmt) && !(cellType == HSSFCell.CELL_TYPE_BLANK)) { //$NON-NLS-1$
  130. cellType = HSSFCell.CELL_TYPE_STRING;
  131. cell.setCellType(cellType);
  132. }
  133. switch (cellType) {
  134. case HSSFCell.CELL_TYPE_BLANK:
  135. result = ""; //$NON-NLS-1$
  136. break;
  137. case HSSFCell.CELL_TYPE_BOOLEAN:
  138. result = cell.getBooleanCellValue();// ? "1" : "0";
  139. break;
  140. case HSSFCell.CELL_TYPE_ERROR:
  141. result = "ERROR: " + cell.getErrorCellValue(); //$NON-NLS-1$
  142. break;
  143. case HSSFCell.CELL_TYPE_FORMULA:
  144. result = cell.getCellFormula(); // сюда мы по идее не попадаем если перед вызовом заресолвить формулу методом evaluateInCell
  145. break;
  146. case HSSFCell.CELL_TYPE_NUMERIC:
  147. if (dateFormatPattern.matcher(fmt).matches()) {
  148. result = cell.getDateCellValue();
  149. } else {
  150. Double numericCellValue = cell.getNumericCellValue();
  151. boolean dolong = !fmt.contains("."); //$NON-NLS-1$
  152. log.debug("check numeric, format = #0, long ? #1", fmt, dolong); //$NON-NLS-1$
  153. if (dolong) {
  154. result = Long.valueOf(numericCellValue.longValue());
  155. log.debug("long = #0", result); //$NON-NLS-1$
  156. }
  157. else
  158. result = numericCellValue;
  159. }
  160. break;
  161. case HSSFCell.CELL_TYPE_STRING:
  162. result = cell.getStringCellValue();
  163. break;
  164. default:
  165. break;
  166. }
  167. log.debug("Cell #0 #1, value = #2 : #3", cell.getRowIndex(), cell.getColumnIndex(), result == null ? "[null]" : result.toString(), result == null ? "[null]" : result.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  168. return result;
  169. }
  170. public static class TextFilter {
  171. public static final char CH07 = (char) 7;
  172. public static final char CH10 = (char) 10;
  173. public static final char CH13 = (char) 13;
  174. public static final char[] DEFAULT_FORBIDDEN_CHARACTERS = { CH07, CH10,
  175. CH13 };
  176. public static final char SPACE = (char) 32;
  177. public static String filterForbiddenCharacters(String s,
  178. char[] forbidden) {
  179. if (s == null || s.trim().length() <= 0)
  180. return s;
  181. for (int i = 0; i < forbidden.length; i++) {
  182. char c = forbidden[i];
  183. s = s.replace(c, SPACE);
  184. }
  185. return s;
  186. }
  187. }
  188. private Map<String, HSSFCellStyle> cachedCellStyles = new HashMap<String, HSSFCellStyle>();
  189. /**
  190. * Exports data into xls
  191. * @param data - список объектов или массивов
  192. * @param fields - используется когда data - список объектов
  193. * @param headers - заголовки полей
  194. * @param fileName - имя файла для сохранения
  195. * @return byte[] - если имя файла не задано, иначе - null
  196. * @throws Exception
  197. */
  198. public byte[] createXls(List<?> data, List<?> fields, List<?> headers, String fileName) throws Exception {
  199. return createXls(data, fields, headers, fileName, null);
  200. }
  201. /**
  202. * Exports data into xls
  203. * @param data - список объектов или массивов
  204. * @param fields - используется когда data - список объектов
  205. * @param headers - заголовки полей
  206. * @param fileName - имя файла для сохранения
  207. * @param setCellValueHandler - обработчик установки значения ячейки (см. {@link SetCellValueHandler})
  208. * @return byte[] - если имя файла не задано, иначе - null
  209. * @throws Exception
  210. */
  211. public byte[] createXls(List<?> data, List<?> fields, List<?> headers, String fileName, SetCellValueHandler setCellValueHandler) throws Exception {
  212. OutputStream outputStream = null;
  213. if (fileName != null)
  214. outputStream = new FileOutputStream(fileName);
  215. else
  216. outputStream = new ByteArrayOutputStream();
  217. try {
  218. CreateXlsContext context = new CreateXlsContext();
  219. HSSFWorkbook wb = new HSSFWorkbook();
  220. HSSFSheet sheet = wb.createSheet("sheet1"); //$NON-NLS-1$
  221. HSSFRow row = sheet.createRow((short) 0);
  222. HSSFCell cell;
  223. Object val = null;
  224. /*
  225. List<String> headers = new ArrayList<String>();
  226. for (Object f : fields) {
  227. headers.add(f.toString());
  228. }
  229. */
  230. for (int c = 0; c < headers.size(); c++) {
  231. cell = row.createCell(c);
  232. cell.setCellType(HSSFCell.CELL_TYPE_STRING);
  233. cell.setCellValue(headers.get(c).toString());
  234. }
  235. int r = 1;
  236. for (Object datarow : data) {
  237. row = sheet.createRow(r);
  238. for (int c = 0; c < headers.size(); c++) {
  239. String fieldName = null;
  240. if (datarow instanceof Object[]) {
  241. Object[] arrrow = (Object[]) datarow;
  242. val = arrrow[c];
  243. } else {
  244. fieldName = fields.get(c).toString();
  245. val = PropertyUtils.getProperty(datarow, fieldName);
  246. }
  247. cell = row.createCell(c);
  248. if (setCellValueHandler != null) {
  249. setCellValueHandler.setCellValue(context, cell, fieldName, val);
  250. } else {
  251. setCellValue(context, cell, val);
  252. }
  253. }
  254. r++;
  255. }
  256. wb.write(outputStream);
  257. } finally {
  258. outputStream.flush();
  259. outputStream.close();
  260. }
  261. if (fileName != null)
  262. return null;
  263. else
  264. return ((ByteArrayOutputStream) outputStream).toByteArray();
  265. }
  266. private void setCellValue(CreateXlsContext context, HSSFCell cell, Object val) {
  267. if (val == null) {
  268. cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
  269. } else {
  270. if(val instanceof Number){
  271. log.debug("setCellValue for number... colIndex = #0, value = #1", cell.getColumnIndex(), val); //$NON-NLS-1$
  272. Number numValue = (Number)val;
  273. cell.setCellValue(numValue.doubleValue());
  274. cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
  275. }else if(val instanceof Boolean){
  276. Boolean boolValue = (Boolean)val;
  277. cell.setCellValue(boolValue.booleanValue());
  278. }else if(val instanceof Date){
  279. log.debug("setCellValue for date... colIndex = #0, value = #1", cell.getColumnIndex(), val); //$NON-NLS-1$
  280. Date dateValue = (Date)val;
  281. cell.setCellValue(dateValue);
  282. cell.setCellStyle(context.getOrCreateCellStyle(cell, DATE_FORMAT_STRING));
  283. }else if(val instanceof HSSFRichTextString){
  284. cell.setCellValue((HSSFRichTextString)val);
  285. }else{
  286. String strValue = val.toString();
  287. cell.setCellValue(new HSSFRichTextString(strValue));
  288. }
  289. }
  290. }
  291. public static ExcelParser instance() {
  292. return (ExcelParser) Component.getInstance("excelParser"); //$NON-NLS-1$
  293. }
  294. }