🍣

【Excel】グラフ作成の効率化テクニック

に公開
2026/01/04

はじめに

測定データのグラフ化において、手作業での書式設定はかなり面倒です。

  • 複数グラフ間での書式統一が困難(フォントサイズ、色、軸範囲等のバラつき)
  • 仕様変更時の修正コストが高い(全グラフの個別編集が必要)

特に、論文・レポート用に同一フォーマットで大量のグラフを作成する場合、この非効率性は顕著です。

解決策:
VBAマクロによる書式の自動適用が有効ですが、従来はコーディング知識が必要でした。本記事では、LLM(Claude、ChatGPT、Codex等)を活用し、自然言語での指示からVBAコードを生成する手法を紹介します。

実装例として、周波数応答グラフ用のマクロ(対数軸設定、Y軸範囲の自動調整、系列の透明度グラデーション)と、効果的なプロンプトの書き方を示します。

実装方針:AI + VBA

なぜVBA?

グラフ書式の自動化には複数の選択肢がありますが、VBAには以下の利点があります。

  • Excelファイル内で完結:別途環境構築不要、ファイル共有で設定も配布可能
  • 動的な処理が可能:データの最大値を取得して軸範囲を自動設定、など
  • 既存ワークフローへの統合:測定データの記録〜グラフ化を一貫してExcel内で実施

AIを使うことで直感性+スループットが両立

VBAコーディングの経験がなくても、以下の手順で実装できます。

  1. 「こういうグラフにしたい」という仕様を自然言語で記述
  2. LLMがVBAコードを生成
  3. 生成されたコードをExcelに貼り付け
  4. 必要に応じてフィードバックし、コードを修正

重要なのはプロンプト設計です。具体的な数値(RGB値、フォントサイズ等)を指定することで、所望のフォーマットを実現できます。

環境設定

VBAマクロを使うので、まずExcelの開発環境を有効化しましょう。

手順

  1. ファイル → オプション → リボンのユーザー設定
  2. 右側の 開発 にチェックを入れる

test
Excel オプション - 開発タブの有効化

  1. リボンに追加された 開発 タブから Visual Basic を選択
  2. VBAエディタで 挿入 → 標準モジュール を選択
  3. 表示されたコードウィンドウに、後述のマクロをペーストする


VBA エディタ - 標準モジュールへのコード実装

注:マクロを使う場合、マクロ有効ブック(.xlsm)として保存する必要があります。

実装例

実際に私が使っている周波数応答グラフ用のマクロを紹介します。アクティブシート内の全グラフに対して、一括で書式を適用する設計になっています。

マクロの機能概要

  • 軸設定:X軸を対数スケール(10Hz〜20kHz)、Y軸を線形スケール(-40dB〜自動上限)
  • 書式統一:フォントサイズ、軸線・グリッド線の色と太さを指定
  • 系列スタイル:単色(濃紺)+ 透明度グラデーションで最大11系列に対応
  • 動的調整:Y軸最大値をデータから自動算出、プロット領域の余白を自動調整

コード全体

Option Explicit

