|
|
|
|
|
|
|
|
|
|
|
|
|
EXERCISE02:
train0202 |
|
2007-1-9 by KOMPas |
|
|
|
exercise02.xls |
|
|
|
■ |
「予定表」のデータを、データベースに保存したり、データベースから読み込んだりしてみましょう。 |
|
|
|
|
|
■ |
EXERCISE では、「EXCELマクロのお勉強」セット\otenki
フォルダにある、otenki.mdb を使います。 |
|
|
展開した\otenki
フォルダが、「マイドキュメント」や「デスクトップ」等にあると、 |
|
|
これからデータベースへの入出力コードを書くとき、データベースを指定するのが長くなるので、 |
|
|
フォルダ毎コピーして、ハードディスクのわかりやすい(記述が簡単な)場所に作り直した方が、あとで楽です。 |
|
|
例えば、「デスクトップ」にあるotenki.mdb を記述するには、 |
|
|
C:\Documents and
Settings\KOMPas\デスクトップ\otenki\otenki.mdb |
|
|
「マイドキュメント」にあるotenki.mdb を記述するには、 |
|
|
C:\Documents and
Settings\KOMPas\My Documents\otenki\otenki.mdb |
|
|
と書かないとなりませんが、(空白文字を含んでいるのでなおややこしい) |
|
|
ハードディスク「C:」に貼り付けた場合なら、 |
|
|
C:\otenki\otenki.mdb |
|
|
ですみます。 |
|
|
|
■ |
「予定表」に、データベース操作用のボタン、及び「アカウント」「パスワード」欄を設定する。 |
|
|
|
|
■ |
あなたの練習用EXCEL カレンダ.xlsの「予定表」に、ボタンを2つ足します。(サンプル参照) |
|
|
セルJ2 に、「データベースへ保存」 |
|
|
|
|
セルJ4 に、「データベースから読込」 |
|
|
と書き込んで、セルの色を変えれば、ボタンのようにみえます。(かな?) |
|
|
「ボタン」の場所や色や幅はお好みで設定できますが、 |
|
|
セルの場所を変えたなら、当然コードもかきかえる必要があります。 |
|
|
|
■ |
「アカウント」欄、「パスワード」欄を作っておきましょう。(サンプル参照) |
|
|
セルJ6 を、「アカウント」欄にします。 |
|
|
|
|
セルJ8 を、「パスワード」欄にします。 |
|
|
J6、J8に「入力する場所」であることがわかるように、薄い色をつけておきます。 |
|
|
わかりやすいように、J5、J7にラベルを書き込みます。(操作には関係がない) |
|
|
|
■ |
「予定表」マクロ BeforeDoubleClick のイベントプロシージャを書く。 |
|
|
|
|
■ |
「ツール」「マクロ」「Visual Basic
Editor」の順に開いて、 |
|
|
左側の「プロジェクトエクスプローラ」で、Sheet2をダブルクリックします.。 |
|
|
今コードを書き込もうとしているのは、「カレンダ」ではなく「予定表」です。 |
|
|
右のコード欄の、一番上左側が「(general)」となっていれば、「Worksheet」に変更します。 |
|
|
一番上右側を、「BeforeDoubleClick」にします。 |
|
|
|
■ |
あらかじめ、次のコードを書き込んでください。 |
|
|
|
(白抜き文字がコード。グリーンおよび橙の文字は省略してもよいところです。) |
|
|
Private Sub
Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) |
|
|
|
'Target
はデータをダブルクリックした場所。rr はtarget左上セルの行番号、cc は左上セルの列番号。 |
|
|
rr = Target.Row |
|
|
|
cc = Target.Column |
|
|
|
If rr = 2 And cc = 10 Then |
|
|
|
ダブルクリック場所が2行目 10列
(つまりJ2セル)なら、「データベースから読込」 |
|
|
|
' ここに「データベースから読込」コード |
|
|
|
ElseIf rr = 4 And cc = 10
Then |
|
|
|
ダブルクリック場所が4行目 10列
(つまりJ2セル)なら、「データベースへ保存」 |
|
|
|
' ここに「データベースへ保存」コード |
|
|
|
Else |
|
|
|
'上記以外の場所なら何もしない。 |
|
|
|
End If |
|
|
|
End Sub |
|
|
|
|
■ |
データベース操作の為のコードを追加する。 |
|
|
|
|
■ |
データベース関連のコードを書く前に、EXCELで、次の準備が要ります。 |
|
|
Visual Basic Editor 画面で、「ツール」−「参照設定」を選択して、 |
|
|
「Microsoft DAO 3.6 Object
Library」にチェックをいれて「OK」します。 |
|
|
もう一度、「ツール」−「参照設定」を選ぶと、 |
|
|
「参照設定」画面に、「Microsoft DAO 3.6 Object
Library」がチェックされているのを確認できます。 |
|
|
|
この設定は、EXCELファイル毎に行う必要があります。 |
|
|
この設定を行ったEXCELファイルは、マクロからデータベースを操作するコードを書くことができます。 |
|
|
実は、Microsoftが推奨しているのは、DAOではなくADOです。 |
|
|
「コードを皆でつかいまわすこと」の楽しさを説明している文脈で、 |
|
|
「主流」をはずすのはいかがなものか?、といった問題がありますが、 |
|
|
DAOは、Windows95以来ずっと(最近はこっそりと)、 |
|
|
Microsoft製品の色んな製品で使われているデータベースエンジンなので、 |
|
|
あと4,5年はサポートされるだろう、ということでご理解を。 |
|
|
(ぼくは自称「筋金入りのDAOファン」なので) |
|
|
|
■ |
水色部分が、データベース関連のマクロを書くときのおまじないコードです。 |
|
|
|
あなたのマクロに書き足してください。 |
|
|
データベースを扱うとき、必ず書き込むコードで、 |
|
|
若干奇妙に見えますが、これさえ書けば、他はどんなデータベース処理でも同じです。 |
|
|
コメント「’操作するデータベース」に続くコード「xdb = 」には、あなたのデータベースパスを指定します。 |
|
|
|
■ |
データベース処理そのものではありませんが、関連処理も合わせてここで書き込みます。 |
|
|
これは、黄色文字にしています。 |
|
|
この部分のコメントは橙文字です。省略してもかまいません。 |
|
|
|
|
Private Sub
Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) |
|
|
|
'操作するデータベース |
|
|
|
xdb =
"c:\otenki\otenki.mdb" |
|
|
|
Dim db As Database |
|
|
|
Set db =
DBEngine.Workspaces(0).OpenDatabase(xdb) |
|
|
|
Dim rs As Recordset |
|
|
|
|
|
|
|
'Target
はデータをダブルクリックした場所。rr はtarget左上セルの行番号、cc は左上セルの列番号。 |
|
|
rr = Target.Row |
|
|
|
cc = Target.Column |
|
|
|
|
|
|
|
'sheet2 データの最終行 endrrの取得 |
|
|
|
endrr
= 5 |
|
|
|
For i
= 5 To 10000 |
|
|
|
If
Sheet2.Cells(i, 1) & "" = "" Then |
|
|
|
Else |
|
|
|
endrr = i |
|
|
|
End If |
|
|
|
Next
i |
|
|
|
'アカウント/パスワードの読込 |
|
|
|
usrtext =
"_やまがたあきた=yamagata_さかたかな=kompas_とくしまえひめ=tokusima_" |
|
|
|
usr = Sheet2.Cells(6, 10):
'アカウント欄データ |
|
|
|
pwd = Sheet2.Cells(8, 10):
'パスワード欄データ |
|
|
|
'読み込んだらパスワード欄を空白にします。 |
|
|
|
Sheet2.Cells(8, 10) = "" |
|
|
|
'otenki テーブルのデータ更新ルール |
|
|
|
'幾つかの理由の為、コードには下記のようなルールを適用します。 |
|
|
|
'(rule1)簡単なパスワード識別コードで、該当しなければ更新できない。 |
|
|
|
'(rule2)otenki
テーブルデータは、そのデータを作成した(追加した)人しか編集/削除はできない。 |
|
|
'(rule3)データの追加は、アカウント欄に有効な記述があるときのみ、 |
|
|
|
' 「記録者」欄が空白または、「記録者」欄が「_アカウント_」を含む行データを追加できる。 |
|
|
|
'(rule4)rule2の例外処理として、1レコードの更新の場合のみ、 |
|
|
|
'
そのデータを作成した(追加した)人でなくても編集/削除ができる。 |
|
|
|
'
但し、そのデータの記録者は更新者名となるので、 |
|
|
|
' アカウントは必要。パスワードは無視。 |
|
|
|
|
|
|
|
If rr = 2 And cc = 10 Then |
|
|
|
ダブルクリック場所が2行目 10列
(つまりJ2セル)なら、「データベースから読込」 |
|
|
|
' ここに「データベースから読込」コード |
|
|
|
ElseIf rr = 4 And cc = 10
Then |
|
|
|
ダブルクリック場所が4行目 10列
(つまりJ2セル)なら、「データベースへ保存」 |
|
|
|
' ここに「データベースへ保存」コード |
|
|
|
ElseIf
usr & "" = "" Then |
|
|
|
|
'アカウントがなければ何もしない。 |
|
|
|
|
ElseIf rr < 5 Then |
|
|
|
|
'上記以外の場所なら何もしない。 |
|
|
|
|
ElseIf rr > endrr Then |
|
|
|
|
'上記以外の場所なら何もしない。 |
|
|
|
|
ElseIf cc = 7 Then |
|
|
|
|
' ここに「1行データのデータベース更新」コード |
|
|
|
Else |
|
|
|
'上記以外の場所なら何もしない。 |
|
|
|
End If |
|
|
|
|
|
|
db.close |
|
|
|
|
|
|
End Sub |
|
|
|
|
■ |
「データベース読込」コード |
|
|
|
|
|
ダブルクリック場所が2行目 10列
(つまりJ2セル)なら、「データベースから読込」 |
|
|
|
'画面のクリア |
|
|
|
Sheet2.Range("a5:c" & endrr).Value = "" |
|
|
|
Sheet2.Range("e5:g" & endrr).Value = "" |
|
|
|
'(データベース操作)otenki
テーブルを開きます。 |
|
|
|
sqls = "select * from
otenki order by 日付" |
|
|
|
Set rs =
db.OpenRecordset(sqls) |
|
|
|
'i は、sheet2へ書込行(開始は5行目) |
|
|
|
i = 5 |
|
|
|
'読込レコードが終わるまで、Do〜Loop 内の処理を繰り返し実行します。 |
|
|
|
Do
Until rs.EOF |
|
|
|
'otenki テーブルから1行ずつ読み込んで、転記します。 |
|
|
|
|
'右辺(データベースから取得した値)を左辺(EXCELシートの指定セル)に転記する、 |
|
|
|
|
'データベース読込「転記コード」です。 |
|
|
|
'読み込んだデータの「日付」フィールドの値を、ddxとします。 |
|
|
|
ddx = rs!日付 |
|
|
|
'日付ddx の「年」を取得して、sheet2 i行 1列目に転記します。 |
|
|
|
Sheet2.Cells(i, 1) = Year(ddx) |
|
|
|
'日付ddx の「年」を取得して、sheet2 i行 2列目に転記します。 |
|
|
|
Sheet2.Cells(i, 2) = Month(ddx) |
|
|
|
'日付ddx の「年」を取得して、sheet2 i行 3列目に転記します。 |
|
|
|
Sheet2.Cells(i, 3) = Day(ddx) |
|
|
|
'読み込んだデータの「本文」フィールドの値を、sheet2 i行 5列目に転記します。 |
|
|
|
Sheet2.Cells(i, 5) = rs!本文 |
|
|
|
|
|
'読み込んだデータの「種類」フィールドの値を、sheet2 i行 6列目に転記します。 |
|
|
|
Sheet2.Cells(i, 6) = rs!種類 |
|
|
|
'読み込んだデータの「記録者」フィールドの値を、sheet2 i行 7列目に転記します。 |
|
|
|
Sheet2.Cells(i, 7) = rs!記録者 |
|
|
|
i = i
+ 1 |
|
|
|
'otenki
テーブルから、1レコード読み終えたら、次のレコードへ移ります。 |
|
|
|
rs.MoveNext |
|
|
|
Loop |
|
|
|
'otenki
テーブルから、全てのレコード読み終えたて、otenki テーブルを閉じます。 |
|
|
|
rs.Close |
|
|
|
|
■ |
「データベース保存」コード |
|
|
|
|
ダブルクリック場所が4行目 10列
(つまりJ2セル)なら、「データベースへ保存」 |
|
|
|
'otenki
テーブルを開いて、「予定表」頁のデータを保存します。 |
|
|
|
'有効なアカウント名とそのパスワード |
|
|
|
|
|
|
|
If
usr & "" = "" Then |
|
|
|
MsgBox "アカウントがありません" |
|
|
|
ElseIf pwd &
"" = "" Then |
|
|
|
MsgBox "パスワードがありません" |
|
|
|
ElseIf InStr(usrtext,
"_" & usr & "=" & pwd & "_") =
0 Then |
|
|
|
MsgBox "有効なアカウントではありません" |
|
|
|
Else |
|
|
|
'(データベース操作)otenki テーブルの、usrが書き込んだデータを全て削除します。 |
|
|
|
sqls = "delete * from otenki where 記録者 like '*_" & usr
& "_*'" |
|
|
|
db.Execute sqls |
|
|
|
'識別値ednn を、処理日から求めます。 |
|
|
|
ednn = (Int(DateValue(Now()) * 10 / 10) Mod 10000) * 10000 |
|
|
|
|
|
|
|
'(データベース操作)otenki テーブルを開きます。 |
|
|
|
Set rs = db.OpenRecordset("otenki") |
|
|
|
'i
は、sheet2データの読込行(開始は5行目) |
|
|
|
i
= 5 |
|
|
|
cnt = 0 |
|
|
|
Do
Until i > endrr |
|
|
|
'EXCELから読み取った1行を、otenki テーブルに書き込むか書き込まないかを識別します。 |
|
|
'デフォルトは、「書き込まない」です。 |
|
|
|
addok = 0 |
|
|
|
|
|
If Sheet2.Cells(i, 1) & "" = "" Then |
|
|
|
'EXCELデータの先頭データが空白のとき、まま |
|
|
|
ElseIf IsDate(Sheet2.Cells(i, 1) & "/" &
Sheet2.Cells(i, 2) & "/" & Sheet2.Cells(i, 3)) = False Then |
|
|
'EXCELデータの年月日が年月日でないとき、まま |
|
|
|
ElseIf Sheet2.Cells(i, 5) & "" = "" Then |
|
|
|
'EXCELデータの本文がないとき、まま |
|
|
|
ElseIf Sheet2.Cells(i, 7) & "" = "" Then |
|
|
|
'EXCELデータの記録者欄が空白のとき新規データとして追加する。 |
|
|
|
addok = True |
|
|
|
ElseIf InStr(Sheet2.Cells(i, 7), "_" & usr &
"_") Then |
|
|
|
'EXCELデータの記録者欄がアカウントにヒットしたら、追加する。 |
|
|
|
addok = True |
|
|
|
End If |
|
|
|
|
|
|
|
If addok Then |
|
|
|
'EXCELデータの年月日から、日付xdate を求める |
|
|
|
xdate = DateValue(Sheet2.Cells(i, 1) & "/" &
Sheet2.Cells(i, 2) & "/" & Sheet2.Cells(i, 3)) |
|
|
'EXCELデータの種類から、xkubun を求める。 |
|
|
|
'種類に記述がないとき、@usrを代用する。 |
|
|
|
|
|
|
|
xkubun = Sheet2.Cells(i, 6) |
|
|
|
If xkubun & "" = "" Then |
|
|
|
xkubun = "@" & usr |
|
|
|
End If |
|
|
|
|
|
|
|
End If |
|
|
|
|
|
|
If addok Then |
|
|
|
cnt = cnt + 1 |
|
|
|
'下記cnttextは、通常otenki テーブルに1つしかない(はずの)keyとなります。 |
|
|
|
cnttext = "_" & usr & "_" & (ednn +
cnt) |
|
|
|
'「予定表」から1行ずつ読み込んで、otenki テーブルに転記します。 |
|
|
|
'右辺(EXCELシートの指定セル)を左辺(データベースフィールド値)に転記する、 |
|
|
|
'データベース書込「転記コード」です。 |
|
|
|
|
|
|
|
'otenki テーブルに新規レコードを追加します。 |
|
|
|
rs.AddNew: |
|
|
|
'xdate値を、「日付」フィールドに転記します。 |
|
|
|
rs!日付 = xdate |
|
|
|
'sheet2 i行 5列目データを、「本文」フィールドに転記します。 |
|
|
|
rs!本文 = Sheet2.Cells(i, 5) |
|
|
|
'xkubun値を、「種類」フィールドに転記します。 |
|
|
|
rs!種類 = xkubun |
|
|
|
'cnttext値を、「記録者」フィールドに転記します。 |
|
|
|
rs!記録者 = cnttext |
|
|
|
rs.Update |
|
|
|
'データベースに書き込んだ記録者データをEXCEL上でも書き換えます。 |
|
|
|
Sheet2.Cells(i, 7) = cnttext |
|
|
|
End If |
|
|
|
i
= i + 1 |
|
|
|
Loop |
|
|
|
rs.Close |
|
|
|
End
If |
|
|
|
|
■ |
「1行データのデータベース更新」コード |
|
|
|
|
If InStr(usrtext,
"_" & usr & "=") = 0 Then |
|
|
|
MsgBox "有効なアカウントではありません" |
|
|
|
Else |
|
|
|
'「記録者」欄がダブルクリックされたとき、その記録者欄データを取得します。 |
|
|
|
tgtednn = Sheet2.Cells(rr,
cc) |
|
|
|
|
|
|
|
If Sheet2.Cells(rr, 1) & "" = "" Then |
|
|
|
'EXCELデータの先頭データが空白のとき、まま |
|
|
|
ElseIf IsDate(Sheet2.Cells(rr, 1) & "/" &
Sheet2.Cells(rr, 2) & "/" & Sheet2.Cells(rr, 3)) = False
Then |
|
|
'EXCELデータの年月日が年月日でないとき、まま |
|
|
|
ElseIf Sheet2.Cells(rr, 5) & "" = "" Then |
|
|
|
'EXCELデータの本文がないとき、まま |
|
|
|
|
ElseIf Sheet2.Cells(rr, 7) & "" = "" Then |
|
|
|
'EXCELデータの記録者欄が空白のとき新規データとして追加する。 |
|
|
|
addok = True |
|
|
|
ElseIf InStr(Sheet2.Cells(rr, 7), "_" & usr &
"_") Then |
|
|
|
'EXCELデータの記録者欄がアカウントにヒットしたら、追加する。 |
|
|
|
addok = True |
|
|
|
End If |
|
|
|
|
|
|
|
If addok Then |
|
|
|
'EXCELデータの年月日から、日付xdate を求める |
|
|
|
xdate = DateValue(Sheet2.Cells(rr, 1) & "/" &
Sheet2.Cells(rr, 2) & "/" & Sheet2.Cells(rr, 3)) |
|
|
'EXCELデータの種類から、xkubun を求める。 |
|
|
|
'種類に記述がないとき、@usrを代用する。 |
|
|
|
|
|
|
|
xkubun = Sheet2.Cells(rr, 6) |
|
|
|
If xkubun & "" = "" Then |
|
|
|
xkubun = "@" & usr |
|
|
|
End If |
|
|
|
|
|
|
|
End If |
|
|
|
'MsgBox xdate & " " & xkubun |
|
|
|
If
addok Then |
|
|
|
If tgtednn & "" = "" Then |
|
|
|
Else |
|
|
|
'データベース上の既存データを削除します。 |
|
|
|
|
|
sqls = "delete * from otenki where 記録者='" & tgtednn
& "'" |
|
|
|
db.Execute sqls |
|
|
|
End If |
|
|
|
|
|
|
'識別値ednn を、処理時から求めます。 |
|
|
|
ednn = (Int(DateValue(Now()) *
10 / 10) Mod 10000) * 1000000 + 900000 + Int(TimeValue(Now()) * 100000) |
|
|
|
|
|
|
'(データベース操作)otenki テーブルを開きます。 |
|
|
|
Set rs = db.OpenRecordset("otenki") |
|
|
|
'右辺(EXCELシートの指定セル)を左辺(データベースフィールド値)に転記する、 |
|
|
|
'データベース書込「転記コード」です。 |
|
|
|
|
|
|
|
'otenki テーブルに新規レコードを追加します。 |
|
|
|
rs.AddNew |
|
|
|
'xdate値を、「日付」フィールドに転記します。 |
|
|
|
|
|
rs!日付 = xdate |
|
|
|
'sheet2 i行 5列目データを、「本文」フィールドに転記します。 |
|
|
|
rs!本文 = Sheet2.Cells(rr, 5) |
|
|
|
'xkubun値を、「種類」フィールドに転記します。 |
|
|
|
rs!種類 = xkubun |
|
|
|
'ednn値を、「記録者」フィールドに転記します。 |
|
|
|
rs!記録者 = "_" & usr & "_" & ednn |
|
|
|
rs.Update |
|
|
|
'データベースに書き込んだ記録者データをEXCEL上でも書き換えます。 |
|
|
|
Sheet2.Cells(rr, 7) = "_" & usr & "_"
& ednn |
|
|
|
rs.Close |
|
|
|
End
If |
|
|
|
|
|
|
End
If |
|
|
|
|
■ |
ふぅ。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|