tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルExcelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10303
投稿日: 2010/11/11(Thu) 18:12
投稿者酔いどれ熊
いつもお世話になっています。ここ数日頭の捻っていますがうまくいかないので
質問させて貰います。

「Excelのグラフをクリップボード経由でPictureBoxに貼付」の中で
新しくグラフを作成して貼り付ける場合に
  MyCharts = xlSheet.ChartObjects
  MyChart = MyCharts.Add(10, 90, 550, 300) -----@
となっていますが、ここを既存のグラフを読み込みたく@の行を色々と変えてみている
のですがうまくいきません。

ターゲットとなるエクセルのファイルは
Sheet1 ←ここにデータが入っています
Graph1 ←Sheet1のデータで作成されたグラフだけのシート その1
Graph2 ←Sheet1のデータで作成されたグラフだけのシート その2

で、このGraph1を引っぱってきたいのですがどのようにすればいいのでしょうか?

Excel.ChartObjectsではExcel.ChartObjects(Index)でシートを指定できるようにも
取れるのですがどうやってもエラーになってしまいます。
どなたか分かる方いましたらご教授頂きたくよろしくお願い致します。

開発環境
Microsoft Visual Studio 2008 Standard Edition & Microsoft Visual Basic 2010 Express
OS:WindowsXP(32) SP3

[ツリー表示へ]
タイトルRe: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10304
投稿日: 2010/11/11(Thu) 19:09
投稿者花ちゃん
>   MyCharts = xlSheet.ChartObjects
>   MyChart = MyCharts.Add(10, 90, 550, 300) -----@
> となっていますが、ここを既存のグラフを読み込みたく@の行を色々と変えてみている
> のですがうまくいきません。

どのように変更されて、どううまくいかなかったのでしょうか?

Excel の既存のファイルを使用する場合と同じ要領で

   MyCharts = xlSheet.ChartObjects
   MyChart1 = CType(MyCharts.Item(1), Excel.Chart)
又は MyChart1 = CType(MyCharts.Item("Graph1"), Excel.Chart)
  
のようにすればいいかと思うのですが。(試していないので未確認ですが)

それより、肝心のExcelのバージョンが書いていないのですが?
Excel のバージョンによって操作が違ってきます。

  http://hanatyan.sakura.ne.jp/patio/read.cgi?no=166

[ツリー表示へ]
タイトルRe^2: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10305
投稿日: 2010/11/12(Fri) 08:59
投稿者酔いどれ熊
> それより、肝心のExcelのバージョンが書いていないのですが?
> Excel のバージョンによって操作が違ってきます。

すいません、失念していました。ExcelはExcel2003です。

>     MyChart1 = CType(MyCharts.Item(1), Excel.Chart)
> 又は MyChart1 = CType(MyCharts.Item("Graph1"), Excel.Chart)

上記でもダメでした。
他にも
        'MyChart1 = CType(MyCharts.Item(1), Excel.Chart)
        'MyChart1 = CType(MyCharts.Item(1), Excel.Charts)
        'MyChart1 = CType(MyCharts.Item("Graph1"), Excel.Chart)
        'MyChart1 = CType(MyCharts.Item("Graph1"), Excel.Charts)
        'MyChart1 = CType(xlSheets.Item(1), Excel.Chart)
        'MyChart1 = MyCharts.Application.Charts.Item("Graph1")

いろいろ試してみてますがエラーが出ます。
(MyChart = MyCharts.Add(10, 90, 550, 300)で追加したグラフは正常に表示されます)

単にどこかの指定の仕方が悪いんだろうとは思うんですが、
その辺の解説は他のサイトとかどこを探しても無くて・・・

[ツリー表示へ]
タイトルRe^3: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10306
投稿日: 2010/11/12(Fri) 11:12
投稿者花ちゃん
> いろいろ試してみてますがエラーが出ます。

だから、どこをどのように変更してどこで、どのようなエラーが出ているのか
キチンと書かないとこれを見ている人には解らないでしょうが?

