SSSDJ day8

1.Java操作Excel
1.1.Java操作办公软件
在开发中,我们经常需要写程序还操作办公软件(其中操作得最多的就是Word与Excel)!
因此,我们使用代码过生成,读取这些文件的数据也是很重要的一个功能。
而我们Java中,也是提供了相应的操作办公软件的框架,其中,最常用的是下面两种:
jxl:只能对Excel进行操作,属于比较老的框架。
POI:是apache的项目,可对ms的word,Excel,PPT进行操作,包括office2003和2007。对两种版本的处理都比较好。具体操作请看官方的文档。

1.2.poi的使用
1.2.1.找到文档
咱们这里直接学习poi的使用,poi针对offices03(xls)与07(xlsx)是单独写了相应的实现api,我们这里直接使用07版的处理方案(注:网上是有相应的兼容方案,可判断)。

1.2.2.引入poi需要的jar包

org.apache.poi poi 3.11 org.apache.poi poi-ooxml 3.11

1.2.3.创建Excel(完成99乘法表)
package cn.itsource.pss.common;

public class ExcelTest {

//创建一个Excel文件
//在文件里加一个99乘法法
//把这文件保存在项目中
@Test
public void testCreateExcel() throws Exception{
    //1.创建一个Excel文件(内存中)
    SXSSFWorkbook wb = new SXSSFWorkbook();
    //2.创建一张表
    Sheet sheet = wb.createSheet("99乘法表");
    //3.创建行
    for (int i = 1; i <= 9; i++) {
        Row row = sheet.createRow(i-1);
        //4.创建列(格子)
        for (int j = 1; j <= i; j++) {
            Cell cell = row.createCell(j-1);
            //5.格子中加数据
            cell.setCellValue(i+"*"+j+"="+(i*j));
        }
    }
    //从内存中写出来
    FileOutputStream out = new FileOutputStream("99.xlsx");
    wb.write(out);
    out.close();
}

}

1.2.4.读取Excel
可以使用我们已经准备好的excel文件做测试
/**

  • 读取我们使用相应的方案
  • @throws Exception
    */
    @Test
    public void readExcel() throws Exception{
    File file = new File(“employee-3.xlsx”);
    FileInputStream fis = new FileInputStream(file);
    //1.读取一个Excel文件(内存中)
    Workbook wb = new XSSFWorkbook(fis);
    //2.拿到第个sheet表
    Sheet sheet = wb.getSheetAt(0);
    //3.拿到wb中的行(不要拿头部)
    int lastRowNum = sheet.getLastRowNum();
    for (int i = 1; i <= lastRowNum; i++) {
    Row row = sheet.getRow(i);
    //4.拿到每一列(格子)
    short lastCellNum = row.getLastCellNum();
    for (int j = 0; j < lastCellNum; j++) {
    Cell cell = row.getCell(j);
    System.out.print(cell.getStringCellValue()+" ");
    }
    System.out.println();
    }
    }

2.SpringMVC导出功能(了解认识)
2.1.SpringMVC下载功能
SpringMVC的下载和原生的Servlet下载方案一致。我们只需要把以前学习过的下载代码拿过来使用即可(如果有忘记这部分功能可能简单去回顾一下):
//下面设置好直接使用即可导出
response.setContentType(“application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”); //mime类型
response.setHeader(“Content-disposition”, “attachment;filename=”+filename);
response.setHeader(“Pragma”, “No-cache”);//设置不要缓存
OutputStream ouputStream = response.getOutputStream();
wb.write(ouputStream);
ouputStream.flush();
ouputStream.close();

