哪位高手指点一二,谢谢!@RequestMapping(value = "/exportperson.do")
public @ResponseBody void writeExcel(PersonView personView,HttpServletRequest request,HttpServletResponse response,@ModelAttribute("currSysUser") SysUser sysUser) {
List<Person> lists = personService.personSearch(personView, sysUser);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String fileName = sdf.format(new Date()); 
fileName = fileName + ".xls" ;
ExtJsonForm ejf = new ExtJsonForm();
try {
OutputStream out = null ; 
out = response.getOutputStream();
WritableWorkbook wwb = Workbook.createWorkbook(out);
WritableSheet ws = wwb.createSheet("人员信息", 0);
ws.setColumnView(4, 22) ; // 设置身份证的列宽
ws.setColumnView(6, 20) ; // 设置籍贯的列宽
ws.setColumnView(9, 15) ; // 设置日期列宽
ws.setColumnView(10, 15) ;
ws.setColumnView(11, 15) ;
ws.setColumnView(12, 15) ;
/**
 * 只能通过API提供的工厂方法来创建Workbook,而不能使用WritableWorkbook的构造函数,
 * 因为类WritableWorkbook的构造函数为protected类型
 * method(1)直接从目标文件中读取WritableWorkbook wwb =
 * Workbook.createWorkbook(new File(targetfile)); method(2)如下实例所示
 * 将WritableWorkbook直接写入到输出流
 */ 
// 创建Excel工作表 指定名称和位置
ws=getWritableSheet(ws,lists);
/*// 写入工作表
  response.setHeader("Content-disposition","attachment;" +
     "filename="+  new String("人员数据".getBytes("GBK"), "ISO_8859_1") +".xls");   
   response.setContentType("application/vnd.ms-excel");  */
   response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");   
   response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");   
   response.setHeader("Pragma", "public"); 
   response.setDateHeader("Expires", (System.currentTimeMillis() + 10000)); 
wwb.write();
wwb.close();
out.close();
} catch (Exception e6) {
ejf.setSuccess(false);
e6.printStackTrace();
}
}

public WritableSheet getWritableSheet( WritableSheet ws,List<Person> lists){
int index = 0; String header[] = {" 姓名","所在单位","所在处室","性别","身份证号码","民族","籍贯",
"个人身份","任职名称","出生日期","任职日期","工作时间","入党(团)时间",
"政治面貌","学历","学位","职称","职务级别","职务类别","享受职务待遇","备注"} ;
// **************往工作表中添加数据*****************
// 1.添加Label对象    Lable(i,j,str) 第一个参数是列,第二个参数是行列,第三个参数是内容
try {
for(int i=0;i<header.length;i++){
Label headerLabel = new Label(i, 0, header[i]);
ws.addCell(headerLabel); 
}
for(int i=0;i<lists.size();i++){ 
Label name = new Label(index,i+1,lists.get(i).getName()) ;
ws.addCell(name);
 // 姓名
index++ ;
Label unitName = new Label(index,i+1,lists.get(i).getUnit().getUnitName()) ;
ws.addCell(unitName); // 所在单位
index++;
if(lists.get(i).getDept()!=null){
Label dept = new Label(index,i+1,lists.get(i).getDept().getUnitName()) ;
if(lists.get(i).getDept().getUnitName()!=null)
ws.addCell(dept); // 所在处室   ---unitName
}
index++ ;
Label sexValue = new Label(index,i+1,lists.get(i).getSexValue()) ;
ws.addCell(sexValue);  // 性别
index++ ;
Label idcard = new Label(index,i+1,lists.get(i).getIdcard()) ;
ws.addCell(idcard);  // 身份证号码
index++;
Label folkCodeValue = new Label(index,i+1,lists.get(i).getFolkCodeValue()) ;
ws.addCell(folkCodeValue);   // 民族
index++ ;
Label nativeCodeValue = new Label(index,i+1,lists.get(i).getNativeCodeValue()) ;
ws.addCell(nativeCodeValue);  // 籍贯
index++;
Label personIdentity = new Label(index,i+1,lists.get(i).getPersonIdentity()) ;
ws.addCell(personIdentity);  // 个人身份
index++ ;
Label dutyTitle = new Label(index,i+1,lists.get(i).getDutyTitle()) ;
ws.addCell(dutyTitle);  // 任职名称
// 添加带有formatting的DateFormat对象
DateFormat df = new DateFormat("yyyy年MM月dd日");
WritableCellFormat wcfDF = new WritableCellFormat(df);
index++ ;
if(lists.get(i).getBirthday()!=null){
DateTime birthday = new DateTime(index, i+1, lists.get(i).getBirthday(), wcfDF);
if(birthday!=null)
ws.addCell(birthday); // 出生日期
}
index++;
if(lists.get(i).getInDutyDate()!=null){
DateTime inDutyDate = new DateTime(index, i+1, lists.get(i).getInDutyDate(), wcfDF);
if(inDutyDate!=null)
ws.addCell(inDutyDate); // 在职日期
}
index++ ;
if(lists.get(i).getWorkDay()!=null){
DateTime workDay = new DateTime(index, i+1, lists.get(i).getWorkDay(), wcfDF);
if(workDay!=null)
ws.addCell(workDay) ;  // 工作时间
}
index++ ;
if(lists.get(i).getKaiserdomDate()!=null){
DateTime kaiserdomDate = new DateTime(index, i+1, lists.get(i).getKaiserdomDate(), wcfDF);
if(kaiserdomDate!=null)
ws.addCell(kaiserdomDate) ;  // 入党(团)时间
}
index++ ;
if(lists.get(i).getKaiserdomCodeValue()!=null){
Label kaiserdomCodeValue = new Label(index,i+1,lists.get(i).getKaiserdomCodeValue()) ;
ws.addCell(kaiserdomCodeValue); // 政治面貌
}
index++ ;
if(lists.get(i).getStudyCodeValue()!=null){
Label studyCodeValue = new Label(index,i+1,lists.get(i).getStudyCodeValue()) ;
ws.addCell(studyCodeValue);  // 学历
}
index++ ;
if(lists.get(i).getDegreeCodeValue()!=null){
Label degreeCodeValue = new Label(index,i+1,lists.get(i).getDegreeCodeValue()) ;
ws.addCell(degreeCodeValue);  // 学位
}
index++ ;
if(lists.get(i).getZhiChengCodeValue()!=null){
Label zhiChengCodeValue = new Label(index,i+1,lists.get(i).getZhiChengCodeValue()) ;
ws.addCell(zhiChengCodeValue);  //职称
}
index++;
if(lists.get(i).getDutyLevelValue()!=null){
Label dutyLevelValue = new Label(index,i+1,lists.get(i).getDutyLevelValue()) ;
ws.addCell(dutyLevelValue);  // 职务级别
}
index++ ;
if(lists.get(i).getPersonSortCodeValue()!=null){
Label personSortCodeValue = new Label(index,i+1,lists.get(i).getPersonSortCodeValue()) ;
ws.addCell(personSortCodeValue);   // 职务类别
}
index++ ;
if(lists.get(i).getEnjoyDealLevelValue()!=null){
Label enjoyDealLevelValue = new Label(index,i+1,lists.get(i).getEnjoyDealLevelValue()) ;
ws.addCell(enjoyDealLevelValue);  // 享受职务待遇
}

index++ ;
if(lists.get(i).getMemo()!=null){
Label memo = new Label(index,i+1,lists.get(i).getMemo()) ;
ws.addCell(memo);   // 备注
}
index = 0;
}
} catch (RowsExceededException e1) {
e1.printStackTrace();
} catch (WriteException e2) {
e2.printStackTrace();
} catch(Exception e3){
e3.printStackTrace() ;
}
return ws;
}

