...

情 19 演習問題 解説 問題 1 (1) Dim i, j As Long, D As Double (2) Skjt

by user

on
Category: Documents
1

views

Report

Comments

Transcript

情 19 演習問題 解説 問題 1 (1) Dim i, j As Long, D As Double (2) Skjt
情 19 演習問題
解説
問題 1
(1) Dim i, j As Long, D As Double
(2) Skjt$ = Cells(2, 1)
(3) Sub CircleDraw(X0 As Single, Y0 As Single, R As Single)
(4) i% = 10
(5) Dim Nserial, YoubiIndex As Integer, Youbi As String
<Ans.>
(1)i : F j : B D:D (2)Skjt : E (3)X0 : C Y0 : C
(4)i : A (5)Nserial : F YoubiIndex : A Youbi : E
<解説>
情 10 参照。基本なのでちゃんと覚えてください。宣言を省略、あるいは空欄にすると Variant 型になるこ
と、変数名の後に&や!など特定の記号を付ける型決定の仕方があることに注意。
※問題の例にもあるように、変数名の文字を大文字にして定義すると、マクロ本文で変数名を全て小文字で
入力したときに Excel が自動でその文字を大文字に直してくれる。つまり、大文字にならない変数名は定義
されてない、あるいはスペルミスがあるということ。趙初歩的だけど、バグ取りには有効な手段なので活用
するといいかも。
問題 2
Sub Test()
'西暦年、月、何回目の何曜日かを入力したとき、
'それが何日であるかを求める。
Dim Seireki As Integer, Tsuki As Integer, Kaisu As Integer
Dim Youbi As String, Hi As Integer, HiIni As Integer
Dim Nserial, YoubiIndex1 As Integer, YoubiIndex2 As Integer
(メモ)
(メモ)
Seireki、Tsuki、Kaisu は整数
Youbi は文字列、Hi、HiIni は整数
Nserial はバリアント型、YoubiIndex1、2 は整数
'データ入力
Seireki = Cells(1, 1).Value
Tsuki = Cells(2, 1).Value
Kaisu = Cells(3, 1).Value
Youbi = Cells(4, 1)
'_____________________________________________________(1)↓
Select Case Youbi
Case "日"
YoubiIndex1 = 1
Case "月"
YoubiIndex1 = 2
Case "火"
YoubiIndex1 = 3
Case "水"
YoubiIndex1 = 4
Case "木"
YoubiIndex1 = 5
Case "金"
YoubiIndex1 = 6
Case "土"
YoubiIndex1 = 7
Case Else
MsgBox "日∼土までのいずれかの曜日を入力して下さい。"
YoubiIndex1 = 0
End Select
'_____________________________________________________(1)↑
If YoubiIndex1 <> 0 Then
'_____________________________________________________(2)↓
HiIni = 1
(メモ)
セル A1 の値を Seireki に代入
セル A2 の値を Tsuki に代入
セル A3 の値を Kaisu に代入
セル A4 の内容を Youbi に代入
(メモ)
Youbi に代入されたデータによる場合分け
Youbi に日が代入されている場合
1 を YoubiIndex1 に代入
Youbi に月が代入されている場合
2 を YoubiIndex1 に代入
Youbi に火が代入されている場合
3 を YoubiIndex1 に代入
Youbi に水が代入されている場合
4 を YoubiIndex1 に代入
Youbi に木が代入されている場合
5 を YoubiIndex1 に代入
Youbi に金が代入されている場合
6 を YoubiIndex1 に代入
Youbi に土が代入されている場合
7 を YoubiIndex1 に代入
Youbi に上記以外または空が代入されている場合
メッセージの表示
0 を YoubiIndex1 に代入
場合分け終了
(メモ)
条件 A:YoubiIndex に 0 以外が代入されている場合
(メモ)
1 を HiIni に代入
Do
'1 日∼7 日の間で該当する曜日になる日を探す。
DoLoop 開始
(メモ)
Nserial = DateSerial(Seireki, Tsuki, HiIni)
YoubiIndex2 = WeekDay(Nserial)
関数 DateSerial で返された値を Nserial に代入
関数 WeekDay で返された値を YoubiIndex2 に代入
If YoubiIndex2 = YoubiIndex1 Then Exit Do
HiIni = HiIni + 1
YoubiIndex2 が YoubiIndex1 と同じ時 DoLoop 終了
HiIni の値を 1 増やす
Loop While HiIni < 8
HiIni が 8 未満の間 Do に戻る
Hi = HiIni + 7 * (Kaisu - 1)
Hi に HiIni + 7
If Hi > 31 Then
MsgBox "あり得ない日です。データを修正して下さい。"
Else
MsgBox "西暦" & Seireki & "年" & Tsuki & "月の第" & _
Kaisu & Youbi & "曜日は" & Hi & "日です。"
End If
'_____________________________________________________(2)↑
End If
(Kaisu - 1)を代入
条件B:Hi の値が 31 以上の時
メッセージを表示
それ以外の時(Hi の値が 31 未満の時)
メッセージを表示
条件B終了
(メモ)
条件A終了
End Sub
<Ans.>
(1)プログラムの部品化(モジュール化)
(2)(a)西暦 2005 年 2 月の第 5 水曜日は 30 日です。(b)あり得ない日です。データを修正してください。
(c)西暦 2005 年 8 月の第 5 水曜日は 31 日です。
(3)(a)<例>
Function GetYoubi(Youbi As String)
Select Case Youbi
Case "日"
GetYoubi = 1
Case "月"
GetYoubi = 2
Case "火"
GetYoubi = 3
Case "水"
GetYoubi = 4
Case "木"
GetYoubi = 5
Case "金"
GetYoubi = 6
Case "土"
GetYoubi = 7
Case Else
MsgBox "日∼土までのいずれかの曜日を入力して下さい。"
GetYoubi = 0
End Select
引き継ぐ変数は Youbi(1 つ)
1 を計算結果としてメインプログラムに代入する
(以下同じ)
End Function
(b)<例>
Sub GetHi(Seireki As Integer, Tsuki As Integer, Kaisu As Integer, YoubiIndex1 As Integer, Youbi As String)
Dim HiIni As Integer, Nserial, YoubiIndex2 As Integer, Hi As Integer
引き継ぐ変数は 5 つ
HiIni = 1
Do
'1 日∼7 日の間で該当する曜日になる日を探す。
Nserial = DateSerial(Seireki, Tsuki, HiIni)
YoubiIndex2 = WeekDay(Nserial)
If YoubiIndex2 = YoubiIndex1 Then Exit Do
HiIni = HiIni + 1
Loop While HiIni < 8
Hi = HiIni + 7 * (Kaisu - 1)
If Hi > 31 Then
MsgBox "あり得ない日です。データを修正して下さい。"
Else
MsgBox "西暦" & Seireki & "年" & Tsuki & "月の第" & _
Kaisu & Youbi & "曜日は" & Hi & "日です。"
End If
End Sub
(4)<例>
Sub Test2()
'西暦年、月、何回目の何曜日かを入力したとき、それが何日であるかを求める。
Dim Seireki As Integer, Tsuki As Integer, Kaisu As Integer
Dim Youbi As String
Dim YoubiIndex1 As Integer
'データ入力
Seireki = Cells(1, 1).Value
Tsuki = Cells(2, 1).Value
Kaisu = Cells(3, 1).Value
Youbi = Cells(4, 1)
'____________________________________________________________________(1)↓
YoubiIndex1 = GetYoubi(Youbi)
関数 GetYoubi 実行(送る変数は 1 つ)
'____________________________________________________________________(1)↑
If YoubiIndex1 <> 0 Then
'____________________________________________________________________(2)↓
GetHi Seireki, Tsuki, Kaisu, YoubiIndex1, Youbi
サブルーチン GetHi 実行(送る変数は 5 つ)
'____________________________________________________________________(2)↑
End If
End Sub
<解説>
・「2 月って 28 日 or29 日までだから(1)(a)は『あり得ない日です∼』じゃないの?」という声が聞こえて
きそうな引っかけ問題…。このプログラムでは、各月がそれぞれ何日までという指定はなく、全て一律に 31
日まであることとして考えていることに気づけるかどうかがポイント。カレンダーを見て考えるのも大切だ
けど、基本的にはプログラミングの流れに沿って計算すること。
・関数 DateSerial は西暦、月、日の 3 つの数字を入力すると、その入力した日が 1900/1/1 から数えて何
日目かということを計算する関数。とんでもない桁数になるので当然バリアント型。
・関数 WeekDay は DateSerial で求めた 1900/1/1 から数えて何日目かという数字を入力すると、その日
が何曜日かということを計算する関数。結果は日曜日なら 1、月曜日なら 2、…というように出力されるの
で、日、月、火、…と表示したければ(3)(a)のような場合分けによる代入を利用する。
・HiIni + 7 (Kaisu - 1)が何を求める計算かはカレンダーを眺めながら自分で考えよう。
・関数プロシージャは DateSerial や WeekDay のような複雑な計算をするための関数を自分で作ってみよ
う!というイメージ。要するに基本的な仕事は計算なので、メインプログラムに対して何か計算した結果をひ
とつだけ送ることができる。送りたい変数名と関数プロシージャの名前を同じにすることを忘れずに!
・サブルーチンプロシージャは同じ作業を何回もやるのは面倒だから外部委託しよう(?)というイメージ。要
するに基本的な仕事は普通のプログラムと一緒。ただし関数プロシージャと違って計算結果をメインプログ
ラムに引き継げないことに注意。
・サブルーチン・関数プロシージャではメインプログラムから引き継いだ数値のデータ型を最初の括弧内で
定義する。メインプログラムで送った変数の数とプロシージャで受け取る変数の数が同じになるよう確認す
る。※プロシージャで受け取る側の変数名を仮引数として授業中ではLやMなどにしていたけど、正直なん
でもいいんだからメインプログラムと同じ変数名のままでもまるで違う名前にしても全然問題ない。
・If͐Then の後を改行せずに続けると、End If が省略できる。小ネタ。
・とりあえずわかんないところがあったら Mizutani 氏に訊ねる。
問題 3
<Ans.>
(1) ActiveSheet.Shapes.AddShape(msoShapeOval, 150, 150, 100, 100).Select
(2) 354 , 228
(3) ActiveSheet.Shapes.AddShape(msoShapeOval, 250, 255, 90, 90).Select
<解説>
・図形のサイズ決めの指令は(図形左上の X 座標 , 図形左上の Y 座標 , 横幅 , 縦幅)という形式。
・Excel 自身が決めている ワールド座標系 はシートの左上が原点で、右方向が X 軸正、下方向が Y 軸正。
・x2 + y2 + 10x - 2000 = 0 →(x + 5)2 + y2 = 452
中心(-5 , 0) = 295 , 300 、半径 45
・とにかく図を書いてみて確認するのが一番。
問題 4
<Ans.>
(1)Sleep 100 (2)Kernel32.dll (3)ア.75 イ.左下 ウ.400 エ.200 オ.302 カ.298 キ.Set En1 ク.En1.Delete
Private Declare Sub Sleep Lib "kernel32" _
(ByVal dwMilliseconds As Long)
Sub Macro1()
Dim En1 As Shape, X0 As Single, Y0 As Single
X0 = 325
Y0 = 125
kernel32 というライブラリから Sleep という関数を引用
関数 Sleep に送る引数が長整数型で単位はミリ秒
サブルーチンプロシージャ開始
En1 はオートシェイプなど図形、X0・Y0 は単精度浮動小数型
X0 に 325 を代入
Y0 に 125 を代入
i=1
Do
Set En1 = ActiveSheet.Shapes.AddShape _
(msoShapeOval, X0, Y0, 150, 150)
i に 1 を代入
DoLoop 開始
選択中のシートに円(始点 X0,Y0、横幅 150、縦幅 150)を描き(準備)、
En1 に割り当てる
DoEvents
Sleep 100
En1 を描く(確定)
100 ミリ秒動作を休止
En1.Delete
En1 を消去
i=i+1
X0 = X0 - 2
Y0 = Y0 + 2
i に i + 1 を代入
X0 に X0 - 2 を代入
Y0 に Y0 + 2 を代入
Loop While i <= 50
i が 50 以下の時 Do に戻る
End Sub
サブルーチンプロシージャ終了
<解説>
・VBA の計算は人間の体感速度からしてみればすっごく早いから、パラパラ漫画を作ろうと思ったら一枚と
一枚の間で VBA には少し休む命令をいれる。Sleep という関数(機能)は VBA が持っている関数ではなく、
Windows 本体が持っている関数なので、VBA 中で使うときにはあらかじめ呼び出す必要がある。最初の行
はその命令。一つ一つ説明するとややこしいので、Sleep を使いたいときは同じモジュール(枠)内にこれも
入れないといけないんだなというくらいで覚えておくだけにとどめておいて大丈夫。(あえて説明すると、
Private は同一モジュール内からのみ参照可能であることを示す宣言、Declare は API 関数を参照すること
を示す宣言、Sleep は API 関数の名前、Lib "kernel32"は参照する DLL ファイル名を指している。この一行
だけでもう一つのサブルーチンプロシージャができていることになり、つまり、Sleep 100 とはプログラム
の部品化で行ったようにサブルーチンプロシージャ内で別のサブルーチンプロシージャを実行し、その際に
引数として 100 を引き継いでいるということ。)
・いくらオートシェイプをいじくり回す指令を出したところで DoEvents 命令を出さない限りオートシェイ
プは変更されていないので注意。
・49 回目のループで i = 50 、X0 = 325 - 2 49 = 227、Y0 = 125 + 2 49 = 223 となり、50 回目
のループで左上の座標が 227, 223 、中心 302, 298 の円を描き、i = 51 になり Loop を終了する。
・別のやり方もあるので一応紹介。
Private Declare Sub Sleep Lib "kernel32"(ByVal dwMilliseconds As Long)
Sub Macro2()
Dim En1 As Shape, X0 As Single, Y0 As Single
X0 = 325
Y0 = 125
Set En1 = ActiveSheet.Shapes.AddShape (msoShapeOval, X0, Y0, 150, 150)
i=1
Do
DoEvents
Sleep 100
i=i+1
En1.IncrementLeft -2
右方向に-2 移動
En1.IncrementTop 2
下方向に 2 移動
Loop While i <= 50
En1.Delete
End Sub
Fly UP