IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity——Excel文件的读写与格式转换 -> 正文阅读

[游戏开发]Unity——Excel文件的读写与格式转换

个人学习笔记,如有错误、疑问、建议,欢迎留言。
声明:本文不得以任何形式进行转载。



?前言:读取Excel文件并转换为jsonxml格式。
?写本文之前有学习本站另外一篇文章:Unity 之 Excel表格转换为Unity用的文件格式 – ScriptableObject,Json,XML 全部搞定_陈言必行的专栏-CSDN博客


一、准备工作

1.1 导入所需的dll

?所需的dll文件链接:Unity——读写Excel文件所需的dll_Supernova_Kai的资源
?首先,在项目中创建一个Excel文件夹,来存储我们的工具,文件夹的结构如下:文件夹结构
?Plugin用来存储我们所需的dllScripts存放我们的脚本文件;Output是工具的文件输出目录。
Plugin中导入下面三个dllEPPlus.dllExcel.dllICSharpCode.SharpZipLib.dll

1.2 创建一个Excel表

?我在Assets文件夹下创了一个文件名为Student的Excel表格,内容如下:
Excel表数据
?准备工作就已经完成了,可以开始写脚本来读取数据了。
?注:创建的Excel文件的拓展名需是.xlsx


二、读取Excel文件

2.1 数据类

?首先,在我们的Excel表格中,每一行是一条完整的数据(一名学生的信息),在存储的时候,我们也同样希望能够在存储的数据结构中,以这种结构出现,我们以json数据为例:我们当然希望存储下来可以以这样的形式:

[
	{id:1,name:小明,gender:,age:15},  //每一条是一名学生的信息
	{id:2,name:小红,gender:,age:17},
]

?那么,我们就需要一个Student类来对应Excel中的数据结构,Stuend脚本如下:

using System;

[Serializable]
public class Student
{
    public int id; //学号
    public string name; //姓名
    public string gender; //性别
    public int age; //年龄
}

?在Stuent类中,字段与Excel中的数据是完全对应的,但是Student只能对应一个学生的信息(即Excel中一行的信息),于是我们需要使用一个List来存储所有的数据,修改Student脚本:

using System;
using System.Collections.Generic;

[Serializable]
public class Student
{
    public int id; //学号
    public string name; //姓名
    public string gender; //性别
    public int age; //年龄
}

[Serializable]
public class StudentList
{
    public List<Student> studentList = new List<Student>(); //学生列表
}

2.2 配置文件脚本

?为了方便管理,写一个ExcelConfig类,用于存储配置信息:

public class ExcelConfig
{
    //打开的Excel文件路径
    public static readonly string openPath = @"E:/Test/ExcelTest/Assets/Student.xlsx";

    //序列化的保存路径
    public static readonly string savePath = @"E:/Test/ExcelTest/Assets/Excel/Output/";
}

?openPath是我们的Student表的路径;savePath是我们输出目录的路径。


2.3 工具脚本

?接下来就要实现Excel的读写工具了,创建ExcelTool脚本,内容如下:

using System.Data;
using System.IO;
using Excel;

public class ExcelTool
{
    public static string openPath = ExcelConfig.openPath; //Excel文件路径

    //读取Excel数据
    public static void ReadExcelContext(StudentList instance)
    {
        FileStream stream = File.Open(openPath, FileMode.Open, FileAccess.Read, FileShare.Read);

        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        DataSet result = excelReader.AsDataSet();

        var table = result.Tables[0]; //0代表第一张子表

        int columnNum = table.Columns.Count; //总列数
        int rowNum = table.Rows.Count; //总行数

        for(int i = 1; i < columnNum; i++) //遍历每一行(因为Excel第一行是注解内容,不是真正的数据,所以索引从1开始)
        {
            Student data = new Student(); //学生实例

            //解析每一列的数据
            data.id = int.Parse(table.Rows[i][0].ToString());
            data.name = table.Rows[i][1].ToString();
            data.gender = table.Rows[i][2].ToString();
            data.age = int.Parse(table.Rows[i][3].ToString());

            instance.studentList.Add(data); //将数据添加到List中
        }
    }
}

2.4 测试脚本

?写一个脚本来测试一下:

using UnityEngine;
using UnityEditor;

public class ExcelWindow : EditorWindow
{
    public StudentList instance = new StudentList();

    [MenuItem("Tools/Excel", false, -10)]
    static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(ExcelWindow));
    }

    void OnGUI()
    {
        if(GUILayout.Button("读取Excel"))
        {
            ExcelTool.ReadExcelContext(instance);
            foreach(var student in instance.studentList)
            {
                Debug.LogFormat("学号:{0},姓名:{1},性别:{2},年龄:{3}", student.id, student.name, student.gender, student.age);
            }
        }
    }
}

?输出信息:
打印信息
?我们就成功把Student表中的数据读取到我们的studentList里面了。

?注意事项:
?1、Excel文件具有独占性,不能在打开Excel文件的情况下,进行读写,可以写一个try...catch语句来处理异常。
?2、在我的测试窗口的脚本里面,当点击读取Excel的按钮时,会执行ExcelTool.ReadExcelContext()方法,读取并向List添加元素,所以,如果反复点击按钮,会多次向List添加元素。


三、序列化为json