先に回答した部分だけでは、当然既存のグラフファイルを表示する事はできませんよ。

Excel の既存のシートを開くのと新規シートを使用すると同じように。

MyChart1 = CType(MyCharts.Item(1), Excel.Chart) のように書き換えたら、それ以降の
部分でエラーがでている(変更した時点で)部分はどのようにしましたか?
各プログラムのステップで何をしているのかをよく見てみればどのように変更しなければ
ならないのか解るかと思うのですが。

[ツリー表示へ]
タイトルRe^4: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10307
投稿日: 2010/11/12(Fri) 11:35
投稿者酔いどれ熊
プログラムレベルも質問の仕方も稚拙でご迷惑を掛けております。

プログラムとしては以下のような感じにしています。
---------------------------------------------------------
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim xlApp As New Excel.Application
        Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
        Dim xlFilePath As String = "c:\Test\Test1.xls"
        Dim xlBook As Excel.Workbook = xlBooks.Open(xlFilePath)
        Dim xlSheets As Excel.Sheets = xlBook.Worksheets
        Dim xlSheet As Excel.Worksheet = xlSheets.Item(1)
        xlApp.Visible = False
        Dim MyCharts As Excel.ChartObjects
        Dim MyChart As Excel.ChartObject
        Dim MyChart1 As Excel.Chart

        MyCharts = xlSheet.ChartObjects
        MyChart = CType(MyCharts.Item("Graph1"), Excel.Chart) '-----@
        MyChart1 = MyChart.Chart

        'Excelグラフをクリップボード経由でPictureBoxに貼付
        'xlSheet.ChartObjects("グラフ 1").Copy()  'これでは、.NET では取得できない
        MyChart1.CopyPicture(Appearance:=Excel.XlPictureAppearance.xlScreen, _
                                    Size:=Excel.XlPictureAppearance.xlScreen, _
                                    Format:=Excel.XlCopyPictureFormat.xlBitmap)

        'クリップボードにあるデータを取得
        Dim iData As IDataObject = Clipboard.GetDataObject()
        If iData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap) Then
            PictureBox1.Image = CType(iData.GetData(DataFormats.Bitmap), Image)
        End If

        MRComObject(MyChart1)               'MyChart1 の解放
        MRComObject(MyChart)                'MyChart の解放
        MRComObject(MyCharts)               'MyCharts の解放

        '==================  ファイルの保存処理  ==================  
        'xlApp.DisplayAlerts = False     '保存時の問合せのダイアログを非表示に設定
        'xlSheet.SaveAs(xlFilePath)      'ファイルに保存
        'xlApp.DisplayAlerts = True      '元に戻す

        '==================  終了処理  =====================  
        MRComObject(xlSheet)            'xlSheet の解放
        MRComObject(xlSheets)           'xlSheets の解放
        xlBook.Close(False)             'xlBook を閉じる
        MRComObject(xlBook)             'xlBook の解放
        MRComObject(xlBooks)            'xlBooks の解放
        xlApp.Quit()                    'Excelを閉じる
        MRComObject(xlApp)              'xlApp を解放
    ’(以下のエクセル解放?処置は省略してます)
    End Sub
---------------------------------------------------------

この状態で実行すると
ChartObjects クラスの Item メソッドが失敗しました。
とのエラーが出て止まってしまっています。

[ツリー表示へ]
タイトルRe^5: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10308
投稿日: 2010/11/12(Fri) 12:32
投稿者花ちゃん
>         MyChart = CType(MyCharts.Item("Graph1"), Excel.Chart) '-----@
> この状態で実行すると
> ChartObjects クラスの Item メソッドが失敗しました。
> とのエラーが出て止まってしまっています。

この時、Excel 上では、Graph1 が表示されていますか?

  MyCharts = xlSheet.ChartObjects
  Debug.Print(MyCharts.Count.ToString())   ' これを追加したらどうなりますか
  MyChart = CType(MyCharts.Item("Graph1"), Excel.Chart) '-----@
  MyChart1 = MyChart.Chart