2.2.直接导出Excel文件
2.2.1.employee.jsp添加导出按钮
导出
2.2.2.EmployeeController完成导出功能
@RequestMapping("/download")
public void download(HttpServletResponse response) throws Exception{
//准备下载的文件名
String filename = “employee.xlsx”;
response.setHeader(“Content-disposition”, filename);
response.setContentType(“application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”); //mime类型
response.setHeader(“Content-disposition”, “attachment;filename=”+filename);
response.setHeader(“Pragma”, “No-cache”);

//1.创建一个Excel文件(内存中)
SXSSFWorkbook wb = new SXSSFWorkbook();
//2.创建一张表
Sheet sheet = wb.createSheet("99乘法表");
//3.创建行
for (int i = 1; i <= 9; i++) {
    Row row = sheet.createRow(i-1);
    //4.创建列(格子)
    for (int j = 1; j <= i; j++) {
        Cell cell = row.createCell(j-1);
        //5.格子中加数据
        cell.setCellValue(i+"*"+j+"="+(i*j));
    }
}
//从内存中写出来
OutputStream out = response.getOutputStream();
wb.write(out);
out.close();

}

2.3.导出真实数据
导出数据时提交表单
2.3.1.完成导出功能的工具方法
package cn.itsource.pss.common;

//Excel的公共类
public class ExcelUtils {
/**
* 导出一个Excel文件
* @param filename 文件名称
* @param heads 文件头
* @param datas 文件内容
* @param response 响应
* @throws Exception
*/
public static void exportExcel(String filename, String[] heads, List<String[]> datas, HttpServletResponse response) throws Exception{
response.setHeader(“Content-disposition”, filename);
response.setContentType(“application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”); //mime类型
response.setHeader(“Content-disposition”, “attachment;filename=”+filename);
response.setHeader(“Pragma”, “No-cache”);
//1.创建一个Excel文件(内存中)
SXSSFWorkbook wb = new SXSSFWorkbook();
//2.创建一张表
Sheet sheet = wb.createSheet();
//3.创建表头
Row headRow = sheet.createRow(0);
for (int i = 0; i < heads.length; i++) {
Cell cell = headRow.createCell(i);
cell.setCellValue(heads[i]);
}
//4.创建表中数据
for (int i = 1; i <= datas.size(); i++) {
//4.1创建数据行
Row row = sheet.createRow(i);
//4.2创建数据列
String[] rowData = datas.get(i-1);
for (int j = 0; j < rowData.length; j++) {
Cell cell = row.createCell(j);
cell.setCellValue(rowData[j]); //添加数据(注意:必需是字符串)
}
}
//从内存中写出来
OutputStream out = response.getOutputStream();
wb.write(out);
out.close();
}
}

2.3.1.EmployeeController完成导出方法
@RequestMapping("/download")
public void download(EmployeeQuery baseQuery,HttpServletResponse response) throws Exception{
//准备相应的表头
String[] heads = {“编号”,“用户名”,“密码”,“邮件”,“年龄”,“部门”};
//拿到相应的员工数据
List employees = employeeService.findByQuery(baseQuery);
//把List格式转换成List<String[]>格式
//1.准备相应的容器
List<String[]> datas = new ArrayList<>();
//2.遍历List
for (int i = 0; i < employees.size(); i++) {
Employee employee = employees.get(i);//拿到某一个员工
//每一行数据与头像长度一致
String[] rowData = new String[heads.length];
//设置数据
rowData[0] = employee.getId().toString();
rowData[1] = employee.getUsername();
rowData[2] = employee.getPassword();
rowData[3] = employee.getEmail();
rowData[4] = employee.getAge()==null?"":employee.getAge().toString();
rowData[5] = employee.getDepartment()==null?"":employee.getDepartment().getName();
datas.add(rowData);
}
String filename = new String(“员工.xlsx”.getBytes(“UTF-8”),“ISO-8859-1”);
ExcelUtils.exportExcel(filename,heads,datas,response);
}

2.3.2.employee.jsp 加上导出按钮
导出

