前言

一个游戏通常需要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:

配置如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <configuration>
  3. <appSettings>
  4. <add key="template" value="//
  5. // #SHEET_NAME# 表格名
  6. //
  7. // #PARAM_DEF# 定义结构体参数
  8. // #DATA_DEF# 初始化表格数据
  9. // #PAIR_DEF# 定义每个参数数据 需要在#DATA_DEF#定义内
  10. using System;
  11. public struct ES_#SHEET_NAME#
  12. {
  13. #PARAM_DEF#
  14. public {} {};
  15. #PARAM_END#
  16. };
  17.  
  18. public partial class ESSheet
  19. {
  20. private static ES_#SHEET_NAME#[] _#SHEET_NAME# = null;
  21. public static ES_#SHEET_NAME#[] F#SHEET_NAME#
  22. {
  23. get
  24. {
  25. if (_#SHEET_NAME#==null)
  26. {
  27. _#SHEET_NAME# = new ES_#SHEET_NAME#[]
  28. {
  29. #DATA_DEF# new ES_#SHEET_NAME# { #PAIR_DEF#{}={}#PAIR_END# }, #DATA_END#
  30. };
  31. }
  32. return _#SHEET_NAME#;
  33. }
  34. }
  35. };" />
  36. </appSettings>
  37. </configuration>

正则解析数据代码如下:

  1. // export c#
  2. Excel.Worksheet worksheet = (Excel.Worksheet)Globals.ThisAddIn.Application.ActiveSheet;
  3.  
  4. string s = System.Configuration.ConfigurationManager.AppSettings.Get("template");
  5. //去注释
  6. Regex regex = new Regex("//[^\\r\\n]*[\\r\\n]+");
  7. var match = regex.Match(s);
  8. while (match.Success)
  9. {
  10. s = s.Replace(match.Value, "");
  11. match = regex.Match(s);
  12. }
  13. // 替换表格名字
  14. string clsName = worksheet.Name;
  15. regex = new Regex(@"#SHEET_NAME#");
  16. match = regex.Match(s);
  17. while (match.Success)
  18. {
  19. s = s.Replace(match.Value, clsName);
  20. match = regex.Match(s);
  21. }
  22.  
  23. // 参数定义
  24. regex = new Regex("#PARAM_DEF#.*#PARAM_END#", RegexOptions.Singleline);
  25. match = regex.Match(s);
  26. if (match.Success)
  27. {
  28. string formatStr = match.Value.Replace("#PARAM_DEF#", "");
  29. formatStr = formatStr.Replace("#PARAM_END#", "").Trim();
  30.  
  31. StringBuilder sb = new StringBuilder();
  32. for (int i = ; i < columnCount; i++)
  33. {
  34. sb.AppendFormat(formatStr, param_types[i], param_names[i]);
  35. if (i != columnCount - )
  36. {
  37. sb.AppendLine();
  38. }
  39. }
  40. s = s.Replace(match.Value, sb.ToString());
  41. }
  42. else
  43. {
  44. MessageBox.Show("#PARAM_DEF# 匹配失败!");
  45. return;
  46. }
  47.  
  48. // 数据定义
  49. regex = new Regex("#DATA_DEF#.*#DATA_END#", RegexOptions.Singleline);
  50. match = regex.Match(s);
  51. if (match.Success)
  52. {
  53. string matchAllStr = match.Value;
  54. string formatStr = matchAllStr.Replace("#DATA_DEF#", "");
  55. formatStr = formatStr.Replace("#DATA_END#", "").Trim();
  56.  
  57. regex = new Regex("#PAIR_DEF#.*#PAIR_END#", RegexOptions.Singleline);
  58. match = regex.Match(formatStr);
  59. if (match.Success)
  60. {
  61. string pairStr = match.Value;
  62. string formatStr2 = pairStr.Replace("#PAIR_DEF#", "");
  63. formatStr2 = formatStr2.Replace("#PAIR_END#", "").Trim();
  64.  
  65. regex = new Regex(@"string");
  66. StringBuilder sb = new StringBuilder();
  67. StringBuilder sb2 = new StringBuilder();
  68. for (int i = ; i <= rowCount; i++)
  69. {
  70. sb2.Clear();
  71. for (int j = ; j <= columnCount; j++)
  72. {
  73.  
  74. string stype = param_types[j - ];
  75. string sname = param_names[j - ];
  76. bool strflg = regex.Match(stype).Success;
  77.  
  78. var value = (worksheet.Cells[i, j] as Excel.Range).Value;
  79. bool nullflg = value == null;
  80. if (!nullflg)
  81. {
  82. string vstr = value.ToString();
  83. vstr = vstr.Trim();
  84. if (string.IsNullOrEmpty(vstr))
  85. {
  86. nullflg = true;
  87. }
  88. else
  89. {
  90. if (strflg)
  91. {
  92. vstr = string.Format("\"{0}\"", vstr);
  93. }
  94. sb2.AppendFormat(formatStr2, sname, vstr);
  95. }
  96. }
  97. if (nullflg)
  98. {
  99. // null cell
  100. if (strflg)
  101. {
  102. // string type?
  103. sb2.AppendFormat(formatStr2, sname, "\"\"");
  104. }
  105. else
  106. {
  107. sb2.AppendFormat(formatStr2, sname, );
  108. }
  109. }
  110. if (j != columnCount)
  111. {
  112. sb2.Append(',');
  113. }
  114. }
  115.  
  116. sb.Append(formatStr.Replace(pairStr, sb2.ToString()));
  117. if (i != rowCount)
  118. {
  119. sb.AppendLine();
  120. }
  121. }
  122. s = s.Replace(matchAllStr, sb.ToString());
  123. }
  124. else
  125. {
  126. MessageBox.Show("#PAIR_DEF# 匹配失败!");
  127. return;
  128. }
  129. }
  130. else
  131. {
  132. MessageBox.Show("#DATA_DEF# 匹配失败!");
  133. return;
  134. }

部分说明

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

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

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

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

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

导出路径设置

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

方法如下:

  1. #region RegistStoreData
  2. public static readonly string registryPath = @"Software\YourCompanyName\YourAddInName";
  3.  
  4. public static void StoreInRegistry(string keyName, string value)
  5. {
  6. RegistryKey rootKey = Registry.CurrentUser;
  7. using (RegistryKey rk = rootKey.CreateSubKey(registryPath))
  8. {
  9. rk.SetValue(keyName, value, RegistryValueKind.String);
  10. }
  11. }
  12.  
  13. public static string ReadFromRegistry(string keyName, string defaultValue = "")
  14. {
  15. RegistryKey rootKey = Registry.CurrentUser;
  16. using (RegistryKey rk = rootKey.OpenSubKey(registryPath, false))
  17. {
  18. if (rk == null)
  19. {
  20. return defaultValue;
  21. }
  22.  
  23. var res = rk.GetValue(keyName, defaultValue);
  24. if (res == null)
  25. {
  26. return defaultValue;
  27. }
  28.  
  29. return res.ToString();
  30. }
  31. }
  32. #endregion
下载

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

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

Excel导出插件-VSTO的更多相关文章

  1. Excel导出插件

    前言 一个游戏通常需要10多个Excel表格或者更多来配置,一般会通过导出csv格式读取配置. 本文提供导出Excel直接生成c#文件,对应数据直接生成结构体和数组,方便开发排错和简化重复写每个表格的 ...

  2. jsexcel导出插件

    ExcelTable.js /* * author:wenluanlai */ (function ($) { Date.prototype.Format = function (fmt) { var ...

  3. PHP原生EXCEL导出带样式无插件无乱码实现

    PHP原生EXCEL导出 经测试 带样式 无插件 无乱码,不需要引入任何插件,不需要修改任何编码 (使用时只需要修改引入php数据库配置文件.修改thead tbody中的数据即可.根据自己的需要去接 ...

  4. Asp.Net 常用工具类之Office—Excel导出(4)

    开发过程中各类报表导入导出防不胜防,网上也是各种解决方法层出不穷,比如Excel,CSV,Word,PDF,HTML等等... 网上各种导出插件也是层出不穷,NPOI,微软Microsoft.Offi ...

  5. .NET Excel导出方法及其常见问题详解

    摘要:.NET Excel导出方法及其常见问题详解. 一.Excel导出的实现方法 在.net 程序开发中,对于Excel文件的导出我们一共有三种导出方式: 利用文件输出流进行读写操作 这种方式的导出 ...

  6. .Net Excel 导出图表Demo(柱状图,多标签页) .net工具类 分享一个简单的随机分红包的实现方式

    .Net Excel 导出图表Demo(柱状图,多标签页) 1 使用插件名称Epplus,多个Sheet页数据应用,Demo为柱状图(Epplus支持多种图表) 2 Epplus 的安装和引用 新建一 ...

  7. laravel 导出插件

    转发:https://blog.csdn.net/gu_wen_jie/article/details/79296470 版本:laravel5 php 5.6 安装步骤: 一.安装插件 ①.首先在L ...

  8. js-xlsx 实现前端 Excel 导出(支持多 sheet)

    之前写文章介绍了使用 js-xlsx 实现导入 excel 的功能,现在再介绍一下如何使用 js-xlsx 进行 excel 导出. [实现步骤] 1. 首先安装依赖 npm install xlsx ...

  9. [moka同学笔记]PHPexcel之excel导出和导入

    原案例来自http://www.sucaihuo.com/有修改 1.目录结构(文件不用解释,应该都可以看得懂,直接看代码)

随机推荐

  1. 如何查看Mac电脑的处理器核心数目-CPU的核心数目

    1.通过点击关于本机来查看

  2. Egret第三方库的制作和使用(模块化 第三方库)

    一.第三方库的制作 官方教程:第三方库的使用方法 水友帖子:新版本第三方库制作细节5.1.x 首先在任意需要创建第三方库的地方,右键,选择"在此处打开命令窗口" 输入egret c ...

  3. C++ Error: no appropriate default constructor available

    我定义了一个结构体,然后初始化它,结果编译报错 no appropriate default constructor available 代码如下: struct matrixXvect_func { ...

  4. iOS - 使用苹果自带的UIVideoEditController进行视频编辑

    UIVideoEditorController类包含了由系统提供的界面,使用户可以交互式的剪切视频.UIVideoEditorController对象处理用户的交互并且提供把编辑后的视频的文件系统路径 ...

  5. R的any和all

    > x<-1:10 > any(x>8) [1] TRUE > all(x>8) [1] FALSE

  6. python转化字符串形式的json

    在使用python对字符串形式的json进行 json.loads() 的操作时,遇到了:JSONDecodeError: Invalid \escape,提示\无法excape,可以通过以下方式将字 ...

  7. html的base标签

    提示:请把 <base> 标签排在 <head> 元素中第一个元素的位置,这样 head 区域中其他元素就可以使用 <base> 元素中的信息了. 注释:如果使用了 ...

  8. 1.0Tensorflow中出现编译问题的解决方案

    跑简单tf例程的时候遇到这个 sess = tf.Session(),I tensorflow/core/platform/cpu_feature_guard.cc:] Your CPU suppor ...

  9. URAL 1277 - Cops and Thieves - [无向图点带权的最小点割]

    题目链接:https://cn.vjudge.net/problem/URAL-1277 The Galaxy Police (Galaxpol) found out that a notorious ...

  10. ionic项目打包好Xcode工程,模拟器运行各种沙盒缓存目录

    用ionic开发好的app,build好iOS端可用的Xcode工程,然后用模拟器跑起来.研究一下js写的代码做本地持久化时,不同类型的文件都放在那里了. cordova-plugin-sqliteS ...