【ExcelVBA】フォーム上のListboxで選択されたデータをグラフに表示させるには

この記事では、フォーム上のListboxで選択されたデータをグラフに表示させる方法についてご説明します。

【動画】フォーム上のListboxで選択されたデータをグラフに表示させる実際の動き

本題に入る前に、まずは次の動画をご覧ください。


Listboxの行が選択されたら、選択された値をグラフに出力します。

グラフを画像に保存し、その画像をImageコントロールに表示させます。

セルに表示させるグラフと違い、フォーム上で扱えるグラフのコントロールが無いので、グラフを画像ファイルに保存してその画像をImageコントロールに表示させることで代替させています。

マクロ作成の流れ

STEP.1
フォーム上のListboxで選択された行のデータをグラフに出力する
フォーム上のListboxで選択された行のデータをグラフに出力します。
STEP.2
グラフを画像に保存する
グラフを画像に保存します。
STEP.3
STEP.2で保存した画像をImageコントロールに表示させる
STEP.2で保存した画像をImageコントロールに表示させます。

Excelファイルの例

今回は次のExcelファイルを用意しました。シートは2つ、フォームが1つです。

【シート:work】

シート「work」には、フォーム「frm_main」を呼び出すボタンと、シート「data」の値を表示させるグラフが設置されています。

フォームにグラフを表示させるため、Listboxで選択されたデータをこのグラフに表示させます。

今回はグラフに「グラフ1」という名前を付けています。

【シート:data】

Listboxに表示させる元データをこの「data」のシートに保存しています。

【フォーム:frm_main】

コントロール「Listbox1」と「Image」の2つを設置しています。

フォームを呼び出してListbox1の行を選択すると以下の画面の通りにグラフが表示されます。

Imageコントロールに表示させているのは以下の画像ファイルです。

この画像は、シート「work」で出力されたグラフの画像です。

なぜわざわざグラフの画像を保存しているのかというと、その画像をフォーム上のImageコントロールに表示させるためです。

そもそもフォームにはグラフのコントロールが無いので、その代替として画像を表示させることで、グラフっぽく見せているだけなんです。

コードの例

Option Explicit

Private Sub ListBox1_Click()
    
    Dim tWs         As Worksheet    'ワークシート変数(シート「work」用)
    Dim dWs         As Worksheet    'ワークシート変数(シート「data」用)
    Dim ChartObj    As ChartObject  'グラフ用変数
    Dim cnt         As Long         'カウンタ用変数
    Dim pic         As StdPicture   '画像用変数
    
    '配列dataAryを定義する
    ReDim dataAry(0)
    
    '配列subjAryを定義する
    ReDim subjAry(0)
    
    'シートを取得する
    Set tWs = Worksheets("top")
    
    'シートを取得する
    Set dWs = Worksheets("data")
        
    '設置されたグラフのインスタンスを生成
    Set ChartObj = tWs.ChartObjects("グラフ1")
        
    With listbox1
        
        '科目ごとの点数の数分処理を繰り返すFor文
        For cnt = 2 To .ColumnCount - 1
        
            '配列のサイズを増やす
            ReDim Preserve dataAry(cnt - 2)
    
            '配列dataAryにListboxの値を格納する
            dataAry(cnt - 2) = .List(.ListIndex, cnt)
    
        Next cnt
        
    End With
    
    With ChartObj.Chart
            
        If ChartObj.Chart.SeriesCollection.Count = 0 Then
        
            '既存の系列が存在しない場合
            
            '選択行の表データをグラフに表示させる
            .SeriesCollection.NewSeries
            
        End If
        
        '選択行の表データをグラフに表示させる
        .SeriesCollection(1).Values = dataAry
        
        'グラフの最大値を100に設定する
        .Axes(xlValue).MaximumScale = 100
        
        'グラフの縦軸のラベルを変更可能にする
        .Axes(xlValue, xlPrimary).HasTitle = True
        
        'グラフの縦軸のラベルを変更する
        .Axes(xlValue, xlPrimary).AxisTitle.Text = "点数"
        
        'グラフの横軸のラベルを変更可能にする
        .Axes(xlCategory, xlPrimary).HasTitle = True
        
        'グラフの横軸のラベルを変更する
        .Axes(xlCategory, xlPrimary).AxisTitle.Text = listbox1.List(listbox1.ListIndex, 1) & "さんの点数"
                
        With .Axes(xlCategory)
        
            '科目名分処理を繰り返すFor文
            For cnt = 0 To 4
            
                '配列subjAryを再定義する
                ReDim Preserve subjAry(cnt)
        
                '配列dataAryに、シート「data」の1行目にある科目名を格納する
                subjAry(cnt) = dWs.Cells(1, cnt + 3).Value
        
            Next cnt
            
            '横軸ラベルを科目に変更する
            .CategoryNames = subjAry
            
        End With
        
        'グラフの画像を保存する(今回は本マクロのExcelファイルと同じ場所に「Graph.jpg」の名前で保存)
        .Export ThisWorkbook.Path & "\Graph.jpg"

        '(グラフの)画像の情報を取得する
         Set pic = LoadPicture(ThisWorkbook.Path & "\Graph.jpg")

        'Imageコントロールの高さを設定する
        Image1.Height = frm_main.Height * 0.5

        'Imageコントロールの幅を、画像のアスペクト比(縦横比)に基づいて設定する
        Image1.Width = Image1.Height * (pic.Width / pic.Height)

        '画像をImageコントロールに設定する
        Image1.Picture = pic
        
    End With
        
