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>
相关推荐
摇滚侠3 小时前
Vue 项目实战《尚医通》,完成预约通知业务,笔记21
前端·vue.js·笔记·前端框架
十五年专注C++开发3 小时前
DocxFactory: 一个C++操作word的开源库(不依赖office控件)
c++·开源·word·后端开发
Z7·3 小时前
word插入的图片显示不完全解决方法
word
西洼工作室5 小时前
前端项目目录结构全解析
前端·vue.js
咫尺的梦想0075 小时前
vue的生命周期
前端·javascript·vue.js
tang_jian_dong6 小时前
win10 配置下载安装 Office LTSC 专业增强版 2024
word·excel
JIngJaneIL7 小时前
数码商城系统|电子|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·数码商城系统
艾小码7 小时前
Vue组件通信不再难!这8种方式让你彻底搞懂父子兄弟传值
前端·javascript·vue.js
lcc1877 小时前
Vue 数据代理
前端·javascript·vue.js