问题解决其实很简单,但是我走了弯路,记录下解决的过程,这也是写代码的乐趣所在。
为实现在Unity3D中读写Excel,我开始仅仅使用了以下两个dll文件:
在Unity Editor中读写Excel完全正常,但是RT,打包成exe后报错如下:
很气,打包成exe后报错连错在哪行代码都不知道,只知道肯定用了某个值为null的变量。我开始还一直在想办法想怎么才能知道错误发生在哪行代码。我发现在Unity Editor中一样的NullReferenceException是给出了具体代码行号的,为什么打包成exe后没有了呢。然后我忽然想通了,感觉自己犯了个低级错误,打包成exe后报错是不可能有具体行号的,因为C#作为一种介于解释型和编译型之间的语言,打包成exe之后其代码已经由.net的语言编译器转化为.net目标代码了,根本不是我写代码时候的样子了。于是我实在一点头绪都没有,只能用了个笨办法,我在出错的这个方法中定义一个初值为0的整型变量i,每执行一行代码就让i++,并且在catch中提示错误的时候显示i的值,这样我就知道了错误原来发生在这里:
IExcelDataReader iExcelDR = ExcelReaderFactory.CreateOpenXmlReader(fs);
DataSet ds = iExcelDR.AsDataSet();
经过检查发现DataSet对象ds的值为null.
OK,那它为什么会为null呢。我先看了这篇帖子:帖子1
里面说了几种从IExcelDataReader读取数据的方法,我都试了,还是一样的NullReferenceException。但是这个帖子里面又给了个github的链接,这是我看的第二个帖子:帖子2
可是我发现这个帖子里面还是没有我想要的答案。这时我在帖子1的评论区里面发现了一个链接:帖子3
这时我才知道,原来我少添加了以上几个dll文件。在安装路径下的\Editor\Data\Mono\lib\mono\unity即可找到这几个dll文件。这是我的路径:
最后附上读写Excel的代码,省略了参数和返回值:
读写Excel所用的引用:
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Data;
using UnityEngine;
using Excel;
using OfficeOpenXml;
using System.Drawing;
读Excel:
public static void ReadExcel()
{
try
{
string ExcelPath = "";//(Excel的路径)
string UserInfo = "";
FileStream fs = File.Open(Excel_Path, FileMode.Open, FileAccess.Read, FileShare.Read);
//这里要注意“.xlsx”格式的文件要使用CreateOpenXmlReader;“.xls”格式的文件要使用CreateBinaryReader
IExcelDataReader iExcelDR = ExcelReaderFactory.CreateOpenXmlReader(fs);
DataSet ds = iExcelDR.AsDataSet();
//0表示是sheet1,读取sheet1的总行数和总列数
int columns = ds.Tables[0].Columns.Count; //总列数
int rows = ds.Tables[0].Rows.Count; //总行数
for (int i = 0; i < rows; i++)
{
//读取每行的第二列的数据,表示行和列的下标均从0开始
string Str = Convert.ToString(ds.Tables[0].Rows[i][1]);
}
}
catch (Exception e)
{
MessageBox.Show(e + " Exception caught. ", "提示", SystemFonts.FormTextFont);
return null;//表示有异常
}
}
向Excel中写入数据:
public static void WriteExcel()
{
//获取要创建Excel文件的路径
string path = ExcelPath;
//该路径的文件是否存在的标识符
bool IsExist = true;
FileInfo newFile = new FileInfo(path);
//如果文件不存在 则先新建一个文件 添加sheet和表头
if (!newFile.Exists)
{
//创建一个新的excel文件
newFile = new FileInfo(path);
IsExist = false;
}
//通过ExcelPackage打开文件
using (ExcelPackage package = new ExcelPackage(newFile))
{
ExcelWorksheet worksheet;
if (IsExist == false)//如果文件不存在,则为新建的Excel表添加sheet和表头
{
worksheet = package.Workbook.Worksheets.Add("Sheet1");
worksheet.Cells[1, 1].Value = "第一列表头";
worksheet.Cells[1, 2].Value = "第二列表头";
worksheet.Cells[1, 3].Value = "第三列表头";
worksheet.Cells[1, 4].Value = "第四列表头";
}
else//如果文件存在 直接获取sheet
{
//获取Sheet1,以向其中写入数据
worksheet = package.Workbook.Worksheets["Sheet1"];
}
//遍历第一列 找到第一个空白行 然后再写入数据
int i = 1;
while (Convert.ToString(worksheet.Cells[i, 1].Value) != "")
{
i++;
}
//此时第i行即为第一个空白行 接下来在该行写入数据
//此处要注意 获取单元格的时候 行和列的序号都是从1开始的 行前列后
//第一列写入数据
worksheet.Cells[i, 1].Value = "第一列数据";
//第二列写入数据
worksheet.Cells[i, 2].Value = "第二列数据"
//第三列写入数据
worksheet.Cells[i, 3].Value = "第三列数据"
//第四列写入数据
worksheet.Cells[i, 4].Value = "第四列数据"
//保存excel
package.Save();
}
}
欢迎留言交流指正。