前言

最近遇到了一个需求,就是要把大量的doc格式文件转换为docx文件,因此就动手做了一个批量转换的小工具。

背景

doc文件是什么?

"doc" 文件是一种常见的文件格式,通常用于存储文本文档。它是 Microsoft Word 文档的文件扩展名。"doc" 是 "document" 的缩写,表示这是一个文档文件。这种文件格式通常包含文本、图像、表格、图形等内容,可以使用 Microsoft Word 或其他兼容的文字处理软件进行打开和编辑。

docx文件是什么?

"docx" 文件是 Microsoft Word 2007 及更高版本中使用的文档文件格式的扩展名。它是 Office Open XML (OOXML) 标准的一部分,是一种基于 XML 的开放标准格式,用于存储文本文档、图像、表格、图形等内容。与早期的 ".doc" 格式相比,".docx" 格式具有更高的兼容性和可扩展性,并且文件大小通常更小。由于其开放的特性,许多其他文字处理软件也支持 ".docx" 格式。

为什么要将doc文件转化为docx文件?

将 ".doc" 文件转换为 ".docx" 文件的主要原因包括:

  1. 更先进的格式:".docx" 使用 Office Open XML 格式,这是一种更现代、更有效的文件格式。它采用了基于 XML 的结构,使得文件更容易解析和处理,同时也提供了更好的兼容性和可扩展性。
  2. 减小文件大小:由于 ".docx" 文件采用了更高效的压缩技术和文件结构,相比 ".doc" 文件通常会更小,这对于存储和传输文件是有利的。
  3. 兼容性:许多最新版本的文字处理软件更支持 ".docx" 格式,而较旧的 ".doc" 格式可能会在一些软件中出现兼容性问题。将文件转换为 ".docx" 格式可以确保在不同平台和软件中的良好兼容性。
  4. 格式稳定性:".docx" 格式的结构更加稳定,不容易出现文件损坏或格式错误的问题,从而提高了文档的可靠性。

综上所述,将 ".doc" 文件转换为 ".docx" 文件可以提高文件的效率、兼容性和稳定性,是一种值得推荐的做法。

实践

方案使用C#通过Microsoft Office Interop实现将.doc文件转换为.docx文件。

添加引用:

前提是需要电脑上安装有word。

页面设计如下所示:

选择doc文件所在的文件夹:

   // 创建一个新的FolderBrowserDialog
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); // 设置FolderBrowserDialog的属性
folderBrowserDialog.Description = "请选择待转换的doc文件所在的文件夹"; // 显示FolderBrowserDialog,并获取结果
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
docFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"你选择的待转换的doc文件所在的文件夹是:{docFolderPath}\r\n";
}

选择保存docx文件的文件夹:

 // 创建一个新的FolderBrowserDialog
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); // 设置FolderBrowserDialog的属性
folderBrowserDialog.Description = "请选择保存docx文件的文件夹"; // 显示FolderBrowserDialog,并获取结果
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
// 用户已选择一个文件夹,可以通过folderBrowserDialog.SelectedPath获取所选文件夹的路径
docxFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"你选择的保存docx文件的文件夹是:{docFolderPath}\r\n";
}

开始转换按钮事件处理函数:

 if (docFolderPath == null || docxFolderPath == null)
{
MessageBox.Show("请先选择doc文件所在的文件夹与保存docx文件的文件夹");
}
else
{ await DocToDocx();
}

为了避免阻塞界面,使用了异步方法。

