Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


7540 / 13645 ツリー ←次へ | 前へ→

【38273】ワークシート上のグラフの座標を知りたい わいわい 06/5/30(火) 20:37 質問[未読]
【38299】Re:ワークシート上のグラフの座標を知りたい Kein 06/5/31(水) 3:12 回答[未読]
【38355】Re:ワークシート上のグラフの座標を知り... わいわい 06/5/31(水) 19:10 質問[未読]
【38360】Re:ワークシート上のグラフの座標を知り... Kein 06/5/31(水) 22:01 回答[未読]
【38371】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/1(木) 8:25 発言[未読]
【38379】Re:ワークシート上のグラフの座標を知り... わいわい 06/6/1(木) 12:41 質問[未読]
【38381】Re:ワークシート上のグラフの座標を知り... Kein 06/6/1(木) 13:04 発言[未読]
【38395】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/1(木) 20:38 発言[未読]
【38396】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/1(木) 21:12 発言[未読]
【38412】Re:ワークシート上のグラフの座標を知り... わいわい 06/6/2(金) 9:33 お礼[未読]
【38413】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/2(金) 10:01 発言[未読]
【38420】Re:ワークシート上のグラフの座標を知り... わいわい 06/6/2(金) 11:12 発言[未読]
【38435】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/2(金) 19:11 発言[未読]
【38437】Re:ワークシート上のグラフの座標を知り... わいわい 06/6/2(金) 20:54 お礼[未読]
【38440】Re:ワークシート上のグラフの座標を知り... ichinose 06/6/2(金) 22:14 発言[未読]

【38273】ワークシート上のグラフの座標を知りたい
質問  わいわい  - 06/5/30(火) 20:37 -

引用なし
パスワード
   いつもお世話になっております。
また分からないことが出てきてしまったのでお教え下さい。

ワークシート『線図01』にグラフが貼り付けてあります。
このシートを表示しているときに
  UserForm1.Show 0
で開きます。そして『線図01』をアクティブにしてグラフ内をマウスでクッリクして、その点の座標を上記Form内のTextBox_XとTextBox_Yに代入したいと考えています。

このときグラフをマウスでクリック(Wクリック又は右クリックでも可)したとき、その点の座標を取得するにはどのようにしたら良いのでしょうか。
出来ればグラフはアクティブにしたくないので、グラフを無視してワークシートの座標(マウス先端の座標が取得できるのならば)の方が良いのかもしれません。
 ActiveChart.PlotArea.InsideLeft等で取得した座標と換算式で、グラフ内座標を導けるのではと考えています。

ちなみに、グラフ貼り付け範囲は、B3:AC37となっています。

宜しくお願いいたします。

【38299】Re:ワークシート上のグラフの座標を知り...
回答  Kein  - 06/5/31(水) 3:12 -

引用なし
パスワード
   グラフ上でクリックするなら、そのグラフをアクティブにしないと何もできません。
まずVBEのメニュー「挿入」でクラスモジュールを挿入し、その先頭から

Public WithEvents myChartClass As Chart

Private Sub myChartClass_MouseUp(ByVal Button As Long, _
ByVal Shift As Long, ByVal x As Long, ByVal y As Long)
  Dim Tp As Single, Lp As Single
 
  With Range("B3")
   Tp = .Top: Lp = .Left
  End With
  With UserForm1
   .TextBox_X.Value = x + Lp
   .TextBox_Y.Value = y + Tp
  End With
End Sub

そしてフォームモジュールの先頭から

Dim myClassModule As New Class1

Private Sub UserForm_Activate()
  ActiveSheet.ChartObjects(1).Activate
End Sub

Private Sub UserForm_Initialize()
  Set myClassModule.myChartClass = _
  ActiveSheet.ChartObjects(1).Chart
End Sub

Private Sub UserForm_Terminate()
  Set myClassModule.myChartClass = Nothing
End Sub

