0
点赞
收藏
分享

微信扫一扫

ssm框架中用poi根据所选择id导出excel文件

我是小瘦子哟 2022-03-15 阅读 59

一、先在pom.xml中引入poi依赖

<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi</artifactId>
   <version>3.15</version>
</dependency>

关于办公文档插件使用的基本思想:把办公文档的所有元素封装成普通的Java类,程序员通过操作这些类达到操作办公文档的目的。

        文件——HSSFWorkbook

        页——HSSFSheet

        行——HSSFRow

        列——HSSFCell

样式——HSSFCellStyle

二、JSP页面

给导出按钮设置id="exportActivityChooseByIdBtn",添加单击事件,发送同步请求

//给“选择导出”按钮添加单击事件
		$("#exportActivityChooseByIdBtn").click(function () {
		    var checkedIds = $("#tBody input:checked")//父标签tBody下的被选中的input
			if(checkedIds.size()==0){
				alert("请选择要导出的活动");
				return;
			}
			if(window.confirm("您确定要导出这"+checkedIds.size()+"条活动吗?")){
		        var ids=[];
		        $.each(checkedIds,function () {
					ids.push(this.value);//this.value就是被选中的id值
                });
                 window.location.href="workbench/activity/exportChooseActivitysByIds.do?ids="+ids;//注意传参格式
            }
        });

 三、Controller层,调用service,根据id查询活动后使用返回的activitychooseList导出到excel

@RequestMapping("/workbench/activity/exportChooseActivitysByIds.do")
    public void exportChooseActivitysByIds(String[] ids, HttpServletResponse response) throws Exception{
        //调用service返回activitychooseList 
        List<Activity> activitychooseList = activityService.querychooseActivityByIds(ids);
        //用apache的poi创建excel文件,并把activityList写入excel文件中
        //创建HSSFWorkbook对象,对应一个excel文件
        HSSFWorkbook wb = new HSSFWorkbook();
        //使用wb创建HSSFSheet对象,对应wb文件中的一页
        HSSFSheet sheet = wb.createSheet("市场活动列表");//设置页名
        //使用sheet创建HSSFRow对象,对应sheet中的一行
        HSSFRow row = sheet.createRow(0);//索引为0就是第一行
        //使用row创建HSSFCell对象,对应row中的列
        HSSFCell cell = row.createCell(0);//索引为0就是第一列
        //往列里设置值
        cell.setCellValue("ID");
        cell = row.createCell(1);
        cell.setCellValue("所有者");
        cell = row.createCell(2);
        cell.setCellValue("活动名称");
        cell = row.createCell(3);
        cell.setCellValue("开始日期");
        cell = row.createCell(4);
        cell.setCellValue("结束日期");
        cell = row.createCell(5);
        cell.setCellValue("成本");
        cell = row.createCell(6);
        cell.setCellValue("描述");
        cell = row.createCell(7);
        cell.setCellValue("创建时间");
        cell = row.createCell(8);
        cell.setCellValue("创建者");
        cell = row.createCell(9);
        cell.setCellValue("修改时间");
        cell = row.createCell(10);
        cell.setCellValue("修改者");


        //先判断list有没有数据
        if(activitychooseList!=null&&activitychooseList.size()>0){//需要首先判断是否有地址,null就代表没有地址则未创建对象,如果已经创建对象,我们就需要判断该对象中是否有值,这个时候就使用空串来进行判断。
            Activity activity=null;
            for(int i=0;i<activitychooseList.size();i++){
//            Activity activity = activityList.get(i); activity拿到外面定义就不用每次循环都创建,效率更高
                activity = activitychooseList.get(i);
                //每遍历出一个activity,生成一行
                row=sheet.createRow(i+1);
                cell = row.createCell(0);
                cell.setCellValue(activity.getId());
                cell = row.createCell(1);
                cell.setCellValue(activity.getOwner());
                cell = row.createCell(2);
                cell.setCellValue(activity.getName());
                cell = row.createCell(3);
                cell.setCellValue(activity.getStartDate());
                cell = row.createCell(4);
                cell.setCellValue(activity.getEndDate());
                cell = row.createCell(5);
                cell.setCellValue(activity.getCost());
                cell = row.createCell(6);
                cell.setCellValue(activity.getDescription());
                cell = row.createCell(7);
                cell.setCellValue(activity.getCreateTime());
                cell = row.createCell(8);
                cell.setCellValue(activity.getCreateBy());
                cell = row.createCell(9);
                cell.setCellValue(activity.getEditTime());
                cell = row.createCell(10);
                cell.setCellValue(activity.getEditBy());
            }
        }

        //改进前,这里说明了很多繁杂步骤,第六点改进后的可以直接替换下面全部

        OutputStream os = new FileOutputStream("E:\\serverDir\\activityList.xls");
        wb.write(os);//wb.write(os)表示你要吧它生成到哪个文件。从内存写到磁盘。内存访问磁盘效率是很低的,要建立链接,占内存,占cpu,不亚于访问一次数据库
        os.close();
        wb.close();
        //把生成的excel文件下载到客户端
        //设置响应类型 application/octet-stream表示excel文件
        response.setContentType("application/octet-stream;charset=UTF-8");
        //设置响应头  Content-Disposition打开方式 attachment以附件的形式
        response.addHeader("Content-Disposition","attachment;filename=AllactivityList.xls");
        OutputStream out = response.getOutputStream();
        InputStream is = new FileInputStream("E:\\serverDir\\activityList.xls");//从磁盘读到内存,要建立链接,占内存,占cpu,不亚于访问一次数据库
        //缓存区,以一个字节数组为单位读更快
        byte[] buff = new byte[256];
        int len=0; //实际读取个数,等于-1时说明读完了
        while((len=is.read(buff))!=-1){
            out.write(buff,0,len);
        }
        is.close();
        out.flush();//out由response生成的,tomcat会自己关闭,不能自己关闭,不flush可能会数据丢失,因为可能还在缓冲区里
    

    }