End Sub

注目すべきコード①

最初に見て頂きたいのは24行目です。

    '設置されたグラフのインスタンスを生成
    Set ChartObj = tWs.ChartObjects("グラフ1")

コードの説明

以上のコードは、設置されたグラフのインスタンスを生成するコードです。

グラフには「グラフ1」という名前を付けています。

注目すべきコード②

次に見て頂きたいのは26行目から39行目です。

    With listbox1
        
        '科目ごとの点数の数分処理を繰り返すFor文
        For cnt = 2 To .ColumnCount - 1
        
            '配列のサイズを増やす
            ReDim Preserve dataAry(cnt - 2)
    
            '配列dataAryにListboxの値を格納する
            dataAry(cnt - 2) = .List(.ListIndex, cnt)
    
        Next cnt
        
    End With

コードの説明

以上のコードは、選択されたlistboxの行の点数を配列dataAryに格納する処理のコードです。

点数をグラフに表示させるため、配列dataAryに格納しておきます。

コードの詳細

29行目のコードは、科目ごとの点数の数分処理を繰り返すFor文です。

32行目のコードで配列dataAryを再定義し、35行目でListboxから取得した点数を格納します。

注目すべきコード③

次に見て頂きたいのは43行目から50行目です。

        If ChartObj.Chart.SeriesCollection.Count = 0 Then
        
            '既存の系列が存在しない場合
            
            '選択行の表データをグラフに表示させる
            .SeriesCollection.NewSeries
            
        End If

コードの説明

以上のコードは、系列がグラフに存在するかを判定し、存在しない場合は系列を表示させる処理のコードです。

系列とは下のことを指します。

すでに系列がグラフに存在しているのに48行目の「.SeriesCollection.NewSeries」メソッドを実行してしまうと、無駄に系列を追加してしまいます。

なので、43行目で系列がグラフに存在しているか判定し、系列がグラフに存在していない時だけ48行目でNewSeriesを実行して系列を生成します。

注目すべきコード④

次に見て頂きたいのは53行目です。

        '選択行の表データをグラフに表示させる
        .SeriesCollection(1).Values = dataAry

コードの説明

以上のコードは、Listboxで選択された行の点数をグラフに出力するコードです。

配列dataAryにはListboxで選択された行の点数が格納されており、Valuesプロパティに格納することでグラフに出力されます。

下の画像は1行目の行が選択されていますが、その行の点数がグラフに表示されています。

注目すべきコード⑤

次に見て頂きたいのは56行目です。

        'グラフの最大値を100に設定する
        .Axes(xlValue).MaximumScale = 100

コードの説明

以上のコードは、グラフの最大値を設定するコードです。