を入れて、『線図01』をアクティブにしてから UserForm1.Show 0 のコードを
実行して下さい。
なお最初のクリックは2回して下さい。以降は1回で結構です。

【38355】Re:ワークシート上のグラフの座標を知り...
質問  わいわい  - 06/5/31(水) 19:10 -

引用なし
パスワード
   Kein 様 いつも回答して頂きありがとうございます。

>グラフ上でクリックするなら、そのグラフをアクティブにしないと何もできません。
やはりそうですか、お教え頂いたリストにて動作確認いたしました。座標の取得はできたのですが、私の意図したものと違っていました。説明が悪かったのですが、私が考えていたのは、グラフの軸を反映した(x,y)座標を取得できないかと言うものです。当初の質問に書いた ActiveChart.PlotArea.InsideLeft等で取得した座標と換算式で、グラフ内座標を導くと言う方法が出来るかと色々やってみたのですが、表示倍率の変更、スクロールなどにより同じポイントでも座標が変化することから難しいのかなと思いました。グラフの軸を反映した(x,y)座標は取得可能なのでしょうか?
あと図々しいとは思いますがもう一つ教えてください。
上記方法が出来ないときの次策としてグラフ上のSeriesCollection(***)をクリックしてそのx,y値を取得できないかと言うことです。
myChartClass_SeriesChangeかな?と思いいじっていたのですが上手くいきません。ご回答宜しくお願いいたします。

【38360】Re:ワークシート上のグラフの座標を知り...
回答  Kein  - 06/5/31(水) 22:01 -

引用なし
パスワード
   >ActiveChart.PlotArea.InsideLeft等で取得した座標と換算式で、グラフ内座標を導く
つまり PlotAreaの左上端を (0, 0) として、PlotArea内の座標を取得したい
ということでしょーか ? それなら

With Range("B3")
  Tp = .Top: Lp = .Left
End With

のところを

With ActiveChart.PlotArea
  Lp = .InsideLeft: Tp = .InsideTop
End With

というように、変更するだけかと思いますが。

【38371】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/1(木) 8:25 -

引用なし
パスワード
   ▼わいわい さん:
おはようございます。

>Kein 様 いつも回答して頂きありがとうございます。
>
>>グラフ上でクリックするなら、そのグラフをアクティブにしないと何もできません。
>やはりそうですか、お教え頂いたリストにて動作確認いたしました。座標の取得はできたのですが、私の意図したものと違っていました。説明が悪かったのですが、私が考えていたのは、グラフの軸を反映した(x,y)座標を取得できないかと言うものです。当初の質問に書いた ActiveChart.PlotArea.InsideLeft等で取得した座標と換算式で、グラフ内座標を導くと言う方法が出来るかと色々やってみたのですが、表示倍率の変更、スクロールなどにより同じポイントでも座標が変化することから難しいのかなと思いました。グラフの軸を反映した(x,y)座標は取得可能なのでしょうか?
例えば、あるセル範囲に以下のような表があり、
x     y
52    46
52    72
71    68
94    98
79    16
43    82
58    37

これを基に散布図を作成した場合、
上記の表だと、散布図として、7個のプロットが表示されますよね?
それぞれのプロットをクリックしたとき、上記の表のX,Yの値が取得したい
ということですか?
また、直接プロットをクリックするのではなく、その近隣をクリックしたときは、
X,Y軸のスケールに基づいたX,Yを取得したいということですか?
例えば、
上記の(52,46)に相当するプロットのちょっと上(Y軸に対して)を
クリックしたら、52,48なんて取得できるような仕様ですか
(48は単に例としてあげている数字です)?


簡単なグラフなら、Keinさんが提示されたグラフのMouseUpイベントで
出来るかもしれません。
Axesオブジェクトのスケールの最大値と最小値を調べることで
x軸y軸のスケールを求めることはできるでしょう?
自分で確認していませんが、スケールがわかれば、比例計算で
出来そうですが、試してみてください。
(でも、結構計算が面倒かもね!!)


