皆さん、こんにちは!Excel VBAでクリエイティブな世界を切り拓く、ベテランVBA講師です。
前回の講座では、植物の「根」の表現に挑戦しました。複雑な形状ながらも、VBAの描画機能を使えば意外と簡単に、そして個性豊かに表現できることを実感していただけたのではないでしょうか。
さて、本日からはいよいよ植物の生命を支え、光合成を担う重要な要素、「茎(くき)」と「葉(は)」の描画に挑みます。この二つは植物の姿を形作る上で、最も目につきやすく、その植物らしさを決定づける部分と言えるでしょう。
植物の茎や葉は、その種類によって驚くほど多様な形、太さ、質感、そして生え方をしています。今回は、その中でも特に基本となる「まっすぐな茎」と、最も一般的な「単葉(たんよう)」の描画に焦点を当て、その描画の基本と応用について、3回に分けてじっくりと学んでいきましょう。
### 1. 茎の描画:直線の基本と応用
植物の茎は、その植物の骨格となる部分です。太さや形状は植物の種類によって様々ですが、まずは最も基本的な「まっすぐな茎」の描画から始めます。VBAで直線を引くことは非常に簡単ですが、そこに「太さ」や「色」、「質感」といった要素を加えていくことで、よりリアルな茎を表現できるようになります。
#### 1.1. 基本的な直線の描画
VBAで図形を描画するには、`ActiveSheet.Shapes.AddLine` メソッドを使用します。このメソッドには、始点と終点の座標を指定する必要があります。
Sub DrawBasicStem()
Dim ws As Worksheet
Set ws = ActiveSheet
‘ 始点 (x1, y1) と 終点 (x2, y2) の座標を指定
‘ Excelの座標系は左上が原点(0,0)で、右方向がX軸、下方向がY軸
Dim x1 As Single, y1 As Single
Dim x2 As Single, y2 As Single
x1 = 100 ‘ 開始X座標
y1 = 300 ‘ 開始Y座標
x2 = 100 ‘ 終了X座標 (まっすぐなのでX座標は同じ)
y2 = 100 ‘ 終了Y座標 (上に向かって伸びる茎)
‘ 直線を描画
Dim stemLine As Shape
Set stemLine = ws.Shapes.AddLine(x1, y1, x2, y2)
‘ 線のプロパティを設定
With stemLine.Line
.ForeColor.RGB = RGB(100, 150, 50) ‘ 緑がかった茶色
.Weight = 3 ‘ 線の太さ (ポイント単位)
End With
End Sub
このコードを実行すると、指定した座標に緑がかった茶色の線が描画されます。`ws.Shapes.AddLine(x1, y1, x2, y2)` の引数で、線の始点と終点の座標を指定します。座標はExcelシート上のポイント単位で、左上が (0, 0) となります。`stemLine.Line.ForeColor.RGB` で線の色を、`stemLine.Line.Weight` で線の太さを設定できます。
#### 1.2. 茎の太さの変化と質感の表現
植物の茎は、常に一定の太さとは限りません。根元に近い部分は太く、先端に向かうにつれて細くなるのが一般的です。また、単なる直線ではなく、少しの歪みや節(ふし)があることで、より自然な見た目になります。
**太さの変化:**
太さを変化させるには、複数の直線を重ねたり、あるいは「円」や「楕円」を組み合わせて表現する方法が考えられます。しかし、より簡単なのは、太さを段階的に変えながら描画していくことです。
Sub DrawVaryingStem()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim startX As Single, startY As Single
Dim endX As Single, endY As Single
Dim currentWeight As Single
Dim numSegments As Integer
Dim segmentLength As Single
Dim xStep As Single
startX = 150
startY = 400
endY = 100
currentWeight = 5 ‘ 開始の太さ
numSegments = 10 ‘ 分割数
segmentLength = (startY – endY) / numSegments
xStep = 5 ‘ X座標のわずかな変化 (茎の曲がりを表現)
Dim i As Integer
Dim currentX As Single, currentY As Single
currentX = startX
currentY = startY
For i = 1 To numSegments
Dim nextX As Single, nextY As Single
Dim nextWeight As Single
nextY = startY – (segmentLength * i)
‘ X座標をわずかに変化させる (右にカーブさせる例)
nextX = startX + (xStep * i / numSegments)
‘ 先端に向かうにつれて細くする
nextWeight = currentWeight * (1 – (i / numSegments) * 0.7) ‘ 70%まで細くする例
Dim stemSegment As Shape
Set stemSegment = ws.Shapes.AddLine(currentX, currentY, nextX, nextY)
With stemSegment.Line
.ForeColor.RGB = RGB(80, 120, 40) ‘ 少し濃い緑
.Weight = nextWeight
End With
currentX = nextX
currentY = nextY
currentWeight = nextWeight ‘ 次のセグメントの開始太さを更新
Next i
End Sub
このコードでは、茎を複数の短い線分に分割し、それぞれの線分の太さやX座標を変化させています。これにより、根元が太く先端が細い、わずかにカーブした茎を表現できます。`nextWeight` の計算で、`currentWeight * (1 – (i / numSegments) * 0.7)` のように、線形補間を用いて太さを徐々に細くしています。X座標の `xStep` を調整することで、カーブの度合いも変更可能です。
**質感の表現:**
茎の質感は、線の色合いや太さだけでなく、微妙な「揺らぎ」や「節」の表現で向上します。
例えば、`Rnd` 関数を使って座標にランダムなオフセットを加えることで、茎の自然な歪みを表現できます。
Sub DrawWavyStem()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim startX As Single, startY As Single
Dim endX As Single, endY As Single
Dim currentWeight As Single
Dim numSegments As Integer
Dim segmentLength As Single
Dim xOffsetRange As Single ‘ X座標の揺らぎの範囲
Dim yOffsetRange As Single ‘ Y座標の揺らぎの範囲
startX = 200
startY = 450
endY = 150
currentWeight = 6
numSegments = 15
segmentLength = (startY – endY) / numSegments
xOffsetRange = 3 ‘ X方向の揺らぎ
yOffsetRange = 1 ‘ Y方向の揺らぎ
Dim i As Integer
Dim currentX As Single, currentY As Single
currentX = startX
currentY = startY
For i = 1 To numSegments
Dim nextX As Single, nextY As Single
Dim nextWeight As Single
nextY = startY – (segmentLength * i)
‘ ランダムなオフセットを加える
nextX = startX + (i * 5 / numSegments) + (Rnd() – 0.5) * xOffsetRange
nextY = nextY + (Rnd() – 0.5) * yOffsetRange
nextWeight = currentWeight * (1 – (i / numSegments) * 0.6)
Dim stemSegment As Shape
Set stemSegment = ws.Shapes.AddLine(currentX, currentY, nextX, nextY)
With stemSegment.Line
.ForeColor.RGB = RGB(70, 110, 30)
.Weight = nextWeight
End With
currentX = nextX
currentY = nextY
currentWeight = nextWeight
Next i
‘ 節(ふし)の表現 (オプション)
‘ 特定のセグメントの終点に円を描画するなど
Dim節Position As Integer
節Position = Int(numSegments / 3) ‘ 例: 3分の1の位置に節を作る
Dim節X As Single, 節Y As Single
‘ 最後のセグメントの終点の座標を取得
Dim lastSegment As Shape
Set lastSegment = ws.Shapes(ws.Shapes.Count) ‘ 直前に描画した線を取得
節X = lastSegment.Left + lastSegment.Width * (i – 1) / numSegments ‘ 最後のセグメントの終点X
節Y = lastSegment.Top + lastSegment.Height * (i – 1) / numSegments ‘ 最後のセグメントの終点Y
‘ 実際にはループ内で各セグメントの終点を記録しておき、指定した位置の終点座標を取得する必要があります。
‘ ここでは簡略化のため、最後のセグメントの終点付近に描画します。
Dim節Circle As Shape
‘ 節の位置を計算 (より正確にはループ内で各セグメントの終点を保持しておく)
Dim節XPos As Single, 節YPos As Single
‘ 仮に、最後のセグメントの終点座標を基に節の位置を決定
節XPos = currentX ‘ ループ終了時のcurrentXが最後のセグメントの終点X
節YPos = currentY ‘ ループ終了時のcurrentYが最後のセグメントの終点Y
Set節Circle = ws.Shapes.AddShape(msoShapeOval, 節XPos – 3, 節YPos – 3, 6, 6) ‘ 節の円
With節Circle.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(70, 110, 30) ‘ 節の色
End With
With節Circle.Line
.Visible = msoFalse ‘ 枠線を非表示
End With
End Sub
`Rnd()` 関数は0から1の間の乱数を返します。これにオフセット範囲を掛け、さらに `0.5` を引くことで、中心からのプラスマイナス両方向へのランダムな移動を表現できます。節の表現は、特定の箇所に小さな円や楕円を描画することで、視覚的なアクセントとなります。ただし、上記の節の座標計算は簡略化しており、正確な節の位置を表現するには、各セグメントの終点を配列などに記録しておく必要があります。
### 2. 単葉(たんよう)の描画:基本形とバリエーション
植物の葉は、光合成を行う主要な器官であり、その形状は非常に多様です。今回は、最も基本的な「単葉」の描画に焦点を当てます。単葉とは、一枚の葉身(ようしん)からできている葉のことです。
#### 2.1. 基本的な単葉の描画(楕円形)
最もシンプルな単葉は、楕円形や卵形です。VBAでは `ActiveSheet.Shapes.AddShape` メソッドで様々な図形を描画できます。
Sub DrawBasicLeaf()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim leafX As Single, leafY As Single
Dim leafWidth As Single, leafHeight As Single
leafX = 100 ‘ 葉の左上の座標
leafY = 150
leafWidth = 50
leafHeight = 80
‘ 楕円形を描画 (葉の基本形)
Dim leafShape As Shape
Set leafShape = ws.Shapes.AddShape(msoShapeOval, leafX, leafY, leafWidth, leafHeight)
‘ 塗りつぶしの設定
With leafShape.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(50, 180, 70) ‘ 鮮やかな緑
.BackColor.RGB = RGB(50, 180, 70) ‘ 背景色と同じにすることで単色に
.GradientStyle = msoGradientLinear ‘ グラデーションを設定 (オプション)
.GradientVariant = 1
.GradientDegree = 0.5
End With
‘ 枠線の設定
With leafShape.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(30, 100, 40) ‘ 少し濃い緑
.Weight = 1 ‘ 線の太さ
End With
End Sub
このコードでは、`msoShapeOval` を使用して楕円形を描画しています。`leafX`, `leafY`, `leafWidth`, `leafHeight` で楕円の位置と大きさを指定します。`leafShape.Fill` で塗りつぶしの色やグラデーションを、`leafShape.Line` で枠線の色や太さを設定できます。グラデーションを加えることで、葉に立体感や光沢感を出すことができます。
#### 2.2. 葉の形状のバリエーション:卵形、心形、槍形など
葉の形は楕円形だけではありません。卵形(たまごがた)、心形(しんけい)、槍形(やりがた)など、様々な形状があります。これらの形状は、基本的な楕円形を基にして、頂点座標を操作することで表現できます。
VBAで複雑な形状を描画するには、`AddPolyline` や `AddShape` メソッドで多角形を描画し、その頂点を編集する方法が有効です。あるいは、より高度な方法として、`Canvas` オブジェクトや `Freeform` 図形を利用することもできます。
ここでは、`AddCurve` メソッドを使用して、なめらかな曲線で構成される葉を描画する例を示します。`AddCurve` メソッドは、複数の制御点を持つベジェ曲線を描画します。
Sub DrawCurvedLeaf()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim leafBaseX As Single, leafBaseY As Single
leafBaseX = 150
leafBaseY = 200
‘ 葉の頂点座標の配列
‘ 葉の基点、先端、左右の膨らみ、そして再び基点に戻るように定義
Dim leafPoints() As Single
‘ 葉の形状を定義する座標 (例: 卵形に近い形状)
‘ 座標は (x1, y1, x2, y2, x3, y3, x4, y4, …) の形式で指定
‘ ここでは、左右対称の卵形を想定し、ベジェ曲線で描画します。
‘ 葉の先端、葉の付け根、そして左右の膨らみを制御する制御点を設定します。
‘ 座標の単位はポイントです。
leafPoints = Array( _
leafBaseX, leafBaseY, _ ‘ 葉の付け根 (開始点)
leafBaseX + 20, leafBaseY – 50, _ ‘ 左側の制御点1
leafBaseX + 50, leafBaseY – 100, _ ‘ 左側の制御点2 (葉の先端付近)
leafBaseX + 60, leafBaseY – 80, _ ‘ 葉の先端 (終点)
leafBaseX + 50, leafBaseY – 60, _ ‘ 右側の制御点1 (葉の先端付近)
leafBaseX + 20, leafBaseY – 10, _ ‘ 右側の制御点2
leafBaseX, leafBaseY _ ‘ 葉の付け根 (終了点、始点に戻る)
)
‘ ベジェ曲線を描画
Dim leafCurve As Shape
Set leafCurve = ws.Shapes.AddCurve(leafPoints)
‘ 線のプロパティを設定 (輪郭線)
With leafCurve.Line
.ForeColor.RGB = RGB(30, 100, 40)
.Weight = 1.5
End With
‘ 塗りつぶしの設定
With leafCurve.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(60, 190, 80) ‘ 葉の色
.BackColor.RGB = RGB(60, 190, 80)
.GradientStyle = msoGradientLinear
.GradientVariant = 1
.GradientDegree = 0.3
End With
‘ 葉脈の描画 (オプション)
‘ 中心となる葉脈を描画
Dim midribX() As Single, midribY() As Single
midribX = Array(leafBaseX, leafBaseX + 30, leafBaseX + 40)
midribY = Array(leafBaseY, leafBaseY – 50, leafBaseY – 80)
Dim midribPoints() As Single
ReDim midribPoints(0 To 5)
midribPoints(0) = midribX(0): midribPoints(1) = midribY(0)
midribPoints(2) = midribX(1): midribPoints(3) = midribY(1)
midribPoints(4) = midribX(2): midribPoints(5) = midribY(2)
Dim midribLine As Shape
Set midribLine = ws.Shapes.AddCurve(midribPoints)
With midribLine.Line
.ForeColor.RGB = RGB(40, 120, 50) ‘ 葉脈の色
.Weight = 0.7
End With
‘ 葉脈の塗りつぶしは不要なので非表示
midribLine.Fill.Visible = msoFalse
‘ 副葉脈の描画 (さらに複雑な表現)
‘ ここでは省略しますが、同様に AddCurve や AddLine を複数回使用して表現できます。
End Sub
`AddCurve` メソッドでは、座標の配列を指定してベジェ曲線を描画します。配列は `(x1, y1, x2, y2, x3, y3, …)` の形式で、各3つの点は曲線の一部を定義します。最初の2つの点は始点と終点、それ以外の点は制御点となります。これらの点を調整することで、様々な形状の葉を描画できます。
葉脈の描画も、中心の葉脈(中肋、ちゅうろく)から枝分かれするように、細い線や曲線を描き足していくことで、よりリアルな表現が可能になります。
#### 2.3. 葉の生え方と配置
茎から葉が生える位置や角度は、植物のシルエットを決定づける重要な要素です。単葉の場合、一般的には「互生(ごせい)」、「対生(たいせい)」、「輪生(りんせい)」といった生え方があります。
* **互生:** 一つの節から一本の葉が出る。
* **対生:** 一つの節から二枚の葉が向かい合って出る。
* **輪生:** 一つの節から三枚以上の葉が輪状に出る。
これらの生え方を考慮して、葉を配置することで、より自然な植物のイラストになります。
Sub ArrangeLeavesOnStem()
Dim ws As Worksheet
Set ws = ActiveSheet
‘ 茎を描画 (ここでは簡略化のため、既に描画されていると仮定)
‘ 実際には、茎の描画コードをここに含めるか、別のSubを呼び出します。
‘ 例: Call DrawWavyStem
‘ 葉の生え方をシミュレーション (互生)
Dim numLeaves As Integer
Dim stemStartX As Single, stemStartY As Single ‘ 茎の開始点
Dim stemEndX As Single, stemEndY As Single ‘ 茎の終了点
Dim stemHeight As Single
‘ 仮の茎の情報を取得 (実際には描画した茎の情報を取得する必要がある)
‘ ここでは例として固定値を使用
stemStartX = 150
stemStartY = 450
stemEndY = 150
stemHeight = stemStartY – stemEndY
numLeaves = 5 ‘ 葉の枚数
Dim i As Integer
Dim leafAngle As Single
Dim leafDistance As Single
Dim leafPos As Single ‘ 茎上の葉の位置 (0から1)
For i = 1 To numLeaves
‘ 葉の位置を茎の長さに沿って配置
leafPos = 0.2 + (i – 1) / (numLeaves – 1) * 0.6 ‘ 茎の下部から上部にかけて配置 (0.2から0.8の間)
‘ 葉のY座標を計算
Dim leafY As Single
leafY = stemStartY – (stemHeight * leafPos)
‘ 茎のX座標を計算 (茎がわずかにカーブしている場合)
‘ ここでは単純化のため、茎のX座標は一定と仮定
Dim leafX As Single
leafX = stemStartX
‘ 葉の角度を計算 (互生なので、少しずつ回転させる)
