XLSX + LuckySheet + LuckyExcel實現前端的excel預覽

文章目錄

    • 功能簡介
    • 簡單代碼實現
    • 效果
    • 參考

功能簡介

  1. 通過LuckyExcel的transformExcelToLucky方法, 我們可以把一個文件直接轉成LuckySheet需要的json字符串, 之后我們就可以用LuckySheet預覽excel
  2. LuckyExcel只能解析xlsx格式的excel文件,因此對于xls和csv的格式,我們需要通過XLSX來轉化成xlsx格式,但在轉化過程中會丟失樣式
  3. 對于excel中存在很多的空白行,在顯示的時候可能會出現卡頓,所以我們需要將過多的空白行移除

簡單代碼實現

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Excel File Upload and Preview with Luckysheet</title>
</head>
<body><!-- 文件上傳控件 -->
<input type="file" id="fileUpload"/><!-- Luckysheet 的容器 -->
<div id="luckysheet" style="position: relative; width: 100%; height: 500px;"></div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script><link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css'/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script><script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script><script>const _xlsxType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';const  _xlsType = 'application/vnd.ms-excel';const  _csvType = 'text/csv';//如果后端是以流的方式返回,可以調用這個方法const handleExcel = (res, fileName) => {const file = getExcelFile(res, fileName);handleExcelFile(file);}// 獲取Excel文件const getExcelFile = (res, fileName) => {// 根據文件后綴名判斷文件類型if (fileName.endsWith('.xlsx')) {return new File([res], fileName, {type: _xlsxType});} else if (fileName.endsWith('.xls')) {return new File([res], fileName, {type: _xlsType});} else if (fileName.endsWith('.csv')) {return new File([res], fileName, {type: _csvType});} else {throw new Error("Unsupported file type");}}// 處理Excel文件const handleExcelFile = (file) => {const fileName = file.name;// 根據文件后綴名判斷文件類型并進行處理if (fileName.endsWith('.xlsx')) {console.log("handle excel for xlsx type..", fileName);handleExcelForXlsxType(file, fileName);} else if (fileName.endsWith('.xls') || fileName.endsWith('.csv')) {console.log("handle excel for xls or csv type..", fileName);handleExcelForXlsAndCsvType(file, fileName);} else {throw new Error("Unsupported file type");}}// 處理xlsx類型的Excel文件const handleExcelForXlsxType = (file, fileName) => {const reader = new FileReader();reader.onload = function (event) {const data = new Uint8Array(event.target.result);const workbook = XLSX.read(data, {type: 'array'});// 獲取Excel文件中的最大行數let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);// 如果行數大于100000,則處理Excel文件中的空行if (maxRowCountFromExcel > 1000000) {console.log("excel file has too many blank row..", maxRowCountFromExcel);handleBlankRowForExcelWithTooManyBlankRow(workbook);const xlsxFile = toXlsxExcelFile(workbook, fileName);createLuckySheet(xlsxFile);} else {createLuckySheet(file);}};reader.readAsArrayBuffer(file);}// 處理xls和csv類型的Excel文件const handleExcelForXlsAndCsvType = (file, fileName) => {const reader = new FileReader();// 讀取文件完成后的回調函數reader.onload = function (event) {const data = new Uint8Array(event.target.result);// 讀取Excel文件內容const workbook = XLSX.read(data, {type: 'array'});// 將Excel文件轉換為xlsx類型const xlsxFile = toXlsxExcelFile(workbook, fileName);// 處理xlsx類型的Excel文件handleExcelForXlsxType(xlsxFile, fileName);};// 以ArrayBuffer的形式讀取文件reader.readAsArrayBuffer(file);}/ 創建Luckysheetconst createLuckySheet = (file) => {// 銷毀已存在的Luckysheetwindow.luckysheet.destroy();// 將Excel文件轉換為Luckysheet的jsonLuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) {if (exportJson.sheets == null || exportJson.sheets.length === 0) {throw new Error("Failed to load excel file");}// 創建Luckysheet的配置項const options = {container: 'luckysheet',data: exportJson.sheets, // title: exportJson.info.name,// userInfo: exportJson.info.name.creator,column: 10,row: 10,showinfobar: false,sheetFormulaBar: true,showConfigWindowResize: false};// 創建Luckysheetwindow.luckysheet.create(options);});}// 獲取Excel文件中的最大行數const getMaxRowCountFromExcel = (workbook) => {let maxRowCount = 0;if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {return maxRowCount;}// 遍歷每個sheet,獲取最大行數workbook.SheetNames.forEach(sheetName => {const worksheet = workbook.Sheets[sheetName];if (worksheet['!ref'] === undefined) {return;}const range = XLSX.utils.decode_range(worksheet['!ref']);maxRowCount = maxRowCount + range.e.r;});console.log("max:", maxRowCount)return maxRowCount;}const reduceBlankRow = (row, range, worksheet) => {// 從給定的行開始,向上遍歷到工作表的起始行while (row > range.s.r) {// 假設當前行是空的let allEmpty = true;// 遍歷當前行的所有列for (let col = range.s.c; col <= range.e.c; col++) {// 獲取當前單元格的引用const cell_ref = XLSX.utils.encode_cell({c: col, r: row});// 如果當前單元格不為空,則將allEmpty設置為false并跳出循環if (worksheet[cell_ref]) {allEmpty = false;break;}}// 如果當前行是空的,則將行數減一,否則跳出循環if (allEmpty) {row--;} else {break;}}// 更新工作表范圍的結束行range.e.r = row;// 更新工作表的范圍引用worksheet['!ref'] = XLSX.utils.encode_range(range.s, range.e);}// 處理Excel文件中的空行const handleBlankRowForExcelWithTooManyBlankRow = (workbook) => {if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {return;}// 遍歷每個sheet,處理空行workbook.SheetNames.forEach(sheetName => {const worksheet = workbook.Sheets[sheetName];if (worksheet['!ref'] === undefined) {return;}const range = XLSX.utils.decode_range(worksheet['!ref']);let row = range.e.r;reduceBlankRow(row, range, worksheet);});}// 將Excel文件轉換為xlsx類型const toXlsxExcelFile = (workbook, fileName) => {const newWorkbook = XLSX.write(workbook, {bookType: 'xlsx', type: 'binary'});const data = new Uint8Array(newWorkbook.length);for (let i = 0; i < newWorkbook.length; i++) {data[i] = newWorkbook.charCodeAt(i);}return new File([data], fileName, {type: _xlsxType});}// 文件上傳控件的change事件處理函數document.getElementById('fileUpload').addEventListener('change', function (e) {// 獲取上傳的文件const file = e.target.files[0];// 處理Excel文件handleExcelFile(file);});</script></body>
</html>

