エクセルマクロ・VBA達人養成塾 小川です。
昨日のブログに書いた、「フォーカス・リーディング」の寺田昌嗣さんから依頼されて作ったマクロ。公開します。
ソースはこんな感じ↓。
Option Explicit
'テストモード制御定数。納品時はすべて False にすること。
Const B_TEST As Boolean = False
Const B_SHOW As Boolean = False
Const B_NOPRINT As Boolean = False
Const S_LEVELBASE = "A7"
Const I_OFFSET = 4 '2つの表の間が何行あるか。表の最後から、次の表のラベルまでの行数を書く
Dim rLev As Range
Dim sz As Long
Dim mj As Boolean
Dim fs As Double
Dim fx As Long
Dim ma As Long
Dim nm As String
Dim cf As String
Dim ct As Long
Dim pn As String
Dim fl As String
Dim ht As Double
Dim wt As Double
Dim kt As String
Public Sub main()
Randomize
Set rLev = Range("LEVELBASE").Offset(Range("LEVEL").Value)
With rLev
sz = .Offset(, 1).Value
mj = .Offset(, 2).Value
End With
fs = Range("SMALL").Value
fx = Range("LARGE").Value
nm = Range("CELLFONT").Value
ma = Range("REPEAT").Value
ct = Range("COPIES").Value
pn = Range("PRINTERNAME").Value
fl = Range("LEVELFONT").Value
ht = Range("CELLHEIGHT").Value
wt = Range("CELLWIDTH").Value
cf = Range("SCOREFONT").Value
kt = Range("KITEN").Value
Dim c As Long
For c = 1 To ma
MainRoutine c
Next
End Sub
Private Sub MainRoutine(kazu As Long)
Dim a As Application
Set a = Application
Dim s As Worksheet
Set s = spre
With s
a.ScreenUpdating = B_SHOW
With .UsedRange
.ClearContents
.ClearFormats
.RowHeight = s.StandardHeight
.ColumnWidth = s.StandardWidth
End With
SetHyo .Range(kt), kazu * 2 - 1
SetHyo .Range(kt).Offset(sz * 2 + I_OFFSET + 1), kazu * 2
a.ScreenUpdating = True
With .PageSetup
.FitToPagesWide = 1
.FitToPagesTall = 1
.CenterHorizontally = True
.CenterVertically = True
If Not B_TEST And Not B_NOPRINT Then
.Parent.PrintOut Copies:=ct, ActivePrinter:=pn, Collate:=True
End If
End With
End With
End Sub
Private Sub SetHyo(rBs As Range, num As Long)
With rBs
.Value = "【LEVEL " & rLev.Value & "-" & num & "】"
.Font.Name = fl
.Font.Size = fs
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
End With
Set rBs = rBs.Offset(2)
With rBs
With Range(.Offset(0, 0), .Offset(sz * 2 + 2, sz * 2 - 1))
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.Font.Size = fs
.RowHeight = ht
.ColumnWidth = wt
.Font.Name = nm
End With
With Range(.Offset(sz * 2 + 1, 0), .Offset(sz * 2 + 1, sz * 2 - 1))
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.MergeCells = True
.Font.Name = cf
Select Case sz
Case 4
.Value = "1回目( )秒 2回目( )秒 3回目( )秒"
Case 5
.Value = "1回目( )秒 2回目( )秒 3回目( )秒"
Case 6
.Value = "1回目( )秒 2回目( )秒 3回目( )秒"
Case 7
.Value = "1回目( )秒 2回目( )秒 3回目( )秒"
End Select
.ShrinkToFit = True
End With
Dim c As Long
For c = 0 To sz ^ 2 - 1
SetFormatValue rLev, .Offset((c \ sz) * 2, (c Mod sz) * 2), fx
Next
Dim rA As Range
Set rA = .Offset((0 \ sz) * 2, (0 Mod sz) * 2)
For c = 0 To sz ^ 2 - 1
Set rA = Union(rA, .Offset((c \ sz) * 2, (c Mod sz) * 2))
Next
Dim r As Range
c = 0
With rand
SetNumList .Range("A1"), sz ^ 2, mj
For Each r In rA
SetEntry r, .Range("A1").Offset(c + 1).Value
c = c + 1
Next
End With
End With
End Sub
Private Sub SetFormatValue(rL As Range, rTgt As Range, fxx As Long)
Dim cLev(2) As Long
With rL
cLev(0) = .Offset(, 3).Value
cLev(1) = .Offset(, 4).Value
cLev(2) = .Offset(, 5).Value
End With
Select Case Int((cLev(0) + cLev(1) + cLev(2)) * Rnd + 1)
Case 0 To cLev(0)
rTgt.Font.Size = fxx
Case cLev(0) + 1 To cLev(0) + cLev(1)
Case cLev(0) + cLev(1) + 1 To cLev(0) + cLev(1) + cLev(2)
Nuri rTgt
End Select
End Sub
Private Sub Nuri(rT As Range)
Dim b2 As Boolean
Dim rBlack As Range
Dim num As Long
b2 = Rnd() * 2 > 1
With rand
SetNumList .Range("D1"), 4, mj
num = .Range("D1").Offset(1).Value - 1
Set rBlack = rT.Offset(num \ 2, num Mod 2)
If b2 Then
num = .Range("D2").Offset(1).Value - 1
Set rBlack = Union(rBlack, rT.Offset(num \ 2, num Mod 2))
End If
rBlack.Interior.Color = vbBlack
End With
End Sub
Private Function Neco(r1 As Range, r2 As Range) As Range
Set Neco = IIf(Rnd() > 0.5, r1, r2)
End Function
'Private Function Mg(r1 As Range, r2 As Range) As Range
' Set Mg = Range(r1, r2)
' Range(r1, r2).MergeCells = True
'End Function
Private Function IsBk(rT As Range) As Boolean
IsBk = rT.Interior.Color = vbBlack
End Function
Private Function CountBk(rA As Range) As Integer
Dim c As Boolean
Dim r As Range
Dim rRet As Range
For Each r In rA
If IsBk(r) Then
If rRet Is Nothing Then
Set rRet = r
Else
Set rRet = Union(rRet, r)
End If
End If
Next
If rRet Is Nothing Then
CountBk = 0
Else
CountBk = rRet.Count
End If
End Function
Private Sub SetEntry(rg As Range, v As Variant)
Dim rAll As Range
Dim rA(3) As Range
With rg
Set rA(0) = .Offset(0, 0)
Set rA(1) = .Offset(1, 0)
Set rA(2) = .Offset(0, 1)
Set rA(3) = .Offset(1, 1)
Set rAll = Range(rA(0), rA(3))
End With
With rAll
Kei .Borders(xlEdgeLeft), .Borders(xlEdgeTop), .Borders(xlEdgeBottom), .Borders(xlEdgeRight)
End With
Dim rRet As Range
Select Case CountBk(rAll)
Case 0
Set rRet = rAll
Case 1
If IsBk(rA(0)) Or IsBk(rA(3)) Then
Set rRet = IIf( _
IsBk(rA(0)), _
Range(Neco(rA(1), rA(2)), rA(3)), _
Range(Neco(rA(1), rA(2)), rA(0)) _
)
'↓以下ではバグが発生した
' Set rRet = IIf( _
' IsBk(rA(0)), _
' Mg(Neco(rA(1), rA(2)), rA(3)), _
' Mg(Neco(rA(1), rA(2)), rA(0)) _
' )
Else
Set rRet = IIf( _
IsBk(rA(1)), _
Range(Neco(rA(0), rA(3)), rA(2)), _
Range(Neco(rA(0), rA(3)), rA(1)) _
)
End If
Case 2
If IsBk(rA(0)) And IsBk(rA(3)) Then
Set rRet = Neco(rA(1), rA(2))
ElseIf IsBk(rA(1)) And IsBk(rA(2)) Then
Set rRet = Neco(rA(0), rA(3))
ElseIf Not IsBk(rA(0)) Then
Set rRet = IIf( _
IsBk(rA(1)), _
Range(rA(0), rA(1)), _
Range(rA(0), rA(2)) _
)
'↓以下ではバグが発生した
' Set rRet = IIf( _
' IsBk(rA(1)), _
' Mg(rA(0), rA(1)), _
' Mg(rA(0), rA(2)) _
' )
Else
Set rRet = IIf( _
IsBk(rA(1)), _
Range(rA(2), rA(3)), _
Range(rA(1), rA(3)) _
)
End If
End Select
With rRet
If .Count > 1 Then
.MergeCells = True
End If
.Value = v
End With
End Sub
Private Sub Kei(ParamArray ba() As Variant)
Dim b As Variant
For Each b In ba
With b
.LineStyle = xlContinuous
.ColorIndex = xlAutomatic
.Weight = xlMedium
End With
Next
End Sub
Private Sub SetNumList(rBs As Range, mx As Long, tpe As Boolean)
Dim c As Long
With rBs
.CurrentRegion.Offset(1).ClearContents
For c = 1 To mx
.Offset(c, 0).Value = IIf(tpe, c, .Offset(c, 6).Value)
.Offset(c, 1).Value = Int(Rnd * mx * 1000) + 1
Next
.Sort Key1:=.Offset(, 1), Order1:=xlAscending, Header:=xlYes
End With
End Sub
↑「以下ではバグが発生した」のところについて補足すると…。
詳しくは調べていないのですが、Iif 関数の第二引数内でセルを結合させるメソッド(VBAではプロパティ扱いですが、やってることはメソッドですね (^^; )を含めると、Iif関数の真偽の値が反転するか、必ず真になるかするようです。
マニアックな話題ですが、そのうち気が向いたらもっと調査したいと思います。
バグなんじゃないかな。