当前位置: 首页 > news >正文

day01-报表技术POI

前言

报表[forms for reporting to the higher organizations],就是向上级报告情况的表格。简单的说:报表就是用表格、图表等格式来动态显示数据,可以用公式表示为:“报表 = 多样的格式 + 动态的数据”。

1、开发环境搭建

功能说明:整个案例我们操作用户表,做一个企业员工(用户)数据的导入导出。

我们使用SpringBoot+通用mapper+vue方式搭建开发环境

第一步:准备数据库,把资料文件夹下中的sql脚本直接执行

《report_manager_db.sql》

/*
Navicat MySQL Data TransferSource Server         : 127.0.0.1
Source Server Version : 50727
Source Host           : 127.0.0.1:3306
Source Database       : report_manager_dbTarget Server Type    : MYSQL
Target Server Version : 50727
File Encoding         : 65001Date: 2020-03-21 22:06:35
*/CREATE DATABASE /*!32312 IF NOT EXISTS*/`report_manager_db` /*!40100 DEFAULT CHARACTER SET utf8 */;USE `report_manager_db`;SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for tb_dept
-- ----------------------------
DROP TABLE IF EXISTS `tb_dept`;
CREATE TABLE `tb_dept` (`id` bigint(20) DEFAULT NULL COMMENT '部门编号',`dept_name` varchar(100) DEFAULT NULL COMMENT '部门编号'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of tb_dept
-- ----------------------------
INSERT INTO `tb_dept` VALUES ('5', '资产管理部');
INSERT INTO `tb_dept` VALUES ('6', '质量监察部');
INSERT INTO `tb_dept` VALUES ('7', '营销部');
INSERT INTO `tb_dept` VALUES ('1', '销售部');
INSERT INTO `tb_dept` VALUES ('2', '人事部');
INSERT INTO `tb_dept` VALUES ('3', '财务部');
INSERT INTO `tb_dept` VALUES ('4', '技术部');-- ----------------------------
-- Table structure for tb_province
-- ----------------------------
DROP TABLE IF EXISTS `tb_province`;
CREATE TABLE `tb_province` (`id` bigint(50) NOT NULL,`name` varchar(100) DEFAULT NULL COMMENT '省份或直辖市或特别行政区名称',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of tb_province
-- ----------------------------
INSERT INTO `tb_province` VALUES ('1', '北京市');
INSERT INTO `tb_province` VALUES ('2', '天津市');
INSERT INTO `tb_province` VALUES ('3', '上海市');
INSERT INTO `tb_province` VALUES ('4', '重庆市');
INSERT INTO `tb_province` VALUES ('5', '河北省');
INSERT INTO `tb_province` VALUES ('6', '山西省');
INSERT INTO `tb_province` VALUES ('7', '辽宁省');
INSERT INTO `tb_province` VALUES ('8', '吉林省');
INSERT INTO `tb_province` VALUES ('9', '黑龙江省');
INSERT INTO `tb_province` VALUES ('10', '江苏省');
INSERT INTO `tb_province` VALUES ('11', '浙江省');
INSERT INTO `tb_province` VALUES ('12', '安徽省');
INSERT INTO `tb_province` VALUES ('13', '福建省');
INSERT INTO `tb_province` VALUES ('14', '江西省');
INSERT INTO `tb_province` VALUES ('15', '山东省');
INSERT INTO `tb_province` VALUES ('16', '河南省');
INSERT INTO `tb_province` VALUES ('17', '湖北省');
INSERT INTO `tb_province` VALUES ('18', '湖南省');
INSERT INTO `tb_province` VALUES ('19', '广东省');
INSERT INTO `tb_province` VALUES ('20', '海南省');
INSERT INTO `tb_province` VALUES ('21', '四川省');
INSERT INTO `tb_province` VALUES ('22', '贵州省');
INSERT INTO `tb_province` VALUES ('23', '云南省');
INSERT INTO `tb_province` VALUES ('24', '陕西省');
INSERT INTO `tb_province` VALUES ('25', '甘肃省');
INSERT INTO `tb_province` VALUES ('26', '青海省');
INSERT INTO `tb_province` VALUES ('27', '台湾省');
INSERT INTO `tb_province` VALUES ('28', '内蒙古自治区');
INSERT INTO `tb_province` VALUES ('29', '广西壮族自治区');
INSERT INTO `tb_province` VALUES ('30', '西藏自治区');
INSERT INTO `tb_province` VALUES ('31', '宁夏回族自治区');
INSERT INTO `tb_province` VALUES ('32', '新疆维吾尔自治区');
INSERT INTO `tb_province` VALUES ('33', '香港特别行政区');
INSERT INTO `tb_province` VALUES ('34', '澳门特别行政区');-- ----------------------------
-- Table structure for tb_resource
-- ----------------------------
DROP TABLE IF EXISTS `tb_resource`;
CREATE TABLE `tb_resource` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`price` double(10,1) DEFAULT NULL,`user_id` bigint(20) DEFAULT NULL,`need_return` tinyint(1) DEFAULT NULL COMMENT '是否需要归还',`photo` varchar(200) DEFAULT NULL COMMENT '照片',PRIMARY KEY (`id`),KEY `fk_user_id` (`user_id`),CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `tb_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of tb_resource
-- ----------------------------
INSERT INTO `tb_resource` VALUES ('1', '记录本', '2.0', '3', '0', '\\resource_photos\\3\\1.jpg');
INSERT INTO `tb_resource` VALUES ('2', '笔记本电脑', '7000.0', '3', '1', '\\resource_photos\\3\\2.jpg');
INSERT INTO `tb_resource` VALUES ('3', '办公桌', '1000.0', '3', '1', '\\resource_photos\\3\\3.jpg');
INSERT INTO `tb_resource` VALUES ('4', '订书机', '50.0', '4', '1', '\\resource_photos\\4\\1.jpg');
INSERT INTO `tb_resource` VALUES ('5', '双面胶带', '5.0', '4', '0', '\\resource_photos\\4\\2.jpg');
INSERT INTO `tb_resource` VALUES ('6', '资料文件夹', '10.0', '4', '0', '\\resource_photos\\4\\3.jpg');
INSERT INTO `tb_resource` VALUES ('7', '打印机', '1200.0', '4', '1', '\\resource_photos\\4\\4.jpg');-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',`user_name` varchar(100) DEFAULT NULL COMMENT '姓名',`phone` varchar(15) DEFAULT NULL COMMENT '手机号',`province` varchar(50) DEFAULT NULL COMMENT '省份',`city` varchar(50) DEFAULT NULL COMMENT '城市',`salary` int(10) DEFAULT NULL,`hire_date` datetime DEFAULT NULL COMMENT '入职日期',`dept_id` bigint(20) DEFAULT NULL COMMENT '部门编号',`birthday` datetime DEFAULT NULL COMMENT '出生日期',`photo` varchar(200) DEFAULT NULL COMMENT '照片路径',`address` varchar(300) DEFAULT NULL COMMENT '现在住址',PRIMARY KEY (`id`),KEY `fk_dept` (`dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES ('1', '大一', '13800000001', '北京市', '北京市', '11000', '2001-01-01 21:18:29', '1', '1981-03-02 00:00:00', '\\static\\user_photos\\1.jpg', '北京市西城区宣武大街1号院');
INSERT INTO `tb_user` VALUES ('2', '不二', '13800000002', '河北省', '石家庄市', '12000', '2002-01-02 21:18:29', '2', '1982-03-02 00:00:00', '\\static\\user_photos\\2.jpg', '北京市西城区宣武大街2号院');
INSERT INTO `tb_user` VALUES ('3', '张三', '13800000003', '河北省', '石家庄市', '13000', '2003-03-03 21:18:29', '3', '1983-03-02 00:00:00', '\\static\\user_photos\\3.jpg', '北京市西城区宣武大街3号院');
INSERT INTO `tb_user` VALUES ('4', '李四', '13800000004', '河北省', '石家庄市', '14000', '2004-02-04 21:18:29', '4', '1984-03-02 00:00:00', '\\static\\user_photos\\4.jpg', '北京市西城区宣武大街4号院');
INSERT INTO `tb_user` VALUES ('5', '王五', '13800000005', '河北省', '唐山市', '15000', '2005-03-05 21:18:29', '5', '1985-03-02 00:00:00', '\\static\\user_photos\\5.jpg', '北京市西城区宣武大街5号院');
INSERT INTO `tb_user` VALUES ('6', '赵六', '13800000006', '河北省', '承德市省', '16000', '2006-04-06 21:18:29', '6', '1986-03-02 00:00:00', '\\static\\user_photos\\6.jpg', '北京市西城区宣武大街6号院');
INSERT INTO `tb_user` VALUES ('7', '沈七', '13800000007', '河北省', '秦皇岛市', '17000', '2007-06-07 21:18:29', '7', '1987-03-02 00:00:00', '\\static\\user_photos\\7.jpg', '北京市西城区宣武大街7号院');
INSERT INTO `tb_user` VALUES ('8', '酒八', '13800000008', '河北省', '秦皇岛市', '18000', '2008-07-08 21:18:29', '6', '1988-03-02 00:00:00', '\\static\\user_photos\\8.jpg', '北京市西城区宣武大街8号院');
INSERT INTO `tb_user` VALUES ('9', '第九', '13800000009', '山东省', '德州市', '19000', '2009-03-09 21:18:29', '1', '1989-03-02 00:00:00', '\\static\\user_photos\\9.jpg', '北京市西城区宣武大街9号院');
INSERT INTO `tb_user` VALUES ('10', '石十', '13800000010', '山东省', '青岛市', '20000', '2010-07-10 21:18:29', '4', '1990-03-02 00:00:00', '\\static\\user_photos\\10.jpg', '北京市西城区宣武大街10号院');
INSERT INTO `tb_user` VALUES ('11', '肖十一', '13800000011', '山东省', '青岛市', '21000', '2011-12-11 21:18:29', '4', '1991-03-02 00:00:00', '\\static\\user_photos\\11.jpg', '北京市西城区宣武大街11号院');
INSERT INTO `tb_user` VALUES ('12', '星十二', '13800000012', '山东省', '青岛市', '22000', '2012-05-12 21:18:29', '4', '1992-03-02 00:00:00', '\\static\\user_photos\\12.jpg', '北京市西城区宣武大街12号院');
INSERT INTO `tb_user` VALUES ('13', '钗十三', '13800000013', '山东省', '济南市', '23000', '2013-06-13 21:18:29', '3', '1993-03-02 00:00:00', '\\static\\user_photos\\13.jpg', '北京市西城区宣武大街13号院');
INSERT INTO `tb_user` VALUES ('14', '贾十四', '13800000014', '山东省', '威海市', '24000', '2014-06-14 21:18:29', '2', '1994-03-02 00:00:00', '\\static\\user_photos\\14.jpg', '北京市西城区宣武大街14号院');
INSERT INTO `tb_user` VALUES ('15', '甄世武', '13800000015', '山东省', '济南市', '25000', '2015-06-15 21:18:29', '4', '1995-03-02 00:00:00', '\\static\\user_photos\\15.jpg', '北京市西城区宣武大街15号院');-- ----------------------------
-- Table structure for tb_month
-- ----------------------------
DROP TABLE IF EXISTS `tb_month`;
CREATE TABLE `tb_month` (`name` varchar(2) DEFAULT NULL COMMENT '月份'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of tb_month
-- ----------------------------
INSERT INTO `tb_month` VALUES ('01');
INSERT INTO `tb_month` VALUES ('02');
INSERT INTO `tb_month` VALUES ('03');
INSERT INTO `tb_month` VALUES ('04');
INSERT INTO `tb_month` VALUES ('05');
INSERT INTO `tb_month` VALUES ('06');
INSERT INTO `tb_month` VALUES ('07');
INSERT INTO `tb_month` VALUES ('08');
INSERT INTO `tb_month` VALUES ('09');
INSERT INTO `tb_month` VALUES ('10');
INSERT INTO `tb_month` VALUES ('11');
INSERT INTO `tb_month` VALUES ('12');

2、Excel说明

在企业级应用开发中,Excel报表是一种最常见的报表需求。Excel报表开发一般分为两种形式:
1、为了方便操作,基于Excel的报表批量上传数据,也就是把Excel中的数据导入到系统中。
2、通过java代码生成Excel报表。也就是把系统中的数据导出到Excel中,方便查阅。

2.1 Excel的两种版本

目前世面上的Excel分为两个大的版本Excel2003和Excel2007及以上两个版本;
两者之间的区别如下:

在这里插入图片描述

Excel2003 是一个特有的二进制格式,其核心结构是复合文档类型的结构,存储数据量较小;

Excel2007 的核心结构是 XML 类型的结构,采用的是基于 XML 的压缩方式,使其占用的空间更小,

​ 操作效率更高

2.2 常见的Excel操作工具

Java中常见的用来操作Excel的方式一般有2种:JXL和POI。

2.2.1 JXL

JXL只能对Excel进行操作,属于比较老的框架,它只支持到Excel 95-2000的版本。现在已经停止更新和
维护,所以本课程中只时简单地演示一下jxl的代码,不会把它作为重点,

2.2.2 POI

POI是apache的项目,可对微软的Word,Excel,PPT进行操作,包括office2003和2007,Excle2003和2007。
poi现在一直有更新。所以现在主流使用POI。

Apache POI是Apache软件基金会的开源项目,由Java编写的免费开源的跨平台的 Java API,Apache
POI提供API给Java语言操作Microsoft Office的功能。

API对象介绍
工作簿 : WorkBook (HSSFWordBook : 2003版本,XSSFWorkBook : 2007级以上)
工作表 : Sheet (HSSFSheet : 2003版本,XSSFSheet : 2007级以上)
行 : Row (HSSFRow : 2003版本,XSSFRow : 2007级以上)
单元格 : Cell (HSSFCell : 2003版本,XSSFCell : 2007级以上)

3、使用JXL导出excel

目前Excel的版本有2013、2010、2007,这些都是新版本的excel,新版本的excel已经出现十多年了,使用人群已经比较多了,所以目前做项目大都做的是导出新版本的excel,而jxl只能操作低版本的excel,所以现在使用jxl做项目已经比较少见,那我们在这里使用jxl导出一个简单一些的excel。

3.1 使用jxl导出基本知识点

通过WritableWorkbook,WritableSheet,Label这三个对象我们就可以实现Excel文件的导出工作。

1、 创建可写入的Excel工作薄

WritableWorkbook workbook= Workbook.createWorkbook(输出流);

2、创建工作表

WritableSheet sheet= workbook.createSheet(工作表的名称, 工作表的索引值);

3、创建单元格

添加文本类单元格

Label labelC = new Label(列索引值, 行索引值, "单元格中的内容");sheet.addCell(labelC);

4、写入到文件

workbook.write();// 写入数据

5、释放资源:

workbook.close();// 关闭文件

3.2 代码实现导出用户列表数据

第一步:UserController中添加方法

@GetMapping(value = "/downLoadXlsByJxl",name = "使用jxl下载")
public void downLoadXlsByJxl(HttpServletResponse response){userService.downLoadByJxl(response);
}

第二步:UserService中的方法

private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ss");public void downLoadXlsByJxl(HttpServletResponse response){try {
//            创建一个工作薄ServletOutputStream outputStream = response.getOutputStream();WritableWorkbook workbook = Workbook.createWorkbook(outputStream);
//            创建一个工作表WritableSheet sheet = workbook.createSheet("一个JXL入门", 0);
//            设置列宽sheet.setColumnView(0,5);sheet.setColumnView(1,8);sheet.setColumnView(2,15);sheet.setColumnView(3,15);sheet.setColumnView(4,30);
//            处理标题String[] titles = new String[]{"编号","姓名","手机号","入职日期","现住址"};Label label = null;for (int i = 0; i < titles.length; i++) {label = new Label(i,0,titles[i]);sheet.addCell(label);}
//            处理导出的内容List<User> userList = this.findAll();int rowIndex = 1;for (User user : userList) {label = new Label(0,rowIndex,user.getId().toString());sheet.addCell(label);label = new Label(1,rowIndex,user.getUserName());sheet.addCell(label);label = new Label(2,rowIndex,user.getPhone());sheet.addCell(label);label = new Label(3,rowIndex,simpleDateFormat.format(user.getHireDate()));sheet.addCell(label);label = new Label(4,rowIndex,user.getAddress());sheet.addCell(label);rowIndex++;}//            导出的文件名称String filename="一个JXL入门.xls";
//            设置文件的打开方式和mime类型response.setHeader( "Content-Disposition", "attachment;filename="  + new String(filename.getBytes(),"ISO8859-1"));response.setContentType("application/vnd.ms-excel");
//            导出workbook.write();
//            关闭资源workbook.close();outputStream.close();} catch (Exception e) {e.printStackTrace();}}

导出内容如下:

在这里插入图片描述

4、POI操作excel

添加所需的依赖:

<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><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.0.1</version>
</dependency>

4.1、POI操作Excel高低版本区别

在POI包中有如下几个主要对象和excel的几个对象对应:

对应excel名称低版本中的类名高版本中的类名
工作簿HSSFWorkbookXSSFWorkbook
工作表HSSFSheetXSSFSheet
HSSFRowXSSFRow
单元格HSSFCellXSSFCell
单元格样式HSSFCellStyleXSSFCellStyle

入门案例代码:创建一个新的工作薄,里面随便写一句话

操作低版本:

package com.itheima.demo;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
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.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
public class POIDemo01 {public static void main(String[] args) throws Exception{Workbook workbook = new HSSFWorkbook(); //创建了一个全新(里面什么都没有)的工作薄Sheet sheet = workbook.createSheet("demo测试");  //创建了一个全新(里面什么都没有)的工作表Row row = sheet.createRow(0);  //创建了第一行(空的)Cell cell = row.createCell(0);//创建的是第一行的第一个单元格cell.setCellValue("这是我第一次玩POI");
//        把工作薄输出到本地磁盘workbook.write(new FileOutputStream("d://test.xls"));}
}

操作高版本:

package com.itheima.demo;
import org.apache.poi.ss.usermodel.Cell;
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.xssf.usermodel.XSSFWorkbook;import java.io.FileOutputStream;public class POIDemo02 {public static void main(String[] args) throws Exception{Workbook workbook = new XSSFWorkbook(); //创建了一个全新(里面什么都没有)的工作薄Sheet sheet = workbook.createSheet("demo测试");  //创建了一个全新(里面什么都没有)的工作表Row row = sheet.createRow(0);  //创建了第一行(空的)Cell cell = row.createCell(0);//创建的是第一行的第一个单元格cell.setCellValue("这是我第一次玩POI");
//        把工作薄输出到本地磁盘workbook.write(new FileOutputStream("d://test.xlsx"));}
}

比较上面两个代码会发现,在开发中只是类的名称不一样,方法是一样的。

4.2、实现用户数据的导入

4.2.1、需求

把资料中的《用户导入测试数据.xlsx》文档中的数据导入到系统中,

内容如下:

在这里插入图片描述

数据的导入就是读取excel中的内容,转成对象插入到数据库中

4.2.2 、思路

一般来说,即将导入的文件,每个列代表什么意思基本上都是固定的,比如第1列就是用户姓名,最后一列就是用户的现住址,并且在做excel时对每个列的类型都是有要求的,这样就可以给我们开发带来很大的简便。

最终的目标就是读取每一行数据,把数据转成用户的对象,保存到表中

实现的步骤:1、根据上传的文件创建Workbook

​ 2、获取到第一个sheet工作表

​ 3、从第二行开始读取数据

​ 4、读取每一个单元格,把内容放入到用户对象的相关的属性中

4.2.3、代码实现

第一步:在Controller接收文件,具体的实现交给service

@PostMapping(value = "/uploadExcel", name = "上传用户数据")
public void uploadExcel(MultipartFile file)  throws Exception{userService.uploadExcel(file);
}

第二步:UserService添加上传用户的方法

public void uploadExcel(MultipartFile file) throws Exception {Workbook workbook = new XSSFWorkbook(file.getInputStream()); //根据上传的输入流创建workbookSheet sheet = workbook.getSheetAt(0); //获取工作薄中的第一个工作表int lastRowIndex = sheet.getLastRowNum(); //获取这个sheet中最后一行数据,为了循环遍历//        以下三个为了节省栈内存,所以提到循环的外面User user = null;Row row = null;Cell cell = null;//开始循环每行,获取每行的单元格中的值,放入到user属性中for (int i = 1; i <= lastRowIndex; i++) {row = sheet.getRow(i);user = new User();//          因为第一个列单元格中是字符串,可以直接使用getStringCellValue方法String userName = row.getCell(0).getStringCellValue(); //用户名user.setUserName(userName);String phone = null; //手机号try {phone = row.getCell(1).getStringCellValue();} catch (IllegalStateException e) {phone = row.getCell(1).getNumericCellValue()+"";}user.setPhone(phone);String province = row.getCell(2).getStringCellValue(); //省份user.setProvince(province);String city = row.getCell(3).getStringCellValue(); //城市user.setCity(city);//            因为在填写excel中的数据时就可以约定这个列只能填写数值,所以可以直接用getNumericCellValue方法Integer salary = ((Double)row.getCell(4).getNumericCellValue()).intValue(); //工资user.setSalary(salary);String hireDateStr = row.getCell(5).getStringCellValue(); //入职日期Date hireDate = simpleDateFormat.parse(hireDateStr);user.setHireDate(hireDate);String birthdayStr = row.getCell(6).getStringCellValue(); //出生日期Date birthday = simpleDateFormat.parse(birthdayStr);user.setBirthday(birthday);String address = row.getCell(7).getStringCellValue(); //现住地址user.setAddress(address);userMapper.insert(user);}}

上传成功后直接查询数据库中的数据:

在这里插入图片描述

4.3、实现用户数据的导出

4.3.1、需求

我们先来一个简单的excel的导出,不要求有什么样式。就是和jxl导出的内容一样就可以

在这里插入图片描述

4.3.2、基本思路

1、创建一个全新的工作薄

2、在新的工作薄中创建一个新的工作表

3、在工作表创建第一行作为标题行,标题固定

4、从第二行循环遍历创建,有多少条用户数据就应该创建多少行

5、把每一个user对象的属性放入到相应的单元格中

4.3.3、代码实现

第一步:在Controller添加方法,具体的实现交给service

@GetMapping(value = "/downLoadXlsxByPoi",name = "使用POI下载高版本")
public void downLoadXlsx(HttpServletResponse response) throws Exception{userService.downLoadXlsx(response);
}

第二步:UserService中实现

public void downLoadXlsx(HttpServletResponse response) throws Exception {//        创建一个空的工作薄Workbook workbook = new XSSFWorkbook();//        在工作薄中创建一个工作表Sheet sheet = workbook.createSheet("测试");//        设置列宽sheet.setColumnWidth(0,5*256);sheet.setColumnWidth(1,8*256);sheet.setColumnWidth(2,15*256);sheet.setColumnWidth(3,15*256);sheet.setColumnWidth(4,30*256);//            处理标题String[] titles = new String[]{"编号","姓名","手机号","入职日期","现住址"};//        创建标题行Row titleRow = sheet.createRow(0);Cell cell = null;for (int i = 0; i < titles.length; i++) {cell = titleRow.createCell(i);cell.setCellValue(titles[i]);}//        处理内容List<User> userList = this.findAll();int rowIndex = 1;Row row = null;for (User user : userList) {row = sheet.createRow(rowIndex);cell = row.createCell(0);cell.setCellValue(user.getId());cell = row.createCell(1);cell.setCellValue(user.getUserName());cell = row.createCell(2);cell.setCellValue(user.getPhone());cell = row.createCell(3);cell.setCellValue(simpleDateFormat.format(user.getHireDate()));cell = row.createCell(4);cell.setCellValue(user.getAddress());rowIndex++;}//            导出的文件名称String filename="员工数据.xlsx";//            设置文件的打开方式和mime类型ServletOutputStream outputStream = response.getOutputStream();response.setHeader( "Content-Disposition", "attachment;filename="  + new String(filename.getBytes(),"ISO8859-1"));response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");workbook.write(outputStream);}

4.4、导出时样式的设置

如果要求导出的excel如下内容:

在这里插入图片描述

通过上图可以看出有些样式需要我们来设置,来看一下都有哪些知识点:
1.画框线

/**
* 设置框线
*/
HSSFCellStyle contentStyle = book.createCellStyle();
contentStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);//底线
contentStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//顶部线
contentStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左侧线
contentStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右侧线

2.合并单元格

//合并单元格 起始行, 结束行, 起始列, 结束列		
sheet.addMergedRegion(new CellRangeAddress(0,0,0,4));

3.设置行高

/**
设置行高
*/
sheet.getRow(1).setHeight((short)500);

4.设置表格的对齐方式和字体

//*设置对齐方式和字体***/
//内容部分的样式
style_content.setAlignment(HSSFCellStyle.ALIGN_CENTER);//设置水平居中
style_content.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//设置垂直居中HSSFFont font = book.createFont();//创建字体
font.setFontName("宋体");//设置字体名称
font.setFontHeightInPoints((short)11);//设置字体大小
style_content.setFont(font);//对样式设置字体//标题样式
HSSFCellStyle style_title = book.createCellStyle();//创建标题样式
style_title.setAlignment(HSSFCellStyle.ALIGN_CENTER);//设置水平居中
style_title.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//设置垂直居中
HSSFFont titleFont = book.createFont();//设置标题字体
titleFont.setFontName("黑体");
titleFont.setBold(true);//加粗
titleFont.setFontHeightInPoints((short)18);//字体大小    
style_title.setFont(titleFont);//将标题字体设置到标题样式
sheet.getRow(0).getCell(0).setCellStyle(style_title);//单元格设置标题样式

其实真正要用代码实现我们最终想要的效果的话,难道不大,但是代码写起来非常麻烦,所以明天给大家介绍一种非常简单的方式,并且还带有样式。

相关文章:

day01-报表技术POI

前言 报表[forms for reporting to the higher organizations]&#xff0c;就是向上级报告情况的表格。简单的说&#xff1a;报表就是用表格、图表等格式来动态显示数据&#xff0c;可以用公式表示为&#xff1a;“报表 多样的格式 动态的数据”。 1、开发环境搭建 功能说…...

如何预防最新的.locked、.locked1勒索病毒感染您的计算机?

尊敬的读者&#xff1a; 近期&#xff0c;网络安全领域迎来一股新潮——.locked、.locked1勒索病毒的威胁&#xff0c;其先进的加密技术令人生畏。本文将深入剖析.locked、.locked1勒索病毒的阴谋&#xff0c;提供特色数据恢复策略&#xff0c;并揭示锁定恶劣行径的先锋预防手…...

实现两张图片的接缝线拼接

使用ORB算法检测特征点&#xff0c;并通过BFMatcher进行特征点匹配。然后&#xff0c;根据Lowes ratio test选择好的匹配点&#xff0c;并使用findHomography计算单应性矩阵。最后&#xff0c;使用warpPerspective将图像进行透视变换&#xff0c;然后将第二张图像粘贴到变换后的…...

基于JNI 实现 嵌套 List 类型参数解析

基于JNI 实现 嵌套 List 类型参数解析 背景分析解决 背景 在前面两篇文章中&#xff0c;我们总结了Java 调用 C/C SDK 的几种方案&#xff0c;分享了JNI在实践过程中的一些踩坑点&#xff0c;而在这篇文章将继续分享针对Java List类型及其嵌套类型&#xff0c;我们的JNI如何接…...

探索灵活性与可维护性的利器:策略(Strategy)模式详解

目录 ​编辑 1. 策略模式概述&#xff1a; 2. 主要角色&#xff1a; 3. 实例场景&#xff1a; 4. 具体实现步骤&#xff1a; 步骤一&#xff1a;定义策略接口 5. 使用策略模式的客户端代码&#xff1a; 总结&#xff1a; 我的其他博客 1. 策略模式概述&#xff1a; 策…...

压缩包文件暴力破解 -Server2005(解析)

任务五十一: 压缩包文件暴力破解 任务环境说明:Server2005 1. 通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机服务版本信息,将 Telnet 版本信息字符串 作为 Flag 提交; flag:Microsoft Windows XP telnetd 2. 通过本地PC中渗透测试平台Kali对服务器场景Windows进行渗透测…...

mars3d加载arcgis发布的服务,⽀持4523坐标

问题 1.从这个服务地址加载&#xff0c;具体在哪⾥去转坐标呢&#xff1f; 加个 usePreCachedTilesIfAvailable&#xff1a;false 参数即可 坐标系为4490的arcgis影像服务图层&#xff0c;配置后瓦片加载不出来&#xff0c;没报错 甚至可以跳转 没有看出问题&#xff0c;或者测…...

『K8S 入门』二:深入 Pod

『K8S 入门』二&#xff1a;深入 Pod 一、基础命令 获取所有 Pod kubectl get pods2. 获取 deploy kubectl get deploy3. 删除 deploy&#xff0c;这时候相应的 pod 就没了 kubectl delete deploy nginx4. 虽然删掉了 Pod&#xff0c;但是这是时候还有 service&#xff0c…...

十七、如何将MapReduce程序提交到YARN运行

1、启动某个节点的某一个用户 hadoopnode1:~$ jps 13025 Jps hadoopnode1:~$ yarn --daemon start resourcemanager hadoopnode1:~$ jps 13170 ResourceManager 13253 Jps hadoopnode1:~$ yarn --daemon start nodemanager hadoopnode1:~$ jps 13170 ResourceManager 15062 Jp…...

华为云CodeArts Deploy常见问答汇总

1.【Deploy】部署java项目&#xff0c;为什么通过springboot启动步骤启动失败了&#xff1f; 答&#xff1a;用户所部署的jar包源码并不是springboot框架&#xff0c;所以无法用springboot启动步骤启动&#xff0c;该步骤并不等同于java -jar 命令&#xff0c;需要使用shell脚…...

前后端交互—开发一个完整的服务器

代码下载 初始化 新建 apiServer 文件夹作为项目根目录&#xff0c;并在项目根目录中运行如下的命令&#xff0c;初始化包管理配置文件: npm init -y运行如下的命令&#xff0c;安装 express、cors: npm i express cors在项目根目录中新建 app.js 作为整个项目的入口文件&a…...

前端框架的虚拟DOM(Virtual DOM)

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

什么是http状态码?

什么是http状态码&#xff1f; 当浏览者访问一个网页时&#xff0c;浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前&#xff0c;此网页所在的服务器会返回一个包含 HTTP 状态码的信息头&#xff08;server header&#xff09;用以响应浏览器的请求。 ht…...

linux/CentOS 7安装Nginx

Nginx 是 C语言 开发&#xff0c;建议在 Linux 上运行&#xff0c;当然&#xff0c;也可以安装 Windows 版本&#xff0c;本篇则使用 CentOS 7 作为安装环境。 Nginx一般使用非root账号安装&#xff0c;如果还没有非root账号&#xff0c;先创建账号 创建账号 创建组&#xf…...

软件工程期末复习+数据仓库ETL

一、软件工程 请用基本路径测试方法为下列程序设计测试用例&#xff0c;并写明中间过程&#xff1a; 第1步&#xff1a;画出流程图 1.菱形用于条件判断。用在有分支的地方。 2.矩形表示一个基本操作。 3.圆形是连接点 第2步&#xff1a;计算程序环路复杂性 流图G的环路复杂…...

学习C语言——体会计算机中的0和1

/* 把hello隐写入一个整型数组,这个小程序可以考察是否清楚数据在内存中存储的具体细节。 具体的说&#xff0c;int类型在小端机器上的存储方式是高位在高地址&#xff0c;低位在低地址&#xff0c;从视觉习惯上和我们的日常书写习惯相反&#xff1b; char类型占用…...

PyTorch官网demo解读——第一个神经网络(1)

神经网络如此神奇&#xff0c;feel the magic 今天分享一下学习PyTorch官网demo的心得&#xff0c;原来实现一个神经网络可以如此简单/简洁/高效&#xff0c;同时也感慨PyTorch如此强大。 这个demo的目的是训练一个识别手写数字的模型&#xff01; 先上源码&#xff1a; fr…...

升华 RabbitMQ:解锁一致性哈希交换机的奥秘【RabbitMQ 十】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 升华 RabbitMQ&#xff1a;解锁一致性哈希交换机的奥秘【RabbitMQ 十】 前言第一&#xff1a;该插件需求为什么需要一种更智能的消息路由方式&#xff1f;一致性哈希的基本概念&#xff1a; 第二&…...

vue3 element-plus 日期选择器 el-date-picker 汉化

vue3 项目中&#xff0c;element-plus 的日期选择器 el-date-picker 默认是英文版的&#xff0c;如下&#xff1a; 页面引入&#xff1a; //引入汉化语言包 import locale from "element-plus/lib/locale/lang/zh-cn" import { ElDatePicker, ElButton, ElConfigP…...

剑指 Offer(第2版)面试题 35:复杂链表的复制

剑指 Offer&#xff08;第2版&#xff09;面试题 35&#xff1a;复杂链表的复制 剑指 Offer&#xff08;第2版&#xff09;面试题 35&#xff1a;复杂链表的复制解法1&#xff1a;模拟 剑指 Offer&#xff08;第2版&#xff09;面试题 35&#xff1a;复杂链表的复制 题目来源&…...

自定义指令Custom Directives

<script setup langts> import { ref } from "vue"const state ref(false)/*** Implement the custom directive* Make sure the input element focuses/blurs when the state is toggled* */ // 以v开头的驼峰式命名的变量都可以作为一个自定义指令 const VF…...

预测性维护对制造企业设备管理的作用

制造企业设备管理和维护对于生产效率和成本控制至关重要。然而&#xff0c;传统的维护方法往往无法准确预测设备故障&#xff0c;导致生产中断和高额维修费用。为了应对这一挑战&#xff0c;越来越多的制造企业开始采用预测性维护技术。 预测性维护是通过传感器数据、机器学习和…...

华为、新华三、锐捷常用命令总结

华为、新华三、锐捷常用命令总结 一、华为交换机基础配置命令二、H3C交换机的基本配置三、锐捷交换机基础命令配置 一、华为交换机基础配置命令 1、创建vlan&#xff1a; <Quidway> //用户视图&#xff0c;也就是在Quidway模式下运行命令。 <Quidway>system-view…...

链路追踪详解(四):分布式链路追踪的事实标准 OpenTelemetry 概述

目录 OpenTelemetry 是什么&#xff1f; OpenTelemetry 的起源和目标 OpenTelemetry 主要特点和功能 OpenTelemetry 的核心组件 OpenTelemetry 的工作原理 OpenTelemetry 的特点 OpenTelemetry 的应用场景 小结 OpenTelemetry 是什么&#xff1f; OpenTelemetry 是一个…...

Node.js 工作线程与子进程:应该使用哪一个

Node.js 工作线程与子进程&#xff1a;应该使用哪一个 并行处理在计算密集型应用程序中起着至关重要的作用。例如&#xff0c;考虑一个确定给定数字是否为素数的应用程序。如果我们熟悉素数&#xff0c;我们就会知道必须从 1 遍历到该数的平方根才能确定它是否是素数&#xff…...

python matplotlib 三维图形添加文字且不随图形变动而变动

要在三维图形中添加文字并使其不随图形变动而变动&#xff0c;可以使用 annotate() 方法。这个方法可以在三维图形中添加文字&#xff0c;并且可以指定文字的位置、对齐方式和字体大小等属性。 下面是一个示例代码&#xff0c;演示如何在三维图形中添加文字&#xff1a; impo…...

Ubuntu设置kubelet启动脚本关闭swap分区

查看swap分区 swapon -s打开swap分区 swapon -a查看/etc/fstab下所有固化的swap分区&#xff0c;注释 vi /etc/fstab修改kubelet.conf文件 vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf添加 ExecStartPre/sbin/swapoff -a生效 systemctl daemon-reload sys…...

MySQL数据库存储

MySQL数据库存储 MySQL数据库简介MySQL开发环境MySQL安装图形化界面工具Navicat使用 表的操作表的概念3.2 创建表3.3 修改表 数据的操作-增删改查4.1 增加数据4.2 删除数据4.3 修改数据4.4 查询数据4.4.1 基础查询4.4.2 分组查询和聚合函数4.4.4 having语句4.4.5 排序4.5 多表联…...

verilog语法进阶,时钟原语

概述&#xff1a; 内容 1. 时钟缓冲 2. 输入时钟缓冲 3. ODDR2作为输出时钟缓冲 1. 输入时钟缓冲 BUFGP verilog c代码&#xff0c;clk作为触发器的边沿触发&#xff0c;会自动将clk综合成时钟信号。 module primitive1(input clk,input a,output reg y); always (posed…...

案例069:基于微信小程序的计算机实验室排课与查询系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…...

双语网站价格/安卓优化大师官方下载

转载 http://blog.csdn.net/lmj623565791/article/details/45059587&#xff1b; 本文出自:【张鸿洋的博客】 概述 RecyclerView出现已经有一段时间了&#xff0c;相信大家肯定不陌生了&#xff0c;大家可以通过导入support-v7对其进行使用。 据官方的介绍&#xff0c;该控件用…...

ubuntu wordpress安装目录/百度快照优化

前段时间学习《深入浅出Nodejs》时&#xff0c;在第四章 - 异步编程中作者朴灵曾提到&#xff0c;异步编程的难点之一是异常处理&#xff0c;书中描述"尝试对异步方法进行try/catch操作只能捕获当次事件循环内的异常&#xff0c;对call back执行时抛出的异常将无能为力&qu…...

网站建设 英文怎么说/大数据营销精准营销

转载链接&#xff1a;https://blog.csdn.net/Silence_Sep/article/details/81119683 起意 看到一篇不错的博客&#xff0c;想转载但是不会&#xff08;没有转载键&#xff09;&#xff0c;网搜发现没有Chrome浏览器的详细转载办法&#xff0c;受博主Bily猪启发&#xff0c;弄了…...

网站开发文档管理工具/网站排名优化方案

第一步&#xff1a;先安装pydevpyDev&#xff1a;http://www.pydev.org/updates 第二步&#xff1a;配置python解释器路径安装好pydev后&#xff0c; 需要配置Python解释器。在Eclipse菜单栏中&#xff0c;点击Windows ->Preferences. 在对话框中&#xff0c;点击pyDev-&…...

品牌seo公司/seo关键词优化公司哪家好

No valid host was found. There are not enough hosts available ascii codec cant decode byte 0xe6 in position 0: ordinal not in range(128)...

做时时彩网站要多少钱/杭州seo网站

Xcode最近的那些破事 最近苹果放出了iPhone6s和iOS9&#xff0c;于是我们就得把Xcode更新到7&#xff0c;并且做好iOS9的适配。Xcode更新比较慢&#xff0c;不少人可能会选择去某些网盘或者迅雷的某些源下载&#xff0c;但是最近爆出了新闻&#xff0c;一些非官方渠道下载的Xc…...