電子書籍の厳選無料作品が豊富!

access2003を勉強中です。

先週1週間かけても解決できないことがありまして、どなたか教えて頂けないでしょうか。

内容は

会社で使用する勤務表に関してです。

ユーザー名(コンボボックス)、日付(カレンダーコントロール)、
出社時間(テキストボックス)、退社時間(テキストボックス
、作業内容(テキストボックス)をユーザーが入力し「登録」
コマンドボタンのイベントで入力した内容を、勤務表テーブルに
反映させたいのです。

その時に同じユーザーの同じ日付を2件入力させないようにしたいので

フォームに入力された内容からユーザー名と日付によって、
同じ内容が勤務表テーブルに無ければinsert、有ればupdateと
条件分岐をしたいのです。

しかし、

Public Sub kinmu()

Dim mmrs As ADODB.Recordset
Dim mmcn As ADODB.Connection

Set mmrs = New ADODB.Recordset
Set mmcn = Application.CurrentProject.Connection

mmrs.Open "勤務表", mmcn, adOpenKeyset, adLockOptimistic

mmrs.MoveFirst

If DCount("[ユーザー名] & [日]", "[勤務表]", "[ユーザー名]=[Forms]![フォーム1]![コンボ56]" & _
"and[日]=[Forms]![フォーム1]![テキスト88]") = 0 Then
mmcn.Execute "INSERT INTO 勤務表 ([ユーザー名],[日],[出社],[退社],[作業内容]) VALUES ([Forms]![フォーム1]![コンボ56],[Forms]![フォーム1]![テキスト88],[Forms]![フォーム1]![テキスト8],[Forms]![フォーム1]![テキスト17],[Forms]![フォーム1]![テキスト28]);"
Else
mmcn.Execute "UPDATE 勤務表 SET (ユーザー名=[Forms]![フォーム1]![コンボ56],日=[Forms]![フォーム1]![テキスト88],出社=[Forms]![フォーム1]![テキスト8],退社=[Forms]![フォーム1]![テキスト17],作業内容=[Forms]![フォーム1]![テキスト28] where [ユーザー名]=[Forms]![フォーム1]![コンボ56] and [日]=[Forms]![フォーム1]![テキスト88]);"
End If

として、「登録」コマンドボタンのイベントとしてCallキーワードによって呼び出そうとしているのですが、うまくいきません。

最初はDCount関数で件数を求め、それを変数に入れる。
IIF関数による分岐。などいろいろ試してはいたのですが、、、。

どなたか教えて下さい。よろしくお願いします。

A 回答 (10件)

1)レコードセットは何のために開いているのですか?


2)分岐うんぬんの前に、

mmcn.Execute "INSERT INTO 勤務表 ([ユーザー名],[日],[出社],[退社],[作業内容]) VALUES ([Forms]![フォーム1]![コンボ56],[Forms]![フォーム1]![テキスト88],[Forms]![フォーム1]![テキスト8],[Forms]![フォーム1]![テキスト17],[Forms]![フォーム1]![テキスト28]);"

これは正しく動作していますか?

この回答への補足

早速のお返事ありがとうございます。

レコードセットは何のために開いているというか、開かないとできないものかと思っていました。

他、動作に関してなんですが、正直動作していません。

いろいろ試したのですが、クエリにてSQLを実行すると動いているのがわかるのですが、条件分岐にに組み込もうとすると動きません。動かせません、、、。

補足日時:2008/06/16 13:44
    • good
    • 0

#1です



まずは、UPDATE文の見直しだけしてみると・・・

Dim mySQL as String
mySQL = "UPDATE 勤務表 SET ( " & _
"ユーザー名 = '" & [Forms]![フォーム1]![コンボ56] & "', " & _
"日 = #" & Format([Forms]![フォーム1]![テキスト88], "yyyy/mm/dd") & "#, " & _
"出社 = #" & Format([Forms]! [フォーム1]![テキスト8],"hh:nn") & "#, " & _
"退社 = #" & Format([Forms]![フォーム1]![テキスト17],"hh:nn") & "#, " & _
"作業内容 = '" & [Forms]![フォーム1]![テキスト 28] "' " & _
"Where [ユーザー名] = '" & [Forms]![フォーム1]![コンボ56] & "' " &_
"And [日] = #" & Format([Forms]![フォーム1]![テキスト88], "yyyy/mm/dd") & "# ;"
Debug.Print mySQL
mmcn.Execute mySQL

と、いう感じかな?

