vue中回显word、Excel、txt、markdown文件

vue中回显word、Excel文件

记录一下最近的功能点,方便下次copy。支出多个sheets 切换展示和单元格合并。

引入插件

vue2版本,插件的版本比较低

json 复制代码
"highlight.js": "^11.11.1",
"mammoth": "^1.11.0",
"marked": "^4.0.0",
"xlsx": "^0.18.5"
"@vue-office/docx": "1.6.3",
"@vue/composition-api": "1.7.2",
javascript 复制代码
import mammoth from 'mammoth'
import VueOfficeDocx from '@vue-office/docx'
import * as XLSX from 'xlsx'
import { marked } from 'marked'
import hljs from 'highlight.js'
import '@vue-office/docx/lib/index.css'

code

javascript 复制代码
<template>
<div>
	    <div class="info-tips" v-loading="isloading" :element-loading-text="$constants.G_COMPANY_INFO.loadingText" v-if="isWordDOCX">
	        <vue-office-docx @rendered="renderedHandler" :src="this.originalFile.fileUrl" style="width: 100%;height: 100%" />
	   </div>
	  <div class="info-tips" v-loading="isloading" :element-loading-text="$constants.G_COMPANY_INFO.loadingText" v-if="isWord">
	     <div class="word-content" v-html="wordHtml"></div>
	   </div>
	   <div class="info-tips" v-loading="isloading" :element-loading-text="$constants.G_COMPANY_INFO.loadingText" v-if="isTxt">
	     <pre class="word-content" v-if="wordHtml">{{ wordHtml }}</pre>
	   </div>
	   <div class="info-tips" v-loading="isloading" :element-loading-text="$constants.G_COMPANY_INFO.loadingText" v-if="isMarkDown">
	     <div class="word-content" v-html="wordHtml"></div>
	   </div>
	   <div class="info-tips" v-loading="isloading" :element-loading-text="$constants.G_COMPANY_INFO.loadingText" v-if="isExcel">
	     <div class="excel-wraper">
	       <table class="excel-table">
	         <tbody>
	           <tr v-for="(row, rowIndex) in currentExcelData" :key="rowIndex">
	             <template v-for="(cell, cellindex) in row">
	               <td
	                 v-if="!isShowTd(row, rowIndex, cellindex)"
	                 :colspan="getColspanNum(rowIndex, cellindex, row)"
	                 :rowspan="getRowspanNum(rowIndex, cellindex, row)"
	                 :key="cellindex"
	               >
	                 {{ cell }}
	               </td>
	             </template>
	           </tr>
	         </tbody>
	       </table>
	     </div>
	     <ul class="excel-name">
	       <li :class="index == currentIndex ? 'actived' : ''" v-for="(item, index) in excelData" @click="getCurrentExcel(index)" :key="index">
	         {{ item.sheetName }}
	       </li>
	     </ul>
	   </div>
