精华内容
下载资源
问答
  • POI万能导出模板

    千次阅读 2018-06-12 21:35:37
    POI万能导出模板

    一.问题

    最近做公司的考勤报工系统,开发多张考勤报表,每一张报表都有导出Excel需求。

    由于每一张报表导出Excel的字段都不同,每一个张报表都写了一个导出方法,工作量大。

    所以想能不能抽取出一个导出的公共方法。

    二.解决问题

    通过Java的反射机制,取出对象中的对应字段,设置到POI的Cell对象中,导出Excel。

    公共方法:

         /**
         * POI导出公共方法
         * @param obj
         * @param className
         * @param fileName
         * @param excelHeaders
         * @param fields
         * @param response
         * @throws Exception
         */
        public static void publicExport(Object obj, Class className, String fileName, String[] excelHeaders,String[] fields, HttpServletResponse response) throws Exception {
            //导出数据为空,直接返回
            List query = (List)obj;
            if (query.size() == 0) {
                return;
            }
            //获取导出数据的总条数
            int countColumnNum = query.size();
            //创建XSSFWorkbook文件对象
            XSSFWorkbook book = null;
            //管理员导出数据
            book = new XSSFWorkbook();
            //创建一个Name的新表
            XSSFSheet sheet = book.createSheet(fileName);
            // 获取表的第一行
            XSSFRow firstRow = sheet.createRow(0);
            //创建表的第一行的每列的说明
            XSSFCell[] firstCells = new XSSFCell[excelHeaders.length];
            //给表的第一行的每一列赋值
            for (int j = 0; j < excelHeaders.length; j++) {
                firstCells[j] = firstRow.createCell(j);
                firstCells[j].setCellValue(new XSSFRichTextString(excelHeaders[j]));
            }
            //反射从对象中取出方法对象
            List<Method> methodList = new ArrayList<>();
            for(String method : fields){
                methodList.add(className.getMethod("get"+firstUpper(method)));
            }
            //把表的第一列写好后,接下来从表的第二列开始把对应的值写入到文件里
            for (int i = 0; i < countColumnNum; i++) {
                //给execl创建一行
                XSSFRow row = sheet.createRow(i + 1);
                //取出数据
                Object object = query.get(i);
                //循环给列赋值
                for (int column = 0; column < excelHeaders.length; column++) {
                    //确认每一列对应的表的列
                    for(int method = 0;method<methodList.size(); method++){
                        XSSFCell cell = row.createCell(method);
                        cell.setCellValue(methodList.get(method).invoke(object)==null?"":methodList.get(method).invoke(object).toString());
                    }
                }
            }
            //写一个try catch捕捉异常(response获取输出流)
            OutputStream os = null;
            try {
    	    //防止导出的Excel文件名中文乱码
                String filename= new String(fileName.getBytes("utf-8"), "ISO_8859_1");
                response.setHeader("Content-Disposition", "attachment;filename="+filename+".xlsx");
                response.setContentType("application");
                response.setContentType("application/vnd.ms-excel;charset=UTF-8");
                os = response.getOutputStream();
                book.write(os);
            } catch (IOException e) {
                System.out.println("IO流异常");
            } finally {
                try {
                    os.close();
                } catch (IOException e) {
                    System.out.println("关闭IO流异常");
                }
            }
        }
    
        /**
          *将字符串的第一个字母转换成大写
          *
          */
        public static String firstUpper(String string) {
            char[] charArray = string.toCharArray();
            charArray[0] -= 32;
            return String.valueOf(charArray);
        }

    参数说明:

    obj:需要导出的数据集合  
    className:需要导出集合的对象Class  
    fileName: 导出Excel文件名  
    excelHeaders:导出Excel内容头信息  
    fields:需要导出的对应字段  

    展开全文
  • POI导入导出

    2017-10-27 20:58:00
     近期项目中的excel导入导出功能需求频繁的出现,趁此机会,今天笔者对POI的Excel数据的导入导出做一番详解,希望对大家有所帮助。 2.准备工作 ①添加POI依赖 操作包 --> org.apache.poi poi-ooxml ...

    1.场景一

          近期项目中的excel导入导出功能需求频繁的出现,趁此机会,今天笔者对POI的Excel数据的导入导出做一番详解,希望对大家有所帮助。

    2.准备工作

    ①添加POI依赖

    <!-- Excel操作包 -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.14-beta1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml-schemas</artifactId>
      <version>3.14-beta1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.14-beta1</version>
    </dependency>
    以及excel Jar包依赖

    <dependency>
      <groupId>net.sourceforge.jexcelapi</groupId>
      <artifactId>jxl</artifactId>
      <version>2.6.10</version>
    </dependency>
    ②自定义一个字段与属性名的excel注解

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface ExcelColProAnnotation {
        /**
         * 列名
         *
         * @return
         */
        String columnName() default "";
    
        /**
         * 是否唯一
         *
         * @return
         */
        boolean isUnique() default false;
    }

    3.Excel导出

    代码如下:

    @RequestMapping("/export")
    public void export(HttpServletRequest request) throws Exception {
        List<User> list=userService.getUser(2);
        HSSFWorkbook wb = new HSSFWorkbook();
        request.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/x-download");
    
        String fileName = "user.xls";
        fileName = URLEncoder.encode(fileName, "UTF-8");
        resp.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        HSSFSheet sheet = wb.createSheet("会员交易记录");
        sheet.setDefaultRowHeight((short) (2 * 256));
        sheet.setColumnWidth(0, 50 * 160);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 16);
        HSSFRow row = sheet.createRow((int) 0);
        sheet.createRow((int) 1);
        sheet.createRow((int) 2);
        sheet.createRow((int) 3);
        sheet.createRow((int) 4);
        sheet.createRow((int) 5);
    
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("姓名 ");
        cell.setCellStyle(style);
    
        cell = row.createCell(1);
        cell.setCellValue("用户名 ");
        cell.setCellStyle(style);
    
        cell = row.createCell(2);
        cell.setCellStyle(style);
        cell.setCellValue("手机号");
    
        cell = row.createCell(3);
        cell.setCellStyle(style);
        cell.setCellValue("密码");
    
        cell = row.createCell(4);
        cell.setCellStyle(style);
        cell.setCellValue("状态");
    
        for (int i = 0; i < list.size(); i++)
        {
            HSSFRow row1 = sheet.createRow((int) i + 1);
            User vuserOrder = list.get(i);
            row1.createCell(0).setCellValue(vuserOrder.getName());//姓名
            row1.createCell(1).setCellValue(vuserOrder.getLoginname());//用户名
            row1.createCell(2).setCellValue(vuserOrder.getPhone());//手机号
            row1.createCell(3).setCellValue(vuserOrder.getPassword());//密码
            row1.createCell(4).setCellValue(vuserOrder.getStatus());//状态
    
        try
        {
            OutputStream out = resp.getOutputStream();
            wb.write(out);
            out.close();
        }
        catch (IOException e)
        {
            logger.info("=====导出excel异常====");
        }
        catch (Exception e1)
        {
            logger.info("=====导出excel异常====");
        }
    }
    }
    剖析详解:

    ①根据前端属性个数新建excel行数

     HSSFRow row = sheet.createRow((int) 0);
        sheet.createRow((int) 1);
        sheet.createRow((int) 2);
        sheet.createRow((int) 3);
        sheet.createRow((int) 4);
        sheet.createRow((int) 5);
    ②根据前端具体表格进行属性名赋值

     HSSFCell cell = row.createCell(0);
        cell.setCellValue("姓名 ");
        cell.setCellStyle(style);
    
        cell = row.createCell(1);
        cell.setCellValue("用户名 ");
        cell.setCellStyle(style);
    
        cell = row.createCell(2);
        cell.setCellStyle(style);
        cell.setCellValue("手机号");
    
        cell = row.createCell(3);
        cell.setCellStyle(style);
        cell.setCellValue("密码");
    
        cell = row.createCell(4);
        cell.setCellStyle(style);
        cell.setCellValue("状态");
    ③根据对应的属性名赋对应的值,对号入座

    HSSFRow row1 = sheet.createRow((int) i + 1);
            User vuserOrder = list.get(i);
            row1.createCell(0).setCellValue(vuserOrder.getName());//姓名
            row1.createCell(1).setCellValue(vuserOrder.getLoginname());//用户名
            row1.createCell(2).setCellValue(vuserOrder.getPhone());//手机号
            row1.createCell(3).setCellValue(vuserOrder.getPassword());//密码
            row1.createCell(4).setCellValue(vuserOrder.getStatus());//状态

    ④导出并下载

    OutputStream out = resp.getOutputStream();
            wb.write(out);
            out.close();

    效果图:


    4.Excel导入

    待导入excel文件如图:


    ①根据待导入的Excel自定义相应的实体,以Person为例

    public class Person {
        @ExcelColProAnnotation(columnName = "姓名")
        private String name;
        @ExcelColProAnnotation(columnName = "年龄")
        private String age;
        @ExcelColProAnnotation(columnName = "爱好")
        private String hobby;
        @ExcelColProAnnotation(columnName = "成绩")
        private String score;
    
        public String getScore() {
            return score;
        }
    
        public void setScore(String score) {
            this.score = score;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String getHobby() {
            return hobby;
        }
    
        public void setHobby(String hobby) {
            this.hobby = hobby;
        }
    }

    其中引用了Excel的自定义注解,将excel中文的字段对应数据库的属性;注意:这里的所有属性最好都定义为String类型,要不然后期的导入效果会不尽人意的。

    ②PersonMapper

    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.cckj.dao.PersonDao">
    
        <!--添加一个人 OK-->
        <insert id="addPerson" parameterType="com.cckj.bean.Person">
            insert into person (name,age,hobby,score)
            values
            (#{name},#{age},
            #{hobby},
            #{score}
            )
        </insert>
    </mapper>
    这里的字段类型可以不写,如果执意要写一定要跟数据库类型保持一致,有人可能会问,你刚才的Person属性都定义为String,这里又要跟数据库保持一致,不冲突么?放心,我清楚的告诉你,就该这么玩!

    ③数据库Person的id设备自增

    ④excel导入方法

    public class POIExcelUtil {
    
        //格式化器
        private static DecimalFormat integerFormat = new DecimalFormat("0");// 格式化 number String
        private static SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 格式化日期字符串
        private static DecimalFormat decimalFormat = new DecimalFormat("0.00");// 格式化数字
        /**
         * 为表格的特定区域绑定下拉框约束
         *
         * @param list   下拉框约束内容
         * @param region 作用区域,长度为4int数组, region[0]: firstRow, region[1]: lastRow, region[2]: firstCol, region[3]: lastCol
         * @param sheet
         */
        public static void explicitListConstraint(String[] list, int[] region, HSSFSheet sheet) {
    
            if (region.length != 4) {
                throw new IllegalArgumentException("下拉框区域数据必须设置完全");
            }
            //DVConstraint constraint = DVConstraint.createFormulaListConstraint(formulaString);
            CellRangeAddressList cellRegions = new CellRangeAddressList(region[0], region[1], region[2], region[3]);
            DVConstraint constraint = DVConstraint.createExplicitListConstraint(list);
            HSSFDataValidation dataValidation = new HSSFDataValidation(cellRegions, constraint);
            sheet.addValidationData(dataValidation);
        }
    
        /**
         * 为单元格添加注释
         *
         * @param content   注释内容
         * @param region    注释矩形框大小;1*1代表一个单元格; region[0] => width; region[1] => height
         * @param patriarch
         * @param cell
         */
        public static void commentForCell(String content, int[] region, HSSFPatriarch patriarch, Cell cell) {
            int col = cell.getAddress().getColumn();
            int row = cell.getAddress().getRow();
            if (region.length != 2) {
                region = new int[]{1, 1};
            }
            HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) col, row, (short) (col + region[0]), row + region[1]));
            comment.setString(new HSSFRichTextString(content));
            cell.setCellComment(comment);
        }
    
        /**
         * 将图片插入到指定位置,并设定图片所占区域大小,以单元格为单位
         * @param imgPath
         * @param region  图片位置以及大小;
         *                图片左上角所在单元格 => region[0]col; region[1]: row;
         *                图片大小,单位为一个单元格的宽或高 => region[2]: width; region[3]: height
         * @param patriarch
         * @param workbook
         */
        public static void pictureToPosition(String imgPath, int[] region, HSSFPatriarch patriarch, Workbook workbook) {
            try {
                if (region.length != 4){
                    throw new IllegalArgumentException("the region should have 4 items which are col, row, width, height for image");
                }
                ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
                BufferedImage bufferImg = ImageIO.read(new File(imgPath));
                ImageIO.write(bufferImg, FilenameUtils.getExtension(imgPath), byteArrayOut);
                HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) region[0], region[1], (short) (region[0]+region[2]), region[1]+region[3]);
                patriarch.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
                byteArrayOut.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //为合并区域设置边框
        public static void setBorderForRegion(int border, CellRangeAddress region, HSSFSheet sheet, Workbook wb) {
            RegionUtil.setBorderBottom(border, region, sheet, wb);
            RegionUtil.setBorderLeft(border, region, sheet, wb);
            RegionUtil.setBorderRight(border, region, sheet, wb);
            RegionUtil.setBorderTop(border, region, sheet, wb);
        }
    
    
        /**
         * excel行转为List,要求实体的个属性使用@ExcelColProAnnotation注解确定excel列名与实体属性对应关系
         * @param clazz 实体类的class实例
         * @param is    excel文件流
         * @param <T>
         * @return
         * @throws Exception
         */
        public static <T> List<T> readExcel(Class<T> clazz, InputStream is) throws Exception {
            List<T> resultList = new ArrayList<T>();
            Workbook workbook = WorkbookFactory.create(is);
            //默认读取第一页表格,第一行为列名行,其余为数据行
            Sheet sheet = workbook.getSheetAt(0);
            //列名-字段名
            Map<String, String> columnMap = new HashMap<String, String>();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                ExcelColProAnnotation annotation = field.getAnnotation(ExcelColProAnnotation.class);
                if (annotation != null) {
                    if (!columnMap.containsKey(annotation.columnName())) {
                        columnMap.put(annotation.columnName(), field.getName());
                    }
                }
            }
            //临时变量
            T t = null;
            Object value = null;
            Row row = null;
            Cell cell = null;
            for (int i = 1, maxRow = sheet.getLastRowNum(); i <= maxRow; i++) {
                row = sheet.getRow(i);
                if (row == null) {
                    continue;
                }
                t = clazz.newInstance();
                //列,
                for (int j = 0, maxCol = row.getLastCellNum(); j <= maxCol; j++) {
                    cell = row.getCell(j);
                    value = getCellValue(cell);
                    if (value == null || "".equals(value)) {
                        continue;
                    }
                    //获取列名
                    String columnName = sheet.getRow(0).getCell(j).toString();
                    BeanUtils.setProperty(t, columnMap.get(columnName), value);
                }
                resultList.add(t);
            }
            return resultList;
        }
    
        public static Object getCellValue(Cell cell){
            Object value = null;
            if (cell == null) {
                return value;
            }
            switch (cell.getCellType()) {
                case XSSFCell.CELL_TYPE_STRING:
                    value = cell.getStringCellValue();
                    break;
                case XSSFCell.CELL_TYPE_NUMERIC:
                    if ("@".equals(cell.getCellStyle().getDataFormatString())) {
                       value = integerFormat.format(cell.getNumericCellValue());
                    } else if ("General".equals(cell.getCellStyle().getDataFormatString())) {
                        value = decimalFormat.format(cell.getNumericCellValue());
                    } else {
                        value = timeFormat.format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
                    }
                    break;
                case XSSFCell.CELL_TYPE_BOOLEAN:
                    value = cell.getBooleanCellValue();
                    break;
                case XSSFCell.CELL_TYPE_BLANK:
                    value = "";
                    break;
                default:
                    value = cell.toString();
            }
            return value;
        }
    
    }

    ⑤好了,直接看controller

    @RequestMapping("/import")
    public String importExcel(){
    
        String path = "C:/Users/zhangxing/Desktop/hello.xlsx";
        File file = new File(path);
        try {
            InputStream inputStream = new FileInputStream(file);
            try {
                List<Person> list= POIExcelUtil.readExcel(Person.class,inputStream);
                for (Person p :list){
                    personService.addPerson(p);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    
        return success();
        }

    当然,path肯定是前端传过来的参数,这里为了方便测试才写死的!一般地,前端是传文件类型给后台,末尾有正解,耐心看!

    效果图:


    5.实际需求补充:

    ①待导入的Excel中的字段有可能对应数据库中的多张表,那该怎么处理呢?

    1>待导入Excel文件截图


    该表中的字段对应数据库中的两个表,person以及staff,另外staff中的person_id是两表连接的桥梁

    person表


    staff表


    2>自定义接受实体类

    public class Person {
        private int personId;
        @ExcelColProAnnotation(columnName = "姓名")
        private String name;
        @ExcelColProAnnotation(columnName = "年龄")
        private String age;
        @ExcelColProAnnotation(columnName = "爱好")
        private String hobby;
        @ExcelColProAnnotation(columnName = "成绩")
        private String score;
        @ExcelColProAnnotation(columnName = "联系电话")
        private String contactPhone;
    
        public int getPersonId() {
            return personId;
        }
    
        public void setPersonId(int personId) {
            this.personId = personId;
        }
    
        public String getContactPhone() {
            return contactPhone;
        }
    
        public void setContactPhone(String contactPhone) {
            this.contactPhone = contactPhone;
        }
    
        public String getScore() {
            return score;
        }
    
        public void setScore(String score) {
            this.score = score;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public String getHobby() {
            return hobby;
        }
    
        public void setHobby(String hobby) {
            this.hobby = hobby;
        }
    }
    
    切记,这里不要忘了申明personId,后面这个是关键

    3>配置mybatis获取自增主键值


    这样配置了,就可以得到该插入数据的id,测试类

    @Test
    public void test11(){
       Person p = new Person();
       p.setAge("13");
       p.setHobby("听书");
       p.setName("laojia");
       p.setScore("90");
        System.out.println("插入前"+p.getPersonId());
        personService.addPerson(p);
        System.out.println("插入后"+p.getPersonId());
    
    }

    效果:


    好了,既然能够的得到插入数据的id,重头戏在后头

    4>通过调用Excel导入方法得到对应的list,然后解析相应的字段插入到对应的表

    @RequestMapping("/import")
    public String importExcel(){
    
        String path = "C:/Users/zhangxing/Desktop/hello.xlsx";
        File file = new File(path);
        try {
            InputStream inputStream = new FileInputStream(file);
            try {
                List<Person> list= POIExcelUtil.readExcel(Person.class,inputStream);
                for (Person p :list){
                    //personService.addPerson(p);
                    Person person = new Person();
                    Staff staff = new Staff();
                    person.setName(p.getName());
                    person.setScore(p.getScore());
                    person.setAge(p.getAge());
                    person.setName(p.getName());
                    person.setHobby(p.getHobby());
                    personService.addPerson(person);
                    staff.setContactPhone(p.getContactPhone());
                    staff.setPersonId(person.getPersonId());
                    staffService.addStaff(staff);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    
        return success("导入成功");
        }
    只有person真正插入了,得到主键值才能起作用


    如果涉及到更多的表插入,需要理清表与表的连接桥梁,然后在按先后顺序插入;

    访问效果:

    person表


    staff表


    ②上传文件接口入参怎么申明?前端代码怎么把参数传给后台?

    1>前端传给后台的是file类型

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>File upload</title>
    <script type="text/javascript" src="js/jQuery.js"></script>
    </head>
    <body>
    <div id="uploadForm">
    <input id="file" type="file" name="file" value="" />
    <button id="upload" type="button" οnclick="getUpload()">upload</button>
    </div>
    <script type="text/javascript">
            function getUpload(){
            alert("haha");
            alert($('#file')[0].files[0]);
            var formData = new FormData();
            formData.append('file', $('#file')[0].files[0]);
            $.ajax({
            url: 'http://localhost:8080/excel/importStaff',
            type: 'POST',
            dataType:"json",
            cache: false,
            data: formData,
            processData: false,
            contentType: false
            }).done(function(res) {
            alert("成功");
            alert(res.data);
            }).fail(function(res) {
            alert(res);
            });
            }
    </script>
    </body>
    </html>
    2>后台的文件上传接口必须是post请求
    //导入用户表
    @PostMapping("/importStaff")
    public ResultInfo importStaff(@RequestParam("file") MultipartFile file) {
        try {
                List<StaffDTO> list = POIExcelUtil.readExcel(StaffDTO.class, file.getInputStream());
                for (StaffDTO s:list){
                    StaffDTO staff = new StaffDTO();
                    Workshop workshop= new Workshop();
                    staff.setStaffNo(s.getStaffNo());
                    staff.setOrigionId(s.getOrigionId());
                    staff.setStaffName(s.getStaffName());
                    staff.setPositionTitle(s.getPositionTitle());
                    staff.setContactPhone(s.getContactPhone());
                    staff.setContactMail(s.getContactMail());
                    staffService.insertStaff(staff);
    
                    workshop.setStaffId(staff.getId());
                    workshop.setWorkshopName(s.getWorkshopName());
                    workshopService.insert(workshop);
    
                }
            } catch (Exception e) {
                e.printStackTrace();
                return success("导入失败");
            }
       
        return success("导入成功");
    }
    3>待上传的excel


    4>上传结果截图

    展开全文
  • POI入门导出Excel及中文乱码问题

    千次阅读 2019-12-03 11:18:23
    POI入门导出Excel及中文乱码问题 一.导入jar包 注意: poi-ooxml 和poi版本需要一致! 我这里使用的是3.7,之前用过4.1.1里面的一些方法会不同 <!--excel解析poi包 --> <dependency> <groupId>...

    POI入门导出Excel及中文乱码问题

    一.导入jar包

    注意:
    • poi-ooxml 和poi版本需要一致!
    • 我这里使用的是3.7,之前用过4.1.1里面的一些方法会不同
    <!--excel解析poi包 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>3.7</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.7</version>
            </dependency>
    

    二.编写Excel工具类

    创建Excel流程:
    1. 需要新建一个Excel文件(HSSFWorkbook)
    2. 在Excel文件中创建一个工作表(HSSFSheet)
    3. 添加表头行并做简单的样式调整(HSSFRow.)
    4. 在表头行中添加对应的表列(HSSFCell)
    5. 添加表中的内容
    public class ExcelUtil {
    
    	 /**
         * 
         * @param sheetName 工作表名
         * @param title 表头
         * @param values 表内容
         * @param wb Excel表
         * @return
         */
        public static HSSFWorkbook getHSSFWorkbook(String sheetName, String[] title, String[][] values, HSSFWorkbook wb){
            System.out.println(Arrays.toString(title));
            //1.创建一个HSSFWorkbook,对应一个Excel文件
            if (wb==null){
                wb = new HSSFWorkbook();
            }
    
            //2.在wb中添加一个sheet
            HSSFSheet sheet = wb.createSheet();
            wb.setSheetName(0, sheetName);
    
    
            //3.在sheet里面添加第0行
            HSSFRow row = sheet.createRow(0);
            //设置表头居中
            HSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    
    
            //4.声明列对象
            HSSFCell cell = null;
            //添加表头标题
            for (int i = 0; i < title.length; i++) {
    
                //第0行第i列
                cell = row.createCell(i);
    
                //列的样式
                cell.setCellStyle(cellStyle);
                //表中的编码
                cell.setCellValue(HSSFCell.ENCODING_UTF_16);
                //列中的数据
                cell.setCellValue(title[i]);
    
            }
    
            //5.创建内容
            for(int i=0;i<values.length;i++){
                row = sheet.createRow(i + 1);
                for(int j=0;j<values[i].length;j++){
                    //将内容按顺序赋给对应的列对象
                    row.createCell(j).setCellValue(values[i][j]);
                }
            }
    
            return wb;
        }
    }
    

    三.编写Controller层

    @Controller
    public class DownLoadController {
    
        @Autowired
        UserService userService;
    
    
        @RequestMapping("/downLoad")
        public String downLoad(HttpServletResponse response) throws Exception {
    
            //获得数据
            List<User> allUsers = userService.getAllUsers();
            //excel 表头
            String[] title = {"编号","姓名","密码","邮箱"};
            //表名
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH.mm.ss");
            String format = sdf.format(new Date());
            String fileName = "用户信息表"+format+".xls";
            //sheet名
            String sheetName = "用户信息表";
            //表内容
            String[][] count = new String[allUsers.size()][title.length];
            //循环得到表里面的内容
            for (int i = 0; i < allUsers.size(); i++) {
                count[i] = new String[title.length];
                User user = allUsers.get(i);
                count[i][0] = user.getId().toString();
                count[i][1] = user.getName();
                count[i][2] = user.getPassword();
                count[i][3] = user.getEmail();
            }
    
            //创建HSSFWorkbook
            HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook(sheetName, title, count, null);
            
            
            //获取输出流
    
            OutputStream output = response.getOutputStream();
    
            response.reset();
    
            //设置分区中文名
    
    
            //设置响应的编码
            //下面三行是关键代码,处理乱码问题
            response.setContentType("application/x-download");
    
            response.setCharacterEncoding("utf-8");
    
            //设置浏览器响应头对应的Content-disposition ,这样才会在浏览器中显示下载
            //attachment :附件
    
            response.setHeader("Content-disposition", "attachment;filename="+new String(fileName.getBytes("gbk"), "iso8859-1")+".xls");
    
            //wb输出
    
            wb.write(output);
    
            output.close();
            
            return "success";
        }
    }
    

    四.结果

    在这里插入图片描述

    五.中文乱码问题

    1.表头乱码问题:

    在声明列对象时注明编码
    注意:
    要先声明编码,再设置列中的数据,不然表头会全部变成1。在Excel表中(short)1 就等于UTF-8

      //4.声明列对象
            HSSFCell cell = null;
            //添加表头标题
            for (int i = 0; i < title.length; i++) {
    
                //第0行第i列
                cell = row.createCell(i);
                //设置列的样式
                cell.setCellStyle(cellStyle);
                
                //先设置表中的编码
                cell.setCellValue(HSSFCell.ENCODING_UTF_16);
                
                //再设置列中的数据
                cell.setCellValue(title[i]);
    
            }
    

    2.工作表名乱码及内容乱码:

    查看下Demo的编码是否是utf-8,我之前是GBK所以一直是乱码

    3.下载的表名乱码:

    在写入到硬盘中设置响应编码即可解决表名乱码问题

     //设置响应的编码
            //下面三行是关键代码,处理乱码问题
            response.setContentType("application/x-download");
    
            response.setCharacterEncoding("utf-8");
    
            //设置浏览器响应头对应的Content-disposition ,这样才会在浏览器中显示下载
            //attachment :附件
    
            response.setHeader("Content-disposition", "attachment;filename="+new String(fileName.getBytes("gbk"), "iso8859-1")+".xls");
    
    

    按照网上教程写的一个小Demo,有错误的地方欢迎指出!谢谢大家!

    展开全文
  • poi excel导出

    2020-11-27 15:51:44
    -- poi引用 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency>

    先引入依赖

    <!--       poi引用 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.0.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.0.1</version>
            </dependency>
    

    工具类:

        private static ExcelUtils excelUtils;
    
        public ExcelUtils() {
        }
    
        public static ExcelUtils ExcelUtils() {
            if (excelUtils== null) {
                excelUtils= new ExcelUtils();
            }
            return excelUtils;
        }
    
    
        /**
         * 动态赋值单元格样式
         */
        Map<String, HSSFCellStyle> Style = new HashMap<>();
        /**
         * 动态赋值字体样式
         */
        Map<String, Font> fontMap = new HashMap<>();
    
        /**
         * 导出
         *
         * @param list    导出的数据
         * @param headers 导出的表头
         * @param name    文件名称
         * @throws IOException
         */
        private void export(List<Map> list, String[] headers, String name) throws IOException {
            Excel transToExcel = new Excel();
            try {
                //这个东西表示获取根目录
                String path = System.getProperty("user.dir");
                OutputStream os = new FileOutputStream(path + "/" + name + ".xls");
                transToExcel.exporteExcel(name, headers, list, os);
                os.close();
            } catch (FileNotFoundException e) {
                System.out.println("无法找到文件");
            } catch (IOException e) {
                System.out.println("写入文件失败");
            }
        }
    
        /**
         * 导出excel文件
         *
         * @param title    表sheet的名字
         * @param headers  表头
         * @param dataList 正文单元格
         * @param out      输出流
         */
        private void exporteExcel(String title, String[] headers, List<Map> dataList, OutputStream out) {
            HSSFWorkbook workBook = new HSSFWorkbook();
            createSheet(title, headers, dataList, workBook);
            //这里可多次调用生成工作簿
    //        createSheet(title + "2", headers, dataList, workBook);
            try {
                workBook.write(out);
            } catch (IOException e) {
                System.out.println("写入文件失败" + e.getMessage());
            }
        }
    
    
        /**
         * 创建sheet
         *
         * @param title    sheet的名字
         * @param headers  表头
         * @param dataList 正文单元格
         */
        private void createSheet(String title, String[] headers, List<Map> dataList, HSSFWorkbook workBook) {
    
            HSSFSheet sheet = workBook.createSheet(title);
             /**
             *合并单元格,注意要在创建行之前合并,起始单元格不能小于结束单元格
             * 参数1: 起始单元格的行数
             * 参数2:结束单元格的行数
             * 参数3: 起始单元格的列
             * 参数4: 结束单元格的列
             * */
           // sheet .addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
         
            sheet.setDefaultColumnWidth(15);
            //设置表头和普通单元格的格式
            HSSFCellStyle headStyle = setHeaderStyle(workBook);
            HSSFCellStyle bodyStyle = setBodyStyle(workBook);
    
            createHeader(headers, sheet, headStyle);
            createBody(dataList, sheet, bodyStyle, headers);
    
        }
    
        /**
         * 创建正文单元格
         *
         * @param dataList  数据数组
         * @param sheet     表
         * @param bodyStyle 单元格格式
         * @param headers   表头
         */
        private void createBody(List<Map> dataList, HSSFSheet sheet, HSSFCellStyle bodyStyle, String[] headers) {
            //可以设置动态赋值颜色 setBodyStyleMov();
            //当前行
            int sheetRow = 1;
            for (int a = 0; a < dataList.size(); a++) {
                Map map = dataList.get(a);
                HSSFRow row = sheet.createRow(sheetRow);
                for (int j = 0; j < headers.length; j++) {
                    HSSFCell cell = row.createCell(j);
                    HSSFRichTextString textString = null;
                    String val=null;
                    if (map.get(headers[j]) != null) {
                       val = map.get(headers[j]).toString();
                        textString= new HSSFRichTextString(val);
                        // 这里可以给单个字体赋值颜色 textString.applyFont(fontMap.get("1"));
                        // 这里可以给单个单元格赋值不同颜色 cell.setCellStyle(style.get("1"));
                        //给单元格赋值颜色和值
                        cell.setCellStyle(bodyStyle);
                        cell.setCellValue(textString);
                    } else {
                        cell.setCellValue(textString);
                    }
    
    
                }
                sheetRow++;
            }
        }
    
        /**
         * 传入字符返回字母
         * @param a
         * @return
         */
        private static String getLetter(String a) {
            StringBuffer sb = new StringBuffer();
            for(int i = 0;i<a.length();i++){
                char c = a.charAt(i);
                if((c<='z'&&c>='a')||(c<='Z'&&c>='A')){
                    if (sb.length()>0){
                        sb.append(",");
                    }
                    sb.append(c);
                }
            }
            System.out.println(sb.toString());
            return sb.toString();
        }
        /**
         * 创建表头
         *
         * @param headers   表头
         * @param sheet     表
         * @param headStyle 表头格式
         */
        private void createHeader(String[] headers, HSSFSheet sheet, HSSFCellStyle headStyle) {
            HSSFRow row = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(headStyle);
                HSSFRichTextString textString = new HSSFRichTextString(headers[i]);
                cell.setCellValue(textString);
                //只能解决英文、数字列宽自适应,如果该列为中文,会出现列宽不足现象。
                sheet.autoSizeColumn((short) i);
                // 解决自动设置列宽中文失效的问题
                // sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 17 / 10);
    
    
            }
        }
    
    
        /**
         * 设置正文单元格格式动态
         *
         * @param workBook
         * @return
         */
        private void setBodyStyleMov(HSSFWorkbook workBook) {
            //拿到palette颜色板
            HSSFPalette palette = workBook.getCustomPalette();
            //自定义颜色 黄 这里是吧 IndexedColors.YELLOW.getIndex() 替换成 rgb(255,255,0)
            palette.setColorAtIndex(IndexedColors.YELLOW.getIndex(), (byte) 255, (byte) 255, (byte) 0);
            //黄色 吧颜色赋值好存到map之后可以调用
            HSSFCellStyle style = workBook.createCellStyle();
            style.setFillForegroundColor(palette.getColor(IndexedColors.YELLOW.getIndex()).getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            Style.put("1", style);
    
            //这里同理替换颜色
            palette.setColorAtIndex(IndexedColors.GOLD.getIndex(), (byte) 90, (byte) 140, (byte) 55);
            Font font = workBook.createFont();
            font.setBold(true);
            font.setColor(palette.getColor(IndexedColors.GOLD.getIndex()).getIndex());
            fontMap.put("1", font);
    
        }
    
        /**
         * 设置正文单元格格式
         *
         * @param workBook
         * @return
         */
        private HSSFCellStyle setBodyStyle(HSSFWorkbook workBook) {
            HSSFCellStyle style = workBook.createCellStyle();
            //设置背景颜色
            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            //边框颜色和宽度设置
            style.setBorderBottom(BorderStyle.THIN);
            style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框
            style.setBorderLeft(BorderStyle.THIN);
            style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框
            style.setBorderRight(BorderStyle.THIN);
            style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框
            style.setBorderTop(BorderStyle.THIN);
            style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框
            //对齐方式设置
            style.setAlignment(HorizontalAlignment.CENTER);
    //        粗体字设置
            Font font = workBook.createFont();
            font.setFontName("微软雅黑");
            style.setFont(font);
            style.setAlignment(HorizontalAlignment.CENTER);//行居中
            style.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
            return style;
        }
    
        /**
         * 设置表头格式
         *
         * @param workBook
         * @return
         */
        private HSSFCellStyle setHeaderStyle(HSSFWorkbook workBook) {
            HSSFCellStyle style = workBook.createCellStyle();
            //设置背景颜色
            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
    //        边框颜色和宽度设置
            style.setBorderBottom(BorderStyle.THIN);
            style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下边框
            style.setBorderLeft(BorderStyle.THIN);
            style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左边框
            style.setBorderRight(BorderStyle.THIN);
            style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右边框
            style.setBorderTop(BorderStyle.THIN);
            style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上边框
    //        对齐方式设置
            style.setAlignment(HorizontalAlignment.CENTER);
    //        粗体字设置
            Font font = workBook.createFont();
            font.setBold(true);
            font.setFontName("微软雅黑");
            style.setFont(font);
            return style;
        }
    
    
    
    展开全文
  • POI excel导出

    2021-05-27 15:09:55
    POM 依赖 3.10-FINAL 工具类 package com.picc.job.utils; ... ... ...import lombok.extern.slf4j.Slf4j;...import org.apache.poi.hssf.usermodel.*; import org.apache.poi.hssf.util.HSSFColor; import
  • POI模板导出word

    千次阅读 2016-04-17 22:18:27
    java使用poi模板方式完成word导出,亲测可用。
  • poi 简单导出wrod

    2021-07-22 13:29:26
    hutool工具类也有导出word的封装,本来图方便想用它的,但是后来发现导出的文档数字和汉字不是一个字体,也就是一行里面会有不同的字体,hutool只能一段一段的换字体,所以换了poi 先看看效果:这里汉字是宋体,数字...
  • Java POI导入导出excel

    千次阅读 2017-02-07 12:06:18
    博客中翻阅到一篇关于Java 利用POI导入导出excel的好文章,这里转载一下,以后便于用
  • poi 3.8 导出excel 乱码

    2012-06-14 16:30:38
    在weblogic服务器下,用poi3.8导出数据成excel,中文数据全部都是乱码
  • Java POI Excel导出文件名中文乱码

    千次阅读 2016-10-17 12:53:34
    在用POI进行excel表导出时,遇到中文文件名乱码问题,用下面的方法得到了解决。 转载自:https://my.oschina.net/chinamummy29/blog/525639 在导出前对名称根据浏览器做下处理 // 判断浏览器类型,firefox...
  • 使用POI组件导出Excel文件

    千次阅读 2019-12-02 16:53:01
    其中Excel文件是最常见的一种导出格式,Java中可导出Excel的组件有很多种,这儿我详细介绍其中一种——POI POI POI由Apache公司开发,可到Apache官网直接下载POI的压缩包 POI压缩包下载 下载后解压,将我们需要的...
  • Java POI导入导出Excel

    2019-12-31 18:41:30
    本文转载自:...1、异常java.lang.NoClassDefFoundError: org/apache/poi/UnsupportedFileFormatException  解决方法:  使用的poi的相关jar包一定版本一定要相同...
  • poi分页导出

    千次阅读 2018-08-10 11:17:57
    //poi导出 ServletOutputStream out = response.getOutputStream(); //设置文件名字 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String fileName = "excel标题" + sdf.format(new Date()...
  • PS:自行练习poi实现导出Excel数据,没有单独写公共ExcelUtil文件,直接在controller层实现; ok 进入正题! ① 引入POI依赖; <dependency> <groupId>org.apache.poi</groupId> <...
  • poi文本导出为数字

    2019-09-24 14:02:42
    1.需求描述 ...POI导出工具类 import com.platform.park.model.vo.carRecords.ExportOutOfYardVO; import io.swagger.annotations.ApiModelProperty; import org.apache.poi.hssf.usermodel.HSSFCell; ...
  • poi导入导出(导出一个或者多个excel)excel工具类 package com.gosun.order.management.common.utils; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import ...
  • POI导入导出excle

    2019-08-13 16:38:23
    import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; ...
  • 近来还是发现了许多可能是刚入门的童鞋加qq咨询poi导入导出的问题以及问起如何基于ssm框架来实现,很久以前就写过struts+jdbc的poi导入导出,但是还是有诸多童鞋处于懵逼(不得不吐槽一下:“童鞋,你的基础可能需要...
  • Springmvc+poi 实现导入导出excel的controller方法和工具类
  • POI导出Excel

    2019-08-26 19:47:24
    POI导出Excel
  • POI流式导出Excel

    千次阅读 2019-08-23 18:32:48
    一、Excel模板导出,不是数据导出(导出是带着限制条件的空Excel) (PS:工具类在最下面) controller层方法 @GetMapping("/export") @ApiOperation(value = "模板下载", notes = "模板下载") public void...
  • Apache Poi Excel导出

    2013-06-06 17:44:34
    HSSFSheet sheet = workbook.createSheet("排放清单导出"); //*******************************************表头样式*************************************** //生成一个样式(用于单元格) HSSFCellStyle...
  • 一.pom文件 &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;dependency&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; &amp;amp;amp;amp;amp;amp;amp;amp;...org.apache.poi&amp;amp
  • POI3.16导出Excel使用

    千次阅读 2018-09-12 23:36:53
    创建Excel文档工作簿: xlsx版本 // 支持数据量可超过100万行 XSSFWorkbook workBook = new XSSFWorkbook(); ...// 由于版本问题,行数不能...下文的单元格相关的代码均以xlsx版本为例,如需以xls版本导出 一般将前...
  • 关于POI导入导出Excel

    2017-06-10 16:20:24
    2. POI有很多组件组成,其中有用于操作Excel格式文件的HSSF和用于操作Word的HWPF,对于Excel表格的操作,首先需要清楚表格的对象。 HSSFWorkbook Excel的文档对象 、HSSFSheet 表单对象、HSSFRow 行对象、HSSFFont
  • POI 实现导出Excel

    2015-04-11 01:35:47
    首先要导入poi jar包,在这里声明一下,例子中用的是poi-3.0.1.jar,你也可以下载最新的, 如果没有大的改动的话,大部分插件都是向后兼容的;如果你要想掌握poi,请仔细阅读代码, 为便于阅读与记忆我加了详细注释...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,486
精华内容 1,794
关键字:

poi中文导出