>上記方法が出来ないときの次策としてグラフ上のSeriesCollection(***)をクリックしてそのx,y値を取得できないかと言うことです。
>myChartClass_SeriesChangeかな?と思いいじっていたのですが上手くいきません。ご回答宜しくお願いいたします。
これで、プロットされた要素を選択してX,Yを取得したいなら、

グラフのSelectイベントで出来そうです。さぐってみて下さい。

但し、この場合も初回のSeriesの選択では、プロットが特定できないので
工夫が必要ですが、処理自体はこっちのほうが簡単そうです。
私が考えているのは、
選択したSeriesオブジェクトのFormulaプロパティを
解析する方法です。

「=SERIES(Sheet1!$B$1,Sheet1!$A$2:$A$21,Sheet1!$B$2:$B$21,1)」
こんなデータから、X,Y値を取得するということです。


それから、こういう難しい内容では特にですが、
例を最低3例ぐらい引用して説明してください。

x  1   y  2
x  2   y  4
x  3   y  6

こんな高校生の算数の等差数列レベルだって、3つは例がないと
規則性が決まらないですよね?
(x 3  y 9だったら、違う数列だもんね)

ましてやここでの質問される内容はどれも上記の数列よりは難しいし、複雑です。
具体的な例を提示しないと中々真意はつたわりませんよ!!

【38379】Re:ワークシート上のグラフの座標を知り...
質問  わいわい  - 06/6/1(木) 12:41 -

引用なし
パスワード
   ichinose 様、Kein 様 回答ありがとうございます。

>それから、こういう難しい内容では特にですが、
>例を最低3例ぐらい引用して説明してください。
についてですが、今回私の扱っているのが非直交5軸の線図から指定ポイントの値をデジタル表示すると言うもので、例を示すのが難しく、余り簡単な例に直すと、回答が『そんなことしなくても出来ますよ』と言うような流れになるのではと危惧して、あえて書かなかったのですが、質問の意味が回答いただける方に伝わらないのでは本末転倒ですね。今後質問には工夫していきます。

>Axesオブジェクトのスケールの最大値と最小値を調べることで
>x軸y軸のスケールを求めることはできるでしょう?
x軸、y軸のスケールは、グラフ自体をマクロで描かせていますので、既知の値です。

例)X軸0→100 Y軸0→20 のグラフ上でクリックした点のPoint(x,y)を求めたい。 まだ出来ないところがあります。宜しくお願いいたします。
(1)
Private Sub myChartClass_MouseUp(ByVal Button As Long, _
ByVal Shift As Long, ByVal x As Long, ByVal y As Long)
  Dim Tp As Single, Lp As Single
'図面のサイズを取得
  With ActiveChart.PlotArea
    Lp = .InsideLeft: Tp = .InsideTop
    Wp = .InsideWidth: Hp = .InsideHeight
    dx = 100 / Wp
    dy = 20 / Hp
  End With
  With UserForm1
    .TextBox_X.Value = 0 +(x * 3/4 * 100/ ActiveWindow.Zoom - Lp)*dx
    .TextBox_Y.Value = 0 +(Tp + Hp - y * 3 / 4 * 100 / _
       ActiveWindow.Zoom) * dy
  End With
End Sub
これで大体の数値は得られるのですが、PlotArea.InsideLeft等とグラフ軸の微妙な差が調整し切れていません。

(2)そこで下記のように出来ればと思いますがどのようにすればよいのでしょう?
Private Sub myChartClass_MouseUp(ByVal Button As Long, _
ByVal Shift As Long, ByVal x As Long, ByVal y As Long)
  Dim Tp As Single, Lp As Single
'図面の表示座標を取得
'ActiveChart.PlotArea.InsideLeft等では駄目そう
 『Point(0,20)』→x_min,y_min  ※◆ここが分かりません。
 『Point(100,0)』→x_MAX,y_MAX ※◆ここが分かりません。
  dx = 100 / (x_MAX - x_min) 
  dy = 20 / (y_max - y_min)
  With UserForm1
    .TextBox_X.Value = 0 + (x - x_min) * dx
    .TextBox_Y.Value = 0 + (y_max - y) * dy
    '実際には、ここで得た値で他の4項目について算出します。
  End With
