前言

一个游戏通常需要10多个Excel表格或者更多来配置,一般会通过导出csv格式读取配置。

本文提供导出Excel直接生成c#文件,对应数据直接生成结构体和数组,方便开发排错和简化重复写每个表格的读取配置方法。

导出效果

                  

上图左图为Excel表格数据,右图 为导出生成的cs文件。

ExcelAddIn工程

  官方文档:https://msdn.microsoft.com/en-us/library/jj620922.aspx

项目环境配置(VS2015配置):

  1、根据博客The Visual Studio Blog VS2015需要下载一个Update,其他的VS版本没试过。

  2、Microsoft Visual Studio Tools for Applications 2015 SDK

  3、Visual Studio 2010 Tools for Office Runtime

依次安装上述SDK,重启VS后新建项目看到可以创建Excel的外接程序了。如下图:

为了在加载项显示对应的按钮图标,需要在项目工程上右键->添加->选择功能区窗口,如下图:

在窗口界面中通过可视化界面可以直接编辑对应的点击按钮功能等。

导出模板

       为了方便导出数据配置,在项目中添加一个App.config:

配置如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="template" value="//
// #SHEET_NAME# 表格名
//
// #PARAM_DEF# 定义结构体参数
// #DATA_DEF# 初始化表格数据
// #PAIR_DEF# 定义每个参数数据 需要在#DATA_DEF#定义内
using System;
public struct ES_#SHEET_NAME#
{
#PARAM_DEF#
public {} {};
#PARAM_END#
}; public partial class ESSheet
{
private static ES_#SHEET_NAME#[] _#SHEET_NAME# = null;
public static ES_#SHEET_NAME#[] F#SHEET_NAME#
{
get
{
if (_#SHEET_NAME#==null)
{
_#SHEET_NAME# = new ES_#SHEET_NAME#[]
{
#DATA_DEF# new ES_#SHEET_NAME# { #PAIR_DEF#{}={}#PAIR_END# }, #DATA_END#
};
}
return _#SHEET_NAME#;
}
}
};" />
</appSettings>
</configuration>

正则解析数据代码如下:

// export c#
Excel.Worksheet worksheet = (Excel.Worksheet)Globals.ThisAddIn.Application.ActiveSheet; string s = System.Configuration.ConfigurationManager.AppSettings.Get("template");
//去注释
Regex regex = new Regex("//[^\\r\\n]*[\\r\\n]+");
var match = regex.Match(s);
while (match.Success)
{
s = s.Replace(match.Value, "");
match = regex.Match(s);
}
// 替换表格名字
string clsName = worksheet.Name;
regex = new Regex(@"#SHEET_NAME#");
match = regex.Match(s);
while (match.Success)
{
s = s.Replace(match.Value, clsName);
match = regex.Match(s);
} // 参数定义
regex = new Regex("#PARAM_DEF#.*#PARAM_END#", RegexOptions.Singleline);
match = regex.Match(s);
if (match.Success)
{
string formatStr = match.Value.Replace("#PARAM_DEF#", "");
formatStr = formatStr.Replace("#PARAM_END#", "").Trim(); StringBuilder sb = new StringBuilder();
for (int i = ; i < columnCount; i++)
{
sb.AppendFormat(formatStr, param_types[i], param_names[i]);
if (i != columnCount - )
{
sb.AppendLine();
}
}
s = s.Replace(match.Value, sb.ToString());
}
else
{
MessageBox.Show("#PARAM_DEF# 匹配失败!");
return;
} // 数据定义
regex = new Regex("#DATA_DEF#.*#DATA_END#", RegexOptions.Singleline);
match = regex.Match(s);
if (match.Success)
{
string matchAllStr = match.Value;
string formatStr = matchAllStr.Replace("#DATA_DEF#", "");
formatStr = formatStr.Replace("#DATA_END#", "").Trim(); regex = new Regex("#PAIR_DEF#.*#PAIR_END#", RegexOptions.Singleline);
match = regex.Match(formatStr);
if (match.Success)
{
string pairStr = match.Value;
string formatStr2 = pairStr.Replace("#PAIR_DEF#", "");
formatStr2 = formatStr2.Replace("#PAIR_END#", "").Trim(); regex = new Regex(@"string");
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = ; i <= rowCount; i++)
{
sb2.Clear();
for (int j = ; j <= columnCount; j++)
{ string stype = param_types[j - ];
string sname = param_names[j - ];
bool strflg = regex.Match(stype).Success; var value = (worksheet.Cells[i, j] as Excel.Range).Value;
bool nullflg = value == null;
if (!nullflg)
{
string vstr = value.ToString();
vstr = vstr.Trim();
if (string.IsNullOrEmpty(vstr))
{
nullflg = true;
}
else
{
if (strflg)
{
vstr = string.Format("\"{0}\"", vstr);
}
sb2.AppendFormat(formatStr2, sname, vstr);
}
}
if (nullflg)
{
// null cell
if (strflg)
{
// string type?
sb2.AppendFormat(formatStr2, sname, "\"\"");
}
else
{
sb2.AppendFormat(formatStr2, sname, );
}
}
if (j != columnCount)
{
sb2.Append(',');
}
} sb.Append(formatStr.Replace(pairStr, sb2.ToString()));
if (i != rowCount)
{
sb.AppendLine();
}
}
s = s.Replace(matchAllStr, sb.ToString());
}
else
{
MessageBox.Show("#PAIR_DEF# 匹配失败!");
return;
}
}
else
{
MessageBox.Show("#DATA_DEF# 匹配失败!");
return;
}