2.3.3.employee.js加上导出方法
var itsource={

//导出数据
export:function(){
$(’#searchForm’).submit();
}
}

3.SpringMVC导入功能(了解认识)
3.1.SpringMVC的上传
我们接下来就简单回顾一下Spring的上传!
3.1.1.添加相应配置(已经完成)
applicationContext-mvc.xml

1048576

3.1.2.准备上传的页面
我们在系统中专门准备上传的页面
/WEB-INF/views/import.jsp
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

Title <%@include file="/WEB-INF/views/head.jsp" %>

${count}

<%-- --%> 确定

3.1.3.ImportController实现
package cn.itsource.pss.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
@Controller
@RequestMapping("/import")
public class ImportController extends BaseController {

//跳转到导入页面
@RequestMapping("/index")
public String index(){
    return "import";
}

//跳转到导入页面
@RequestMapping("/xlsx")
public String importXlsx(MultipartFile xlsxFile) throws Exception{
    System.out.println(xlsxFile.getContentType()); //文件的类型(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
    System.out.println(xlsxFile.getName()); //文件的名称(xlsxFile)
    System.out.println(xlsxFile.getOriginalFilename());//文件的名称(employee-3.xlsx)
    System.out.println(xlsxFile.getSize()); //文件的大小
    return "import";
}

}

3.2.准备上传的工具方法
ExcelUtils:
/**

3.3.完成ImportController
package cn.itsource.pss.web.controller;

@Controller
@RequestMapping("/import")
public class ImportController extends BaseController {

@Autowired
private IDepartmentService departmentService;
@Autowired
private IEmployeeService employeeService;
//跳转到导入页面
@RequestMapping("/index")
public String index(){
    return "import";
}
//跳转到导入页面
@RequestMapping("/xlsx")
public String importXlsx(MultipartFile xlsxFile, Model model) throws Exception{
    //拿到上传的数据
    List<String[]> list = ExcelUtils.importExcel(xlsxFile.getInputStream());
    int count = 0;
    for (int i = 0; i < list.size(); i++) {
        //拿到每一行数据
        String[] data = list.get(i);
        //准备Employee对象进行数据放置
        Employee employee = new Employee();
        employee.setUsername(data[0]+ UUID.randomUUID().toString().substring(0,5));//随机一个名称
        employee.setPassword(data[1]);
        employee.setEmail(data[2]);
        String age = data[3];
        if(StringUtils.isNotBlank(age)){
            employee.setAge(Integer.parseInt(age));
        }
        //拿到与设置部门
        String deptName = data[4];
        if(StringUtils.isNotBlank(deptName)){
            Department department = departmentService.findByName(deptName);
            employee.setDepartment(department); 
        }
        employeeService.save(employee);
        count ++;
    }
    //给出成功提示
    model.addAttribute("count","成功导入"+count+"条数据!");
    return "import";
}

}

4.EasyPOI导出
咱们在开发的时候,总会遇到需要通过代码操作办公软件的情况,而excel与word的操作最为频繁。
当然我们Java程序员可以选择JXL或者POI来完成相应的Excel操作,但是大家用过都知道,有些地方感觉还是不够简单,不那么尽如人意。
今天给大家介绍一个EasyPoi,就算我们不会底层的POI,也可以非常轻松的完成Excel的操作。EasyPoi,主打简单,不过功用依然OK(绝对够用)。现在我们就来尝试一步一步还进行它的入门学习:

4.1.基本使用
引入咱们easypoi的jar包
特别注意:把之前咱们的POI引入去掉(有冲突)

cn.afterturn easypoi-base 3.2.0 cn.afterturn easypoi-web 3.2.0 cn.afterturn easypoi-annotation 3.2.0

4.2.Employee对象加注解
注意:一定要加上getter,setter
@Entity
@Table(name=“employee”)
public class Employee extends BaseDomain {
@Excel(name=“用户名”)
private String username;
private String password;
@Excel(name=“邮件”,width = 25)
private String email;
@Excel(name=“年纪”)
private Integer age;

@Excel(name = "头像",type = 2,savePath = "/images/head",height = 23)
private String headImage; //头像

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="department_id")
//Json Ignore(忽略) Properties(属性)
//@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})
@ExcelEntity
private Department department;

部门有相应的关连
@Entity
@Table(name=“department”)
public class Department extends BaseDomain {

@Excel(name = "部门名称")
private String name;

4.3.员工的页面 Employee.jsp

用户名: 邮件: 部门:
<a href="#" class="easyui-linkbutton" data-method="search" iconCls="icon-search">查询</a>
<!--  button不加type属性就是提交 -->
<button class="easyui-linkbutton" iconCls="icon-search">导出</button>

4.4.控制层进行导出 EmployeeController
/**

  • 导出功能:下载

  • @param map

  • @return
    */
    @RequestMapping("/download")
    public String download(ModelMap map,EmployeeQuery query, HttpServletRequest request) {
    //拿到所有数据
    List list = employeeService.findByQuery(query);
    //获取到真实路径
    //解决了下载的图片的路径问题
    String realPath = request.getServletContext().getRealPath("");
    list.forEach(e -> {
    e.setHeadImage(realPath+e.getHeadImage());
    System.out.println(e.getHeadImage());
    });

    //设置一些属性
    ExportParams params = new ExportParams(“员工管理”, “明细”, ExcelType.XSSF);
    //params.setFreezeCol(3);
    map.put(NormalExcelConstants.DATA_LIST, list); // 数据集合
    map.put(NormalExcelConstants.CLASS, Employee.class);//导出实体
    map.put(NormalExcelConstants.PARAMS, params);//参数
    map.put(NormalExcelConstants.FILE_NAME, “employee”);//文件名称
    //返回的名称 :easypoiExcelView -> 并没有找我的bean,而且当做一个路径去进行访问
    // 现在默认去找的视图解析器,而没有找我的那一个bean
    return NormalExcelConstants.EASYPOI_EXCEL_VIEW;//View名称
    }

特别注意:要使用 return NormalExcelConstants.EASYPOI_EXCEL_VIEW
spring的.xml 需要加上:

<context:component-scan base-package=“cn.afterturn.easypoi.view” />

5.EasyPOI导入
5.1.准备一个导入页面
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>

Title <%@include file="/WEB-INF/views/head.jsp" %> 导入

5.2.准备controller
@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile) throws Exception {

//准备导入的参数
ImportParams params = new ImportParams();
params.setTitleRows(1);

List<Employee> list = ExcelImportUtil.importExcel(
        empFile.getInputStream(),
        Employee.class,
        params);

list.forEach(e ->{
   // System.out.println(e+","+e.getDepartment());
    //根据部门名称拿到它的部门,再放到对应的员工中
    Department dept = departmentService.findByName(e.getDepartment().getName());
    e.setDepartment(dept);
    //给一个默认密码
    e.setPassword("123");
    employeeService.save(e);
});

return "import";

}

