直接上代码,原理之前的随笔已经讲过了。
1.先看看效果
2.html代码,含js代码
cpm system
<div> <a href="/home/export">导出</a> </div>
地区公司部门员工姓名
3.后台代码
3.1 分页参数对象
package com.xincheng.cpm.common;/** * Created by hdwang on 2017/6/22. * 分页参数 */public class PageParam {/** * 第几次绘画(前端标识) */private int draw;/** * 起始记录(从0开始),mysql也是从0开始,吻合,good! */private int start;/** * 页大小 */private int length;public int getDraw() {return draw; }public void setDraw(int draw) {this.draw = draw; }public int getStart() {return start; }public void setStart(int start) {this.start = start; }public int getLength() {return length; }public void setLength(int length) {this.length = length; }/** * 第几页(0-n) */public int getPage(){return this.start/this.length; } }
3.2 数据返回对象
package com.xincheng.cpm.common;import java.util.List;/** * Created by hdwang on 2017/6/22. * 表格数据(datatables) */public class TableData<T> {/** * 第几次绘画(前端标识) */private int draw;/** * 行过滤(不知道干嘛的) */private int recordsFiltered;/** * 总行数 */private int recordsTotal;/** * 行数据 */private List<T> data;/** * 起始记录(用于前端初始化序列号用的) */private int start;/** * 错误信息 */private String error;public int getDraw() {return draw; }public void setDraw(int draw) {this.draw = draw; }public int getRecordsFiltered() {return recordsFiltered; }public void setRecordsFiltered(int recordsFiltered) {this.recordsFiltered = recordsFiltered; }public int getRecordsTotal() {return recordsTotal; }public void setRecordsTotal(int recordsTotal) {this.recordsTotal = recordsTotal; }public List<T> getData() {return data; }public void setData(List<T> data) {this.data = data; }public int getStart() {return start; }public void setStart(int start) {this.start = start; }public String getError() {return error; }public void setError(String error) {this.error = error; } }
3.3 数据实体对象
package com.xincheng.cpm.common;import java.io.Serializable;/** * Created by hdwang on 2017/7/14. */public class Member{private String area;private String company;private String department;private String userName;private Integer areaRowSpan;private Integer companyRowSpan;private Integer departmentRowSpan;public Member(String area,String company,String department,String userName){this.area = area;this.company = company;this.department = department;this.userName = userName; }public String getArea() {return area; }public void setArea(String area) {this.area = area; }public String getCompany() {return company; }public void setCompany(String company) {this.company = company; }public String getDepartment() {return department; }public void setDepartment(String department) {this.department = department; }public String getUserName() {return userName; }public void setUserName(String userName) {this.userName = userName; }public Integer getAreaRowSpan() {return areaRowSpan; }public void setAreaRowSpan(Integer areaRowSpan) {this.areaRowSpan = areaRowSpan; }public Integer getCompanyRowSpan() {return companyRowSpan; }public void setCompanyRowSpan(Integer companyRowSpan) {this.companyRowSpan = companyRowSpan; }public Integer getDepartmentRowSpan() {return departmentRowSpan; }public void setDepartmentRowSpan(Integer departmentRowSpan) {this.departmentRowSpan = departmentRowSpan; } }
3.4 导出相关类
package com.xincheng.cpm.common;/** * Created by hdwang on 2017/7/14. */public class ExcelData {private String value;//单元格的值private int colSpan = 1;//单元格跨几列private int rowSpan = 1;//单元格跨几行private boolean alignCenter;//单元格是否居中,默认不居中,如果选择是,则水平和上下都居中public boolean isAlignCenter() {return alignCenter; }public void setAlignCenter(boolean alignCenter) {this.alignCenter = alignCenter; }public String getValue() {return value; }public void setValue(String value) {this.value = value; }public int getColSpan() {return colSpan; }public void setColSpan(int colSpan) {this.colSpan = colSpan; }public int getRowSpan() {return rowSpan; }public void setRowSpan(int rowSpan) {this.rowSpan = rowSpan; } }
package com.xincheng.cpm.common;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.CellStyle;import org.apache.poi.ss.util.CellRangeAddress;import org.apache.poi.xssf.usermodel.XSSFFont;import org.apache.poi.xssf.usermodel.XSSFRow;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.util.List;/** * Created by hdwang on 2017/7/14. */public class ExcelUtil {/** * 生成excel工作簿 * @param sheetTitle sheet名称 * @param titles 标题 * @param rows 行数据 * @return 工作簿 */public XSSFWorkbook execute(String sheetTitle,String[] titles,List<List<ExcelData>> rows) {//定义工作簿XSSFWorkbook workbook = new XSSFWorkbook();//th样式CellStyle titleStyle = workbook.createCellStyle(); titleStyle.setBorderBottom((short) 1); titleStyle.setBorderRight((short)1); titleStyle.setBorderLeft((short)1); titleStyle.setBorderTop((short)1); titleStyle.setVerticalAlignment((short)1); titleStyle.setAlignment((short)2); XSSFFont font = workbook.createFont(); font.setBold(true); titleStyle.setFont(font);//td样式CellStyle style = workbook.createCellStyle(); style.setBorderBottom((short)1); style.setBorderRight((short)1); style.setBorderLeft((short)1); style.setBorderTop((short)1); style.setVerticalAlignment((short)1);//创建工作表XSSFSheet sheet = workbook.createSheet(sheetTitle); sheet.setDefaultRowHeightInPoints(20.0F);//创建标题行XSSFRow titleRow = sheet.createRow(0);for(int col=0;col<titles.length;col++) { //遍历列Cell cell = titleRow.createCell(col); cell.setCellStyle(titleStyle); cell.setCellValue(titles[col]);for(int row=0;row<rows.size();row++){ //遍历行int rowIndex = row+1; XSSFRow contentRow = sheet.getRow(rowIndex);if(contentRow == null){ contentRow = sheet.createRow(rowIndex); } ExcelData data = rows.get(row).get(col); Cell contentRowCell = contentRow.createCell(col); contentRowCell.setCellStyle(style); contentRowCell.setCellValue(data.getValue());//合并单元格if (data.getColSpan() > 1 || data.getRowSpan() > 1) { CellRangeAddress cra = new CellRangeAddress(rowIndex, rowIndex + data.getRowSpan() - 1, col, col + data.getColSpan() - 1); sheet.addMergedRegion(cra); } } }return workbook; } }
3.5 controller层
package com.xincheng.cpm.controller;import com.chenrd.common.excel.ExportExcel;import com.xincheng.cpm.common.*;import com.xincheng.cpm.entity.cpm.User;import com.xincheng.cpm.service.UserService;import com.xincheng.cpm.vo.IncomeDailyVO;import org.apache.commons.lang3.StringUtils;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.domain.Page;import org.springframework.data.domain.PageImpl;import org.springframework.data.domain.PageRequest;import org.springframework.data.domain.Pageable;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.OutputStream;import java.net.URLEncoder;import java.util.*;/** * Created by hdwang on 2017/6/19. */@Controller @RequestMapping("/home")public class HomeController { @Autowired UserService userService; @RequestMapping("")public String index(HttpSession session, ModelMap map, HttpServletRequest request){ User user = (User) session.getAttribute("user"); map.put("user",user);return "home"; } @RequestMapping(value="/query",method= RequestMethod.POST) @ResponseBodypublic TableData<Member> getUserByPage(PageParam pageParam, User user){ Page<Member> userPage = this.getMembers(pageParam); TableData<Member> datas = new TableData<>(); datas.setDraw(pageParam.getDraw()); datas.setStart(pageParam.getStart()); datas.setData(userPage.getContent()); datas.setRecordsFiltered((int)userPage.getTotalElements()); datas.setRecordsTotal((int)userPage.getTotalElements());return datas; }private Page<Member> getMembers(PageParam pageParam) {//1.模拟数据库查询Pageable pageable = new PageRequest(pageParam.getPage(), pageParam.getLength());long count = 6; List<Member> members = getMembersFromDb();//2.计算rowspanthis.countRowspan(members); Page<Member> memberPage = new PageImpl<Member>(members,pageable,count);return memberPage; }private void countRowspan(List<Member> members) { Map<String,Integer> propertyCountMap = this.countPropertyCount(members); List<String> hadGetKeys = new ArrayList<>(); //曾经取过的keyfor(Member member:members){ String areaKey = member.getArea(); String companyKey = areaKey+member.getCompany(); String departmentKey = companyKey+ member.getDepartment(); Integer areaCount = propertyCountMap.get(areaKey);if(areaCount == null){ member.setAreaRowSpan(1); }else{if(hadGetKeys.contains(areaKey)){ member.setAreaRowSpan(0); //曾经取过}else{ member.setAreaRowSpan(areaCount); //第一次取 hadGetKeys.add(areaKey); } } Integer companyCount = propertyCountMap.get(companyKey);if(companyCount == null){ member.setCompanyRowSpan(1); }else {if(hadGetKeys.contains(companyKey)){ member.setCompanyRowSpan(0); }else{ member.setCompanyRowSpan(companyCount); hadGetKeys.add(companyKey); } } Integer departmentCount = propertyCountMap.get(departmentKey);if(companyCount == null){ member.setDepartmentRowSpan(1); }else {if(hadGetKeys.contains(departmentKey)){ member.setDepartmentRowSpan(0); }else{ member.setDepartmentRowSpan(departmentCount); hadGetKeys.add(departmentKey); } } } }private List<Member> getMembersFromDb() { Member member1 = new Member("安徽","A","人力资源部"," 小红"); Member member2 = new Member("安徽","B","人力资源部"," 小明"); Member member3 = new Member("浙江","C","人力资源部"," 小君"); Member member4 = new Member("浙江","C","技术部"," 小王"); Member member5 = new Member("浙江","D","技术部"," 小李"); Member member6 = new Member("浙江","D","人力资源部"," 小刚"); List<Member> members = new ArrayList<>(); members.add(member1); members.add(member2); members.add(member3); members.add(member4); members.add(member5); members.add(member6);return members; }/** * 统计每个字段的每组成员个数 * @param rows 记录 * @return 每个字段的每组成员个数 */private Map<String,Integer> countPropertyCount(List<Member> rows){ Map<String,Integer> propertyCountMap = new HashMap<>();for(Member member:rows){// "area": 无父级分组String area = member.getArea();if(propertyCountMap.get(area) == null){ propertyCountMap.put(area,1); }else{int count = propertyCountMap.get(area); propertyCountMap.put(area,count+1); }// "company":有area父组String company = member.getCompany(); String uniqueParent = member.getArea(); String key = uniqueParent + company;if(propertyCountMap.get(key) == null){ propertyCountMap.put(key,1); }else{int count = propertyCountMap.get(key); propertyCountMap.put(key,count+1); }// "department": 有area,company这两个父组String department = member.getDepartment(); uniqueParent = member.getArea()+member.getCompany(); key = uniqueParent + department;if(propertyCountMap.get(key) == null){ propertyCountMap.put(key,1); }else{int count = propertyCountMap.get(key); propertyCountMap.put(key,count+1); } }return propertyCountMap; } @RequestMapping("/export")public void export(HttpServletResponse response) throws IOException { List<Member> members = this.getMembersFromDb();this.countRowspan(members); List<List<ExcelData>> rows = new ArrayList<>();for(Member member:members){ List<ExcelData> row = new ArrayList<>(); ExcelData col1 = new ExcelData(); col1.setValue(member.getArea()); col1.setRowSpan(member.getAreaRowSpan()); row.add(col1); ExcelData col2 = new ExcelData(); col2.setValue(member.getCompany()); col2.setRowSpan(member.getCompanyRowSpan()); row.add(col2); ExcelData col3 = new ExcelData(); col3.setValue(member.getDepartment()); col3.setRowSpan(member.getDepartmentRowSpan()); row.add(col3); ExcelData col4 = new ExcelData(); col4.setValue(member.getUserName()); row.add(col4); rows.add(row); } OutputStream outputStream = response.getOutputStream();try { String filename = URLEncoder.encode("员工" + ".xlsx", "UTF-8"); response.setContentType("application/vnd.ms-excel"); response.addHeader("Content-Disposition", "octet-stream;filename=" + filename); ExcelUtil excelUtil = new ExcelUtil(); XSSFWorkbook workbook = excelUtil.execute("sheet1",new String[]{"地区","公司","部门","员工姓名"},rows); workbook.write(outputStream); } finally {if (outputStream != null) outputStream.close(); } } }
导出excel功能使用poi类库实现。至此,页面展示和导出均OK!
以上是多种情况合并单元格的方法讲解的详细内容。更多信息请关注PHP中文网其他相关文章!

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

禅工作室 13.0.1
功能强大的PHP集成开发环境