Groovy で Excel ファイルを読み込んで .properties ファイルを作成してみる

Java の .properties ファイルってのを作成するための元データを Excel で管理していて、今までは Excel マクロ を使って .properties ファイルを作成していたんだけど、
ビルドプロセスの一環に組み込む事にしようってことで、Excel マクロだと権限の問題等があって何とかならないかな〜?と相談された。


そこで、「Groovy だったら Excel ファイルもサクッと扱えますよ」と自分で試した事も無いのに言ってみたら、じゃあ Groovy 使っていいよって事になったので勉強中。
こんな感じの Excel から

各言語毎に、.properties ファイルを作成したい。

日本語 英語


ScriptomでExcelファイルの内容の読み込み - No Programming, No Life を参考にして何とか出来た!

import org.codehaus.groovy.scriptom.*

def messages = [ ja : new Properties(), en : new Properties() ]

Scriptom.inApartment
{
  def excelApp
  def workBook
  try { 
    excelApp = new ActiveXObject('Excel.Application')
    def fileName = "〜\\Message.xls"
    // ファイルを開く
    workBook = excelApp.workbooks.open(fileName)
   
    // セルに対しての操作
    workBook.sheets(1).cells.with {
      def rowIndex = 2
      def messageKey = cells.item(rowIndex, 1).value
      while (messageKey) { 
        def japanese = cells.item(rowIndex, 2).value
        def english = cells.item(rowIndex, 3).value
        messages.ja.setProperty(messageKey, japanese)
        messages.en.setProperty(messageKey, english)
        rowIndex++
        messageKey = cells.item(rowIndex, 1).value
      } 
    }
  } finally { 
    workBook?.close()
    excelApp?.quit()
  }
}

messages.each { entry -> 
  entry.value.store(new File("〜\\Message_${entry.key}.properties").newOutputStream(), "$entry.key")
}

まだ、Groovy を使い慣れてないんだろうな〜。もっとスッキリ実装出来そうな気がする。。

注意する点は、Excel の quit メソッドが呼ばれないと Excel のプロセス が残ったままになる。これは、.NET から呼び出しても同じかな。


ただ .NET の場合使用した参照を全部保持して、System.Runtime.InteropServices.Marshal.ReleaseComObject メソッド で参照をデクリメントしないと Excel プロセスを解放しないので、Groovy の方が楽ちん!
ちなみに C# で COMで Excel を操作する場合のソース (メンドイので途中省略)(VSTO の場合は、ここまできっちり解放しなくても大丈夫なはず)

※遅延バインディング(Excelのバージョンを意識しない様に)を使ってるので、全部 Invoke 経由でのアクセスになってますが、
 遅延バインディングでは無くても 全部 try〜finally で囲って ReleaseComObject メソッドを呼ばないとダメです。
 また、try 〜 finally を全部一つにすると ReleaseComObject メソッドで例外が発生した場合、全て解放されないケースが出てくるので、一つずつ解放しないとダメなはずです。

using System;
using System.Reflection;

namespace ConsoleApplication15 {
  class Program {
    static void Main(string[] args) {
      object excelApp = null;
      try {
        excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
        object workbooks = null;
        try {
          workbooks = excelApp.GetType().InvokeMember("Workbooks", BindingFlags.Public | BindingFlags.GetProperty, null, excelApp, null);
          object workbook = null;
          try {
            workbook = workbooks.GetType().InvokeMember("Open", BindingFlags.Public | BindingFlags.InvokeMethod, null, workbooks, new object[] { @"〜\Message.xls" });
            object sheets = null;
            try {
              sheets = workbook.GetType().InvokeMember("Sheets", BindingFlags.Public | BindingFlags.GetProperty, null, workbook, null);
              object sheet = null;
              try {
                sheet = sheets.GetType().InvokeMember("Item", BindingFlags.Public | BindingFlags.GetProperty, null, sheets, new object[] { 1 });
                // Cells
                try {
                  // Cell
                  while(true) {
                    try {
                    } finally {
                    }
                    if (〜) {
                      break;
                    }
                  }
                } finally {
                }
              } finally {
                if (sheet != null) {
                  System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
                }
              }
            } finally {
              if (sheets != null) {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
              }
            }
          } finally {
            if (workbook != null) {
              try {
                workbook.GetType().InvokeMember("Close", BindingFlags.Public | BindingFlags.InvokeMethod, null, workbook, null);
              } finally {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
              }
            }
          }
        } finally {
          if (workbooks != null) {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
          }
        }
      } finally {
        if (excelApp != null) {
          try {
            excelApp.GetType().InvokeMember("Quit", BindingFlags.Public | BindingFlags.InvokeMethod, null, excelApp, null);
          } finally {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
          }
        }
      }
    }
  }
}