[▲]区切りで、複数の(not条件)除外検索
If Not IsNull(Me.txtWord4) Then
strFilter = strFilter & " AND " & BuildCriteria("職名", dbText, _
"*" & Replace(StrConv(Me.txtWord4, vbWide), "▲", "* And Not *") & "*")
End If
If Me.CurrentRecord < 1 Then
'//抽出でレコードが見つからなかったので新規登録画面を表示する
Me.AllowAdditions = True
'//抽出内容を設定する
Me!日付.DefaultValue = Me!検索用日付
Me!氏名.DefaultValue = Me!検索用氏名
End If
Option Compare Database
Option Explicit
Private preValue As String
Private Sub グループヘッダー1_Format(Cancel As Integer, FormatCount As Integer)
If preValue = "" Or preValue = Me.名前.Value & " " & Me.性別.Value Then
Cancel = True
End If
preValue = Me.名前.Value & " " & Me.性別.Value
End Sub
Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)
preValue = ""
End Sub
Dim lastID As String
Dim newNo As Long
lastID = Nz(DMax("発行番号", "発行簿", "コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'"))
If lastID = "" Then
'//新規(条件グループの連番が見つからなかった時)なので初期値を設定する
If Me!区分 = "後" Then
newNo = 501
Else
newNo = 1
End If
Else
'//連番部分を取り出して1増やす
newNo = Val(Right(lastID, 3)) + 1
End If
Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(newNo, "000")
管理番号の中にCSDという文字が含まれていなかったらどうしたい?がないと回答も中途半端にしかできないですが
InStr 関数
基本、InStr()は結果が数値です
InStr(~)=""
という比較はしません。やるなら「0」と比較して次の形ですIIf(InStr(~)>0,あるとき(,ないとき))
IIf(InStr(~)=0,ないとき(,あるとき))
「
価格 = Int(価格 - (220 * 0.088 + 100) * 0.95 / 0.934+0.5)
」と「価格 = Int(価格 - (220 * 0.088) * 0.95 / 0.934+0.5)
」はどちらも(左辺)=(右辺)
の形になっています。比較の式なので結果は
True
かFalse
ですね。たぶん、フィールド名を「価格」としたいのだと思いますが、この場合は(式) AS 価格
のように、式の後にAS句をつなげてフィールド名を記述します
Likeで指定年度を検索して、除く年度を除外すること自体が矛盾してるのでは?
もしかしてやりたいことは、指定年度から除く年月を除外したいのでしょうか?
Cd = "管理番号,Int((価格 - IIf(管理番号 = 'csd-',19.36,119.36) 0.95) / 0.934)
と変更して、その場しのぎはできたのですが、
非常に汎用性が低いので、
正しい処理の仕方を、ご教授できたらと思います。
でいかがでしょうか。
kitasue 様
度々のレス失礼します。
別枠で新たに除外検索用に、
txtWord4というテキストボックスを用意し、
除外ワードだけを複数指定するという事は実現できました。
レス2番のように1つのテキストボックスで、
複数の除外ワードを指定する事が、
実現可能でしたらお知恵をお借り出来ましたらありがたいです。
よろしくお願いします。
kitasue 様
回答いただき誠にありがとうございます。
コードを使用させて頂きましたところ、
▲後のワードで除外検索が出来ました。
<質問>
大変恐縮ですが追加で質問させていただきます。
下記のように除外ワードを複数指定し検索は可能でしょうか?
(読点[、]でor条件、句点[。]and条件では、
複数ワードを指定出来たのですが、除外検索では難しいでしょうか?)
職名というレコードに
チーフ
SPチーフ
ADチーフ
というレコードがあったとして、
検索語句例:チーフ▲SP▲AD
→職名でチーフ が含まれるレコードのうちで、SP と AD を除いたレコードが検索表示される
※現在のコードで、上記の検索をすると下記のようなエラーmsgが出ました。
「実行時エラー'2435'
指定した式の閉じかっこが多すぎます。」
もし良い案がありましたら、教えて頂けましたら幸いです。
セキュリティが最優先事項ならACCESSはNGじゃないですかね
テーブルデータを保護する(hatena chipsさん)
ACCESSパスワード強制解除とかで検索するとそれなりに情報出てくるし
ある程度妥協できるなら
1.上記リンクのとおり、SharePointとのリンク部分はパスワード付きのACCESSファイルで制限、実行ファイルはパスワード埋め込みつつACCDEファイルにして参照情報閲覧不可
2.VBAでレコードセットを動的に生成&VBAをパスワードで保護( VBAのモジュールにパスワードを設定するには?(T'sWareさん))
3.SharePointにODBC接続できるドライバを用意して実行ファイルに接続情報を埋め込みつつACCDEファイル化する(サードパーティ製のドライバが必要っぽい)
※かるくWebを漁ってみた(試してない)結果なのでご了承を
でいかがでしょう。
スミマセン。自己解決しました。
スッキリしました!教えていただき、ありがとうございました。
>デフォルトの仕様を否定するほどのメリットは感じられませんね
今まで参考にしていた本が全て(?)txtなど付けるものだったので
目から鱗が落ちました。
現在作成中のものは付けてしまったので今更変更しづらいですが、今後参考にさせていただきます
とりあえずはその認識であっています。
フォームのフィルターに指定する文字列や、定義域集計関数(DLookupとか)の条件部分はSQLのWHERE句に相当する文字列を指定することになっています。
WHERE句はその条件指定で
(フィールド名)(比較演算子)(値)
の形をとれるため、これに従ってフィールド名を要求している部分にフィールド名を記述するというわけです。で、この時に使えるフィールド名はそのSQL文が実行されるときの対象となるデータ(テーブル、クエリや、フォームのフィルタならレコードソース)のフィールド名となります。
VBAの処理で文字列が生成され、その文字列をSQLとして処理する。「SQLに関わるとき」はそんな処理をしているんだと理解できるとフィールド名の使いどころもわかると思います。
特に間違いはないですが、コントロール名とフィールド名の間に制約はないので、レコードソースの「タイトル」フィールドを参照するコントロールに「タイトル」という名前を付けることは普通にできることです。(コントロール名「タイトル」のコントロールソースに「タイトル」を指定する)
実際、既存のフィールドの追加からコントロールを追加するとデフォルトでフィールド名をコントロール名としたコントロールができるのがACCESSの仕様ですし
テーブル名はTから始めましょう、クエリ名はQから始めましょうのイメージでテキストボックスならtxt、チェックボックスならchkという話はあるのかもしれませんが、デフォルトの仕様を否定するほどのメリットは感じられませんね
ちなみに悩む、というのが
If chkタイトル = True Then ←この時はコントロール名
DoCmd.OpenForm "F_作品", , , "作品NO='" & Me!txt作品NO ←フィールド名とコントロール名
上のようなときです。
SQLに関わるときがフィールド名になるのでしょうか?
なんだか色々勘違いしていたようで…すみません。
フィールド名は大元の名前(テーブルのフィールド名) 例:「タイトル」
コントロール名はフォームでテキストボックス等につける名前 例:「txtタイトル」
ですよね?
>フィールドを参照するコントロールをフィールド名と異なるコントロール名にすることがまずないので
?認識が間違っているでしょうか…😓
フィールドとはテーブルやクエリで設定した列のことを言います。フィールド名はその各列を識別するための名前ですね。
「txtタイトル、みたいなもの」はフォーム上に設置したテキストボックスやコンボボックスにつけた名前ですよね?これらフォーム上に設置するモノのことをコントロールと言います。ですので、「txtタイトル、みたいなもの」はコントロール名です。
「コントロールソースを引用する」ということは通常しません。
掲示板でのやり取りの関係上、「txtタイトルのコントロールソースを指定してください」と回答することはありますが、往々にして質問者がコントロール名しか提示していないためフィールド名がわからずそうせざるを得ない。といった理由からです。
よく使うので覚えてしまったものもありますが、やりたいことで検索したりMicrosoft公式のドキュメントを見れば書いてあるのでその通りにやるだけです。フィールド名を指定する必要がある場所にはそう書いてあります。
そもそもの話、フィールドを参照するコントロールをフィールド名と異なるコントロール名にすることがまずないので、どうしてそんなことに・・・などと思ってしまいますが
コントロールが表示されてもいいのならテキストボックスでそれっぽく代用するとかですかね
大きいチェックボックスを作る(もう一度学ぶMS-Accessさん)
見た目に使ってるのがテキストボックスなので条件付き書式で見た目を変えられます
「見た目使用不可なのにクリックしてしまった」のは更新前処理でつかんでCancelという感じで
ただ、ボタンっぽいテキストボックスは非常に困難そうでした
参考:Yahoo知恵袋
パッと見ボタンですが、ボタン的な動作はありません。マウスを乗せるとハイパーリンク機能でマウスカーソルの形が変わるだけです
リンク先では、条件付き書式で前景色を変えていましたが、コントロールソースでも
=IIF(条件,"","標題")
とするといいのかなと思いました代案
ボタンにボタンっぽいテキストボックスを被せます
テキストボックスは条件付き書式やコントロールソースで使用不可の見た目を設定します
テキストボックスのマウスクリック時で、ボタンが使用可能であればSetFocusしつつ、WindowsAPIで再度マウス押し下げイベントを送り込みます
画面上の任意の位置をクリックするVBAコード(VBA(マクロ)で仕事を楽しく効率化さん)
テーマの使用をしたボタンは真似できないのとボタンのポイント時の強調表示ができないあたりがパッと思いつく違いです
ご回答ありがとうございました。
私の環境では、列は6.5列余分にスクロールされて
行は7行余分にスクロールされます。
どちらにしてもどうしようもないとのこと、教えていただきありがとうございました。
確認してみたところ、
縦方向だと、最後の1行(新規行かある場合はその行)だけが見えるところまでスクロールできる、
横方向だと、最後の1列だけが見える範囲までスクロールできる、
というような仕様になっていると思いますが、
これ以上にスクロールできてしまうということでしょうか。
それとも、これはスクロールしすぎと感じるということでしょうか。
どちらにしても、スクロールできる範囲を設定できるプロパティはないのでどうしようもないと思います。
気に入っていただけて良かったです。
簡単に解説をしておきます。
フィルター関係のコードは下記のものとほぼ同じで、最後の Filter、FilterOn を設定するところを、サブフォームのものに変更しただけです。
複数条件の抽出フォームの設計 その1 - hatena chips
非連結のメインフォームの詳細セクションに、上記のフォームヘッダーのコントロール群を配置します。
その下に、データシートビュー表示のサブフォームを配置します。
サブフォームコントロールの幅は詳細セクションの幅と同じにします。
また、「水平アンカー」「垂直アンカー」プロパティをどちらも「両方」に設定します。
これでメインフォームをリサイズしても、それにあわせて拡大/縮小します。
フォームを開く時に、サブフォームの最上部へ移動、高さもフィルターのコントロール群を覆える高さにします。
また、詳細セクションの高さもそれに合わせます。
フォームヘッダーに「フィルターを開く」ボタンを配置して、それで、
サブフォームの位置、詳細セクションの高さを変更して、フィルターのコントロール群をサブフォームの裏に隠したり、見えるようしています。
もし、ご不明な点がありましたら、追加質問してください。
データを確認させていただきました!素晴らしいですね!この方式で作ってみたいと思います。
ありがとうございました!!
データシートビュー表示がいいのなら、サブフォームにデータシートフォームを埋め込んで、
フィルター用のテキストボックスやコマンドボタンは普段は閉じておいて、ボタンクリックで開くようにするというのはどうでしょうか。
言葉では分かりにくいと思いますので、サンプルを作成しましたので、参考にしてみてください。
FrmFilter_1_1.accdb
ボタンについても調べたり実行していましたが、
帳票のためロックをかけても
全てのレコードにかかってしまうという問題があるのですね・・・
やはりこちらを参考に作成するしかないのですよね。
帳票フォームでレコード毎にテキストボックスの表示/非表示を切り換えたい
なるほど、そういう手もありますね。
右クリック、コンボボックス、データシートビュー、
3つの可能性から検討していきたいと思います。
ありがとうございました!
構想だけ
フォームヘッダーの部分って列のラベル表示とかしていますか?
この部分にコントロールを2つ重ねて
下:テキストボックス(コンボボックス)でフィルタ用
上:テキストボックスでラベル表示用
両方ともタブストップを「しない」
ラベル用コントロールでフォーカス取得時にフィルタ用にSetFocus
コントロールソースは「
="ラベル名"&IIf([フィルタ用]<>"","▼","▽")
」これで少しはそれっぽい見た目になるんじゃないかと思います
以前教えていただき、ありがとうございました。
こちらの件、やはり重たいので悩んでいます。
ある条件を満たした際、チェックボックス(やボタン)を「使えない」とわかるようにしたいのですが、軽く対処できる方法はありませんでしょうか。
※ボタンはまだあまり調べていないのですが、チェックボックスは調べても方法が見つからず…
>テキストボックス上で右クリックすれば、並べ替えとかフィルターのメニューが出ますが
本当ですね!知りませんでした。ありがとうございます。
>VBAでフィルター処理を作りこめば
ページの上の領域を結構使ってしまうのが気になっております。
別ウィンドウのポップアップで検索するフォームも別のところで作ってみたのですが
やはりいまいち使い勝手がいいとは言えなくて、あれもこれも欲張るのは難しいですね・・
>エクセルに移行するのはもったいないと
そうですよね。エクセルに移行しようとは思っていないのですが、
アクセスの「データシートビュー」のが、エクセルライクでユーザーにもわかりやすいので悩んでおりました。
ただ、見栄えがあまりよくなくて…
テキストボックスの右クリックをユーザーにわかりやすく告知できないか考えてみようかと思います。
テキストボックス上で右クリックすれば、並べ替えとかフィルターのメニューが出ますがそれでは不足ですか。
あるいは、リボンの「並べ替えとフィルター」セクションの「詳細設定」の「フォームフィルター」だと複数のフィールドの条件をまとめて設定できます。
あとは、VBAでフィルター処理を作りこめば自由に思い通りのUIが構築できます。
例えば、下記のような感じです。
複数条件の抽出フォームの設計 その1 - hatena chips
フィルタリングに関してはエクセルよりデータベースであるアクセスの方が高機能、高速ですので、それが目的でエクセルに移行するのはもったいないと思います。
いまやっていることよりも、やっていて手間や不満に思うことがあるか?という目線で考えるといいです
メリットはないことはないと思いますが、ACCESSが覚えられる(ゴールが明確なので挫折しにくい)のが一番のメリットで、ACCESSを知らないというだけで忌避される(特に引き継ぎ)という問題を回避できるのか?が一番のデメリットになりそうです
EXCELからACCESSに乗り換えるときは
・データ的に誤りのないインプットをしたい(させたい)
・データ量が多く、作業ごとに必要な内容だけで表示したい
・集計したデータに合わせて書式を整えた印刷をしたい
といった、大量のデータを操作する必要があるかどうかが焦点でしょうか。現状の「記録だけでいい」状態からだとメリットは感じられないと思います
仰る通り、別名をつけてあげればよかったんですね。きれいにまとまりました。ありがとうございました。
前の質問と同じで抽出フォームを使えば既存レコードの表示はできます
「日付」「氏名」の項目固定で抽出になるのでその辺は調整してあげるといいと思います
検索結果でレコードが無ければ新規として登録できるようにしてあげればいいので抽出処理の後に追加の条件判定をして追加の処理を入れます
※「検索用日付」、「検索用氏名」は抽出用のそれぞれのフィールドです。適宜置き換えてください
※フォームを開いたときに新規登録ができるとまずいので開くときイベントでレコードの追加を「しない」にする処理を追加しておきましょう
基本はフォームでやるそれと変わりません
複数条件の抽出フォームの設計 その1
フィルターの設定先をレポートを参照するように変更する必要はあります
Me.Filter
↓
Reports!レポート名.Filter
など
レポートに直接編集できる検索窓を設置する方法はちょっとわかりません
抽出フォームをポップアップで表示し、レポートの上に被せるように表示させておくというのが妥協点かと思います
「Q取引先.宛先2」自体がフィールド名になってるので[Q取引先.宛先2]としてあげればいいです
こういうフィールド名はやっかいなので、クエリ作成の段階で、クエリデザインなら「取引先の宛先2:Q取引先.宛先2」のようにして、使いやすい形にフィールドに別名をつけてあげるといいと思います
上記は新スレッドをたてるつもりがレスになってました
スルーしてください
書き直します
まず、入力フォームの日付フィールドと氏名フィールドに入力します
他には出勤時間などのフィールドがあります
日付と氏名どちらもが一致するレコードがすでにある場合にはその他のフィールドには既存のレコードを表示
日付と氏名が一致するものがなければ新規レコードとして作成
というのはどのようにしたらよいですか?
ありがとうございました!思い通りの印刷が出来ました。
フームのレコードソースを、レポートのレコードソースと同じにしてみてください。
VBAが必要になりますね。
まずは、グループ化/並べ替えは、[番号]フィールドのみグループ化して、下記のように設定します。
昇順 ヘッダーセクション付き フッターセクションなし
リボンの[コードの表示]をクリックしてVBAウィンドウを表示させます。
そこに下記のコードをコピーして貼り付けてください。
これでご希望の結果になると思います。
やっていることは、
モジュールレベル変数 preValue に直前のレコードの値を格納しておいて、
現在のレコードの値と比較して同じたったら、Cancel = True でヘッダーを出力しない。
異なっていたらそのまま出力とするということです。
ページヘッダーセクションで preValue = "" としているのは、
ページの先頭にレコードの前に空白行が出力されるのを防ぐためです。
3つ目のブロックに回答っぽいものがありますが1行で書くなら
Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" )),3)) + 1, "000")
↓
Me!発行番号 = Me!コード & "-" & Me!区分 & "-" & Format(Val(Right(Nz(DMax("発行番号", "発行簿","コード='" & Me!コード & "' AND 区分='" & Me!区分 & "'" ),IIf(Me!区分 = "後", 500, 0)),3)) + 1, "000")
フォーム上のテキストボックスだとか、レポートで一発表示だけしたいとか、どうしても計算式1行で済ませなければいけないという要件がでることもままあります。どっちも同じことをやっているのでどっちが基本ということもないですがVBAで記述するなら柔軟性を活用すべしということですね
自分でも見直したコードを追記してみた(やっていることは変わらない)ので見比べてみてください
後から見直したらもっといいコードがあったんじゃないかなと思うことはよくあること。なので
先のコードよりわかりやすくなってると思います
区分で設定を変えたいということでそこだけ条件分岐にしましたが、元々の「連番+1の処理」をそのまま残して初期値側を「後でプラス1されるからマイナス1しておく」ように弄ったところも条件分岐させてあげたほうが直感的に書けますね
ついでに
lastID
もAs String
指定できるので変な使い方ができないよう(バグのもとにならないよう)に制限できるのも良い点かなと余談
変数名も「lastNo」と「newNo」だとそっくりなのに中身別物じゃないかってなるので手を加えてみました