読者です 読者をやめる 読者になる 読者になる

【SSIS】日本語の小文字を大文字に変換する

たまにある要件シリーズです。

半角カタカナを全角にする、とかなら文字マップ変換を使うのがベストなんですが、ひらがなやカタカナの小文字(「ぁ」とか「ゃ」とか)を大文字に変換する機能は流石についていません。

一応大文字⇔小文字の変換があるんですが、これは多分アルファベットじゃないと無理です。実際に試したところ、日本語では変換されませんでした。

仕方ないので自力で変換テーブルを作ってマッピングしましょう。

後、正確には小文字ではなく捨て仮名もしくは小書き文字と呼ぶらしいです。ためになりますね。

変換テーブルの作成

Wikipediaを参考に変換用のDictionaryを作ってみましょう。

var nameDic = new Dictionary<char, char>()
{
    {'ぁ', 'あ'},
    {'ぃ', 'い'},
    {'ぅ', 'う'},
    {'ぇ', 'え'},
    {'ぉ', 'お'},
    {'っ', 'つ'},
    {'ゃ', 'や'},
    {'ゅ', 'ゆ'},
    {'ょ', 'よ'},
    {'ゎ', 'わ'},
    {'ァ', 'ア'},
    {'ィ', 'イ'},
    {'ゥ', 'ウ'},
    {'ェ', 'エ'},
    {'ォ', 'オ'},
    {'ヵ', 'カ'},
    {'ヶ', 'ケ'},
    {'ッ', 'ツ'},
    {'ャ', 'ヤ'},
    {'ュ', 'ユ'},
    {'ョ', 'ヨ'},
    {'ヮ', 'ワ'},
};

後は対象のstringをforeachで回し、StringBuilderかなんかで組み立て直してあげればOKです。

コード

実際のコードはこんな感じです。以前と同じようにリフレクションを使います。カラムの設定をReadWriteにしておくのを忘れないようにしましょう。

public override void 入力0_ProcessInputRow(入力0Buffer Row)
{
    var nameDic = new Dictionary<char, char>()
    {
        {'ぁ', 'あ'},
        {'ぃ', 'い'},
        {'ぅ', 'う'},
        {'ぇ', 'え'},
        {'ぉ', 'お'},
        {'っ', 'つ'},
        {'ゃ', 'や'},
        {'ゅ', 'ゆ'},
        {'ょ', 'よ'},
        {'ゎ', 'わ'},
        {'ァ', 'ア'},
        {'ィ', 'イ'},
        {'ゥ', 'ウ'},
        {'ェ', 'エ'},
        {'ォ', 'オ'},
        {'ヵ', 'カ'},
        {'ヶ', 'ケ'},
        {'ッ', 'ツ'},
        {'ャ', 'ヤ'},
        {'ュ', 'ユ'},
        {'ョ', 'ヨ'},
        {'ヮ', 'ワ'},
    };

    var propArray = Row.GetType().GetProperties();

    var isNullProp = propArray.Where(x => x.Name.Contains("_IsNull"));
    var valueProp = propArray.Where(x => !x.Name.Contains("_IsNull"));

    do
    {
        //値がNULLかどうかをチェックするDictionaryを作成
        var isNullDic = isNullProp
                        .Select(x => new { Name = x.Name.Replace("_IsNull", ""), Value = (bool)x.GetValue(Row, null) })
                        .ToDictionary(x => x.Name, y => y.Value);

        foreach (var prop in valueProp.Where(x => !isNullDic[x.Name]))
        {
            var name = prop.GetValue(Row, null) as string;
            var sb = new StringBuilder();

            foreach (var c in name)
            {
                if (nameDic.ContainsKey(c))
                {
                    sb.Append(nameDic[c]);
                }
                else
                {
                    sb.Append(c);
                }
            }

            prop.SetValue(Row, sb.ToString(), null);
        }
        
    } while (Row.NextRow());
}

まとめ

Dictionaryを用意するのは別にProcessInputRowじゃなくてもいいです。好みの問題だと思います。