Unity 之 实现读取代码写进Word文档功能实现 -- 软著脚本生成工具
创始人
2025-05-29 01:19:35

Unity 之 实现读取代码写进Word文档功能

  • 前言
  • 一,实现步骤
    • 1.1 逻辑梳理
    • 1.2 用到工具
  • 二,实现读写文件
    • 2.1 读取目录相关
    • 2.2 读写文件
  • 三,编辑器拓展
    • 3.1 编辑器拓展介绍
    • 3.2 实现界面可视化
  • 四,源码分享
    • 4.1 工具目录
    • 4.2 完整代码

前言

之所以有一篇这样的文章,是因为最进在申请软著时,要复制60页的代码到Word文档中,手动复制了一次,下一次就在也不想去复制了。记得之前好像看见过有人用Py写过这样的工具,但是Py我有不熟。就有了使用Unity写一个这样的工具的想法,一起来看看效果吧~

看看效果:

只需要选择想导出的脚本的根目录和保存Word文件的根目录(不选默认执行到工程的Asset目录);然后点击:"开始读取CS并写Word"即可:

生成的脚本在WPS打开:

PS:生成的文档完全按照代码中的格式来处理的,没有剔除空格和注释。需要的童鞋可以自行拓展一下工具脚本。


一,实现步骤

1.1 逻辑梳理

基本思路

  1. 在文件夹中找到要复制的Csharp脚本
  2. 读取Csharp脚本
  3. 保存读取到的内容到Word文档中

知识点

  1. 遍历文件夹,根据后缀找到指定文件
  2. 读取文件中的数据
  3. 将读取到的数据保存到文档中
  4. 编辑器拓展 - 分装成工具

1.2 用到工具

用到的是NPOI库:

  1. NPOI是指构建在POI 3.x版本之上的一个程序,NPOI可以在没有安装Office的情况下对Word或Excel文档进行读写操作。
  2. NPOI是一个开源的C#读写Excel、WORD等微软OLE2组件文档的项目。

工程目录:

PS:需要插件的同学,可以到文末工具资源包中获取。


二,实现读写文件

这里只对用的逻辑进行讲解,若需要全面学习文件的读取相关,可以看我之前写过的博文:

  1. 本地数据交互 – 文件概述 – File类介绍和使用
  2. 本地数据交互 – 文件相关类介绍 – 读写txt文本文件

2.1 读取目录相关

  1. 判断是否存在目录文件
private static string filePath = "Assets/ScriptTemp.docx";
// 检查目录是否存在
if (Directory.Exists(filePath))
{// 存在就删除Directory.Delete(filePath);
}
  1. 创建指定文件
private static string filePath = "Assets/ScriptTemp.docx";
FileStream fs = new FileStream(savePath + filePath, FileMode.Create);
  1. 遍历文件夹并筛选.cs后缀文件