效果

在這里插入圖片描述

參考

https://juejin.cn/post/7211805251216031801
https://segmentfault.com/a/1190000043720845
https://juejin.cn/post/7232524757525659708
https://blog.csdn.net/q2qwert/article/details/130908294
https://www.cnblogs.com/ajaemp/p/12880847.html
https://blog.csdn.net/weixin_40775791/article/details/135409716
https://blog.csdn.net/u013113491/article/details/129106671

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

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

相關文章

.NET 漏洞分析 | 某ERP系統存在SQL注入

01閱讀須知 此文所提供的信息只為網絡安全人員對自己所負責的網站、服務器等&#xff08;包括但不限于&#xff09;進行檢測或維護參考&#xff0c;未經授權請勿利用文章中的技術資料對任何計算機系統進行入侵操作。利用此文所提供的信息而造成的直接或間接后果和損失&#xf…

Java中s-EJB 與 e-EJB的區別

在Java中&#xff0c;關于“s-EJB”與“e-EJB”的區分&#xff0c;實際上可能存在一定的誤解或混淆&#xff0c;因為在標準的EJB&#xff08;Enterprise JavaBeans&#xff09;術語中&#xff0c;并沒有直接稱為“s-EJB”和“e-EJB”的明確分類。然而&#xff0c;為了嘗試解答這…

【Postman gRPC測試全攻略】探索微服務通信的新紀元

標題&#xff1a;【Postman gRPC測試全攻略】探索微服務通信的新紀元 gRPC是一種高性能、開源和通用的RPC框架&#xff0c;由Google主導開發&#xff0c;它使用Protocol Buffers作為接口描述語言和消息交換格式。Postman作為API開發的利器&#xff0c;也提供了對gRPC服務的測試…

封裝2個函數

1 #include "key1.h"2 //封裝EXTI章節函數3 void hal_exti_init(int exti,unsigned int i)4 {5 switch(exti)6 {7 case 9:8 //使能GPIOF外設時鐘9 RCC->MP_AHB4ENSETR | (0x1<<5);10 //將PF9設置為輸出模式11 …

MyBatis(22)如何在 MyBatis 中使用注解而不是 XML 映射文件

在 MyBatis 中&#xff0c;使用注解而不是 XML 映射文件來進行 SQL 映射是一種更為簡潔直觀的方式&#xff0c;尤其適用于 SQL 語句較少的場景。通過注解&#xff0c;開發者可以直接在接口方法上聲明 SQL 語句&#xff0c;這樣可以減少項目中的配置文件數量&#xff0c;使得項目…

學習筆記——動態路由——OSPF(認證)

十二、OSPF鄰居認證 1、OSPF鄰居認證概述 鏈路是路由器接口的另一種說法&#xff0c;因此OSPF也稱為接口狀態路由協議。OSPF通過路由器之間通告網絡接口的狀態來建立鏈路狀態數據庫&#xff0c;生成最短路徑樹&#xff0c;每個OSPF路由器使用這些最短路徑構造路由表。 OSPF認…

