Pre Merge pull request !222 from 孤舟烟雨/auto-494979-dev-094ab998

This commit is contained in:
孤舟烟雨 2022-09-15 02:07:54 +00:00 committed by Gitee
commit 4bef092c0e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 387 additions and 3 deletions

View File

@ -0,0 +1,33 @@
package com.ruoyi.common.excel.builder;
import com.ruoyi.common.excel.common.SheetModel;
import lombok.Getter;
/**
* 单元格信息构建器
*
* @author liyang
**/
@Getter
public abstract class CellModelBuilder extends SheetModelBuilder {
/**
* 列索引
*/
protected final int colIndex;
/**
* 行索引
*/
protected final int rowIndex;
protected CellModelBuilder(String sheetName, int rowIndex, int colIndex) {
super(sheetName);
this.rowIndex = rowIndex;
this.colIndex = colIndex;
}
/**
* 具体构建方法
* @return
*/
@Override
abstract protected SheetModel build() ;
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.common.excel.builder;
import com.ruoyi.common.excel.common.SheetModel;
import lombok.Getter;
/**
* sheet页信息构建器
*
* @author liyang
**/
@Getter
public abstract class SheetModelBuilder {
/**
* sheet名称
*/
protected final String sheetName;
protected SheetModelBuilder(String sheetName) {
this.sheetName = sheetName;
}
/**
* 具体构建方法
* @return
*/
abstract protected SheetModel build() ;
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.common.excel.common;
import com.ruoyi.common.excel.builder.CellModelBuilder;
import lombok.Getter;
/**
* 单元格信息
*
* @author liyang
*/
@Getter
public class SheetCellModel extends SheetModel {
/**
* 列索引
*/
protected int colIndex;
/**
* 行索引
*/
protected int rowIndex;
public SheetCellModel(CellModelBuilder cellModelBuilder) {
super(cellModelBuilder);
this.rowIndex = cellModelBuilder.getRowIndex();
this.colIndex = cellModelBuilder.getColIndex();
}
protected SheetCellModel(){
}
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.common.excel.common;
import com.ruoyi.common.excel.builder.SheetModelBuilder;
import lombok.Getter;
/**
* sheet页信息
*
* @author liyang
*/
@Getter
public class SheetModel {
/**
* sheet名称
*/
protected String sheetName;
public SheetModel(SheetModelBuilder sheetModelBuilder) {
this.sheetName = sheetModelBuilder.getSheetName();
}
protected SheetModel() {
}
}

View File

@ -0,0 +1,90 @@
package com.ruoyi.common.excel.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.ruoyi.common.excel.model.CommentModel;
import com.ruoyi.common.utils.poi.PoiExcelUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义批注处理器
*
* @author liyang
*/
public class CustomCommentWriteHandler implements RowWriteHandler {
/**
* sheet页名称列表
*/
private List<String> sheetNameList;
List<CommentModel> commentList = new ArrayList<>();
/**
* 自定义批注适配器构造方法
*
* @param commentList 批注信息
* @param extension 文件后缀xlsxxls
*/
public CustomCommentWriteHandler(List<CommentModel> commentList, String extension) {
if (CollUtil.isEmpty(commentList)) {
return;
}
//文件不为指定的格式时默认为Xlsx
if (StrUtil.equals(extension, "xlsx") == false && StrUtil.equals(extension, "xls") == false) {
extension = "xlsx";
}
this.commentList = commentList.stream().filter(x ->
StrUtil.isNotBlank(x.getSheetName()) && x.getColIndex() >=0 && x.getRowIndex() >= 0 && StrUtil.isNotBlank(x.getCommentContent())
).collect(Collectors.toList());
sheetNameList = this.commentList.stream().map(x -> x.getSheetName()).distinct().collect(Collectors.toList());
this.extension = extension;
}
/**
* 文档后缀名
*/
private String extension;
@Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
Integer relativeRowIndex, Boolean isHead) {
Sheet sheet = writeSheetHolder.getSheet();
//不需要添加批注或者当前sheet页不需要添加批注
if (CollUtil.isEmpty(commentList) || sheetNameList.contains(sheet.getSheetName()) == false) {
return;
}
//获取当前行的批注信息
List<CommentModel> rowCommentList = commentList.stream().filter(x ->
StrUtil.equals(x.getSheetName(), sheet.getSheetName())
&& StrUtil.equals(String.valueOf(relativeRowIndex), String.valueOf(x.getRowIndex()))).collect(Collectors.toList());
//当前行没有批注信息
if (CollUtil.isEmpty(rowCommentList)) {
return;
}
List<Integer> colIndexList = rowCommentList.stream().map(x -> x.getColIndex()).distinct().collect(Collectors.toList());
for (Integer colIndex : colIndexList) {
//同一单元格的批注信息
List<CommentModel> cellCommentList = rowCommentList.stream().filter(x ->
StrUtil.equals(String.valueOf(colIndex), String.valueOf(x.getColIndex()))).collect(Collectors.toList());
if (CollUtil.isEmpty(cellCommentList)) {
continue;
}
//批注内容拼成一条
String commentContent = cellCommentList.stream().map(x -> x.getCommentContent()).collect(Collectors.joining());
Cell cell = row.getCell(colIndex);
PoiExcelUtil.addComment(cell, commentContent, extension);
}
//删除批注信息
commentList.remove(rowCommentList);
//重新获取要添加的sheet页姓名
sheetNameList = commentList.stream().map(x -> x.getSheetName()).distinct().collect(Collectors.toList());
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.common.excel.model;
import com.ruoyi.common.excel.common.SheetCellModel;
import lombok.Getter;
/**
* 批注信息类
*
* @author liyang
*/
@Getter
public class CommentModel extends SheetCellModel {
/**
* 批注内容
*/
private String commentContent;
private CommentModel() {
}
/**
* 生成批注信息
*
* @param sheetName sheet页名称
* @param rowIndex 行号
* @param columnIndex 列号
* @param commentContent 批注内容
* @return
*/
public static CommentModel createCommentModel(String sheetName, int rowIndex, int columnIndex, String commentContent) {
CommentModel commentModel = new CommentModel();
//sheet页名称
commentModel.sheetName = sheetName;
//行号
commentModel.rowIndex = rowIndex;
//列号
commentModel.colIndex = columnIndex;
//批注内容
commentModel.commentContent = commentContent;
return commentModel;
}
}

View File

@ -15,6 +15,8 @@ import com.ruoyi.common.excel.CellMergeStrategy;
import com.ruoyi.common.excel.DefaultExcelListener;
import com.ruoyi.common.excel.ExcelListener;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.excel.handler.CustomCommentWriteHandler;
import com.ruoyi.common.excel.model.CommentModel;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import lombok.AccessLevel;
@ -116,7 +118,49 @@ public class ExcelUtil {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 导出excel模板
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param commentList 批注
* @param response 响应体
*/
public static <T> void exportExcelCommentTemplate(List<T> list, List<CommentModel> commentList, String sheetName, Class<T> clazz, HttpServletResponse response) {
exportExcelCommentTemplate(list,commentList, sheetName, clazz, false, response);
}
/**
* 导出excel模板
*
* @param list 导出数据集合
* @param sheetName 工作表的名称
* @param clazz 实体类
* @param merge 是否合并单元格
* @param commentList 批注
* @param response 响应体
*/
public static <T> void exportExcelCommentTemplate(List<T> list, List<CommentModel> commentList, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) {
try {
resetResponse(sheetName, response);
ServletOutputStream os = response.getOutputStream();
ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz)
.autoCloseStream(false)
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new CustomCommentWriteHandler(commentList, "xlsx"))
// 大数值自动转换 防止失真
.registerConverter(new ExcelBigNumberConvert())
.sheet(sheetName);
if (merge) {
// 合并处理器
builder.registerWriteHandler(new CellMergeStrategy(list, true));
}
builder.doWrite(list);
} catch (IOException e) {
throw new RuntimeException("导出Excel异常");
}
}
/**
* 单表多数据模板导出 模板格式为 {.属性}
*

View File

@ -0,0 +1,70 @@
package com.ruoyi.common.utils.poi;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
/**
* POI Excel工具类
*
* @author liyang
*/
public class PoiExcelUtil {
/**
* 给Cell添加批注
*
* @param cell 单元格
* @param value 批注内容
* @param extension 扩展名
*/
public static void addComment(Cell cell, String value, String extension) {
Sheet sheet = cell.getSheet();
cell.removeCellComment();
if ("xls".equals(extension)) {
ClientAnchor anchor = new HSSFClientAnchor();
// 关键修改
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setRow1(cell.getRowIndex());
anchor.setCol2(cell.getColumnIndex() + 5);
anchor.setRow2(cell.getRowIndex() + 6);
// 结束
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
Comment comment = drawing.createCellComment(anchor);
// 输入批注信息
comment.setString(new HSSFRichTextString(value));
// 将批注添加到单元格对象中
cell.setCellComment(comment);
} else if ("xlsx".equals(extension)) {
ClientAnchor anchor = new XSSFClientAnchor();
// 关键修改
anchor.setDx1(0);
anchor.setDx2(0);
anchor.setDy1(0);
anchor.setDy2(0);
anchor.setCol1(cell.getColumnIndex());
anchor.setRow1(cell.getRowIndex());
anchor.setCol2(cell.getColumnIndex() + 5);
anchor.setRow2(cell.getRowIndex() + 6);
// 结束
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
Comment comment = drawing.createCellComment(anchor);
// 输入批注信息
comment.setString(new XSSFRichTextString(value));
// 将批注添加到单元格对象中
cell.setCellComment(comment);
}
}
}

View File

@ -13,6 +13,7 @@ import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.excel.model.CommentModel;
import com.ruoyi.common.utils.ValidatorUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.demo.domain.TestDemo;
@ -29,6 +30,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -145,4 +147,17 @@ public class TestDemoController extends BaseController {
@PathVariable Long[] ids) {
return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
}
/**
* 获取导入模板
*/
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
List<CommentModel> commentList = new ArrayList<>();
String sheetName = "组织机构";
commentList.add(CommentModel.createCommentModel(sheetName, 0, 0, "部门id不能为空\n换行文本"));
commentList.add(CommentModel.createCommentModel(sheetName, 0, 1, "用户id不能为空\n换行文本"));
commentList.add(CommentModel.createCommentModel(sheetName, 0, 2, "排序好不能为空\n换行文本"));
ExcelUtil.exportExcelCommentTemplate(new ArrayList<>(),commentList, sheetName, TestDemoImportVo.class, response);
}
}

View File

@ -1 +1 @@
如果使用的是RuoYi-Vue3前端那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。
如果使用的是Vue3前端那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。

View File

@ -190,6 +190,10 @@
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
@ -425,7 +429,12 @@ export default {
//
submitFileForm() {
this.$refs.upload.submit();
}
},
/** 下载模板操作 */
importTemplate() {
this.download('/demo/demo/importTemplate', {
}, `unit_template_${new Date().getTime()}.xlsx`)
},
}
};
</script>