> 作業時間 日付/時刻型
の辺りは、基本的にクエリー上に生成するフィールドであって、テーブル上ではないと思うんだけど・・・「休憩時間」がないのが、引っかかってるのかな?
後、日付も・・・基本的に、出社時刻、退社時刻に、含められるから、クエリー上に作成、テーブル上に設定するフィールドじゃ、無いような・・・

> シングルクオートやダブルクオート等使い方が複雑で理解できていません。
これは、VBA上では、ダブルクオートのみが文字列として区分
SQL上では、シングルクオート、ダブルクオート同義、VBA上では、VBAの文字列と混同しないように、SQL用にシングルクオートを使用してると・・・特に好み次第で、使い方が違うという話^^;;;

この回答への補足

返信いただきありがとうございました。

実は、いろいろと調べていくうちにやりたい事は下記のコードで
できることがわかりました。せっかく高度なやり方を教えて頂いた
のに。。。早く教えて頂いた内容で使いこなせるよう勉強したいと
思います。今回は本当にありがとうございました。


'DCount関数で勤務表の中からユーザー名がコンボ56と同じ且つ日がテキスト88と同じものをカウントする
If DCount("*", "勤務表", "勤務表.ユーザー名 = " & _
"[Forms]![フォーム1].[コンボ56] AND 勤務表.日 = [Forms]![フォーム1].[テキスト88]") = 0 Then

'DCount関数の結果が0だったら挿入処理
DoCmd.RunSQL "INSERT INTO 勤務表 " & _
"(ユーザー名,月,日,出社,出社属性,退社,退社属性,作業時間,作業内容) " & _
"VALUES ([Forms]![フォーム1]![コンボ56], " & _
"[Forms]![フォーム1]![テキスト77], " & _
"[Forms]![フォーム1]![テキスト88], " & _
"[Forms]![フォーム1]![テキスト8], " & _
"[Forms]![フォーム1]![コンボ58], " & _
"[Forms]![フォーム1]![テキスト17], " & _
"[Forms]![フォーム1]![コンボ60], " & _
"[Forms]![フォーム1]![テキスト66], " & _
"[Forms]![フォーム1]![テキスト28]);"

Else

'DCount関数の結果が0ではなかったら更新処理
DoCmd.RunSQL "UPDATE 勤務表 SET " & _
"ユーザー名 = [Forms]![フォーム1].[コンボ56] , " & _
"月 = [Forms]![フォーム1]![テキスト77] , " & _
"日 = [Forms]![フォーム1]![テキスト88] , " & _
"出社 = [Forms]![フォーム1]![テキスト8] , " & _
"出社属性 = [Forms]![フォーム1]![コンボ58] , " & _
"退社 = [Forms]![フォーム1]![テキスト17] , " & _
"退社属性 = [Forms]![フォーム1]![コンボ60] , " & _
"作業時間 = [Forms]![フォーム1]![テキスト66] , " & _
"作業内容 = [Forms]![フォーム1]![テキスト28] " & _
"where ユーザー名 = [Forms]![フォーム1].[コンボ56] And 日 = [Forms]![フォーム1]![テキスト88];"
End If

補足日時:2008/06/17 18:03
    • good
    • 0

本題とそれてきましたのでこのあたりで最後にします。


http://office.microsoft.com/ja-jp/access/HA01117 …
ここが参考になると思うので読んでみてください。

また、検索サイトで「access SQL フォームの値」などのキーワードで検索してみるといいかもしれません。

いくつものことを一度にやろうとすると、うまくいかなかったときにどこが悪いのかわかりません。
MsgBoxなどを利用して自分の思い通りの値が取得できているかどうかを確認しながらプログラミングしたらいいと思います。

この回答への補足

今回は何度も教えて頂きまして本当にありがとうございました。

なんとかやろうとしている事はできました。

ただご指摘の通り一度に多くを求めるのはよくないと感じました。

また、なにかありましたらよろしくお願いします。

補足日時:2008/06/17 18:06
    • good
    • 0

No7です。



× MsgBox DLookup("*","勤務表","ユーザー名='xxxxx'")
○ MsgBox DCount("*","勤務表","ユーザー名='xxxxx'")

でした。
    • good
    • 0

順番に・・・ということで、まずは