5.3.准备相应的验证功能
5.3.1.JSR 303 规范的导包

org.hibernate hibernate-validator 5.2.4.Final

5.3.2.Employee加上相应的注解
@Excel(name=“用户名”)
@NotNull(message = “用户名不为空”)
private String username;
private String password;
@Excel(name=“邮件”,width = 25)
private String email;
@Excel(name=“年纪”)
@Max(value = 80,message = “max 最大值不能超过80”)
private Integer age;

5.3.3.完成验证的功能
@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception {
//准备导入的参数
ImportParams params = new ImportParams();
params.setTitleRows(1);
// need:需要 verfiy:核实,验证
params.setNeedVerfiy(true); //需要验证

    //excel导入的一个结果
    ExcelImportResult<Employee> result = ExcelImportUtil.importExcelMore(
            empFile.getInputStream(),
            Employee.class, params);
    //引入正确的list(正常保存)
    result.getList().forEach(e ->{
        // System.out.println(e+","+e.getDepartment());
        //根据部门名称拿到它的部门,再放到对应的员工中
        Department dept = departmentService.findByName(e.getDepartment().getName());
        e.setDepartment(dept);
        //给一个默认密码
        e.setPassword("123");
        employeeService.save(e);
    });

// //引入错误的list
// result.getFailList().forEach(e ->{
// System.out.println(“错误的:”+e);
// });
//如果有错误,就直接导出错误文件到前台
// Verfiy:检验 Fail:失败
if(result.isVerfiyFail()){
//如果验证失败,代码到这里面来
//失败的文件已经准备好了
Workbook failWorkbook = result.getFailWorkbook();
//把这个文件导出
response.setContentType(“application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”); //mime类型
response.setHeader(“Content-disposition”, “attachment;filename=error.xlsx”);
response.setHeader(“Pragma”, “No-cache”);//设置不要缓存
OutputStream ouputStream = response.getOutputStream();
failWorkbook.write(ouputStream);
ouputStream.flush();
ouputStream.close();
}

    return "import";
}

