Microsoft Access 掲示板

views
4 フォロー
6,467 件中 1 から 40 までを表示しています。
12
はづき 2025/04/17 (木) 13:44:01 69f3e@da8eb >> 9

なな、なんと。そんなやり方ありましたか。
確認させていただきます。

11

サブフォームを作る労力とどのくらい差があるかなぁとも思っていしまいますし

ですよね。
フォームウィザードでデータシートビューで作成すれば1分もかからずに作成できますからね。
現状のロジックも参照先を変更するだけでそのまま使えるはずですし。

10
hiroton 2025/04/17 (木) 13:20:42 da23d@f966d >> 9

あー、なるほど、そういう仕組みありましたねぇ。使わないとパッと出てこないです
サブフォームを作る労力とどのくらい差があるかなぁとも思っていしまいますし

9
hatena 2025/04/17 (木) 12:26:04 修正

サブフォームコントロールにクエリ(データシート)を設定した場合、
代替案はないでしょうか?というのが冒頭での質問の本意です。

そういうことでしたか。
ソースオブジェクトにテーブルやクエリを設定した場合、メインフォームを開いたときに自動でサブフォームオブジェクトが生成されますので、それにイベントを設定することができます。
Accessのフォームの場合、イベントプロパティにFunctionを設定できますので、それを利用すればご希望のことは実現可能です。

まず、標準モジュールに下記のFunctionを記述してください。

Function CurentEvent()
    With CodeContextObject
        Debug.Print "レコード移動しました!IDは" & !ID
        .Parent!テキスト1.Value = !ID
   End With
End Function

CodeContextObject はFunctionが呼び出されたオブジェクトを返します。

メインフォームの読み込み時イベントに下記のコードを設定してください。

Private Sub Form_Load()
    Me.サブフォームコントロール名.Form.OnCurrent = "=CurentEvent()"
End Sub

クエリにはIDフィールドがあり、メインフォームには「テキスト1」というテキストボックスがあるという前提です。

メインフォームを開いてサブフォームでレコード移動してみてください。
イベントが発生しているのが確認できるでしょう。

13
beginner 2025/04/17 (木) 11:59:35 61dd6@2128d

hatenaさん ありがとうございます。
確かにSQLの文法と、VBAの文法がごっちゃになってました。それを意識しながら進めます。多分DAOが何なのかが理解できてないのですね。色々勉強していきます。自分のコードが妥当なのかどうか自信ない事が多いので・・・
今回も大変お世話になりました。

3
はづき 2025/04/17 (木) 11:56:42 69f3e@da8eb >> 2

なるほどです、クリック時のイベントでフラグを立てるというのは思ってもいませんでした。
貴重な情報、ありがとうございます。

8
はづき 2025/04/17 (木) 11:55:52 69f3e@da8eb >> 7

はやりそうですよね、当初の理解通りではありました。
現状、ボタンクリック時に呼び込みはできているので、
このためだめにサブフォームを作って、ロジックも変えないといけない工数が大きいので、
暫くは様子をみます。

7
hiroton 2025/04/17 (木) 11:47:40 6230f@f966d

なるほど、把握しました
ソースオブジェクトにフォームを指定しない場合は、明示的にイベントを発生させることができないので基本的には無理ですね

6
はづき 2025/04/17 (木) 11:40:43 69f3e@da8eb >> 5

なるほどです。すみません、説明不足でした。
サブフォームコントロールのソースオブジェクトは、サブフォームではなく、
クエリ(データシート)を設定しています。

サブフォームは作っていなくて、そもそもこれを作って設定すれば、
カレントのイベントが取れるというのは、冒頭でもお話した通り、理解はしております。

サブフォームコントロールにクエリ(データシート)を設定した場合、
代替案はないでしょうか?というのが冒頭での質問の本意です。

5

そういうことですね。つまりは、サブフォームコントロールではできないってことですか。