//序列化为json
public static void ConvertToJson(StudentList instance)
{
	string json = JsonUtility.ToJson(instance);

	//如果路径不存在,创建路径
	if(!Directory.Exists(ExcelConfig.savePath))
		Directory.CreateDirectory(ExcelConfig.savePath);
	
	File.WriteAllText(ExcelConfig.savePath + "student" + ".json", json);
	AssetDatabase.Refresh(); //刷新Assets
}

?输出的json文件如下:

{"studentList":
	[
		{"id":1,"name":"小明","gender":"男","age":15},
		{"id":2,"name":"小红","gender":"女","age":17},
		{"id":3,"name":"小王","gender":"男","age":16},
		{"id":4,"name":"小李","gender":"女","age":16}
	]
}

四、序列化为Xml

//序列化为xml
public static void ConvertToXml(StudentList instance)
{
    if(!Directory.Exists(ExcelConfig.savePath))
        Directory.CreateDirectory(ExcelConfig.savePath);

    XmlDocument doc = new XmlDocument();

    XmlElement root = doc.CreateElement("root"); //创建根节点
    doc.AppendChild(root); //添加根节点

    for(int i = 0; i < instance.studentList.Count; i++)
    {
        XmlElement data = doc.CreateElement("data"); //创建一级节点data
        root.AppendChild(data); //添加data节点到根节点下

        //创建二级节点
        XmlElement id = doc.CreateElement("id");
        XmlElement name = doc.CreateElement("name");
        XmlElement gender = doc.CreateElement("gender");
        XmlElement age = doc.CreateElement("age");

        //添加二级节点到data节点下
        data.AppendChild(id);
        data.AppendChild(name);
        data.AppendChild(gender);
        data.AppendChild(age);

        //设置数据
        id.InnerText = instance.studentList[i].id.ToString();
        name.InnerText = instance.studentList[i].name;
        gender.InnerText = instance.studentList[i].gender;
        age.InnerText = instance.studentList[i].age.ToString();

    }

    string filePath = ExcelConfig.savePath + "Student" + ".xml";
    doc.Save(filePath); //保存
    AssetDatabase.Refresh(); //刷新Assets
}

?输出的xml文件如下:

<root>
  <data>
    <id>1</id>
    <name>小明</name>
    <gender></gender>
    <age>15</age>
  </data>
  <data>
    <id>2</id>
    <name>小红</name>
    <gender></gender>
    <age>17</age>
  </data>
  <data>
    <id>3</id>
    <name>小王</name>
    <gender></gender>
    <age>16</age>
  </data>
  <data>
    <id>4</id>
    <name>小李</name>
    <gender></gender>
    <age>16</age>
  </data>
</root>

五、写入Excel

?前面介绍了如何读取Excel文件并转换为其他格式,那么把数据写入Excel文件呢?
?首先需要引用命名空间:

using OfficeOpenXml;

?在ExcelTool中添加如下函数:(这里就以那个读取出来的StudentList的实例为例了)

//写入Excel
public static void WriteExcel(StudentList instance)
{
    string savePath = ExcelConfig.savePath + "Student2" + ".xlsx"; //Excel文件的路径
    FileInfo fileInfo = new FileInfo(savePath);
    
    using(ExcelPackage package = new ExcelPackage(fileInfo))
    {
        ExcelWorkbook workbook = package.Workbook; //Excel表
        	
        ExcelWorksheet worksheet; //Excel子表
        worksheet = workbook.Worksheets.Add("Sheet1"); //添加一个子表Sheet1
		
        //遍历列表并写入数据
        for(int i = 0; i < instance.studentList.Count; i++)
        {
        	//注意!worksheet中索引是从1开始的,也就是说最左上角的单元格是[1,1]
            int row = i + 1; //行号
            worksheet.Cells[row, 1].Value = instance.studentList[i].id.ToString();
            worksheet.Cells[row, 2].Value = instance.studentList[i].name;
            worksheet.Cells[row, 3].Value = instance.studentList[i].gender;
            worksheet.Cells[row, 4].Value = instance.studentList[i].age.ToString();
        }
        package.Save(); //保存
        AssetDatabase.Refresh(); //刷新Assets
    }
}

?上面代码的作用:获取指定路径的Excel表(如果没有,会新建),并新建一个子表Sheet1,将刚才我们那个读取到List中的学生信息写入进去。

?上面的代码只能添加一个新的子表,如果我们需要修改原有Excel子表的内容怎么办呢?
?修改原有的内容:
?使用下面这行代码可以让worksheet获取指定索引的子表:

worksheet = workbook.Worksheets[1]; //在worksheets中,子表的索引是从1开始的

?获取到了子表,就可以通过worksheet.Cells[]随意修改表中的内容了。

?注意事项:
?1、在worksheets中,Excel的索引是从1开始的,也就是说:第一张子表的索引是1;在子表中,最左上角的单元格的索引是[1,1]


?目前项目中存在的问题:
?1、因为每一张Excel表的结构不一样,我们用来存储每一条Excel数据的类(文中项目的StudentStudentList类)需要根据不同的Excel表来修改(暂时没有想到比较好的方法,C#可以动态创建属性吗?)。
?2、在ExcelTool中,读取Excel数据以及转换格式为xml的方法中,都是使用的是手动解析和手动设置格式,可以自动化吗?


?附:
?文中的Excel示例项目的链接:ExcelTest.unitypackage_Supernova_Kai的资源

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-12-08 14:08:08  更:2021-12-08 14:09:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 20:26:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码