POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解相关的知识,希望对你有一定的参考价值。

http://blog.csdn.net/l081307114/article/details/46009015

http://www.cnblogs.com/dreammyle/p/5458280.html

 

. Office2007与Office Open XML

    在Office 2007之前,Office一直都是以二进制位的方式存储,但这种格式不易被其它软件拿来使用,在各界的压力下,MicroSoft于2005年发布了基于XML的ooxml开放文档标准。ooxml的xml schema强调减少load time,增快parsing speed,将child elements分开存储,而不是multiple attributes一起存,这有点类似于HTML的结构。ooxml 使用XML和ZIP技术结合进行文件存储,因为XML是一个基于文本的格式,而且ZIP容器支持内容的压缩,所以其一大优势就是可以大大减小文件的尺寸。其它特点这里不再叙述。

2. SAX方式解析XML

    SAX全称Simple API for XML,它是一个接口,也是一个软件包。它是一种XML解析的替代方法,不同于DOM解析XML文档时把所有内容一次性加载到内存中的方式,它逐行扫描文档,一边扫描,一边解析。所以那些只需要单遍读取内容的应用程序就可以从SAX解析中受益,这对大型文档的解析是个巨大优势。另外,SAX “推" 模型可用于广播环境,能够同时注册多个ContentHandler,并行接收事件,而不是在一个管道中一个接一个地进行处理。一些支持 SAX 的语法分析器包括 Xerces,Apache parser(以前的 IBM 语法分析器)、MSXML(Microsoft 语法分析器)和 XDK(Oracle 语法分析器)。这些语法分析器是最灵活的,因为它们还支持 DOM。

3. POI以SAX解析excel2007文件

   所需jar包:poi-3.10-FINAL-20140208.jar,poi-ooxml-3.10-FINAL-20140208.jar, poi-ooxml-schemas-3.10-FINAL-20140208.jar

   辅助工具:Open XML SDK 2.5

   原始文件:book1.xlsx

   技术分享

   SDK展示:注意其中第四行只有三个cell元素,第五行只有两个cell元素,而这种空单元格的处理正是我们所要注意的

技术分享

   程序源码:

  

