自学内容网 自学内容网

上传word表格识别出table表格 转为二维数组并显示(vue)

一 、在main.js引入全局JS

import JSZip from 'jszip';
export default {
     async extractWordTablesToArrays(file, callback) {
        const Zip = new JSZip();
        try {
            // 解压 Word 文档
            const zip = await Zip.loadAsync(file);
            const documentXml = await zip.file("word/document.xml").async("string");
            // 解析 XML
            const parser = new DOMParser();
            const documentDoc = parser.parseFromString(documentXml, "application/xml");
            // 获取命名空间
            const namespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
            // 获取所有表格
            const tables = documentDoc.getElementsByTagNameNS(namespace, "tbl");
            const allTables = []; // 存储所有表格的二维数组
            if (!tables || tables.length === 0) {
                console.warn("未找到表格内容,请检查 XML 结构");
                return [];
            }
            for (const table of tables) {
                const rows = table.getElementsByTagNameNS(namespace, "tr");
                const tableArray = []; // 当前表格的二维数组
                for (const row of rows) {
                    const cells = row.getElementsByTagNameNS(namespace, "tc");
                    const rowArray = []; // 当前行的数据
                    // 存储已合并的单元格
                    let colSpanInfo = [];

                    for (let i = 0; i < cells.length; i++) {
                        const cell = cells[i];
                        let cellText = "";
                        // const paragraphs = cell.getElementsByTagNameNS(namespace, "p");
                        const paragraphs = cell.getElementsByTagName("w:p");
                        // 检查合并单元格属性
                        const gridSpan = cell.getElementsByTagNameNS(namespace, "gridSpan")[0];
                        const vMerge = cell.getElementsByTagNameNS(namespace, "vMerge")[0];

                        // 获取合并信息
                        let colspan = gridSpan ? parseInt(gridSpan.getAttribute("w:val"), 10) : 1;
                        let rowspan = 1;

                        if (vMerge && vMerge.getAttribute("w:val") === "restart") {
                            rowspan = 2; // 假设合并两行
                        } else if (vMerge && !vMerge.getAttribute("w:val")) {
                            continue; // 如果是合并单元格的继续部分,则跳过
                        }

                        // 为当前单元格初始化计数器
                        const currentLevelNumbers = {};
                        for (const paragraph of paragraphs) {
                            // 提取段落编号
                            let listPrefix = "";
                            
                            // 初始化当前段落文本
                            let paragraphText = listPrefix ? `${listPrefix} ` : "";

                            const runs = paragraph.getElementsByTagName("w:r");
                            for (const run of runs) {
                                let textContent = "";
                                const texts = run.getElementsByTagName("w:t");
                                for (const text of texts) {
                                    textContent += text.textContent;
                                }

                                // 检查格式
                                const rPr = run.getElementsByTagName("w:rPr")[0];
                                let formattedText = textContent;

                                if (rPr) {
                                    const bold = rPr.getElementsByTagName("w:b").length > 0;
                                    const italic = rPr.getElementsByTagName("w:i").length > 0;
                                    const vertAlignElement = rPr.getElementsByTagName("w:vertAlign")[0];

                                    if (bold) {
                                        formattedText = `<b>${formattedText}</b>`;
                                    }
                                    if (italic) {
                                        formattedText = `<i>${formattedText}</i>`;
                                    }
                                    if (vertAlignElement) {
                                        const vertAlign = vertAlignElement.getAttribute("w:val");
                                        if (vertAlign === "superscript") {
                                            formattedText = `<sup>${formattedText}</sup>`;
                                        } else if (vertAlign === "subscript") {
                                            formattedText = `<sub>${formattedText}</sub>`;
                                        }
                                    }
                                }

                               

                                paragraphText += formattedText;
                            }

                            // 处理换行符
                            const breaks = paragraph.getElementsByTagName("w:br");
                            for (const br of breaks) {
                                paragraphText += "<br>";
                            }

                            cellText += paragraphText; // 将段落文本添加到单元格文本
                        }

                        // 更新合并单元格的信息
                        if (colSpanInfo[i]) {
                            colspan = colSpanInfo[i].colspan;
                        }

                        // 保存当前单元格信息
                        rowArray.push({
                            text: cellText,
                            colspan: colspan,
                            rowspan: rowspan
                        });

                        // 记录跨列合并
                        if (colspan > 1) {
                            for (let j = 1; j < colspan; j++) {
                                colSpanInfo[i + j] = { colspan: 0 }; // 用 0 填充后续的列合并
                            }
                        }
                    }

                    tableArray.push(rowArray); // 添加当前行到表格数组
                }

                allTables.push(tableArray); // 添加当前表格到所有表格数组
            }

            console.log("解析后的二维数组:", allTables);
            callback(allTables); // 返回处理后的 HTML
            
        } catch (error) {
            console.error("解析 Word 文件失败:", error);
            return [];
        }
    },

  getWordTablesThumbnails(tables, callback) {
        let combinedHtml = `
            <div style="display: flex; flex-wrap: wrap; gap: 16px; justify-content: start;">
        `;
    
        // 遍历每个表格,生成缩略图
        tables.forEach((table, index) => {
            let tableHtml = `
                <div 
                    style="
                        border: 1px solid #ccc; 
                        padding: 8px; 
                        width: 200px; 
                        height: 150px; 
                        overflow: hidden; 
                        position: relative; 
                        cursor: pointer;"
                    οnclick="document.getElementById('table-modal-${index}').style.display='block';"
                >
                    <div 
                        style="
                            transform: scale(0.3); 
                            transform-origin: top left; 
                            position: absolute; 
                            width: 1000px;"
                    >
                        <table 
                            border="1" 
                            style="
                                border-collapse: collapse; 
                                width: 100%; 
                                text-align: center; 
                                table-layout: auto;"
                        >
            `;
    
            table.forEach((row) => {
                tableHtml += `<tr>`;
    
                // 遍历单元格
                row.forEach((cell) => {
                    tableHtml += `
                        <td 
                            colspan="${cell.colspan || 1}" 
                            rowspan="${cell.rowspan || 1}" 
                            style=""
                        >
                          <span > ${cell.text}</span> 
                        </td>
                    `;
                });
    
                tableHtml += `</tr>`;
            });
    
            tableHtml += `
                        </table>
                    </div>
                </div>
                <!-- 模态框显示原始表格 -->
                <div 
                    id="table-modal-${index}" 
                    style="
                        display: none; 
                        position: fixed; 
                        top: 0; 
                        left: 0; 
                        width: 100%; 
                        height: 100%; 
                        background: rgba(0, 0, 0, 0.7); 
                        z-index: 9999;"
                    οnclick="this.style.display='none';"
                >
                    <div 
                        style="
                            background: #fff; 
                            margin: 50px auto; 
                            height: 80%;
                            padding: 20px; 
                            max-width: 80%;
                            box-sizing:border-box;
                            max-width: 80%; 
                            overflow: auto;"
                    >
            `;
    
            // 原始大小的表格内容
            tableHtml += `
                        <table 
                            border="1" 
                            style="
                                border-collapse: collapse; 
                                width: 100%; 
                                text-align: center; 
                                table-layout: auto;"
                        >
            `;
    
            table.forEach((row) => {
                tableHtml += `<tr>`;
    
                // 遍历单元格
                row.forEach((cell) => {
                    tableHtml += `
                        <td 
                            colspan="${cell.colspan || 1}" 
                            rowspan="${cell.rowspan || 1}" 
                            style=""
                        >
                          <span > ${cell.text}</span> 
                        </td>
                    `;
                });
    
                tableHtml += `</tr>`;
            });
            tableHtml += `
                        </table>
                    </div>
                </div>
            `;
    
            combinedHtml += tableHtml;
        });
    
        combinedHtml += `</div>`;
    
        const container = document.createElement("div");
        container.innerHTML = combinedHtml;
        callback(container.innerHTML);
    },


    },


