名称未設定-2

平成29年度秋期基本情報技術者_表計算のマクロをExcelVBAで再現する

目次

1.出典
2.問題で使用するExcelシート「ログ」「アクセス先集計」のダミーデータの簡単な作り方
3.問題文の要旨
4.問題文(疑似言語)
5.解答群(疑似言語)
6.問題文(VBA翻訳)
7.VBA翻訳の補足説明
8.解答群(VBA翻訳)
9.正解
10.正解を入れたVBA完全版 ※動作確認済み
11.2次元配列バージョン ※動作確認済み
12.バックナンバー
13.ExcelVBA講座ご紹介

1.出典

経済産業省国家試験(IPA情報処理推進機構)
平成29年度秋期 基本情報技術者試験 午後試験 選択問題 問13表計算設問3[解答欄d~f]

なお、試験問題及び正解の著作権はIPA情報処理推進機構に帰属します。

2.問題で使用するExcelシート「ログ」「アクセス先集計」のダミーデータの簡単な作り方

シート「ログ」

・セルC2以降:
="http://"&REPT(CHAR(INT(RAND()*26+97)),3)&".co.jp/index.html"
・その他の列はマクロとは無関係なので空白でも良い。
・ただし、C列はRand()を使ってダミーのデータを入力しているので値の貼り付けをして数式を消しておくこと。

シート「アクセス先集計」

・1行目を見出しとして、A2:B9999はあらかじめ空白にしておく。

3.問題文の要旨

社内から社外へのアクセスを調べるため、サーバのログをワークシート「ログ」に保存した。ただし、ログのデータは最大9998件までとする。アクセス先のURLごとのアクセス回数を求めるマクロPage_countを作成して、ワークシート「アクセス先集計」のB2以降に出力したい。

4.問題文(疑似言語)

[マクロ:Page_count]
〇マクロ:Page_count
〇数値型:log_line, count_line
〇文字列型:log_url, count_urllog_line ← 1
■ 相対(ログ!A1, log_line, 2) <> null
|・count_line ← 1
|・log_url ← 相対(ログ!A1, log_line, 2)
|・count_url ← 相対(A1, count_line, 0)
|■ [ 解答欄d ]
||・count_linecount_line + 1
||・count_url ← 相対(A1, count_line, 0)
|■
|▲ [ 解答欄e ]
||・相対(A1, count_line, 0) ← log_url
||・相対(A1, count_line, 1) ← 1
|+-----
||・[ 解答欄f ]
|▼
|・log_linelog_line + 1
■

5.解答群(疑似言語)

dに関する解答群
 ア 論理積(count_url = null, count_url = log_url)
 イ 論理積(count_url = null, count_url <> log_url)
 ウ 論理積(count_url <> null, count_url <> log_url)
 エ 論理和(count_url = null, count_url = log_url)
 オ 論理和(count_url = null, count_url <> log_url)
 カ 論理和(count_url <> null, count_url <> log_url)

eに関する解答群
 ア count_url = log_url
 イ count_url = null
 ウ count_url <> null
 エ log_url = null
 オ log_url <> null

fに関する解答群
 ア 相対(A1, count_line, 1) ← 相対(A1, count_line, 1) + 1
 イ 相対(A1, count_line, 1) ← 相対(ログ!A1, log_line, 2)
 ウ 相対(A1, count_line, 2) ← 相対(A1, count_line, 2) + 1
 エ 相対(A1, count_line, 2) ← 相対(ログ!A1, log_line, 2)
 オ 相対(A1, log_line, 1) ← 相対(A1, log_line, 1) + 1
 カ 相対(A1, log_line, 1) ← 相対(A1, log_line, 2) + 1

6.問題文(VBA翻訳)

Sub Page_count()
   Dim log_line As Integer, count_line As Integer
   Dim log_url As String, count_url As String
   log_line = 1
   Do While Sheets("ログ").Range("A1").Offset(log_line, 2) <> ""
       count_line = 1
       log_url = Sheets("ログ").Range("A1").Offset(log_line, 2)
       count_url = Range("A1").Offset(count_line, 0)
       Do While [ 解答欄d ]
           count_line = count_line + 1
           count_url = Range("A1").Offset(count_line, 0)
       Loop
       If [ 解答欄e ] Then
           Range("A1").Offset(count_line, 0) = log_url
           Range("A1").Offset(count_line, 1) = 1
       Else
           [ 解答欄f ]
       End If
       log_line = log_line + 1
   Loop
