ExcelJS實現導入轉換HTML展示(附源碼可直接使用)

目錄

簡介

開始實踐

難點

文件示例

效果預覽

具體實現

安裝

完整代碼

總結


簡介

在日常工作中,我們可能會遇到需要上傳并展示 Excel 文件的需求,實現文件內容的在線預覽。 這里給大家接收一個組件庫exceljs,這個組件庫進過實踐發現可以實現我們需要的功能。在這里我為了方便使用了(技術棧?Vue 3 + Element Ui 筆者自己使用的項目模板)來實現該功能。

開始實踐

NPM地址?內部有中文文檔

難點

基礎單元格和合并單元格和空白單元格的混合處理

文字樣式和背景樣式的讀取映射

文件示例

這里直接造了一個兩個sheet的excel做測試

效果預覽

具體實現

安裝

npm install exceljs

完整代碼

<template><div><el-uploadaction="":auto-upload="false":show-file-list="true":on-change="handleFileUpload"accept=".xlsx,.xls"><el-button type="primary"> 上傳 Excel </el-button></el-upload><!-- 渲染 Excel 生成的 HTML 表格 --><div v-html="tableHtml" /></div>
</template><script setup>
import { ref } from "vue";
import * as ExcelJS from "exceljs";const tableHtml = ref(""); // 存儲 HTML 表格內容
const themeColors = {0: "#FFFFFF", // 白色 √1: "#000000", // 黑色 √2: "#C9CDD1", // 灰色 √3: "#4874CB", // 藍色 √4: "#D9E1F4", // 淺藍 √5: "#F9CBAA", // 橙色 √6: "#F2BA02", // 淺橙 √7: "#00FF00", // 淺綠 √8: "#30C0B4", // 青色 √9: "#E54C5E", // 紅色 √10: "#FFC7CE", // 淺紅11: "#7030A0", // 紫色
};// 獲取單元格顏色
const getCellColor = (cell) => {if (cell.fill && cell.fill.fgColor) {if (cell.fill.fgColor.argb) {return `#${cell.fill.fgColor.argb.substring(2)}`; // ARGB 轉 RGB}if (cell.fill.fgColor.theme !== undefined) {return themeColors[cell.fill.fgColor.theme] || "#FFFFFF"; // 主題色轉換}}return ""; // 無顏色
};
// 獲取單元格字體顏色
const getCellFontColor = (cell) => {if (cell.font && cell.font.color && cell.font.color.argb) {return `#${cell.font.color.argb.substring(2)}`; // ARGB 轉 RGB}if (cell.font && cell.font.color && cell.font.color.theme) {return themeColors[cell.font.color.theme] || "#000"; // 主題色轉換}return "#000"; // 默認黑色
};
const handleStyles = (cell) => {let styles = [];// 讀取字體顏色styles.push(`color: ${getCellFontColor(cell)}`);// 讀取背景色styles.push(`background-color: ${getCellColor(cell)}`);// 加粗if (cell.font && cell.font.bold) {styles.push("font-weight: bold");}// 文字對齊if (cell.alignment) {if (cell.alignment.horizontal) {styles.push(`text-align: ${cell.alignment.horizontal}`);}if (cell.alignment.vertical) {styles.push(`vertical-align: ${cell.alignment.vertical}`);}}return styles.join("; ");
};// 獲取工作表維度信息
const getWorksheetDimensions = (worksheet) => {let maxRow = 0;let maxCol = 0;worksheet.eachRow((row, rowIndex) => {maxRow = Math.max(maxRow, rowIndex);row.eachCell((cell, colIndex) => {maxCol = Math.max(maxCol, colIndex);});});return { maxRow, maxCol };
};// 處理上傳的 Excel 文件
const handleFileUpload = async (file) => {const excelData = await readExcel(file.raw);tableHtml.value = excelData; // 更新 HTML 表格內容
};
// 處理常規單元格內容
const handleValueSimple = (value) => {if (!value) return "&nbsp;";if (typeof value === "object" && value.richText) {const valueStr = value.richText.reduce((acc, curr) => {let colorValue = "";if (curr.font && curr.font.color && curr.font.color.theme) {colorValue = getCellFontColor(curr) || `#000`;}if (curr.font && curr.font.color && curr.font.color.argb) {colorValue = `#${curr.font.color.argb.substring(2)}`;} else {colorValue = `#000`;}return acc + `<span style="color:${colorValue}">${curr.text}</span>`;}, "");return valueStr;}return value.toString();
};
// 處理合并單元格內容
const handleValue = (value) => {if (!value) return "&nbsp;";if (typeof value === "object" && value.richText) {const valueArr = value.richText.reduce((acc, curr) => {let colorValue = "";if (curr.font && curr.font.color && curr.font.color.argb) {colorValue = `#${curr.font.color.argb.substring(2)}`;} else {colorValue = `#000`;}const newData = curr.text.split(/\r/).map((item) => `<p style="color:${colorValue}">${item}</p>`);return acc.concat(newData);}, []);return valueArr.join("").replace(/\n/g, "<br />");}return value.toString();
};let worksheetIds = [];
// 讀取 Excel 并轉換成 HTML
const readExcel = async (file) => {const workbook = new ExcelJS.Workbook();const arrayBuffer = await file.arrayBuffer();const { worksheets } = await workbook.xlsx.load(arrayBuffer);worksheetIds = worksheets.map((v) => v.id); // 獲取工作表 ID集合let allHtml = "";workbook.eachSheet(function (worksheet, sheetId) {// 處理合并單元格const merges = worksheet?.model?.merges || [];const currentSheetIndex = worksheetIds.indexOf(sheetId); // 獲取當前工作表的索引// 獲取工作表維度const { maxRow, maxCol } = getWorksheetDimensions(worksheet);allHtml +='<table border="1" style="border-collapse: collapse;width:100%;margin-bottom: 20px;">';// 使用雙重循環確保每個單元格位置都被處理for (let rowIndex = 1; rowIndex <= maxRow; rowIndex++) {allHtml += "<tr>";for (let colIndex = 1; colIndex <= maxCol; colIndex++) {const cell = worksheet.getCell(rowIndex, colIndex);let cellValue = cell.value || "";// 檢查當前單元格是否在合并范圍內let isInMerge = false;let isMergeStart = false;let rowspan = 1;let colspan = 1;for (let merge of merges) {const [start, end] = merge.split(":");const startCell = worksheet.getCell(start);const endCell = worksheet.getCell(end);const startRow = startCell.row;const startCol = startCell.col;const endRow = endCell.row;const endCol = endCell.col;if (rowIndex >= startRow && rowIndex <= endRow && colIndex >= startCol && colIndex <= endCol) {isInMerge = true;if (rowIndex === startRow && colIndex === startCol) {isMergeStart = true;rowspan = endRow - startRow + 1;colspan = endCol - startCol + 1;}break;}}// 如果是合并單元格的起始位置,創建合并單元格if (isMergeStart) {let styles = handleStyles(cell);const mergeValue = cellValue || "&nbsp;";allHtml += `<td rowspan="${rowspan}" colspan="${colspan}" style="${styles}">${handleValue(mergeValue)}</td>`;}// 如果不在合并范圍內,創建普通單元格else if (!isInMerge) {let styles = handleStyles(cell);const displayValue = cellValue ? handleValueSimple(cellValue) : "&nbsp;";allHtml += `<td style="${styles}">${displayValue}</td>`;}// 如果單元格在合并范圍內但不是起始位置,跳過(由合并單元格處理)}allHtml += "</tr>";}allHtml += "</table>";});return allHtml;
};
</script>

總結

exceljs功能很多,這里給大家介紹了execljs的一種用法,實現導入轉換html頁面顯示,便于瀏覽。大家感興趣可以去翻翻文檔??NPM地址?內部有中文文檔,exceljs功能很強大推薦大家自己嘗試一下。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95408.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95408.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95408.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ECDH和數字簽名

文章目錄一、核心區別&#xff1a;目的完全不同二、協同工作關系&#xff1a;缺一不可的安全組合三、技術結合點&#xff1a;都基于ECC(橢圓曲線密碼學)ECDH&#xff08;橢圓曲線迪菲-赫爾曼密鑰交換&#xff09;和數字簽名&#xff08;如ECDSA&#xff0c;橢圓曲線數字簽名算法…

withCredentials(簡單說:帶不帶憑證)

一、withCredentials是什么&#xff1f;withCredentials 是瀏覽器 XMLHttpRequest 或 Fetch API&#xff08;以及 axios 等基于它們的庫&#xff09;中的一個配置項&#xff0c;作用是控制跨域請求時是否攜帶 Cookie、HTTP 認證信息等憑證。用更通俗的方式解釋&#xff1a;二、…

window系統使用命令行來安裝OpenSSH服務器或客戶端

可以通過 PowerShell 命令行來安裝&#xff0c;這種方式更直接可靠&#xff1a;以管理員身份打開 PowerShell&#xff1a; 按下 Win S 搜索 “PowerShell”右鍵點擊 “Windows PowerShell”&#xff0c;選擇"以管理員身份運行"安裝 OpenSSH 客戶端&#xff1a; Add-…

vim中常見操作及命令

在 Vim 中為所有行的行首添加相同字符&#xff0c;可以使用以下方法&#xff1a; 方法1&#xff1a;使用 :%s 替換命令&#xff08;推薦&#xff09; vim :%s/^/要添加的字符/ 例如要在所有行首添加 #&#xff1a;vim :%s/^/#/ 方法2&#xff1a;使用塊選擇模式&#xff08;可視…

開發使用mybatis是用混合模式還是全注解模式

在使用 MyBatis 開發項目時&#xff0c;Mapper 接口是為數據庫操作提供最直觀的方法&#xff0c;但在實現方式上&#xff0c;我們有兩種選擇&#xff1a;全注解模式和混合模式。那么&#xff0c;他們有什么區別&#xff0c;應該如何選擇&#xff1f;我們一起來討論一下。一、全…

WS2812燈帶效果設計器上位機

軟件使用方法介紹&#xff1a;bilibili地址 【免寫單片機代碼WS2812燈帶效果設計軟件-嗶哩嗶哩】 https://b23.tv/xFhxMGm

Docker 容器(二)

Docker四、Docker容器數據卷1.數據卷的主要特點2.卷的共享與繼承&#xff08;1&#xff09;卷的共享&#xff08;Sharing&#xff09;(2) 卷的繼承&#xff08;Inheritance&#xff09;3.數據卷運行實例五、Dockerfile1.Dockerfile2. 創建一個名為 myubuntu的自定義鏡像第 1 步…

PCB基礎細節--工藝篇

pcb基礎細節&#xff08;工藝篇&#xff09; 1. 孔與焊盤2. PCB各層之間的作用3. 阻抗匹配 3.1. 什么是傳輸線&#xff1f;我們只看特性阻抗&#xff0c;時延以后再說。 在畫原理圖時&#xff0c;我們把電阻&#xff0c;電容&#xff0c;電感是抽象成一個點了。兩邊加一個電壓&…

信創服務器總死機原因及解決辦法

哈嘍&#xff0c;你好啊&#xff0c;我是雷工&#xff01;最近有個項目使用信創的服務器&#xff0c;總是出現死機的情況&#xff0c;聯系廠家檢查了一下&#xff0c;說是沐創網卡固件較低造成的&#xff0c;讓移除網卡或升級固件嘗試一下。記得5月份按廠家的說法處理過一臺&am…

03_網關ip和端口映射(路由器轉發)操作和原理

網關ip和端口映射&#xff08;路由器轉發&#xff09;操作和原理IP 與端口映射配置全指南&#xff1a;2 種方案搞定外網訪問內網一、先搞懂&#xff1a;為什么需要 IP 與端口映射&#xff1f;二、方案一&#xff1a;路由器端口映射&#xff08;適合有公網 IP&#xff0c;長期穩…

「數據獲取」《安徽建設統計年鑒》(2002-2007)(2004、2006缺失)(獲取方式看綁定的資源)

01、數據簡介《安徽建設統計年鑒》是一部全方位反映安徽省建設事業發展變遷的重要統計資料著作。該書系統收集并精心整理了 2006 年度安徽省城鄉建設領域的核心統計數據&#xff0c;涵蓋城鄉建設固定資產投資、建筑業發展態勢、城鎮建設推進情況等多個關鍵方面&#xff0c;為政…

Python/JS/Go/Java同步學習(第一篇)格式化/隱藏參數一鍋端 四語言輸出流參數宇宙(附源碼/截圖/參數表/避坑指南/老板沉默術)

&#x1f91d; 免罵聲明&#xff1a; 本文四語言輸出流參數經本蜀黎實戰整理&#xff0c;旨在提供快速參考指南&#x1f4dd;因各語言版本迭代及不同系統環境差異&#xff0c;偶爾可能出現整理不全面之處&#xff0c;實屬正常?歡迎理性交流補充&#xff0c;噴子勿噴——畢竟你…

人工智能助力流感疫苗選擇:MIT 團隊推出 VaxSeer 系統

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

使用 qmake 生成 Makefile,Makefile 轉換為 Qt 的 .pro 文件

使用 qmake 生成 Makefile 的完整指南 qmake 是 Qt 提供的構建工具&#xff0c;用于從 .pro 項目文件生成 Makefile。以下是詳細的使用方法&#xff1a; 基本使用方法 1. 從 .pro 文件生成 Makefile bash qmake -o Makefile your_project.pro2. 直接運行 qmake&#xff08;自動…

利用DeepSeek編寫驗證xlsx格式文件中是否啟用sharedStrings.xml對讀寫效率影響python程序

讓他分別用100*10000個單元格有100、1000、10000個不同的1-200字符長的大寫英文字母字符串測試. 一開始DeepSeek沒有找到啟用sharedStrings.xml的寫xlsx模塊&#xff0c;我自己找了pyxlsbwriter的例子告訴他才改好的。 import os import time import random import string impo…

【C++框架#2】gflags 和 gtest 安裝使用

spdlog 安裝和使用 1. 概述 介紹&#xff1a;spdlog 是一個高性能、超快速、零配置的 C 日志庫&#xff0c;它旨在提供簡潔的 API 和豐富的功能&#xff0c;同時保持高性能的日志記錄。它支持多種輸出目標、格式化選項、線程安全以及異步日志記錄。 github 鏈接&#xff1a;htt…

平衡掌控者-游戲數值戰斗設計

一、有效生命值1、計算公式有效生命生命值/&#xff08;1-傷害減免率&#xff09;/&#xff08;1-閃避率&#xff09;2、前搖和后搖對數值來說&#xff0c;戰斗由兩大模塊組成&#xff0c;一個是戰斗公式生效前的戰斗攻擊流程&#xff0c;一個是戰斗公式與自身流程。比如說&…

使用DataLoader加載本地數據 食物分類案例

目錄 一.食物分類案例 1..整合訓練集測試集文檔 2.導入相關的庫 3.設置圖片數據的格式轉換 3.數據處理 4.數據打包 5.定義卷積神經網絡 6.創建模型 7.訓練和測試方法定義 8.損失函數和優化器 9.訓練模型&#xff0c;測試準確率 10.測試模型 之前我們DataLoader加載…

從零開始的python學習——函數(2)

? ? ? ? ? づ?ど &#x1f389; 歡迎點贊支持&#x1f389; 個人主頁&#xff1a;勵志不掉頭發的內向程序員&#xff1b; 專欄主頁&#xff1a;python學習專欄&#xff1b; 文章目錄 前言 一、變量作用域 二、函數執行過程 三、鏈式調用 四、嵌套調用 五、函數遞歸 六、…

RAG 的完整流程是怎么樣的?

RAG&#xff08;檢索增強生成&#xff09;的完整流程可分為5個核心階段&#xff1a;數據準備&#xff1a;清洗文檔、分塊處理&#xff08;如PDF轉文本切片&#xff09;&#xff1b;向量化&#xff1a;使用嵌入模型&#xff08;如BERT、BGE&#xff09;將文本轉為向量&#xff1…