记得配置扫描Controller

四、Service和实现类

public interface ActivityService {

    List<Activity> querychooseActivityByIds(String[] ids);

}
@Service("activityService")
public class ActivityServiceImpl implements ActivityService{
    @Autowired
    ActivityMapper activityMapper;
 
    @Override
    public List<Activity> querychooseActivityByIds(String[] ids) {
        return activityMapper.selectchooseActivityByIds(ids);
    }

}
记得配置扫描Service

五、Dao和mapper

public interface ActivityMapper {

    //根据所选id查询活动
    List<Activity> selectchooseActivityByIds(String[] ids);

}
<!--//根据所选ids查询活动-->
    <select id="selectchooseActivityByIds" parameterType="String" resultMap="BaseResultMap">
        select a.id , u1.name as owner, a.name, a.start_date, a.end_date, a.cost, a.description, a.create_time,
        u2.name as create_by, a.edit_time, u3.name as edit_by
        from tbl_activity a
        join tbl_user u1 on a.owner = u1.id
        join tbl_user u2 on a.create_by = u2.id
        left join tbl_user u3 on a.edit_by =u3.id
        where a.id in
        <foreach collection="array" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
        order by a.create_time desc
    </select>
记得配置mapper注解扫描器

六、改进

先写到磁盘再读取磁盘效率太低了,正好workbook对象里有个方法wb.write(out) ,把workbook对象里的数据输出到outputStream对象out里,直接让它输出到浏览器。比起上面效率更高、代码更简洁。


        //设置响应类型 application/octet-stream表示excel文件
        response.setContentType("application/octet-stream;charset=UTF-8");
        //设置响应头  Content-Disposition打开方式 attachment以附件的形式
        response.addHeader("Content-Disposition","attachment;filename=AllactivityList.xls");
        OutputStream out = response.getOutputStream();
        wb.write(out);
        wb.close();
        out.flush();//out由response生成的,tomcat会自己关闭,不能自己关闭,不flush可能会数据丢失

七、总结

1、导出功能不能使用异步请求,这样下载框弹不出来,只能使用同步请求(三种:地址栏、超链接、表单)

2、这里发送请求是用地址栏,特别注意地址栏的传参格式

3、var ids=[]; 在JS中创建数组必须使用这个形式,不能 var ids = new Array();  我就是这里找bug找很久,也不知道为什么,有懂的大哥能说一下吗?

觉得写得不错就点个赞吧😋

举报

相关推荐

0 条评论