二、页面中 点击图片上传本地文件

<template>
    <div>
        <img src="@/assets/img/word.png" alt="" style="width: 30px; height: 30px" @click="clickUpload" />
        <el-dialog
            append-to-body
            title="Add Academic Integrity Committee"
            :visible.sync="addVisible"
            width="80%"
            :close-on-click-modal="false"
        >
            <div v-html="tablesHtml" class="wordTableHtml"></div>
        </el-dialog>
    </div>
</template>
<script>
export default {
    data() {
        return {
            tablesHtml: '',
            tables: [], // 保存解析后的表格数据
            addVisible: false
        };
    },
    components: {},
    methods: {
        addVisCancle() {
            this.addVisible = false;
        },
        clickUpload() {
            this.tables = [];
            var that = this;
            const input = document.createElement('input');
            input.type = 'file';
            input.accept = '.docx'; // 限制为 Word 文件
            input.addEventListener('change', function () {
                const file = input.files[0];
                if (file) {
                    const reader = new FileReader();
                    reader.onload = function (e) {
                        that.$commonJS.extractWordTablesToArrays(file, function (wordTables) {
                            console.log('tablesHtml at line 61:', wordTables);
                            that.tables = wordTables;
                            that.$commonJS.getWordTablesThumbnails(wordTables, function (html) {
                                console.log('html at line 78:', html);
                                that.tablesHtml = html;
                                that.addVisible = true;
                            });
                            that.$emit('tables', that.tables, html);
                        });
                    };
                    reader.readAsArrayBuffer(file);
                }
            });
            input.click();
        },
    }
};
</script>

