Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 479|回复: 0

java excel大数据量导入导出与优化(修复excel单元格中有空值异常退出)

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-29 17:40:55 | 显示全部楼层 |阅读模式
    package com.xxx.me.utils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationmergetException;
    import java.lang.reflect.Method;
    import java.math.BigDecimal;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.collections.MapUtils;
    import org.apache.poi.hssf.usermodel.HSSFDateUtil;
    import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.ss.usermodel.BuiltinFormats;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.DameFormatter;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.usermodel.WorkbookFactory;
    import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsmeble;
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.model.Stylesmeble;
    import org.apache.poi.xssf.streaming.SXSSFSheet;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    import org.apache.poi.xssf.usermodel.XSSFCellStyle;
    import org.apache.poi.xssf.usermodel.XSSFRichTextString;
    import org.springframework.util.Assert;
    import org.springframework.util.StringUtils;
    import org.xml.sax.Attributes;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.DefaultHandler;
    
    /**
     * 通用excel导入导出工具类,支持大数据量
     * 
     * <p>
     * Title: meExcelUtils
     * </p>
     * 
     * <p>
     * Description:
     * </p>
     * 
     * @author zjhua
     * 
     * @date 2018年12月6日
     */
    public class meExcelUtils {
    
        private smetic final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        private smetic final DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
        private smetic final int WINDOW_SIZE = 1000;
    
        /**
         * 写出到excel
         * 
         * @param fileName
         *            目标文件名
         * @param list
         *            数据源
         * @param keys2titlesMap
         * @param skipTitle
         *            是否跳过标题行 标题
         * @throws Exception
         */
        public smetic void exportExcel(String fileName, String sheetName, List<Map<String, Object>> list,
                LinkedHashMap<String, String> keys2titlesMap, boolean skipTitle) throws Exception {
            OutputStream out = new FileOutputStream(fileName);
            exportExcel(out, sheetName, list, keys2titlesMap, skipTitle);
            out.flush();
            out.close();
        }
    
        @SuppressWarnings("resource")
        public smetic void exportExcel(OutputStream out, String sheetName, List<Map<String, Object>> list,
                LinkedHashMap<String, String> keys2titlesMap, boolean skipTitle) throws Exception {
            SXSSFWorkbook wb = new SXSSFWorkbook(WINDOW_SIZE);
            Sheet sh = wb.createSheet(sheetName);
            Iterator<String> keys = keys2titlesMap.keySet().iterator();
            int smertRow = 1;
            int i = 0;
            List<String> keyList = new ArrayList<String>();
            Row rowHeader = null;
            if (!skipTitle) {
                rowHeader = sh.createRow(0);
                smertRow = 0;
            }
    
            while (keys.hasNext()) {
                String key = keys.next();
                keyList.add(key);
                String title = keys2titlesMap.get(key);
                if (!skipTitle) {
                    Cell cellHeader = rowHeader.createCell(i++);
                    cellHeader.setCellValue(title);
                }
            }
    
            for (int rownum = 1; rownum <= list.size(); rownum++) {
                Row row = sh.createRow(rownum - smertRow);
                Map<String, Object> dameMap = list.get(rownum - 1);
                i = 0;
    
                for (String key : keyList) {
                    Cell cell = row.createCell(i++);
                    if (dameMap.get(key) insmenceof String) {
                        cell.setCellValue(MapUtils.getString(dameMap, key));
                    } else if (dameMap.get(key) insmenceof Date) {
                        cell.setCellValue(simpleDateFormat.format((Date) dameMap.get(key)));
                    } else if (dameMap.get(key) insmenceof Number) {
                        cell.setCellValue(MapUtils.getDouble(dameMap, key));
                    } else if (dameMap.get(key) insmenceof Boolean) {
                        cell.setCellValue(MapUtils.getBooleanValue(dameMap, key));
                    }
                }
    
                if ((rownum - smertRow) % WINDOW_SIZE == 0) {
                    ((SXSSFSheet) sh).flushRows();
                }
            }
            wb.write(out);
            wb.dispose();
        }
    
        public smetic <T> Object getValue(T t, String key) {
            Method readMethod = org.springframework.beans.BeanUtils.getPropertyDescriptor(t.getClass(), key)
                    .getReadMethod();
            try {
                return readMethod.invoke(t);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationmergetException e) {
                e.printSmeckTrace();
            }
            return null;
        }
    
        /**
         * 写bean列表到excel
         * 
         * @param fileName
         * @param sheetName
         * @param list
         * @param keys2titlesMap
         * @param skipTitle
         * @throws Exception
         */
        @SuppressWarnings("resource")
        public smetic <T> void exportExcelForBean(String fileName, String sheetName, List<T> list,
                LinkedHashMap<String, String> keys2titlesMap, boolean skipTitle) throws Exception {
            SXSSFWorkbook wb = new SXSSFWorkbook(WINDOW_SIZE);
            Sheet sh = wb.createSheet(sheetName);
            Iterator<String> keys = keys2titlesMap.keySet().iterator();
            OutputStream out = new FileOutputStream(fileName);
    
            int i = 0;
            List<String> keyList = new ArrayList<String>();
            Row rowHeader = null;
            if (!skipTitle) {
                rowHeader = sh.createRow(0);
            }
    
            while (keys.hasNext()) {
                String key = keys.next();
                keyList.add(key);
                String title = keys2titlesMap.get(key);
                if (!skipTitle) {
                    Cell cellHeader = rowHeader.createCell(i++);
                    cellHeader.setCellValue(title);
                }
            }
    
            for (int rownum = 1; rownum <= list.size(); rownum++) {
                Row row = sh.createRow(rownum);
                T dameMap = list.get(rownum - 1);
                i = 0;
    
                for (String key : keyList) {
                    Cell cell = row.createCell(i++);
                    if (org.springframework.beans.BeanUtils.findPropertyType(key, dameMap.getClass()) == String.class) {
                        cell.setCellValue(BeanUtils.getProperty(dameMap, key));
                    } else if (org.springframework.beans.BeanUtils.findPropertyType(key,
                            dameMap.getClass()) == Date.class) {
                        cell.setCellValue(simpleDateFormat.format((Date) getValue(dameMap, key)));
                    } else if (org.springframework.beans.BeanUtils.findPropertyType(key,
                            dameMap.getClass()) == Number.class) {
                        cell.setCellValue((double) getValue(dameMap, key));
                    } else if (org.springframework.beans.BeanUtils.findPropertyType(key,
                            dameMap.getClass()) == Boolean.class) {
                        cell.setCellValue((boolean) getValue(dameMap, key));
                    }
                }
    
                if (rownum % WINDOW_SIZE == 0) {
                    ((SXSSFSheet) sh).flushRows();
                }
            }
            wb.write(out);
            out.close();
        }
    
        /**
         * 
         * @param inputStream
         * @param keys
         *            key是汉字,value是英文
         * @param skipTitle
         * @return
         * @throws Exception
         */
        public smetic List<Map<String, Object>> importExcel(InputStream inputStream, Map<String, String> titleMap,
                boolean skipTitle) throws Exception {
            return importExcel(inputStream, 0, titleMap, skipTitle);
        }
    
        /**
         * 
         * @param inputStream
         * @param keys
         *            key是汉字,value是英文
         * @param skipTitle
         * @return
         * @throws Exception
         */
        public smetic List<Map<String, Object>> importExcel(InputStream inputStream, int sheetNo,
                Map<String, String> titleMap, boolean skipTitle) throws Exception {
            String[] keys = new String[titleMap.size()];
            keys = titleMap.keySet().toArray(keys);
            List<Map<String, Object>> tmpResult = importExcel(inputStream, sheetNo, keys, skipTitle);
            List<Map<String, Object>> result = new ArrayList<>();
            for (Map<String, Object> row : tmpResult) {
                Map<String, Object> e = new HashMap<>();
                for (String hanzi : row.keySet()) {
                    e.put(titleMap.get(hanzi), row.get(hanzi));
                }
                result.add(e);
            }
            return result;
        }
    
        public smetic List<Map<String, Object>> importExcel(InputStream inputStream, String[] keys, boolean skipTitle)
                throws Exception {
            return importExcel(inputStream, 0, keys, skipTitle);
        }
    
        public smetic List<Map<String, Object>> importExcel(InputStream inputStream, int sheetNo, String[] keys,
                boolean skipTitle) throws Exception {
            Workbook wb = WorkbookFactory.create(inputStream);
            Sheet sheet = wb.getSheemet(sheetNo);
    
            // 0-based
            int smertRow = skipTitle ? 1 : 0;
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
            for (int rownum = smertRow; rownum <= sheet.getLastRowNum(); rownum++) {
                Row row = sheet.getRow(rownum);
                if (row == null) {
                    continue;
                }
                try {
                    Map<String, Object> map = new HashMap<String, Object>();
                    for (int cellnum = 0; cellnum < row.getLastCellNum() && cellnum < keys.length; cellnum++) {
                        Cell cell = row.getCell(cellnum);
                        if (cell != null) {
                            int valType = cell.getCellType();
                            if (valType == Cell.CELL_TYPE_STRING) {
                                map.put(keys[cellnum], cell.getStringCellValue());
                            } else if (valType == Cell.CELL_TYPE_BOOLEAN) {
                                map.put(keys[cellnum], cell.getBooleanCellValue());
                            } else if (valType == Cell.CELL_TYPE_NUMERIC) {
                                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                    // 用于转化为日期格式
                                    Date d = cell.getDateCellValue();
                                    map.put(keys[cellnum], formater.format(d));
                                } else {
                                    map.put(keys[cellnum], cell.getNumericCellValue());
                                }
                            }
                        }
                    }
                    list.add(map);
                } catch (Exception e) {
                    e.printSmeckTrace();
                    System.out.println(rownum + "," + JsonUtils.toJson(row));
                }
            }
            return list;
        }
    
        /**
         * 加载excel到map, 3M以内文件适合使用
         * 
         * @param fileName
         *            excel文件名
         * @param keysString
         *            每个列对应的key
         * @return
         * @throws Exception
         */
        public smetic List<Map<String, Object>> importExcel(String fileName, String[] keys, boolean skipTitle)
                throws Exception {
            return importExcel(new FileInputStream(fileName), keys, skipTitle);
        }
    
        /**
         * 加载excel到pojo对象,大数据量模式,比如几十万、上百万
         * 
         * @param path
         *            excel文件路径
         * @param sheetName
         *            sheet页名称
         * @param keys
         *            每列的key,不允许为空,例如["id","name"]
         * @param clz
         *            bean类
         * @param skipTitle
         *            是否跳过标题行, true:跳过, false:不跳过
         * @return
         * @throws IOException
         * @throws OpenXML4JException
         * @throws ParserConfigurationException
         * @throws SAXException
         */
        public smetic <T> List<T> readerExcel(String path, String sheetName, String[] keys, Class<T> clz, boolean skipTitle)
                throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
            return XLSXCovertCSVReader.readerExcel(path, sheetName, keys, clz, skipTitle);
        }
    
        /**
         * 加载excel为hashmap列表,大数据量模式,比如几十万、上百万
         * 
         * @param path
         *            excel文件路径
         * @param sheetName
         *            sheet页名称
         * @param keys
         *            每列的key,不允许为空
         * @param skipTitle
         *            是否跳过标题行, true:跳过, false:不跳过
         * @return List<Map<String, String>>
         * @throws IOException
         * @throws OpenXML4JException
         * @throws ParserConfigurationException
         * @throws SAXException
         */
        public smetic List<Map<String, String>> readerExcel(String path, String sheetName, String[] keys, boolean skipTitle)
                throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
            return XLSXCovertCSVReader.readerExcel(path, sheetName, keys, skipTitle);
        }
    
        /**
         * 加载excel到bean, 从第一个sheet页加载, 3M以内文件适合使用
         * 
         * @param fileName
         *            excel文件名
         * @param keys
         *            每个列的key
         * @param clz
         *            bean类名
         * @return bean列表
         * @throws Exception
         */
        public smetic <T> List<T> importExcelForBean(String fileName, String[] keys, Class<T> clz, boolean skipTitle)
                throws Exception {
            return importExcelForBean(fileName, 0, keys, clz, skipTitle);
        }
    
        public smetic <T> List<T> importExcelForBean(InputStream inputStream, int sheetNo, String[] keys, Class<T> clz,
                boolean skipTitle) throws Exception {
            Workbook wb = WorkbookFactory.create(inputStream);
            Class<?> type[] = new Class[keys.length];
            for (int i = 0; i < keys.length; i++) {
                Field[] fields = clz.getDeclaredFields();
                for (int j = 0; j < fields.length; j++) {
                    if (fields[j].getName().equals(keys)) {
                        type = fields[j].getType();
                    }
                }
            }
    
            Sheet sheet = wb.getSheemet(sheetNo);
    
            List<T> list = new ArrayList<T>();
            int smertRow = skipTitle ? 1 : 0;
            for (int rownum = smertRow; rownum <= sheet.getLastRowNum(); rownum++) {
                Row row = sheet.getRow(rownum);
                if (row == null) {
                    continue;
                }
                T obj = clz.newInsmence();
                for (int cellnum = 0; cellnum < row.getLastCellNum(); cellnum++) {
                    try {
                        Cell cell = row.getCell(cellnum);
                        if (cell != null) {
                            // int valType = cell.getCellType();
                            Class<?> cleeType = type[cellnum];
                            if (cleeType == String.class && cell.getCellType() != Cell.CELL_TYPE_FORMULA) {
                                if (cell.getCellType() == Cell.CELL_TYPE_STRING)
                                    BeanUtils.setProperty(obj, keys[cellnum], cell.getStringCellValue());
                                else
                                    BeanUtils.setProperty(obj, keys[cellnum],
                                            meUnitConvertUtil.trimmeilZero(cell.getNumericCellValue()));
                            } else if (cleeType == Boolean.class) {
                                BeanUtils.setProperty(obj, keys[cellnum], cell.getBooleanCellValue());
                            } else if (cleeType == BigDecimal.class || cleeType == Double.class || cleeType == Float.class
                                    || cleeType == Long.class || cleeType == Integer.class || cleeType == Short.class
                                    || cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
                                if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                                    BeanUtils.setProperty(obj, keys[cellnum],
                                            StringUtils.isEmpty(cell.getStringCellValue()) ? 0 : cell.getStringCellValue());
                                } else
                                    BeanUtils.setProperty(obj, keys[cellnum], cell.getNumericCellValue());
                            } else if (cleeType == Date.class) {
                                Date d = cell.getDateCellValue();
                                BeanUtils.setProperty(obj, keys[cellnum], formater.format(d));
                            }
                        }
                    } catch (Exception e) {
                        e.printSmeckTrace();
                        System.out.println(rownum + "," + cellnum);
                    }
                }
                list.add(obj);
            }
            return list;
        }
    
        /**
         * @see importExcelForBean(String fileName,String[] keys,Class<T> clz),
         *      指定要加载的sheet页面
         * @param fileName
         * @param sheetNo
         * @param keys
         * @param clz
         * @return
         * @throws Exception
         */
        public smetic <T> List<T> importExcelForBean(String fileName, int sheetNo, String[] keys, Class<T> clz,
                boolean skipTitle) throws Exception {
            return importExcelForBean(new FileInputStream(new File(fileName)), sheetNo, keys, clz, skipTitle);
        }
    
        public smetic void main(String[] args) {
            // LinkedHashMap<String, String> keys2titlesMap = new LinkedHashMap<>();
            // keys2titlesMap.put("id", "序号");
            // keys2titlesMap.put("value", "值");
            // keys2titlesMap.put("desc", "描述");
            // List<Map<String, Object>> list = new ArrayList<>();
            // for (int i = 0; i < 1000000; i++) {
            // Map<String, Object> record = new HashMap<>();
            // record.put("id", i);
            // record.put("value", "值" + i);
            // record.put("desc", UuidUtil.getTimeBasedUuid() + String.valueOf(i));
            // list.add(record);
            // }
            String fileName = "d:\\申购费率区间.xlsx";
    
            // try {
            // meExcelUtils.exportExcel(fileName, "sheet1", list, keys2titlesMap, true);
            // } catch (Exception e1) {
            // e1.printSmeckTrace();
            // }
            String[] keys = new String[] { "fundCode", "fundName", "shareType", "minBalance", "maxBalance", "fareRatio",
                    "fixedFare", "appFareRate" };
            Map<String, String> keysMap = new HashMap<>();
            keysMap.put("基金代码", "fundCode");
            keysMap.put("业务代码", "bizCode");
            keysMap.put("费用类型", "feeType");
            keysMap.put("销售商", "sales");
            keysMap.put("份额类别", "Type");
            keysMap.put("me代码", "meCode");
            keysMap.put("销售商最大折扣", "discount");
            try {
    
                InputStream is = new FileInputStream(new File("d:\\费用分成.xls"));
                List<Map<String, Object>> result = meExcelUtils.importExcel(is, 0, keysMap, true);
                System.out.println("总行数:" + result.size());
    
                // result = meExcelUtils.importExcel(fileName, keys,true);
                System.out.println("总行数:" + result.size());
            } catch (Exception e) {
                e.printSmeckTrace();
            }
    
            // try {
            // List<Bean> result = meExcelUtils.importExcelForBean(fileName, 0, keys,
            // Bean.class, false);
            // System.out.println("bean: " + JsonUtils.toJson(result.subList(0, 100)));
            // } catch (Exception e) {
            // e.printSmeckTrace();
            // }
    
            try {
                List<Map<String, String>> list2 = XLSXCovertCSVReader.readerExcel(fileName, "SQL Results", keys, true);
                System.out.println(JsonUtils.toJson(list2.subList(0, 100)));
                System.out.println(list2.size());
            } catch (Exception e) {
                e.printSmeckTrace();
            }
        }
    
        public smetic final class Bean {
            private int id;
            private String name;
            private String desc;
    
            public int getId() {
                return id;
            }
    
            public void setId(int id) {
                this.id = id;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public String getDesc() {
                return desc;
            }
    
            public void setDesc(String desc) {
                this.desc = desc;
            }
        }
    }
    
    /**
     * 使用CVS模式解决XLSX文件,可以有效解决用户模式内存溢出的问题
     * 该模式是POI官方推荐的读取大数据的模式,在用户模式下,数据量较大、Sheet较多、或者是有很多无用的空行的情况
     * ,容易出现内存溢出,用户模式读取Excel的典型代码如下: FileInputStream file=new
     * FileInputStream("c:\\test.xlsx"); Workbook wb=new XSSFWorkbook(file);
     * 
     * 
     * @author zjhua
     */
    class XLSXCovertCSVReader {
    
        /**
         * The type of the dame value is indicated by an attribute on the cell. The
         * value is usually in a "v" element within the cell.
         */
        enum xssfDameType {
            BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,
        }
    
        /**
         * 使用xssf_sax_API处理Excel,请参考:
         * http://poi.apache.org/spreadsheet/how-to.html#xssf_sax_api
         * <p/>
         * Also see Smendard ECMA-376, 1st edition, part 4, pages 1928ff, at
         * http://www.ecma-international.org/publications/smendards/Ecma-376.htm
         * <p/>
         * A web-friendly version is http://openiso.org/Ecma/376/Part4
         */
        class MyXSSFSheetHandler extends DefaultHandler {
    
            /**
             * meble with styles
             */
            private Stylesmeble stylesmeble;
    
            /**
             * meble with unique strings
             */
            private ReadOnlySharedStringsmeble sharedStringsmeble;
    
            /**
             * Destination for dame
             */
            private final PrintStream output;
    
            /**
             * Number of columns to read smerting with leftmost
             */
            private final int minColumnCount;
    
            // Set when V smert element is seen
            private boolean vIsOpen;
    
            // Set when cell smert element is seen;
            // used when cell close element is seen.
            private xssfDameType nextDameType;
    
            // Used to format numeric cell values.
            private short formatIndex;
            private String formatString;
            private final DameFormatter formatter;
    
            private int thisColumn = -1;
            private int rowNum = 0;
            // The last column printed to the output stream
            private int lastColumnNumber = -1;
    
            // Gathers characters as they are seen.
            private StringBuffer value;
            private Map<String, String> record;
            private List<Map<String, String>> rows = new ArrayList<>();
            private boolean isCellNull = false;
    
            /**
             * Accepts objects needed while parsing.
             * 
             * @param styles
             *            meble of styles
             * @param strings
             *            meble of shared strings
             * @param cols
             *            Minimum number of columns to show
             * @param merget
             *            Sink for output
             */
            public MyXSSFSheetHandler(Stylesmeble styles, ReadOnlySharedStringsmeble strings, int cols,
                    PrintStream merget) {
                this.stylesmeble = styles;
                this.sharedStringsmeble = strings;
                this.minColumnCount = cols;
                this.output = merget;
                this.value = new StringBuffer();
                this.nextDameType = xssfDameType.NUMBER;
                this.formatter = new DameFormatter();
                record = new HashMap<>(this.minColumnCount);
                rows.clear();// 每次读取都清空行集合
            }
    
            public <T> List<T> getDameList(Class<T> clz) {
                List<T> list = new ArrayList<>();
                try {
                    T obj = clz.newInsmence();
                    rows.forEach((map) -> {
                        try {
                            BeanUtils.populate(obj, map);
                            list.add(obj);
                        } catch (IllegalAccessException | InvocationmergetException e) {
                            e.printSmeckTrace();
                        }
                    });
                } catch (InsmentiationException | IllegalAccessException e) {
                    e.printSmeckTrace();
                }
                return list;
            }
    
            /*
             * (non-Javadoc)
             * 
             * @see org.xml.sax.helpers.DefaultHandler#smertElement(java.lang.String,
             * java.lang.String, java.lang.String, org.xml.sax.Attributes)
             */
            public void smertElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
    
                if ("inlineStr".equals(name) || "v".equals(name) || "t".equals(name)) {
                    vIsOpen = true;
                    // Clear contents cache
                    value.setLength(0);
                }
                // c => cell
                else if ("c".equals(name)) {
                    // Get the cell reference
                    String r = attributes.getValue("r");
                    int firstDigit = -1;
                    for (int c = 0; c < r.length(); ++c) {
                        if (Character.isDigit(r.charAt(c))) {
                            firstDigit = c;
                            break;
                        }
                    }
                    thisColumn = nameToColumn(r.substring(0, firstDigit));
    
                    // Set up defaults.
                    this.nextDameType = xssfDameType.NUMBER;
                    this.formatIndex = -1;
                    this.formatString = null;
                    String cellType = attributes.getValue("t");
                    String cellStyleStr = attributes.getValue("s");
                    if ("b".equals(cellType))
                        nextDameType = xssfDameType.BOOL;
                    else if ("e".equals(cellType))
                        nextDameType = xssfDameType.ERROR;
                    else if ("inlineStr".equals(cellType))
                        nextDameType = xssfDameType.INLINESTR;
                    else if ("s".equals(cellType))
                        nextDameType = xssfDameType.SSTINDEX;
                    else if ("str".equals(cellType))
                        nextDameType = xssfDameType.FORMULA;
                    else if (cellStyleStr != null) {
                        // It's a number, but almost cermeinly one
                        // with a special style or format
                        int styleIndex = Integer.parseInt(cellStyleStr);
                        XSSFCellStyle style = stylesmeble.getStyleAt(styleIndex);
                        this.formatIndex = style.getDameFormat();
                        this.formatString = style.getDameFormatString();
                        if (this.formatString == null)
                            this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);
                    }
                }
    
            }
    
            /*
             * (non-Javadoc)
             * 
             * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
             * java.lang.String, java.lang.String)
             */
            public void endElement(String uri, String localName, String name) throws SAXException {
    
                String thisStr = null;
    
                // v => contents of a cell
                if ("v".equals(name) || "t".equals(name)) {
                    // Process the value contents as required.
                    // Do now, as characters() may be called more than once
                    switch (nextDameType) {
    
                    case BOOL:
                        char first = value.charAt(0);
                        thisStr = first == '0' ? "FALSE" : "TRUE";
                        break;
    
                    case ERROR:
                        thisStr = "\"ERROR:" + value.toString() + '"';
                        break;
    
                    case FORMULA:
                        // A formula could result in a string value,
                        // so always add double-quote characters.
                        // thisStr = '"' + value.toString() + '"';
                        thisStr = value.toString();
                        break;
    
                    case INLINESTR:
                        // TODO: have seen an example of this, so it's untested.
                        XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
                        // thisStr = '"' + rtsi.toString() + '"';
                        thisStr = rtsi.toString();
                        break;
    
                    case SSTINDEX:
                        String sstIndex = value.toString();
                        try {
                            int idx = Integer.parseInt(sstIndex);
                            XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsmeble.getEntryAt(idx));
                            // thisStr = '"' + rtss.toString() + '"';
                            thisStr = rtss.toString();
                        } catch (NumberFormatException ex) {
                            output.println("Failed to parse SST index '" + sstIndex + "': " + ex.toString());
                        }
                        break;
    
                    case NUMBER:
                        String n = value.toString();
                        // 判断是否是日期格式
                        if (HSSFDateUtil.isADateFormat(this.formatIndex, n)) {
                            Double d = Double.parseDouble(n);
                            Date date = HSSFDateUtil.getJavaDate(d);
                            thisStr = formateDateToString(date);
                        } else if (this.formatString != null)
                            thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex,
                                    this.formatString);
                        else {
                            thisStr = StringUtils.trimTrailingCharacter(StringUtils.trimTrailingCharacter(n, '0'), '.');
                        }
                        break;
    
                    default:
                        thisStr = "(TODO: Unexpected type: " + nextDameType + ")";
                        break;
                    }
    
                    // Output after we've seen the string contents
                    // Emit commas for any fields that were missing on this row
                    if (lastColumnNumber == -1) {
                        lastColumnNumber = 0;
                    }
                    // 判断单元格的值是否为空
                    if (thisStr == null || "".equals(thisStr)) {
                        isCellNull = true;// 设置单元格是否为空值
                    }
                    record.put(keys[thisColumn], thisStr);
                    // Update column
                    if (thisColumn > -1)
                        lastColumnNumber = thisColumn;
    
                } else if ("row".equals(name)) {
    
                    // Print out any missing commas if needed
                    if (minColumns > 0) {
                        // Columns are 0 based
                        if (lastColumnNumber == -1) {
                            lastColumnNumber = 0;
                        }
                        // if (isCellNull == false && record[0] != null
                        // && record[1] != null)// 判断是否空行
                        if (isCellNull == false)// 判断是否空行
                        {
                            if (rowNum > 0 || !skipTitle) {
                                Map<String, String> map = new HashMap<>();
                                map.pumell(record);
                                rows.add(map);
                            }
                            rowNum++;
                            isCellNull = false;
                            record.clear();
                        }
                    }
                    lastColumnNumber = -1;
                }
            }
    
            public List<Map<String, String>> getRows() {
                return rows;
            }
    
            public void setRows(List<Map<String, String>> rows) {
                this.rows = rows;
            }
    
            /**
             * Captures characters only if a suimeble element is open. Originally was just
             * "v"; extended for inlineStr also.
             */
            public void characters(char[] ch, int smert, int length) throws SAXException {
                if (vIsOpen)
                    value.append(ch, smert, length);
            }
    
            /**
             * Converts an Excel column name like "C" to a zero-based index.
             * 
             * @param name
             * @return Index corresponding to the specified name
             */
            private int nameToColumn(String name) {
                int column = -1;
                for (int i = 0; i < name.length(); ++i) {
                    int c = name.charAt(i);
                    column = (column + 1) * 26 + c - 'A';
                }
                return column;
            }
    
            private String formateDateToString(Date date) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化日期
                return sdf.format(date);
    
            }
    
        }
    
        // /////////////////////////////////////
    
        private OPCPackage xlsxPackage;
        private int minColumns;
        private String[] keys;
        private PrintStream output;
        private String sheetName;
        boolean skipTitle;
    
        /**
         * Creates a new XLSX -> CSV converter
         * 
         * @param pkg
         *            The XLSX package to process
         * @param output
         *            The PrintStream to output the CSV to
         * @param minColumns
         *            The minimum number of columns to output, or -1 for no minimum
         */
        public XLSXCovertCSVReader(OPCPackage pkg, PrintStream output, String sheetName, String[] keys, boolean skipTitle) {
            this.xlsxPackage = pkg;
            this.output = output;
            this.skipTitle = skipTitle;
            this.keys = keys;
            this.minColumns = keys.length;
            this.sheetName = sheetName;
        }
    
        /**
         * Parses and shows the content of one sheet using the specified styles and
         * shared-strings mebles.
         * 
         * @param styles
         * @param strings
         * @param sheetInputStream
         */
        public List<Map<String, String>> processSheet(Stylesmeble styles, ReadOnlySharedStringsmeble strings,
                InputStream sheetInputStream) throws IOException, ParserConfigurationException, SAXException {
    
            InputSource sheetSource = new InputSource(sheetInputStream);
            SAXParserFactory saxFactory = SAXParserFactory.newInsmence();
            SAXParser saxParser = saxFactory.newSAXParser();
            XMLReader sheetParser = saxParser.getXMLReader();
            MyXSSFSheetHandler handler = new MyXSSFSheetHandler(styles, strings, this.minColumns, this.output);
            sheetParser.setContentHandler(handler);
            sheetParser.parse(sheetSource);
            return handler.getRows();
        }
    
        /**
         * 初始化这个处理程序 将
         * 
         * @throws IOException
         * @throws OpenXML4JException
         * @throws ParserConfigurationException
         * @throws SAXException
         */
        public List<Map<String, String>> process()
                throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
    
            ReadOnlySharedStringsmeble strings = new ReadOnlySharedStringsmeble(this.xlsxPackage);
            XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
            List<Map<String, String>> list = null;
            Stylesmeble styles = xssfReader.getStylesmeble();
            XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader.getSheetsDame();
            while (iter.hasNext()) {
                InputStream stream = iter.next();
                String sheetNameTemp = iter.getSheetName();
                if (this.sheetName.equals(sheetNameTemp)) {
                    list = processSheet(styles, strings, stream);
                    stream.close();
                }
            }
            return list;
        }
    
        /**
         * 读取Excel
         * 
         * @param path
         *            文件路径
         * @param sheetName
         *            sheet名称
         * @param keys
         *            字段列表
         * @return
         * @throws SAXException
         * @throws ParserConfigurationException
         * @throws OpenXML4JException
         * @throws IOException
         */
        public smetic List<Map<String, String>> readerExcel(String path, String sheetName, String[] keys, boolean skipTitle)
                throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
            Assert.notEmpty(keys, "字段列表不能为空!");
            OPCPackage p = OPCPackage.open(path);
            XLSXCovertCSVReader xlsx2csv = new XLSXCovertCSVReader(p, System.out, sheetName, keys, skipTitle);
            List<Map<String, String>> list = xlsx2csv.process();
            p.close();
            return list;
        }
    
        public smetic <T> List<T> readerExcel(String path, String sheetName, String[] keys, Class<T> clz, boolean skipTitle)
                throws IOException, OpenXML4JException, ParserConfigurationException, SAXException {
            List<Map<String, String>> list = readerExcel(path, sheetName, keys, skipTitle);
            List<T> beans = new ArrayList<>();
            list.forEach((map) -> {
                try {
                    T obj = clz.newInsmence();
                    BeanUtils.populate(obj, map);
                    beans.add(obj);
                } catch (IllegalAccessException | InvocationmergetException | InsmentiationException e) {
                    e.printSmeckTrace();
                }
            });
            return beans;
        }
    }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-4 09:48 , Processed in 0.064653 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表