5.4.自定义验证
注意:一定要实现IExcelVerifyHandler接口
注意:扫描它,把它交给Spring管理
<context:component-scan base-package=“cn.itsource.aisell.common” />
5.4.1.准备验证规则
/**

  • 准备一个自定义验证
    */
    @Component
    public class EmployeeExcelVerifyHandler implements IExcelVerifyHandler {

    @Autowired
    private IEmployeeService employeeService;

    @Override
    public ExcelVerifyHandlerResult verifyHandler(Employee employee) {
    ExcelVerifyHandlerResult result = new ExcelVerifyHandlerResult(true);
    //如果存在,返回false
    if(!employeeService.checkUsername(employee.getUsername())){
    //代表用户名重复
    result.setMsg(“用户名重复”);
    result.setSuccess(false);
    }
    return result;
    }
    }

5.4.2.验证规则用起来
@Autowired
private EmployeeExcelVerifyHandler employeeExcelVerifyHandler;

@RequestMapping("/employeeXlsx")
public String employeeXlsx(MultipartFile empFile, HttpServletResponse response) throws Exception {
//准备导入的参数
ImportParams params = new ImportParams();
params.setTitleRows(1);
// need:需要 verfiy:核实,验证
params.setNeedVerfiy(true); //需要验证
//加入自定义验证
params.setVerifyHandler(employeeExcelVerifyHandler);

return “import”;
}

6.系统数据字典
系统的初始数据我们就可以称之为数据字典
6.1.概念(对表的抽取)
这里我们首先要理解我们现在所说的系统数据字典的概念:
比如说我们系统中需有这么两张表:单位,品牌
单位表
id bigInt
name Varchar(50)
Unit数据
Id name
1 斤
2 辆
3 打

品牌表
id bigInt
name Varchar(50)
Brand数据
Id name
1 七匹狼
2 耐克
3 阿迪
4 阿迪王

大家可以看到,这两张表的结构是完全一致的,而我们以后可能会出现很多类似的表,如下图咱们如果做的是招聘网站会出现的表:

如此的话,我们就需要创建很多相应的Domain与对应的一套CRUD功能!这样的话,相同的工作感觉会特别多!
而我们使用数据字典,可以减少这个不必要的工作量,把这些结构一致的表用数据字典来完成。
减少类似id,name这样的模型(品牌模型,单位模型)
如果表有上下级自关联就不能使用数据字典,如producttype

6.2.设计
添加数据字典类型、数据字典明细结构的表(就组成了数据字典)
6.2.1.数据字典类型

6.2.2.数据字典明细

大家可以通过这个表设计思考一下为什么我们有这两张表可以解决刚才那么相同结构表的问题?

6.3.完成Domain
6.3.1.SystemDictionaryType
有多少类似id,name的表就定义多少常量,在系统初始化的时候就完成
public static final String PRODUCT_BRAND=”productBrand”;
public static final String PRODUCT_UNIT=”productUnit”
@Entity
@Table(name=“systemdictionarytype”)
public class SystemDictionaryType extends BaseDomain{
public static final String PRODUCT_BRAND=“productBrand”;//品牌sn
public static final String PRODUCT_UNIT=“productUnit”;//单位sn
@Column(updatable = false)
private String sn;
private String name;
//get,set…
}

6.3.2.SystemDictionaryDetail
@Entity
@Table(name=“systemdictionarydetail”)
public class SystemDictionaryDetail extends BaseDomain {

private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="types_id")
private Systemdictionarytype types;
//get,set…

}

完成后使用代码生成器生成
尽量理解数据字典(明天的产品模块我们也需要使用到它)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值