Dim tempLastNo As Long '//条件により連番の初期値を変えたい
Dim lastNo
Dim newNo As Long
'//新規(条件グループの連番が見つからなかった時)の仮の連番を設定する
If Me!区分 = "後" Then
tempLastNo = 500
Else
tempLastNo = 0
End If
'//発行番号は「[コード]-[区分]-[連番(3桁0詰め)]」形式の文字列なのでうまいことなんやかんやする
lastNo = Nz(DMax("発行番号", "発行簿", "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"), tempLastNo)
newNo = Val(Right(lastNo, 3)) + 1
Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(newNo, "000")
データの更新問題につきまして、あちこちで更新されない状況が起きています…
コンボボックスには下記コードにてrequeryをつけたりしているのですが、
'''
private sub cbo更新したい_afterUpdate()
me.cbo更新したい.requery
end sub
'''
あっているでしょうか?
また、同期したいところがちょこちょこみつかるのですが、
テキストボックスやチェックボックスについても
全てにrequeryをつけるという対処方法になりますでしょうか?
Private Sub btnSubmit_Click()
Dim strFilter As String
'中略
'条件指定3_複数キーワード入力
'読点[、]区切りで部分一致でor条件 句点[。]区切りで部分一致でand条件)
If Me.txtWord3 <> "" Then
Dim strSubFilter As String
strSubFilter = Me.txtWord3
strSubFilter = "*" & Replace(strSubFilter, "。", "* And *") & "*"
strSubFilter = Replace(strSubFilter, "、", "* Or *")
strSubFilter = "(" & BuildCriteria("職名", dbText, strSubFilter) & ")"
strFilter = strFilter & " AND " & strSubFilter
End If
'後略
End Sub
Me.txtWord3 => strSubFilter
チーフ。リーダー => (職名 Like "*チーフ*" And 職名 Like "*リーダー*")
チーフ、リーダー => (職名 Like "*チーフ*" Or 職名 Like "*リーダー*")
チーフ。リーダー、ボス => (職名 Like "*チーフ*" And 職名 Like "*リーダー*" Or 職名 Like "*ボス*")
Dim matchOr as boolean
Dim matchAnd as boolean
matchOr = InStr("、", Me!txtWord) > 0
matchAnd = InStr("。", Me!txtWord) > 0
If matchOr And matchAnd Then
'「、」「。」両方含むとき'
ElseIf matchOr And Not matchAnd Then
'「、」だけ両方含むとき'
ElseIf Not matchOr AND matchAnd Then
'「。」だけ両方含むとき'
Else
'「、」「。」どちらも含まないとき'
End If
Const OrSeparator = "、"
Const AndSeparator = "。"
Dim filterWords
Dim n As Long
If Me!txtWord3 <> "" Then
filterWords = Split(Me!txtWord3, OrSeparator)
For n = 0 To UBound(filterWords)
filterWords(n) = BuildCriteria("[職名]", dbText, _
"" & Replace(StrConv(filterWords(n), vbWide), AndSeparator, " AND
") & "")
Next
strFilter = strFilter & " AND " & Join(filterWords, " OR ")
End If
Private Sub コマンド14_Click()
Dim FindWhat
FindWhat = DLookup("案件グループID", "クエリ1", "案件No='" & Me.テキスト12 & "'")
If IsNull(FindWhat) Then
MsgBox "該当する案件Noは見つかりませんでした。"
Else
Me.案件グループ.SetFocus
DoCmd.FindRecord FindWhat
End If
End Sub
hiroton様
回答頂きましてありがとうございます。
簡単に、どこかに条件分岐を入れるといいのかな~、などと考えていました。
式を分解して考える事が基本に繋がるのですね。
マネだけせずに、考えていきたいと思います。
ありがとうございます。
おかげさまで、上記の質問の内容は出来ましたが、追加がありました。
| 番号 | 名前 | 性別 |
| 1 | 猫 | オス |
| 6 | 猫 | メス |
| 2 | 猫 | メス |
| 5 | 犬 | オス |
| 4 | 犬 | オス |
| 3 | 犬 | メス |
このデータの場合、最優先は番号だとしたら、
| 番号 | 名前 | 性別 |
| 1 | 猫 | オス |
| 空白 | | |
| 2 | 猫 | メス |
| 空白 | | |
| 3 | 犬 | メス |
| 空白 | | |
| 4 | 犬 | オス |
| 5 | 犬 | オス |
| 空白 | | |
| 6 | 猫 | メス |
このようにしたいです。
グループで番号を優先にしても名前を優先にしても
うまくいかなかったので、大変申し訳ございませんが、
ご教授願います。
印刷はレポートでするのですよね。
まずは、
に関しては、下記を参考にしてください。
レコードがない場合も用紙の最後まで罫線を出力する - hatena chips
レポートの「グループ化/並べ替え」の機能で、
並べ替えの追加で「名前」フィールドを追加。
その後、グループの追加で「性別」フィールドを追加。
「ヘッダーセクションなし、フッターセクション付き」に設定。
以上です。
詳しく書いて説明して頂き、ありがとうございます。
出先のため、後日じっくりと勉強させていただきます。
フォームにレコードを表示していて、別のところ(別フォームや更新クエリ、VBAなど)で同じレコードを更新したときに、その更新が反映されないという意味でしたら、反映させたいフォームに対して Refresh すれば反映されます。
自分自身なら
Me.Refresh
、別フォームならForms!フォーム名.Refresh
ということになります。これはカレントレコードのみの更新です。
もし、帳票フォームで複数レコードの更新を反映させたいなら、フォームに対して Requery です。フォームに対してRequeryすると先頭レコードへ
前の回答のコンボボックスの Requery はValueの更新ではなく、コンボボックスのリストの更新になります。
Form.Refresh メソッド (Access) | Microsoft Docs
Requery メソッド (Access) | Microsoft Docs
式をバラバラにしてみましょう
処理は一番内側の括弧から順に処理されます。
バラバラにするなら下から順に処理を書けばいいということですね。
気を付ける点は、DMax関数は「値かNULL」が返ってくるところです。今回の場合、発行番号を対象にしているので「文字列かNULL」ですね。
条件に一致する発行番号がないとき(項目が新規の組み合わせの場合)、DMax関数がNULLを返すわけですが、この時の動きを調べてみてください。
結果を言うと項目が新規の組み合わせの場合、最新の番号として0(になる値)がとれるため、最新の番号+1で連番を作るということになっています。
この部分に条件分岐をいれてあげればいいですね。
ここまで何でもかんでも変数にして、とする必要はないですが、VBAで記述するなら適宜変数を置くと理解しやすくなります。
「Not(A and B and C and D)」は「(Not A) or (Not B) or (Not C) or (Not D)」と等価です。
クエリのデザインビューなら条件を横一列に設定すればANDですが、行を変えるとORになりますね。
データの更新問題につきまして、あちこちで更新されない状況が起きています…
コンボボックスには下記コードにてrequeryをつけたりしているのですが、
'''
private sub cbo更新したい_afterUpdate()
me.cbo更新したい.requery
end sub
'''
あっているでしょうか?
また、同期したいところがちょこちょこみつかるのですが、
テキストボックスやチェックボックスについても
全てにrequeryをつけるという対処方法になりますでしょうか?
マクロの選択の中に、「最新の情報に更新する」というものがあり
ページの頭にボタンを置いて更新をかけたりしますが、
それでも更新されないことがあり困っています。
教えていただきありがとうございます!連休中にじっくり読みます。
検索しても解決法に届かなかったため、大変助かりました。
ありがとうございました。
テキストボックスの印刷時縮小をはいに設定して下さい。
知識が幅広く必要なためか、あまりうまいこと解説しているところはないですね。
VBAとSQL
VBAはプログラミング言語です。
SQLは構造化照会言語(データベースを扱うための所定の書式)です。
VBAにはSQLを実行する機能がありますが、実行そのものはデータベースエンジンに丸投げします。なので、「SQL構文を文字列で指示する」までがVBAで出来ることです。そして、この文字列がSQLの文法として正しいかどうかすらチェックしません。ダメだったらダメだったときにエラーだと返ってくるだけです
SQL構文の例
VBAでSQLを実行する例
入力ミスをしてみましょう
VBAでSQLを実行する例(入力ミス)
実行しようとするSQL構文
単独の文字列としか見ないVBAではわかりにくいですが、SQL構文を色を付けてくれるエディタでみると間違っていることが分かりやすいですね。
実際には様々な部分を変数にしたいとなると思うので、ワンステップ置いて内容を確認するようにするといいです
&もあちこちに出ていますが、VBAでもSQLでも前後の文字列を連結するという役割をします。SQL構文を作るためのVBAの&なのか、SQLとして処理されるときの&(VBA上ではただの文字)なのか、これもコードの色分けがあるとわかりやすいと思います。
もちろん、SQLで処理するときでもただの文字として見たいということもあり得ます。
#
や'
リテラルのデータ型を表す文字です。
リテラルとはコード内に直打ちされた値のことです。
VBAではリテラルのデータ型によって
数値型 => 数値をそのまま
文字型 => 「"」で囲む ※「'」は使えない
日付型 => 「#」で囲む
(ACCESS)SQLではリテラルのデータ型によって
数値型 => 数値をそのまま
文字型 => 「"」または「'」で囲む
日付型 => 「#」で囲む
というように決まっています。
そしてこの(ACCESS)SQLでの「#」はかなりローカルな仕様です。
SQLとは単にそういった場合、本来、国際規格で決まっているモノで、それには日付型に「#」を使うルールはありません。そのため、SQLを勉強しようとしてもこの「#」についての解説はACCESSに言及しているようなところでしか見ることができません。
SQL構文を確認する
VBAならDebug.Printで実行直前の文字列を取得できます。フォームのテキストボックスなんかの場合はとりあえず「
="購入日=#" & [最新購入日] & "#"
」のように確認したい部分だけの式にするといいでしょう後はそれで表示された文字列をコピーして色分け表示すればいいです。
この掲示板ならコードブロックを使うと色分け表示できます。(上の誤りなSQLの表示を見ると今一歩な感じ)
Webサービスを探してもいいでしょう(SQL Fiddle(sqlfiddle.com)とか)
※ローカルルールな「#」にどのように対応しているのかは気に掛ける必要があります
そもそものもとになるSQL構文はクエリデザインから作成するのも手です。
適当な抽出条件を設定したクエリを作って、表示できることを確認したあとSQLビューを確認すればもとになるSQLが作れます。あとは「適当な抽出条件」としたところを変数に置き換えていけば動的に変化するSQL文が作れます。
デザインビューからの表示を通すことによって、データ型による囲み文字の補完、型不一致のエラーのチェックなんかができます
2つの主キーの片方と連結しているテーブルも削除できることを確認しました。
削除問題について、考え方が理解できておりません。
(削除できない=新規登録できない状況と理解しています)
フォームでレコードを削除しようとした場合、クエリで複数のテーブルのフィールドを持っているときは、何を削除することになるのでしょうか。
クエリで取り込まれている主キーのテーブルデータということで間違ってないでしょうか。
レコードを削除できなかった原因がわかりました。
2つの主キーを持っているテーブル(別々に2個)とクエリで連結していたのですが、
そこを取り除いたら削除できるようになりました。
主キーではない項目を使用して連結しているとダメという記事を読んだのですが、
2つの主キーの片方と繋ぐとダメなのでしょうか・・
また、一対一の関係性を持つテーブルを元にしたフォームも削除がきかなかったため
重複ありに変更しました。
BuildCriteriaは引数に決まった書式の文字列を要求するので1度通すと書式が不適切になってしまいます
あとは、例えば、「チーフ、、リーダー」のような誤入力(「、」が2回連続している)なんかも決まった書式を満たせずエラーになるので注意が必要ですね
文字列を区切り文字でsplitして配列に~な処理は今回はあまり適していない(hatenaさんの回答のほうが適切)なので、そういう関数もあるなぁくらいで大丈夫です
hiroton 様
迅速な回答いただき誠にありがとうございます。
hatena 様が教え得て頂いた>レス4で実装できました。
BuildCriteriaを2回重ねる事は出来ないのですね。
配列にして処理すること、加えて勉強させて頂きます。
hatena 様
迅速な回答いただき誠にありがとうございます。
句点、部分一致の文中の間違いご指摘ありがとうございます。
>あと、読点 と 句点 が混在する可能性はありますか。
>「チーフ。リーダー、ボス」とか。
読点 と 句点 が混在する可能性はありません。
どちらかでしか検索出来ないようにしたいとおもっています。
たたき台を使用させて頂きましたところ、
思っていたように検索が出来ました。
本当にありがとうございます。
教えて頂いたこと、勉強させて頂きます。
2は解決いたしました。クエリの中での、主キーとのつなぎ方の問題でした。失礼いたしました。
ありがとうございます!所持している本にも理屈が載ってなかったので、すごく助かります。熟読します。
いちおう、たたき台として、
読点(、)、句点(。)混在は可能ですが、And演算子がOr演算子より演算順位が高いので、
ユーザーがそれを理解していないと期待の結果にならない場合があるので注意が必要。
上記の strSubFilter には、下記のような条件式が格納されます。
部分一致が考慮されていないですね。
あと、AND と OR の演算優先順位を考慮する必要もあります。
可能ですが、下記の点について補足をお願いします。
'条件指定3_複数キーワード入力_読点[、]区切りであいまいor検索 読点[。]区切りで 完全一致(and検索)
の部分ですが、
読点[、]区切りであいまいor検索
は、あいまい(=部分一致) で or条件、つまり、複数のキーワードのうち一つでも含まれれば抽出する、
ということでよね。
読点[。]区切りで 完全一致(and検索)
は(読点は句点の間違いとして)、完全一致でand条件ということはありえないので、部分一致 で and条件ということですよね。
つまり、複数のキーワードをすべて含むデータを抽出する。
あと、読点 と 句点 が混在する可能性はありますか。
「チーフ。リーダー、ボス」とか。
テキストの中に「、」「。」が含まれているかどうかチェックすれば条件分岐はできます
BuildCriteriaを2回重ねることはできないので、どちらかの条件部分を自前で実装ですね。ただ、配列にして処理してしまえば出来上がった条件をつなげるだけなのであっさりできます
引用符に関しては、下記が参考になると思います。
Access上のコード内で引用符(")と単引用符(')の使い分けについて - hatena chips
上記のリンク先でもいってますが、まずは、VBAコードとSQLコードは違う言うことを意識する必要があります。
まずは上記の解説を読んで理解してください。
そのうえで、
=DLookUp("案件NO","Q_案件","購入日=#" & [最新購入日] & "#")
この DLookup はVBAの関数です。それぞれの引数は、
第一引数 フィールド名またはフィールド名を含む式を文字列で指定
第二引数 テーブル名/クエリ名を文字列で指定
第三引数 抽出条件式を文字列として指定
抽出条件式はSQLのコードです。クエリのSQLのWHERE句に記述する式のことです。
それをVBAの文字列とします。
あと、コード中で、数値、文字列、日付を扱うときは、扱いが異なります。
数値はそのまま、文字列は引用符で囲む(上記のリンクを参照)、日付は # で囲む、
という決まりです。
これはVBAでもSQLでも同じです。
うまくいきました!すごいです。
や&やコーテーションの使い方がいつまでたっても難しく感じます。
何か参考になる良いサイトはないでしょうか…
(今回下記サイトを参考にしていたのですが、#の件がのっていませんでした)
https://pctips.jp/pc-soft/access-dlookup-howto2019/
内容細かく見てないけど
=DLookUp("案件NO",[Q_案件],"購入日='" & [最新購入日] & "'")
↓
=DLookUp("案件NO","Q_案件","購入日=#" & [最新購入日] & "#")
かな?
適当なテキストボックスのコントロールソースにに「=[最新購入日]」としてみましょう。次に「=[Q_案件]」としてみましょう
詳しく教えていただき、ありがとうございます。
この件につきまして、最新購入日の他のフィールドをひっぱりたいのですがうまくいきません。
サブフォーム内にテキストボックスを作成し、コントロールソースに以下の式を入れましたが
「Name?」と表示される状況です。
コーテーションや「txt・・・」に変更したりと、苦戦しているのですがうまくいきません…
=DLookUp("案件NO",[Q_案件],"購入日='" & [最新購入日] & "'")
どこに問題があるのでしょうか??スミマセン…
フォームにはデータの操作について追加の許可、削除の許可、更新の許可のプロパティがあります
主フォームのレコード移動時と、グループタイトルの更新後処理でサブフォームのこれらのプロパティを変更すればロックは掛けられると思います
「グレーに」するも同じタイミングでサブフォームの背景色を変更してあげればそれっぽくなりそうですがどんな感じが希望なのかですね
更新のみが問題で対象がテキストボックスやコンボボックスだけなら条件付き書式を使ってフィールドの有効・無効を切り替えるでもいいと思います
Yes/No型フィールド(チェックボックス)なんかは条件付き書式が使えないのでこの方法は使えませんが
ありがとうございます!
すごく複雑なことかと思っていたのですが、こんなに短いコードで解決したのですね…
勉強不足でスミマセン。本当に助かりました。
送付されたファイル 検索したい.accdb
ファイル見ました。
「F案件グループ」フォームの検索ボタン「コマンド14」のイベントプロシージャを下記のように記述してください。
これでご希望の結果になると思います。
検索テキストボックス「テキスト12」はコンボボックスに変更するとより使いやすくなると思います。
「テキスト12」を右クリックして[コントロールの種類の変更]-[コンボボックス]をクリック。
「値集合ソース」に下記のSQLを設定します。
上記の改修をしたファイル 検索したい_hatena.accdb
②について説明不足でしたので書きなおします。
②サブフォーム内の案件NOに「5555」が含まれる、案件グループ「0002」のページを開く
こういった感じのことができるようにしたいです…
お返事ありがとうございます!先ほど「Microsoft Access 掲示板用ファイル送信」からサンプルデータを送信させていただきました。
具体的にやりたいことは、
①「F案件グループ」のヘッダーの検索ボックスで「5555」と検索
②サブフォーム内に「5555」が含まれる、案件グループ「0002」のページを開く
※案件NOが空のものも存在します。
※本当は存在しないで欲しいのですが、案件NOが複数のグループに存在する可能性もあります。
※案件NOをインデックス(重複無)にしないのは、空のものを作りたいことがあるためです。
以上になります。お時間ある際にご確認いただけたらうれしいです。
念の為に確認ですが、「案件グループフォーム」上にサブフォームコントロールがありそこに「サブ案件フォーム」が埋め込まれているということでしょうか。(たまに、主フォームと別に引いていフォームのことをサブフォームと表現される方がみえるので)
サブフォームコントロールだとするなら、リンク親フィールドとリンク子フィールドの設定を「案件番号」に設定すれば、自動でメインフォームの案件番号でサブフォームのデータは絞り込まれます。
これで解決でないのなら、メインフォーム、サブフォームのテーブルのフィールド構成、クエリならSQL文とうを提示して、どのようにしたいのか具体的に説明してください。
hatena様
返信おくれて申し訳ありません。
解説までしていただき、本当にありがとうございました。
そうだったんですね!ホッとしました。
できるだけ自分で調べたいと思いながらなかなか答えに辿り着けずで…
お忙しい中、いつもご回答ありがとうございます。
Accessは、データを削除してもファイルサイズは小さくなりません。実際にデータを削除するのではなく削除したというマークを付けるだけです。大量のデータを扱うのが前提のデータベースは一般的にこのような設計になってます。
つまり、データの追加、削除を繰り返すと、削除マークのついた無駄なスペースがどんどん増えていくわけです。
この無駄なスペースを削除する機能が「最適化/修復」です。定期的に「最適化/修復」を実行するようにするとファイルサイズが無駄に肥大することなく運用できます。
「名前を付けて保存」をするとこの無駄なスペースを除いてコピーが作成されるのだと思われます。
ということで特に気にすることはないと思います。
朝から「管理2」で作成していたデータにつき、
名前を付けて保存⇒「Accessデータベース」で新たに「管理3」として保存したところ
ますます容量が小さくなりました。
「管理」 25000KB
「管理2」13000KB ←朝より大きくなっている
「管理3」4000KB
気になってバックアップのサイズを確認したところ
4000KB程度のものと、15000KBのもの(バックアップ後に触った?)が存在しました。
サイズが異なり、不安になっております。
データ整理する際、消してはまずいものがありますでしょうか。
また、データ保存方法は
名前を付けて保存⇒「Accessデータベース」ではないのでしょうか。
※検索して見ていたのですが、特に保存に問題があるようには思えず…
インデックス(重複)にしたのち、色々設定を確認していたところ
設定に問題があったようで、案件IDなしで追加できるようになりました。
お騒がせして申し訳ありません。これで作っていきたいと思います。ありがとうございました。
>案件IDはなにか別のシステムから案件が正式に決まったときに発行されるとかなんですかね
仰る通りです。書き忘れており申し訳ありません・・
主キーからは外したのですが、インデックス(重複無)に設定していたり、リレーションシップの関係で、空白にしたり、仮で「0000」と入れておけないようです。
(設計に問題があるのか…?)
もう1つ別にテーブルを作った方がいいのかな、など考えております。(案件IDがないもの専用。案件が発行された時点で更新クエリを使って移動?)
他に良い方法があれば何卒ご教示ください😭
案件管理IDを別に用意して案件IDはインデックス(重複あり)で運用する
案件IDはなにか別のシステムから案件が正式に決まったときに発行されるとかなんですかね(ACCESSでは正式に決定される前に情報入力したいみたいな)
データとして存在するのに主キーとして設定できるフィールドがないのなら自前で用意するしかないですね