Источником этой ошибки был второй вызов из строки:
if(!isdataRowOK)
В этом месте переменная oneOfBestMasterRowNumber
должна быть не undefined
, если 3 ячейки в строке плохие, потому что после нее, если 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>
С Новым годом и Рождеством!