前端界面在線excel編輯器 。node編寫post接口獲取文件流,使用傳參替換表格內容展示、前后端一把梭。

首先luckysheet插件是支持在線替換excel內容編輯得但是瀏覽器無法調用本地文件,如果只是展示,讓后端返回文件得二進制文件流就可以了,直接使用luckysheet展示。

這里我們使用xlsx-populate得node簡單應用來調用本地文件,自己寫一個接口,讓自己對后端有更一步得了解。

效果圖:

首先我們創建一個node應用

1、只是想展示文件,直接讓后端返回文件流可以跳過直接往下拉,看如何在線展示excel編輯器

2、node下載得二進制文件流,不需要展示得可以直接導出下載

前置條件:已經安裝node16以上版本

初始化項目:

1.創建項目目錄 :一個文件夾名為?my-xlsx-populate
2.文件內右鍵打開cmd? 使用命令創建? ?生成package.json:(-y使用默認配置)
npm init -y

3.package.json文件我們需要得依賴復制一下,大家直接npm i 就可以了

{"name": "my-xlsx-populate", // 項目唯一標識符"version": "1.0.0", // 初始版本號"description": "基于Excel文件操作的Node.js服務框架","main": "server.js", // 主入口文件"scripts": {"test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" // 啟動服務腳本[2](@ref)},"keywords": [], // 關鍵詞列表"license": "ISC", // 開源協議"dependencies": {"cors": "^2.8.5", // 跨域資源共享中間件,用于處理跨域請求"express": "^4.21.2", // Node.js核心Web框架,提供HTTP服務基礎能力"multer": "^1.4.5-lts.1", // 文件上傳處理中間件,支持multipart/form-data"xlsx-populate": "^1.21.0" // Excel文件操作庫,支持讀寫xlsx文件}
}

4.創建server.js文件,功能如下 。

  1. /excelprocess創建post接口
  2. 獲取body傳參循環操作xlsx-populate替換excel內容
  3. 接口返回文件流