サブフォームコントロールにはサブフォームが埋め込まれているので、そのサブフォームのイベントに設定すればご希望のことは可能です。
サブフォームに設定したレコード移動イベントは、メインフォームを開いてサブフォームでレコード移動させれば発生します。

まずはやってみてうまくいかないなら、どのようにしたのか、記述したコード、どのようにうまくいかないのか説明してください。

4
はづき 2025/04/17 (木) 11:22:53 69f3e@da8eb >> 3

ありがとうごいざいます。

そういうことですね。つまりは、サブフォームコントロールではできないってことですか。
サブフォームとか単純なイメージコントロールが使えればこの問題はないのですが、
画像ファイルがクラウド上にありまして、ActiveXのwebbrowserコントロールを使う想定です。
画像を縮小したりもするので、イベントで制御しないと、と感じております。

3

メインフォームは閉じておいて、サブフォームをデザインビューで開いて、そのレコード移動時にイベントプロシージャを設定すればいいでしょう。

もし、メインフォームのイメージコントロールに顔写真を表示させていて、サブフォームには画像ファイルのパスが格納されているなら、
VBAを使うわなくても、イメージコントロールのコントロールソースにサブフォームの画像パスフィールドを参照するようにすればご希望のことは実現できると思います。

=[サブフォームコントロール名].Form![画像ファイルパスフィールド名]
2

前方一致の機能は、使えなくはないですが、組織に含まれる中間のキーワードをいれても上がってこず機能として藤生部です。

自己解決済みのようですが、下記で紹介している方法が参考になるかもしれません。

コンボボックスのリストを入力値で制限する
コンボボックスのリストに表示されるデータが非常に多いので、選択するのに苦労します。そこで、コンボボックスのテキストボックス部にデータの一部を入力すると、リストのデータがそれを含むものに制限されるようにしています。↓↑キーで選択できるようにしたいですが、↓キーで選択しようとすると一番上のデータしか選択できません。 このような質問をみかけました。リストを入力値で制限する方法はWEBでさがせば見つかると思い...
Fc2

12

NullがOKなら変数宣言時に Dim kensa As Variant としておくと rs![検査] = kensa の右辺には特に何もする必用ないという事ですね? 

はい、フィールドのデータ型がテキスト型の場合、それでほぼ問題ないです。
非連結テキストボックスは未入力の場合はNull値になりますので。
ただ、VBAで "" を代入したり、 "" を手入力した場合、Null値ではなく空文字列になりますので、注意が必要です。
この辺はいろいろ複雑なので説明しだすときりがなくより混乱しそうなので、とりあえずフィールドのプロパティで「空文字列の許可」を「いいえ」にしておいて、エラーが出たらその時に対応するということでいいでしょう。

ネットで調べても右辺固定値の場合は型指定がすべきとあるのですがフォーム値の場合は特にデータ型設定してないので、分からなかったのです。

これは、SQLの文法と、VBAの文法をごっちゃにしているのが、理解が進まない原因でしょう。