```以下样式看情况 因为我需要 上标 下标 粗体 字体 的样式
```css
<style scoped>
::v-deep .wordTableHtml b span {
    font-weight: bold !important;
}
::v-deep .wordTableHtml i span {
    font-style: italic !important;
}
::v-deep .wordTableHtml sub span {
    vertical-align: sub;
}
::v-deep .wordTableHtml sup span {
    vertical-align: super;
}
::v-deep .wordTableHtml sub {
    vertical-align: sub !important;
}
::v-deep .wordTableHtml sup {
    vertical-align: super !important;
}
::v-deep .wordTableHtml span[style*='vertical-align: super'] {
    vertical-align: super !important;
}
::v-deep .wordTableHtml span[style*='vertical-align: sub'] {
    vertical-align: sub !important;
}
::v-deep .wordTableHtml table {
    border: 0px !important;
    border-collapse: collapse; /* 去除单元格间隙 */
    width: auto;
    margin: 0 auto !important;
    table-layout: auto; /* 自动调整列宽 */
    text-align: left;
    font-family: 'Charis SIL' !important;
    font-size: 7.5pt !important;
    mso-font-kerning: 1pt !important;
    line-height: 10pt !important;
    mos-line-height: 10pt !important;
}
::v-deep .wordTableHtml table td,
.wordTableHtml table th::v-deep {
    padding: 5px;
    text-align: left !important;

    word-wrap: break-word; /* 长单词自动换行 */
    word-break: break-word;
    font-family: 'Charis SIL' !important;
    font-size: 7.5pt !important;
    mso-font-kerning: 1pt !important;
    line-height: 10pt !important;
    mos-line-height: 10pt !important;
}
::v-deep .wordTableHtml table tbody tr td {
    text-align: left !important;
    border-left: none !important;
    mso-border-left-alt: none !important;
    border-right: none !important;
    mso-border-right-alt: none !important;
    border-top: none;
    mso-border-top-alt: none !important;
    border-bottom: none !important;
    mso-border-bottom-alt: none !important;
    border: 1px dashed #dcdfe6 !important;
    border-left: 1px dashed #dcdfe6 !important;
    border-right: 1px dashed #dcdfe6 !important;
    word-break: keep-all !important;
    /* text-align: justify !important;  */
}
::v-deep .wordTableHtml table tr td p {
    display: flex;
    text-align: left !important;
    align-items: center;
    margin: 0;
    font-family: 'Charis SIL' !important;
    font-size: 7.5pt !important;
    mso-font-kerning: 1pt !important;
    line-height: 10pt !important;
    mos-line-height: 10pt !important;
}
::v-deep .wordTableHtml table span {
    color: #000000;
    text-align: left !important;
    font-family: 'Charis SIL' !important;
    font-size: 7.5pt !important;
    mso-font-kerning: 1pt !important;
    line-height: 10pt !important;
    mos-line-height: 10pt !important;
}
::v-deep .wordTableHtml table .color-highlight {
    color: rgb(0, 130, 170) !important;
    font-family: 'Charis SIL' !important;
    font-size: 7.5pt !important;
    mso-font-kerning: 1pt !important;
    line-height: 10pt !important;
    mos-line-height: 10pt !important;
}
::v-deep .wordTableHtml table tr:first-child td {
    border-top: 1px solid #000 !important;

    border-bottom: 1px solid #000 !important;
}
::v-deep .wordTableHtml table tr:last-of-type td {
    border-bottom: 1px solid #000 !important;
}
</style>

原文地址:https://blog.csdn.net/shelter123456/article/details/144295595

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!