End Sub

7.VBA翻訳の補足説明

「相対(A1, 」は「Range("A1").Offset(」と訳します。
「相対(ログ!A1, 」は「Sheets("ログ").Range("A1").Offset(」と訳します。

8.解答群(VBA翻訳)

dに関する解答群

 ア count_url = "" And count_url = log_url
 イ count_url = "" And count_url <> log_url
 ウ count_url <> "" And count_url <> log_url
 エ count_url = "" Or count_url = log_url
 オ count_url = "" Or count_url <> log_url
 カ count_url <> "" Or count_url <> log_url

eに関する解答群

 ア count_url = log_url
 イ count_url = ""
 ウ count_url <> ""
 エ log_url = ""
 オ log_url <> ""

fに関する解答群

 ア Range("A1").Offset(count_line, 1) ← Range("A1").Offset(count_line, 1) + 1
 イ Range("A1").Offset(count_line, 1) ← Sheets("ログ").Range("A1").Offset(log_line, 2)
 ウ Range("A1").Offset(count_line, 2) ← Range("A1").Offset(count_line, 2) + 1
 エ Range("A1").Offset(count_line, 2) ← Sheets("ログ").Range("A1").Offset(log_line, 2)
 オ Range("A1").Offset(log_line, 1) ← Range("A1").Offset(log_line, 1) + 1
 カ Range("A1").Offset(log_line, 1) ← Range("A1").Offset(log_line, 2) + 1

9.正解

d ウ
基本的に作業する行を次に進めるのは空白でない場合であり「Do while ~ <> ""」は基本形。count_lineをインクリメントしているので、一致するURLを探しているのは明らか。つまり、次の行に進む条件はさらに不一致の場合に限られる(And)。
e イ
アクセス回数に1を入れるのは見つからなかった場合なので、count_urlは空白。
f ア
見つかったのだから、アクセス回数をインクリメントすればよい。

10.正解を入れたVBA完全版 ※動作確認済み

Sub Page_count()
   Dim log_line As Integer, count_line As Integer
   Dim log_url As String, count_url As String
   log_line = 1
   Do While Sheets("ログ").Range("A1").Offset(log_line, 2) <> ""
       count_line = 1
       log_url = Sheets("ログ").Range("A1").Offset(log_line, 2)
       count_url = Range("A1").Offset(count_line, 0)
       Do While count_url <> "" And count_url <> log_url
           count_line = count_line + 1
           count_url = Range("A1").Offset(count_line, 0)
       Loop
       If count_url = "" Then
           Range("A1").Offset(count_line, 0) = log_url
           Range("A1").Offset(count_line, 1) = 1
       Else
           Range("A1").Offset(count_line, 1) = Range("A1").Offset(count_line, 1) + 1
       End If
       log_line = log_line + 1
   Loop
End Sub

11.2次元配列バージョン ※動作確認済み

問題の趣旨を変えないまま2次元配列に置き換えてみました。

Sub Page_count()
   Dim a(1 To 9998, 1 To 2)
   log_url = Sheets("ログ").Range("C2").Resize(9998, 1)
   log_line = 1
   count_line_max = 1
   Do While log_url(log_line, 1) <> ""
       count_line = 1
       count_url = a(count_line, 1)
       Do While count_url <> "" And count_url <> log_url(log_line, 1)
           count_line = count_line + 1
           If count_line_max < count_line Then count_line_max = count_line
           count_url = a(count_line, 1)
       Loop
       If count_url = "" Then
           a(count_line, 1) = log_url(log_line, 1)
           a(count_line, 2) = 1
       Else
           a(count_line, 2) = a(count_line, 2) + 1
       End If
       log_line = log_line + 1
   Loop
   Range("A2").Resize(count_line_max, 2) = a
End Sub

12.バックナンバー

13.ExcelVBA講座ご紹介


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