我正在用javascript阅读Excel文件。
其中一个单元格具有VLOOKUP
公式:
VLOOKUP(C40,D107:F114,3,FALSE) //(searched value, table range, returned value column, exact match)
它的基本作用是在C40
表范围(起点和终点)中搜索D107 -> F114
上的值,然后在3
列上返回该值。此示例-F
列。 FALSE
表示我们正在寻找完全匹配的内容。
我需要提取在公式D107:F114
(3
列(D
,E
,F
),8
上定义的表单元格(107
,108
,109
等)并将其内容保存在代码中。
这是我所做的-很好,我想知道是否有更短的方法来做到这一点:
const formula = sheet.cell('A40').formula()
var splittedFormula = formula.split(/[\s,]+/) //split formula by params -> splittedFormula = [C40, D107:F114, 3, FALSE]
const numOfColumns = splittedFormula[2] //geting the total number of columns by the third param- "returned value column" -> numOfColumns = 3
let numOfCells = splittedFormula[1].split(/[\s:]+/) //get the start point of the table -> numOfCells = [D107, F114]
let startingCell = numOfCells[0].replace(/\D/g, '') //extract the starting cell -> startingCell = 107
let startingColumn = numOfCells[0].replace(/\d+/g, '') //extract the starting column -> startingColumn = D
numOfCells =
numOfCells[1].replace(/\D/g, '') - numOfCells[0].replace(/\D/g, '') + 1 //calculate how many cells on each column by substracting the start point cell from the end point cell (`114 - 107`) -> numOfCells = 8
var table = new Array(numOfColumns) //defining an array of arrays -> table = [3]
let currentCell
//loop through the table in the excel sheet and save it's content each column is an array that store the cells value. table = [3][8]
for (var i = 0; i < numOfColumns; i++) { //numOfColumns=3
table[i] = new Array(numOfCells) //numOfCells=8
currentCell = startingCell
for (var j = 0; j < numOfCells; j++) {
table[i][j] = sheet.cell(startingColumn + currentCell).value()
currentCell = parseFloat(currentCell) + 1 //increment to the next cell i.e. 107 + 1 = 108 etc..
}
startingColumn = String.fromCharCode(startingColumn.charCodeAt() + 1) //increment to the next column i.e. D + 1 = F etc..
}
答案 0 :(得分:1)
第一个“最小化”(也是最重要的一个)是检查您的sheet
实例是否允许提取切片(等同于您尝试提取的子矩阵或表)。
您可以通过更通用的方式
let formula = 'D107:F114'
let [colStart, rowStart, colEnd, rowEnd] = formula.match(/([A-Z]+)(\d+):([A-Z]+)(\d+)/).slice(1);
//[ colStart='D', rowStart='107', colEnd='F', rowEnd='114' ]
rowStart = parseInt(rowStart);
rowEnd = parseInt(rowEnd);
colStart = colStart.charCodeAt()-65;
colEnd = colEnd.charCodeAt()-65;
请注意,这里您可能有AA或ZZ之类的列,因此您可能希望相应地适应colStart
和colEnd
的转换
map
代替for循环let table = Array(colEnd-colStart+1).fill(0).map((_, j)=>{
return Array(rowEnd-rowStart+1).fill(0).map((_, i)=>{
let col = colStart + j;
let row = rowStart + i;
return sheet.cell(String.fromCharCode(col+65)+row).value();
})
})
关于AA或ZZ,下面是一种将它们来回转换为int的算法,但是再次可能依赖于您的库,因为无论如何它都必须解析您的字符串。
let sheet = {
cell(x){return {value(){return x}}}
}
//not used, but enough to handle single letters...
function toColIdx(s){
return s.charCodeAt()-'A'.charCodeAt();
}
function idxToCol(idx){
return String.fromCharCode(idx+'A'.charCodeAt())
}
let base = (function(){
let idxToChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
let charToIdx = idxToChar.reduce((acc, f,i)=>(acc[f] = i+1, acc),{})
//I have checked the identity of idxToCol == idxToCol(toColIdx(idxToCol)) up to 16384
return {
toColIdx(s){
return s.split('')
.reverse()
.reduce((acc,c,i)=>acc+charToIdx[c]*Math.pow(26,i),0);
},
idxToCol(idx){
if(idx==1)return 'A';
let n = Math.ceil(Math.log(idx)/Math.log(26));
s = '';
for(let i = 0; i<n; ++i){
let x = idx % 26;
if(x != 0){
s = idxToChar[x-1] + s;
idx-=x;
idx /= 26;
}else{
s = 'Z' + s;
idx-=26;
idx /= 26;
if(idx==0) return s;
}
}
return s;
}
}
})();
function extract(sheet, formula){
let [colStart, rowStart, colEnd, rowEnd] = formula.match(/([A-Z]+)(\d+):([A-Z]+)(\d+)/).slice(1);
//[ colStart='D', rowStart='107', colEnd='F', rowEnd='114' ]
rowStart = parseInt(rowStart);
rowEnd = parseInt(rowEnd);
colStart = base.toColIdx(colStart)
colEnd = base.toColIdx(colEnd)
return Array(colEnd-colStart+1).fill(0).map((_, j)=>{
return Array(rowEnd-rowStart+1).fill(0).map((_, i)=>{
let col = colStart + j;
let row = rowStart + i;
return sheet.cell(base.idxToCol(col)+row).value();
})
})
}
console.log(JSON.stringify(extract(sheet, 'A107:D114'),null,2))
console.log(JSON.stringify(extract(sheet, 'BZ107:CA114'),null,2))