解决方案 »

  1.   

    问题补充:
    Warning:  Maximum number of format records exceeded.  Using default format.
    Warning:  Maximum number of format records exceeded.  Using default format.
    Warning:  Maximum number of format records exceeded.  Using default format.
    Warning:  Maximum number of format records exceeded.  Using default format.
    Warning:  Maximum number of format records exceeded.  Using default format.
    Warning:  Maximum number of format records exceeded.  Using default format.     在服务器后台输出如上的提示,怎么修改它输出的最大记录数?
      

  2.   

    List<Person> lists = personService.personSearch(personView, sysUser);
    一万条分页读取啊,用了hibernate还敢一次性读取。
      

  3.   

    哎。。今天真的是不在状态。。我还以为你说读取Excel中1w数据内存溢出了用楼上的分页读取吧,没有人一次性读1W条的。
      

  4.   

    你的错误原因是Warning:  Maximum number of format records exceeded.  Using default format.这个不是内存溢出。
    DateFormat df = new DateFormat("yyyy年MM月dd日");
    WritableCellFormat wcfDF = new WritableCellFormat(df);
    是你的格式定义的太多了,把这个格式定义放到循环的外面,我以前碰到过,这样就好了,.......
      

  5.   

    1万条记录不算多,10万条应该没什么问题,再多就要增加jvm的启动的缓存了。
      

  6.   

    1 你调整一下JVM内存
    2 你可以启用多个线程生产多个文件输出,最后合并成一个文件
      

  7.   

    (不好意思 上面的问题描述的不是很清楚)
       问题补充:    我实现的功能是:把查询的数据导出,通过response下载到本地,数据必须是一次输出来了吧?数据导出到Excel,只能一次性输出吧?
      ws=getWritableSheet(ws,lists);
                /*// 写入工作表
                  response.setHeader("Content-disposition","attachment;" +
                             "filename="+  new String("人员数据".getBytes("GBK"), "ISO_8859_1") +".xls");   
                           response.setContentType("application/vnd.ms-excel");  */
                           response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");   
                           response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");   
                           response.setHeader("Pragma", "public"); 
                           response.setDateHeader("Expires", (System.currentTimeMillis() + 10000)); 
                wwb.write();
                wwb.close();
                out.close();
      

  8.   

    使用net.sf.jxls.transformer.XLSTransformer导出,模板即可,不用在java代码里定义列,写单元格。public class ExportExcel { /** 模板放置的路径 */
    public static final String TEMPLATE_PATH = "/WEB-INF/excelTemplate/"; /** 导出的Excel临时放置的路径 */
    public static final String EXCEL_TEMP_PATH = "/WEB-INF/excelTemplate/temp/"; // 获得导出文件的模板。
    private static String getTemplateFile(String fileName) {
    // 获得当前应用的全路径,就是"/web"
    String strBasePatch = XXX.getWebPath();
    // 获得模板文件的全路径
    fileName = strBasePatch + TEMPLATE_PATH + fileName;
    return fileName;
    } // 获得导出文件。
    private static String getExportFile(String fileName) {
    // 对特殊字符进行转义,以免出现文件路径错误
    fileName = fileName.replaceAll("[\\\\/*?<>:\"|]", "-");
    // 获得当前应用的全路径,就是"/web"
    String strBasePatch = Toolkit.getWebPath();
    // 根据导出文件名获得临时文件名,这样做为了防止同时请求时出现冲突,然后获得输出的Excel文件的全路径
    fileName = strBasePatch + EXCEL_TEMP_PATH + fileName.replace('.', '_')
    + System.currentTimeMillis() + ".xls";
    return fileName;
    } /**
     *
     * @param request
     * @param response
     * @param templateFileName-模板文件的名称
     * @param exportFileName-要导出的Excel文件的名称
     * @throws Exception
     */
    public static void exportExcel(Map beans, HttpServletResponse response,
    String templateFileName, String exportFileName) {
    templateFileName = getTemplateFile(templateFileName);
    String strPhysicalFileName = getExportFile(exportFileName); XLSTransformer transformer = new XLSTransformer();
    File src = null;
    InputStream pi = null;
    ServletOutputStream sos = null;
    try {
    transformer.transformXLS(templateFileName, beans,
    strPhysicalFileName);
    // 再使用流的方式来读取这个文件,我觉得这个地方应该有一个方法能够直接生成流,但是没有找到。
    response.reset();
    response.setContentType("application/x-msdownload");
    response.setHeader("Content-Disposition", PubFunctions
    .unicodeToGB("attachment;filename=\"" + exportFileName
    + "\""));
    sos = response.getOutputStream();
    src = new File(strPhysicalFileName);
    if (!src.exists() || !src.isFile()) {
    throw new Exception(
    "No Such Source File" + strPhysicalFileName, null);
    }
    if (!src.canRead()) {
    throw new Exception("SourceFile :" + strPhysicalFileName
    + "is unreadable", null);
    }
    pi = new FileInputStream(src);
    byte[] blobbytes = new byte[10240];
    int bytesRead = 0;
    while ((bytesRead = pi.read(blobbytes)) != -1) {
    sos.write(blobbytes, 0, bytesRead);
    }
    sos.flush();
    } catch (Exception e) { } finally {
    try {
    pi.close();
    src.delete();
    } catch (Exception e) {
    }
    }
    }
    需要引入四个jar:
    commons-jexl-1.0.jar\jxl.jar\jxls-core-0.9.5.jar\jxls-reader-0.9.5.jar
      

  9.   

    分页读取然后append到xls里面...理论上大概就是这样了.
      

  10.   

    似乎 M$ Excel 一个 Sheet 只能装最多 65535 条记录。咋办?分页么?如果非得分页不如早点分页,还能减少内存使用。
      

  11.   

    哦!
    导出到Excel中的数据有几万条,导出数据通过后台代码导出的,这跟分页查询有关系?
      

  12.   


    我现在需要实现的功能是:
       前台是用Ext js,用Excel把查询结果从服务器导出到客户端,数据有几万条也有可能几十万条?现在的实现使用上面的代码完成的,效果不理想,有没有更好的办法来解决这个问题?
      

  13.   

    首先 从数据库中读取  还是建议分页处理   毕竟1W条怎么的也得几M大小了吧分页读取数据库中的数据   将个页面生成一个临时的XLS文件   这样分10页 就产生了10个结构相同的 XLS 文件然后  参考
    http://www.iteye.com/topic/240053
    给出的方法  将10个临时的XLS文件合并将合并后的XLS文件提供给前台下载 
    最后可以根据需要把临时文件删除再提一下啊  如果 确定只有1W行 并且以后数据量也不会增加    你不妨修改一下JVM大小  不过修改JVM 不是根本解决问题的方法 但却是最简单的方法
      

  14.   

    我现在需要实现的功能是:
      前台是用Ext js,用Excel把查询结果从服务器导出到客户端,数据有几万条也有可能几十万条?现在的实现使用上面的代码完成的,效果不理想,有没有更好的办法来解决这个问题
    我感觉你可以这样 首先你可以在查询数据库的时候判断一下总条数 一次性指导处5000条(假设) 大于5000的就分次呗 来个循环就可以了第一次创建excel 然后就全部是追加就可以了。这只是我的想法性能上应该也可以优化 可以保持文件流开启 全部导出完在关闭,