名称未設定-2

平成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講座ご紹介


この記事が気に入ったらサポートをしてみませんか?