/// 
/// 递归文件夹下的cs文件
/// 
/// 
static void FileName(string folderPath)
{DirectoryInfo info = new DirectoryInfo(folderPath);foreach (DirectoryInfo item in info.GetDirectories()){FileName(item.FullName);}foreach (FileInfo item in info.GetFiles()){// 找到文件夹下的脚本if (item.FullName.EndsWith(".cs", StringComparison.Ordinal)){//将目录缓存下来,之后读文件的时候用//csScriptFullName.Add("Assets" + item.FullName.Replace(Application.dataPath, ""));}}
}

2.2 读写文件

  1. 读取文件内容

这里不适用ReadToEnd方法是因为,我发现在后续写入的时候会不会自动换行。所以使用循环的方式一行一行的读取文件内容。

// 读取脚本内容
StreamReader streamReader = new StreamReader(itemPath, Encoding.UTF8);
// 不适用
//string res = streamReader.ReadToEnd();
string res = "";
while (!streamReader.EndOfStream)
{res = streamReader.ReadLine() + "\n";//Debug.Log($"读取脚本内容: {res}");
}
// 释放资源
streamReader.Dispose();
  1. 写入Word文件

引用命名空间,没有的话就是没有导入1.2说的.dll文件,在到文末工具包中下载:

using NPOI.XWPF.UserModel;

写入Word步骤:创建文档 —> 创建段落 —>设置格式 —> 写入内容 —> 生成文档

XWPFDocument doc = new XWPFDocument();
// 新建段落
XWPFParagraph paragraph = doc.CreateParagraph();
// 左对齐
paragraph.Alignment = ParagraphAlignment.LEFT;
// 新建运行行
XWPFRun run = paragraph.CreateRun();
// 设置颜色
run.SetColor("000000");
// 字体
run.FontFamily = "宋体";
// 字号
run.FontSize = 10;
// 设置内容
run.SetText("内容内容内容");// 写入文档
FileStream fs = new FileStream("文件目录", FileMode.OpenOrCreate);
// 写入
doc.Write(fs);
// 释放资源
fs.Close();
fs.Dispose();

三,编辑器拓展

3.1 编辑器拓展介绍

  1. MenuItem
    使用MenuItem标识可以为编辑器添加新的菜单。点击后执行一些特定的逻辑,没有额外的操作界面。只有静态方法可以使用该标识,该标识可以把静态方法转换为菜单命令。
    比如:
[MenuItem("Tools/生成Word")]
public static void CreateWindow()
{Debug.Log("todo... 点了按钮");
}

  1. EditorWindow
    继承自EditorWindow的类,可以实现更复杂的编辑器窗口功能。且这种窗口是可以自由内嵌到Unity编辑器内,共同组成编辑器的Layout

通过在OnGUI()函数内调用GUILayout、EditorGUILayout、GUI等类的一些方法来实现复杂的界面。

下面是结果常用Layout 示例代码:

private void OnGUI()
{// 接受用户输入float size = EditorGUILayout.FloatField("输入size:", size);EditorGUILayout.LabelField("提示信息 :");// 添加空行EditorGUILayout.Space();if (GUILayout.Button("点击按钮")){pathRoot = EditorUtility.OpenFolderPanel("路径选择", pathRoot, "");}
}

3.2 实现界面可视化

  1. 创建脚本引用Editor命名空间,继承EditorWindow
  2. 新建OnGUI方法实现,可视化界面
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;public class TestEditor : EditorWindow
{/// /// 读取根目录/// private static string pathRoot = "Assets";private static float size;[MenuItem("Tools/Test111")]public static void CreateWindow(){TestEditor window = GetWindow(false, "测试调试窗口", true);window.Show();}// 显示窗口private void OnGUI(){EditorGUILayout.LabelField("提示信息 :");size = EditorGUILayout.FloatField("输入size:", size);// 换行EditorGUILayout.Space();EditorGUILayout.LabelField("换行后的提示信息 :");EditorGUILayout.Space();// 按钮if (GUILayout.Button("选择脚本路径")){pathRoot = EditorUtility.OpenFolderPanel("路径选择", pathRoot, "");}}
}


四,源码分享

4.1 工具目录

打包后的工具目录:

工程下载:源码和步骤都在上面分享过了,若还有什么不明白的,可以 点击链接下载 ,积分不够的童鞋关注下方卡片,回复:“Word” 或者 “软著脚本工具” 即可获得Demo源码~


4.2 完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
using NPOI.XWPF.UserModel;
using System.Text;
using Debug = UnityEngine.Debug;public class CreateWordDocxEditor : EditorWindow
{/// /// 读取根目录/// private static string pathRoot = "Assets";/// /// 保存根目录/// private static string savePath = "Assets";// 文件名称private static string filePath = "/ScriptTemp.docx";[MenuItem("Tools/生成Word")]public static void CreateWindow(){CreateWordDocxEditor window = GetWindow(false, "配置生成文档需求", true);window.Show();}// 显示窗口private void OnGUI(){EditorGUILayout.BeginHorizontal();EditorGUILayout.Space();EditorGUILayout.LabelField("当前脚本路径 :" + pathRoot);EditorGUILayout.Space();EditorGUILayout.EndHorizontal();EditorGUILayout.BeginHorizontal();EditorGUILayout.Space();if (GUILayout.Button("选择脚本路径")){pathRoot = EditorUtility.OpenFolderPanel("路径选择", pathRoot, "");Debug.Log("选择脚本路径 : " + pathRoot);}EditorGUILayout.Space();EditorGUILayout.EndHorizontal();EditorGUILayout.BeginHorizontal();EditorGUILayout.Space();EditorGUILayout.LabelField("选择保存路径 :" + savePath);EditorGUILayout.Space();EditorGUILayout.EndHorizontal();EditorGUILayout.BeginHorizontal();EditorGUILayout.Space();if (GUILayout.Button("选择保存路径")){savePath = EditorUtility.OpenFolderPanel("路径选择", savePath, "");Debug.Log("选择保存路径 : " + savePath);}EditorGUILayout.Space();EditorGUILayout.EndHorizontal();EditorGUILayout.BeginHorizontal();EditorGUILayout.Space();if (GUILayout.Button("开始读取CS并写入Word")){CreateWordDocxFile();}EditorGUILayout.Space();EditorGUILayout.EndHorizontal();}static void CreateWordDocxFile(){Debug.Log("打包开始执行");csScriptFullName.Clear();FileName(pathRoot);CreatOrOpenDoc();EditorUtility.ClearProgressBar();AssetDatabase.Refresh();Debug.Log("打包执行结束");}/// /// 暂存遍历到的CS脚本全路径/// static List csScriptFullName = new List();/// /// 创建或打开文档/// /// private static void CreatOrOpenDoc(){try{// 检查目录是否存在if (Directory.Exists(savePath + filePath)){// 存在就删除Directory.Delete(savePath + filePath);}FileStream fs = new FileStream(savePath + filePath, FileMode.OpenOrCreate);XWPFDocument doc = new XWPFDocument();int index = 0;foreach (var itemPath in csScriptFullName){//Debug.Log($"csScriptFullName[i]: {item}");// 读取脚本内容StreamReader streamReader = new StreamReader(itemPath, Encoding.UTF8);//string res = streamReader.ReadToEnd();string res = "";while (!streamReader.EndOfStream){res = streamReader.ReadLine() + "\n";Debug.Log($"读取脚本内容: {res}");// 新建段落 设置格式XWPFParagraph paragraph = doc.CreateParagraph();paragraph.Alignment = ParagraphAlignment.LEFT;XWPFRun run = paragraph.CreateRun();run.SetColor("000000");run.FontFamily = "宋体";run.FontSize = 10;run.SetText(res);}// 释放资源streamReader.Dispose();EditorUtility.DisplayProgressBar("处理中...", "正在处理:" + itemPath,index * 1.0f / csScriptFullName.Count);index++;Debug.Log($"文件生成完成:{savePath} {filePath} ");}try{doc.Write(fs);}catch (Exception e){Debug.LogError($"文件不可写入,请查看原因:{e}");}fs.Close();fs.Dispose();}catch (Exception e){Debug.LogError($"创建失败,同名文件被打开!问题:{e}");}Debug.Log($"文件生成在: {savePath + filePath}");}/// /// 递归文件夹下的cs文件/// /// static void FileName(string folderPath){DirectoryInfo info = new DirectoryInfo(folderPath);foreach (DirectoryInfo item in info.GetDirectories()){FileName(item.FullName);}foreach (FileInfo item in info.GetFiles()){// 找到文件夹下的脚本if (item.FullName.EndsWith(".cs", StringComparison.Ordinal)){csScriptFullName.Add("Assets" + item.FullName.Replace(Application.dataPath, ""));}}}
}

相关内容

热门资讯

全面控货价格仍倒挂,泸州老窖无... 泸州老窖离“白酒老三”宝座越来越远,面临的挑战也越来越严峻了。5月29日,履职十年的董事钱旭离职的公...
识局安排安徽某政府对接工业机器... 文/识局招商团队(识局微信公共账号zhijuzk)6月6日,周五。识局安排安徽某政府对接工业机器人项...
V观财报|*ST天喻及实控人之...   中新经纬6月6日电 *ST天喻6日盘后公告,公司及实际控制人之一闫春雨于6月6日分别收到《中国证...
未来已来,怎么抓住先进科技新起... 所有的产业都值得用AI重新做一遍用。用这句话来总结新一轮的AI科技浪潮,可能并不过分,人工智能技术正...
嘉麟杰:控股股东一致行动人及实... 6月6日晚间,上海嘉麟杰纺织品股份有限公司(嘉麟杰,002486.SZ)公告,公司控股股东绍兴国骏企...
58同城姚劲波6.6亿“买药”... 初代互联网大佬寻找“第二曲线”!作者 | 赵普编辑丨高岩来源 | 野马财经姚劲波出手,易明医药(00...
隆基绿能:股东HHLR拟减持不... 6月6日晚间,隆基绿能科技股份有限公司(隆基绿能,601012.SH)公告,截至本公告披露日,HHL...
阿特斯:股东元禾重元拟减持不超... 6月6日晚间,阿特斯阳光电力集团股份有限公司(阿特斯,688472.SH)公告,公司于今日收到持股3...
公募REITs总市值突破200... 距首批REITs上市不到4年时间,全市场公募REITs总市值突破2000亿元。第一财经获悉,未来,数...
破解融资难题 稠州银行金融“活... 潮新闻客户端 通讯员 刘家慧 民营企业是经济发展的生力军,是浙江市场经济高度活跃的金名片。作为起源于...
深交所:本周共对14起上市公司... 6月3日至6月6日,深交所共对80起证券异常交易行为采取了自律监管措施,涉及盘中拉抬打压、虚假申报等...
德国ETF今年悄悄大涨3成,原... 今年QDII最火基金。 作者 | 市值风云基金研究部 编辑 | 小白 风云君发现,今年外国股市中,...
6月6日沪深两市强势个股与概念... 一、强势个股截至6月6日收盘,上证综指上涨0.04%,收于3385.36点,深证成指下跌0.19%,...
玩商标文字游戏“多半”“翻车” 维 辰 断句的艺术,被一些人给玩明白了。 前有“壹号土猪肉”“千禾0酱油”中的“壹号土”“千禾0”其...
突发!千亿级险企中邮保险原总经... 据财新报道,中邮人寿原总经理党均章失联了,消息称其已经被有关部门带走调查。 公开资料显示,党均章,...
白银价格创13年来新高,投资时... 文/张文晖6月5日,贵金属市场上演了一场令人瞩目的行情。现货白银价格大幅飙升,一度涨幅超过4.5%,...
5天翻倍股金陵体育:苏超联赛有... “苏超”概念股金陵体育公告称,苏超联赛有部分场地使用了公司的足球比赛器材。6月6日,江苏金陵体育器材...
如何选出业绩长期稳定的基金?(... 优秀的基金经理在业绩表现上往往有一个显著特点:短期业绩未必锋芒毕露,但随着时间维度拉长,业绩却愈发亮...
英国承认:统计数据存在重大错误... 有多少资讯是真正有用的?FinGraph是中文财经世界唯一一家每日图形化早晚专栏,为专注于全球市场的...
王自如AI创业,坦言“来钱快” 王自如投身 AI 创业领域,其言辞中毫不掩饰地提及“来钱快”。这一表述反映出当下 AI 创业的某种现...
又一培训机构,黄了? 培训机构... 5月24日晚上,知名医考教培机构“金英杰”创始人赵红峰,被自家员工堵在了办公室。当天,员工们发现自己...
上交所:将推动上市公司进一步加... 据上交所发布6月6日消息,为贯彻落实党中央、国务院关于资本市场的决策部署,落实中央政治局会议和新“国...
上交所召开高分红重回报暨上市公... 6月5日,上海证券交易所召开高分红重回报暨上市公司价值提升座谈会,就进一步提升高分红、高股息率上市公...
全球吃瓜!马斯克怒掀特朗普情色... 全世界最有钱的人,和美国最有权的人。骂出了全世界,最难听的话!今天一早,外网都炸了, 因为马斯克的爆...
《西游记》演员叶以萌去世!曾饰... 搜狐娱乐讯 近日,据博主《1982西游记》透露,演员叶以萌于6月4日凌晨2点38分因病医治无效离世,...
6月6日复盘:银行+新消费牛市... 昨天A股成交量是1.29万亿,因为有增量资金,我觉得市场继续上涨问题是不大的。但今天成交量只有1.5...
美财政部“书面指导”:日本央行... 美国财政部罕见"指导"日本央行加息,日本财务大臣加藤胜信回应称,将把货币政策细节留给日本央行来决定。...
苏股IPO | 刚刚,无锡这家... 今天(6月6日),上交所上市审核委员会2025年第18次会议审核通过江阴华新精密科技股份有限公司(以...
不正当竞争、强制骑手二选一 ?... 唉,我记得当初,京东给外卖骑手兄弟,写过一封信。其中一点是:对兼职骑手永不强迫“二选一”。但.......
港股收盘 | 三大指数周线延续... 财联社6月6日讯(编辑 胡家荣)本周港股三大指数延续近期涨势。截至周五收盘,恒生指数累计上涨2.16...