そもそも、このプログラムを見た限りでは、前回作成したグラフを再表示するような
仕様になっていますが、そのような必要があるなら、グラフを作成した時にグラフを
BMP 形式等で保存しておけば済む事ではないのですか?
(VB からはその保存したBMPファイルをピクチャーボックスに読み込むだけで済むし)

[ツリー表示へ]
タイトルRe^6: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10309
投稿日: 2010/11/12(Fri) 12:59
投稿者酔いどれ熊
> この時、Excel 上では、Graph1 が表示されていますか?

Excel上のSheet1が表示されています。
(Sheet1、Graph1、Graph2、の順で並んでいてSheet1が表示されている状態です)


>   Debug.Print(MyCharts.Count.ToString())   ' これを追加したらどうなりますか

デバッグ表示の方には
0
'System.Runtime.InteropServices.COMException' の初回例外が mscorlib.dll で
発生しました。

と表示されています。

> そもそも、このプログラムを見た限りでは、前回作成したグラフを再表示するような
> 仕様になっていますが、そのような必要があるなら、グラフを作成した時にグラフを
> BMP 形式等で保存しておけば済む事ではないのですか?

このボタン動作としてはグラフをフォーム上に表示させているだけですが、別の動作時に
バイナリデータを読み込んで数値化して該当Excelファイル(Test1.xls)のSheet1に
入れ込んでいます。
なぜ新規にグラフを作成しないかというのは、グラフ上に注記や判定範囲の補助線とか
を記載しているため、エクセルファイル内に予めグラフを用意しているのです。
−別ボタンで数値代入
−本動作でフォーム上にグラフ表示
−結果はエクセルで保存
と言った流れです。
エクセル表示をTrueにしてそちらを見ればいいっていわれると詰んでしまいますが
VB6で出来ていたフォーム上に表示(.copyからクリップボード経由でメタファイル取得)
が.NETでも実現させたいのです。

[ツリー表示へ]
タイトルRe^7: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10311
投稿日: 2010/11/12(Fri) 14:34
投稿者花ちゃん
下記の部分を

>         xlApp.Visible = False
>         Dim MyCharts As Excel.ChartObjects
>         Dim MyChart As Excel.ChartObject
>         Dim MyChart1 As Excel.Chart
>
>         MyCharts = xlSheet.ChartObjects
>         MyChart = CType(MyCharts.Item("Graph1"), Excel.Chart) '-----@
>         MyChart1 = MyChart.Chart


下記のように変更してみて下さい。

        xlApp.Visible = False
        'Dim MyCharts As Excel.ChartObjects
        'Dim MyChart As Excel.ChartObject
        Dim MyChart1 As Excel.Chart

        'MyCharts = xlSheet.ChartObjects
        'MyChart = CType(MyCharts.Item("Graph1"), Excel.Chart) '-----@
        MyChart1 = CType(xlBook.Charts("Graph1"), Excel.Chart)



        MRComObject(MyChart1)           'MyChart1  の解放
        'MRComObject(MyChart)            'MyChart   の解放
        'MRComObject(MyCharts)           'MyChart1s の解放

[ツリー表示へ]
タイトル【解決】: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10312
投稿日: 2010/11/12(Fri) 14:59
投稿者酔いどれ熊
ありがとうございます。ばっちりグラフが表示されました。

--------------------------------------
        '===============  グラフの表示設定  =======================
        Dim MyChart1 As Excel.Chart

        MyChart1 = CType(xlBook.Charts("Graph1"), Excel.Chart)      
        '"Graph1"はチャート名

        MyChart1.CopyPicture(Appearance:=Excel.XlPictureAppearance.xlScreen, _
                                    Size:=Excel.XlPictureAppearance.xlScreen, _
                                    Format:=Excel.XlCopyPictureFormat.xlBitmap)

        'クリップボードにあるデータを取得してPictureBox1に表示
        Dim iData As IDataObject = Clipboard.GetDataObject()
        If iData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap) Then
            PictureBox1.Image = CType(iData.GetData(DataFormats.Bitmap), Image)
        End If

        MRComObject(MyChart1)               'MyChart1 の解放
