|
|
|
@ -413,6 +413,105 @@ export async function previewText(blobData, fileName) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 清洗工作表数据,处理可能导致 sheet_to_html 失败的特殊值 |
|
|
|
* @param {Object} worksheet - 工作表对象 |
|
|
|
* @returns {Object} 清洗后的工作表 |
|
|
|
*/ |
|
|
|
function sanitizeWorksheet(worksheet) { |
|
|
|
if (!worksheet) return worksheet |
|
|
|
|
|
|
|
// 遍历工作表中的所有单元格
|
|
|
|
Object.keys(worksheet).forEach(cellRef => { |
|
|
|
// 跳过特殊属性(如 !ref, !cols, !rows, !merges 等)
|
|
|
|
if (cellRef.startsWith('!')) return |
|
|
|
|
|
|
|
const cell = worksheet[cellRef] |
|
|
|
if (!cell) { |
|
|
|
// 如果单元格为 undefined 或 null,设置为空字符串
|
|
|
|
worksheet[cellRef] = { t: 's', v: '' } |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 处理单元格值
|
|
|
|
if (cell.v === undefined || cell.v === null) { |
|
|
|
cell.v = '' |
|
|
|
cell.t = 's' // 设置类型为字符串
|
|
|
|
} |
|
|
|
|
|
|
|
// 处理超链接 - 如果超链接目标是 undefined,移除超链接
|
|
|
|
if (cell.l && (cell.l.Target === undefined || cell.l.Target === null)) { |
|
|
|
delete cell.l |
|
|
|
} |
|
|
|
|
|
|
|
// 处理富文本 - 如果富文本数组包含 undefined 元素
|
|
|
|
if (cell.r && Array.isArray(cell.r)) { |
|
|
|
cell.r = cell.r.filter(item => item !== undefined && item !== null) |
|
|
|
if (cell.r.length === 0) { |
|
|
|
delete cell.r |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 处理公式错误
|
|
|
|
if (cell.t === 'e' && cell.v === undefined) { |
|
|
|
cell.v = '#ERROR!' |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
return worksheet |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 安全地将工作表转换为HTML |
|
|
|
* @param {Object} worksheet - 工作表对象 |
|
|
|
* @param {Object} options - 转换选项 |
|
|
|
* @returns {String} HTML字符串 |
|
|
|
*/ |
|
|
|
function safeSheetToHtml(worksheet, options = {}) { |
|
|
|
try { |
|
|
|
// 先清洗数据
|
|
|
|
const sanitizedSheet = sanitizeWorksheet(worksheet) |
|
|
|
return XLSX.utils.sheet_to_html(sanitizedSheet, options) |
|
|
|
} catch (error) { |
|
|
|
console.warn('sheet_to_html 转换失败,尝试使用 sheet_to_json 方式:', error) |
|
|
|
|
|
|
|
// 备用方案:使用 sheet_to_json 转换后再生成HTML
|
|
|
|
try { |
|
|
|
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' }) |
|
|
|
|
|
|
|
if (!jsonData || jsonData.length === 0) { |
|
|
|
return '<table><tr><td>(空工作表)</td></tr></table>' |
|
|
|
} |
|
|
|
|
|
|
|
// 手动生成HTML表格
|
|
|
|
let html = '<table>' |
|
|
|
jsonData.forEach((row, rowIndex) => { |
|
|
|
html += '<tr>' |
|
|
|
if (Array.isArray(row)) { |
|
|
|
row.forEach(cell => { |
|
|
|
const tag = rowIndex === 0 ? 'th' : 'td' |
|
|
|
// 确保cell值是字符串,处理各种类型
|
|
|
|
let cellValue = '' |
|
|
|
if (cell !== undefined && cell !== null) { |
|
|
|
cellValue = String(cell) |
|
|
|
.replace(/&/g, '&') |
|
|
|
.replace(/</g, '<') |
|
|
|
.replace(/>/g, '>') |
|
|
|
} |
|
|
|
html += `<${tag}>${cellValue}</${tag}>` |
|
|
|
}) |
|
|
|
} |
|
|
|
html += '</tr>' |
|
|
|
}) |
|
|
|
html += '</table>' |
|
|
|
return html |
|
|
|
} catch (jsonError) { |
|
|
|
console.error('备用转换方案也失败:', jsonError) |
|
|
|
return '<table><tr><td>(工作表解析失败)</td></tr></table>' |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 预览Excel文件 |
|
|
|
* @param {ArrayBuffer} arrayBuffer - 文件数据(ArrayBuffer格式) |
|
|
|
@ -423,11 +522,11 @@ export function previewExcel(arrayBuffer, fileName) { |
|
|
|
const workbook = XLSX.read(arrayBuffer, { type: 'array' }) |
|
|
|
const sheetName = workbook.SheetNames[0] |
|
|
|
const worksheet = workbook.Sheets[sheetName] |
|
|
|
const htmlString = XLSX.utils.sheet_to_html(worksheet, { editable: false }) |
|
|
|
const htmlString = safeSheetToHtml(worksheet, { editable: false }) |
|
|
|
|
|
|
|
// 预先生成所有sheet的HTML
|
|
|
|
const sheetsHtml = workbook.SheetNames.map(name => { |
|
|
|
return XLSX.utils.sheet_to_html(workbook.Sheets[name], { editable: false }) |
|
|
|
return safeSheetToHtml(workbook.Sheets[name], { editable: false }) |
|
|
|
}) |
|
|
|
|
|
|
|
// 创建预览窗口
|
|
|
|
|