前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Doc纯文本迁移到Doc表格中

Doc纯文本迁移到Doc表格中

作者头像
Caleb
修改2020-11-13 15:03:14
1.2K0
修改2020-11-13 15:03:14
举报
文章被收录于专栏:乐赞分享乐赞分享

前几日,一朋友给我发来了一个文档,说是让我帮忙把文本内容复制到一个新的表格内容中。当我做完第一份后,才知道还有很多文档需要处理。所以就想着做一个工具来批量处理。

示例
示例

踩坑记录

起初是这样想的:

  • 先拿到文档的内容:因为给我的文档是.doc后缀的文件,然后通过一通readFile操作,发现读出来一堆文字乱码。索性先停掉了这部分工作。
  • 获取表格数据:最开始的想法是把表格转成HTML,然后通过设定模板的方法将内容导入。但是各种工具转成的HTML都不尽人意,没样式、文字乱码。

然后发现两条路都堵死了,那不行啊。文档实在是太多了,难道真要一个一个的去复制吗?

又找了很久,发现了一个原本忽视的内容:.docx文件,作为取代.doc的格式,他的本质是一个zip文件。

更多

docx是微软Word的文件扩展名,Microsoft Office2007之后版本使用,其基于Office Open XML标准的压缩文件格式取代了其以前专有的默认文件格式,在传统的文件名扩展名后面添加了字母“x”(即“.docx”取代“.doc”、“.xlsx”取代“.xls”、“.pptx”取代“.ppt”)。任何能够打开DOC文件的文字处理软件都可以将该文档转换为DOCX文件,docx文件比doc文件所占用空间更小,docx格式的文件本质上是一个XML文件

docx格式的文件本质上是一个ZIP文件。将一个docx文件的后缀改为ZIP后是可以用解压工具打开或是解压的。事实上,Word2007的基本文件就是ZIP格式的,他可以算作是docx文件的容器。

docx 格式文件的主要内容是保存为XML格式的,但文件并非直接保存于磁盘。它是保存在一个ZIP文件中,然后取扩展名为docx。将 .docx 格式的文件后缀改为ZIP后解压, 可以看到解压出来的文件夹中有word这样一个文件夹,它包含了Word文档的大部分内容。而其中的document.xml文件则包含了文档的主要文本内容。

百度百科-docx

有了这个信息后,我觉得应该有希望了。第一步先被搁置了,我们从第二步开始。既然有了xml文件,那么就可以使用模板来进行xml的填充了。那就开始处理表格模板。

我们先把想要的字段都用标识字符进行占位(切记使用完整且准确的英文,不然会自动切割字符)

表格模板
表格模板

有了模板以后,通过npm包adm-zip来直接解压表格模板数据。发现解压出来的document.xml里面已经包含了之前定义的标识占位符。

那么填充就显得很简单了。通过readFile读取到xml文件,然后替换的内容就完美填充到各个字段了。

到这里看起来后面的步骤已经完成了,但是第一步如何获取基础文档的内容呢。随后我在互联网的海洋中翻找了很久,找到了一个npm包@gmr-fms/word-extractor。可以直接读取到doc文档内容(在此感谢大佬)

通过@gmr-fms/word-extractor的支持,可以拿到整个文档,通过正则筛选出了我想要的字段内容,然后将内容替换给document.xml。完成内容的更改。

最后一步就是将第二步解压出来的文档文件再压缩成一个.docx文件,这里我使用的是archiver,可以直接将文件压缩为.docx

完美替换
完美替换

代码实现

先装依赖

npm i @gmr-fms/word-extractor adm-zip archiver

const fs = require('fs')
const path = require('path')

// 读取doc文档工具
const extract = require('@gmr-fms/word-extractor');
// 直接解压docx文件
var admZip = require('adm-zip');
// 压缩文件
const archiver = require('archiver');

// 在doc文件夹下存放的是将要处理的文档
var files = fs.readdirSync(path.resolve(__dirname, './doc')) 

files.forEach(i => {
    var fileName = i.split("_")[0];

    extract.fromFile(path.resolve(__dirname, './doc/' + i)).then(doc => {
        var body = doc.getBody();
        var number = body.match(/第.*单元/g)[0].split('第')[1].split('单元')[0];
        var name = body.match(/第.*课 .*/g)[0].split(' ')[1]
        var time = body.split('三、教学时间')[1].split('四、教学过程')[0].replace('\n', '').replace('\n', '');
        var target = body.split('一、教学目标')[1].split('二、教学准备')[0].replace('\n', '');
        var have = body.split('二、教学准备')[1].split('三、教学时间')[0].replace('\n', '')
        var procedure = body.split('四、教学过程')[1].replace('\n', '')

        // template下存放的是表格模板文件  index.docx 为表格模板
        var zip = new admZip(`./template/index.docx`);

        // result文件夹存放的是解压出来的表格模板文件夹
        zip.extractAllTo(`./result/${fileName}`, true);
        var xml = fs.readFileSync(`./result/${fileName}/word/document.xml`)  // 读取document.xml
        var xmlStr = xml.toString()
        // 开始替换文档
        xmlStr = xmlStr.replace(/number/g, number);
        xmlStr = xmlStr.replace(/name/g, name);
        xmlStr = xmlStr.replace(/time/g, time);
        xmlStr = xmlStr.replace(/target/g, target);
        xmlStr = xmlStr.replace(/have/g, have);
        xmlStr = xmlStr.replace(/procedure/g, procedure)
        // 重写文档
        fs.writeFileSync(`./result/${name}/word/document.xml`, xmlStr) 

        var archive = archiver('zip', {
            zlib: {
                level: 8
            }
        }).on('error', function (err) {
            throw err;
        });

        // 压缩到 zip 文件夹下的是最终生成的带表格的文档
        var output = fs.createWriteStream(__dirname + `/zip/${name}.docx`)
            .on('close', function (err) {
                if (err) {
                    console.log('关闭archiver异常:', err);
                    return;
                }
                console.log(`已生成${name}文件`);
            });

        archive.pipe(output);
        archive.directory(`./result/${name}/`, '');
        archive.finalize();
    });
})

这里主要是提供了一个思路,供大家参考。合理的转变思路可能问题解决的会更方便点。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 踩坑记录
  • 代码实现
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档