平成30年度秋期基本情報技術者_表計算のマクロをExcelVBAで再現する
目次
1.出典
2.問題で使用するExcelシート「来店状況」のダミーデータの簡単な作り方
3.問題文の要旨
4.問題文(疑似言語)
5.解答群(疑似言語)
6.問題文(VBA翻訳)
7.VBA翻訳の補足説明
8.解答群(VBA翻訳)
9.正解
10.正解を入れたVBA完全版 ※動作確認済み
11.2次元配列バージョン ※動作確認済み
12.バックナンバー
13.ExcelVBA講座ご紹介
1.出典
経済産業省国家試験(IPA情報処理推進機構)
平成30年度秋期 基本情報技術者試験 午後試験 選択問題 問13表計算設問3[解答欄e~g]
なお、試験問題及び正解の著作権はIPA情報処理推進機構に帰属します。
2.問題で使用するExcelシート「来店状況」の簡単な作り方
・セルB1:1~8の整数(任意)
・セルA3:連番で最大250番まで
・セルB3:午前10時以降の時刻
・セルB4以降:=B3+INT(RAND()*10+1)/24/60
・セルC3以降:=CHOOSE(INT(RAND()*3+1),"A","B","C")
・セルF3以降:=INT(RAND()*15+5)/24/60
・セルG3以降:=IF(A3="","",E3+F3)
・B、C、F、G列の表示形式は「h:mm」
・ただし、B、C、F列はRand()を使ってダミーのデータを入力しているので値の貼り付けをして数式を消しておくこと。
3.問題文の要旨
Excelシート「来店状況」で、受付をした順(A列)に窓口でサービスを提供する。窓口番号(D列)は1番から窓口数(セルB1)までの整数とする。
窓口が複数空いていたら窓口番号の最も小さい窓口で対応する。受付時刻に窓口が空いていれば、受付時刻をそのままサービス開始時刻(E列)とすればよいが、窓口が空いていない場合は早く終わりそうな窓口が終了する時刻(終了時刻G列の最小値)をサービス開始時刻とする。マクロを用いてD列およびE列を求めたい。
4.問題文(疑似言語)
[マクロ:queue_simulation]
〇マクロ:queue_simulation
〇数値型:i, work_line, sw, end_time[9], min_time, min_no
■ i: 1, i <= B1, 1
|・end_time[i] ← 0
■
・work_line ← 1
・sw ← 0
■ 論理積(sw = 0, work_line <= 250)
|・min_no ← 1
|・min_time ← end_time[1]
|■ i: 2, i <= B1, 1
||▲ [ 解答欄e ]
|||・min_time ← end_time[i]
|||・min_no ← i
||▼
|■
|・相対(A2, work_line, 3) ← [ 解答欄f ]
|▲ 相対(A2, work_line, 1) > min_time
||・相対 (A2, work_line, 4) ← 相対 (A2, work_line, 1)
|+-----
||・相対 (A2, work_line, 4) ← min_time
|▼
|・[ 解答欄g ]
|・work_line ← work_line + 1
|▲ 相対(A2, work_line, 0) = null
||・sw ← 1
|▼
■
5.解答群(疑似言語)
eに関する解答群
ア min_time < end_time[i]
イ min_time < end_time[min_no]
ウ min_time < 相対(A2, work_line, 1)
エ min_time > end_time[i]
オ min_time > end_time[min_no]
カ min_time > 相対(A2, work_line, 1)
fに関する解答群
ア end_time[i]
イ end_time[min_no]
ウ i
エ min_no
オ min_time
カ work_line
gに関する解答群
ア end_time[min_no] ← min_time
イ end_time[min_no] ← 相対(A2, work_line, 4)
ウ end_time[min_no] ← 相対(A2, work_line, 6)
エ end_time[work_line] ← min_time
オ end_time[work_line] ← 相対(A2, work_line, 4)
カ end_time[work_line] ← 相対(A2, work_line, 6)
6.問題文(VBA翻訳)
Sub queue_simulation()
Dim i As Integer, work_line As Integer, sw As Integer, min_no As Integer
Dim end_time(8) As Single, min_time As Single
For i = 1 To Range("B1")
end_time(i) = 0
Next
work_line = 1
sw = 0
Do While sw = 0 And work_line <= 250
min_no = 1
min_time = end_time(1)
For i = 2 To Range("B1")
If [ 解答欄e ] Then
min_time = end_time(i)
min_no = i
End If
Next
Range("A2").Offset(work_line, 3) = [ 解答欄f ]
If Range("A2").Offset(work_line, 1) > min_time Then
Range("A2").Offset(work_line, 4) = Range("A2").Offset(work_line, 1)
Else
Range("A2").Offset(work_line, 4) = min_time
End If
[ 解答欄g ]
work_line = work_line + 1
If Range("A2").Offset(work_line, 0) = "" Then
sw = 1
End If
Loop
End Sub
7.VBA翻訳の補足説明
・数値型については、時間だけSingle、それ以外はIntegerにしています。
・要素番号0~8の配列は、疑似言語はend_time[9]と宣言しますが、VBAではend_time(8)となります。
・「相対(A2,」は「Range("A2").Offset(」と訳します。
8.解答群(VBA翻訳)
eに関する解答群
ア min_time < end_time(i)
イ min_time < end_time(min_no)
ウ min_time < Range("A2").Offset(work_line, 1)
エ min_time > end_time(i)
オ min_time > end_time(min_no)
カ min_time > Range("A2").Offset(work_line, 1)
fに関する解答群
ア end_time(i)
イ end_time(min_no)
ウ i
エ min_no
オ min_time
カ work_line
gに関する解答群
ア end_time(min_no) = min_time
イ end_time(min_no) = Range("A2").Offset(work_line, 4)
ウ end_time(min_no) = Range("A2").Offset(work_line, 6)
エ end_time(work_line) = min_time
オ end_time(work_line) = Range("A2").Offset(work_line, 4)
カ end_time(work_line) = Range("A2").Offset(work_line, 6)
9.正解
e エ
(次の行にmin_time=end_time(i)と書いてあるのだから、「最小値が更新されたら」という条件式になるのは当たり前)
f エ
(その前のループでmin_no = iを求めているのだから、min_noを代入しなかったら求めた意味がない)
g ウ
(end_time=終了_時刻 はG列に書いてあるし、end_time(8)なのに250まであるwork_lineが添え字になるわけがない)
10.正解を入れたVBA完全版 ※動作確認済み
Sub queue_simulation()
Dim i As Integer, work_line As Integer, sw As Integer, min_no As Integer
Dim end_time(8) As Single, min_time As Single
For i = 1 To Range("B1")
end_time(i) = 0
Next
work_line = 1
sw = 0
Do While sw = 0 And work_line <= 250
min_no = 1
min_time = end_time(1)
For i = 2 To Range("B1")
If min_time > end_time(i) Then
min_time = end_time(i)
min_no = i
End If
Next
Range("A2").Offset(work_line, 3) = min_no
If Range("A2").Offset(work_line, 1) > min_time Then
Range("A2").Offset(work_line, 4) = Range("A2").Offset(work_line, 1)
Else
Range("A2").Offset(work_line, 4) = min_time
End If
end_time(min_no) = Range("A2").Offset(work_line, 6)
work_line = work_line + 1
If Range("A2").Offset(work_line, 0) = "" Then
sw = 1
End If
Loop
End Sub
11.2次元配列バージョン ※動作確認済み
表計算の問題なのに2次元配列を使わないのはいかがなものかと思いましたので、問題の趣旨を変えないまま2次元配列に置き換えてみました。
Sub queue_simulation()
Dim end_time(8) As Single, min_time As Single
Dim liststart As Range
Set liststart = Range("A2")
max_row = 250
raiten1 = liststart.Offset(1, 0).Resize(max_row, 6)
ReDim raiten2(1 To max_row, 1 To 2)
mado = Range("B1")
For i = 1 To mado
end_time(i) = 0
Next
work_line = 1
sw = 0
Do While sw = 0 And work_line <= 250
min_no = 1
min_time = end_time(1)
For i = 2 To mado
If min_time > end_time(i) Then
min_time = end_time(i)
min_no = i
End If
Next
raiten2(work_line, 1) = min_no
If raiten1(work_line, 2) > min_time Then
raiten2(work_line, 2) = raiten1(work_line, 2)
Else
raiten2(work_line, 2) = min_time
End If
end_time(min_no) = raiten2(work_line, 2) + raiten1(work_line, 6)
work_line = work_line + 1
If raiten1(work_line, 1) = "" Then
sw = 1
End If
Loop
liststart.Offset(1, 3).Resize(work_line - 1, 2) = raiten2
End Sub
C言語やJavaなどにくらべると表計算の問題は簡単すぎるので、せめて2次元配列かFunctionの呼び出しくらいは入れてほしいですね。
12.バックナンバー
13.ExcelVBA講座ご紹介
この記事が気に入ったらサポートをしてみませんか?