VUE動(dòng)態(tài)生成word的實(shí)現(xiàn)
不廢話,直接上代碼。
前端代碼:
<template> <Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="110"> <FormItem label="項(xiàng)目(全稱):" prop="orgName"> <Input v-model="formValidate.orgName" placeholder="請(qǐng)輸入項(xiàng)目名稱"></Input> </FormItem> <FormItem label="申請(qǐng)人:" prop="applyName" > <Input v-model="formValidate.applyName" placeholder="請(qǐng)輸入申請(qǐng)人"></Input> </FormItem> <FormItem label="電話:" prop="applyPhone"> <Input v-model="formValidate.applyPhone" placeholder="請(qǐng)輸入電話"></Input> </FormItem> <FormItem label="生效日期:" style="float: left"> <Row> <FormItem prop="startDate"> <DatePicker type="date" format="yyyy-MM-dd" placeholder="請(qǐng)選擇生效日期" v-model="formValidate.startData"></DatePicker> </FormItem> </Row> </FormItem> <FormItem label="失效日期:"> <Row> <FormItem prop="endDate"> <DatePicker type="date" format="yyyy-MM-dd" placeholder="請(qǐng)選擇失效日期" v-model="formValidate.endData"></DatePicker> </FormItem> </Row> </FormItem> <FormItem label="備注:" prop="vmemo"> <Input v-model="formValidate.vmemo" type="textarea" :autosize="{minRows: 2,maxRows: 5}" placeholder="備注"></Input> </FormItem> <FormItem> <Button type="primary" @click="handleSubmit('formValidate')">生成申請(qǐng)單</Button> </FormItem> </Form> </template> <script> import axios from 'axios'; export default { data () { return { formValidate: { orgName: '', applyName: '', applyPhone: '', startDate: '', endDate: '', vmemo:'' }, ruleValidate: { orgName: [ { required: true, message: '項(xiàng)目名稱不能為空!', trigger: 'blur' } ], applyName: [ { required: true, message: '申請(qǐng)人不能為空!', trigger: 'blur' } ], applyPhone: [ { required: true, message: '電話不能為空!', trigger: 'change' } ], startDate: [ { required: true, type: 'date', message: '請(qǐng)輸入license有效期!', trigger: 'change' } ], endDate: [ { required: true, type: 'date', message: '請(qǐng)輸入license有效期!', trigger: 'change' } ], } } }, methods: { handleSubmit (name) { this.$refs[name].validate((valid) => { if (valid) { axios({ method: 'post', url: this.$store.getters.requestNoteUrl, data: this.formValidate, responseType: 'blob' }).then(res => { this.download(res.data); }); } }); }, download (data) { if (!data) { return } let url = window.URL.createObjectURL(new Blob([data])) let link = document.createElement('a'); link.style.display = 'none'; link.href = url; link.setAttribute('download', this.formValidate.orgName+'('+ this.formValidate.applyName +')'+'-申請(qǐng)單.doc'); document.body.appendChild(link); link.click(); } } } </script>
后臺(tái):
/** * 生成license申請(qǐng)單 */ @RequestMapping(value = "/note", method = RequestMethod.POST) public void requestNote(@RequestBody LicenseRequestNoteModel noteModel, HttpServletRequest req, HttpServletResponse resp) { File file = null; InputStream fin = null; ServletOutputStream out = null; try { req.setCharacterEncoding("utf-8"); file = ExportDoc.createWord(noteModel, req, resp); fin = new FileInputStream(file); resp.setCharacterEncoding("utf-8"); resp.setContentType("application/octet-stream"); resp.addHeader("Content-Disposition", "attachment;filename="+ noteModel.getOrgName()+"申請(qǐng)單.doc"); resp.flushBuffer(); out = resp.getOutputStream(); byte[] buffer = new byte[512]; // 緩沖區(qū) int bytesToRead = -1; // 通過(guò)循環(huán)將讀入的Word文件的內(nèi)容輸出到瀏覽器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fin != null) fin.close(); if (out != null) out.close(); if (file != null) file.delete(); // 刪除臨時(shí)文件 } catch (IOException e) { e.printStackTrace(); } } }
public class ExportDoc { private static final Logger logger = LoggerFactory.getLogger(ExportDoc.class); // 針對(duì)下面這行有的報(bào)空指針,是目錄問(wèn)題,我的目錄(項(xiàng)目/src/main/java,項(xiàng)目/src/main/resources),這塊也可以自己指定文件夾 private static final String templateFolder = ExportDoc.class.getClassLoader().getResource("/").getPath(); private static Configuration configuration = null; private static Map<String, Template> allTemplates = null; static { configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); allTemplates = new HashedMap(); try { configuration.setDirectoryForTemplateLoading(new File(templateFolder)); allTemplates.put("resume", configuration.getTemplate("licenseApply.ftl")); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static File createWord(LicenseRequestNoteModel noteModel, HttpServletRequest req, HttpServletResponse resp) throws Exception { File file = null; req.setCharacterEncoding("utf-8"); // 調(diào)用工具類(lèi)WordGenerator的createDoc方法生成Word文檔 file = createDoc(getData(noteModel), "resume"); return file; } public static File createDoc(Map<?, ?> dataMap, String type) { String name = "temp" + (int) (Math.random() * 100000) + ".doc"; File f = new File(name); Template t = allTemplates.get(type); try { // 這個(gè)地方不能使用FileWriter因?yàn)樾枰付ň幋a類(lèi)型否則生成的Word文檔會(huì)因?yàn)橛袩o(wú)法識(shí)別的編碼而無(wú)法打開(kāi) Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); t.process(dataMap, w); w.close(); } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } return f; } private static Map<String, Object> getData(LicenseRequestNoteModel noteModel) throws Exception { Map<String, Object> map = new HashedMap(); map.put("orgName", noteModel.getOrgName()); map.put("applyName", noteModel.getApplyName()); map.put("applyPhone", noteModel.getApplyPhone()); map.put("ncVersion", noteModel.getNcVersionModel()); map.put("environment", noteModel.getEnvironmentModel()); map.put("applyType", noteModel.getApplyTypeModel()); map.put("mac", GetLicenseSource.getMacId()); map.put("ip", GetLicenseSource.getLocalIP()); map.put("startData", DateUtil.Date(noteModel.getStartData())); map.put("endData", DateUtil.Date(noteModel.getEndData())); map.put("hostName", noteModel.getHostNames()); map.put("vmemo", noteModel.getVmemo()); return map; } }
public class LicenseRequestNoteModel{ private String orgName = null; private String applyName = null; private String applyPhone = null; private String ncVersionModel= null; private String environmentModel= null; private String applyTypeModel= null; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd") private Date startData= null; @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd") private Date endData= null; private String[] hostName= null; private String vmemo= null; private String applyMAC= null; private String applyIP= null; public String getOrgName() { return orgName; } public void setOrgName(String projectName) { this.orgName = projectName; } public String getApplyName() { return applyName; } public void setApplyName(String applyName) { this.applyName = applyName; } public String getApplyPhone() { return applyPhone; } public void setApplyPhone(String applyPhone) { this.applyPhone = applyPhone; } public String getNcVersionModel() { return ncVersionModel; } public void setNcVersionModel(String ncVersionModel) { this.ncVersionModel = ncVersionModel; } public String getEnvironmentModel() { return environmentModel; } public void setEnvironmentModel(String environmentModel) { this.environmentModel = environmentModel; } public String getApplyTypeModel() { return applyTypeModel; } public void setApplyTypeModel(String applyTypeModel) { this.applyTypeModel = applyTypeModel; } public Date getStartData() { return startData; } public void setStartData(Date startData) { this.startData = startData; } public Date getEndData() { return endData; } public void setEndData(Date endData) { this.endData = endData; } public String[] getHostName() { return hostName; } public String getHostNames() { return StringUtils.join(this.hostName,","); } public void setHostName(String[] hostName) { this.hostName = hostName; } public String getVmemo() { return vmemo; } public void setVmemo(String vmemo) { this.vmemo = vmemo; } public String getApplyMAC() { return applyMAC; } public void setApplyMAC(String applyMAC) { this.applyMAC = applyMAC; } public String getApplyIP() { return applyIP; } public void setApplyIP(String applyIP) { this.applyIP = applyIP; } }
補(bǔ)充知識(shí):vue elementui 頁(yè)面預(yù)覽導(dǎo)入excel表格數(shù)據(jù)
html代碼:
<el-card class="box-card"> <div slot="header" class="clearfix"> <span>數(shù)據(jù)預(yù)覽</span> </div> <div class="text item"> <el-table :data="tableData" border highlight-current-row style="width: 100%;"> <el-table-column :label="tableTitle" > <el-table-column min-width="150" v-for='item tableHeader' :prop="item" :label="item" :key='item'> </el-table-column> </el-table-column> </el-table> </div> </el-card>
js代碼:
import XLSX from 'xlsx' data() { return { tableData: '', tableHeader: '' } }, mounted: { document.getElementsByClassName('el-upload__input')[0].setAttribute('accept', '.xlsx, .xls') document.getElementsByClassName('el-upload__input')[0].onchange = (e) => { const files = e.target.filesconst itemFile = files[0] // only use files[0]if (!itemFile) return this.readerData(itemFile) } }, methods: { generateDate({ tableTitle, header, results }) { this.tableTitle = tableTitle this.tableData = results this.tableHeader = header }, handleDrop(e) { e.stopPropagation() e.preventDefault() const files = e.dataTransfer.files if (files.length !== 1) { this.$message.error('Only support uploading one file!') return } const itemFile = files[0] // only use files[0] this.readerData(itemFile) e.stopPropagation() e.preventDefault() }, handleDragover(e) { e.stopPropagation() e.preventDefault() e.dataTransfer.dropEffect = 'copy' }, readerData(itemFile) { if (itemFile.name.split('.')[1] != 'xls' && itemFile.name.split('.')[1] != 'xlsx') { this.$message({message: '上傳文件格式錯(cuò)誤,請(qǐng)上傳xls、xlsx文件!',type: 'warning'}); } else { const reader = new FileReader() reader.onload = e => { const data = e.target.result const fixedData = this.fixdata(data) const workbook = XLSX.read(btoa(fixedData), { type: 'base64' }) const firstSheetName = workbook.SheetNames[0] // 第一張表 sheet1 const worksheet = workbook.Sheets[firstSheetName] // 讀取sheet1表中的數(shù)據(jù) delete worksheet['!merges']let A_l = worksheet['!ref'].split(':')[1] //當(dāng)excel存在標(biāo)題行時(shí) worksheet['!ref'] = `A2:${A_l}` const tableTitle = firstSheetName const header = this.get_header_row(worksheet) const results = XLSX.utils.sheet_to_json(worksheet) this.generateDate({ tableTitle, header, results }) } reader.readAsArrayBuffer(itemFile) } }, fixdata(data) { let o = '' let l = 0 const w = 10240 for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w))) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w))) return o }, get_header_row(sheet) { const headers = [] const range = XLSX.utils.decode_range(sheet['!ref']) let Cconst R = range.s.r /* start in the first row */ for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */ var hdr = 'UNKNOWN ' + C // <-- replace with your desired defaultif (cell && cell.t) hdr = XLSX.utils.format_cell(cell) headers.push(hdr) } return headers }
以上這篇VUE動(dòng)態(tài)生成word的實(shí)現(xiàn)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue element-ui導(dǎo)航實(shí)現(xiàn)全屏/取消全屏功能
這篇文章主要介紹了vue element-ui導(dǎo)航實(shí)現(xiàn)全屏/取消全屏功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08vue中keep-alive、activated的探討和使用詳解
這篇文章主要介紹了vue中keep-alive、activated的探討和使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07SpringBoot+Vue開(kāi)發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件
這篇文章主要介紹了SpringBoot+Vue開(kāi)發(fā)之Login校驗(yàn)規(guī)則、實(shí)現(xiàn)登錄和重置事件,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10element-ui table組件如何使用render屬性的實(shí)現(xiàn)
這篇文章主要介紹了element-ui table組件如何使用render屬性的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11vue定時(shí)器設(shè)置和關(guān)閉頁(yè)面時(shí)關(guān)閉定時(shí)器方式
這篇文章主要介紹了vue定時(shí)器設(shè)置和關(guān)閉頁(yè)面時(shí)關(guān)閉定時(shí)器方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06vue?el-input設(shè)置必填提示功能(單個(gè)與多個(gè))
有的功能需要設(shè)置必填項(xiàng),當(dāng)然也需要判斷是不是添上了,下面這篇文章主要給大家介紹了關(guān)于vue?el-input設(shè)置必填提示功能(單個(gè)與多個(gè))的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02vue深拷貝的3種實(shí)現(xiàn)方式小結(jié)
當(dāng)使用同一個(gè)對(duì)象產(chǎn)生沖突時(shí),可以使用lodash包,對(duì)該對(duì)象進(jìn)行深拷貝,從而使操作的對(duì)象為不同的對(duì)象,這篇文章主要給大家介紹了關(guān)于vue深拷貝的3種實(shí)現(xiàn)方式,需要的朋友可以參考下2023-02-02