If DCount("*", "勤務表",
"勤務表.ユーザー名 = [Forms]![フォーム1].[コンボ56] AND
勤務表.日 = [Forms]![フォーム1].[テキスト88]") = 0 Then
この部分をどうにかしてみたらいかがでしょうか?

フォームにボタンを設置して

'xxxxxはテーブルに存在する名前
MsgBox DLookup("*","勤務表","ユーザー名='xxxxx'")

のようなコードを書いてみてください。
テーブルにxxxxxさんが登録されている数がメッセージボックスで示されると思います。
次に、xxxxxを固定ではなくフォーム上のテキストボックスの入力した文字列が指定出来るようにするにはどうしたらいいか考えます。

というような感じで順番にプログラムを作っていくと良いかと思います。
ちなみに、これ以上詳しい説明を求めるのであればプログラムを組む以前にまず本を読んだ方がいいと思います。
初心者用の本でいいので1冊買ってみるのをおすすめします。

この回答への補足

度々のご返信感謝いたします。

ご指摘頂いた内容にてやってみたいと思います。

それとなんですが、、、
実は昨日のコードで勤務表テーブルに"ユーザー名"と"日"の組み合わせが1件も無い場合は入力フォームの値が勤務表にinsertされることは確認できたのですが、1件ある場合は

実行時エラー'3464' 抽出条件でデータ型が一致しません。

というエラーになってしまいます。どうやらupdateの構文が違うみたいです。

実は初心者用の本ほ3冊購入しており、会社にある2冊の計5冊をみながらやっているのですが、、、、情けないです。

ただ、どの本にもinsert,updateで
(1)フォームの値を指定する時の方法
(2)updateのWHERE句で2つの条件を指定する方法
が無く、悩んでおります。
(いづれの本もSQLに関してはクエリで条件を指定しテーブルにinsert,updateする等のやり方で、今回は参考にならなそうです。)

他、Meキーワードの使い方も何がおかしいのかわからない状態です。

お忙しいとは思いますが、アドバイス頂ければと思います。よろしくお願いします。

補足日時:2008/06/17 10:26
    • good
    • 0

#1です



> Format関数を使用してyyyy/mm/ddか、mm/dd/yyyyを指定してあげてください

ぁぁ、すみません
英語版Windowsだと、dd/mm/yyyyへ自動的に変換する場合があるので・・・yyyy/mm/ddの方が良いです
    • good
    • 0

#1です


> UPDATE文の更新条件の内容を
> (1)勤務表テーブルの"ユーザー名"がコンボ56と同じ
> (2)勤務表テーブルの"日"の値がテキスト88と同じ

のエラーがどう言うSQL文を出しているか判りませんが・・・
テーブルのデータの型によって文自体も変わります
ユーザ名はテキスト?数値?
テキストは「'」で前後を囲む、数値は不要
日は、テキスト?日付時刻型?
テキストは「'」で前後を囲む、日付型は「#」で囲む
で、日付時刻型のデフォルトは、PCの設定よって変換が変わりますので、Format関数を使用してyyyy/mm/ddか、mm/dd/yyyyを指定してあげてください
たまに自動だと、yyの2桁になる場合が、稀にあります

まずは、テーブルの型を提示しないと、明確な回答は出ないよ^^;

この回答への補足

ご返信ありがとうございます。
そして、当方の返信が遅くなり大変申し訳ありません。

さっそくなんですが、
UPDATE文を実行時のエラーは

実行時エラー '3464' 抽出条件でデータ形が一致しません。

というものです。

ユーザー名 は テキスト型、
日     は 日付/時刻型

他にも
月 数値型
出社 日付/時刻型
出社属性 テキスト型
退社 日付/時刻型
退社属性 テキスト型
作業時間 日付/時刻型
作業内容 テキスト型
というフィールドがあります。

素人の質問で大変申し訳ないのですが、

ユーザー名=[Forms]![フォーム1]![コンボ56]

の場合どこに ' を使用すればいいのでしょうか?

いろいろ自分なりにも調べてはいるのですが、シングルクオートやダブルクオート等使い方が複雑で理解できていません。
アドバイス頂けますでしょうか?よろしくお願いします。

補足日時:2008/06/17 10:31
    • good
    • 0

まずは動作するInsert文とupdate文を書くところから始めましょう。



ADOでもいいですが、ローカルテーブルが対象であれば
Docmd.RUNSQL "Insert into ~"
Docmd.RUNSQL "update ~ Set ~"
で事足ります。

また、
"ユーザー名=[Forms]![フォーム1]![コンボ56],・・・"
ではなく、
"ユーザー名='" & [Forms]![フォーム1]![コンボ56] & "',・・・"
のように書きます。

自分自身のフォームが対象であればMeキーワードを使った方がすっきりかけます。

いきなり長いコードを書くのではなく、一つずつ確認しながら書いていくことをおすすめします。

この回答への補足

度々のご返信ありがとうございます。
ご指摘頂いた内容でできるようにいろいろ試してはいるのですが、
どうやら
DCount , Insert , updateともシングルクオートもしくはダブルクオートの使い方がおかしいのかうまくいきません。

If DCount("*", "勤務表",
"勤務表.ユーザー名 = [Forms]![フォーム1].[コンボ56] AND
勤務表.日 = [Forms]![フォーム1].[テキスト88]") = 0 Then
DoCmd.RunSQL "INSERT INTO 勤務表 (ユーザー名,月,日,出社,
出社属性,退社,退社属性,作業時間,作業内容) VALUES (
[Forms]![フォーム1]![ユーザー名],
[Forms]![フォーム1]![月],
[Forms]![フォーム1]![日],
[Forms]![フォーム1]![出社],
[Forms]![フォーム1]![出社属性],
[Forms]![フォーム1]![退社],
[Forms]![フォーム1]![退社属性],
[Forms]![フォーム1]![作業時間],
[Forms]![フォーム1]![作業内容]);"
Else
DoCmd.RunSQL "UPDATE 勤務表 SET
勤務表.ユーザー名 = '" & [Forms]![フォーム1]![コンボ56] & "' , 勤務表.月 = '" & [Forms]![フォーム1]![テキスト77] & "' ,
勤務表.日 = '" & [Forms]![フォーム1]![テキスト88] & "' ,
勤務表.出社 = '" & [Forms]![フォーム1]![テキスト8] & "' ,
勤務表.出社属性 = '" & [Forms]![フォーム1]![コンボ58] & "' ,
勤務表.退社 = '" & [Forms]![フォーム1]![テキスト17] & "' ,
勤務表.退社属性 = '" & [Forms]![フォーム1]![コンボ60] & "' ,
勤務表.作業時間 = '" & [Forms]![フォーム1]![テキスト66] & "' , 勤務表.作業内容 = '" & [Forms]![フォーム1]![テキスト28] & "' where 勤務表.ユーザー名 = '" & [Forms]![フォーム1]![コンボ56] & "' and 勤務表.日 = '" & [Forms]![フォーム1]![テキスト77] & "';"

End If

他、Meキーワードは使用時エラーになってしまいます。
何度も申し訳ありませんが、よろしくお願いします。

補足日時:2008/06/16 18:35
    • good
    • 0

どうせDCOUNTで件数を求めるのにADOレコードセットを開くのなら


mmrs.Open "SELECT * FROM 勤務表 WHERE [ユーザー名] = '" & Me.コンボ56 & "' AND [日] = #" & Me.テキスト88 & "#"
でレコードセットを開き
mmrs.RecordCountが1ならフィールドに各コントロールの値を代入してmmrs.Update
mmrs.RecordCountが0ならmmrs.AddNewしてコントロール値を代入後Update
とかの方がソース的にはすっきりすると思うのですが

この回答への補足

ご返信ありがとうございます。
そして当方からの返信が遅くなり大変申し訳ありません。

ご指摘頂いた内容是非参考にさせて頂きます。

いろいろ試しておりまして、まだ、実際にできておりませんが、結果は

返信させて頂きたいと思います。

よろしくお願いします。

補足日時:2008/06/16 19:03
    • good
    • 0

ADOは、よく判りませんが・・・とりあえず気が付いた点で



> If DCount("[ユーザー名] & [日]", "[勤務表]", _
> "[ユーザー名]=[Forms]![フォーム1]![コンボ56]" & _
> "and[日]=[Forms]![フォーム1]![テキスト88]") = 0 Then

「"[ユーザー名] & [日]"」の、フィールド名が適切ではない
("*"で十分だと思うよ)
また、「and」の前後にブランクが無いため、演算子として、機能していない

環境によっては、誤動作の元になるので、「[Forms]![フォーム1]![~]」は、「"」の中ではなく、VBAにて値に変更して置く
うまく行けば動くが、うまく行かないと、動作しない可能性が残る

この回答への補足

ご返信頂きありがとうございました。
また、当方からの返信遅くなり大変申し訳ありません。

Formの値を変更する件は、一度やりたい内容ができてから修正
したいと考えています。その他はご指摘通り変更させて頂きました。

ただ、いろいろ試しておりますが、なかなかうまくいきません。
(今はUPDATE文の構文エラーという内容で進めなくなっています。)

UPDATE文の更新条件の内容を

(1)勤務表テーブルの"ユーザー名"がコンボ56と同じ
(2)勤務表テーブルの"日"の値がテキスト88と同じ

場合に更新するというふうに2つ設定する場合どのようにすればよいのでしょうか?アドバイス頂けると大変助かります。よろしくお願いします。

補足日時:2008/06/16 19:01
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!