End Sub

>グラフのSelectイベントで出来そうです。さぐってみて下さい。
これからTRYして見ます。

【38381】Re:ワークシート上のグラフの座標を知り...
発言  Kein  - 06/6/1(木) 13:04 -

引用なし
パスワード
   んー・・そんな難しいことをするのが目的だったなら、
私には到底わかりません。ただ一つ言えることは
Select イベントでは、引数に座標を捕捉するものが無いので
無理なのでは ? ということだけです。Selectイベントの
サンプルは↓のようなものになります。

Sub myChartClass_Select(ByVal ElementID As Long, _
ByVal Arg1 As Long, ByVal Arg2 As Long)
  If ElementID = xlSeries Then
   If Arg2 <> -1 Then
     MsgBox "系列番号 = " & Arg1 & vbLf & _
     "ポイント番号 = " & Arg2
   End If
  End If
End Sub

Selectイベントの引数は、初めに選択したオブジェクトの種類が ElementID に
渡され、それによって Arg1, Arg2 の値が決ります。上の例では任意の系列を選択
したときに、その系列番号とその中の Point のIndexがメッセージされます。
Arg2 = -1 の場合は、全てのポイントが選択されている(つまり系列全体が選択
されている)という状態を表します。
以上がグラフオブジェクトの Selectイベント の概要ですので、座標は取得
出来ません。

【38395】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/1(木) 20:38 -

引用なし
パスワード
   ▼わいわい さん:
こんばんは。

>ichinose 様、Kein 様 回答ありがとうございます。
>
>>それから、こういう難しい内容では特にですが、
>>例を最低3例ぐらい引用して説明してください。
>についてですが、今回私の扱っているのが非直交5軸の線図から指定ポイントの値をデジタル表示すると言うもので、例を示すのが難しく、余り簡単な例に直すと、回答が『そんなことしなくても出来ますよ』と言うような流れになるのではと危惧して、あえて書かなかったのですが、質問の意味が回答いただける方に伝わらないのでは本末転倒ですね。今後質問には工夫していきます。
この「非直交5軸の線図」というのは、私にはわかりませんが・・・。
簡単なグラフでためしてみると・・・・、


>
>>Axesオブジェクトのスケールの最大値と最小値を調べることで
>>x軸y軸のスケールを求めることはできるでしょう?
>x軸、y軸のスケールは、グラフ自体をマクロで描かせていますので、既知の値です。
>
>例)X軸0→100 Y軸0→20 のグラフ上でクリックした点のPoint(x,y)を求めたい。 まだ出来ないところがあります。宜しくお願いいたします。
>(1)
>Private Sub myChartClass_MouseUp(ByVal Button As Long, _
>ByVal Shift As Long, ByVal x As Long, ByVal y As Long)
>  Dim Tp As Single, Lp As Single
  Dim hx As single
  Dim hy As single
>'図面のサイズを取得
>  With ActiveChart.PlotArea
>    Lp = .InsideLeft: Tp = .InsideTop
>    Wp = .InsideWidth: Hp = .InsideHeight
>    dx = 100 / Wp
>    dy = 20 / Hp
>  End With
   hx = ActiveChart.ChartArea.Left
   hy = ActiveChart.ChartArea.Top
  

   With UserForm1
    .TextBox_X.Value = _
      (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp) * dx
    .TextBox_Y.Value = _
       (Tp + Hp - 0.75 * y * 100 / ActiveWindow.Zoom + hy) * dy
>  End With
>End Sub
>これで大体の数値は得られるのですが、PlotArea.InsideLeft等とグラフ軸の微妙な差が調整し切れていません。


これではどうでしょうか?
もっともこれでも微妙な誤差は残りますね・・・。


