个人学习笔记,如有错误、疑问、建议,欢迎留言。 声明:本文不得以任何形式进行转载。
?前言:读取Excel 文件并转换为json 、xml 格式。 ?写本文之前有学习本站另外一篇文章:Unity 之 Excel表格转换为Unity用的文件格式 – ScriptableObject,Json,XML 全部搞定_陈言必行的专栏-CSDN博客
一、准备工作
1.1 导入所需的dll
?所需的dll 文件链接:Unity——读写Excel文件所需的dll_Supernova_Kai的资源 ?首先,在项目中创建一个Excel 文件夹,来存储我们的工具,文件夹的结构如下: ?Plugin 用来存储我们所需的dll ;Scripts 存放我们的脚本文件;Output 是工具的文件输出目录。 在Plugin 中导入下面三个dll :EPPlus.dll 、Excel.dll 、ICSharpCode.SharpZipLib.dll
1.2 创建一个Excel表
?我在Assets 文件夹下创了一个文件名为Student 的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
{
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;
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];
int columnNum = table.Columns.Count;
int rowNum = table.Rows.Count;
for(int i = 1; i < columnNum; i++)
{
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);
}
}
}
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
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();
}
?输出的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
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");
root.AppendChild(data);
XmlElement id = doc.CreateElement("id");
XmlElement name = doc.CreateElement("name");
XmlElement gender = doc.CreateElement("gender");
XmlElement age = doc.CreateElement("age");
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();
}
?输出的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 的实例为例了)
public static void WriteExcel(StudentList instance)
{
string savePath = ExcelConfig.savePath + "Student2" + ".xlsx";
FileInfo fileInfo = new FileInfo(savePath);
using(ExcelPackage package = new ExcelPackage(fileInfo))
{
ExcelWorkbook workbook = package.Workbook;
ExcelWorksheet worksheet;
worksheet = workbook.Worksheets.Add("Sheet1");
for(int i = 0; i < instance.studentList.Count; i++)
{
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();
}
}
?上面代码的作用:获取指定路径的Excel 表(如果没有,会新建),并新建一个子表Sheet1 ,将刚才我们那个读取到List中的学生信息写入进去。
?上面的代码只能添加一个新的子表,如果我们需要修改原有Excel 子表的内容怎么办呢? ?修改原有的内容: ?使用下面这行代码可以让worksheet 获取指定索引的子表:
worksheet = workbook.Worksheets[1];
?获取到了子表,就可以通过worksheet.Cells[] 随意修改表中的内容了。
?注意事项: ?1、在worksheets 中,Excel 的索引是从1 开始的,也就是说:第一张子表的索引是1 ;在子表中,最左上角的单元格的索引是[1,1]
?目前项目中存在的问题: ?1、因为每一张Excel 表的结构不一样,我们用来存储每一条Excel 数据的类(文中项目的Student 与StudentList 类)需要根据不同的Excel 表来修改(暂时没有想到比较好的方法,C# 可以动态创建属性吗?)。 ?2、在ExcelTool 中,读取Excel 数据以及转换格式为xml 的方法中,都是使用的是手动解析和手动设置格式,可以自动化吗?
?附: ?文中的Excel 示例项目的链接:ExcelTest.unitypackage_Supernova_Kai的资源
|