Pythonを使って、MicrosoftのExcelのグラフを作る方法を紹介します。 ネットで調べたところ、グラフのオブジェクトの ChartWizard というメソッドを使えばわりと簡単にできるようです。
まず、最小限の例です。 次のスクリプトを実行すると、グラフのみのシートが追加されて下の画像のグラフができます。
import win32com.client
import os.path
MyData = ( ('Name','Value'), ('A',5), ('B',2), ('C',3), ('D',7), )
MyRange = "A1:B5"
#Run Excel
xlApp = win32com.client.Dispatch("Excel.Application")
xlApp.Visible = 1
xlApp.Workbooks.Add()
xlSheet = xlApp.Workbooks(1).Sheets(1)
#Input Data
DataRange = xlSheet.Range(MyRange)
DataRange.Value = MyData
#Draw Graph
xlChart = xlApp.Charts.Add()
xlChart.ChartWizard(Source = DataRange, Gallery = 3, Format = None,
PlotBy = 2, CategoryLabels = 1, SeriesLabels = 1, HasLegend = 1,
Title = 'Sample01', CategoryTitle = 'Name', ValueTitle = 'Value',)
#Save File
FileName = 'PyExcGrp01.xls'
FilePath = os.path.join(os.path.dirname(__file__), FileName)
xlApp.Workbooks(1).SaveAs(FilePath)
xlApp.Quit()
スクリプトの中で、Excelの起動(#Run Excel)、データ入力(#Input Data)、ファイル保存(#Save File)、は、 「1: PythonでExcelの初歩的な操作」で説明してます。 ここで解説するのは、#Draw Graph の部分です。
「xlChart = xlApp.Charts.Add()」
でグラフオブジェクト xlChart が作られます。
xlChart の ChartWizardメソッドの設定でグラフが描かれます。
この説明を次にします。
ChartWizardの引数は、次のようになります。
| 引数名 | 意味 |
|---|---|
| Source | グラフのデータの範囲 |
| Gallery | グラフのタイプ |
| Format | グラフのサブタイプ |
| PlotBy | データが横方向か縦方向かの指定 |
| CategoryLabels | カテゴリーが入力されている行または列番号 |
| SeriesLabels | シリーズが入力されている行または列番号 |
| HasLegend | 1なら凡例を表示する。0なら表示しない |
| Title | グラフのタイトル |
| CategoryTitle | カテゴリーのタイトル |
| ValueTitle | 値のタイトル |
| ExtraTitle | 他のタイトル |
以下、それぞれの引数の説明をします。
グラフに表示したいデータの範囲オブジェクトを指定します。
引数 Gallery には、棒グラフ、折れ線グラフ、円グラフなど、グラフのタイプを数値で指定します。具体的には次のようになります。
| グラフタイプ | 数値 | Visual Basicでの名前 | 注意 |
|---|---|---|---|
| 面グラフ | 1 | xlArea | |
| 集合横棒グラフ | 2 | xlBarClustered | |
| 集合縦棒グラフ | 3 | xlColumnClustered | |
| 折れ線グラフ | 4 | xlLine | |
| 円グラフ | 5 | xlPie | 一番目の系列だけ表示する |
| レーダーグラフ | 6 | xlRadar | |
| 散布図 | 7 | xlXYScatter | |
| 縦棒と折れ線 | 8 | --- | 系列がひとつならば縦棒のみ |
| 3D面グラフ | 9 | xl3DArea | |
| 3D横棒グラフ | 10 | xl3DBarClustered | |
| 3D縦棒グラフ | 11 | xl3DColumn | |
| 3D折れ線グラフ | 12 | xl3DLine | |
| 3D円グラフ | 13 | xl3DPie | |
| 3D等高線 | 14 | xlSurface | 系列がひとつならばエラー |
| ドーナツグラフ | 15 | xlDoughnut |
引数 Format は、Visual Basic だと数値を設定することで他のグラフタイプにできますが、
Python だと適当に入れても変化ありません。
かといって省略するとエラーでグラフが描かれないので、
「Format = None」としておくのが無難です。
まだ研究の余地があります。
これらの引数は、元データの表の行と列の意味に関係があります。 上のスクリプト例で作られる表は、
| Name | Value |
| A | 5 |
| B | 2 |
| C | 3 |
| D | 7 |
という感じになってます。
ここでは、(最初の行以外の)行が1つのレコード(物、人、日時、場所など)を表し、
列はフィ−ルド(名前、個数、値段、年齢、身長、点数、気温など)を表しています。
ひとつの列がひとつの「系列」になります。
こういう方向で作られた表の場合は、PlotBy = 2 とします。
ここの説明では、この方向で作られた表のみを扱います。
こうじゃなく、行列の方向(意味)が入れ替わってる場合は、PlotBy = 1 になります。
1, 2 の意味は Visual Basic の定数で 1が xlRows、2が xlColumns のことです。
もっと正確な言い方はあるでしょうけど、普段Excelは使ってないのでなんと言っていいのかわかりません。 例えば「行が並んでる方向」といった簡単そうな言葉でも、人によって解釈は違うかも知れません。 ひとつの行は横向きですけど、複数の行は縦方向に増えて並んでます。 そうすると「行が並んでる方向」は、横なのか縦なのか、どっちの解釈もありえます。
CategoryLabels は、「個々のレコードの名前」がある列番号(行列が入れ替わってれば行番号)を指定します。
上の表で「A, B, C, D」がある列番号で、実際の棒グラフでは棒の下に表示させる名前になります。
SeriesLabels は、「系列名(フィールド名、項目名)」がある行番号(行列が入れ替わってれば列番号)を指定します。
上の表で「Name, Value」がある行番号で、実際の棒グラフでは凡例の部分に表示される名前を含んだ行を指定します。
この行が無い場合は値は SeriesLabels = 0 とします。
1(または True)なら凡例を表示します。0(または False)なら表示しません。
Title はグラフのタイトルで、上の例だとグラフの上に表示されます。
CategoryTitle はカテゴリー(項目)のタイトルで、上の例だとグラフの横軸の下に表示されます。
ValueTitle は値のタイトルで、上の例だとグラフの縦軸の下に表示されます。
ExtraTitle は・・・、上のスクリプトに追加で設定しても表示されない(見えない)のでよくわかりません。
最初のスクリプトの ChartWizard の Gallery 部分のみを書き換えた例をいくつか作ってみます。
凡例がABCDになってます。
一見、XY直交座標軸に見えますが、ABCDの4個の値なので四方に伸びてます。
今までの例は、('A',5), ('B',2) ・・・と、A, B ・・・それぞれに対して値が一つだけでした。
言いかえると、5,2,3,7 と変化する系列が一つだけでした。
これを、系列が複数ある例を作ります。最初のスクリプトの、MyData, MyRange を
MyData = (('A',5,3), ('B',2,6), ('C',3,5), ('D',7,3), ('E',2,4), )
MyRange = "A1:C5"
と置き換えて、グラフの Galleryをいくつか作ってみます。
系列1が棒グラフで目盛は左側、系列2が折れ線グラフで目盛は右側になります。
ぱっと見ても何が何だかわかりません。 もっとデータが多くて目の細かい連続的なグラフにならないと意味が無いようです。
これまでは、グラフだけのシートが作られてそこに表示されてましたが、
通常のシートに描く方法を説明します。
最初のスクリプトの、#Draw Graph の部分だけを書き換えて、他は同じです。
ChartWizardメソッドの引数名は省略してます。
#Draw Graph xlChart = xlApp.Charts.Add() xlChart.ChartWizard(DataRange, 2, None, 2, 1, 1, 1,'Sample01', 'Name', 'Value','Extra') xlChart.Location(2, "Sheet1") #Sheet1に表示する xlChartObj = xlSheet.ChartObjects(1) CellC2 = xlSheet.Cells(2,3) #セルC2を基準に使う xlChartObj.Left, xlChartObj.Top = CellC2.Left, CellC2.Top #位置の設定 xlChartObj.Width, xlChartObj.Height= CellC2.Left * 2, CellC2.Height * 10 #縦横サイズの設定
シートにグラフを描くのは、xlChart.Location(2, "Sheet1") の部分です。
ここで引数の「2」は、Visual Basic での「xlLocationAsObject」の意味になります。
「"Sheet1"」がグラフを表示させたいシートになります。
が、しかし!!、これらの設定に関係なく一番上のシートに描かれてしまうようです。
一番上以外のシートに描きたい場合は、
という方法になります。具体的には、
xlSheet2.Move(xlSheet1) xlChart.Location(2, xlSheet2.Name) xlSheet2.Move(None, xlSheet1)
となります。
ここでシートのメソッド Move の引数は、1個だけだとその引数のシートの前に移動します。
引数のシートの後ろに移動させたい場合は (None, xlSheet1)と指定します。
Visual Basic のリファレンスを見ると、Move(After = xlSheet1) でできそうなんですが、これが上手くいきません・・・。
話を戻して、グラフの位置は xlChartObj.Left, xlChartObj.Top、
サイズは xlChartObj.Width, xlChartObj.Height に数値を入れて設定します。
上の例では、シートのセルの位置と大きさに合わせてます。
これでシートに自由に配置できますが、サイズを縮小すると中のグラフ本体や文字も縮小されてしまいます。 このグラフ本体などの設定について、次に解説します。
ここでは、グラフ本体やラベルなどの設定を解説します。
勝手に「グラフ本体」と言ってますが、具体的には Excel で PlotArea というオブジェクトのことです。 まず、グラフ本体の位置とサイズを変更します。 具体的には次のスクリプトになります (まだ見た目が悪いのはおいておきます・・)
#Draw Graph
xlChart = xlApp.Charts.Add()
xlChart.ChartWizard(DataRange, 5, None, 2, 1, 1, 1,'Sample01', 'Name', 'Value','Extra')
xlChart.Location(3, "Sheet1")
xlChartObj = xlSheet.ChartObjects(1)
xlChartObjEmb = xlChartObj.Chart
xlPlotArea = xlChartObjEmb.PlotArea
xlPlotArea.Left, xlPlotArea.Top = 30,10
xlPlotArea.Width, xlPlotArea.Height = 130,130
ここでのポイントは、いったん xlChartObjEmb = xlChartObj.Chart と、
ワンクッション置く必要があるということです
(最初、xlChartObj.PlotArea とやって出来なくてハマりました)。
位置とサイズは、Left, Top, Width, Height メソッドで指定します。
ただし、ここで大きな値を指定しても、グラフ部分の枠 (xlChartObj.Width, xlChartObj.Height) に収まる大きさに制限されます(文字はちょっとはみ出してますけど)。
ちなみに、円グラフでは大きさ・位置を指定しないと、小さくてちょっと見づらいです。
上の円グラフでは、グラフ本体を拡大すると文字も拡大されてます。この文字の大きさを調整してみます。
この「文字」の部分は、円グラフとドーナツグラフでは DataLabels オブジェクトになります。
上のスクリプトの、xlChartObjEmb・・・ の部分からです。
xlChartObjEmb = xlChartObj.Chart xlPlotArea = xlChartObjEmb.PlotArea xlPlotArea.Left, xlPlotArea.Top = 30,30 xlPlotArea.Width, xlPlotArea.Height = 130,130 xlChartObjEmb.SeriesCollection(1).DataLabels().Font.Size = 9
最後の行のようにすることで、文字部分のフォントサイズの変更ができます。
SeriesCollection(1) の1は、系列が1個だけなのでこうなります。
ドーナツグラフのように系列が複数ある場合は、系列ごとに1,2・・などを指定します。
とりあえずここまでです。 他にも、色の変更や3Dグラフの視点の角度とかの設定やらいろいろありますが、 凝り出すときりがありません。 ある程度見やすいグラフを作るための知識としては、これくらいでいいんじゃないでしょうか。