完全にぴったりは無理なのかなあ・・・。

【38396】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/1(木) 21:12 -

引用なし
パスワード
   今度は、Selectイベントを使用した例です。

散布図を例に取り上げました。

まず、新規ブックのSheet1のシートモジュールに
'==================================================================
Dim WithEvents cht As Chart
'===================================================================
Sub mk_sammple() 'サンプルデータとグラフの作成
  Dim mkcht As Chart
  With Me
    .Range("a1:b1").Value = Array("X", "Y")
    With .Range("a2:b31")
     .Formula = "=round(100*rand(),2)"
     .Value = .Value
     End With
    End With
  Set mkcht = ThisWorkbook.Charts.add
  With mkcht
    .ChartType = xlXYScatter
    .SetSourceData Source:=Me.Range("A1:B31"), PlotBy:=xlColumns
    .Location Where:=xlLocationAsObject, Name:=Me.Name
   End With
End Sub
'====================================================================
Sub set_obj() 'オブジェクトの設定
  Set cht = Me.ChartObjects(1).Chart
End Sub
Sub reset_obj() 'オブジェクトの設定解除
  Set cht = Nothing
End Sub
'====================================================================
Function edit_addr(add, podr As Long) As String
'Seriesのformulaプロパティの解析
  Dim idx As Long, jdx As Long
  Dim ans()
  Dim wk As Variant
  wk = Split(Replace$(Replace$(add, "=SERIES(", ""), "," & podr & ")", ""), ",")
  jdx = 1
  For idx = LBound(wk) To UBound(wk)
   If TypeName(Application.Evaluate(wk(idx))) = "Range" Then
    ReDim Preserve ans(1 To jdx)
    ans(jdx) = wk(idx)
    jdx = jdx + 1
    End If
   Next
  If jdx > 1 Then
   edit_addr = Join(ans(), ",")
  Else
   edit_addr = ""
   End If
End Function
'======================================================================
Private Sub cht_Select(ByVal ElementID As Long, ByVal Arg1 As Long, ByVal Arg2 As Long)
'selectイベント
  Dim srs As Series
  Dim srsstr As Variant
  Dim addr As Variant
  If ElementID = xlSeries Then
    Set srs = cht.SeriesCollection(Arg1)
    srsstr = Split(edit_addr(srs.Formula, srs.PlotOrder), ",")
    xaddr = srsstr(UBound(srsstr) - 1)
    yaddr = srsstr(UBound(srsstr))
    If Arg2 = -1 Then
     Arg2 = 1
     srs.Points(Arg2).Select
     End If
    If Arg2 > 0 Then
     MsgBox "(x,y)=" & "(" & Application.Range(xaddr).Cells(Arg2).Value & "," & _
              Application.Range(yaddr).Cells(Arg2).Value & ")"
     End If
    End If
End Sub


1.まず、mk_sammpleを実行し、当該シートにサンプルデータとグラフを
  作成してください。

2.次にset_objを実行し、イベントの発生を可能にしてください。


3.ここから本番です。適当なプロットを選択してください。
 全てのポイントが選択された場合、自動的に最初のポイントを選択するように
 しています。このとき、最初のポイントのX,Yが表示されます。


4.続いて別のポイントを選択してください。選択されたポイントのX,Yが
  表示されます。

こちらは、正確な値が表示されます。


これを わいわいさんのおっしゃる「非直交5軸の線図」に
応用できますか?

【38412】Re:ワークシート上のグラフの座標を知り...
お礼  わいわい  - 06/6/2(金) 9:33 -

引用なし
パスワード
   ichinose 様、Kein 様 長々とお付き合いい頂きありがとうございます。

>   hx = ActiveChart.ChartArea.Left
>   hy = ActiveChart.ChartArea.Top
>   With UserForm1
>    .TextBox_X.Value = _
>      (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp) * dx
>    .TextBox_Y.Value = _
>       (Tp + Hp - 0.75 * y * 100 / ActiveWindow.Zoom + hy) * dy
>これではどうでしょうか?
>もっともこれでも微妙な誤差は残りますね・・・。

