1. 程式人生 > >Excel導出插件

Excel導出插件

tostring cell width ngs man ros fig mas path

前言

一個遊戲通常需要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 {0} {1
}; #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#{0}={1}#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 = 0; i < columnCount; i++)
    {
        sb.AppendFormat(formatStr, param_types[i], param_names[i]);
        if (i != columnCount - 1)
        {
            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 = 3; i <= rowCount; i++)
        {
            sb2.Clear();
            for (int j = 1; j <= columnCount; j++)
            {

                string stype = param_types[j - 1];
                string sname = param_names[j - 1];
                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, 0);
                    }
                }
                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;
}
View Code

部分說明

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

Excel導出插件