• POI跨行导出excell表格实现.md


    # POI跨行导出excell表格实现
    ### 需求:需要导出父子级关系的元素,父级需要跨行显示,子级需要单独显示。


    ### 由于数据库中的数据存的是子级存父级的ID形式,所以需要将数据包装,自己将装在父级下的list中,本案例将会包装成五级子级形式。

    ### 第一步:首先写sql ,sql中要计算出父级需要跨的行数。(思路:首先自身内连接,计算出每一级需要跨的行数,在与主表相连将跨行数关联上去)

    ```xml

    <select id="findList" resultType="OcScope">
    SELECT
    a.* ,b.label as typeName,c.scope_name as parentName,
    case when a.level =1 then '评估维度'
    when a.level =2 then '评估类别'
    when a.level =3 then '评估项目'
    when a.level =4 then '评估内容'
    when a.level =5 then '问题'
    else '未知类别' end as levelName
    FROM oc_scope a left join oc_dict b on a.type=b.value and b.type="evaluation_dimension"
    left join oc_scope c on a.parent_id=c.id
    WHERE a.status = #{DEL_FLAG_NORMAL}
    <if test="scopeName != null and scopeName != ''">
    AND a.scope_name LIKE
    <if test="dbName == 'oracle'">'%'||#{scopeName}||'%'</if>
    <if test="dbName == 'mssql'">'%'+#{scopeName}+'%'</if>
    <if test="dbName == 'mysql'">CONCAT('%', #{scopeName}, '%')</if>
    </if>
    <if test="type != null and type != ''">
    AND a.type = #{type}
    </if>
    <if test="level != null and level != ''">
    AND a.level = #{level}
    </if>
    <if test="remark != null and remark != ''">
    AND a.remark = #{remark}
    </if>
    <if test="parentId != null and parentId != ''">
    AND a.parent_id = #{parentId}
    </if>

    <if test="scopeName != null and scopeName != ''">
    AND a.scope_name LIKE CONCAT(CONCAT('%',#{scopeName},'%'))
    </if>
    ORDER BY a.type,a.level, a.sort
    </select>


    ```
    ### 第二步:编写实体类(OcScope):

    ```java
    private String type;
    private String level;
    private OcScope parent;
    private String parentId;
    private String parentName;
    private String grandFatherName;
    private String module;
    private String typeName;
    private String scopeName;
    private String p1ScopeName;
    private String p2ScopeName;
    private String p3ScopeName;
    private String p4ScopeName;
    private Integer count1;
    private Integer count2;
    private Integer count3;
    private Integer count4;
    private String activityCatalogue;
    private String sow;
    private String activityCataloguePosition;
    private String sowPosition;
    private String remark;
    private String sort;
    private Double weights;
    private Double p1Weights;
    private Double p2Weights;
    private Double p3Weights;
    private Double p4Weights;
    private Double remainWeights;
    private String levelName;
    private String showStatus;
    .......

    ```

    ### 第三步:编写mapper层:

    ```java
    public List<OcScope> findCountList(OcScope ocScope);
    ```

    ### 第四步:编写server层:
    一.需要先包装数据,将子级包装到list中
    1.写一个实体类(ExcelDataBo)包装数据:

    ```java
    public class ExcelDataBo {
    private String id;
    private String name;
    private String pid;
    private Double weights;
    private Integer count;
    private String level;
    private List<ExcelDataBo> subList;
    ...........
    }

    ```


    2.包装数据

    ```java
    public List<ExcelDataBo> getExcelDataList() {
    List<ExcelDataBo> boList = Lists.newArrayList();
    //从数据库中查询出level=1的数据
    OcScope ocScope = new OcScope();
    ocScope.setLevel("1");
    List<OcScope> list1 = dao.findList(ocScope);
    //从数据库中查询出level=2的数据
    ocScope.setLevel("2");
    List<OcScope> list2 = dao.findList(ocScope);
    //从数据库中查询出level=3的数据
    ocScope.setLevel("3");
    List<OcScope> list3 = dao.findList(ocScope);
    //从数据库中查询出level=4的数据
    ocScope.setLevel("4");
    List<OcScope> list4 = dao.findList(ocScope);
    //从数据库中查询出level=5的数据
    ocScope.setLevel("5");
    List<OcScope> list5 = dao.findList(ocScope);

    int count1=0,count2=0,count3=0,count4=0;
    for (OcScope oc : list1) { // level 1
    if (oc.getLevel().equals("1")) {
    ExcelDataBo bo = new ExcelDataBo();
    bo.setId(oc.getId());
    bo.setPid(oc.getParentId());
    bo.setName(oc.getScopeName());
    bo.setWeights(oc.getWeights());
    count1=0; //首先赋值为0,count1:用于记录该项需要跨的行数

    List<ExcelDataBo> boList2 = Lists.newArrayList();
    for (OcScope oc2 : list2) { // level 2
    if (oc2.getParentId().equals(bo.getId())) {
    ExcelDataBo bo2 = new ExcelDataBo();
    bo2.setId(oc2.getId());
    bo2.setPid(oc2.getParentId());
    bo2.setName(oc2.getScopeName());
    bo2.setWeights(oc2.getWeights());
    count2=0; //首先赋值为0,count2:用于记录该项需要跨的行数
    List<ExcelDataBo> boList3 = Lists.newArrayList();
    for (OcScope oc3 : list3) { // level 3
    if (oc3.getParentId().equals(bo2.getId())) {
    ExcelDataBo bo3 = new ExcelDataBo();
    bo3.setId(oc3.getId());
    bo3.setPid(oc3.getParentId());
    bo3.setName(oc3.getScopeName());
    bo3.setWeights(oc3.getWeights());
    count3=0; //首先赋值为0,count3:用于记录该项需要跨的行数
    List<ExcelDataBo> boList4 = Lists.newArrayList();
    for (OcScope oc4 : list4) { // level 4
    if (oc4.getParentId().equals(bo3.getId())) {
    ExcelDataBo bo4 = new ExcelDataBo();
    bo4.setId(oc4.getId());
    bo4.setPid(oc4.getParentId());
    bo4.setName(oc4.getScopeName());
    bo4.setWeights(oc4.getWeights());
    count4=0; //首先赋值为0,count4:用于记录该项需要跨的行数
    List<ExcelDataBo> boList5 = Lists.newArrayList();
    for (OcScope oc5 : list5) { // level 5
    if (oc5.getParentId().equals(bo4.getId())) {
    ExcelDataBo bo5 = new ExcelDataBo();
    bo5.setId(oc5.getId());
    bo5.setPid(oc5.getParentId());
    bo5.setName(oc5.getScopeName());
    bo5.setWeights(oc5.getWeights());
    bo5.setCount(1); //直接赋值1,这是最底层数据不存跨行的问题
    boList5.add(bo5);
    count4++;
    }
    }
    if(count4==0) //有可能其下没有list子级,但是本身需要跨一行
    count4=1;
    bo4.setCount(count4);
    bo4.setSubList(boList5);
    boList4.add(bo4);
    count3 = count3+count4;
    }
    }
    if(count3==0)//有可能其下没有list子级,但是本身需要跨一行
    count3=1;
    bo3.setCount(count3);
    bo3.setSubList(boList4);
    boList3.add(bo3);
    count2 = count2+count3;
    }
    }
    if(count2==0) //有可能其下没有list子级,但是本身需要跨一行
    count2=1;
    bo2.setCount(count2);
    bo2.setSubList(boList3);
    boList2.add(bo2);
    count1 = count1 + count2;
    }
    }
    if(count1==0) //有可能其下没有list子级,但是本身需要跨一行
    count1=1;
    bo.setCount(count1);
    bo.setSubList(boList2);
    boList.add(bo);
    }

    }
    return boList;
    }

    ```

    二.将数据写在excel中去

    1.编写工具类(ExcelUtils),注:该类可直接复制我的就行

    ```java

    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Enumeration;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.zip.CRC32;
    import java.util.zip.CheckedOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    import java.util.zip.ZipOutputStream;

    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.CellStyle;
    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.ss.util.CellRangeAddress;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XMLWriter;

    import com.google.common.collect.Maps;
    import com.thinkgem.jeesite.common.utils.IdGen;

    public class ExcelUtils {
    /**
    * 根据路径获取Workbook
    * @param filePath excel文件路径
    * @return
    * @throws Exception
    */
    public static Workbook getWorkbook(String filePath) throws Exception{
    int version = 0;
    if (filePath.endsWith(".xls")) {
    version = 2003;
    }else if (filePath.endsWith(".xlsx")) {
    version = 2007;
    }else {
    throw new Exception("Incorrect file format,Only allowed '.xls,.xlsx' extension");
    }
    Workbook workbook = null;
    switch (version) {
    case 2003:
    POIFSFileSystem fs = new POIFSFileSystem(new BufferedInputStream(new FileInputStream(filePath)));
    workbook = new HSSFWorkbook(fs);
    break;

    case 2007:
    workbook = new XSSFWorkbook(new BufferedInputStream(new FileInputStream(filePath)));
    break;
    }
    return workbook;
    }

    /**
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
    long start = System.currentTimeMillis();
    Workbook wb = ExcelUtils.getWorkbook("D:/temp/002.xlsx");
    XSSFSheet sheet = (XSSFSheet) wb.getSheet("Security");
    int last = sheet.getLastRowNum();
    System.out.println("rownum:"+last);
    System.out.println("phy rownum:"+sheet.getPhysicalNumberOfRows());
    System.out.printf("删除共花费%s毫秒 ",System.currentTimeMillis() - start);

    System.out.println(sheet.getRow(1).getCell(0).getStringCellValue().equals("Level 4 (Product)"));

    Field nameField = XSSFSheet.class.getDeclaredField("_rows");
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL);//把 final从修饰集中除掉
    nameField.setAccessible(true); //允许访问 private
    Object object = nameField.get(sheet);
    SortedMap<Integer, XSSFRow> rowMap = (SortedMap<Integer, XSSFRow>) object;
    Integer index = new Integer(4);
    int idx = rowMap.headMap(index).size();
    Field worksheetField = XSSFSheet.class.getDeclaredField("worksheet");
    worksheetField.setAccessible(true);
    nameField.setAccessible(true); //允许访问 private
    CTWorksheet worksheet = (CTWorksheet) worksheetField.get(sheet);
    worksheet.getSheetData().removeRow(idx);
    rowMap.remove(index);
    System.out.println(((SortedMap<Integer, XSSFRow>)object).keySet());

    List<XSSFRow> list = new ArrayList<XSSFRow>();
    for (int i=0;i<last;i++) {
    if (i==5) {
    continue;
    }
    list.add(sheet.getRow(i));
    }

    int sheetIndex = wb.getSheetIndex(sheet);
    String sheetname = sheet.getSheetName();
    //wb.removeSheetAt(sheetIndex);
    Sheet createSheet = wb.createSheet(sheetname+"2");
    wb.setSheetOrder(sheetname+"2", sheetIndex);

    for (int i=1;i<list.size()+1;i++) {
    Row row = sheet.getRow(i);
    XSSFRow createRow = (XSSFRow) createSheet.createRow(i);
    createRow.copyRowFrom(row, new CellCopyPolicy());
    }

    last = sheet.getLastRowNum();
    System.out.println("rownum:"+last);
    start = System.currentTimeMillis();
    wb.write(new FileOutputStream("D:/temp/007-test.xlsx"));
    System.out.printf("写共花费%s毫秒",System.currentTimeMillis() - start);
    wb.close();
    }
    * @throws Exception
    */

    public static void testZipFiles(String filePath) throws Exception{
    zipFiles("D:/temp/test/99b6d26cbea34e3890b9a16b5b2a6676","D:/temp/test/test.xlsx");
    }

    public static void main(String[] args) throws Exception {
    String unzipExcel = unzipExcel("D:/temp/test/0010.xlsx","D:/temp/test/");
    System.out.println(unzipExcel);
    }

    @SuppressWarnings("unchecked")
    public static void editXml(String filePath) throws Exception{
    long start = System.currentTimeMillis();
    SAXReader reader = new SAXReader();
    Document document = reader.read(new File(filePath));
    Element rootElement = document.getRootElement();
    Iterator<Element> elements = rootElement.element("sheetData").elementIterator("row");
    int index = 0;
    while (elements.hasNext()) {
    Element row = elements.next();
    index++;
    String rownum = index+"";
    if (index>2) {
    //获取第一列
    Element col = row.element("c");
    if (col.element("v")==null) {
    row.getParent().remove(row);
    index--;
    continue;
    }

    row.addAttribute("r", rownum);

    List<Element> cols = row.elements("c");
    for (Element element : cols) {
    String colnum = element.attributeValue("r");
    //数字匹配
    Matcher matcher = Pattern.compile("\d+").matcher(colnum);
    matcher.find();
    String colno = matcher.group();
    colnum = colnum.replace(colno, "");
    element.addAttribute("r", colnum + rownum);
    }
    }
    }

    /**
    List<Element> elements = rootElement.element("sheetData").elements("row");
    for (int i = 0; i < elements.size(); i++) {
    Element row = elements.get(i);
    int index = i+1;
    String rownum = index+"";
    if (!row.attributeValue("r").equals(rownum)) {
    row.addAttribute("r", index+"");
    }
    List<Element> cols = row.elements("c");
    for (Element element : cols) {
    String colnum = element.attributeValue("r");
    //数字匹配
    Matcher matcher = Pattern.compile("\d+").matcher(colnum);
    matcher.find();
    String colno = matcher.group();
    colnum = colnum.replace(colno, "");
    element.addAttribute("r", colnum + rownum);
    }

    }
    */
    OutputFormat outputFormat = OutputFormat.createPrettyPrint();
    outputFormat.setEncoding("UTF-8"); // 指定XML编码
    outputFormat.setNewlines(false); //设置是否换行
    outputFormat.setIndent(false); //设置是否缩进
    XMLWriter writer = new XMLWriter(new FileWriter("D:/temp/0010/xl/worksheets/test.xml"), outputFormat);
    writer.write(document);
    writer.close();
    document.clone();
    System.out.println(String.format("共耗时%s ms", System.currentTimeMillis()-start));
    }

    @SuppressWarnings("unchecked")
    public static void removeFromXml(String xmlFilePath,Map<Integer, Object> indexs) throws Exception{
    long start = System.currentTimeMillis();
    SAXReader reader = new SAXReader();
    File xmlFile = new File(xmlFilePath);
    Document document = reader.read(xmlFile);
    Element rootElement = document.getRootElement();
    Iterator<Element> elements = rootElement.element("sheetData").elementIterator("row");
    int index = 0;
    int i = 0;
    for (;elements.hasNext();i++) {
    Element row = elements.next();
    index++;
    String rownum = index+"";
    if (i>=2) {
    if (indexs.containsKey(i)) {
    row.getParent().remove(row);
    index--;
    continue;
    }

    row.addAttribute("r", rownum);

    List<Element> cols = row.elements("c");
    for (Element element : cols) {
    String colnum = element.attributeValue("r");
    //数字匹配
    Matcher matcher = Pattern.compile("\d+").matcher(colnum);
    matcher.find();
    String colno = matcher.group();
    colnum = colnum.replace(colno, "");
    element.addAttribute("r", colnum + rownum);
    }
    }
    }

    OutputFormat outputFormat = OutputFormat.createPrettyPrint();
    outputFormat.setEncoding("UTF-8"); // 指定XML编码
    outputFormat.setNewlines(false); //设置是否换行
    outputFormat.setIndent(false); //设置是否缩进

    //创建临时文件
    String tempFileName = IdGen.uuid();
    File tempFile = new File(xmlFilePath.replace(xmlFile.getName(), tempFileName+".xml"));

    XMLWriter writer = new XMLWriter(new FileOutputStream(tempFile), outputFormat);
    writer.write(document);
    writer.close();
    //删除原来xml
    try {
    xmlFile.delete();
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    //重命名修改后的xml
    tempFile.renameTo(new File(xmlFilePath));
    System.out.println(String.format("共耗时%s ms", System.currentTimeMillis()-start));
    }

    /**
    * 解压excel文件到指定临时目录,并返回解压后的临时目录
    * @param excelFilePath
    * @param tempPath
    * @return
    * @throws Exception
    */
    public static String unzipExcel (String excelFilePath,String tempPath) throws Exception{
    String tempDir = tempPath;
    String dirName = IdGen.uuid();
    ZipFile zipFile = null;
    try {
    zipFile = new ZipFile(new File(excelFilePath));
    if (tempPath.endsWith("/")||tempPath.endsWith(File.separator)) {
    tempDir = tempDir + dirName + File.separator;
    }else {
    tempDir = tempDir + File.separator + dirName + File.separator;
    }
    unZipFiles(zipFile, tempDir);
    } catch (Exception e) {
    throw e;
    }finally{
    if (zipFile!=null) {
    zipFile.close();
    }
    }
    return tempDir.replaceAll("\\", "/");
    }

    @SuppressWarnings("rawtypes")
    private static void unZipFiles(ZipFile zipFile,String descDir)throws IOException{
    for(Enumeration entries = zipFile.entries();entries.hasMoreElements();){
    ZipEntry entry = (ZipEntry)entries.nextElement();
    String zipEntryName = entry.getName();
    InputStream in = zipFile.getInputStream(entry);
    String outPath = (descDir+zipEntryName).replaceAll("\\", "/");;
    //判断路径是否存在,不存在则创建文件路径
    File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
    if(!file.exists()){
    file.mkdirs();
    }
    //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
    if(new File(outPath).isDirectory()){
    continue;
    }
    //输出文件路径信息
    System.out.println(outPath);

    OutputStream out = new FileOutputStream(outPath);
    byte[] buf1 = new byte[1024];
    int len;
    while((len=in.read(buf1))>0){
    out.write(buf1,0,len);
    }
    in.close();
    out.close();
    }
    System.out.println("******************unzip scuccess********************");
    }

    // public static void unZipFiles(File zipFile,String descDir)throws IOException{
    // File pathFile = new File(descDir);
    // if(!pathFile.exists()){
    // pathFile.mkdirs();
    // }
    // unZipFiles(zipFile, descDir);
    // }

    public static void zipFiles(String inputFileName,String outPutFileName) throws IOException {
    File file = new File(inputFileName);
    if (!file.exists()){
    throw new RuntimeException(inputFileName + "not exists!");
    }
    String rootPath = inputFileName;

    if (inputFileName.endsWith("/")) {
    rootPath = inputFileName.substring(0,inputFileName.lastIndexOf("/"));
    }
    FileOutputStream fileOutputStream = null;
    CheckedOutputStream cos = null;
    ZipOutputStream out = null;
    try {
    fileOutputStream = new FileOutputStream(outPutFileName);
    cos = new CheckedOutputStream(fileOutputStream,new CRC32());
    out = new ZipOutputStream(cos);
    zipByType(file, out, "",rootPath);

    } catch (Exception e) {
    e.printStackTrace();
    throw new RuntimeException(e);
    }finally {
    if (out!=null) {
    out.close();
    }
    if (fileOutputStream!=null) {
    fileOutputStream.close();
    }
    }
    }

    /**
    * 判断是目录还是文件,根据类型(文件/文件夹)执行不同的压缩方法
    */
    private static void zipByType(File file, ZipOutputStream out, String basedir,String rootDir) {
    /* 判断是目录还是文件 */
    if (file.isDirectory()) {
    zipDirectory(file, out, "",rootDir);
    } else {
    zipFile(file, out, basedir,rootDir);
    }
    }

    /**
    * 压缩一个目录
    */
    private static void zipDirectory(File dir, ZipOutputStream out, String basedir,String rootDir) {
    if (!dir.exists()){
    return;
    }
    File[] files = dir.listFiles();
    for (int i = 0; i < files.length; i++) {
    /* 递归 */
    zipByType(files[i], out, basedir + dir.getName() + "/",rootDir);
    }
    }

    /**
    * 压缩一个文件
    */
    private static void zipFile(File file, ZipOutputStream out, String basedir, String rootDir) {
    if (!file.exists()) {
    return;
    }
    try {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    //获取文件相对于压缩文件夹根目录的子路径
    String subPath = file.getAbsolutePath();
    int index = subPath.indexOf(file.getAbsolutePath());
    if (index != -1)
    {
    subPath = subPath.substring(rootDir.length() + File.separator.length());
    }
    ZipEntry entry = new ZipEntry(subPath);
    out.putNextEntry(entry);
    int count;
    byte data[] = new byte[4096];
    while ((count = bis.read(data, 0, 4096)) != -1) {
    out.write(data, 0, count);
    }
    bis.close();
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }

    /**
    * 删除Excel中需要保留Sheet之外的其他Sheet,返回Workbook对象
    * @param filePath Excel文件路径
    * @param sheetName 需要保留的Sheet名称
    * @return 返回只包含保留Sheet的Workbook对象
    * @throws Exception
    */
    public static Workbook getSingleSheetWorkbook(String filePath,String sheetName) throws Exception {
    Workbook workbook = getWorkbook(filePath);
    int numberOfSheets = workbook.getNumberOfSheets();
    String[] sheetNames = new String[numberOfSheets];
    for (int i = 0; i < numberOfSheets; i++) {
    sheetNames[i] = workbook.getSheetName(i);
    }
    for (String name : sheetNames) {
    if (!sheetName.equalsIgnoreCase(name)) {
    workbook.removeSheetAt(workbook.getSheetIndex(name));
    }
    }
    return workbook;
    }

    /**
    * 删除Excel中需要保留Sheet之外的其他Sheet,返回Workbook对象
    * @param workbook Workbook对象
    * @param sheets 需要保留的Sheet名称数组
    * @return 返回只包含保留Sheet的Workbook对象
    * @throws Exception
    */
    public static Workbook getSheetWorkbook(Workbook workbook,String[] sheets) throws Exception {
    int numberOfSheets = workbook.getNumberOfSheets();
    String[] sheetNames = new String[numberOfSheets];
    for (int i = 0; i < numberOfSheets; i++) {
    sheetNames[i] = workbook.getSheetName(i);
    }
    Map<String, Object> sheetMap = Maps.newHashMap();
    for (String sheet : sheets) {
    sheetMap.put(sheet.toLowerCase(), null);
    }
    for (String name : sheetNames) {
    if (!sheetMap.containsKey(name.toLowerCase())) {
    workbook.removeSheetAt(workbook.getSheetIndex(name));
    }
    }
    return workbook;
    }

    /**
    * 复制单元格样式
    * @param wb 新建单元格所在Workbook
    * @param scrCell 源单元格,需要复制的单元格
    * @param destCell 目标单元格,新建单元格
    */
    public static void copyCellStyle(Workbook wb,Cell scrCell, Cell destCell) {
    CellStyle newStyle = wb.createCellStyle();
    copyStyle(scrCell.getCellStyle(), newStyle);
    destCell.setCellStyle(newStyle);
    }

    // 单元格样式复制函数
    private static void copyStyle(CellStyle oldStyle, CellStyle newStyle) {
    newStyle.setAlignment(oldStyle.getAlignment());
    //边框和边框颜色
    newStyle.setBorderBottom(oldStyle.getBorderBottom());
    newStyle.setBorderLeft(oldStyle.getBorderLeft());
    newStyle.setBorderRight(oldStyle.getBorderRight());
    newStyle.setBorderTop(oldStyle.getBorderTop());
    newStyle.setTopBorderColor(oldStyle.getTopBorderColor());
    newStyle.setBottomBorderColor(oldStyle.getBottomBorderColor());
    newStyle.setRightBorderColor(oldStyle.getRightBorderColor());
    newStyle.setLeftBorderColor(oldStyle.getLeftBorderColor());

    //背景和前景
    newStyle.setFillBackgroundColor(oldStyle.getFillBackgroundColor());
    newStyle.setFillForegroundColor(oldStyle.getFillForegroundColor());

    newStyle.setDataFormat(oldStyle.getDataFormat());
    newStyle.setFillPattern(oldStyle.getFillPattern());
    // newStyle.setFont(oldStyle.getFont(null));
    newStyle.setHidden(oldStyle.getHidden());
    newStyle.setIndention(oldStyle.getIndention());//首行缩进
    newStyle.setLocked(oldStyle.getLocked());
    newStyle.setRotation(oldStyle.getRotation());//旋转
    newStyle.setVerticalAlignment(oldStyle.getVerticalAlignment());
    newStyle.setWrapText(oldStyle.getWrapText());
    }

    public static void copyRowStyle(Workbook wb,Row scrRow,Row destRow){
    for (int i=0;i<destRow.getLastCellNum();i++) {
    Cell cell = scrRow.getCell(i);
    if (cell!=null) {
    CellStyle newStyle = wb.createCellStyle();
    newStyle.cloneStyleFrom(scrRow.getCell(i).getCellStyle());
    destRow.getCell(i).setCellStyle(newStyle);
    }
    }
    }

    /**
    * 判断指定的单元格是否是合并单元格,如果是则返回合并单元格index,不是则返回-1
    * @param sheet
    * @param row 行下标
    * @param column 列下标
    * @return
    */
    public static int isMergedRegion(Sheet sheet,int row ,int column) {
    int sheetMergeCount = sheet.getNumMergedRegions();
    for (int i = 0; i < sheetMergeCount; i++) {
    CellRangeAddress range = sheet.getMergedRegion(i);
    int firstColumn = range.getFirstColumn();
    int lastColumn = range.getLastColumn();
    int firstRow = range.getFirstRow();
    int lastRow = range.getLastRow();
    if(row >= firstRow && row <= lastRow){
    if(column >= firstColumn && column <= lastColumn){
    return i;
    }
    }
    }
    return -1;
    }

    /**
    * 获取合并单元格的值
    * @param sheet
    * @param row
    * @param column
    * @return
    */
    public static String getMergedRegionValue(Sheet sheet ,int row , int column){
    int sheetMergeCount = sheet.getNumMergedRegions();

    for(int i = 0 ; i < sheetMergeCount ; i++){
    CellRangeAddress ca = sheet.getMergedRegion(i);
    int firstColumn = ca.getFirstColumn();
    int lastColumn = ca.getLastColumn();
    int firstRow = ca.getFirstRow();
    int lastRow = ca.getLastRow();
    if(row >= firstRow && row <= lastRow){
    if(column >= firstColumn && column <= lastColumn){
    Row fRow = sheet.getRow(firstRow);
    Cell fCell = fRow.getCell(firstColumn);
    return getCellValue(fCell) ;
    }
    }
    }

    return null ;
    }

    /**
    * 获取单元格的值
    * @param cell
    * @return
    */
    public static String getCellValue(Cell cell) {
    if (cell == null)
    return "";
    if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
    return cell.getStringCellValue();
    } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
    return String.valueOf(cell.getBooleanCellValue());
    } else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
    return cell.getCellFormula();
    } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    return String.valueOf(cell.getNumericCellValue());
    }
    return "";
    }


    /**
    * 合并单元格
    * @param sheet
    * @param firstRow 开始行
    * @param lastRow 结束行
    * @param firstCol 开始列
    * @param lastCol 结束列
    */
    public static void mergeRegion(Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
    sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
    }

    }
    ```
    2.将数据写到excel中去

    ```java
    //注入地址,防止硬编码问题
    @Value("${excel.temp.dir}")
    private String tempDir;

    @SuppressWarnings("unchecked")
    public void exportEvaluationTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception {
    Workbook workbook = null;
    File destFile = null;
    try {
    //保证模板文件放在项目中,或者自己的c/d盘中,(本例是放在项目中的) 获取最新Excel模板
    String classpath = exportEvaluationTemplate.class.getClassLoader().getResource("").getPath(); //获取当类的位置
    String templatePath = classpath + "/templates/"; //类所在的文件夹中新建一个templates包用来存储文件的包

    // templatePath:文件的地址
    File srcFile = new File(templatePath+"Evaluation_Template.xlsx"); //拿到文件
    String tempName = "Evaluation_Template_" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";
    destFile = new File(tempDir + "/" + tempName);
    FileUtils.copyFile(srcFile, destFile);
    workbook = ExcelUtils.getWorkbook(destFile.getPath());
    Sheet sheet = workbook.getSheetAt(0);
    // 得到需要写入的数据
    List<ExcelDataBo> rowList = getExcelDataList();
    // 统计信息从第2行,第一列开始写
    int rowIndex = 1; // 行
    int cellIndex = 0; //列
    for (ExcelDataBo bo : rowList) {
    String cellName = bo.getName();
    Double cellWeights = bo.getWeights();
    int rowMgrCnt = bo.getCount(); // 合并行数
    cellIndex = 0;
    //将数据写入表格
    sheet.getRow(rowIndex).getCell(cellIndex).setCellValue(cellName);
    //合并所需要的行或者列
    if(rowMgrCnt > 1) //如果rowMgrCnt<1,就没有必要合并单元格了
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, cellIndex, cellIndex);
    cellIndex++;
    sheet.getRow(rowIndex).getCell(cellIndex).setCellValue(cellWeights);
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, cellIndex, cellIndex);
    List<ExcelDataBo> boList2 = bo.getSubList();
    if(boList2!=null && boList2.size()>0 ){
    for (ExcelDataBo bo2 : boList2) {
    rowMgrCnt = bo2.getCount(); // 合并行

    int c1=cellIndex;
    c1++;
    sheet.getRow(rowIndex).getCell(c1).setCellValue(bo2.getName());
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c1, c1);
    c1++;
    // sheet.getRow(rowIndex).getCell(c1).setCellValue(bo2.getWeights());
    if(bo2.getWeights()!=null && !bo2.getWeights().equals("") )
    {
    sheet.getRow(rowIndex).getCell(c1).setCellValue(bo2.getWeights());
    }else{
    sheet.getRow(rowIndex).getCell(c1).setCellValue(0);
    }
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c1, c1);
    List<ExcelDataBo> boList3 = bo2.getSubList();
    if(boList3!=null && boList3.size()>0 ){
    for (ExcelDataBo bo3 : boList3) {
    rowMgrCnt = bo3.getCount(); // 合并行
    int c2=c1;
    c2++;
    sheet.getRow(rowIndex).getCell(c2).setCellValue(bo3.getName());
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c2, c2);
    c2++;
    if(bo3.getWeights()!=null && !bo3.getWeights().equals("") )
    {
    sheet.getRow(rowIndex).getCell(c2).setCellValue(bo3.getWeights());
    }else{
    sheet.getRow(rowIndex).getCell(c2).setCellValue(0);
    }
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c2, c2);

    List<ExcelDataBo> boList4 = bo3.getSubList();
    if(boList4!=null && boList4.size()>0 ){
    for (ExcelDataBo bo4 : boList4) {
    rowMgrCnt = bo4.getCount(); // 合并行

    int c3=c2;
    c3++;
    sheet.getRow(rowIndex).getCell(c3).setCellValue(bo4.getName());
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c3, c3);
    c3++;
    if(bo4.getWeights()!=null && !bo4.getWeights().equals("") )
    {
    sheet.getRow(rowIndex).getCell(c3).setCellValue(bo4.getWeights());
    }else{
    sheet.getRow(rowIndex).getCell(c3).setCellValue(0);
    }
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c3, c3);

    List<ExcelDataBo> boList5 = bo4.getSubList();
    if(boList5!=null && boList5.size()>0 ){
    for (ExcelDataBo bo5 : boList5) {
    rowMgrCnt = 1; // 合并行
    int c4=c3;
    c4++;
    sheet.getRow(rowIndex).getCell(c4).setCellValue(bo5.getName());
    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c4, c4);
    c4++;
    if(bo5.getWeights()!=null && !bo5.getWeights().equals("") )
    {
    sheet.getRow(rowIndex).getCell(c4).setCellValue(bo5.getWeights());
    }else{
    sheet.getRow(rowIndex).getCell(c4).setCellValue(0);
    }

    if(rowMgrCnt > 1)
    ExcelUtils.mergeRegion(sheet, rowIndex, rowIndex + rowMgrCnt - 1, c4, c4);
    //将行数怎家
    rowIndex=rowIndex+rowMgrCnt;
    }
    }else{ //进入else就是等于说是rowMgrCnt=0,输出表格需要换行开始下一行的数据输出。
    rowIndex = rowIndex+1;
    }

    }

    }else{
    rowIndex = rowIndex+1;
    }
    }
    }else{
    rowIndex = rowIndex+1;
    }
    }

    }else{
    rowIndex = rowIndex+rowMgrCnt;
    }

    }
    OutputStream wos = null;
    try {
    wos = new FileOutputStream(destFile);
    workbook.write(wos);
    } catch (Exception e) {
    throw e;
    } finally {
    if (wos != null) {
    wos.close();
    }
    }
    FileUtils.downFile(destFile, request, response);
    } catch (Exception e) {
    throw e;
    } finally {
    if (workbook != null) {
    workbook.close();
    }
    if (destFile != null) {
    try {
    destFile.delete();
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }
    }
    }
    ```


    ### 第五步:编写controller层:

    ```java
    /**
    * 表单导出方法
    * @param request
    * @param response
    * @throws Exception
    */
    @RequestMapping(value = "export")
    public void exportEvaluationTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception {

    ocScopeService.exportEvaluationTemplate(request,response);

    }

    ```

  • 相关阅读:
    多线程(6)线程属性
    多线程(五) Thread和Object中线程相关方法
    面试汇总
    多线程(4)线程生命周期
    多线程(3) 多线程之线程的停止和中断
    springboot(6)redis缓存
    软件安装(总)
    redis分布式锁
    第一天
    Thinkphp5高级进阶教程
  • 原文地址:https://www.cnblogs.com/jiajialeps/p/10311966.html
Copyright © 2020-2023  润新知