チェックしてみたところ、InsideWidthとInsideHeightは図面上最小軸と最大軸の距離を正確(4/3*ActiveWindow.Zoom/100補正はしていますが)に表しており、
InsideLeftとInsideTopの値は、図面左上(X最小軸,Y最大軸)から(-4,-4)であることから

  With ActiveChart.PlotArea
    Lp = .InsideLeft + 4: Tp = .InsideTop + 4
    Wp = .InsideWidth: Hp = .InsideHeight
    dx = 100 / Wp
    dy = 100 / Hp
  End With
とすることで、図面上の座標をほぼ正確に獲得できました。精度はこの程度で十分と思います。

>今度は、Selectイベントを使用した例です。
動作確認致しました。グラフ発生モジュールまで作成していただき、本当にありがとうございます。内容については、まだ読みきれていませんが、色々応用できそうなので、有難く使わせていただきます。

>これを わいわいさんのおっしゃる「非直交5軸の線図」に
>応用できますか?

大層な書き方しましたが、結局は実験式によるグラフを集めて、それぞれの関連を表したグラフです。画面表示が可能な2次元グラフですから(x,y)が分かれば後は換算式でバリバリ(コンピューターが)計算できます。

この度は、お二方ともにありがとうございました。

【38413】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/2(金) 10:01 -

引用なし
パスワード
   ▼わいわい さん:
おはようございます。

>
>>   hx = ActiveChart.ChartArea.Left
>>   hy = ActiveChart.ChartArea.Top
>>   With UserForm1
>>    .TextBox_X.Value = _
>>      (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp) * dx
>>    .TextBox_Y.Value = _
>>       (Tp + Hp - 0.75 * y * 100 / ActiveWindow.Zoom + hy) * dy
>>これではどうでしょうか?
>>もっともこれでも微妙な誤差は残りますね・・・。
>
>チェックしてみたところ、InsideWidthとInsideHeightは図面上最小軸と最大軸の距離を正確(4/3*ActiveWindow.Zoom/100補正はしていますが)に表しており、
>InsideLeftとInsideTopの値は、図面左上(X最小軸,Y最大軸)から(-4,-4)であることから
>
>  With ActiveChart.PlotArea
>    Lp = .InsideLeft + 4: Tp = .InsideTop + 4
>    Wp = .InsideWidth: Hp = .InsideHeight
>    dx = 100 / Wp
>    dy = 100 / Hp
>  End With

↑これは、疑問ですねえ??、せっかくActiveWindow.Zoomを使用して
倍率まで考慮しているのに定数を指定してしまって大丈夫ですか?
倍率が変われば4に相当する値も変わりますよ!!
そもそも4が合っていますか?
ポイントは0.75単位なんですけどねえ・・・。
もし、気がついたら調べてみてください。

【38420】Re:ワークシート上のグラフの座標を知り...
発言  わいわい  - 06/6/2(金) 11:12 -

引用なし
パスワード
   ichinose 様

>>InsideLeftとInsideTopの値は、図面左上(X最小軸,Y最大軸)から(-4,-4)であることから
>>  With ActiveChart.PlotArea
>>    Lp = .InsideLeft + 4: Tp = .InsideTop + 4

>↑これは、疑問ですねえ??、せっかくActiveWindow.Zoomを使用して
>倍率まで考慮しているのに定数を指定してしまって大丈夫ですか?
>倍率が変われば4に相当する値も変わりますよ!!
ここでの4は、0.75 * x * 100 / ActiveWindow.Zoom により換算した上での実験値ですので論理的な根拠はありませんが、表示倍率の変更には対応できています。(但しグラフの左上が表示されていない場合は、おかしな数値を返します)

