Unity Excel导表工具转Lua文件

news/2025/2/22 19:01:54

思路介绍

借助EPPlus读取Excel文件中的配置数据,根据指定的不同类型的数据配置规则来解析成对应的代码文本,将解析出的字符串内容写入到XXX.lua.txt文件中即可

EPPlus常用API

//命名空间
using OfficeOpenXml;


//Excel文件路径
var fileExcel = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

//加载Excel数据资源
var excelPackage = new ExcelPackage(fileExcel);

//工作表列表
var sheetList = excelPackage.Workbook.Worksheets;

foreach (var sheet in sheetList)
{
    var sheetName = sheet.Name;//工作表名称
    var rowCount = sheet.Dimension.Rows;//总行数
    var columnCount = sheet.Dimension.Columns;//总列数
    
    for (var i = 4; i <= rowCount; i++)
    {
        for (var j = 1; j <= columnCount; j++)
        {
            
            //获取第几行第几列的数据
            var value = sheet.GetValue(i, j);
           
        }
    }
}

制定Excel数据类型配置规则

编写导表工具之前,需要和策划、后端沟通制定数据配置规则

例如:

类型

标记

数值型

number

布尔型

bool

字符串

string

列表

list<type>

type支持:number,bool,string

示例:2,3,4

字典

dic<key|value>

type支持: number,bool,string

示例:语文|88;数学|91;英语|67

 

导入EPPlus.dll


在Unity的Assets下创建Plugins文件夹,并将EPPlus.dll文件放到该文件夹中

核心代码

using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using OfficeOpenXml;
using UnityEditor;

public class ExcelToLua
{
     //Excel导表文件路径
    public static readonly string ExcelFolderPath = "D:\\Study\\Excel";
    //lua文件路径
    private static readonly string LuaFolderPath = Path.Combine(Application.dataPath, "LuaScripts");
    //Table文件后缀拼接
    private const string LuaNameEnd = "Table.lua.txt";
    
    [MenuItem("新项目工具/导表工具/导入Excel表数据", false, 1)]
    static void ImportSingleExcelFile()
    {
        if (Directory.Exists(ExcelFolderPath))
        {
            var path = EditorUtility.OpenFilePanel("打开文件", ExcelFolderPath, "xlsx");
            if (path.Length != 0)
            {
                CreateLuaFile(path);
                AssetDatabase.Refresh();
            }
        }
    }
    
    /// <summary>
    /// 获取Excel数据并创建Lua文件
    /// </summary>
    /// <param name="filePath"></param>
    public static void CreateLuaFile(string filePath)
    {
        //Excel文件路径
        var fileExcel = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        
        //加载Excel数据资源
        var excelPackage = new ExcelPackage(fileExcel);
        
        //工作表列表
        var sheetList = excelPackage.Workbook.Worksheets;
        
        StringBuilder sb = new StringBuilder();
        //变量字典
        var variableDic = new Dictionary<int, string>();
        //变量类型字典
        var typeDic = new Dictionary<int, string>();
        
        var fileName = Path.GetFileName(filePath); //文件名称带后缀  例:A-活动_activity.xls
        sb.Append($"--{fileName}\nreturn {{\n");
        
        foreach (var sheet in sheetList)
        {
            variableDic.Clear();
            typeDic.Clear();
            var sheetName = sheet.Name;//工作表名称
            var rowCount = sheet.Dimension.Rows;//总行数
            var columnCount = sheet.Dimension.Columns;//总列数
            
            //变量类型列表
            InitSheetDic(sheet, typeDic, 1);
            //变量列表
            InitSheetDic(sheet, variableDic, 2);
            sb.Append($"[\"{sheetName}\"] = {{\n");
            
            for (var i = 4; i <= rowCount; i++)
            {
                for (var j = 1; j <= columnCount; j++)
                {
                    if (!typeDic.ContainsKey(j) || !variableDic.ContainsKey(j))
                    {
                        break;
                    }
                 
                    var type = typeDic[j];
                    var variable = variableDic[j];
                 
                    if (type == null || variable == null)
                    {
                        continue;
                    }
                    //获取第几行第几列的数据
                    var value = sheet.GetValue(i, j);
                    var valueStr = GetTypeValue(type, value);
                    if (j == 1)
                    {
                        sb.Append($"    [{valueStr}] = {{");
                    }
                         
                    sb.Append($"{variable} = {valueStr};");
                }
                sb.Append("};\n");
            }
            
            sb.Append("},\n");
        }
        
        sb.Append("}");
        
        var txtName = Path.GetFileNameWithoutExtension(filePath);
        var nameIndex = txtName.LastIndexOf('_');
        if (nameIndex != -1)
        {
            txtName = txtName.Substring(nameIndex + 1);
            txtName = txtName.Substring(0, 1).ToUpper() + txtName.Substring(1);
        }
             
        //创建XXXTable文件
        File.WriteAllText($"{LuaFolderPath}\\{txtName}{LuaNameEnd}", sb.ToString());
        
        Debug.Log($"<color=#00EE00>{fileName}</color>表导入成功");
        sb.Clear();
    }
    
    //将Excel列表某一行的数据初始化到指定字典中
    private static void InitSheetDic(ExcelWorksheet sheet, Dictionary<int, string> dic, int rowNum)
    {
        var columnSum = sheet.Dimension.End.Column;
        for (var i = 1; i <= columnSum; i++)
        {
            var value = sheet.GetValue(rowNum, i);
            if (value == null)
                break;
            dic[i] = value.ToString();
        }
    }
    