[java] view plain copy
 
  1. package test;  
  2.   
  3. import java.io.BufferedWriter;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.OutputStreamWriter;  
  8. import java.sql.SQLException;  
  9. import java.util.ArrayList;  
  10. import java.util.Iterator;  
  11. import java.util.List;  
  12.   
  13. import org.apache.poi.openxml4j.opc.OPCPackage;  
  14. import org.apache.poi.ss.usermodel.BuiltinFormats;  
  15. import org.apache.poi.ss.usermodel.DataFormatter;  
  16. import org.apache.poi.xssf.eventusermodel.XSSFReader;  
  17. import org.apache.poi.xssf.model.SharedStringsTable;  
  18. import org.apache.poi.xssf.model.StylesTable;  
  19. import org.apache.poi.xssf.usermodel.XSSFCellStyle;  
  20. import org.apache.poi.xssf.usermodel.XSSFRichTextString;  
  21. import org.xml.sax.Attributes;  
  22. import org.xml.sax.ContentHandler;  
  23. import org.xml.sax.InputSource;  
  24. import org.xml.sax.SAXException;  
  25. import org.xml.sax.XMLReader;  
  26. import org.xml.sax.helpers.DefaultHandler;  
  27. import org.xml.sax.helpers.XMLReaderFactory;  
  28.   
  29. public class ExampleEventUserModel {  
  30.       
  31.     private static StylesTable stylesTable;  
  32.       
  33.     /** 
  34.      * 处理一个sheet 
  35.      * @param filename 
  36.      * @throws Exception 
  37.      */  
  38.     public void processOneSheet(String filename) throws Exception {  
  39.           
  40.         OPCPackage pkg = OPCPackage.open(filename);  
  41.         XSSFReader r = new XSSFReader( pkg );  
  42.         stylesTable = r.getStylesTable();   
  43.         SharedStringsTable sst = r.getSharedStringsTable();  
  44.   
  45.         XMLReader parser = fetchSheetParser(sst);  
  46.   
  47.         // Seems to either be rId# or rSheet#  
  48.         InputStream sheet2 = r.getSheet("rId1");  
  49.         InputSource sheetSource = new InputSource(sheet2);  
  50.         parser.parse(sheetSource);  
  51.         sheet2.close();  
  52.     }  
  53.   
  54.     /** 
  55.      * 处理所有sheet 
  56.      * @param filename 
  57.      * @throws Exception 
  58.      */  
  59.     public void processAllSheets(String filename) throws Exception {  
  60.           
  61.         OPCPackage pkg = OPCPackage.open(filename);  
  62.         XSSFReader r = new XSSFReader( pkg );  
  63.         SharedStringsTable sst = r.getSharedStringsTable();  
  64.           
  65.         XMLReader parser = fetchSheetParser(sst);  
  66.   
  67.         Iterator<InputStream> sheets = r.getSheetsData();  
  68.         while(sheets.hasNext()) {  
  69.             System.out.println("Processing new sheet:\\n");  
  70.             InputStream sheet = sheets.next();  
  71.             InputSource sheetSource = new InputSource(sheet);  
  72.             parser.parse(sheetSource);  
  73.             sheet.close();  
  74.             System.out.println("");  
  75.         }  
  76.     }  
  77.   
  78.     /** 
  79.      * 获取解析器 
  80.      * @param sst 
  81.      * @return 
  82.      * @throws SAXException 
  83.      */  
  84.     public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {  
  85.         XMLReader parser =  
  86.             XMLReaderFactory.createXMLReader(  
  87.                     "org.apache.xerces.parsers.SAXParser"  
  88.             );  
  89.         ContentHandler handler = new SheetHandler(sst);  
  90.         parser.setContentHandler(handler);  
  91.         return parser;  
  92.     }  
  93.   
  94.     /**  
  95.      * 自定义解析处理器 
  96.      * See org.xml.sax.helpers.DefaultHandler javadocs  
  97.      */  
  98.     private static class SheetHandler extends DefaultHandler {  
  99.           
  100.         private SharedStringsTable sst;  
  101.         private String lastContents;  
  102.         private boolean nextIsString;  
  103.           
  104.         private List<String> rowlist = new ArrayList<String>();   
  105.         private int curRow = 0;   
  106.         private int curCol = 0;  
  107.           
  108.         //定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等  
  109.         private String preRef = null, ref = null;  
  110.         //定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格  
  111.         private String maxRef = null;  
  112.           
  113.         private CellDataType nextDataType = CellDataType.SSTINDEX;   
  114.         private final DataFormatter formatter = new DataFormatter();   
  115.         private short formatIndex;   
  116.         private String formatString;   
  117.           
  118.         //用一个enum表示单元格可能的数据类型  
  119.         enum CellDataType{   
  120.             BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL   
  121.         }  
  122.           
  123.         private SheetHandler(SharedStringsTable sst) {  
  124.             this.sst = sst;  
  125.         }  
  126.           
  127.         /** 
  128.          * 解析一个element的开始时触发事件 
  129.          */  
  130.         public void startElement(String uri, String localName, String name,  
  131.                 Attributes attributes) throws SAXException {  
  132.               
  133.             // c => cell  
  134.             if(name.equals("c")) {  
  135.                 //前一个单元格的位置  
  136.                 if(preRef == null){  
  137.                     preRef = attributes.getValue("r");  
  138.                 }else{  
  139.                     preRef = ref;  
  140.                 }  
  141.                 //当前单元格的位置  
  142.                 ref = attributes.getValue("r");  
  143.                   
  144.                 this.setNextDataType(attributes);   
  145.                   
  146.                 // Figure out if the value is an index in the SST  
  147.                 String cellType = attributes.getValue("t");  
  148.                 if(cellType != null && cellType.equals("s")) {  
  149.                     nextIsString = true;  
  150.                 } else {  
  151.                     nextIsString = false;  
  152.                 }  
  153.                   
  154.             }  
  155.             // Clear contents cache  
  156.             lastContents = "";  
  157.         }  
  158.           
  159.         /** 
  160.          * 根据element属性设置数据类型 
  161.          * @param attributes 
  162.          */  
  163.         public void setNextDataType(Attributes attributes){   
  164.   
  165.             nextDataType = CellDataType.NUMBER;   
  166.             formatIndex = -1;   
  167.             formatString = null;   
  168.             String cellType = attributes.getValue("t");   
  169.             String cellStyleStr = attributes.getValue("s");   
  170.             if ("b".equals(cellType)){   
  171.                 nextDataType = CellDataType.BOOL;  
  172.             }else if ("e".equals(cellType)){   
  173.                 nextDataType = CellDataType.ERROR;   
  174.             }else if ("inlineStr".equals(cellType)){   
  175.                 nextDataType = CellDataType.INLINESTR;   
  176.             }else if ("s".equals(cellType)){   
  177.                 nextDataType = CellDataType.SSTINDEX;   
  178.             }else if ("str".equals(cellType)){   
  179.                 nextDataType = CellDataType.FORMULA;   
  180.             }  
  181.             if (cellStyleStr != null){   
  182.                 int styleIndex = Integer.parseInt(cellStyleStr);   
  183.                 XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);   
  184.                 formatIndex = style.getDataFormat();   
  185.                 formatString = style.getDataFormatString();   
  186.                 if ("m/d/yy" == formatString){   
  187.                     nextDataType = CellDataType.DATE;   
  188.                     //full format is "yyyy-MM-dd hh:mm:ss.SSS";  
  189.                     formatString = "yyyy-MM-dd";  
  190.                 }   
  191.                 if (formatString == null){   
  192.                     nextDataType = CellDataType.NULL;   
  193.                     formatString = BuiltinFormats.getBuiltinFormat(formatIndex);   
  194.                 }   
  195.             }   
  196.         }  
  197.           
  198.         /** 
  199.          * 解析一个element元素结束时触发事件 
  200.          */  
  201.         public void endElement(String uri, String localName, String name)  
  202.                 throws SAXException {  
  203.             // Process the last contents as required.  
  204.             // Do now, as characters() may be called more than once  
  205.             if(nextIsString) {  
  206.                 int idx = Integer.parseInt(lastContents);  
  207.                 lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();  
  208.                 nextIsString = false;  
  209.             }  
  210.   
  211.             // v => contents of a cell  
  212.             // Output after we‘ve seen the string contents  
  213.             if (name.equals("v")) {   
  214.                 String value = this.getDataValue(lastContents.trim(), "");   
  215.                 //补全单元格之间的空单元格  
  216.                 if(!ref.equals(preRef)){  
  217.                     int len = countNullCell(ref, preRef);  
  218.                     for(int i=0;i<len;i++){  
  219.                         rowlist.add(curCol, "");  
  220.                         curCol++;  
  221.                     }  
  222.                 }  
  223.                 rowlist.add(curCol, value);  
  224.                 curCol++;   
  225.             }else {   
  226.                 //如果标签名称为 row,这说明已到行尾,调用 optRows() 方法   
  227.                 if (name.equals("row")) {  
  228.                     String value = "";  
  229.                     //默认第一行为表头,以该行单元格数目为最大数目  
  230.                     if(curRow == 0){  
  231.                         maxRef = ref;  
  232.                     }  
  233.                     //补全一行尾部可能缺失的单元格  
  234.                     if(maxRef != null){  
  235.                         int len = countNullCell(maxRef, ref);  
  236.                         for(int i=0;i<=len;i++){  
  237.                             rowlist.add(curCol, "");  
  238.                             curCol++;  
  239.                         }  
  240.                     }  
  241.                     //拼接一行的数据  
  242.                     for(int i=0;i<rowlist.size();i++){  
  243.                         if(rowlist.get(i).contains(",")){  
  244.                             value += "\\""+rowlist.get(i)+"\\",";  
  245.                         }else{  
  246.                             value += rowlist.get(i)+",";  
  247.                         }  
  248.                     }  
  249.                     //加换行符  
  250.                     value += "\\n";  
  251.                     try {  
  252.                         writer.write(value);  
  253.                     } catch (IOException e) {  
  254.                         e.printStackTrace();  
  255.                     }  
  256.                     curRow++;  
  257.                     //一行的末尾重置一些数据  
  258.                     rowlist.clear();   
  259.                     curCol = 0;   
  260.                     preRef = null;  
  261.                     ref = null;  
  262.                 }   
  263.             }   
  264.         }  
  265.           
  266.         /** 
  267.          * 根据数据类型获取数据 
  268.          * @param value 
  269.          * @param thisStr 
  270.          * @return 
  271.          */  
  272.         public String getDataValue(String value, String thisStr)   
  273.   
  274.         {   
  275.             switch (nextDataType)   
  276.             {   
  277.                 //这几个的顺序不能随便交换,交换了很可能会导致数据错误   
  278.                 case BOOL:   
  279.                 char first = value.charAt(0);   
  280.                 thisStr = first == ‘0‘ ? "FALSE" : "TRUE";   
  281.                 break;   
  282.                 case ERROR:   
  283.                 thisStr = "\\"ERROR:" + value.toString() + ‘"‘;   
  284.                 break;   
  285.                 case FORMULA:   
  286.                 thisStr = ‘"‘ + value.toString() + ‘"‘;   
  287.                 break;   
  288.                 case INLINESTR:   
  289.                 XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());   
  290.                 thisStr = rtsi.toString();   
  291.                 rtsi = null;   
  292.                 break;   
  293.                 case SSTINDEX:   
  294.                 String sstIndex = value.toString();   
  295.                 thisStr = value.toString();   
  296.                 break;   
  297.                 case NUMBER:   
  298.                 if (formatString != null){   
  299.                     thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString).trim();   
  300.                 }else{  
  301.                     thisStr = value;   
  302.                 }   
  303.                 thisStr = thisStr.replace("_", "").trim();   
  304.                 break;   
  305.                 case DATE:   
  306.                     try{  
  307.                         thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);   
  308.                     }catch(NumberFormatException ex){  
  309.                         thisStr = value.toString();  
  310.                     }  
  311.                 thisStr = thisStr.replace(" ", "");  
  312.                 break;   
  313.                 default:   
  314.                 thisStr = "";   
  315.                 break;   
  316.             }   
  317.             return thisStr;   
  318.         }   
  319.   
  320.         /** 
  321.          * 获取element的文本数据 
  322.          */  
  323.         public void characters(char[] ch, int start, int length)  
  324.                 throws SAXException {  
  325.             lastContents += new String(ch, start, length);  
  326.         }  
  327.           
  328.         /** 
  329.          * 计算两个单元格之间的单元格数目(同一行) 
  330.          * @param ref 
  331.          * @param preRef 
  332.          * @return 
  333.          */  
  334.         public int countNullCell(String ref, String preRef){  
  335.             //excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD  
  336.             String xfd = ref.replaceAll("\\\\d+", "");  
  337.             String xfd_1 = preRef.replaceAll("\\\\d+", "");  
  338.               
  339.             xfd = fillChar(xfd, 3, ‘@‘, true);  
  340.             xfd_1 = fillChar(xfd_1, 3, ‘@‘, true);  
  341.               
  342.             char[] letter = xfd.toCharArray();  
  343.             char[] letter_1 = xfd_1.toCharArray();  
  344.             int res = (letter[0]-letter_1[0])*26*26 + (letter[1]-letter_1[1])*26 + (letter[2]-letter_1[2]);  
  345.             return res-1;  
  346.         }  
  347.           
  348.         /** 
  349.          * 字符串的填充 
  350.          * @param str 
  351.          * @param len 
  352.          * @param let 
  353.          * @param isPre 
  354.          * @return 
  355.          */  
  356.         String fillChar(String str, int len, char let, boolean isPre){  
  357.             int len_1 = str.length();  
  358.             if(len_1 <len){  
  359.                 if(isPre){  
  360.                     for(int i=0;i<(len-len_1);i++){  
  361.                         str = let+str;  
  362.                     }  
  363.                 }else{  
  364.                     for(int i=0;i<(len-len_1);i++){  
  365.                         str = str+let;  
  366.                     }  
  367.                 }  
  368.             }  
  369.             return str;  
  370.         }  
  371.     }  
  372.       
  373.     static BufferedWriter writer = null;  
  374.   
  375.     public static void main(String[] args) throws Exception {  
  376.         ExampleEventUserModel example = new ExampleEventUserModel();  
  377.         String str = "Book1";  
  378.         String filename = "D:\\\\"+str+".xlsx ";  
  379.         System.out.println("-- 程序开始 --");  
  380.         long time_1 = System.currentTimeMillis();  
  381.         try{  
  382.             writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\\\"+str+".csv")));  
  383.             example.processOneSheet(filename);  
  384.         }finally{  
  385.             writer.close();  
  386.         }  
  387.         long time_2 = System.currentTimeMillis();  
  388.         System.out.println("-- 程序结束 --");  
  389.         System.out.println("-- 耗时 --"+(time_2 - time_1)+"ms");  
  390.     }  
  391.   
  392.   
  393. }  

 