>そもそも4が合っていますか?
>ポイントは0.75単位なんですけどねえ・・・。
>もし、気がついたら調べてみてください。
うっ これは、・・・『4』を得るために200%とか400%で見ているときに4.025とか3.925がでていて150%や75%のときに4.00が出たのが印象に残ったのかな?
まあ、もともとポイントごと(デジタル的?)の選択しか出来ないので本当に正確な値と言うのは無理ですから、この程度の誤差はしょうがないと思います。

確認したところ、75%表示のときに1ドット=1また150%表示のときに1ドット=0.5ですから、グラフ軸左上とPlotAreaの左上は 16/3*ActiveWindow.Zoom/100 ドット(当然四捨五入)ずれていると言うことみたいですね。

【38435】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/2(金) 19:11 -

引用なし
パスワード
   ▼わいわい さん:
こんばんは。

>確認したところ、75%表示のときに1ドット=1また150%表示のときに1ドット=0.5ですから、グラフ軸左上とPlotAreaの左上は 16/3*ActiveWindow.Zoom/100 ドット(当然四捨五入)ずれていると言うことみたいですね。
なるほど・・・、実は私は当初Zoomの事まで考慮してなかったので
すごい!!と感心していたのですが・・・。


ちょっと実験してみましょう!!

新規ブックの適当なシートのシートモジュールに

'======================================================================
Dim WithEvents cht As Chart
'======================================================================
Sub set_obj()
  Set cht = Me.ChartObjects(1).Chart
  MsgBox cht.Name
End Sub
'======================================================================
Sub reset_obj()
  Set cht = Nothing
End Sub
'=========================================================================
Private Sub cht_MouseDown(ByVal Button As Long, ByVal Shift As Long, ByVal x As Long, ByVal y As Long)
  Dim dx As Double
  Dim dy As Double
  Dim hx As Double
  Dim hy As Double
  Dim txt As TextBox
  Dim shp As Shape
  Dim xmax As Double
  Dim ymax As Double
  With cht.PlotArea
    lp = .InsideLeft: Tp = .InsideTop
    Wp = .InsideWidth: Hp = .InsideHeight
  End With
  ymax = cht.Axes(xlValue).MaximumScale
  xmax = cht.Axes(xlCategory).MaximumScale
  dx = xmax / Wp
  dy = ymax / Hp
  hx = cht.ChartArea.Left
  hy = cht.ChartArea.Top
  MsgBox "Plotx" & (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp) * dx & "----" & "plotY" & (Tp + Hp - 0.75 * y * 100 / ActiveWindow.Zoom + hy) * dy & vbCrLf & _
     "plotarea inleft" & cht.PlotArea.InsideLeft & "----" & "plotarea intop" & cht.PlotArea.InsideTop & vbCrLf & _
     "plotarea left" & cht.PlotArea.Left & "----plotarea top " & cht.PlotArea.Top & vbCrLf & _
     "0.75*x= " & 0.75 * x & "---- 0.75*y= " & 0.75 * y & vbCrLf & _
     "chartarea.left " & ActiveChart.ChartArea.Left & "--- chartarea top " & ActiveChart.ChartArea.Top
End Sub
'=======================================================================
Sub mk_sample()
  Dim mkcht As Chart
  With Me
    .Range("a1:b1").Value = Array("X", "Y")
    With .Range("a2:b31")
     .Formula = "=round(100*rand(),2)"
     .Value = .Value
     End With
    End With
  Set mkcht = ThisWorkbook.Charts.add
  With mkcht
    .ChartType = xlXYScatter
    .SetSourceData Source:=Me.Range("A1:B31"), PlotBy:=xlColumns
    .PlotArea.Left = 0
    .PlotArea.Top = 0
    .Location Where:=xlLocationAsObject, Name:=Me.Name
   End With
End Sub


前回のSelectイベントのコードをMouseDownイベント用に変更したものです。
zoomは、100%で実行してください。

1.mk_sampleを実行してサンプルデータとグラフを作成してください。

