我正在遍历一个Excel文件的Sheet 1
,该文件包含3列,其中包含100行数据(字符串),并将行中的每个单元格与Sheet 2
中的组合行进行比较。
检查应该开始逐行使用Sheet 1
,查看行中每个单元格的值是否与Sheet 2
中的任何行逐行匹配。如果检查失败,则应停止对该行的进一步检查,并开始下一个要检查的行。 Sheet 1
中无法匹配的单元格应标记为红色。
我下面的代码接近我的需要,但是如果Sheet 1
(例如Row 1: B2 and B3
)行中有2个或更多单元格与任何行都不匹配,则会抛出错误的Sheet 2
。
错误:
(node:9040) UnhandledPromiseRejectionWarning: Error: Invalid Address: Aundefined
at Object.validateAddress (C:\node_modules\exceljs\dist\es5\utils\col-cache.js:86:13)
at new module.exports (C:\node_modules\exceljs\dist\es5\doc\cell.js:29:12)
at module.exports.getCellEx (C:\node_modules\exceljs\dist\es5\doc\row.js:55:14)
at module.exports.getCell (C:\node_modules\exceljs\dist\es5\doc\row.js:72:41)
at C:\so.js:56:61
at C:\node_modules\exceljs\dist\es5\doc\worksheet.js:370:11
at Array.forEach (<anonymous>)
at module.exports.eachRow (C:\node_modules\exceljs\dist\es5\doc\worksheet.js:368:18)
at C:\so.js:16:19
at <anonymous>
(node:9040) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9040) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
示例数据:
第1页:
| COL A | COL B | COL C |
|-------|--------|--------|
| bob | one | silver |
| bob | eleven | blue |
| bob | eleven | red |
| bob | eleven | red |
| bob | one | red |
| bob | eight | red |
| bob | eight | red |
| bob | eight | red |
| terry | seven | yellow |
| terry | seven | yellow |
| terry | seven | gold |
表2:
| COL A | COL B | COL C |
|-------|--------|--------|
| bob | eleven | blue |
| bob | eleven | red |
| bob | eight | red |
| terry | seven | yellow |
| terry | seven | orange |
根据示例数据,在B1
的{{1}}中应有三个标记为红色的单元格(B5
,C11
和Sheet 1
)。例如
这是scenarios example PDF进行检查的方式:
代码:
new.xlsx
答案 0 :(得分:6)
此错误的来源是从该行进行的第二次呼叫:
if(!isdataRowOK)
在该位置,如果行中的3个单元格不正确,则变量oneOfBestMasterRowNumber
不应为undefined
,因为在变量getRow('undefined')
之后,我们将出错。因为这个原因,我们现在像下面这样检查它,并为它写入值1
(1。行号),因为在这种情况下无关紧要。
if(oneOfBestMasterRowNumber == void 0) //void 0 - undefined
oneOfBestMasterRowNumber = 1;
还有一个地方我们应该更改:而不是代码行:
if(numberOfGoodCellsInRow == 2)
oneOfBestMasterRowNumber = masterRowNumber;
我们应该写以下行:
if(numberOfGoodCellsInRow > numberOfGoodCellsInBestRow)
{
numberOfGoodCellsInBestRow = numberOfGoodCellsInRow;
oneOfBestMasterRowNumber = masterRowNumber;
}
因为行中不仅只有一个单元可能是坏的,所以。现在我们也有了新变量numberOfGoodCellsInBestRow
。
我认为最好将行中的两个或三个单元格标记为不好,但是如果只需要一行中的一个单元格,则可以在单元格着色后取消注释break;
。
另请参见以下代码中的评论:
// Import the library
var Excel = require('exceljs'),
moment = require('moment'),
// Define Excel filename
ExcelFile = 'so.xlsx',
// Read from the file
workbook = new Excel.Workbook();
workbook.xlsx.readFile(ExcelFile)
.then(function()
{
// Use workbook
var dataSheet = workbook.getWorksheet('Sheet 1'),
masterSheet = workbook.getWorksheet('Sheet 2');
dataSheet.eachRow({ includeEmpty: false }, function(dataRow, dataRowNumber)
{
var dataRowCells =
{
dataCell1: dataRow.getCell('A'),
dataCell2: dataRow.getCell('B'),
dataCell3: dataRow.getCell('C')
},
isdataRowOK = false,
oneOfBestMasterRowNumber,
cellNames = ['A','B','C'],
numberOfGoodCellsInBestRow = 0;
masterSheet.eachRow({ includeEmpty: false }, function(masterRow, masterRowNumber)
{
if(!isdataRowOK)
{
var numberOfGoodCellsInRow = 0;
for(var i = 1; i < 4; i++)
if(dataRowCells['dataCell' + i].value === masterRow.getCell(cellNames[i-1]).value)
numberOfGoodCellsInRow++;
//here we detect if 1 or 2 cells are bad
if(numberOfGoodCellsInRow > numberOfGoodCellsInBestRow)
{
numberOfGoodCellsInBestRow = numberOfGoodCellsInRow;
oneOfBestMasterRowNumber = masterRowNumber;
}
if(numberOfGoodCellsInRow == 3)
isdataRowOK = true
}
});
//here was error source: oneOfBestMasterRowNumber
//should be not undefined if 3 cells in row are bad
if(oneOfBestMasterRowNumber == void 0)//void 0 - undefined
oneOfBestMasterRowNumber = 1;
if(!isdataRowOK)
{
//here was error place: if getRow('undefined') then was error
var masterRowForCheck = masterSheet.getRow(oneOfBestMasterRowNumber);
for(var i = 1; i < 4; i++)
{
var dataCell = dataRowCells['dataCell' + i];
if(dataCell.value !== masterRowForCheck.getCell(cellNames[i-1]).value)
{
// Mark this failed cell as color red
dataCell.style = Object.create(dataCell.style); // Shallow-clone the style, break references
dataCell.fill = {type: 'pattern', pattern:'solid', fgColor:{argb:'FA8072'}}; // Set background
//break; uncomment this if you want only one cell as color red marked in the row
}
}
}
});
return workbook.xlsx.writeFile('new.xlsx');
});
}
可视化示例
我已将Node.js代码转换为客户端JavaScrpt代码,以通过在
下面的代码段中从两个不同的数据集(模仿Excel表)进行检查来演示该代码。
function checkDataset(obj)
{
var radios = obj.parentNode.elements['dataset'],
dataSetNumber,
i = radios.length;
for(; i--;)
if(radios[i].checked)
{
dataSetNumber = i;
break
}
var dataSheet = xlsFile['data' + dataSetNumber],
masterSheet = xlsFile['master' + dataSetNumber];
dataSheet.forEach(function(dataRow, dataRowIndex)
{
var dataRowCells =
{
dataCell1: dataRow.A,
dataCell2: dataRow.B,
dataCell3: dataRow.C
},
isdataRowOK = false,
oneOfBestMasterRowIndex,
cellNames = ['A','B','C'],
numberOfGoodCellsInBestRow = 0;
masterSheet.forEach(function(masterRow, masterRowIndex)
{
if(!isdataRowOK)
{
var numberOfGoodCellsInRow = 0;
for(var i = 1; i < 4; i++)
if(dataRowCells['dataCell' + i].value === masterRow[cellNames[i-1]].value)
numberOfGoodCellsInRow++;
//here we detect if 1 or 2 cells are bad
if(numberOfGoodCellsInRow > numberOfGoodCellsInBestRow)
{
numberOfGoodCellsInBestRow = numberOfGoodCellsInRow;
oneOfBestMasterRowIndex = masterRowIndex;
}
if(numberOfGoodCellsInRow == 3)
isdataRowOK = true
}
});
//oneOfBestMasterRowIndex should be not undefined if 3 cells in row are bad
if(oneOfBestMasterRowIndex == void 0)//void 0 - undefined
oneOfBestMasterRowIndex = 0;
if(!isdataRowOK)
{
var masterRowForCheck = masterSheet[oneOfBestMasterRowIndex];
for(var i = 1; i < 4; i++)
{
var dataCell = dataRowCells['dataCell' + i];
if(dataCell.value !== masterRowForCheck[cellNames[i-1]].value)
{
// Mark this failed cell as color red
dataCell.bgColor = 'red';
//break; uncomment this if you want only one cell as color red marked in the row
}
}
}
});
var table = '<table border="1"><tr style="background:#00a;color:#fff">'
+ '<th>A</th><th>B</th><th>C</th></tr>';
dataSheet.forEach(function(dataRow, dataRowIndex)
{
table += '<tr>';
for(var i in dataRow)
table += '<td bgcolor="' + (dataRow[i].bgColor ? 'red' : '')
+ '">' + dataRow[i].value + '</td>';
table += '</tr>';
});
document.write(table + '</table>');
}
function cells(strValues)
{
var v = strValues.split('\t');
return{A: {value: v[0]}, B: {value: v[1]}, C: {value: v[2]}}
}
var xlsFile =
{
//Dataset 1:
data0:
[
cells('bob sacsac sxcsc'),
cells('sacfbrb eleven blue'),
cells('ascasc one red'),
cells('tyjytn one red'),
cells('ascsac one red'),
cells('terry elf yellow'),
cells('terry seven elf'),
cells('terry elf elf'),
cells('terry elf elf'),
cells('terry seven yellow'),
cells('terry elf elf'),
cells('terry seven orange'),
cells('terry seven yellow'),
cells('santa mary jane'),
cells('bob zero mauve'),
cells('bob one silver'),
cells('bob eleven blue'),
cells('bob eleven red'),
cells('bob eleven red'),
cells('bob one red'),
cells('bob eight red'),
cells('bob eight red'),
cells('bob eight red'),
cells('terry seven yellow'),
cells('terry seven yellow'),
cells('terry seven gold')
],
master0:
[
cells('bob eleven blue'),
cells('bob eleven red'),
cells('bob eight red'),
cells('terry seven yellow'),
cells('bob seven yellow'),
cells('terry seven orange'),
cells('tiger one red')
],
//Dataset 2:
data1:
[
cells('bob one blue'),
cells('bob eleven blue'),
cells('bob eleven red'),
cells('bob eleven red'),
cells('bob one red'),
cells('bob eight red'),
cells('bob eight red'),
cells('bob eight red'),
cells('terry seven yellow'),
cells('terry seven yellow'),
cells('terry seven gold')
],
master1:
[
cells('bob eleven blue'),
cells('bob eleven red'),
cells('bob eight red'),
cells('terry seven yellow'),
cells('terry seven orange')
]
};
<form method="post" action="#">
<p><b>Which dataset do you want check?</b></p>
<label><input type="radio" name="dataset">Dataset 1</label><br>
<label><input type="radio" name="dataset" checked>Dataset 2</label><br><br>
<input type="button" value="Check it" onclick="checkDataset(this)">
</form>
圣诞快乐,新年快乐!