Quantcast
Channel: 日曜大工、DIY、Excel VBAのページ
Viewing all articles
Browse latest Browse all 83

互換性のあるグラフの描き方

$
0
0
グラフを描くVBAは互換性が低く、悪いです。このため複雑なコーディングをすると、自分のPCでは何ら問題なくグラフを描いてくれるのに、別のPCでは動かないことがあります。けっこうあります。
症状はいろいろです。例えば、真っ白な枠だけしか描かれない場合や、グラフの折れ線を中途半端にしか描かない場合などがあります。
 
 
そこで参考となる情報をまとめました。
 
さて、互換性には種類があります。
・Excelのバージョンによる違い。
・Excelのバージョンは同じなのにPCが違うと動いたり動かなかったり。
・PCもExcelのバージョンも同じなのにデータが違うと動いたり動かなかったり。
 
★ 予備知識
まずはオブジェクトの階層構造を頭に入れておきます。これを知るとモヤモヤが消えてすっきりします。
 
Sheetオブジェクト
  |
  ChartObjectオブジェクト ・・・ グラフの枠=長方形の白い台紙。   .name を取得も設定もできる
    |
    Chartオブジェクト ・・・ グラフそのもの。     .name は取得だけできる
 
 
■ Excelバージョン間の互換性
このサイトOfficeTANAKAによると、Chartの名前はExcelのバージョンによって違うと書いてあります。 
     Excel2003 → ブック名 と通し番号
     Excel2010 → シート名 と通し番号
 
またこの本家マイクロソフトのサイトによるとVisual Studio 2010では次のように書かれています。
Chart コントロールを作成すると、Excel は Name プロパティを sheetname Chart n" と言う文字列に設定します (n はワークシート上の埋め込みグラフの数)。 たとえば、Chart を Sheet1 に追加し、それがワークシートの最初の埋め込みグラフの場合は、Name プロパティの値は Sheet1 グラフ 1になります。
Name プロパティは読み取り専用ですが、親 Microsoft.Office.Interop.Excel.ChartObject の Name プロパティを使用して名前の一部を変更することができます。 指定した新しい名前で、Name プロパティによって返される文字列の "Chart n" 部分が置き換わります。 たとえば、次のコードは、Chart コントロールのName プロパティ値を Sheet1 グラフ 1 から Sheet1 SalesChart に変更します。
本家の解説は難しい。私は疲れているときには読む気力が湧きません。
 
さて、どっちなんだろう?  chart.name を構成するのは、シート名 なのか ブック名なのか?
そこで実証しました。Excelのバージョンは、Excel2003と 2010 です。
この実験を始める前に、シート名は、「graph」に設定しておきました。
 