DocToDocx方法如下所示:

  public async System.Threading.Tasks.Task DocToDocx()
{
// 使用Task.Run来启动一个新的异步任务
await System.Threading.Tasks.Task.Run(() =>
{
// 创建 Word 应用程序实例
Microsoft.Office.Interop.Word.Application wordApp = new Microsoft.Office.Interop.Word.Application(); int i = 1;
// 遍历所有.doc文件
foreach (string docFile in GetFiles(docFolderPath, "*.doc"))
{
// 打开输入的 .doc 文件
Document doc = wordApp.Documents.Open(docFile); // 获取不带扩展名的文件名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(docFile); // 将扩展名改为.docx
string docxFileName = Path.ChangeExtension(fileNameWithoutExtension, ".docx"); string docxFilePath = Path.Combine(docxFolderPath, docxFileName); // 将 .doc 文件保存为 .docx 格式
doc.SaveAs2(docxFilePath, WdSaveFormat.wdFormatXMLDocument); // 关闭 .doc 文件
doc.Close(); // 释放 Document 对象的资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc); // 使用Invoke方法来更新richTextBox1
richTextBox1.Invoke((Action)(() =>
{
richTextBox1.Text += $"第{i}个文件:{docFile}转换完成 {DateTime.Now}\r\n"; // 设置插入点到文本的最后
richTextBox1.SelectionStart = richTextBox1.Text.Length; // 滚动到插入点
richTextBox1.ScrollToCaret();
})); i++;
} // 退出 Word 应用程序
wordApp.Quit(); // 释放资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp); // 使用Invoke方法来更新richTextBox1
richTextBox1.Invoke((Action)(() =>
{
richTextBox1.Text += $"转换完成 {DateTime.Now}\r\n";
}));
});

GetFiles方法如下所示:

   // 这个方法返回一个IEnumerable<string>,表示文件的路径
public IEnumerable<string> GetFiles(string path, string searchPattern)
{
// 获取文件夹下的所有文件
string[] files = Directory.GetFiles(path, searchPattern); // 遍历所有文件
foreach (string file in files)
{
// 返回当前文件
yield return file;
}
}

这里使用了yield关键字,使用yield的好处如下:

  1. 延迟执行:迭代器的执行会被延迟,直到迭代器被消费时才开始。这意味着如果你有一个大的数据集合需要处理,但并不需要立即处理所有数据,那么使用yield可以帮助你节省内存和计算资源。
  2. 简化代码:yield可以使你的代码更简洁,更易于阅读和理解。你不需要创建一个临时的集合来存储你的结果,而是可以直接使用yield return来返回结果。
  3. 无需一次性生成所有结果:当处理大量数据时,一次性生成所有结果可能会消耗大量内存。使用yield可以在每次迭代时只生成一个结果,从而节省内存。

实现原理其实很简单,就是用新版本的word打开再保存就行了。

 // 打开输入的 .doc 文件
Document doc = wordApp.Documents.Open(docFile); // 获取不带扩展名的文件名
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(docFile); // 将扩展名改为.docx
string docxFileName = Path.ChangeExtension(fileNameWithoutExtension, ".docx"); string docxFilePath = Path.Combine(docxFolderPath, docxFileName); // 将 .doc 文件保存为 .docx 格式
doc.SaveAs2(docxFilePath, WdSaveFormat.wdFormatXMLDocument); // 关闭 .doc 文件
doc.Close(); // 释放 Document 对象的资源
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);

需要转换的doc文件所在的文件夹:

软件使用截图:

实现效果:

实现了批量doc文件转换为docx文件。

如果不熟悉C#也可以通过Python实现。

以下是一个文件转换的示例代码,经过测试可行:

import os
import win32com.client def convert_doc_to_docx(doc_path):
# 创建Word应用程序对象
word = win32com.client.Dispatch("Word.Application") # 打开.doc文件
doc = word.Documents.Open(doc_path) # 设置新的文件路径
docx_path = os.path.splitext(doc_path)[0] + ".docx" # 保存文件为.docx格式
doc.SaveAs(docx_path, FileFormat=16) # 16 represents wdFormatXMLDocument # 关闭文档
doc.Close() # 关闭Word应用程序
word.Quit() # 使用函数
convert_doc_to_docx("Path")

由于时间精力有限,没有写成批量处理的形式。

还有一种方案就是在word里写VBA。

采用哪种方案可以根据自己的熟练度。