最后输出结果:

[plain] view plain copy
 
  1. 书目,作者,主题,语言,分类,阅读计划,  
  2. 生活在别处,米兰.昆德拉,人生感悟,英语,哲理,3周,  
  3. 人间词话,王国维,诗词评论,中文,文学,5周,  
  4. 宽容,房龙,,英语,,,  
  5. 深入理解计算机系统,,,,计算机,,  

 

 

 

本文实例主要讲述了Java生成CSV文件的方法,具体实现步骤如下:

1、新建CSVUtils.java文件:

技术分享
package com.saicfc.pmpf.internal.manage.utils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

/**
 * 文件操作
 */
public class CSVUtils {

    /**
     * 生成为CVS文件
     * 
     * @param exportData 源数据List
     * @param map csv文件的列表头map
     * @param outPutPath 文件路径
     * @param fileName 文件名称
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static File createCSVFile(List exportData, LinkedHashMap map, 
            String outPutPath, String fileName) {
        File csvFile = null;
        BufferedWriter csvFileOutputStream = null;
        try {
            File file = new File(outPutPath);
            if (!file.exists()) {
                file.mkdir();
            }
            // 定义文件名格式并创建
            csvFile = File.createTempFile(fileName, ".csv", new File(outPutPath));
            System.out.println("csvFile:" + csvFile);
            // UTF-8使正确读取分隔符","
            csvFileOutputStream = new BufferedWriter(
                    new OutputStreamWriter(
                            new FileOutputStream(csvFile), "UTF-8"),1024);
            System.out.println("csvFileOutputStream:" + csvFileOutputStream);
            // 写入文件头部
            for (Iterator propertyIterator = map.entrySet().iterator(); 
                    propertyIterator.hasNext();) {
                java.util.Map.Entry propertyEntry = 
                        (java.util.Map.Entry) propertyIterator.next();
                csvFileOutputStream.write(
                        "" + (String) propertyEntry.getValue() != null ?
                                (String) propertyEntry.getValue() : "" + "");
                if (propertyIterator.hasNext()) {
                    csvFileOutputStream.write(",");
                }
            }
            csvFileOutputStream.newLine();
            // 写入文件内容
            for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {
                Object row = (Object) iterator.next();
                for (Iterator propertyIterator = map.entrySet().iterator(); 
                        propertyIterator.hasNext();) {
                    java.util.Map.Entry propertyEntry = 
                            (java.util.Map.Entry) propertyIterator.next();
                    csvFileOutputStream.write((String) BeanUtils.getProperty(
                            row, (String) propertyEntry.getKey()));
                    if (propertyIterator.hasNext()) {
                        csvFileOutputStream.write(",");
                    }
                }
                if (iterator.hasNext()) {
                    csvFileOutputStream.newLine();
                }
            }
            csvFileOutputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                csvFileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return csvFile;
    }

    /**
     * 下载文件
     * 
     * @param response
     * @param csvFilePath 文件路径
     * @param fileName 文件名称
     * @throws IOException
     */
    public static void exportFile(HttpServletResponse response, 
            String csvFilePath, String fileName)
            throws IOException {
        response.setContentType("application/csv;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + 
                    URLEncoder.encode(fileName, "UTF-8"));

        InputStream in = null;
        try {
            in = new FileInputStream(csvFilePath);
            int len = 0;
            byte[] buffer = new byte[1024];
            response.setCharacterEncoding("UTF-8");
            OutputStream out = response.getOutputStream();
            while ((len = in.read(buffer)) > 0) {
                out.write(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF });
                out.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 删除该目录filePath下的所有文件
     * 
     * @param filePath 文件目录路径
     */
    public static void deleteFiles(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isFile()) {
                    files[i].delete();
                }
            }
        }
    }

    /**
     * 删除单个文件
     * 
     * @param filePath 文件目录路径
     * @param fileName 文件名称
     */
    public static void deleteFile(String filePath, String fileName) {
        File file = new File(filePath);
        if (file.exists()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isFile()) {
                    if (files[i].getName().equals(fileName)) {
                        files[i].delete();
                        return;
                    }
                }
            }
        }
    }

    /**
     * 测试数据
     * 
     * @param args
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        List exportData = new ArrayList<Map>();
        Map row1 = new LinkedHashMap<String, String>();
        row1.put("1", "11");
        row1.put("2", "12");
        row1.put("3", "13");
        row1.put("4", "14");
        exportData.add(row1);
        row1 = new LinkedHashMap<String, String>();
        row1.put("1", "21");
        row1.put("2", "22");
        row1.put("3", "23");
        row1.put("4", "24");
        exportData.add(row1);
        LinkedHashMap map = new LinkedHashMap();
        map.put("1", "第一列");
        map.put("2", "第二列");
        map.put("3", "第三列");
        map.put("4", "第四列");

        String path = "c:/export/";
        String fileName = "文件导出";
        File file = CSVUtils.createCSVFile(exportData, map, path, fileName);
        String fileName2 = file.getName();
        System.out.println("文件名称:" + fileName2);
    }
}
技术分享

2、调用createCSVFile方法生成CSV文件

技术分享
  public static void main(String[] args) {
        String name = "银行退款数据";
        List exportData = new ArrayList();
        LinkedHashMap datamMap = null;
        for (Iterator iterator = refundList.iterator(); iterator.hasNext();) {
            HashMap map = (HashMap) iterator.next();
            datamMap = new LinkedHashMap();
            datamMap.put("1", map.get("merOrderId"));
            datamMap.put("2", DateUtil.convertDateToString("yyyyMMdd", 
                    (Date) map.get("orderTime")));
            BigDecimal amount = (BigDecimal) map.get("amount");
            String amountString = amount.divide(new BigDecimal(10)).toPlainString();
            datamMap.put("3", amountString);
            datamMap.put("4", map.get("remark") != null ? map.get("remark") : "");
            exportData.add(datamMap);
        }
        LinkedHashMap map = new LinkedHashMap();
        map.put("1", "订单号");
        map.put("2", "支付日期");
        map.put("3", "退货现金金额(整数金额 单位:分)");
        map.put("4", "退货原因");
        File file = CSVUtils.createCSVFile(exportData, map, filePath, name);// 生成CSV文件
        fileName = file.getName();
        CSVUtils.exportFile(response, filePath + fileName, fileName);// 下载生成的CSV文件
    }
技术分享

本文转自:http://www.jb51.net/article/52724.htm

以上是关于POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解的主要内容,如果未能解决你的问题,请参考以下文章

POI读写大数据量EXCEL

JAVA Apache POI 之sax 解析10万级大数量数据

POI 读大文件日志

使用POI解析Excel时,出现org.xml.sax.SAXParseException: duplicate attribute 'o:relid'的解决办法

解析xlsx文件---Java读取Excel2007

解析xlsx文件---Java读取Excel2007