当前位置: 首页 > news >正文

Unity 之 实现读取代码写进Word文档功能实现 -- 软著脚本生成工具

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后缀文件
/// <summary>
/// 递归文件夹下的cs文件
/// </summary>
/// <param name="folderPath"></param>
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
{/// <summary>/// 读取根目录/// </summary>private static string pathRoot = "Assets";private static float size;[MenuItem("Tools/Test111")]public static void CreateWindow(){TestEditor window = GetWindow<TestEditor>(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
{/// <summary>/// 读取根目录/// </summary>private static string pathRoot = "Assets";/// <summary>/// 保存根目录/// </summary>private static string savePath = "Assets";// 文件名称private static string filePath = "/ScriptTemp.docx";[MenuItem("Tools/生成Word")]public static void CreateWindow(){CreateWordDocxEditor window = GetWindow<CreateWordDocxEditor>(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("打包执行结束");}/// <summary>/// 暂存遍历到的CS脚本全路径/// </summary>static List<string> csScriptFullName = new List<string>();/// <summary>/// 创建或打开文档/// </summary>/// <param name="filePath"></param>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}");}/// <summary>/// 递归文件夹下的cs文件/// </summary>/// <param name="folderPath"></param>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, ""));}}}
}

相关文章:

Unity 之 实现读取代码写进Word文档功能实现 -- 软著脚本生成工具

Unity 之 实现读取代码写进Word文档功能前言一&#xff0c;实现步骤1.1 逻辑梳理1.2 用到工具二&#xff0c;实现读写文件2.1 读取目录相关2.2 读写文件三&#xff0c;编辑器拓展3.1 编辑器拓展介绍3.2 实现界面可视化四&#xff0c;源码分享4.1 工具目录4.2 完整代码前言 之所…...

Typora图床配置:Typora + PicGo + 阿里云OSS

文章目录一、前景提要二、相关链接三、搭建步骤1. 购买阿里云对象存储OSS2. 对象存储OSS&#xff1a;创建Bucket3. 阿里云&#xff1a;添加OSS访问用户及权限4. 安装Typora5. 配置PicGo方法一&#xff1a;使用PicGo-Core (Command line)方法二&#xff1a;使用PicGo(app)6. 最后…...

二进制搭建以太坊2.0节点-2023最新详细版文档

文章目录 一、配置 JWT 认证二、部署执行节点geth2.1 下载geth二进制文件2.2 geth节点启动三、部署共识节点Prysm3.1 下载Prysm脚本3.2 Prysm容器生成四、检查节点是否同步完成4.1 检查geth执行节点4.2 检查prysm共识节点4.3 geth常用命令五、节点同步详细说明5.1 启动时日志5.…...

如何简化跨网络安全域的文件发送流程,大幅降低IT人员工作量?

为什么要做安全域的隔离&#xff1f; 随着企业数字化转型的逐步深入&#xff0c;企业投入了大量资源进行信息系统建设&#xff0c;信息化程度日益提升。在这一过程中&#xff0c;企业也越来越重视核心数据资产的保护&#xff0c;数据资产的安全防护成为企业面临的重大挑战。 …...

带你深入了解c语言指针后续

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨在该…...

借助Intune无感知开启Bitlocker

希望使用 Intune 部署 BitLocker&#xff0c;但不知道从哪里开始&#xff1f;这是人们最开始使用 Intune 时最常见的问题之一。在本博客中&#xff0c;你将了解有关使用 Intune 管理 BitLocker 的所有信息&#xff0c;包括建议的设置、BitLocker CSP 在客户端上的工作方式&…...

零基础该如何转行Python工程师?学习路线是什么?

最近1年的主要学习时间&#xff0c;都投资到了 python 数据分析和数据挖掘上面来了&#xff0c;虽然经验并不是十分丰富&#xff0c;但希望也能把自己的经验分享下&#xff0c;最近也好多朋友给我留言&#xff0c;和我聊天&#xff0c;问我python该如何学习&#xff0c;才能少走…...

Go项目(商品微服务-1)

文章目录简介建表protohandler商品小结简介 商品微服务主要在于表的设计&#xff0c;建哪些表&#xff1f;表之间的关系是怎样的&#xff1f; 主要代码就是 CURD表和字段的设计是一个比较有挑战性的工作&#xff0c;比较难说清楚&#xff0c;也需要经验的积累&#xff0c;这里…...

机器学习——集成学习

引言 集成学习&#xff1a;让机器学习效果更好&#xff0c;单个不行&#xff0c;群殴走起。 分类 1. Bagging:训练多个分类器取平均&#xff08;m代表树的个数&#xff09;。 2.Boosting&#xff08;提升算法&#xff09;:从弱学习器开始加&#xff0c;通过加权来进行训练。…...

VS编译系统 实用调试技巧

目录什么是bug?调试是什么&#xff1f;有多重要&#xff1f;debug和release的介绍windows环境调试介绍、一些调试实例如何写出&#xff08;易于调试&#xff09;的代码编程常见的错误什么是bug?其实bug在英文翻译中有表示臭虫的含义&#xff0c;因为第一次被发现的导致计算机…...

【华为OD机试模拟题】用 C++ 实现 - GPU 调度(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明GPU 调度题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。...

腾讯前端必会react面试题合集

React-Router的路由有几种模式&#xff1f; React-Router 支持使用 hash&#xff08;对应 HashRouter&#xff09;和 browser&#xff08;对应 BrowserRouter&#xff09; 两种路由规则&#xff0c; react-router-dom 提供了 BrowserRouter 和 HashRouter 两个组件来实现应用的…...

Linux搭建SVN服务器,并内网穿透实现公网远程访问

文章目录1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6.2 配置…...

C++STL之list的模拟实现

目录 一.list准备 二. iterator迭代器 1._list_iterator 2.begin()、end() 3.const_begin()、const_end() 4.!&& 5. && -- 6.operator* 7.operator-> 三.Modify(修改) 1.insert() 2.erase() 3.push_back() && push_front() 4.pop_bac…...

为什么硬件性能监控很重要

当今的混合网络环境平衡了分布式网络和现代技术的实施。但它们并不缺少一个核心组件&#xff1a;服务器。保持网络正常运行时间归结为监控和管理导致网络停机的因素。极有可能导致性能异常的此类因素之一是硬件。使用硬件监控器监控网络硬件已成为一项关键需求。 硬件监视器是…...

HTTP缓存

HTTP缓存HTTP缓存引发的一个问题HTTP缓存的作用HTTP缓存的分类强制缓存协商缓存&#xff08;解决强缓存下资源不更新问题&#xff09;缓存策略HTTP缓存引发的一个问题 有一次在开发移动端H5项目&#xff0c;UI提了几个UI问题&#xff0c;经过样式调试&#xff0c;android上没有…...

SPI设备树处理过程

SPI设备树处理过程 文章目录SPI设备树处理过程参考资料&#xff1a;一、 spi_device结构体二、 SPI设备树格式2.1 SPI Master2.2 SPI Device2.3 设备树示例三、设备树实例3.1 使用GPIO模拟的SPI控制器3.2 IMX6ULL SPI控制器四、 设备树处理过程致谢参考资料&#xff1a; 内核头…...

数据有哪些重要的作用?

我们正处在科技高速发展的时代&#xff0c;如今互联网已经与我们的生活息息相关&#xff0c;我们每天在互联网产生大量的数据&#xff0c;这些数据散落在网络中看似没有怎么作用&#xff0c;但是这些数据经过系统的处理整合起来确实非常有价值的。 一、 发展大数据技术可以提高…...

spring面试题总结

1、spring是什么&#xff1f; spring是一个轻量级IOC和AOP容器框架&#xff0c;是为Java应用程序提供基础性服务的一套框架&#xff0c;目的是用于简化企业应用的开发&#xff0c;开发者只需要关注业务需求即可&#xff1a; core container 容器组件 spring context&#xff0c…...

使用MUI与H5+构建移动端app

前言 通过mui构建APP 效果图: <!DOCTYPE html> <html> <head><meta charset...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...