自己动手做一个批量doc转换为docx文件的小工具的更多相关文章

  1. 开源一个自动整理B站UWP客户端软件进行批量下载的视频文件的小工具BiliVideosReoganizeHelper​

    ​ 大家都知道B站是一个很受欢迎的视频学习网站,上面有很多无私的up主上传了大量优秀的教学视频,在此向B站致敬,向广大UP主致敬. 有时,我们需要下载收藏一些视频,以防止以后找不到了.那么我们可以用B ...

  2. Python如何实现doc文件转换为docx文件?

    Python如何实现doc文件转换为docx文件? 在开发过程中遇到一个关于读写doc和docx的问题: 一个文件夹中有两种文件, 一种为doc结尾, 一种为docx结尾, 需要将这些文件全部重命名. ...

  3. java使用poi读取doc和docx文件(maven自动导入依赖包)

    java使用poi读取doc和docx文件(maven自动导入依赖包) 于是在网上搜寻了一阵之后才发现原来doc文档和excel一样不能用普通的io流的方法来读取,而是也需要用poi,于是进行了一番尝 ...

  4. 用C#Winform写个简单的批量清空文件内容和删除文件的小工具

    用C#Winform写个简单的批量清空文件内容和删除文件的小工具 本文介绍这个简单得不能再简单的小项目.做这个项目,有以下目的. 1 当然是做个能用的工具 2 学习使用Github 关于用VS2013 ...

  5. 一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具

    一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具 Intro DbTool 是一个支持 CodeFirst/DbFirst/ModelFirst 的数据库小工具,原本 ...

  6. 告别收费BI!如何自己动手做一个免费的可视化数据报表还支持文档在线预览?

    本人大学刚毕业目前在一家互联网公司从事产品运营工作,一季度刚过,公司需要我出一份产品运营数据报表,由于产品用户数据.订单数据等数据量太大,我希望找一款Bi产品,支持我做出一个精美的可视化报表,还可以让 ...

  7. java使用poi读取doc和docx文件

    这几天在学习java io流的东西,有一个网友看到博客后问了一个问题,就是说他的doc文档为什么用我所说的方法死活就是乱码. 我一开始以为是他方法问题,结果自己试了之后发现和他的结果一样也是乱码. 于 ...

  8. [转]用Python做一个自动生成读表代码的小脚本

    写在开始(本片文章不是写给小白的,至少你应该知道一些常识!) 大家在Unity开发中,肯定会把一些数据放到配置文件中,尤其是大一点的项目,每次开发一个新功能的时候,都要重复的写那些读表代码.非常烦.来 ...

  9. ruby利用Zip Gem写一个简单的压缩和解压的小工具

    在UNIX下的我们怎么会沦落到用ruby写压缩和解压工具呢?直接上shell啊!但是请允许本猫这次可耻的用ruby来玩玩吧!其实ruby GEM中有很多压缩解压包,我选的是Zip,也许是因为名字符合K ...

  10. 教你动手做一个 iOS 越狱 app

    前言 俗话说得好, 万事开头难. 仅仅是上图一个如此简单地不能再简单的小app, 其实都不算是app, 只是注入了一段代码进系统中, 等到特定的函数方法调用的时候就会被我们hook掉, 执行我们写的代 ...

随机推荐

  1. C# 二十年语法变迁之 C# 2,C# 3 ,C# 4参考

    C# 二十年语法变迁之 C# 2,C# 3 ,C# 4参考 https://benbowen.blog/post/two_decades_of_csharp_i/ 自从 C# 于 2000 年推出以来 ...

  2. axios.delete传参,400错误

    我在使用axios.delete进行传参的时候,发现会报400错误 后端代码(C#) 前端代码 这样的参数请求会报400错误 后端就一个参数,前端发一个id为什么接受不到呢? 在网上找了半天,终于明白 ...

  3. 如何从零实现属于自己的 API 网关?

    序言 上一篇文章:你连对外接口签名都不会知道?有时间还是要学习学习. 有很多小伙伴反应,对外的 API 中相关的加签,验签这些工作可以统一使用网关去处理. 说到网关,大家肯定比较熟悉.市面上使用比较广 ...

  4. Java并发编程实例--7.守护(Damon)线程

    Java有一种特殊线程叫守护(后台)线程. 1.这类线程拥有非常低的优先级且通常只是在没有其他线程运行的情况下执行. 2.其通常作为无线循环服务去执行某项任务. 3.不能让他们去执行重要任务因为你不知 ...

  5. python3发送需要双向认证的wss请求

    python3发送需要双向认证的wss请求 websocket链接python有很多封装好的库:websocket-client.websockets.aiowebsocket 这里用的websoke ...

  6. VS2019 添加三方文件夹遇到的坑

    在开发新项目时需要用到一些三方 API,这些三方 API 没有生成 lib,所以我们在 VS 编译器中添加这些三方文件夹的头文件路径后 会出现 ERROR LNK2019 的错误提示,这些提示通常都是 ...

  7. win32 - 使用Desktop Duplication API复制桌面图像

    该代码来源于codeproject,经过测试发现,在屏幕处于旋转的情况下捕获的图像是黑色的.暂时没有找到原因. 代码开箱即用, #define WIN32_LEAN_AND_MEAN #include ...

  8. 使用俩个链接在一起的容器运行wordpress

    # 问题,如何分离mysql和wordpress,使它们每个都单独运行一个容器. # 解决办法:运行时通过--link选项使它们链接在一起 --link <container_name>: ...

  9. 【LeetCode二叉树#18】修剪二叉搜索树(涉及重构二叉树与递归回溯)

    修剪二叉搜索树 力扣题目链接(opens new window) 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R.通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) .你 ...

  10. 使用矩池云 Docker 虚拟机安装VNC、Conda、Python及CUDA

    矩池云虚拟机支持 Docker 使用,但是由于虚拟机目前不支持启动时传递环境变量来设置VNC.Jupyterlab 连接密码,所以我们没有创建相关基础镜像(设置固定密码容易泄漏),下面给大家介绍手动安 ...