Sub ChangeFontSizeAndBold_NoTitle()
    Dim ws As Worksheet
    Dim chartObj As ChartObject
    Dim chart As chart
    Dim fontSize As Integer
    Dim series As series

    ' フォントサイズを指定
    fontSize = 16

    ' 現在のシートを対象にする
    Set ws = ActiveSheet

    ' シート内の全てのグラフオブジェクトに対して処理
    For Each chartObj In ws.ChartObjects
        Set chart = chartObj.chart

        ' 枠線(グラフオブジェクト)の枠線をなしに設定
        chartObj.ShapeRange.Line.Visible = msoFalse

        ' プロットエリアの枠線を灰色、太さ1.25に設定
        chart.PlotArea.Format.Line.ForeColor.RGB = RGB(120, 120, 120)
        chart.PlotArea.Format.Line.Weight = 1.25

        ' 縦軸の線を灰色、太さ1.25に設定
        chart.Axes(xlValue).Format.Line.ForeColor.RGB = RGB(120, 120, 120)
        chart.Axes(xlValue).Format.Line.Weight = 1.25

        ' 横軸の線を灰色、太さ1.25に設定
        chart.Axes(xlCategory).Format.Line.ForeColor.RGB = RGB(120, 120, 120)
        chart.Axes(xlCategory).Format.Line.Weight = 1.25

        ' 縦目盛線(主)をグレー、太さ0.5に設定
        chart.Axes(xlValue).MajorGridlines.Format.Line.ForeColor.RGB = RGB(160, 160, 160)
        chart.Axes(xlValue).MajorGridlines.Format.Line.Weight = 0.5

        ' 縦目盛線(補助)を薄いグレー、太さ0.5に設定
        chart.Axes(xlValue).MinorGridlines.Format.Line.ForeColor.RGB = RGB(225, 225, 225)
        chart.Axes(xlValue).MinorGridlines.Format.Line.Weight = 0.5

        ' 横目盛線(主)をグレー、太さ0.5に設定
        chart.Axes(xlCategory).MajorGridlines.Format.Line.ForeColor.RGB = RGB(160, 160, 160)
        chart.Axes(xlCategory).MajorGridlines.Format.Line.Weight = 0.5

        ' 横目盛線(補助)を薄いグレー、太さ0.5に設定
        chart.Axes(xlCategory).MinorGridlines.Format.Line.ForeColor.RGB = RGB(225, 225, 225)
        chart.Axes(xlCategory).MinorGridlines.Format.Line.Weight = 0.5

        ' X軸ラベルのフォント設定
        chart.Axes(xlCategory).TickLabels.Font.Size = fontSize
        chart.Axes(xlCategory).TickLabels.Font.Bold = False
        chart.Axes(xlCategory).TickLabels.Font.Color = RGB(0, 0, 0)

        ' Y軸ラベルのフォント設定
        chart.Axes(xlValue).TickLabels.Font.Size = fontSize
        chart.Axes(xlValue).TickLabels.Font.Bold = False
        chart.Axes(xlValue).TickLabels.Font.Color = RGB(0, 0, 0)

        ' X軸タイトルの設定
        If Not chart.Axes(xlCategory, xlPrimary).HasTitle Then
            chart.Axes(xlCategory, xlPrimary).HasTitle = True
        End If
        chart.Axes(xlCategory, xlPrimary).AxisTitle.Text = "Frequency (Hz)"
        chart.Axes(xlCategory, xlPrimary).AxisTitle.Font.Size = fontSize + 2
        chart.Axes(xlCategory, xlPrimary).AxisTitle.Font.Bold = False
        chart.Axes(xlCategory, xlPrimary).AxisTitle.Font.Color = RGB(0, 0, 0)

        '=== X軸(横軸)対数設定・範囲・目盛 ===
        Dim xAx As Axis
        On Error Resume Next
        Set xAx = chart.Axes(xlCategory, xlPrimary)
        On Error GoTo 0
        If Not xAx Is Nothing Then
            Call SetupLogXAxis(xAx, 10#, 20000#)
        End If

        ' Y軸タイトルの設定
        If Not chart.Axes(xlValue, xlPrimary).HasTitle Then
            chart.Axes(xlValue, xlPrimary).HasTitle = True
        End If
        chart.Axes(xlValue, xlPrimary).AxisTitle.Text = "Gain (dB)"
        chart.Axes(xlValue, xlPrimary).AxisTitle.Font.Size = fontSize + 2
        chart.Axes(xlValue, xlPrimary).AxisTitle.Font.Bold = False
        chart.Axes(xlValue, xlPrimary).AxisTitle.Font.Color = RGB(0, 0, 0)

        '=== Y軸(縦軸)のスケーリング設定 ===
        ' 主目盛線:10 dB刻み、補助目盛線:5 dB刻み
        ' 最小値:-40 dB、最大値:プロットの最大値を10の位で切り上げ
        Dim yMax As Double, yMaxCeil As Double
        yMax = GetChartMaxY(chart)
        yMaxCeil = WorksheetFunction.Ceiling(yMax, 10)
        With chart.Axes(xlValue)
            .MinimumScaleIsAuto = False
            .MaximumScaleIsAuto = False
            .MinimumScale = -40
            .MaximumScale = yMaxCeil
            .MajorUnit = 10
            .MinorUnit = 5
            .HasMinorGridlines = True
            .MajorTickMark = xlOutside
            .MinorTickMark = xlOutside
        End With

        ' 凡例の処理
        If chart.HasLegend Then
            With chart.Legend
                With .Font
                    .Size = fontSize - 2
                    .Bold = False
                    .Color = RGB(0, 0, 0)
                End With
                With .Format.Fill
                    .ForeColor.RGB = RGB(255, 255, 255)
                    .Transparency = 0.1
                End With
            End With
        End If

        '--- 単色&透明度をシリーズ番号に応じて設定(1~11で不透明度UP) ---
        Const BASE_R As Long = 10
        Const BASE_G As Long = 62
        Const BASE_B As Long = 85
        Const MAX_SERIES As Long = 11
        Const TRANS_START As Double = 0.65
        Const TRANS_END   As Double = 0.05

        Dim s As series
        Dim idx As Long
        Dim frac As Double
        Dim t As Double

        idx = 1
        For Each s In chart.SeriesCollection
            With s.Format.Line
                .Visible = msoTrue
                .Weight = 1.75
                .ForeColor.RGB = RGB(BASE_R, BASE_G, BASE_B)
                frac = WorksheetFunction.Min(idx - 1, MAX_SERIES - 1) / (MAX_SERIES - 1)
                t = TRANS_START + (TRANS_END - TRANS_START) * frac
                If t < 0 Then t = 0
                If t > 1 Then t = 1
                .Transparency = t
            End With
            idx = idx + 1
        Next s

        ' データラベルのフォント設定
        For Each series In chart.SeriesCollection
            If series.HasDataLabels Then
                series.DataLabels.Font.Size = fontSize
                series.DataLabels.Font.Bold = False
                series.DataLabels.Font.Color = RGB(0, 0, 0)
            End If
        Next series

        '=== グラフタイトルは使用しない ===
        ' 上部タイトルを無効化
        chart.HasTitle = False
        ' 以前の下部タイトル(BottomTitle)があれば削除
        Dim shp As Shape
        For Each shp In chart.Shapes
            If shp.Name = "BottomTitle" Then
                shp.Delete
                Exit For
            End If
        Next shp
        ' ラベルが詰まりすぎないように、X軸ラベルの更に下に最低パディングを確保
        ' 第2引数は確保したい余白パディング(ポイント)。フォントサイズ係数的 + 余白を足す。
        Call EnsureBottomPadding(chart, fontSize * 0.9 + 8, 0)
    Next chartObj
End Sub

Private Sub SetupLogXAxis(xAx As Axis, minVal As Double, maxVal As Double)
    ' X軸を対数(底10)に設定。値軸の場合のみ MajorUnit=1 を適用。
    ' カテゴリ軸では MajorUnit は設定不可のため、エラーは無視し補助目盛のみ判定する。
    On Error Resume Next
    With xAx
        .ScaleType = xlLogarithmic
        .LogBase = 10
        .MinimumScaleIsAuto = False
        .MaximumScaleIsAuto = False
        .MinimumScale = minVal
        .MaximumScale = maxVal

        ' 値軸(xlValue)なら MajorUnit が設定可。カテゴリ軸ではエラーになるため無視。
        .MajorUnitIsAuto = False
        Err.Clear
        .MajorUnit = 1     ' 1デケード刻み(10^n)
        If Err.Number <> 0 Then
            ' カテゴリ軸など:MajorUnit が非対応 → 何もしない
            Err.Clear
        End If

        ' 補助目盛は Excel の対数仕様(2~9倍)を利用
        .MinorUnitIsAuto = True
        .HasMinorGridlines = True
        .MinorTickMark = xlOutside
        .MajorTickMark = xlOutside

        ' ラベルの書式は参照セルに追従
        .TickLabels.NumberFormatLinked = True
    End With
    On Error GoTo 0
End Sub

Private Function GetChartMaxY(ch As chart) As Double
    Dim s As series
    Dim v As Variant
    Dim curMax As Double
    Dim tmp As Double
    curMax = -1E+308
    On Error Resume Next
    For Each s In ch.SeriesCollection
        v = s.Values
        If IsArray(v) Then
            tmp = Application.WorksheetFunction.Max(v)
        Else
            tmp = CDbl(v)
        End If
        If Err.Number = 0 Then
            If tmp > curMax Then curMax = tmp
        Else
            Err.Clear
        End If
    Next s
    On Error GoTo 0
    If curMax = -1E+308 Then
        curMax = 0  ' フォールバック
    End If
    GetChartMaxY = curMax
End Function

Private Sub EnsureBottomPadding(ch As chart, paddingPts As Single, Optional minPlotHeight As Single = 60)
    On Error Resume Next

    Dim axisBottom As Single
    Dim currentGap As Single
    Dim diff As Single

    ' X軸ラベル最下の位置と、ChartArea底とのギャップを取得
    axisBottom = ch.Axes(xlCategory).Top + ch.Axes(xlCategory).Height
    currentGap = ch.ChartArea.Height - axisBottom

    ' 目標との差分(+:余白が不足、-:余白が過剰)
    diff = paddingPts - currentGap

    ' 微妙な差分は調整不要
    If Abs(diff) <= 0.5 Then GoTo CleanExit

    If diff > 0 Then
        ' --- 余白が足りない:プロットエリアを上に押し上げる(高さを縮める優先) ---
        Dim deltaUp As Single
        deltaUp = diff

        If ch.PlotArea.Height > deltaUp + minPlotHeight Then
            ch.PlotArea.Height = ch.PlotArea.Height - deltaUp
        Else
            ' 最低高を守りつつ分をTopを上に上げて確保
            Dim needMoveUp As Single
            needMoveUp = deltaUp - (ch.PlotArea.Height - minPlotHeight)
            ch.PlotArea.Height = minPlotHeight
            ch.PlotArea.Top = Application.Max(0, ch.PlotArea.Top - needMoveUp)
        End If

    Else
        ' --- 余白が余っている:プロットエリアを下側に拡張^上に移動 ---
        Dim needReduce As Single
        needReduce = -diff   ' 減らしたいギャップ量

        ' 1) まず高さを伸ばしてギャップを埋める
        Dim freeBottom As Single
        Dim grow As Single
        freeBottom = ch.ChartArea.Height - (ch.PlotArea.Top + ch.PlotArea.Height)
        grow = Application.Min(needReduce, Application.Max(0, freeBottom - 1))
        If grow > 0 Then
            ch.PlotArea.Height = ch.PlotArea.Height + grow
            needReduce = needReduce - grow
        End If

        ' 2) まだ余るなら、プロットエリアを下に移動
        If needReduce > 0 Then
            freeBottom = ch.ChartArea.Height - (ch.PlotArea.Top + ch.PlotArea.Height)
            Dim moveDown As Single
            moveDown = Application.Min(needReduce, Application.Max(0, freeBottom - 1))
            If moveDown > 0 Then
                ch.PlotArea.Top = ch.PlotArea.Top + moveDown
            End If
        End If
    End If

CleanExit:
    On Error GoTo 0
End Sub

主要な処理の解説

軸範囲の動的設定

yMax = GetChartMaxY(chart) 
yMaxCeil = WorksheetFunction.Ceiling(yMax, 10)

GetChartMaxY関数で全系列のデータから最大値を取得し、Ceilingで10dB単位に切り上げることで、データに応じた適切なY軸範囲を設定します。

系列の透明度制御

frac = WorksheetFunction.Min(idx - 1, MAX_SERIES - 1) / (MAX_SERIES - 1)
t = TRANS_START + (TRANS_END - TRANS_START) * frac

系列番号に応じて透明度を線形補間(65%→5%)することで、多数の系列を色を変えずに区別可能にします。

実行方法

  1. コードを標準モジュールに貼り付け
  2. グラフを含むシートをアクティブにする
  3. Alt + F8 でマクロ実行ダイアログを開く
  4. ChangeFontSizeAndBold_NoTitle を選択して実行

適用結果

マクロ適用前後の比較

デフォルト設定(適用前)


Excel デフォルト設定のグラフ
これはよくないです。学生実験のレポートでよく見かけますね。

課題:

  • グラフタイトルが不要
  • 軸名が明記されていない
  • x軸ラベルの位置が不自然
  • フォントが小さく可読性が低い
  • グリッド線が太く、データ線より目立つ
  • 軸範囲が自動設定で適切でない
  • 系列の色が派手で論文向きでない

マクロ適用後

Bode Plot of the Tone Control Circuit — Neck Position, Volume Knob
Bode Plot of the Tone Control Circuit — Neck Position, Volume Knob Adjusted

改善点:

  • フォント16pt/18ptで視認性向上
  • グリッド線を薄いグレーに変更し、データ線を強調
  • Y軸範囲を-40dB〜データ最大値+αに自動設定
  • 系列を単色+透明度グラデーションで整理

実際の使用例

このマクロは、以下の測定データ記事で実際に使用しています。

https://zenn.dev/bj_9/articles/6134865b03c8d6

https://zenn.dev/bj_9/articles/1a6c0173af4a5b

複数の測定条件を比較する際に、全グラフで統一したフォーマットを維持できています。

グラフデザインの原則

今回紹介したマクロでは、以下のデザイン原則に基づいてグラフ書式を設定しています。

1. 視覚的階層の構築

要素の太さと濃さで重要度を表現します。

要素 設定 目的
データ線 1.75pt、濃紺 <u>最も目立たせる</u>
軸線 1.25pt、RGB(120,120,120) 枠組みを示す
主グリッド線 0.5pt、RGB(160,160,160) 目盛りを補助
補助グリッド線 0.5pt、RGB(225,225,225) さらに控えめ

データそのものに視覚的重みを置くことを意識しましょう。グリッド線は必要でなければ外しても構いません。

2. 単色+透明度グラデーション

系列が多い場合(10本以上)、色分けではなく透明度で区別します。

利点:

  • モノクロ印刷でも判別可能
  • カラーユニバーサルデザインに対応
  • フォーマルな印象を維持

注意:系列が交わる場合は、この手法は適していません。交わる場合は系列数を減らして色分けしましょう。

3. 対数軸での目盛り設計

周波数軸(X軸)は対数表示とし、以下を設定します。

  • 主目盛:1デケード刻み(10, 100, 1000, 10000 Hz)
  • 補助目盛:対数の標準刻み(2, 3, 4, ..., 9の倍数)
  • 範囲:10Hz〜20kHz(可聴域をカバー)

[!hint]
周波数軸は対数とすることが原則です。

4. フォントサイズの最適化

用途に応じたフォントサイズを設定します。

用途 軸ラベル 軸タイトル 根拠
論文・記事 16pt 18pt Web表示(800×500px)で可読
プレゼン 24pt 27pt スライド投影時の視認性

太字は視覚的に煩雑になるため使用しない方が良いです。

5. グラフタイトルの省略

グラフ内のタイトルは設けず、キャプションで説明します。

根拠:

  • 学術論文の標準的な形式(図番号+キャプション)に準拠
  • グラフ内スペースをデータ表示領域に充てる

6. 動的な軸範囲設定

Y軸範囲はデータに応じて自動調整します。

yMax = GetChartMaxY(chart)
yMaxCeil = WorksheetFunction.Ceiling(yMax, 10)
.MinimumScale = -40  ' 固定値
.MaximumScale = yMaxCeil  ' データ依存

方針:

  • 最小値:-40dB固定(S/N比の下限から決定すると良い)
  • 最大値:データ最大値を10dB単位で切り上げ

これにより、データの変動範囲に応じた適切なスケールを自動設定できます。

プロンプト設計

LLMに効果的なVBAコードを生成させるには、明確で具体的なプロンプトが必要です。

プロンプトの構成要素

以下の4要素を含めることで、期待通りのコードが得られます。

1. 目的の明示

Excel VBAで、周波数応答グラフを科学論文品質にフォーマットするマクロを作成

2. 技術仕様

- X軸: 対数スケール(10Hz〜20kHz)、グレー軸線 RGB(120,120,120)
- Y軸: 線形スケール(-40dB〜自動上限)、10dB刻み主目盛、5dB刻み補助目盛

3. 処理要件

- アクティブシート内の全グラフに一括適用
- Y軸最大値はデータから自動算出し、10dB単位で切り上げ

4. エラーハンドリング

- 対数軸設定時のカテゴリ軸エラーを適切に処理
- グラフが存在しない場合はスキップ

プロンプト例(簡潔版)

Excel VBAで、周波数応答グラフを科学論文品質にフォーマットするマクロを作成してください。

仕様:
- X軸: 対数(10-20000 Hz)、グレー軸線(RGB 120,120,120)
- Y軸: 線形(-40~自動上限 dB)、10dB刻み主目盛、5dB刻み補助目盛
- グリッド: 主(RGB 160,160,160)、補助(RGB 225,225,225)
- 系列: 全て濃紺(RGB 10,62,85)、透明度は1番目65%→11番目5%でグラデーション
- フォント: 軸ラベル16pt、軸タイトル18pt、全て非太字
- グラフタイトルなし、X軸下に適切な余白を自動確保

アクティブシート内の全グラフに一括適用。
エラーハンドリングを含め、堅牢な実装にしてください。

一度に完璧なコードを生成しなくても、段階的に機能を追加することもできるので、まずは思いつく範囲で書いてみましょう。

実装後の調整

生成されたコードを実行して確認し、必要に応じてフィードバックします。
LLMに適切にコメントアウトを書かせてコードの可読性を上げておいた上で、数値の変更程度であれば自力で修正すると良いです。

まとめ

AI + VBAを使えば、プログラミング経験がなくても論文品質のグラフを量産できます。
プロンプトの書き方には少しコツが要りますが、一度覚えてしまえばスムーズです。
測定データのグラフ化で困っている方は、ぜひ試してみてください。

Discussion