鄧杰海
(江西中醫(yī)藥高等??茖W(xué)校教育技術(shù)中心,撫州344000)
在計(jì)算機(jī)課程的實(shí)踐教學(xué)中,上機(jī)實(shí)踐操作課占的比重較大。在上機(jī)過(guò)程中,教師有時(shí)需要在機(jī)房的教師電腦端給學(xué)生演示軟件的操作,需要將教師端的電腦屏幕實(shí)現(xiàn)發(fā)送給學(xué)生電腦端;或者在學(xué)生上機(jī)過(guò)程中,也需要實(shí)時(shí)監(jiān)控學(xué)生的桌面,關(guān)注學(xué)生在上機(jī)過(guò)程中的一舉一動(dòng),防備學(xué)生上機(jī)課開小差,操作一些與上課無(wú)關(guān)的軟件應(yīng)用,如打游戲、看電影或看小說(shuō)。為了實(shí)現(xiàn)以上兩個(gè)目的,使用一套計(jì)算機(jī)機(jī)房教學(xué)輔助軟件還是很有必要的。在日常教學(xué)中教學(xué)輔助軟件也應(yīng)用了幾個(gè),或多或少都存在一些問(wèn)題,不能完全滿足要求,因此需要自主開發(fā)一套機(jī)房輔助軟件。
開發(fā)機(jī)房輔助軟件的功能模塊中,有一個(gè)模塊實(shí)現(xiàn)的功能是將上課班級(jí)學(xué)生的名單導(dǎo)入,并在Electron渲染進(jìn)程中將班級(jí)名單顯示出來(lái),在軟件界面中要響應(yīng)鼠標(biāo)事件,將鼠標(biāo)停留的學(xué)生信息能突出的顯示來(lái),從而可以快速地定位到需要關(guān)注的學(xué)生的電腦上。本文的范圍為將Electron 怎么導(dǎo)入Excel 表格,JavaScript編程語(yǔ)言怎么實(shí)現(xiàn)這些功能并操作DOM。以下就各部分的功能及實(shí)現(xiàn)的源代碼進(jìn)行說(shuō)明。
在編寫本部分的軟件實(shí)現(xiàn)過(guò)程中,導(dǎo)入文件使用到的是input type=file 元素來(lái)實(shí)現(xiàn)本地文件的導(dǎo)入。通過(guò)input type=file 元素,可以得到本地文件的file 對(duì)象。如果直接使用input type=file 元素,由Chromium開源引擎渲染之后界面不大美觀。為了解決這個(gè)問(wèn)題,需要引用CSS 技術(shù),對(duì)input type=file 元素進(jìn)行處理。文章的篇幅有限,此處就不將Html 語(yǔ)言和CSS 文本樣式計(jì)算機(jī)語(yǔ)言寫上。
如圖1 所示,在沒(méi)有經(jīng)過(guò)CSS 語(yǔ)言處理,input type=file 的外觀確實(shí)不美觀。在經(jīng)過(guò)CSS 語(yǔ)言處理和HTML 語(yǔ)言定義之后,就可以得到如圖2 所示的外觀界面。
圖1 未經(jīng)處理的界面
圖2 經(jīng)過(guò)處理的選擇班級(jí)的界面
將要導(dǎo)入的Excel 表頭如圖3 所示。
圖3 導(dǎo)入的Excel文件表頭結(jié)構(gòu)
利用JS-XLSX 工具庫(kù)將Excel 文件導(dǎo)入渲染進(jìn)程的程序清單如下:
var XLSX=require('xlsx');
var Electron=require('Electron').remote;
var stuinfo=require('./stuinfo');
var userinterface=require('./userInterface');
var process_wb=(function(){
return function process_wb(wb){
wb.SheetNames.forEach(function(sheetName){
var worksheet=wb.Sheets[sheetName];//獲得工作表對(duì)象
var colNumArr=['A','B','C','D','E','F','G','H','I','J','K','L','M','N'];
//用于Excel 表格每行的編號(hào)
var i=2;
var j=0;
//var cell_address='A2';
var rowVal=[];
//獲得單元格地址
var cell_address=colNumArr[0]+i;
//獲得單元格地址相對(duì)應(yīng)的單元格對(duì)象
var cell_obj=worksheet[cell_address];
//獲得對(duì)應(yīng)單元格地址的源數(shù)據(jù),如果不是undefined 則表示單元格有數(shù)據(jù),進(jìn)入循環(huán)進(jìn)行處理
var cell_val=(cell_obj?cell_obj.v:undefined);
//如果單元格的源數(shù)據(jù)不為undefined,則進(jìn)入循環(huán)進(jìn)行處理
while(cell_val){
if(cell_val){
//用于存放獲得的單元格數(shù)據(jù)的數(shù)組的下標(biāo)
j=0;
//對(duì)Excel 表格A~N 列的數(shù)據(jù)進(jìn)行處理
colNumArr.forEach(function(colNum){
//取到第i 行每一列的單元格地址
cell_address=colNum+i;
//獲得對(duì)應(yīng)單元格地址的單元格對(duì)象
cell_obj=worksheet[cell_address];
//獲得相應(yīng)單元格的源數(shù)據(jù)
rowVal[j++]=cell_obj.v;
});
//console.log(rowVal);
//獲得的一行的單元格數(shù)據(jù)push 入存放學(xué)生信息的stuinfo 數(shù)組,并同時(shí)在渲染進(jìn)程顯示
stuinfo.appendStu(rowVal);
//調(diào)用渲染進(jìn)程函數(shù),將學(xué)生的姓名與學(xué)號(hào)信息在渲染進(jìn)程的界面中顯示出來(lái)
userInterface.initSrc(rowVal[0],rowVal[1]);
//將存放每行單元格數(shù)據(jù)的臨時(shí)數(shù)組清空,準(zhǔn)備存放下一個(gè)學(xué)生信息
rowVal.length=0;
}
//調(diào)到Excel 表格的下一行
i++;
cell_address=colNumArr[0]+i;
cell_obj=worksheet[cell_address];
cell_val=(cell_obj?cell_obj.v:undefined);
}
});
};
})();
var do_file=(function(){
return function do_file(files){
var f=files[0];
var reader=new FileReader();
reader.onload=function(e){
var data=e.target.result;
//獲得Excel 表格的無(wú)符號(hào)單字節(jié)的數(shù)組
data=new Uint8Array(data);
//調(diào)用JS-XLSX 工具庫(kù)函數(shù)process_wb 對(duì)數(shù)組進(jìn)行處理
process_wb(XLSX.read(data,{type:'array'}));
};
reader.readAsArrayBuffer(f);
};
})();
(function(){
var xlf=document.getElementById('selectFile');
function handleFile(e){
if(e.target.files.length===0){
return;
}
let filePath=$(this).val();
let urlArr=filePath.split("\");
let fileName=urlArr[urlArr.length-1];
$(".fileName").val(fileName);
userinterface.clearScrn();
do_file(e.target.files);
}
//調(diào)用input type=file 元素的change 事件獲得打開的Excel文件的File 對(duì)象
xlf.addEventListener('change',handleFile,false);})();
以上程序清單中的函數(shù)來(lái)自GitHub 地址:https://github.com/SheetJS/js-xlsx,對(duì)相關(guān)的函數(shù)作了一些修改,在相關(guān)的Demo 程序中,沒(méi)有將Excel 的每個(gè)單元格進(jìn)行處理,而是使用XLSX.utils.sheet_to_html 函數(shù)將Excel 表格中的數(shù)據(jù)直接顯示在div 元素中。如此處理顯然不能滿足要求,根據(jù)圖3 所示的Excel 表頭,修改了一下GitHub 地址所提供的程序源代碼,如上面的process_wb(wb)函數(shù),對(duì)上課班級(jí)中的每個(gè)學(xué)生信息進(jìn)行處理。
在將Excel 本地文件中的數(shù)據(jù)導(dǎo)入內(nèi)存數(shù)組中同時(shí),也將學(xué)生的學(xué)號(hào)和姓名信息在渲染進(jìn)程的界面中顯示出來(lái),如圖4 所示是在導(dǎo)入學(xué)生信息之前的界面,圖5 是導(dǎo)入學(xué)生信息之后的界面。
圖4 導(dǎo)入Excel文件之前渲染進(jìn)程的界面
圖5 導(dǎo)入Excel學(xué)生信息之后的渲染進(jìn)程界面
以上就是導(dǎo)入班級(jí)信息之后再調(diào)用渲染進(jìn)程的initSrc 函數(shù),將學(xué)生的姓名和學(xué)號(hào)在渲染進(jìn)程的主界面中顯示出來(lái),源代碼如下,文章篇幅有限,就沒(méi)有將渲染進(jìn)程界面中的CSS 文本樣式計(jì)算機(jī)語(yǔ)言寫上:
//初始化屏幕界面
function initSrc(stuXh,stuXm){
if(!document)document=window.document;
const mainArea=document.getElementById('main-areaDJH');
const template=document.querySelector('#scr-maintemp');
let clone=document.importNode(template.content,true);
clone.querySelector('img').src='./public/nologin.svg';
clone.querySelector('img').setAttribute('id',stuXh);
clone.querySelector('.stuXhmain').innerText=stuXh;
clone.querySelector('.stuXmmain').innerText=stuXm;
mainArea.appendChild(clone);
const scrleft=document.getElementById('page-wrapperDJH');
const lefttemp=document.querySelector('#scr-lefttemp');
let clone2=document.importNode(lefttemp.content,true);
clone2.querySelector('.leftXh').innerText=stuXh;
clone2.querySelector('.leftXm').innerText=stuXm;
scrleft.appendChild(clone2);
}
渲染進(jìn)程對(duì)應(yīng)的index.html 文件如下:
在實(shí)現(xiàn)本文論述的功能過(guò)程中,在網(wǎng)上找了好多的資料,也學(xué)到了很多的東西。但網(wǎng)上的資料都不是太齊全,很多程序源代碼還要靠自己寫出來(lái)。通過(guò)使用Electron 結(jié)構(gòu)技術(shù)開發(fā)桌面程序之后,發(fā)現(xiàn)使用JavaScript 語(yǔ)言開發(fā)桌面程序有天然的優(yōu)勢(shì),特別應(yīng)用CSS 文本樣式計(jì)算機(jī)語(yǔ)言設(shè)計(jì)渲染進(jìn)程的界面非常方便,網(wǎng)上資料也非常多,感覺比傳統(tǒng)的桌面開發(fā)工具C#、Delphi 和VC 做界面還方便。