600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 用Excel模板进行数据导出加前台vue展示excel并打印

用Excel模板进行数据导出加前台vue展示excel并打印

时间:2024-07-10 19:23:16

相关推荐

用Excel模板进行数据导出加前台vue展示excel并打印

前言:

找了好多资料,基本都是需要页面上写好table再获取数据进行展示或者将其转为pdf再页面展示,我不想这样做于是想了好久,在翻来翻去的时候无意间发现了WorkSheet的一个方法叫做 saveToHtml() 于是灵光一闪,对啊直接将其转化为html进行展示不就得了!!!!上代码!!

Excel模板:

要求是按照${ } 内写的属性进行多数据导出

后端:

pom.xml

<!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></dependency><!-- 国产的,我这边用于将excel转html --><dependency><groupId>e-iceblue</groupId><artifactId>spire.xls.free</artifactId><version>5.1.0</version></dependency>

工具类

package mon.utils.poi;import lombok.Data;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.CellStyle;/*** @author* 读取excel的信息并进行存储*/@Datapublic class ReadExcel {/** 当前列的值*/private String key;/** 当前列对应的位置*/private Integer rowCellNum;/** 当前列的信息*/private Cell cell;/** 当前列的样式*/private CellStyle cellStyle;}

注:考虑到以后改动模板的情况,我将该列样式存储了起来,以后你想改模板,比如列加宽加高,改变字体颜色,只需要在你的模板上 找到对应的${ xxxx } 添加样式即可,后续该列都会是这个样式

package mon.utils.poi;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 org.springframework.util.CollectionUtils;import java.io.FileInputStream;import java.util.*;/*** @author excel列表数据替换*/public class ReplaceExcelUtil {/*** 替换excel列的数据,只用于多导出用** @param fis* @param listMap* @param staRowNum 从第几行开始写入* @return* @throws Exception*/public static Workbook replaceExcelList(FileInputStream fis, List<Map<String, Object>> listMap, int staRowNum) throws Exception {if (CollectionUtils.isEmpty(listMap)) {throw new RuntimeException("要打印的数据不能为空!");}Workbook wb = new XSSFWorkbook(fis);Sheet sheet = wb.getSheetAt(0);//获取当前行Row rowHead = sheet.getRow(staRowNum);//获取当前行总列数int forSize = rowHead.getPhysicalNumberOfCells();List<ReadExcel> list = new ArrayList<>();for (int i = 0; i < forSize; i++) {String cellValue = rowHead.getCell(i).toString();ReadExcel excel = new ReadExcel();excel.setKey(cellValue);excel.setRowCellNum(i);excel.setCell(rowHead.getCell(i));excel.setCellStyle(rowHead.getCell(i).getCellStyle());list.add(excel);}int i = 0;for (Map<String, Object> mapData : listMap) {Row row = sheet.createRow(staRowNum + i);buildMap(mapData);for (ReadExcel excelBean : list) {Cell cell = row.createCell(excelBean.getRowCellNum());if (mapData.containsKey(excelBean.getKey())) {cell.setCellValue(String.valueOf(mapData.get(excelBean.getKey())));}cell.setCellStyle(excelBean.getCellStyle());}i++;}return wb;}/*** 构造map,不再用外部替代了** @param data*/public static void buildMap(Map<String, Object> data) {Iterator<Map.Entry<String, Object>> iterator = data.entrySet().iterator();Map<String, Object> newMap = new HashMap<>(data.size());while (iterator.hasNext()) {Map.Entry<String, Object> entry = iterator.next();String newKey = "${" + entry.getKey() + "}";newMap.put(newKey, entry.getValue());iterator.remove();}data.putAll(newMap);}}

代码:

@GetMapping("/printXX")public byte[] printXX() throws Exception {List<Map<String, Object>> list = new ArrayList<>();//这里是我自己造的数据for (int i = 0; i < 100; i++) {Map<String, Object> map = new HashMap<>();map.put("archiveType", "xxxxxxxxxxxx");map.put("archiveCenterNo", "xxxxxxxx");map.put("title", "xxxxxxxxxxx");map.put("staEndTime", "-09-06 09:46:08");map.put("pageNumber", 1);map.put("pageSize", 1);map.put("team", "xxxxxxx");map.put("title", "xxxxxxxxx");list.add(map);}//数据替换FileInputStream fis = new FileInputStream("模板的路径");Workbook wk = ReplaceExcelUtil.replaceExcelList(fis, list, 4);com.spire.xls.Workbook wb = new com.spire.xls.Workbook();//读取成流并写入到 com.spire.xls.WorkbookByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();wk.write(byteArrayOutputStream);InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());wb.loadFromStream(inputStream);//这里使用取巧的方式,不对整个excel进行转换,只对第一个sheet获取数据转换为htmlWorksheet worksheet = wb.getWorksheets().get(0);ByteArrayOutputStream pdfStream = new ByteArrayOutputStream();worksheet.saveToHtml(pdfStream, HTMLOptions.Default);return pdfStream.toByteArray();}

前端:

vue 页面:

<el-dialog title="打印" :visible.sync="printFlag" append-to-body :close-on-click-modal ="false" width="70%" :show-close="false"><div slot="default" class="dialog-footer"><el-button v-print="'#printExcel'" ref=""> 打 印 </el-button></div><div ref="printExcel" id="printExcel" ></div></el-dialog>

请求接口:

这里为什么要再添加个样式是因为打印需要,如果不添加这个样式就会导致打印连续,而无法正常结尾(可自行去掉试试),还有为什么 对<table> 也添加样式,是因为无法在外部div设置的居中是没用的,所以我采用了在这个位置进行文字替换,替换上了设置居中

printExcel(){this.printFlag = true;//这个只是个get方法获取后台的数据printXXX().then(rep =>{this.$refs.printExcel.innerHTML = null;let pageStyle = `<style type="text/css">` +"@media print" +"{" +" table { page-break-after:auto }" +" tr { page-break-inside:avoid; page-break-after:auto }" +" td { page-break-inside:avoid; page-break-after:auto }" +" thead { display:table-header-group }" +" tfoot { display:table-footer-group }" +"}";let s = rep.toString().replace(`<style type="text/css">`,pageStyle).replace(`<table cellspacing="0">`,`<table cellspacing="0" style="margin:0 auto">`);this.$refs.printExcel.innerHTML = s;})},

预览效果展示:

打印展示

结语:

这里面前端有个bug得说一下,因为前台展示的html是excel转出来的,所以宽度是转换时就固定了的,如果你前端dialog设置的太小就会变成这样:

注意设宽一点,或者解决了麻烦在评论里说一下

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。