SQL文はVBAコード内では単なる文字列です。それをAccessやDAOがSQLとして解釈して実行します。単なる文字列ですから型指定は文字列内で型指定文字(')でします。

例えば下記のように'で囲んで文字列だと指定します。これはSQL文法です。

strSQL = "検査='" & Kensa & "'" 

DAOで更新する場合は、rs![検査] はVBAオブジェクトなのでVBA文法にそって記述します。ですので'で囲こむ必要はないです。

rs![検査].Value = kensa

コードを読むときやネット記事を読むときは、それがSQL文法なのか、VBA文法なのか意識して読むと理解がすすむと思います。

下記の記事もVBA上でSQLを扱う場合の注意点について説明していますので目を通しておくことをお勧めします。

Access上のコード内で引用符(")と単引用符(')の使い分けについて - hatena chips

2
はづき 2025/04/17 (木) 10:44:20 69f3e@da8eb >> 1

ありがとうございます。
すみません、全く理解できておりませんで。
情報が不足しておりましたので追記させていただくと、メインフォームは非連結フォームです。

>サブフォームそのものでレコード移動時のイベントが発生します

初歩的なご質問で恐縮です、このイベントにコードを書くのに、どのように呼び出す(表示)できますか。

1
hiroton 2025/04/17 (木) 10:26:32 6230f@f966d

サブフォームコントロールのイベントではなく、サブフォームそのものでレコード移動時のイベントが発生します
サブフォームからはMe.Parentで親フォームが参照できます

11
beginner 2025/04/17 (木) 10:14:25 61dd6@2128d

hatenaさん ありがとうございます。
NullがOKなら変数宣言時に Dim kensa As Variant としておくと rs![検査] = kensa の右辺には特に何もする必用ないという事ですね? この右辺を rs![検査] = ’ & kensa & ' としてもエラーになるので、どう設定するのかなと思ってたのです。
ネットで調べても右辺固定値の場合は型指定がすべきとあるのですがフォーム値の場合は特にデータ型設定してないので、分からなかったのです。DAOは勉強し始めでルールがあまり分かってないもので。

1
はづき 2025/04/17 (木) 10:02:25 69f3e@da8eb

場合分けせずに、デフォルトで設定するのはやめて、
キーワードが入ったら、コンボボックスにdistinct likeを使って該当組織を表示させることとしました。

10

非連結フォームのフィールド値を変数にしてテーブル追加させる場合、そのデータ形式も設定した方がいいのでしょうか? 
例えば下記の右辺がその変数で文字列の場合です。それはどう記述するといいでしょうか? また日付型の場合は?
rs![検査] = kensa

フィールドのデータ型と変数のデータ型は合わせた方がいいでしょう。
ただ、フィールドがNull値を許容する設定で、Null値を代入することがあるならVariant型かな。

日付型の場合は、変数に代入する前に日付として正しいかどうかIsDate関数でチェックするようにした方がいいですね。

9
beginner 2025/04/17 (木) 08:28:12 61dd6@2128d

hatenaさん ありがとうございます。
それの方が楽に出来そうですね。Recordset、RecordsetCloneも試して様子みます。
あと教えて頂きたいのですが、DAOでレコード追加(rs.AddNew)についてです。
非連結フォームのフィールド値を変数にしてテーブル追加させる場合、そのデータ形式も設定した方がいいのでしょうか? 
例えば下記の右辺がその変数で文字列の場合です。それはどう記述するといいでしょうか? また日付型の場合は?
rs![検査] = kensa
知識不足ですみません、宜しくお願いします。

8

因みにフォームの表示分を対象に色々する場面が多いのですが、SQL使わずDAOだけでも可能でしょうか? 

フォームに表示されているレコードはRecordsetプロパティで取得できますので、それを対象に更新すればいいですね。

    Dim rs As DAO.Recordset
    Set rs = Me.Recordset
    rs.MoveFirst
    Do Until rs.EOF
        rs.Edit
        rs!check = -1
        rs.Update
        rs.MoveNext
    Loop
    MsgBox "更新しました"

この方法はフォームに現在表示されているレコードを対象に更新しますので、SQLのようにWhere条件とか考慮せずに記述できるので楽です。

また、このコードだと、カレントレコードが先頭から最後まで移動しながら更新していきます。
レコード移動させたくない場合は、Set rs = Me.Recordsetの部分をSet rs = Me.RecordsetCloneとします。こうすればレコード移動せずに更新できます。

ただ、SQLで更新するのと比べると処理速度は遅くなります。ただし、フォームに表示されている件数が多くなければ体験できる差はでないでしょう。

この辺の詳細は興味があれば下記を参照して研究してみてください。

フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips

1
あん 2025/04/16 (水) 14:44:23 b41ab@0c44c

すみません。解決しました。ありがとうございました。

7
beginner 2025/04/16 (水) 14:31:06 61dd6@e1025

hatenaさん ありがとうございます。
UPDATE [フォームソースのクエリ名] にしたら正常に対象分(表示されているレコードリスト)のみYesに出来ました!
クエリを更新する事でソースであるテーブルを更新させてもいいのですね。
[T_製造履歴]には完成年フィールドがなかったのでフィルターが出来なかったのですね。前回投稿と同じ様な事例でした。
まだ完全には理解出来てないと思いますがパラメータになってしまうというのが大分イメージ出来ました。
自分では絶対解決出来ない事でしたので本当に助かりました。
因みにフォームの表示分を対象に色々する場面が多いのですが、SQL使わずDAOだけでも可能でしょうか? DAOは余り理解出来てないのですがフォームの表示レコードをレコードセットにするイメージで。

6

ちなみに、「WHEREのMe.filterが効いてなく全レコードがチェックON」になるのは、
Accessは[完成年]をパラメータとして判断して、まずはアクティブフォームから探します。
フォームには[完成年]というフィールドがありますから、その値をパラメータ値として取得します。フォームの[完成年]を参照するとカレントレコードの値を取得します。
カレントレコードの完成年が2025年で、[cb完成年]で2025年を選択していればすべてのレコードの[check]がオンになります。

5

「完成年」フィールドは日付型の完成日がT_製造履歴にあり、それを使ってYear([完成日付])をそのクエリに組み込んでます。

[T_製造履歴]テーブルには[完成年]フィールドはないということですよね。
ならば、[完成年]はパラメータとして判断されますので、
”実行エラー3061 パラメータが少なすぎます。1を指定して下さい”
というエラーになります。

SQLの[T_製造履歴]の部分をフォームのレコードソースのクエリに変更するか、
下記のようにサブクエリにして[完成年]、[完成月]の演算フィールドを追加すればいいでしょう。

strSQL = _
    "UPDATE " & _
    "(SELECT *, Year(完成日) As 完成年, Month(完成日) As 完成月 FROM [T_製造履歴]) " & _
    "SET [check] = -1 " & _
    "WHERE (" & Me.filter & ");"
4
beginner 2025/04/16 (水) 11:05:34 61dd6@e1025

hatenaさん ありがとうございます。
試した分のイミディエイトウィンドウには UPDATE [T_製造履歴] SET [check] = -1 WHERE ([製品ID]=377 AND [完成年]=2015); と表示されました。
フォームのレコードソースは「T_製造履歴」を基にして他のテーブルを連結させたクエリとしてます。
「完成年」フィールドは日付型の完成日がT_製造履歴にあり、それを使ってYear([完成日付])をそのクエリに組み込んでます。フォームの抽出コンボ完成年のソースも同じクエリから取ってきてます。

3

とりあえず上の回答のデバッグコードを試してみて、出力されたSQL文を提示してください。

あと、下記を確認ください。
フォームのレコードソースは「T_製造履歴」で間違いないですか。
「完成年」フィールドのデータ型は数値型ですか。

2
beginner 2025/04/16 (水) 09:42:41 61dd6@e1025

状況の追記です。この一覧フォームのフィルター用コンボボックスには製品ID、顧客ID、完成年、完成月、完成日があります。製品IDが未選択時はリスト表示出来ない様にしてます。各コンボ選択(更新後)ではフィルター(投稿したコードを各コンボからCall)が効いてフォームのリスト表示は問題ありません。リスト表示分のみcheckをYesに更新させるボタン(投稿したコード)で更新させる形です。その後、DoCmd.RunSQL strSQL を CurrentDb.Execute strSQL にして試しして下さいみると製品IDと顧客IDは問題なくフォーム表示分のみYesになります。完成年コンボで抽出後ではフォーム表示は問題ないのですがYesに更新実行すると”実行エラー3061 パラメータが少なすぎます。1を指定して下さい”となります(前回投稿と同様)。因みにコンボ完成月、完成日は完成年が未選択では不可にしてます。DoCmd.RunSQL strSQL では実行されるのですが完成年条件が無視されて指定の製品ID分の全レコードがcheck Yesになります。
何かコードに不備があるのでしょうか?

1

下記のようにデバッグ用のコードを埋め込んで実行してみてください。

strSQL = _
         "UPDATE [T_製造履歴] SET [check] = -1 " & _
         "WHERE (" & Me.filter & ");"
Debug.Print strSQL 'デバッグ用
Exit Sub           'デバッグ用

イミディエイトウィンドウにstrSQLに格納されているSQL文が出力されますので、それが正しいものになっているか確認しましょう。

6
beginner 2025/04/15 (火) 15:50:21 61dd6@e1025

skさん ありがとうございます。フィールドの名前とも一致しない識別子の事も大変重要ですね。今まで認識してなかったので勉強になりました。ACCESSは名前で判断されるので注意が必要ですね。
確かに「I'm sorry.」ではエラー出ましたのでReplace・・・にしたらOKでした。
細かい設定をしないと、どこでエラーになるか分かりませんね、いい経験となりました。ACCESSは奥が深く大変ですが、コツコツするしかありません。色々な事を教えて頂けて大変有り難いです。
本当に感謝です。

5

前回質問分でhirotonさんとhatenaさんから回答頂いた下記は
CurrentDb.Execute strSQLでいけたのですが、これは何故でしょうか?

変数 strSQL に格納された SQL 文の中に「パラメータと解釈し得る要素」が含まれておらず、
また SQL 全体において構文上の不備がないからです。

この場合の「パラメータと解釈し得る要素」とは、主に次のようなものです。

  • データベース上のどのテーブル/クエリの名前とも一致しない識別子

  • クエリから呼び出されたテーブル/クエリのどのフィールドの名前とも一致しない識別子

件の INSERT INTO 文 においては、Forms![F_改修履歴に追加設定]![tx受付日付代入用]などの記述は
FROM 句で呼び出されている[T_製造履歴]のどのフィールドの名前とも一致しないため、
暗黙的に「そういう名前のパラメータである」と解釈されます。

strSQL = ", [完成日付]=" &  Format(Me!change_Date, "#yyyy/mm/dd#")

上記の場合は非連結テキストボックス[change_Date]の値が
「 SQL 内における日時リテラル」として組み込まれるよう
文字列の整形と文字列連結が行われており、最終的に
UPDATE 文の中に「パラメータと解釈し得る要素」が
含まれないようになっています。

strSQL & ", [備考]='" & Me!change_Biko & "'"

ちなみに、この時の非連結テキストボックス[change_Biko]の値が
「I'm sorry.」という文字列だった場合、SQL 上の構文エラーが発生します。

文字列リテラルの囲み記号としてシングルクォーテーションを使用する場合は、
文字としてのシングルクォーテーションを次のようにエスケープした方がよいでしょう。


If Not IsNull(Me!change_Biko) Then strSQL = strSQL & ", [備考]='" & Replace(Me!change_Biko, "'", "''", 1, -1, vbBinaryCompare) & "'"

SQL 文のチェック作業を行なう際には、

'イミディエイトウィンドウに変数 strSQL の値( SQL 文)を出力
Debug.Print strSQL
'変数 strSQL に格納された SQL 文を実行
CurrentDb.Execute strSQL

以上のようにしておき、生成された SQL 文が実際に
どのようになっているかを確認してみることをお奨めします。

4
beginner 2025/04/15 (火) 08:57:51 61dd6@e1025

hirotonさん skさん 詳細な回答ありがとうございました。なりほどそういう事だったのですね。
因みに前回質問分でhirotonさんとhatenaさんから回答頂いた下記はCurrentDb.Execute strSQLでいけたのですが、これは何故でしょうか? 更新と追加の違いはありますが(完全に理解出来てなくすみません)

Dim strSQL As String
If Not IsNull(Me!change_Date) Then strSQL = ", [完成日付]=" &  Format(Me!change_Date, "#yyyy/mm/dd#")
If IsDate(Me!change_Kokyaku) Then strSQL = strSQL & ", [顧客ID]=" & Me!change_Kokyaku
If Not IsNull(Me!change_Firm) Then strSQL = strSQL & ", [firmID]=" & Me!change_Firm
If Not IsNull(Me!change_Tanto) Then strSQL = strSQL & ", [製造担当者ID]=" & Me!change_Tanto
If Not IsNull(Me!change_Biko) Then strSQL = strSQL & ", [備考]='" & Me!change_Biko & "'"

If strSQL = "" Then Exit Sub

strSQL = "UPDATE [T_製造履歴] SET " & Mid(strSQL, 3) & " WHERE [check]=True;"

3

なお、任意のコントロールの値を「 SQL 内におけるリテラル」として文字列連結させる手法もよく見られますが、以下のようなケースに備えてエスケープ処理を行うことが望ましいでしょう。

  • コントロールの値(文字列)にシングルクォーテーション( ' )やダブルクォーテーション(")、改行(などの制御文字)が含まれている場合。

  • コントロールの値が Null である場合。

DAO.QueryDef オブジェクトを使用してパラメータの値渡しを直接行なうのであれば、エスケープ処理は不要です。

2

実行時エラー'3061'
パラメータが少なすぎます。4を指定して下さい。

変数 strSQL に格納されている SQL がパラメータクエリになっているからです。

Forms![F_改修履歴に追加設定]![tx受付日付代入用]

Forms![F_改修履歴に追加設定]![tx改修内容代入用]

Forms![F_改修履歴に追加設定]![tx完了日付代入用]

Forms![F_改修履歴に追加設定]![tx_memo代入用]

以上の 4 箇所がそれぞれ暗黙的なパラメータとして認識されています。

そして DAO.Database オブジェクトの Execute メソッドでは、
パラメータへの値渡しを行うことが出来ません。

この場合は、次のいずれかの方法を用いるのが妥当です。

'Access のシステムメッセージの表示を無効にする
DoCmd.SetWarnings False
'Access の[SQL の実行]アクションを呼び出す
DoCmd.RunSQL strSQL
'Access のシステムメッセージの表示を有効にする
DoCmd.SetWarnings True
'フォーム[F_改修履歴に追加設定]のフォームモジュールから実行する場合

Dim dbTarget As DAO.Database
Dim qdfTemp As DAO.QueryDef
Dim lngInsertedCount As Long

'カレントデータベースの参照
Set dbTarget = CurrentDb
'一時的なクエリを作成する
Set qdfTemp = dbTarget.CreateQueryDef("", strSQL)

With qdfTemp
    '各パラメータに値を渡す
    .Parameters("Forms![F_改修履歴に追加設定]![tx受付日付代入用]").Value = Me![tx受付日付代入用].Value
    .Parameters("Forms![F_改修履歴に追加設定]![tx改修内容代入用]").Value = Me![tx改修内容代入用].Value
    .Parameters("Forms![F_改修履歴に追加設定]![tx完了日付代入用]").Value = Me![tx完了日付代入用].Value
    .Parameters("Forms![F_改修履歴に追加設定]![tx_memo代入用]").Value = Me![tx_memo代入用].Value
    'クエリを実行する
    .Execute dbFailOnError
    'クエリによって影響を受けたレコードの件数を取得する
    lngInsertedCount = qdfTemp.RecordsAffected
End With

Set qdfTemp = Nothing
Set dbTarget = Nothing

If lngInsertedCount > 0 Then
    MsgBox "[T_登録中継用_改修履歴]に " & lngInsertedCount & " 件のレコードが追加されました。", _
           vbInformation, _
           "実行完了"
Else
    MsgBox "追加対象となるレコードがありません。", _
           vbInformation, _
           "対象レコードなし"
End If

後者の方法は、主に以下のようなケースにおいて用いるのが適しています。

  • 特定のインターフェース(この場合はフォーム)に依存せず、パラメータに任意の値を直接渡したい場合

  • 実行されたクエリ/SQLによって影響を受けたレコードの件数を取得したい場合

  • DAO.Workspace オブジェクトと連携してトランザクション処理を行いたい場合

1
hiroton 2025/04/14 (月) 14:09:42 c632e@f966d

DoCmdは「ACCESS」の機能を呼び出します
「ACCESS」は、自身がどんなフォームがあるだとか、そこにどんなコントロールがあるだとか認識できます。なので、クエリ実行時(DoCmd.RunSQL)にForms![F_改修履歴に追加設定]![tx受付日付代入用]が何者か判断できます

CurrentDb.Executeは「DAO」の機能を呼び出します
「DAO」はACCESSの構文を解釈する機能はないので、Forms![F_改修履歴に追加設定]![tx受付日付代入用]を一つの、そのような名称のパラメータ(変数)として解釈しようとします。結果、そのようなパラメータを用意していないDAOを実行しようとして、パラメータが少なすぎますとエラーを返してきています

CurrentDb.Executeを使うのであれば、DAOで実行する前に、VBAで値の変換を済ませておく(strSQLの中にフィールド指定の構文を入れない)必要があります

strSQL = _
    " INSERT INTO T_登録中継用_改修履歴" & _
          " (製造履歴ID, 受付日付, 改修内容, 完了日付, MEMO)" & _
    " SELECT" & _
          " 製造履歴ID" & _
          ", #" & Forms![F_改修履歴に追加設定]![tx受付日付代入用] & "#" & _
          ", '" & Forms![F_改修履歴に追加設定]![tx改修内容代入用] & "'" & _
          ", #" & Forms![F_改修履歴に追加設定]![tx完了日付代入用] & "#" & _
          ", '" & Forms![F_改修履歴に追加設定]![tx_memo代入用] & "'" & _
    " FROM T_製造履歴" & _
    " WHERE check=True;"

参考
パラメータクエリを含むSQLをVBAから実行する(hatena chipsさん)


英語でのエラーだと、たとえば

"Run-time error '3061'. Too few parameters. Expected 1."

のようになるようです。ネイティブならすんなり意味が分かるんでしょうか。日本語にするなら

”実行時エラー'3061'
パラメータが少なすぎます。パラメータが1つ必要です。”

隠れた文字が表現されているといいと思いますし、意訳して「パラメータが1つ不足しています」とかなるとわかりやすいんじゃないかと

7
beginner 2025/04/10 (木) 11:35:41 61dd6@e1025

hirotonさん ありがとうございます。大変勉強になります。
""では上手く検出出来ませんでしたが、よく考えると全角スペースには有効ではありませんでした。この非連結テキストボックスには入力し易い様にプロパティに ひらがな 設定してます。なので全角状態になっているからでした。なのでフォーカス喪失後イベントに下記を記述しました。他の変更用非連結部は全てコンボボックスからの選択ですので大丈夫です。
確かに「備考を削除する」の想定もありますね。様子みて作成していきます。
Nullと""、" " の違いは難しいですね。本当にありがとうございました。

     If Me.[change_Biko] = "" Or Me.[change_Biko] = " " Then
        Me.[change_Biko] = Null
     End If
    ```  
6
hiroton 2025/04/10 (木) 10:48:08 b4b71@f966d

通常、非連結のテキストボックスに""(長さ0の文字列)が入ることはありません
フォーム上での人の操作で「何か入力」→「Delete等で削除」を行うと、非連結のテキストボックスの内容はNULLになります。(レコードソースに連結されたコントロールの場合、設定によっては""が入る場合があります)

VBAによる操作等で、直接 Me!テキストボックス = "" のような処理を行うと、非連結のテキストボックスでもその値が""になったりはします

そもそも気にしていなかったのですが、逆に、「備考を削除したい」という場合はないのでしょうか?
「NULLなので更新対象外」と、「内容削除のために""が入力されている」は実作業の上では判別できないので、「備考を削除する」チェックボックスを追加で用意するとかになると思います

また、とりあえず、回答ではIsNull()を使っていますが、NULL""同じように扱われればよいなら Me!テキストボックス & "" = "" で判定できます

Select Case True
    Case Me!Delete_Biko
        strSQL = strSQL & ", [備考]=''"
        '// データ構造によっては
        '// strSQL = strSQL & ", [備考]=NULL"
    Case Me!change_Biko & "" <> ""
        strSQL = strSQL & ", [備考]='" & Me!change_Biko & "'"
End Select

そのほかのコントロールについても、データ型が文字列型以外になるのならばIsDate()IsNumeric()等で判定してあげるとより良いと思います

Not IsNull(Null) ' =>False
Not IsNull("")   ' =>True
IsDate(Null)     ' =>False
IsDate("")       ' =>False
5
beginner 2025/04/10 (木) 09:44:03 61dd6@e1025

hirotonさん hatenaさん ありがとうございます。
なるほどです! 複数FilterのWHERE組立の様にしたらいいのですね(,の件も確かにそうですね)。
コマンドボタンにコード記述したら上手くいきました。
あと一つだけアイデア頂きたいのですがchange_Bikoに誤って""(長さ0の文字列)だけが入力されて、それが更新に反映されるのを防ぎたいのですが、それはどうすればいいでしょうか?

★この履歴の更新ですが登録ミスの変更や仕様変更等が発生した場合の変更をまとめてする為のものです(最終的な正しい履歴にする為の)。

宜しくお願いします。

4
hiroton 2025/04/10 (木) 09:26:05 b4b71@f966d >> 3

あー、そうですね。訂正ありがとうございます
フォームに見えてるデータならDAOでやるかなぁとか考えていたらろくにテストもせず投稿してしまいました

3
hatena 2025/04/09 (水) 23:03:51 修正 >> 1

前者のコードだと、Me!change_Biko がNullのとき、WHERE の直前に , が来ることになりSQLエラーになりますね。
例えば、直前に, を付けておいて最後に先頭の, を削除してSQL文を完成させるようにすればいいでしょう。

Dim strSQL As String
If Not IsNull(Me!change_Date) Then strSQL = ", [完成日付]=" &  Format(Me!change_Date, "\#yyyy/mm/dd\#") 
If IsDate(Me!change_Kokyaku) Then strSQL = strSQL & ", [顧客ID]=" & Me!change_Kokyaku
If Not IsNull(Me!change_Firm) Then strSQL = strSQL & ", [firmID]=" & Me!change_Firm
If Not IsNull(Me!change_Tanto) Then strSQL = strSQL & ", [製造担当者ID]=" & Me!change_Tanto
If Not IsNull(Me!change_Biko) Then strSQL = strSQL & ", [備考]='" & Me!change_Biko & "'"

If strSQL = "" Then Exit Sub

strSQL = "UPDATE [T_製造履歴] SET " & Mid(strSQL, 3) & " WHERE [check]=True;"
CurrentDb.Execute strSQL

後者のコードはカレントレコードの値で上書きしてしまいますね。
「元の値と同じ値で書き換える」なら下記のような感じになるかと。

Dim txDt  As String, koID As String, fiID As String, taID As String, txBiko As String
txDt = IIf(IsNull(Me!change_Date), "[完成日付]", Format(Me!change_Date, "\#yyyy/mm/dd\#"))
koID = Nz(Me.change_Kokyaku, "[顧客ID]") 
fiID = Nz(Me.change_Firm, "[firmID]") 
taID = Nz(Me.change_Tanto, "[製造担当者ID]")
txBiko = IIf(IsNull(Me.change_Biko), "[備考]", "'" & Me.change_Biko & "'")

Dim strSQL As String
strSQL = "UPDATE [T_製造履歴] " & _
         "SET [完成日付]=" & txDt & ", " & _
         "[顧客ID]=" & koID & ", " & _
         "[firmID]=" & fiID & ", " & _
         "[製造担当者ID]=" & taID & ", " & _
         "[備考]=" & txBiko & " " & _
         "WHERE [check]=True;"

CurrentDb.Execute strSQL