這是我寫的一段代碼,談不上高質量,但匯總了很多語言精粹。
總結一下我寫代碼的特點:
1、在開頭處注明代碼屬性,作者是誰,日期是啥,功能作甚等
2、沿襲了java代碼規范,我還是比較喜歡寫main函數,把所有功能封裝成普通函數,在main函數寫處理邏輯,這樣寫的代碼架構簡單明了
3、就是注釋啦,注釋一定要夠,代碼第一次寫問題難免會有,在閑暇時刻,我比較喜歡看自己先前寫的代碼,有改進的地方會改進改進,偶爾也會有bug和其他人閱讀,這時候注釋就很重要呢
3.1、寫注釋主要是每個函數,要注明參數的作用,函數的功能,接下來就是塊級區域,小片段功能代碼注釋,作用域廣的變量注釋
4、是命名規范了,命名規范采用駝峰命名法,變量名一定得具有代表意思,英語單詞一定要准確,我通常是在單詞本里復制過來的
5、了解耗性能的操作,字符串操作比整形運算性能低得多,遞歸算法耗內存,做循要及時退出循環,不寫死循環
6、變量要有賦初值的習慣,方便聲明變量是什么類型
const xlsx = require('xlsx')
const fpath = './user.xlsx'
/**
* auth:李金科
* func:解析帶有合並單元格的xlsx文件
* date:21-7-29
*/
function main(){
// let datas = parseXlsxData(fpath,'通訊錄',1)
let datas = parseXlsxData(fpath,0,1)
// let datas = parseXlsxData(fpath)
console.log(datas)
}
main()
// xlsx解析函數,通過路徑參數,和表名稱(沒有名稱用Sheet2表示第二張表)參數解析xlsx文件,
// 參數3為無效列數,設置無效列會把生成的數組的行數據從后向前刪除字段值
function parseXlsxData(fpath,sheetName,colNone=0){
const sourceData = xlsx.readFile(fpath, {}) // 通過xlsx庫獲取源數據
sheetName = sheetName ? sheetName : Object.keys(sourceData.Sheets).pop()
let sheetData = sourceData.Sheets[sheetName] // 獲取xlsx表數據,默認獲取第一張
if(!sheetData) return '你訪問的數據表不存在'
// 獲取行數col和列數row
let ref = sheetData['!ref']
let refParse = ref.match(/[a-z]+|[0-9]+/ig)
let col = refParse[3] - refParse[1] + 1
let row = refParse[2].charCodeAt() - refParse[0].charCodeAt() + 1
// 獲取單元格合並數據並建立數組索引
let merges = sheetData['!merges']
let mergesParses = xlsxMergeParse(merges)
let mergeIndexs = mergeIndex(mergesParses)
// 根據表的行數和列數創建一個表,在創建每個單元格時插入數據,數據填充普通單元格直接引用sheetData,
//合並單元格通過映射下標計算引用sheetData
let datas = []
for(let i = 1;i< col + 1 ;i++){
let row = []
for(let j = refParse[0].charCodeAt();j<refParse[2].charCodeAt()+1-colNone;j++){
let letter = String.fromCharCode(j)
let k = j-64
row.push(sheetData[letter+i] ? sheetData[letter+i].w : autoFill([i,k],mergeIndexs,mergesParses,sheetData))
}
datas.push(row)
}
return datas
}
// 解析單元格合並數據方法
// 解析表格單元格合並數據 把參與合並的單元格全部計算並統計位置信息
function xlsxMergeParse(merges){
let arr = []
merges.map(v=>{
let {s,e} = v
let result = []
let addNum = 1 //使數組下標加一,符合Excel單元格下標
if(s.c === e.c){
for(let i = s.r;i<e.r+1;i++){result.push([i+addNum,s.c+addNum])}
}else{
for(let i = s.c;i<e.c+1;i++){result.push([s.r+addNum,i+addNum])}
}
arr.push(result)
})
return arr
}
// 單元格合並數據建立索引
// 單元格合並數據為三維數組,為了提升數據處理效率,添加索引(變為一維數組,序列化位置信息)
function mergeIndex(mergesParse){
let datas = []
mergesParse.map((v,i) => {
let row = []
v.map((v1,i1) => {
row.push(v1.join(','))
row.push([i,i1].join('-'))
})
datas.push(row)
})
return datas.flat(Infinity)
}
// 根據單元格下標計算應該填充的值
function autoFill(point,index,mergesParses,sheetData){
// 判斷此單元格是否屬於合並單元格
let isNeed = index.indexOf(point.join(','))
if(isNeed < 0) return undefined
// 通過索引獲取映射的合並數據三維數組的下標
let target = index[isNeed+1]
let result = target.split('-')[0]
result = mergesParses[result][0]
// 返回合並單元格左上單元格數據
result = sheetData[String.fromCharCode(result[1]+64)+result[0]].w
return result
}