サポンテ 勉強ノート

サポンテの勉強ノート・読書メモなどを晒します。

【コードジェネレータ】Excel などから TSV を貼り付けて、C# のオブジェクトリスト初期化コードを生成する

【コードジェネレータ】Excel などから TSV を貼り付けて、C# のオブジェクトリスト初期化コードを生成する

はじめに

 ソースコードとデータは切り離して管理すべきですが、それでもコード中にデータを埋め込みたいケースはしばしば発生します。テストコードとか。

 そのようなデータの元ネタとして、Excel や Numbers や Google Spreadsheet などの表計算ソフトや、ObjectBrowser などの RDBMS クライアントを用いたいという要件はあるかと思います。

 そのようなデータ元ネタは「コピー」すると、TSV 文字列としてクリップボードに格納されます。その TSV を「ペースト」してコードを生成してくれるジェネレータを JSFiddle で作りました。

コードジェネレータ

 左の入力欄に、サンプルのように TSV 文字列をコピペして、convert ボタンをクリックしてください。右側の入力欄に生成したコードが書き出されます。

 サンプル文字列がすでに入力されているので、convert ボタンをクリックするだけで動作を確認できます。

生成されるコード例

 以下のようなコードが出力されます。

var dataSrc = new[]{
    @"1  Apple   200",
    @"2  Banana  150",
    @"3  Citrus  300",
};

var data = dataSrc
    .Select(e => e.Split(' '))
    .Select(e => new
    {
        Id = e[0],
        Name = e[1],
        Price = e[2],
    });

foreach (var item in data)
{
    Console.WriteLine(item.ToString());
}

ソースコード

 念のため、ソースコードも載っけておきます。JSFiddle がサービス終了しちゃうかもしれませんからね。

 それに、オフラインで使いたいという要件もあるかもしれません(その場合、CDN のところは修正してください)。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        @media (prefers-color-scheme: dark) {
            body {
                background-color: #333;
                color: #fff;
            }
            textarea {
                background-color: #444;
                color: #fff;
            }
        }
    </style>
</head>
<body>
    <div id="app">
        <textarea name="" id="src" cols="30" rows="10" v-model="src" placeholder="Excel などからコピペしてください"></textarea>
        <button v-on:click="convert">convert</button>
        <textarea name="" id="result" cols="30" rows="10" v-model="result"></textarea>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                src: "Id\tName\tPrice\n1\tApple\t200\n2\tBanana\t150\n3\tCitrus\t300",
                result: "",
            },
            methods: {
                convert: function (e) {
                    var lines = this.src.split("\n");
                    
                    var ret = "var dataSrc = new []{\n";
                    for (let i = 1; i < lines.length; i++) {
                        ret += "    @\"";
                        ret += lines[i];
                        ret += "\",\n";
                    }
                    ret += "};\n\n";
                    
                    ret += "var data = dataSrc\n";
                    ret += "    .Select(e => e.Split('\t'))\n";
                    ret += "    .Select(e => new {\n";
                    var colnames = lines[0].split("\t");
                    for (let j = 0; j < colnames.length; j++) {
                        ret += "        " + colnames[j] + " = e[" + j + "],\n";
                    }
                    ret += "    });\n\n";
                    
                    ret += "foreach (var item in data)\n";
                    ret += "{\n";
                    ret += "    Console.WriteLine(item.ToString());\n";
                    ret += "}\n";
                    
                    this.result = ret;
                }
            }
        });
    </script>
</body>
</html>

おわりに

 以前なら、このようなコードは ExcelVBA で作成していました。

 でも Excel の無い環境もあるでしょうし、VBA だと共有したい時に配布しないといけないんですよね。共有したいツールが増えると、手間も増えます。

 そのような点から、JavaScript を使った Web サービスの方が、作り手の視点からも、使う側の視点からも嬉しい気がしてきました。Web サービスになっていれば URL をメールやチャットで送るだけですからね。JSFiddle や CodePen のような便利なサービスもありますし。