コード1
    .ChartObjects.Add(gX, gY, gSizeX, gSizeY).Name = strID
        With .ChartObjects( strID).Chart
            tempstr = .Name
            '''''tempstr = Replace(tempstr, "graph ", "")
           .ChartType = xlXYScatterLines
           .SetSourceData Source:=rngByouga, PlotBy:=xlColumns
           .Location Where:=xlLocationAsObject, Name:="graph"
            .HasTitle = True
             ・・・
 
この実験の結果、tempstrは、Excel2003 と 2010 いずれの場合もシート名と strIDの結合された文字列でした。
 
 
 
コード2
    .ChartObjects.Add(gX, gY, gSizeX, gSizeY).Select
        Selection.Activate
        With ActiveChart
           tempstr = .Name
           .ChartType = xlXYScatterLines
           .SetSourceData Source:=rngByouga, PlotBy:=xlColumns
           .Location Where:=xlLocationAsObject, Name:="graph"
            .HasTitle = True
             ・・・
 
この実験の結果、tempstrは、Excel2003 と 2010 いずれの場合もシート名と "グラフ 1"の結合された文字列でした。
 
 
というわけで、
Chart.nameは、Excel2003 と 2010 いずれの場合もシート名と "グラフ 1"または設定した文字列の結合です。
 
しかし念のため、コーディングの後に、労力を惜しまず両方のバージョンで実証試験するのが安心です。
 
 
■ パソコン間の互換性
パソコン間で互換性が無い原因はメモリー不足によるものと推定しています。
ですから、グラフを描くもとになるデータセットが小さい場合や、グラフの個数が少ない場合はパソコン間の互換性はあります。
バグが発生しやすい状況は、
 ・データが大きい場合
 ・グラフを描くコードを実行するまでに、大きいコードを処理していて、メモリーを消費している場合
 
いろいろ試行錯誤した結果、たいていのパソコンで動くコードが見つかりました。このサイトに詳しく書かれているコードです。
コードの説明: ChartObjectsをAddで作って、名前を付けておきます。そして、各種プロパティーを設定するために名前で呼び出します。このやり方が一番確実に動くコードでした。消費するメモリーが少ないのだと思います。 
Sub sample1()

Dim myRange As Range
Set myRange = Range("A1:D2")

Worksheets("Sheet1").ChartObjects.Add(50, 50, 300, 200).Name = "グラフの名前"

With ActiveSheet.ChartObjects("グラフの名前").Chart
.ChartType = xlPie
.SetSourceData Source:=myRange, PlotBy:=xlRows
.ApplyDataLabels Type:=xlDataLabelsShowLabelAndPercent, LegendKey:=False, HasLeaderLines:=True
End With

End Sub
 
同じサイトに紹介されている次のコードは搭載しているメモリーが少ないPCでは動かないことがありました。
Sub sample()

Dim myRange As Range
Set myRange = Range("A1:D2")

With Worksheets("Sheet1").ChartObjects.Add(50, 50, 300, 200).Chart
.ChartType = xlPie
.SetSourceData Source:=myRange, PlotBy:=xlRows
.ApplyDataLabels Type:=xlDataLabelsShowLabelAndPercent, LegendKey:=False, HasLeaderLines:=True
End With

End Sub
 
パソコン間の依存性がさらに発生しやすいコードはこれ↓です。メモリーが1GBのパソコンでは動きましたが、512MBのパソコンでは動かない場合がありました。
     ActiveSheet.ChartObjects.Add(25, 125, 338, 220).Select
この例に限らず、VBAすべてに言えることですが、 .select はメモリー消費が多いようです。
 
一般的に言われていることですが、activate や select 文はできるだけ使わないのがエレガントなプログラムです。私の経験ではこれらを使うと勘違いすることによるバグが多発します。つまり、コードが長くなるとactivateされたシートを見失ってしまい勘違いしてしまうのです。selectも同じです。記録マクロで生成されたコードはactivateやselectがたくさん入ってますが、これを修正しておいた方がいいです。
 
パソコン間の依存性を減らす別の方法は、Excel2003からExcel2010に変えて、しかもメモリーをたっぷり積むことです。 たとえば1GB以上。仕事で使うなら、プログラミングに余分な神経と労働時間をかけるよりも経済的だと思います。  
Excel2003よりもExcel2010はメモリーの使い方が工夫されていますので、同じPCでもバグが発生しにくいです。つまりグラフを描かなかったり、中途半端にしか描かないというバグが発生しにくいです。 
 
 
● 参考web
 
EXCEL VBA:埋め込みグラフオブジェクトの命名方法について
 
VBA便利帳
 
Office TANAKA
グラフの名前を設定/取得する
 
グラフを削除する バージョン依存性がある
 
 
 
VBAからの自動グラフ作成でのエラー
  どうしても原因が不明の時はこれかもしれません。こんな技は特殊すぎて思いつかないですね。 
  どんなやり方かというと、Excelファイルを開けるとき「マクロを無効」にして開ける。そしてそのまま上書き保存。
  この簡単な操作によって、マクロを動作させるときに使用されるワーキング領域にたまってしまっていたゴミ
  を掃除できる・・・と説明されてます。
 
ワークシートにグラフを挿入する
 

Viewing all articles
Browse latest Browse all 83

Trending Articles