基于Vue框架實現的記事本

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>懶人記事本</title><style>body {fo…

深度網絡現代實踐 - 深度前饋網絡之反向傳播和其他的微分算法篇

序言 反向傳播&#xff08;Backpropagation&#xff0c;簡稱backprop&#xff09;是神經網絡訓練過程中最關鍵的技術之一&#xff0c;尤其在多層神經網絡中廣泛應用。它是一種與優化方法&#xff08;如梯度下降法&#xff09;結合使用的算法&#xff0c;用于計算網絡中各參數的…

大數據面試題之數倉(1)

目錄 介紹下數據倉庫 數倉的基本原理 數倉架構 數據倉庫分層(層級劃分)&#xff0c;每層做什么?分層的好處? 數據分層是根據什么? 數倉分層的原則與思路 知道數倉建模常用模型嗎?區別、優缺點? 星型模型和雪花模型的區別?應用場景?優劣對比 數倉建模有哪些方式…

【Symfony社區全接觸】深入探索文檔與支持資源

標題&#xff1a;【Symfony社區全接觸】深入探索文檔與支持資源 Symfony是一個強大的PHP框架&#xff0c;擁有一個活躍的開發者社區和豐富的文檔資源。這些資源對于學習和使用Symfony至關重要。本文將詳細介紹Symfony的文檔和社區支持&#xff0c;包括官方文檔、社區論壇、郵件…

如何計算弧線彈道的落地位置

1&#xff09;如何計算弧線彈道的落地位置 2&#xff09;Unity 2021 IL2CPP下使用Protobuf-net序列化報異常 3&#xff09;編譯問題&#xff0c;用Mono可以&#xff0c;但用IL2CPP就報錯 4&#xff09;Wwise的Bank在安卓上LoadBank之后&#xff0c;播放沒有聲音 這是第393篇UWA…

02 數據加工層 如何搭建用戶與內容的標準規范體系

你好&#xff0c;我是周大壯。 01 講我們提到了個性化流量分發體系的四個階段&#xff0c;并著重講解了數據采集階段的內容。那么&#xff0c;這一講我們主要圍繞數據加工階段的內容進行詳細講解。 在課程開始之前&#xff0c;我們先舉一個場景進行說明。 近年來&#xff0c…

靜態方法與實例方法的區別

靜態方法與實例方法的區別 1、靜態方法&#xff08;Static Methods&#xff09;1.1 調用方式1.2 訪問權限 2、實例方法&#xff08;Instance Methods&#xff09;2.1 調用方式2.2 訪問權限 3、總結 &#x1f496;The Begin&#x1f496;點點關注&#xff0c;收藏不迷路&#x1…

大數據面試題之數倉(2)

目錄 維度表和事實表的區別? 什么是ER模型? OLAP、OLTP解釋(區別)三范式是什么&#xff0c;舉些例子 維度設計過程&#xff0c;事實設計過程 維度設計中有整合和拆分&#xff0c;有哪些方法&#xff0c;并詳細說明 事實表設計分幾種&#xff0c;每一種都是如何在業…

【C++】解決 C++ 語言報錯:Invalid Array Index

文章目錄 引言 無效數組索引&#xff08;Invalid Array Index&#xff09;是 C 編程中常見且危險的錯誤之一。當程序試圖使用不合法的索引訪問數組時&#xff0c;就會發生無效數組索引錯誤。這種錯誤不僅會導致程序崩潰&#xff0c;還可能引發不可預測的行為和安全漏洞。本文將…

【PB案例學習筆記】-28制作一個右鍵菜單

寫在前面 這是PB案例學習筆記系列文章的第28篇&#xff0c;該系列文章適合具有一定PB基礎的讀者。 通過一個個由淺入深的編程實戰案例學習&#xff0c;提高編程技巧&#xff0c;以保證小伙伴們能應付公司的各種開發需求。 文章中設計到的源碼&#xff0c;小凡都上傳到了gite…

任天堂稱未來第一方游戲不會使用生成式AI

雖然EA、育碧、暴雪、Embracer等西方游戲廠商都大力支持生成式AI技術&#xff0c;但日本老牌游戲公司任天堂并不會追隨這一步伐。任天堂已經確認該公司未來的第一方游戲不會使用生成式AI技術。 在公司最近的投資人問答會上&#xff0c;任天堂描繪了公司未來游戲愿景。在談到AI技…

安徽農業大學學報

《安徽農業大學學報》是安徽農業大學主辦&#xff0c;國內外公開發行的綜合性農業科學類學術期刊&#xff0c;主要刊登茶葉科學、動植物遺傳育種、作物栽培、植物保護、林學、動物科學與動物醫學、水產科學、生物學、土壤學、農業生態與環境科學、園藝學、食品科學、農業機械工…

Oracle PL / SQL變量值

常量 要聲明常量&#xff0c;請在類型說明符之前放入關鍵字CONSTANT。 常量必須在其聲明中初始化。 每次輸入塊或子程序時&#xff0c;都會初始化常量。 以下代碼顯示如何定義REAL類型的常量&#xff0c;并為常量指定一個不可更改的值5。 DECLARE n_real CONSTANT RE…

51單片機第27步_單片機工作在睡眠模式

重點學習51單片機工作在睡眠模式。 1、進入“睡眠模式”的方法 通過將PCON寄存器中的PDWN置1&#xff0c;則CPU會進入“睡眠模式”。在“睡眠模式”中,晶振將停止工作&#xff0c;因此&#xff0c;定時器和串口都將停止工作&#xff0c;只有外部中斷繼續工作。如果單片機電源…