const express = require('express');
const XlsxPopulate = require('xlsx-populate');
const path = require('path');
const fs = require('fs');
const cors = require('cors'); // 引入 cors 中間件const app = express();// 使用 cors 中間件,允許所有來源的請求
app.use(cors());// 解析 JSON 請求體
app.use(express.json());// 檢查 excelTemplates 目錄是否存在,不存在則創建
const templateDir = path.join(__dirname, 'excelTemplates');
if (!fs.existsSync(templateDir)) {fs.mkdirSync(templateDir);
}// 處理靜態文件,使得前端頁面可以被訪問
app.use(express.static(__dirname));// 處理文件處理請求
app.post('/excelprocess', async (req, res) => {try {// 獲取 excelTemplates 目錄下的所有文件const files = fs.readdirSync(templateDir);if (files.length === 0) {console.error('excelTemplates 目錄中沒有文件');return res.status(400).send('excelTemplates 目錄中沒有文件');}// 選擇第一個文件作為模板const selectedFile = path.join(templateDir, files[0]);console.log('選定模板文件:', selectedFile);// 檢查文件擴展名const fileExtension = path.extname(selectedFile).toLowerCase();if (fileExtension !== '.xlsx') {console.error('文件擴展名不正確:', fileExtension);return res.status(400).send('僅支持 .xlsx 文件');}// 檢查文件是否可讀fs.accessSync(selectedFile, fs.constants.R_OK);// 讀取 Excel 文件const workbook = await XlsxPopulate.fromFileAsync(selectedFile);console.log('成功讀取文件:', selectedFile);const sheet = workbook.sheet(0);// 獲取傳入的修改數據const modifications = req.body;// 根據傳入的數據修改 Excel 文件內容for (const [cellAddress, value] of Object.entries(modifications)) {sheet.cell(cellAddress).value(value);}// 生成修改后的文件路徑const defaultFileName = 'output.xlsx';const outputPath = path.join(__dirname, defaultFileName);// 將修改后的文件保存到磁盤await workbook.toFileAsync(outputPath);console.log('文件已保存到:', outputPath);// 對文件名進行嚴格編碼const originalFileName = req.query.filename || '修改后.xlsx'; // 使用查詢參數中的文件名或默認文件名const encodedFileName = encodeURIComponent(originalFileName).replace(/'/g, '%27');// 設置響應頭并發送文件流res.setHeader('Content-Disposition', `attachment; filename="${encodedFileName}"`);res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');// 使用流的方式發送文件const fileStream = fs.createReadStream(outputPath);fileStream.pipe(res);// 監聽文件流的錯誤fileStream.on('error', (err) => {console.error('文件流發送時出錯:', err);res.status(500).send('文件流發送時出錯');});} catch (error) {console.error('處理文件時出錯:', error.message);res.status(500).send(`處理文件時出錯: ${error.message}`);}
});// 啟動服務器
const port = 3000;
app.listen(port, () => {console.log(`服務器運行在端口 http://localhost:${port}/`);
});

5.創建excelTemplates文件夾用于存放我們要操作得本地文件,在里放入一個excel文件

全部目錄如下:

excel模板sheet設置如下:

6.運行node 服務

7.打開接口調試工具

接口類型: post

接口地址 :?http://localhost:3000/excelprocess

接口傳參:

[{"sheetName": "Sheet1", "data": {"A1": "新值1"}},{"sheetName": "Sheet2", "data": {"A1": "新值2"}},{"sheetName": "Sheet3", "data": {"A1": "新值3"}}
]

點擊下載:

打開文件內容如下:

替換成功,我們獲取到了一個替換后得二進制文件流

xlsx-populate更多具體配置請看我得另一篇文章:

前端插件使用xlsx-populate,花樣配置excel內容,根據坐添加標替換excel內容,修改顏色,合并單元格...。_xlsxpopulate-CSDN博客

接下來我們將二進制文件展示到前端接口

接下來我們使用luckysheet插件展示操作完得excel文件

使用luckysheet插件

1.克隆官方gite代碼到本地
git clone https://gitee.com/mengshukeji/Luckysheet.git
2.流水線操作-下載依賴打包得到dist文件
npm install
npm install gulp -gnpm run build

3.來到VUE項目根目錄下創建? ?public/Luckysheet
  將dist里面得文件復制到public/Luckysheet目錄下
4.來到VUE項目根目錄下luckysheet.html?

將public/Luckysheet里面得文件引入到luckysheet.html?

luckysheet.html 內容如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><link rel="icon" href="<%= BASE_URL %>favicon.ico"><title>luckysheet-wrapper</title><link rel="stylesheet" href="/Luckysheet/plugins/css/pluginsCss.css"><link rel="stylesheet" href="/Luckysheet/plugins/plugins.css"><link rel="stylesheet" href="/Luckysheet/css/luckysheet.css"><link rel="stylesheet" href="/Luckysheet/assets/iconfont/iconfont.css"><script src="/Luckysheet/plugins/js/plugin.js"></script><script src="/Luckysheet/luckysheet.umd.js"></script>
</head>
<body>
<noscript><strong>We're sorry but luckysheet-wrapper doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="sheetContainer" style="margin:0px;padding:0px;position:absolute;width:100%;height:95%;left: 0px;top: 0px;"></div>
<!-- built files will be auto injected -->
</body>
</html>

目錄結構如下:

5.界面引用Luckysheet

這里我們使用? iframe 官方得方法是把Luckysheet實列掛在到windows實列上,初始化為windows.luckysheet? 但是我想一個界面同時存在多個編輯器時候,就會出現只能有一個excel展示,我們使用iframe把luckysheet 實列用沙箱隔離,保證獨立性

<iframe :id="iframeId" height="100%" width="100%" src="/luckysheet.html" class="no-scroll"></iframe>

我得另一篇具體文章詳情:解決Luckysheet在線預覽編輯Excel、PDF.....無法在同一個界面創建多個luckysheet實列問題-CSDN博客

什么是iframe,火爆的微前端解決方案方案,教你快速看懂使用-CSDN博客

有興趣大家可以去看看哈~

6.這里為了編輯器邏輯隔離,也為了可以創建多個實列,我們把編輯器封裝為一個子組件使用:

功能邏輯:

第一步:這里我們需要引入luckyexcel ,因為luckysheet只支持展示json格式得文件,我們從node接口http://localhost:3000/excelprocess 獲取得是二進制文件流,所以要轉換。
npm install luckyexcel --save
第二步:將我們準備得 luckysheet.html 文件引入到 iframe ,設置動態id
  <iframe :id="iframeId" height="100%" width="100%" src="/luckysheet.html" class="no-scroll"></iframe>const iframeId = `iframe${Math.random().toString().substring(2)}`;

第三步:onMounted 里面 初始化 luckysheet實列
const $sheet = ref(null); // 存儲luckysheet實例
onMounted(() => {const frame = document.querySelector(`#${iframeId}`);frame.onload = () => {$sheet.value = frame.contentWindow.luckysheet;const container = frame.contentDocument.createElement('div');container.id = 'sheetContainer';frame.contentDocument.body.appendChild(container);$sheet.value.create({container: container.id});initLuckysheet(); //調用后端接口};});
第四步:調用node接口
const initLuckysheet = async () => {try {const response = await axios.post('http://localhost:3000/excelprocess',[{"sheetName": "Sheet1", "data": {"A1": "新值1"}},{"sheetName": "Sheet2", "data": {"A1": "新值2"}},{"sheetName": "Sheet3", "data": {"A1": "新值3"}}] , {responseType: 'blob'}).then(response => {const file = new File([response.data], 'XXX.xlsx', {type: response.data.type});console.log(file);var files = [];files.push(file);uploadExcel(files); //加載表單數據});} catch (error) {console.error('加載并解析 Excel 失敗:', error);}
};

第五步:接口返回數據使用 luckyexcel 轉換為json格式 初始化? luckysheet ,加載表單數據
const uploadExcel = (files) => {LuckyExcel.transformExcelToLucky(files[0], function (exportJson, luckysheetfile) {if (exportJson.sheets == null || exportJson.sheets.length == 0) return alert('讀取excel文件內容失敗, 目前不支持XLS文件!');$sheet.value.destroy();$sheet.value.create({data: exportJson.sheets,title: exportJson.info.name,userInfo: exportJson.info.name.creator,container: 'sheetContainer', // 設定DOM容器的idshowtoolbar: false, // 是否顯示工具欄showinfobar: false, // 是否顯示頂部信息欄showstatisticBar: true, // 是否顯示底部計數欄sheetBottomConfig: false, // sheet頁下方的添加行按鈕和回到頂部按鈕配置allowEdit: false, // 是否允許前臺編輯enableAddRow: false, // 是否允許增加行enableAddCol: false, // 是否允許增加列sheetFormulaBar: true, // 是否顯示公式欄enableAddBackTop: false, // 返回頭部按鈕showsheetbar: true, // 是否顯示底部sheet頁按鈕// 自定義配置底部sheet頁按鈕showsheetbarConfig: {add: false,menu: false,},});});
};
子組件eftExcel.vue 完整代碼 如下
<template><div style="height: 100%; overflow: hidden;"><div class="controls"></div><iframe :id="iframeId" height="100%" width="100%" src="/luckysheet.html" class="no-scroll"></iframe></div>
</template><script setup>
import {ref, onMounted, defineProps} from 'vue';
import axios from 'axios';
import * as LuckyExcel from 'luckyexcel';
import { ElMessage } from 'element-plus'
const iframeId = `iframe${Math.random().toString().substring(2)}`;
const $sheet = ref(null); // 存儲luckysheet實例onMounted(() => {const frame = document.querySelector(`#${iframeId}`);frame.onload = () => {$sheet.value = frame.contentWindow.luckysheet;const container = frame.contentDocument.createElement('div');container.id = 'sheetContainer';frame.contentDocument.body.appendChild(container);$sheet.value.create({container: container.id});initLuckysheet();};});const initLuckysheet = async () => {try {const response = await axios.post('http://localhost:3000/excelprocess',[{"sheetName": "Sheet1", "data": {"A1": "新值1"}},{"sheetName": "Sheet2", "data": {"A1": "新值2"}},{"sheetName": "Sheet3", "data": {"A1": "新值3"}}] , {responseType: 'blob'}).then(response => {const file = new File([response.data], 'XXX.xlsx', {type: response.data.type});console.log(file);var files = [];files.push(file);uploadExcel(files);});} catch (error) {console.error('加載并解析 Excel 失敗:', error);}
};
const uploadExcel = (files) => {LuckyExcel.transformExcelToLucky(files[0], function (exportJson, luckysheetfile) {if (exportJson.sheets == null || exportJson.sheets.length == 0) return alert('讀取excel文件內容失敗, 目前不支持XLS文件!');$sheet.value.destroy();$sheet.value.create({data: exportJson.sheets,title: exportJson.info.name,userInfo: exportJson.info.name.creator,container: 'sheetContainer', // 設定DOM容器的idshowtoolbar: false, // 是否顯示工具欄showinfobar: false, // 是否顯示頂部信息欄showstatisticBar: true, // 是否顯示底部計數欄sheetBottomConfig: false, // sheet頁下方的添加行按鈕和回到頂部按鈕配置allowEdit: false, // 是否允許前臺編輯enableAddRow: false, // 是否允許增加行enableAddCol: false, // 是否允許增加列sheetFormulaBar: true, // 是否顯示公式欄enableAddBackTop: false, // 返回頭部按鈕showsheetbar: true, // 是否顯示底部sheet頁按鈕// 自定義配置底部sheet頁按鈕showsheetbarConfig: {add: false,menu: false,},});});
};</script><style scoped>
.controls {margin-bottom: 20px;
}.no-scroll {overflow: hidden; /* 隱藏水平和垂直滾動條 */
}
</style>
第六步:父組件引入調用
<template>
<div class="index_body"><div class="container"><el-main style="height: calc(100% - 80px); position: relative; padding: 0px"><LeftExcel ></LeftExcel></el-main></div>
</div>
</template><script setup>
import LeftExcel from './leftExcel.vue'
import { ref, onMounted, onUnmounted } from 'vue'</script><style lang="scss" scoped>
.index_body{
margin-top: 50px;.container {display: flex;justify-content: space-between; /* 根據需要調整 */align-items: stretch; /* 根據需要調整 */height: 100vh; /* 根據需要調整 */
}.left-component {flex: 1; /* 根據需要調整 */margin-right: 10px; /* 根據需要調整 */
}.right-component {flex: 1; /* 根據需要調整 */margin-left: 10px; /* 根據需要調整 */
}
}
</style>

效果展示:

第六步:我們操作一下功能

接口傳參中我們可以自己修改為需要得內容

    const response = await axios.post('http://localhost:3000/excelprocess',[{"sheetName": "Sheet1", "data": {"A1": "新值1"}},{"sheetName": "Sheet2", "data": {"A1": "新值2"}},{"sheetName": "Sheet3", "data": {"A1": "新值3"}}] , {responseType: 'blob'})

我們把本地得表格添加邊框,只替換其中得值,再次展示,實際開發中我們可以提前設置好模板得樣式比如換行,合并單元格,這樣我們只要替換其中得坐標值就可以了。

大家看到這里麻煩給個贊吧!!!

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

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

相關文章

JavaScript學習20-Event事件對象

1.屬性 即點擊誰就打印出來誰 2.方法 未添加stopPropagatio方法&#xff1a; 添加stopPropagatio方法后&#xff1a;

FreeRTOS 啟動過程中 SVC 和 PendSV 的工作流程?

在 FreeRTOS 的啟動過程中,SVC(Supervisor Call) 和 PendSV(Pendable Service Call) 是兩個關鍵的系統異常,分別用于 首次任務啟動 和 任務上下文切換。它們的協作確保了從內核初始化到多任務調度的平滑過渡。以下是詳細的工作流程分析(以 ARM Cortex-M 為例): 1. SVC…

[自制調試工具]構建高效調試利器:Debugger 類詳解

一、引言 在軟件開發的漫漫征程中&#xff0c;調試就像是一位忠誠的伙伴&#xff0c;時刻陪伴著開發者解決代碼里的各類問題。為了能更清晰地了解程序運行時變量的狀態&#xff0c;我們常常需要輸出各種變量的值。而 Debugger 類就像是一個貼心的調試助手&#xff0c;它能幫我…

foobar2000 VU Meter Visualisation 插件漢化版 VU表

原英文插件點此 界面展示 下載 https://wwtn.lanzout.com/iheI22ssoybi 安裝方式 解壓安裝文件&#xff0c;文件名為&#xff1a;foo_vis_vumeter-0.10.2_CHINIESE.fb2k-component

消息中間件對比與選型指南:Kafka、ActiveMQ、RabbitMQ與RocketMQ

目錄 引言 消息中間件的定義與作用 消息中間件在分布式系統中的重要性 對比分析的四種主流消息中間件概述 消息中間件核心特性對比 消息傳遞模型 Kafka&#xff1a;專注于發布-訂閱模型 ActiveMQ&#xff1a;支持點對點和發布-訂閱兩種模型 RabbitMQ&#xff1a;支持點…

liunx輸入法

1安裝fcitx5 sudo apt update sudo apt install fcitx fcitx-pinyin 2配置為默認輸入法 設置-》系統-》區域和語言 點擊系統彈出語言和支持選擇鍵盤輸入法系統 3設置設置 fcitx-configtool 如果沒顯示需要重啟電腦 4配置fcitx 把搜狗輸入法放到第一位&#xff08;點擊下面…

WindowsPE文件格式入門05.PE加載器LoadPE

https://bpsend.net/thread-316-1-1.html LoadPE - pe 加載器 殼的前身 如果想訪問一個程序運行起來的內存,一種方法就是跨進程讀寫內存,但是跨進程讀寫內存需要來回調用api,不如直接訪問地址來得方便,那么如果我們需要直接訪問地址,該怎么做呢?.需要把dll注進程,注進去的代碼…

QGIS中第三方POI坐標偏移的快速校正-百度POI

1.百度POI&#xff1a; name,lng,lat,address 龍記黃燜雞米飯(共享區店),121.908315,30.886636,南匯新城鎮滬城環路699弄117號(A1區110室) 好福記黃燜雞(御橋路店),121.571409,31.162292,滬南路2419弄26號1層B間 御品黃燜雞米飯(安亭店),121.160322,31.305977,安亭鎮新源路792號…

SQL的調優方案

一、前言 SQL調優是提升數據庫性能的關鍵手段。需結合索引優化、SQL語句優化、執行計劃分析及數據庫架構設計等多方面綜合處理。 二、索引優化 創建合適索引 高頻查詢字段&#xff1a;對WHERE、JOIN、ORDER BY涉及的字段創建索引&#xff0c;尤其是區分度高的字段&#xff08…

【項目管理】第一部分 信息技術 1/2

相關文檔&#xff0c;希望互相學習&#xff0c;共同進步 風123456789&#xff5e;-CSDN博客 概要 知識點&#xff1a; 現代化基礎設施、數字經濟、工業互聯網、車聯網、智能制造、智慧城市、數字政府、5G、常用數據庫類型、數據倉庫、信息安全、網絡安全態勢感知、物聯網、大數…

【玩泰山派】1、mac上使用串口連接泰山派

文章目錄 前言picocom工具連接泰山派安裝picocom工具安裝ch340的驅動串口工具接線使用picocom連接泰山派 參考 前言 windows上面有xshell這個好用的工具可以使用串口連接板子&#xff0c;在mac上好像沒找到太好的工具&#xff0c;只能使用命令行工具去搞了。 之前查找說mac上…

【C++奇遇記】C++中的進階知識(繼承(一))

&#x1f3ac; 博客主頁&#xff1a;博主鏈接 &#x1f3a5; 本文由 M malloc 原創&#xff0c;首發于 CSDN&#x1f649; &#x1f384; 學習專欄推薦&#xff1a;LeetCode刷題集 數據庫專欄 初階數據結構 &#x1f3c5; 歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如…

【Scratch編程系列】Scratch編程軟件界面

Scratch是一款由麻省理工學院(MIT&#xff09; 設計開發的少兒編程工具。其特點是&#xff1a;使用者可以不認識英文單詞&#xff0c;也可以不使用鍵盤&#xff0c;就可以進行編程。構成程序的命令和參數通過積木形狀的模塊來實現。用鼠標拖動指令模塊到腳本區就可以了。 這個軟…

開篇 - 配置Unlua+VsCode的智能提示、調試以及學習方法

智能提示 為要綁定Lua的藍圖創建模板文件&#xff0c;這會在Content/Script下生成lua文件 然后點擊生成智能代碼提示&#xff0c;這會在Plugins/Unlua/Intermediate/生成Intenllisense文件夾 打開VSCode,點擊文件->將工作區另存為。生成一個空工作區&#xff0c;放置在工程…

QEMU-KVM加SPICE,云電腦誕生了

沒錯&#xff01;?QEMU-KVM SPICE? 的組合&#xff0c;本質上就是一套?輕量級云電腦&#xff08;云桌面&#xff09;?的解決方案。通過虛擬化技術將計算資源池化&#xff0c;再通過SPICE協議提供流暢的遠程桌面體驗&#xff0c;用戶用任意設備&#xff08;筆記本/平板/瘦客…

hashtable遍歷的方法有哪些

在 Java 中&#xff0c;遍歷 Hashtable&#xff08;或其現代替代品 HashMap&#xff09;有多種方式&#xff0c;以下是 6 種常用方法的詳細說明和代碼示例&#xff1a; 1. 使用 keySet() 增強 for 循環 Hashtable<String, Integer> table new Hashtable<>(); // …

如何完整遷移 Git 倉庫 ?

Git 已經成為軟件開發中版本控制和協作的事實上的標準。有時&#xff0c;開發人員可能需要將整個 Git 存儲庫 (包括其歷史記錄、分支和標記) 移動到新的位置或托管服務。在這個全面的指南中&#xff0c;我們將討論在不丟失任何關鍵數據或歷史記錄的情況下無縫地重新定位完整 Gi…

BPSK調制器的作用和基本原理

BPSK&#xff08;Binary Phase Shift Keying&#xff0c;二進制相移鍵控&#xff09;調制器是數字通信系統中的關鍵組件&#xff0c;其核心作用是將二進制數字信號轉換為模擬載波信號&#xff0c;通過相位變化傳遞信息。其具體作用的詳細說明如下&#xff1a; 一、BPSK調制器的…

LeetCode-98. 驗證二叉搜索樹

一、題目 給定一個二叉樹&#xff0c;判斷其是否是一個有效的二叉搜索樹。假設一個二叉搜索樹具有如下特征&#xff1a; 若它的左子樹不空&#xff0c;則左子樹上所有結點的值均小于它的根結點的值&#xff1b; 若它的右子樹不空&#xff0c;則右子樹上所有結點的值均大于它的…

Python菜鳥教程(小程序)

目錄 一.簡易計算器 二.學生成績分級 三.密碼設置 四.作業選擇 點贊收藏,評論支持 一.簡易計算器 print(-------使用的運算符-------\n) print(1.加號) print(2.減號) print(3.乘號) print(4.除號) Aint(input(請輸入第一個數: )) Bint(input(請輸入第二個數: )) Fi…