    //根据不同类型的数据拼接对应格式的数据内容
    private static string GetTypeValue(string typeStr, object val)
    {
        if (val == null)
            return GetDefaultValue(typeStr);
    
        var value = val.ToString();
        var result = value;
        switch (typeStr)
        {
            case "number":
            case "bool":
                break;
            case "string":
                result = "\"" + value + "\"";
                break;
            case "list<number>":
            case "list<bool>":
                result = "{" + value + "}";
                break;
            case "list<string>":
                var strArray = value.Split(',');
                if (strArray.Length > 0)
                {
                    var sb = new StringBuilder();
                    sb.Append("{");
                    foreach (var item in strArray)
                    {
                        sb.Append($"\"{item}\",");
                    }
    
                    sb.Append("}");
                    result = sb.ToString();
                }
                break;
            default:
                if (typeStr.Contains("dic<"))
                {
                    if (typeStr.Contains("string"))
                    {
                        var frontIndex = typeStr.IndexOf("string");
                        var backIndex = typeStr.LastIndexOf("string");
                        var isFront = frontIndex == 5;
                        var isBack = backIndex == (typeStr.Length - 7);
    
                        var strDic = value.Split(';');
                        if (strDic.Length > 0)
                        {
                            var sb = new StringBuilder();
                            sb.Append("{");
                            foreach (var item in strDic)
                            {
                                var cell = item.Split("|");
                                var frontStr = isFront ? "\"" + cell[0] + "\"" : cell[0];
                                var backStr = isBack ? "\"" + cell[1] + "\"" : cell[1];
                                sb.Append($"[{frontStr}] = {backStr},");
                            }
    
                            sb.Append("}");
                            result = sb.ToString();
                        }
                    }
                    else
                    {
                        var sb = new StringBuilder();
                        var strDic = value.Split(';');
                        if (strDic.Length > 0)
                        {
                            sb.Append("{");
                            foreach (var item in strDic)
                            {
                                var cell = item.Split("|");
                                sb.Append($"[{cell[0]}] = {cell[1]},");
                            }
    
                            sb.Append("}");
                            result = sb.ToString();
                        }
                    }
                }
                else
                {
                    result = "\"" + value + "\"";
                }
                break;
        }
        return result;
    }
    
    //如果某个数据未填,返回默认值
    private static string GetDefaultValue(string typeStr)
    {
        string result;
        switch (typeStr)
        {
            case "number":
                result = "0";
                break;
            case "bool":
                result = "false";
                break;
            case "string":
                result = "\"\"";
                break;
            default:
                if (typeStr.Contains("dic") || typeStr.Contains("list"))
                    result = "{}";
                else
                    result = "\"\"";
                break;
        }
        return result;
    }
}

小提示

1、在实际开发工作中,一般会用到导入单个或者所有的表两种逻辑。对于导出所有的表的逻辑,可以借助多线程来提高效率。

2、对于一些配置错误的情况也需要考虑到,增加一些报错逻辑判断并提示。


http://www.niftyadmin.cn/n/5862658.html

相关文章

论文概览 |《Urban Analytics and City Science》2023.10 Vol.50 Issue.8

本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年10月第50卷第8期的论文的题目和摘要&#xff0c;一共包括21篇SCI论文&#xff01; 论文1 Advances in geospatial approaches to transport networks and sustainable mobility …

YARN的工作机制及特性总结

YARN hadoop的资源管理调度平台&#xff08;集群&#xff09;——为用户程序提供运算资源的管理和调度 用户程序&#xff1a;如用户开发的一个MR程序 YARN有两类节点&#xff08;服务进程&#xff09;&#xff1a; 1. resourcemanager 主节点master ----只需要1个来工作 2. nod…

06、ElasticStack系列,第六章:elasticsearch设置密码

第六章&#xff1a;Elasticsearch设置密码 一、修改配置文件 ##进入容器 docker exec -it elasticsearch bash##启用认证 vi config/elasticsearch.yml 添加如下内容&#xff1a; http.cors.enabled: true http.cors.allow-origin: "*" http.cors.allow-headers: A…

基于Python+Django+Vue的旅游景区推荐系统系统设计与实现源代码+数据库+使用说明

运行截图 功能介绍 前台功能包括&#xff1a;首页、详情页、订单、用户中心。后台功能包括&#xff1a;首页、轮播图管理、管理员、卖家管理、买家管理、景区管理、订单管理非开源功能&#xff08;分类管理&#xff0c;地区管理&#xff0c;收藏管理&#xff0c;评论管理&a…

echarts找不到了?echarts社区最新地址

前言&#xff1a;在之前使用echarts的时候&#xff0c;还可以通过上边的导航栏找到echarts社区&#xff0c;但是如今的echarts变更之后&#xff0c;就找不到echarts社区了。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 如今…

【雅思博客06】Daily Life

对话 A: Honey, the house is such a mess! I need you to help me tidy up a bit. My boss and her husband are coming over for dinner, and the house needs to be spotless! B: I’m in the middle of something right now. I’ll be there in a second. A: This can’t …

【电机控制器】ESP32-C3语言模型——豆包

【电机控制器】ESP32-C3语言模型——豆包 文章目录 [TOC](文章目录) 前言一、简介二、代码三、实验结果四、参考资料总结 前言 使用工具&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、简介 二、代码 #include <WiFi.h> #inc…

【CXX】5 桥接模块参考

1 CXX主要概念概览已经涵盖了CXX用来表示语言边界的高级模型。本章在此基础上详细介绍#[cxx::bridge]的语法和功能。 extern “Rust” ——将不透明的Rust类型、Rust函数、Rust方法暴露给C&#xff1b;具有生命周期的函数。extern“C”——绑定不透明的C类型、C函数、C成员函数…