2.作成したグラフのPlotareaのLeftとTopプロパティは0に設定しました。
  グラフを良く見てください。
  この「0」って、グラフエリアからのポイントですよね?

3.set_objを実行してイベントの発生を可能にしてください。

4.まず、このチャートオブジェクトの左上の角をクリックしてください。
  (0.75*X 及び、0.75*yが0になるポイントです)。
  結構合わせるのが難しいですけど・・・、
  両方0になるポイントをクリックしてください。
  このとき、Msgboxが表示されますが、
  抜粋すると、
  Plotarea.Left Plotarea.Topは、0
  ChartArea.Left Chartarea.Topは、共に3と表示されました
  (私の環境で)

  つまり、PolotareaのLeft,Topは、Chartareaを起点にしたポイントであるのに
  対し、イベントから取得される0.75*xと0.75*yは、
  ChartObjectの左上を角を起点にしています。

  このポイント3の補正のための処理が必要だと思っているのです。

  よって、Mousedownイベントの補正が上記のコードのようになるのですが・・。
  プロットもクリックしてください。X,Yの値もおおよそ合っています。


 いかがでしょうか?

【38437】Re:ワークシート上のグラフの座標を知り...
お礼  わいわい  - 06/6/2(金) 20:54 -

引用なし
パスワード
   ichinose 様

毎回丁寧な回答して頂き、検証用マクロまで組んでいただきありがとうございます。

>つまり、PolotareaのLeft,Topは、Chartareaを起点にしたポイントであるのに
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1.
>対し、イベントから取得される0.75*xと0.75*yは、
>ChartObjectの左上を角を起点にしています。
>このポイント3の補正のための処理が必要だと思っているのです。
ですが
>lp = PlotArea.InsideLeft
>hx = ChartArea.Left
>Plotx" & (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp)
1.にあるようにlp、hxは、同系の座標(シート基準?)ですので 
hxを基準にしたときの -hx-lpとlpを基準にしたときの -lpは等しいものと考えられます。よって補正すべき数値は、lpからグラフの左上頂点までの距離(私は4としていますが前回回答からもう少し制度を上げられそうです)ですね。

>なるほど・・・、実は私は当初Zoomの事まで考慮してなかったので
>すごい!!と感心していたのですが・・・。
表示倍率についてはこれでよいのですが、lp、wpが画面上に無いときの処理が問題です。これについては、座標読み取り作業時には、グラフを強制的に画面に収まるようにサイズ調節することで対応しようと思います。(四隅の何れかが表示されていれば追えるような気がしていますが)

【38440】Re:ワークシート上のグラフの座標を知り...
発言  ichinose  - 06/6/2(金) 22:14 -

引用なし
パスワード
   ▼わいわい さん:
納得です。

>
>毎回丁寧な回答して頂き、検証用マクロまで組んでいただきありがとうございます。
>
>>つまり、PolotareaのLeft,Topは、Chartareaを起点にしたポイントであるのに
>    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1.
>>対し、イベントから取得される0.75*xと0.75*yは、
>>ChartObjectの左上を角を起点にしています。
>>このポイント3の補正のための処理が必要だと思っているのです。
>ですが
>>lp = PlotArea.InsideLeft
>>hx = Chartarea.Left

>>Plotx" & (0.75 * x * 100 / ActiveWindow.Zoom - hx - lp)
>1.にあるようにlp、hxは、同系の座標(シート基準?)ですので 
グラフの端が基準ですね!!
InsideLeftはChartarea.Leftからの相対位置だと思っていましたが、
これが間違いでした。(だって、3なんてちょうど良さそうな値だから・・)。
これは、収穫でした。4のほうが実際はしっくりきたんですけど、
どこからくる4なのかがわからなかったので、
理屈としてはInsideLeftがChartarea.Leftの相対値だと
納得できたので思い込んでました。
それでも4ぴったりというのは、疑問が残りますが・・・。

わいわい さんの投稿により、私もたくさん勉強になりました。
ありがとうございました。

7540 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free