タイミングチャートをIronPythonとExcelを使って書いてみる
いつもの如く、ネットをふらふらしていたら、以下のBlogネタを見つけました。
- shirouの現実touhi[wp] ≫ タイムチャート作成ソフト(他
http://www.shirou.jp/blog1/?p=520 - なひたふJTAG日記: Microsoft Excelで波形を描く方法
http://nahitafu.cocolog-nifty.com/nahitafu/2007/04/excel_e5a2.html - タイミングチャート清書ツール tchart
http://www.mech.tohoku-gakuin.ac.jp/rde/contents/library/tchart/indexframe.html
そっか〜、Excelでもタイミングチャート書けるんだぁ…。
…ちと勉強用にIronPythonを使って、Excelにタイミングチャートを書くツールを作ってみっかな?
という訳で
作ってみました。
名前は、t_cha(T-茶)って命名してみました。(茶に意味は無い)
つまりは、↓こんな事ができます。
t_cha1 posted by (C)wacky
使い方は、以下のステップを踏みます。
- テキスト形式で、タイミングチャートデータを作ります
タイミングチャートデータの書式は、タイミングチャート清書ツール:原稿の作り方の一部をサポートしています(まぁ、後述するソースを見れば一目瞭然ですね) - "t_cha.py"って言う、IronPythonプログラムを動かします
第1引数に1.のテキストファイルを与え、第2引数には、出力したいExcelファイル名を与えます - "t_cha.py"が動いて、テキストファイルを読み込んでExcelの上にタイミングチャート図を作ります
その後、Excelファイルに出力して終了します
ふむ、結構簡単に作れるもんですね。
t_chaを使う前の、お膳立て
今回のIronPythonツールは、Excelを必要とします。
という訳で、以下のようにして、COMタイプライブラリをIronPythonで読める形式のライブラリに変換してください。
(実行例は、Excel2000ですが、.olbファイルさえ合わせれば、何でもOKだと思います)
C:\Program Files\Microsoft Office\Office>tlbimp "C:\Program Files\Microsoft Offi ce\Office\EXCEL9.OLB" /out:excel9.dll Microsoft (R) .NET Framework Type Library to Assembly Converter 2.0.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. Type library imported to C:\Program Files\Microsoft Office\Office\excel9.dll
実行すると、以下の3ファイルが自動生成されます。
- excel9.dll
- office.dll
- vbide.dll
出来たら、t_chaを実行するフォルダにコピーして下さい。
t_chaのソースコード
次に、t_chaのソースを以下に示します。
ファイル名は、"t_cha.py"とでもして下さい。
#!/usr/bin/env python # coding: cp932 """ 参考にしたリンク。 -shirouの現実touhi[wp] ≫ タイムチャート作成ソフト(他 http://www.shirou.jp/blog1/?p=520 -なひたふJTAG日記: Microsoft Excelで波形を描く方法 http://nahitafu.cocolog-nifty.com/nahitafu/2007/04/excel_e5a2.html -タイミングチャート清書ツール tchart http://www.mech.tohoku-gakuin.ac.jp/rde/contents/library/tchart/indexframe.html -【VB.NET】COMラッパーアセンブリに厳密名で署名 - Insider.NET http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=27151&forum=7 -Excel97 の COM の IDL から TLB を生成したい http://m--takahashi.com/bbs/pastlog/09100/09068.html """ import sys import nt import clr clr.AddReferenceToFile("Excel9.dll") from excel9 import * clr.AddReferenceToFile("Office.dll") from Office import * class TimingChartExcel: """タイミングチャートをExcelで描画するクラス 以下のように呼び出してください o = TimingChartExcel() o.create() o.draw_1signal(2, "clk", "_~_~") o.save("hoge") """ def __init__(self): """コンストラクタ""" self.xlApp = None self.xlBook = None self.xlSheet = None def __del__(self): """デストラクタ""" # 強制的にExcelを閉じる self.xlBook.Saved = True self.xlApp.Quit() def RGB(self, r, g, b): """R, G, BをCOLORREF値に変換""" v = (r & 0xff) | ((g & 0xff) << 8) | ((b & 0xff) << 16) return v def create(self): """タイミングチャートを描画するファイルの新規作成 """ self.xlApp = ApplicationClass() self.xlApp.Visible = True # WorkBookを開く self.xlBook = self.xlApp.Workbooks.Add() # WorkSheetを開く self.xlSheet = self.xlBook.Sheets[1] print self.xlSheet.Name self.__描画の前準備() def __描画の前準備(self): self.xlSheet.Cells.Select() self.xlApp.Selection.ColumnWidth = 0.96 self.xlApp.Selection.RowHeight = 9.6 self.xlSheet.Columns["A:A"].Select() self.xlApp.Selection.ColumnWidth = 0.96 * 10 def __1CLKの描画(self, x, y, c, pre_c): o = self.xlSheet.Cells[y, x] # 前後のデータが違うならば、縦線が必要だ if c != pre_c: self.xlSheet.Shapes.AddLine(o.Left, o.Top, o.Left, o.Top + o.Height) # '~'はHigh / '_'はLow / '|'はタイミング線を引く if c == "~": self.xlSheet.Shapes.AddLine(o.Left, o.Top, o.Left + o.Width, o.Top) elif c == "_": self.xlSheet.Shapes.AddLine(o.Left, o.Top + o.Height, o.Left + o.Width, o.Top + o.Height) elif c == "|": top = self.xlSheet.Cells[1, x].Top down = self.xlSheet.Cells[50, x].Top left = o.Left lo = self.xlSheet.Shapes.AddLine(left, top, left, down).Line lo.ForeColor.RGB = self.RGB(255, 0, 0) lo.DashStyle = MsoLineDashStyle.msoLineSquareDot return x else: raise "no char" return x + 1 def draw_1signal(self, rowNo, name, data): """1つの信号の描画 - rowNo = 描画する行位置(1〜以上を指定) - name タイミングチャートの信号名 - data タイミングチャートのデータ文字列 """ print name, data self.xlSheet.Cells[rowNo, 1].Value = name x = 2 pre_c = None for c in data: x = self.__1CLKの描画(x, rowNo, c, pre_c) pre_c = c def save(self, fileName): """現在のシートをファイルに保存""" if fileName.find(":") == -1: fileName = nt.getcwd() + "\\" + fileName print "save:" + fileName self.xlSheet.SaveAs(fileName) def command_parse(): """コマンド解析""" try: for i in range(len(sys.argv)): print "argv[%d] = %s" % (i, sys.argv[i]) if len(sys.argv) < 3: raise "コマンド引数が足りないよ" in_file = sys.argv[1] out_file = sys.argv[2] return in_file, out_file except: print "USAGE> t_cha <入力ファイル(.TXT)> <出力ファイル(.XLS)>" raise def main(): in_file, out_file = command_parse() o = TimingChartExcel() o.create() f = file(in_file) row = 2 for l in f: print l name, data = l.split() data = data.strip(" \t\n") o.draw_1signal(row, name, data) row = row + 2 if raw_input("タイミングチャートを保存しますよ?(yes = 'Y')") == 'Y': o.save(out_file) if __name__=="__main__": main()
t_chaの実行例
コンソールでの実行例を以下に示します。
$ ipy t_cha.py test.txt hoge.xls argv[0] = t_cha.py argv[1] = test.txt argv[2] = hoge.xls Sheet1 Clk _~_~_~_~_~_~_~_~_~_~_~_~_~_~_~ Clk _~_~_~_~_~_~_~_~_~_~_~_~_~_~_~ Sync _~~|__________~~__________~~___ Sync _~~|__________~~__________~~___ タイミングチャートを保存しますよ?(yes = 'Y')Y save:F:\Wacky\Test\python\20070430.IronPythonでタイミングチャート\hoge.xls
上では、test.txtから、タイミングチャート図を作って、hoge.xlsに出力する。って事を行っています。
ちなみに、test.txtの中身は、どんなものかと言うと、↓こんな簡単なものです。
Clk _~_~_~_~_~_~_~_~_~_~_~_~_~_~_~ Sync _~~|__________~~__________~~___
ちょっとしたポイント
と言っても、大した事はありません。
- 公開しないメソッドは、helpコマンドで表示されないように、"__"をプレフィクスに付けてます
- IronPythonは、Unicodeで動くので、メソッド名に(一部)日本語使っちゃったりしてます
- タイミングチャートの書式を拡充したかったら、"__1CLKの描画"メソッドをいじればOKでしょう
- Excelのコンテナ配列にアクセスする時、IronPythonでは"()"でなく"[]"な点に注意
- "ipy t_cha.py"ってのが面倒なら、pycとかでバイナリ化してしまって下さい