部分说明

1、几个导出定义:第一行 参数名 , 第二行  参数类型  ,第三行起为 数据,表格名为 结构体名字 。

2、Globals.ThisAddIn.Application.ActiveSheet 为当前选中的Excel表格。

3、获取 i 行 j 列数据方法如下:

var value = (worksheet.Cells[i, j] as Excel.Range).Value;

4、这里导出cs文件,如果需要导出cpp文件可以自己修改上面的模板配置即可实现。

导出路径设置

由于插件没有存储数据的地方,因此这里将导出路径直接存在了注册表上。

方法如下:

     #region RegistStoreData
public static readonly string registryPath = @"Software\YourCompanyName\YourAddInName"; public static void StoreInRegistry(string keyName, string value)
{
RegistryKey rootKey = Registry.CurrentUser;
using (RegistryKey rk = rootKey.CreateSubKey(registryPath))
{
rk.SetValue(keyName, value, RegistryValueKind.String);
}
} public static string ReadFromRegistry(string keyName, string defaultValue = "")
{
RegistryKey rootKey = Registry.CurrentUser;
using (RegistryKey rk = rootKey.OpenSubKey(registryPath, false))
{
if (rk == null)
{
return defaultValue;
} var res = rk.GetValue(keyName, defaultValue);
if (res == null)
{
return defaultValue;
} return res.ToString();
}
}
#endregion
下载

完整代码地址:https://github.com/mydishes/ESExport

可执行插件地址https://github.com/mydishes/ESExport/tree/master/public

最新文章

  1. Spring映射器、适配器、解析器
  2. 高并发应用场景下的负载均衡与故障转移实践,AgileEAS.NET SOA 负载均衡介绍与实践
  3. Java数据结构之字符串模式匹配算法---Brute-Force算法
  4. file_put_contents保存数据,
  5. JMS消息中间件系列[ActiveMQ](一)
  6. TFS2008解除独占式锁定文件命令(转载)
  7. Win7系统安装Centos7.0双系统(二)
  8. Golang几个常用记录日志对比
  9. php接口开发--复制缩减Codeigniter的车轮
  10. GridView动态构建OrderBy进行排序
  11. shell练习--用户下载交互检测
  12. Oracle查看被锁的表和解锁[转]
  13. (Problem 5)Smallest multiple
  14. c# 强制退出程序
  15. php数据库连接及简单操作
  16. Yii2框架ACF(AccessControl Filter)的使用
  17. Linux root密码忘记了怎么办?
  18. Xcode10 library not found for -lstdc++ 找不到问题
  19. 解决Myeclipse通过svn导入项目后,项目直接报错问题
  20. 后端自测必备神器-PostMan

热门文章

  1. Centos 使用 docker
  2. locate命令的使用
  3. s3cmd在配置后使用时提示ERROR: S3 error: 403 (InvalidAccessKeyId): The AWS Access Key Id you provided does not exist in our records.
  4. iOS - 沙盒机制(SandBox)和获取沙盒路径
  5. Django之数据聚合函数 annotate
  6. OpenCV Cut Image via ROI 根据兴趣区域剪裁图片
  7. Taking a peek inside with the Actuator
  8. short url短链接原理
  9. python 使用set对列表去重,并保持列表原来顺序
  10. 如何解决win8系统下卸载软件出现错误代码为2502和2503的问题