xcel文件合并工具是一款非常方便的表格合并工具,用戶能使用這款軟件將多個Excel表格進行合并至一張表中。用戶能使用這款軟件指定需要進行合并的列,還能自由的選擇需要進行合并的單元格等。軟件使用簡單易上手,并且無需安裝,解壓之后即可使用。
轉載自當游網,原文地址:
http://www.3h3.com/soft/212043.html
格元素詳解與練習
提到表格,大家最先想到的就是EXCEL這款軟件,實際上在對表格的操作上,HTML與EXCEL非常相似。
在展示數據,統計數據方面,表格比文字描述更具表達優勢,在網頁中,表格也經常被用來展示數據、計劃日常安排等內容。如圖所示:
今天我們就來學習一下如何向頁面中添加表格元素。
首先來介紹一下表格元素中的基本標簽。
NO.1:<table></table>
這個標簽是書寫表格的第一個標簽,它本身在頁面上看不出什么內容,但是它的屬性可以控制表格顯示的全局樣式。這個標簽的開始標簽寫在表格元素的開頭,結尾標簽寫在表格元素的結尾。
NO.2:<caption></caption>
這個標簽是表格的標題標簽。
NO.3:<tr></tr>
這個標簽定義表格的列標簽。
NO.4:<th></th>
這個標簽是列表標題標簽,例如,男生、女士、姓名等。
NO.5:<td></td>
這個標簽定義表格的行標簽。
OK,這些基本標簽就可以構建一個基礎的表格元素。示例代碼如下:
<table><!-- 寫在表格元素的開頭 --><caption>表格標題</caption><!-- 表格標題 --><tr>標題標簽<th>姓名</th><!-- 標題標簽 --><th>年齡</th></tr><tr><td>一列一行</td><td>一列二行</td></tr><tr><td>二列一行</td><td>二列二行</td></tr></table><!-- 寫在表格元素的結尾 -->
頁面效果如圖所示:沒有表格的外邊框。
如何添加外邊框呢?在<table>標簽中修改border屬性即可,示例代碼如下:border="1"是給表格添加寬為1的邊界線。
<table border="1"><!-- border="1"是給表格添加寬為1的邊界線 -->
效果如圖所示:
這時,您會發現表格在頁面上的尺寸非常小,可不可以按照頁面尺寸來顯示表格嗎?當然可以,這就需要為<table>標簽修改第二個屬性width,示例代碼如圖所示:width="100%"指的是表格寬度與平面寬度一致。
<table border="1" width="100%"><!-- width="100%"指的是表格寬度與平面寬度一致 -->
效果如圖所示:
ok!今天的講解先到這里,明天我會繼續為大家講解<thead></thead>、<tfoot></tfoot>、<tbody></tbody>三個標簽,以及合并單元格操作。
今天的完整代碼示例如下:
<!DOCTYPE HTML>
<html>
<head>
<title>第一個網頁</title>
</head>
<body><h1>第一個網頁</h1><hr>
<h2>表格元素</h2><hr>
<table border="1" width="100%">
<caption>表格標題</caption>
<tr>
<th>姓名</th>
<th>年齡</th>
</tr>
<tr><td>一列一行</td>
<td>一列二行</td>
</tr>
<tr>
<td>二列一行</td>
<td>二列二行</td>
</tr>
</table>
</body>
</html>
正所謂萬丈高樓平地起,html技術雖然簡單,但是內容相對繁瑣,也是以后進一步學習網頁制作的基礎,希望大家動手寫每一段代碼,把每一步踩堅實。
喜歡的小伙伴請關注我,閱讀中遇到任何問題請給我留言,如有疏漏或錯誤歡迎大家斧正,不勝感激!
HTML序章(學習目的、對象、基本概念)——零基礎自學網頁制作
HTML是什么?——零基礎自學網頁制作
第一個HTML頁面如何寫?——零基礎自學網頁制作
HTML頁面中head標簽有啥用?——零基礎自學網頁制作
初識meta標簽與SEO——零基礎自學網頁制作
HTML中的元素使用方法1——零基礎自學網頁制作
HTML中的元素使用方法2——零基礎自學網頁制作
HTML元素中的屬性1——零基礎自學網頁制作
HTML元素中的屬性2(路徑詳解)——零基礎自學網頁制作
使用HTML添加表格1(基本元素)——零基礎自學網頁制作
使用HTML添加表格2(表格頭部與腳部)——零基礎自學網頁制作
使用HTML添加表格3(間距與顏色)——零基礎自學網頁制作
使用HTML添加表格4(行顏色與表格嵌套)——零基礎自學網頁制作
16進制顏色表示與RGB色彩模型——零基礎自學網頁制作
HTML中的塊級元素與內聯元素——零基礎自學網頁制作
初識HTML中的<div>塊元素——零基礎自學網頁制作
在HTML頁面中嵌入其他頁面的方法——零基礎自學網頁制作
封閉在家學網頁制作!為頁面嵌入PDF文件——零基礎自學網頁制作
HTML表單元素初識1——零基礎自學網頁制作
HTML表單元素初識2——零基礎自學網頁制作
HTML表單3(下拉列表、多行文字輸入)——零基礎自學網頁制作
HTML表單4(form的action、method屬性)——零基礎自學網頁制作
HTML列表制作講解——零基礎自學網頁制作
為HTML頁面添加視頻、音頻的方法——零基礎自學網頁制作
音視頻格式轉換神器與html視頻元素加字幕——零基礎自學網頁制作
HTML中使用<a>標簽實現文本內鏈接——零基礎自學網頁制作
前些天看到Luckysheet支持協同編輯Excel,正符合我們協同項目的一部分,故而想進一步完善協同文章,但是遇到了一下困難,特此做聲明哈,若侵權,請聯系我刪除文章!
若侵犯版權、個人隱私,請聯系刪除哈!!!(我可不想踩縫紉機)
Luckysheet ,一款純前端類似excel的在線表格,功能強大、配置簡單、完全開源。當然,也原生支持協同,下面,我們針對協同部分做詳細講解。官網使用的是Java,也有協同的Demo,我就不說了,下面用 Node 實現協同,完整的樣例如下,我們開始吧
?
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/plugins.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/css/luckysheet.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet/dist/assets/iconfont/iconfont.css' />
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/luckysheet.umd.js"></script>
Luckysheet: Luckysheet ,一款純前端類似excel的在線表格,功能強大、配置簡單、完全開源。
https://gitee.com/mengshukeji/Luckysheet
官網建議我們在上網址下載完整的包,這樣,我們得到的是luckysheet的源碼,可以進行二次開發。很重要哈,最后我們也會這樣做。
?
npm i --s // 執行 npm 命令,進行依賴包的下載
npm run build // 執行打包命令(二次開發是需要修改源碼的)
把dist包放到自己的項目中,我已經更名了哈:
?
然后,index.html 直接引入這個地址的文件就行了(二開一定是引這個地址哈)。
<!-- 引入 luck Sheet 二次開發地址 就是你剛才 build 的那個 dist 包 -->
<link rel='stylesheet' href='./luckysheet/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='./luckysheet/dist/plugins/plugins.css' />
<link rel='stylesheet' href='./luckysheet/dist/css/luckysheet.css' />
<link rel='stylesheet' href='./luckysheet/dist/assets/iconfont/iconfont.css' />
<script src="./luckysheet/dist/plugins/js/plugin.js"></script>
<script src="./luckysheet/dist/luckysheet.umd.js"></script>
這個方式建議大家都試試,二次開發一定是這個方式哈!
如果大家覺得不用二開,就是用原生的功能 ,那直接使用 npm 下載就行了。
npm i luckysheet
<link rel='stylesheet' href='./node_modules/luckysheet/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='./node_modules/luckysheet/dist/plugins/plugins.css' />
<link rel='stylesheet' href='./node_modules/luckysheet/dist/css/luckysheet.css' />
<link rel='stylesheet' href='./node_modules/luckysheet/dist/assets/iconfont/iconfont.css' />
<script src="./node_modules/luckysheet/dist/plugins/js/plugin.js"></script>
<script src="./node_modules/luckysheet/dist/luckysheet.umd.js"></script>
<div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div>
onMounted(()=> {
// 初始化表格
var options={
container: "luckysheet", //luckysheet為容器id
};
luckysheet.create(options);
});
?
這樣就已經是一個完善的表格編輯器了,支持函數、圖表、填充等多項功能。
?
因此,我們分別配置這幾個參數:
配置loadUrl接口地址,加載所有工作表的配置,并包含當前頁單元格數據,與loadSheetUrl配合使用。參數為gridKey(表格主鍵)
$.post(loadurl, {"gridKey" : server.gridKey}, function (d) {})
源碼寫法如上,因此,我們需要創建一個 post請求的地址:
?編輯
app.use("/excel", excelRouter); // 添加公共前綴
配置 loadUrl,加了 baseURL是做了請求代理哈
allowUpdate: true,
loadUrl: "/baseURL/excel",
接口要求返回以下數據,我們直接復制,然后返回:
"[
//status為1的sheet頁,重點是需要提供初始化的數據celldata
{
"name": "Cell",
"index": "sheet_01",
"order": 0,
"status": 1,
"celldata": [{"r":0,"c":0,"v":{"v":1,"m":"1","ct":{"fa":"General","t":"n"}}}]
},
//其他status為0的sheet頁,無需提供celldata,只需要配置項即可
{
"name": "Data",
"index": "sheet_02",
"order": 1,
"status": 0
},
{
"name": "Picture",
"index": "sheet_03",
"order": 2,
"status": 0
}
]"
本例中,只返回一個sheet表,初始化 0 0 單元格內容為 ‘默認數據’
router.post("/", (req, res, next)=> {
// console.log("lucySheet");
let sheetData=[
//status為1的sheet頁,重點是需要提供初始化的數據celldata
{
name: "Cell",
index: "sheet_01",
order: 0,
status: 1,
celldata: [
{
r: 0,
c: 0,
v: { v: "默認數據", m: "111", ct: { fa: "General", t: "n" } },
},
],
},
];
res.json(JSON.stringify(sheetData));
});
?編輯
?編輯
操作表格后,實時保存數據的websocket地址,此接口也是共享編輯的接口地址。注意,發送給后端的數據默認是經過pako壓縮過后的。后臺拿到數據需要先解壓。通過共享編輯功能,可以實現Luckysheet實時保存數據和多人同步數據,每一次操作都會發送不同的參數到后臺
因此,我們需要初始化一個 ws 連接:
module.exports=()=> {
console.log("等待初始化 WS 服務...");
// 搭建ws服務器
const { WebSocketServer }=require("ws");
const wss=new WebSocketServer({ port: 9000 });
console.log(" WS 服務初始化成功,連接地址:ws://localhost:9000");
wss.on("connection", (ws, req)=> {
console.log("用戶連接");
});
};
? 打開控制臺,可以看到連接成功的提示,我們可以一下源碼是怎么處理的:
?編輯
除了看到輸出語句外,我們更應該關注一個 send 事件,因為 websocket 是通過send 發送數據的,還有的是pako.gzip()壓縮。因此,服務端監聽 message 獲取數據:
?
至此,我們可以獲取一些基礎信息:
也就是這樣,我也不知道如何進行下去了,就加了官方的微信,就發生了篇頭的那張截圖。但是革命還在繼續。加了官網微信群,特此感謝【小李飛刀刀】的指導。
?
const pako=require("pako");
/**
* @DESC 導出解壓方法
* @param { string } str
* @returns
*/
exports.unzip=(str)=> {
let chartData=str
.toString()
.split("")
.map((i)=> i.charCodeAt(0));
let binData=new Uint8Array(chartData);
let data=pako.inflate(binData);
return decodeURIComponent(
String.fromCharCode.apply(null, new Uint16Array(data))
);
};
?編輯
得到上圖,就知道該怎么辦了吧,映射的是用戶的所有操作哈。需要添加用戶標記
let id=Math.random().toString().split(".")[1].slice(0, 3);
// 需要添加自定義屬性
ws.wid=id;
ws.wname="user_" + id;
我們一定要看源碼是如何處理的哈,官網文檔并沒有那么詳細:
?
因此,同步光標的時候,我們應該發送type=3 的數據,我們封裝ws的事件響應中心:
// wss.clients 所有的客戶端
wss.clients.forEach((conn)=> {
// 不發送給自己
if (conn.wid===ws.wid) return;
// 使得 this 指向當前連接對象
wshandle.call(conn, unzip(data));
});
?
我們還沒做數據同步哈,因此數據沒有顯示,不影響,先顯示用戶光標。
/**
* ws 事件響應中心
* 根據不同的事件,返回不同的數據
* type 1 成功/失敗
* type 2 更新數據
* type 3 用戶光標
* type 4 批量處理數據
*/
function wshandle(data) {
// 表示用戶移動鼠標 實際是需要根據指令實現不同的響應的,但是這里統一做 更新數據
this.send(callbackdata.call(this, data, JSON.parse(data).t==="mv" ? 3 : 2));
}
?
至此,協同好像已經實現了,但是還沒完。
源碼中需要返回 {message ,id} 兩個數據,因此直接封裝 退出函數:
?編輯
/**
* 用戶退出
*/
function exit() {
this.send(JSON.stringify({ message: "用戶退出", id: this.wid }));
}
監聽ws close 事件:
ws.on("close", (ws)=> {
try {
// 實現用戶退出
wss.clients.forEach((conn)=> {
if (conn.wid===ws.wid) return;
// 使得 this 指向當前連接對象
exit.call(conn);
});
} catch (error) {
console.log(error);
}
});
?
?
不知道大家發現沒有,當多人協作時,我們的用戶id 是錯的,原因是我們move時,傳的參數不對:
?
// 使得 this 指向當前連接對象 ,并且保證,操作對象始終是當前用戶
wshandle.call(conn, { id: ws.wid, name: ws.wname }, unzip(data));
// 表示用戶移動鼠標 實際是需要根據指令實現不同的響應的,但是這里統一做 更新數據
// 手動傳輸 user
this.send(callbackdata(user, data, JSON.parse(data).t==="mv" ? 3 : 2));
// function callback:
return JSON.stringify({
createTime: dayjs().format("YYYYMMHH mm:hh:ss"),
data,
id: user.id,
returnMessage: "success",
status: 0,
type,
username: user.name,
});
表格操作完成后,使用luckysheet.getAllSheets()方法獲取到全部的工作表數據,全部發送到后臺存儲。
?
協同存儲就是用戶的每次操作,都會觸發 websocket,因此,我們直接在websocket中調用控制層,實現數據的更新,舉例說明:
[
{
"data":[], // 每個工作表參數組成的一維數組
"name": "Cell", //工作表名稱
"color": "", //工作表顏色
"index": 0, //工作表索引
"status": 1, //激活狀態
"order": 0, //工作表的下標
"hide": 0,//是否隱藏
"row": 36, //行數
"column": 18, //列數
"defaultRowHeight": 19, //自定義行高
"defaultColWidth": 73, //自定義列寬
"celldata": [], //初始化使用的單元格數據
"config": {
"merge":{}, //合并單元格
"rowlen":{}, //表格行高
"columnlen":{}, //表格列寬
"rowhidden":{}, //隱藏行
"colhidden":{}, //隱藏列
"borderInfo":{}, //邊框
"authority":{}, //工作表保護
},
"scrollLeft": 0, //左右滾動條位置
"scrollTop": 315, //上下滾動條位置
"luckysheet_select_save": [], //選中的區域
"calcChain": [],//公式鏈
"isPivotTable":false,//是否數據透視表
"pivotTable":{},//數據透視表設置
"filter_select": {},//篩選范圍
"filter": null,//篩選配置
"luckysheet_alternateformat_save": [], //交替顏色
"luckysheet_alternateformat_save_modelCustom": [], //自定義交替顏色
"luckysheet_conditionformat_save": {},//條件格式
"frozen": {}, //凍結行列配置
"chart": [], //圖表配置
"zoomRatio":1, // 縮放比例
"image":[], //圖片
"showGridLines": 1, //是否顯示網格線
"dataVerification":{} //數據驗證配置
},
// ... 其他 sheet 頁數據與上類似
]
上是整個sheet的配置項,數據庫表可以根據這個來構建,數據表單獨分開、樣式表也單獨分開,還有基礎配置表:
?
?
這樣就不用存儲很多無效的數據,能實現對某一條數據的精確控制與存儲,節省數據庫存儲空間。
兩種方式實現哈,先隱藏默認,然后自定定位實現添加按鈕,或者根據配置項實現配置
/deep/.luckysheet_info_detail_save,
/deep/.luckysheet_info_detail_update {
display: none;
}
?
npm i luckyexcel
綁定了一個 input ref='importFileRef'
const importFileHandle=(e)=> {
let { files }=e.target;
LuckyExcel.transformExcelToLucky(files[0], (exportJson, luckysheetfile)=> {
luckysheet.create({
container: "luckysheet", // luckysheet is the container id
data: exportJson.sheets,
title: exportJson.info.name,
userInfo: exportJson.info.name.creator,
});
// 清空
importFileRef.value.value="";
});
};
?
但是這樣會丟失協同性:
// 文件導入
const importFileHandle=(e)=> {
let { files }=e.target;
LuckyExcel.transformExcelToLucky(files[0], (exportJson, luckysheetfile)=> {
// 【會丟失協同性】
// luckysheet.create({
// container: "luckysheet", // luckysheet is the container id
// data: exportJson.sheets,
// title: exportJson.info.name,
// userInfo: exportJson.info.name.creator,
// });
let { info, sheets }=exportJson;
luckysheet.setWorkbookName(info.name);
sheets.forEach((sheet)=> {
// sheet 便是每一個 sheet 頁,需要根據實際的數量動態創建
luckysheet.setSheetAdd({
sheetObject: sheet,
});
});
// 清空
importFileRef.value.value="";
});
};
?
npm i exceljs file-saver
import Excel from "exceljs";
import FileSaver from "file-saver";
import { ElMessage } from "element-plus";
export const exportExcel=async (name, luckysheet)=> {
// 獲取 buffer
let buffer=await getBuffer(luckysheet);
download(name, buffer);
};
/**
* 使用 fileSaver 進行文件保存操作
* @param {Buffer} buffer
*/
function download(name, buffer) {
try {
const blob=new Blob([buffer], {
type: "application/vnd.ms-excel;charset=utf-8",
});
FileSaver.saveAs(blob, `${name}.xlsx`);
ElMessage.success("文件導出成功");
} catch (error) {
ElMessage.error("文件導出失敗");
}
}
/**
*
* @param { Array as luckysheet.getluckysheetfile() } luckysheet
* @returns
*/
async function getBuffer(luckysheet) {
// 參數為luckysheet.getluckysheetfile()獲取的對象
// 1.創建工作簿,可以為工作簿添加屬性
const workbook=new Excel.Workbook();
// 2.創建表格,第二個參數可以配置創建什么樣的工作表
luckysheet.every(function (table) {
if (table.data.length===0) return true;
const worksheet=workbook.addWorksheet(table.name);
// 3.設置單元格合并,設置單元格邊框,設置單元格樣式,設置值
setStyleAndValue(table.data, worksheet);
setMerge(table.config.merge, worksheet);
setBorder(table.config.borderInfo, worksheet);
return true;
});
// 4.寫入 buffer
const buffer=await workbook.xlsx.writeBuffer();
return buffer;
}
var setMerge=function (luckyMerge={}, worksheet) {
const mergearr=Object.values(luckyMerge);
mergearr.forEach(function (elem) {
// elem格式:{r: 0, c: 0, rs: 1, cs: 2}
// 按開始行,開始列,結束行,結束列合并(相當于 K10:M12)
worksheet.mergeCells(
elem.r + 1,
elem.c + 1,
elem.r + elem.rs,
elem.c + elem.cs
);
});
};
var setBorder=function (luckyBorderInfo, worksheet) {
if (!Array.isArray(luckyBorderInfo)) {
return;
}
// console.log('luckyBorderInfo', luckyBorderInfo)
luckyBorderInfo.forEach(function (elem) {
// 現在只兼容到borderType 為range的情況
// console.log('ele', elem)
if (elem.rangeType==="range") {
let border=borderConvert(elem.borderType, elem.style, elem.color);
let rang=elem.range[0];
// console.log('range', rang)
let row=rang.row;
let column=rang.column;
for (let i=row[0] + 1; i < row[1] + 2; i++) {
for (let y=column[0] + 1; y < column[1] + 2; y++) {
worksheet.getCell(i, y).border=border;
}
}
}
if (elem.rangeType==="cell") {
// col_index: 2
// row_index: 1
// b: {
// color: '#d0d4e3'
// style: 1
// }
const { col_index, row_index }=elem.value;
const borderData=Object.assign({}, elem.value);
delete borderData.col_index;
delete borderData.row_index;
let border=addborderToCell(borderData, row_index, col_index);
// console.log('bordre', border, borderData)
worksheet.getCell(row_index + 1, col_index + 1).border=border;
}
// console.log(rang.column_focus + 1, rang.row_focus + 1)
// worksheet.getCell(rang.row_focus + 1, rang.column_focus + 1).border=border
});
};
var setStyleAndValue=function (cellArr, worksheet) {
if (!Array.isArray(cellArr)) {
return;
}
cellArr.forEach(function (row, rowid) {
// const dbrow=worksheet.getRow(rowid+1);
// //設置單元格行高,默認乘以1.2倍
// dbrow.height=luckysheet.getRowHeight([rowid])[rowid]*1.2;
row.every(function (cell, columnid) {
if (rowid==0) {
const dobCol=worksheet.getColumn(columnid + 1);
//設置單元格列寬除以8
dobCol.width=luckysheet.getColumnWidth([columnid])[columnid] / 8;
}
if (!cell) {
return true;
}
//設置背景色
let bg=cell.bg || "#FFFFFF"; //默認white
bg=bg==="yellow" ? "FFFF00" : bg.replace("#", "");
let fill={
type: "pattern",
pattern: "solid",
fgColor: { argb: bg },
};
let font=fontConvert(
cell.ff,
cell.fc,
cell.bl,
cell.it,
cell.fs,
cell.cl,
cell.ul
);
let alignment=alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr);
let value="";
if (cell.f) {
value={ formula: cell.f, result: cell.v };
} else if (!cell.v && cell.ct && cell.ct.s) {
// xls轉為xlsx之后,內部存在不同的格式,都會進到富文本里,即值不存在與cell.v,而是存在于cell.ct.s之后
// value=cell.ct.s[0].v
cell.ct.s.forEach((arr)=> {
value +=arr.v;
});
} else {
value=cell.v;
}
// style 填入到_value中可以實現填充色
let letter=createCellPos(columnid);
let target=worksheet.getCell(letter + (rowid + 1));
// console.log('1233', letter + (rowid + 1))
for (const key in fill) {
target.fill=fill;
break;
}
target.font=font;
target.alignment=alignment;
target.value=value;
return true;
});
});
};
var fontConvert=function (
ff=0,
fc="#000000",
bl=0,
it=0,
fs=10,
cl=0,
ul=0
) {
// luckysheet:ff(樣式), fc(顏色), bl(粗體), it(斜體), fs(大小), cl(刪除線), ul(下劃線)
const luckyToExcel={
0: "微軟雅黑",
1: "宋體(Song)",
2: "黑體(ST Heiti)",
3: "楷體(ST Kaiti)",
4: "仿宋(ST FangSong)",
5: "新宋體(ST Song)",
6: "華文新魏",
7: "華文行楷",
8: "華文隸書",
9: "Arial",
10: "Times New Roman ",
11: "Tahoma ",
12: "Verdana",
num2bl: function (num) {
return num===0 ? false : true;
},
};
// 出現Bug,導入的時候ff為luckyToExcel的val
//設置字體顏色
fc=fc==="red" ? "FFFF0000" : fc.replace("#", "");
let font={
name: typeof ff==="number" ? luckyToExcel[ff] : ff,
family: 1,
size: fs,
color: { argb: fc },
bold: luckyToExcel.num2bl(bl),
italic: luckyToExcel.num2bl(it),
underline: luckyToExcel.num2bl(ul),
strike: luckyToExcel.num2bl(cl),
};
return font;
};
var alignmentConvert=function (
vt="default",
ht="default",
tb="default",
tr="default"
) {
// luckysheet:vt(垂直), ht(水平), tb(換行), tr(旋轉)
const luckyToExcel={
vertical: {
0: "middle",
1: "top",
2: "bottom",
default: "top",
},
horizontal: {
0: "center",
1: "left",
2: "right",
default: "left",
},
wrapText: {
0: false,
1: false,
2: true,
default: false,
},
textRotation: {
0: 0,
1: 45,
2: -45,
3: "vertical",
4: 90,
5: -90,
default: 0,
},
};
let alignment={
vertical: luckyToExcel.vertical[vt],
horizontal: luckyToExcel.horizontal[ht],
wrapText: luckyToExcel.wrapText[tb],
textRotation: luckyToExcel.textRotation[tr],
};
return alignment;
};
var borderConvert=function (borderType, style=1, color="#000") {
// 對應luckysheet的config中borderinfo的的參數
if (!borderType) {
return {};
}
const luckyToExcel={
type: {
"border-all": "all",
"border-top": "top",
"border-right": "right",
"border-bottom": "bottom",
"border-left": "left",
},
style: {
0: "none",
1: "thin",
2: "hair",
3: "dotted",
4: "dashDot", // 'Dashed',
5: "dashDot",
6: "dashDotDot",
7: "double",
8: "medium",
9: "mediumDashed",
10: "mediumDashDot",
11: "mediumDashDotDot",
12: "slantDashDot",
13: "thick",
},
};
let template={
style: luckyToExcel.style[style],
color: { argb: color.replace("#", "") },
};
let border={};
if (luckyToExcel.type[borderType]==="all") {
border["top"]=template;
border["right"]=template;
border["bottom"]=template;
border["left"]=template;
} else {
border[luckyToExcel.type[borderType]]=template;
}
// console.log('border', border)
return border;
};
function addborderToCell(borders, row_index, col_index) {
let border={};
const luckyExcel={
type: {
l: "left",
r: "right",
b: "bottom",
t: "top",
},
style: {
0: "none",
1: "thin",
2: "hair",
3: "dotted",
4: "dashDot", // 'Dashed',
5: "dashDot",
6: "dashDotDot",
7: "double",
8: "medium",
9: "mediumDashed",
10: "mediumDashDot",
11: "mediumDashDotDot",
12: "slantDashDot",
13: "thick",
},
};
// console.log('borders', borders)
for (const bor in borders) {
// console.log(bor)
if (borders[bor].color.indexOf("rgb")===-1) {
border[luckyExcel.type[bor]]={
style: luckyExcel.style[borders[bor].style],
color: { argb: borders[bor].color.replace("#", "") },
};
} else {
border[luckyExcel.type[bor]]={
style: luckyExcel.style[borders[bor].style],
color: { argb: borders[bor].color },
};
}
}
return border;
}
function createCellPos(n) {
let ordA="A".charCodeAt(0);
let ordZ="Z".charCodeAt(0);
let len=ordZ - ordA + 1;
let s="";
while (n >=0) {
s=String.fromCharCode((n % len) + ordA) + s;
n=Math.floor(n / len) - 1;
}
return s;
}
?
在excel協同的時候,還需要跟我們quill編輯器類似,綁定fileid:
updateUrl:
"ws://localhost:9000?fileid=" + router.currentRoute.value.params.fileid, // 實現傳參,
二開實現websocket的關閉連接:
// 源碼中 server.js 添加方法
closeWebSocket: function () {
let _this=this;
if ("WebSocket" in window) {
_this.websocket.close();
} else console.error("## closeWebSocket", locale().websocket.support);
},
global.api(api.js 文件)
/**
* 導出 websocket 的關閉方法:
* luckysheet.wsclose() 進行調用
*/
export function wsclose() {
console.log('調用自定義方法 server.closeWebSocket()')
server.closeWebSocket();
}
重新打包,在需要的地方進行調用:
?
但是每次關閉連接后,都會alert,把這個關了:
?
?
與文件關聯后,不是同一個文件的不能協同編輯。
到此,功能都已經開發完了。還是那句話哈:
如果侵權了,請聯系刪除!
如果侵權了,請聯系刪除!
如果侵權了,請聯系刪除!
****對luckysheet的協同做一下總結吧:
作者:樸shu
鏈接:https://juejin.cn/post/7298170736480485376
*請認真填寫需求信息,我們會在24小時內與您取得聯系。