</div>
</template>
<script>
	data(){
		return{
		  isloading:true,
		  isWord: false,
		  wordHtml: undefined,
		  isExcel: false,
		  excelData: [],
		  currentExcelData: [],
		  currentIndex: 0,
		  isWordDOCX: false,
		  isTxt: false,
		  isMarkDown: false,
		}
	},
	methods:{
	 	  //根据XLSX解析出来的merges数组来判断表格是否需要合并
	    isShowTd(row, rowIndex, cellindex) {
	      let hiddlen = false
	      let curmerges = this.excelData[this.currentIndex].merges
	      curmerges.forEach((item, index) => {
	      // 纵向合并判断
	        if (item.s.c == item.e.c && rowIndex > item.s.r && rowIndex <= item.e.r && cellindex == item.s.c) {
	          if (row[item.s.c] == null) {
	            hiddlen = true
	          }
	        }
	         // 横向合并判断
	        if (item.s.r == item.e.r && rowIndex == item.s.r && cellindex > item.s.c && cellindex <= item.e.c) {
	          if (row[cellindex] == null) {
	            hiddlen = true
	          }
	        }
	      })
	      return hiddlen
	    },
	    // docx文件加载完成回调
	    renderedHandler() {
	      this.isloading = false
	    },
	        //多个sheets切换
	    getCurrentExcel(index) {
	      this.currentIndex = index
	      this.currentExcelData = this.excelData[index].excelData
	    },
	    //由于表格是遍历解析出来的数据得到的,这里表格的自动合并行并不会删除被合并的单元格,需要手动隐藏被合并的单元格的列数据
	    getColspanNum(rowIndex, cellindex) {
	      let num = null
	      let merges = this.excelData[this.currentIndex].merges
	      merges.forEach((item, index) => {
	        if (item.s.r == item.e.r && rowIndex == item.s.r && cellindex == item.s.c) {
	          num = item.e.c - item.s.c + 1
	        }
	      })
	
	      return num
	    },
	     //由于表格是遍历解析出来的数据得到的,这里表格的自动合并行并不会删除被合并的单元格,需要手动隐藏被合并的单元格的行数据
	    getRowspanNum(rowIndex, cellindex) {
	      let num = null
	      let merges = this.excelData[this.currentIndex].merges
	      merges.forEach((item, index) => {
	        if (item.s.c == item.e.c && rowIndex == item.s.r && cellindex == item.s.c) {
	          num = item.e.r - item.s.r + 1
	        }
	      })
	      return num
	    },
	    previewWord() {
	      this.$service.systemget(this.$apis.getPreviewFile, { fileId }).then(
	        async res => {
	          if (res.data.status == 0) {
	            this.originalFile = res.data.data.originalFile ? res.data.data.originalFile : this.datas
	          } else {
	            this.originalFile = this.datas
	          }
	
	          this.isExcel = this.getExcelType()
	          this.isTxt = this.getWordTypeTXT()
	
	          if (this.isWord || this.isExcel) {
	            const response = await fetch(this.originalFile.fileUrl, {
	              method: 'GET',
	              mode: 'cors',
	              credentials: 'omit'
	            })
	            if (!response.ok) {
	              this.isloading = false
	              throw new Error('Http错误:' + response.status + '-' + response.statusText)
	            }
	
	            const arrayBuffer = await response.arrayBuffer()
	            const u8Array = new Uint8Array(arrayBuffer)
	            const ext = this.originalFile.fileUrl
	              .split('.')
	              .pop()
	              .toLowerCase()
	            if (ext === 'docx') {
	              const result = await mammoth.convertToHtml({ arrayBuffer: arrayBuffer, ignoreEmptyParagraphs: false })
	              this.wordHtml = result.value
	              this.isloading = false
	            } else if (ext == 'xlsx' || ext == 'xls') {
	              const workbook = XLSX.read(u8Array, { type: 'array', cellDates: true, cellNF: false })
	              let SheetNames = workbook.SheetNames
	              let Sheets = workbook.Sheets
	              SheetNames.forEach((item, index) => {
	                const worksheet = Sheets[item]
	                const merges = worksheet['!merges']
	                let excelData = XLSX.utils.sheet_to_json(worksheet, { header: 1, raw: false })
	                let max = 0
	                excelData.forEach(item => {
	                  if (item.length > max) {
	                    max = item.length
	                  }
	                })
	                excelData.forEach((item, index) => {
	                  if (item.length < max && index > 0) {
	                    let n = max - item.length
	                    for (let i = 0; i < n; i++) {
	                      item.push(null)
	                    }
	                  }
	                })
	                this.excelData.push({
	                  sheetName: item,
	                  excelData,
	                  max,
	                  merges
	                })
	                this.currentExcelData = this.excelData[0].excelData
	                this.currentIndex = 0
	              })
	              this.isloading = false
	            }
	          } else if (this.isTxt || this.isMarkDown) {
	            const response = await fetch(this.originalFile.fileUrl)
	            if (!response.ok) {
	              this.isloading = false
	              throw new Error('Http错误:' + response.status + '-' + response.statusText)
	            }
	            this.wordHtml = await response.text()
	            if (this.isMarkDown) {
	              const renderer = new marked.Renderer()
	              renderer.code = (code, language) => {
	                const validLanguage = hljs.getLanguage(language) ? language : 'plaintext'
	                console.log(validLanguage)
	
	                return `<pre class="hljs"><code>${hljs.highlight(code, { language: validLanguage }).value}</code></pre>`
	              }
	              this.wordHtml = marked(this.wordHtml, { renderer })
	            }
	            this.isloading = false
	          }
	        },
	        err => {
	          this.preivewDatas = this.datas
	          this.originalFile = this.datas
	          this.isloading = false
	          this.globalHandleConnectTimeoutErr(err)
	        }
	      )
	    }
	}
	</script>
相关推荐
七月十二11 小时前
【Vite】离线打包@iconify/vue的图标
前端·vue.js
缺点内向11 小时前
如何在C#中为文本内容添加行号?
开发语言·c#·word·.net
深色風信子11 小时前
Vue 富文本编辑器
前端·javascript·vue.js·wangeditor·vue 富文本·wangeditor-text·前端富文本
程序定小飞11 小时前
基于SpringBoot+Vue的常规应急物资管理系统的设计与实现
java·开发语言·vue.js·spring boot·后端·spring
网络点点滴11 小时前
Vue3路由query参数
前端·javascript·vue.js
dubochao_xinxi11 小时前
fastapi 接收10g 以上的文件 pandas 读取超过 10GB 的 Excel 文件
excel·pandas·fastapi
我叫张小白。12 小时前
Vue3 Hooks:逻辑复用的解决方案
前端·javascript·vue.js·前端框架·vue
我叫张小白。12 小时前
Vue3 Props 的使用:组件间数据传递的桥梁
前端·javascript·vue.js·vue3
何以解忧,唯有..13 小时前
Vue 列表渲染
前端·javascript·vue.js
前端程序猿i13 小时前
彻底搞懂防抖(Debounce)与节流(Throttle):源码实现与应用场景
开发语言·前端·javascript·vue.js·ecmascript