JavaScript xlsx自己导入任意excel文件的表头复杂并且数据有合并单元格和空数据怎么处理成json的完全案例
时间: 2024-02-17 20:59:56 浏览: 255
好的,我来为您解答。
首先,我们需要使用`xlsx`库来读取Excel文件并将其转换为JSON格式。在处理复杂表头和合并单元格时,我们需要使用`xlsx`的`utils`模块中的一些函数来帮助我们解析数据。以下是完整的代码示例:
```javascript
const XLSX = require('xlsx');
function importExcel(file) {
const workbook = XLSX.readFile(file);
const sheet_name_list = workbook.SheetNames;
const data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]], {
header: 1,
defval: null,
});
// 获取表头行数
let headerRowCount = 1;
for (let i = 0; i < data.length; i++) {
if (data[i].filter((c) => c !== null).length > data[headerRowCount - 1].filter((c) => c !== null).length) {
headerRowCount = i + 1;
}
}
// 处理表头
const header = data.slice(0, headerRowCount).reduce((arr, row) => {
const mergedIndexes = [];
for (let i = 0; i < row.length; i++) {
if (row[i] === null) {
if (mergedIndexes.some((idx) => idx === i)) {
continue;
}
const prev = arr[arr.length - 1];
if (prev) {
const last = prev[prev.length - 1];
const mergedCount = last.mergedCount || 1;
last.mergedCount = mergedCount + 1;
mergedIndexes.push(i);
}
} else {
arr.push([{ value: row[i] }]);
}
}
return arr;
}, []);
// 处理数据行
const rows = data.slice(headerRowCount).reduce((arr, row) => {
const mergedIndexes = [];
const dataRow = [];
for (let i = 0; i < row.length; i++) {
if (row[i] === null) {
if (mergedIndexes.some((idx) => idx === i)) {
continue;
}
const prev = dataRow[dataRow.length - 1];
const mergedCount = prev ? prev.mergedCount || 1 : 1;
const cell = { ...prev, mergedCount };
dataRow[dataRow.length - 1] = cell;
mergedIndexes.push(i);
} else {
dataRow.push({ value: row[i] });
}
}
arr.push(dataRow);
return arr;
}, []);
// 合并表头和数据行
const result = rows.map((row) => {
const obj = {};
header.forEach((col, i) => {
const cell = row[i];
if (cell) {
const { value, mergedCount } = cell;
if (mergedCount > 1) {
obj[value] = row[i + mergedCount - 1].value;
} else {
obj[value] = cell.value;
}
}
});
return obj;
});
return result;
}
```
这里的`importExcel`函数接收一个Excel文件路径作为参数,并返回一个JSON数组。在此函数中,我们首先使用`XLSX`库将Excel文件读入`workbook`对象中。然后,我们使用`sheet_to_json`函数将工作簿中的第一个工作表转换为JSON格式。为了处理复杂表头和合并单元格,我们需要做以下几件事情:
1. 获取表头行数:我们需要找出表头占用的行数。为此,我们可以遍历整个数据数组并找到表格中具有最大列数的行。这通常是表头行。
```javascript
let headerRowCount = 1;
for (let i = 0; i < data.length; i++) {
if (data[i].filter((c) => c !== null).length > data[headerRowCount - 1].filter((c) => c !== null).length) {
headerRowCount = i + 1;
}
}
```
2. 处理表头:我们需要将表头行转换为一个嵌套数组,其中每个单元格都是一个对象,该对象包含单元格值和可能的合并单元格数。为此,我们可以遍历表头行并查找空单元格。如果单元格为空,则表示该单元格与前面的单元格合并,我们需要将其与前面的单元格一起处理。如果单元格不为空,则表示该单元格是一个新的表头单元格。
```javascript
const header = data.slice(0, headerRowCount).reduce((arr, row) => {
const mergedIndexes = [];
for (let i = 0; i < row.length; i++) {
if (row[i] === null) {
if (mergedIndexes.some((idx) => idx === i)) {
continue;
}
const prev = arr[arr.length - 1];
if (prev) {
const last = prev[prev.length - 1];
const mergedCount = last.mergedCount || 1;
last.mergedCount = mergedCount + 1;
mergedIndexes.push(i);
}
} else {
arr.push([{ value: row[i] }]);
}
}
return arr;
}, []);
```
3. 处理数据行:我们需要将数据行转换为一个嵌套数组,其中每个单元格都是一个对象,该对象包含单元格值和可能的合并单元格数。为此,我们可以遍历每一行并查找空单元格。如果单元格为空,则表示该单元格与前面的单元格合并,我们需要将其与前面的单元格一起处理。如果单元格不为空,则表示该单元格是一个新的数据单元格。
```javascript
const rows = data.slice(headerRowCount).reduce((arr, row) => {
const mergedIndexes = [];
const dataRow = [];
for (let i = 0; i < row.length; i++) {
if (row[i] === null) {
if (mergedIndexes.some((idx) => idx === i)) {
continue;
}
const prev = dataRow[dataRow.length - 1];
const mergedCount = prev ? prev.mergedCount || 1 : 1;
const cell = { ...prev, mergedCount };
dataRow[dataRow.length - 1] = cell;
mergedIndexes.push(i);
} else {
dataRow.push({ value: row[i] });
}
}
arr.push(dataRow);
return arr;
}, []);
```
4. 合并表头和数据行:最后,我们需要将表头和数据行合并到一起。为此,我们可以遍历每一行并为每一列创建一个对象键。然后,我们可以使用单元格的值填充对象的键值。如果单元格具有合并单元格,则我们需要跳过该单元格的后续单元格,以便正确地填充对象的键值。
```javascript
const result = rows.map((row) => {
const obj = {};
header.forEach((col, i) => {
const cell = row[i];
if (cell) {
const { value, mergedCount } = cell;
if (mergedCount > 1) {
obj[value] = row[i + mergedCount - 1].value;
} else {
obj[value] = cell.value;
}
}
});
return obj;
});
return result;
```
现在,我们可以使用`importExcel`函数来将任意Excel文件转换为JSON格式。如果Excel文件具有复杂的表头和合并单元格,则该函数也可以正确处理。
阅读全文