--------------------------------------

>これで得られるのは、Worksheet 上のチャートオブジェクト(ChartObject)ですね。
>こちらはグラフシート(Chart)ですね。

勉強になりました。同じグラフなのに表示場所によって違ってくるんですね。



管理人(花ちゃん)さん、魔界の仮面弁士さん
本当に有り難うございました。

[ツリー表示へ]
タイトルRe^8: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10313
投稿日: 2010/11/12(Fri) 16:47
投稿者魔界の仮面弁士
> Dim MyChart1 As Excel.Chart
> MyChart1 = CType(xlBook.Charts("Graph1"), Excel.Chart)

処理イメージからすると、
 Dim MyCharts As Excel.Sheets = xlBook.Charts
 Dim MyChart1 As Excel.Chart = DirectCast(MyCharts("Graph1"), Excel.Chart)
   :
   :
 MRComObject(MyChart1)
 MRComObject(MyCharts)
になりそうな気がするのですが、xlBook.Charts が
解放漏れする事は無いのでしょうか。(未検証)

[ツリー表示へ]
タイトルRe^9: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10314
投稿日: 2010/11/12(Fri) 17:03
投稿者花ちゃん
> > Dim MyChart1 As Excel.Chart
> > MyChart1 = CType(xlBook.Charts("Graph1"), Excel.Chart)
>
> 処理イメージからすると、
>  Dim MyCharts As Excel.Sheets = xlBook.Charts
>  Dim MyChart1 As Excel.Chart = DirectCast(MyCharts("Graph1"), Excel.Chart)
>    :
>    :
>  MRComObject(MyChart1)
>  MRComObject(MyCharts)
> になりそうな気がするのですが、xlBook.Charts が
> 解放漏れする事は無いのでしょうか。(未検証)

一応解放はされていたのでそのまま投稿したのですが、後で気が付いて修正しようかな
と思ったら、解決報告されていたのでどうしょうかなと思っていたところでした。

[ツリー表示へ]
タイトルRe^9: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10315
投稿日: 2010/11/15(Mon) 13:50
投稿者酔いどれ熊
> > Dim MyChart1 As Excel.Chart
> > MyChart1 = CType(xlBook.Charts("Graph1"), Excel.Chart)
> xlBook.Charts が解放漏れする事は無いのでしょうか。(未検証)

自分もエクセルが解放されていたので特に気にしてませんでしたけど追記しておきます。
ご指摘ありがとうございました。

[ツリー表示へ]
タイトルRe: Excelの『既存』グラフをクリップボード経由でPictureBoxに貼付
記事No10310
投稿日: 2010/11/12(Fri) 13:34
投稿者魔界の仮面弁士
>   MyCharts = xlSheet.ChartObjects
> MyChart = MyCharts.Add(10, 90, 550, 300)
これで得られるのは、Worksheet 上のチャートオブジェクト(ChartObject)ですね。


> Sheet1 ←ここにデータが入っています
> Graph1 ←Sheet1のデータで作成されたグラフだけのシート その1
> Graph2 ←Sheet1のデータで作成されたグラフだけのシート その2
こちらはグラフシート(Chart)ですね。


> で、このGraph1を引っぱってきたいのですがどのようにすればいいのでしょうか?
Sheets コレクションから .Item("Graph1") で Chart オブジェクトを得られます。
もしくは、Workbook オブジェクト → Charts プロパティ → Charts コレクション経由でも可。

そこまでできれば、あとは Chart オブジェクトの CopyPicture メソッドで画像を得られます。

[ツリー表示へ]