今回はグラフに表示させる値が100点満点の点数なので、MaximumScaleプロパティの値に100を設定しています。

MaximumScaleプロパティの値に100を設定すると以下のように100がグラフ表示の上限になります。

注目すべきコード⑥

次に見て頂きたいのは59行目から68行目です。

        'グラフの縦軸のラベルを変更可能にする
        .Axes(xlValue, xlPrimary).HasTitle = True
        
        'グラフの縦軸のラベルを変更する
        .Axes(xlValue, xlPrimary).AxisTitle.Text = "点数"
        
        'グラフの横軸のラベルを変更可能にする
        .Axes(xlCategory, xlPrimary).HasTitle = True
        
        'グラフの横軸のラベルを変更する
        .Axes(xlCategory, xlPrimary).AxisTitle.Text = listbox1.List(listbox1.ListIndex, 1) & "さんの点数"

コードの説明

以上のコードは、グラフの縦軸と横軸それぞれのラベルに文言を設定する処理のコードです。

縦軸のラベルには「点数」の文字列を、横軸のラベルには選択された行の生徒名に「さんの点数」の文字列を結合させた文字列を表示させています。

注目すべきコード⑦

次に見て頂きたいのは70行目から86行目です。

        With .Axes(xlCategory)
        
            '科目名分処理を繰り返すFor文
            For cnt = 0 To 4
            
                '配列subjAryを再定義する
                ReDim Preserve subjAry(cnt)
        
                '配列dataAryに、シート「data」の1行目にある科目名を格納する
                subjAry(cnt) = dWs.Cells(1, cnt + 3).Value
        
            Next cnt
            
            '横軸ラベルを科目に変更する
            .CategoryNames = subjAry
            
        End With

コードの説明

以上のコードは、シート「data」の1行目から科目名を取得して配列subjAryに格納し、その配列の値を横軸ラベルを設定する処理のコードです。

横軸ラベルに科目名を設定すると、以下のように横軸ラベルに科目名が表示されます。

シート「data」の1行目にある科目名が格納されている配列subjAryをCategoryNamesプロパティに格納することで科目名がグラフに表示されています。

コードの詳細

72行目のコードは、科目名分処理を繰り返すFor文です。

76行目のコードで配列subjAryを再定義し、35行目でシート「data」の1行目にある科目名を格納します。

84行目のコードでは、CategoryNamesプロパティに科目名が格納された配列subjAryを格納しています。

注目すべきコード⑧

次に見て頂きたいのは89行目から101行目です。

        'グラフの画像を保存する(今回は本マクロのExcelファイルと同じ場所に「Graph.jpg」の名前で保存)
        .Export ThisWorkbook.Path & "\Graph.jpg"

        '(グラフの)画像の情報を取得する
         Set pic = LoadPicture(ThisWorkbook.Path & "\Graph.jpg")

        'Imageコントロールの高さを設定する
        Image1.Height = frm_main.Height * 0.5

        'Imageコントロールの幅を、画像のアスペクト比(縦横比)に基づいて設定する
        Image1.Width = Image1.Height * (pic.Width / pic.Height)

        '画像をImageコントロールに設定する
        Image1.Picture = pic

コードの説明

以上のコードは、グラフを画像ファイルに出力し、フォーム上にあるImageコントロールにその画像を表示させる処理のコードです。

フォーム上にあるImageコントロールに画像を表示させたら、Imageコントロールのサイズを調整しています。

コードの詳細

89行目のコードでは、グラフを画像に出力します。

92行目のコードでは、出力された画像ファイルの情報を取得します。

95行目のコードでは、Imageコントロールの縦幅を調整します。

98行目のコードでは、Imageコントロールの横幅を調整します。

101行目のコードでは、Imageコントロールに画像ファイルを表示させます。

動作確認

Excelファイルの例」をご覧ください。

最後に

この記事では、フォーム上のListboxで選択されたデータをグラフに表示させる方法についてご説明しました。

フォーム上のListboxで選択されたデータをグラフに表示させたい場合は本記事を参考にして頂けたら幸いです。

プログラミングのスキルを習得するなら

プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。

プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。

→ TechAcademyの「1週間 無料体験」はこちら