Const cSQL = ""SELECT * FROM Tbl1 WHERE 下限値<=[x] AND 上限値>[x];"
Dim rs As DAO.Recordset, x As Long
x = Val(InputBox("数値を入力"))
Set rs = CurrentDB.OpenRecordset(Replace(cSQL,"[x]",x))
If rs.EOF Then
MsgBox "該当するデータはありません。"
Else
MsgBox "gr1: " & rs!gr1 & vbCrLf & _
"std1: " & rs!std1 & vbCrLf & _
"gr2: " & rs!gr2 & vbCrLf & _
"std2: " & rs!std2
End If
For i = 0 To 48
gr = ""
y = Min(i)
z = mx(i)
If x >= Min(i) And x < mx(i) Then
gr = gr1(i)
std1 = std1(i)
gr2 = gr2(i)
std2 = std2(i)
Exit For
End If
Next
If gr = "" Then
gr = gr1(49)
std1 = std1(49)
gr2 = gr2(49)
std2 = std2(49)
End If
For i = 1 To 49
If x >= Min(i) And mx(i) Then
gr = gr1(i)
std1 = std1(i)
gr2 = gr2(i)
std2 = std2(i)
Exit For
Else
gr = gr1(50)
std1 = std1(50)
gr2 = gr2(50)
std2 = std2(50)
End If
Next
Private Sub cmb_syouhin_GotFocus()
If Me.opb_syusoku = 1 Then
Me.cmb_syouhin.RowSource = "SELECT * FROM 商品テーブル WHERE 終息 = False;"
Else
Me.cmb_syouhin.RowSource = "商品テーブル"
End
End Sub
hatenaさん ありがとうございます。
”田中”を変数のtyokusouに変更するだけで出来ました。
ややこしく考えすぎでした。とにかく変数の前に”で区切り & 変数 & で繋いでその後に”で記述始めたらいいのですね。
初歩的な事に丁寧な解説頂き、すみませんでした。
お世話になりました。
前回の回答と、リンク先を熟読して、一度自分でチャレンジしてみてください。
一度理解できれば、簡単なことだと思います。
どうしてもできないようでしたら、その旨返信してください。
ヒント
リンク先でも言ってますが、SQLとVBAは別物ですので、SQLの部分とVBAコードの部分を意識するようにしましょう。
文字列結合はSQLでもVBAでも &
引用符は SQLでは ' または " どちらでも可、VBAでは " のみ
hatenaさん ありがとうございます。
コード修正したら出来ました。あと変数の前に★等の記号入れたいのですがどう記述したらいいでしょうか?
= [T発注Sub].[備考・MEMO] & ' " & tyokusou & " さんへ直送';" の 変数tyokusouの前にです。
" ★田中さんに直送 ”としたいのです。頭がこんがらがってしまって・・・すみません。
SQL内の文字列リテラルは引用符("または')で囲む必要があります。
つまり、下記のようなSQLになります。
※tyokusou の中身が 田中 の場合
このSQLをVBA内に記述する場合は、VBAとしての文字列リテラルにする必要があるので、引用符(")で囲む必要があります。
変数部分は文字列リテラルの外に出す必要がありますので、下記のようになります。
下記を一読しておくと理解が深まると思います。
Access上のコード内で引用符(")と単引用符(')の使い分けについて - hatena chips
みなさま丁寧なご解説ありがとうございました。省略してうまくいく時と、そうでない時があり、少し困っていましたが、省略可能でもきちんと表現したいと思います。ありがとうございました。
原因がはっきりしているエラーなので、根本的に設計からやり直して解決するしかないでしょう。臭い物に蓋をしても遅かれ早かれ損切りするしかないですわー。
すでに解決済みかもしれませんが、最近この症状にはまって一応解決したのでコメントさせて頂きます
解決方法は、Accessを64bitで再インストールしたらエラーがなくなりました、根本的な解決ではないかもしれません
私の場合32bitだったのでもしやと思い64bitにしたというだけです、何らかの上限や制約があるかもしれないのでもしかするともっとクエリを複雑にすると64bitでも同じ症状が出るかもしれません
何かの参考になれば幸いです
リンク先の質問では、コンボボックスのリストをカナで制限する方法ですね。
そのコンボボックスで選択した値で該当の従業員データをフォームに表示する方法については一切触れられてません。
この部分を実際どのように実現しているかの説明が必要かと。
総合計のSUM関数の集計のレポートのレコードソースのクエリを作るしか手が無いようなので諦めます。有難う御座いました。
Access に限って言えば、参照されているテーブルが 1 つのみである場合については * を省略しても構いません。
例えば、1 対 1 または多対 1 の関係にある 2 つのテーブルを内部結合し、右テーブルのうち、ある条件に該当するレコードを抽出した上、左テーブルのレコードのみを削除する(右テーブルのレコードは削除しない)ような場合は、「削除対象となるレコードを含むテーブル」の指定が必要となります。
一般的な SQL の構文規則において、 ; は「複数のステートメントで構成されているクエリ( SQL Server でいうところのストアドプロシージャ等)内の個々のステートメントを区切る終端記号」として用いられます。
クエリ内で呼び出されるステートメントが 1 つのみである場合は ; を省略しても構いません。
ただ Access に関しては「 1 つのクエリにおいて呼び出せる命令は 1 つのみである」という仕様となっているため、上記のような複数のステートメントで構成されたクエリを作成、実行することは出来ません。
したがって、事実上はほとんどのケースにおいて ; を省略してもしなくても正常に実行されます。
唯一の例外は、PARAMETERS 句を記述してクエリパラメータを明示的に定義する場合です。
上記のようなパラメータクエリの場合、PARAMETERS 句と DELETE 文を ; で区切らなければ構文エラーが発生します。
つまり * にしろ ; にしろ「省略してもよいケース」と「省略してはいけないケース」があるということです。
そういえばそんな設定あったようなと思って、365で新規ファイルを作成して確認したらありました。
この数値を変更してみましたが、コンボボックスのリストに表示される件数には影響がありませんでした。100に設定しても100件に制限されるわけではない。
そこで、9万件のレコード数のテーブルを作成してコンボボックスに設定しましたら、リストに表示されたのは65536件まででした。
私の試した環境では上記の設定に関係なく、これが上限のようです。
古いmdbファイル眺めてたらこんな設定がありました
(新規作成したaccdbファイルでは表示されません)
別件でオプション眺めてたらこの質問を思い出しただけなので、質問の回答になるかはわかりません
フィールド指定の「
*
」いらないです。たぶん、ACCESSの場合、クエリデザインでクエリを作成するときにフィールド出力が必要なのでしょう。(クエリ作成ツールの仕様)
その関係で自動整形で付与されたりします
DELETE ステートメント (Microsoft Access SQL)
「省略可能記述」なので、省略する/しないでどちらが正しいか?はありません。どちらも正しいです。これは一般的なSQLにおいても記述はないので、普段から記述しないで良いでしょう
構文終端の「
;
(セミコロン)」技術資料が見つかりませんでした。現実的には省略可能です。これもACCESSにおいてはどちらが正しいというものでもないでしょう。これも、必要、不要、省略可能は様々なSQLの個性によるようです
ただし、システムによってはSQL構文を連続して記述したり、続けて何かの記述を許すようなモノもあります。そのような場合には、当然
;
が必要になりますACCESSだけを扱っている場合は気にする必要はないが、SQL自体に興味がある場合は記述する癖をつけておいたほうが無難です
ここはAccessに関する質疑応答、技術的な情報交換の場です。
それを踏まえて、他の閲覧者や後から検索で訪問した人にとって、意味のある情報になるように、下記のような要件に対してAccessでどのように解決するかという観点で、回答をおいておきます。
PDFから表データを取り込む
WordでPDFファイルを開きます。
欲しい表部分をコピーしてエクセルのシートに貼り付けます。
これをAccessにインポートします。
これで、pdfの表データをAccessのテーブルとして取り込めます。
これは1回のみの作業なのでVBAにするまでもないでしょう。
VBAで自動化したい場合は、下記等を参考に。
【Excel/VBA】PDFやWordから表データだけを抽出するマクロ | hamalabo
キー値をもとに、下限値と上限値の範囲に合致するデータをとりだす。
取り込んだテーブル名はTbl1とする。
[条件値]と[下限値]フィールドにインデックスを設定する。
わずかな手抜きは止めて、2次配列に格納する事にしました。
PDFの表なら、もっといい方法はありそうですが、
後だしで、どんどん情報がかわっていくいつものパターンなので、
まあいいや。
このように修正したら、正常になりました。
ご指摘の通り、配列のままでは使えませんでした。
実際には、PDFの表を変換したデータを使います。
とりあえず、税額表等のデータは、寿限無コードを使わなくて済むようになったので、
無駄な労力を使わなくて済むようになりました。
Dim x As Long
Dim y As Long
Dim z As Long
Min = Split("0,63000,73000,83000,93000,101000,107000,114000,122000,130000,138000,146000,155000,165000,175000,185000,195000,210000,230000,250000,270000,290000,310000,330000,350000,370000,395000,425000,455000,485000,515000,545000,575000,605000,635000,665000,695000,730000,770000,810000,855000,905000,955000,1005000,1055000,1115000,1175000,1235000,1295000,1355000", ",")
mx = Split("63000,73000,83000,93000,101000,107000,114000,122000,130000,138000,146000,155000,165000,175000,185000,195000,210000,230000,250000,270000,290000,310000,330000,350000,370000,395000,425000,455000,485000,515000,545000,575000,605000,635000,665000,695000,730000,770000,810000,855.ooo,905000,955000,1005000,1055000,1115000,1175000,1235000,1295000,1355000,1355000", ",")
gr1 = Split("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50", ",")
std1 = Split("58000,68000,78000,88000,98000,104000,110000,118000,126000,134000,142000,150000,160000,170000,180000,190000,200000,220000,240000,260000,280000,300000,320000,340000,360000,380000,410000,440000,470000,500000,530000,560000,590000,620000,650000,680000,710000,750000,790000,830000,880000,930000,980000,1030000,1090000,1150000,1210000,1270000,1330000,1390000", ",")
gr2 = Split("1,1,1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", ",")
std2 = Split("88000,88000,88000,88000,98000,104000,110000,118000,126000,134000,142000,150000,160000,170000,180000,190000,200000,220000,240000,260000,280000,300000,320000,340000,360000,380000,410000,440000,470000,500000,530000,560000,590000,620000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000", ",")
x = 70000
For i = 0 To 48
gr = ""
y = Min(i)
z = mx(i)
If x >= Min(i) And x < mx(i) Then
gr = gr1(i)
std1 = std1(i)
gr2 = gr2(i)
std2 = std2(i)
Exit For
End If
Next
If gr = "" Then
gr = gr1(49)
std1 = std1(49)
gr2 = gr2(49)
std2 = std2(49)
End If
連想配列のキーは完全一致しか無理です。完全一致なので高速に検索できるのです。
このコードなら、xが10000間隔でgrが1増えていくという規則性があるので、下記のようなコードで可能です。
間隔が不規則であるなら、下記のようなテーブルを作成してそれを参照すればいいでしょう。
x_lowには範囲の下限値を入力しておきます。
また、インデックスを設定しておくと高速に検索できます。
下記のコードでgrを取得できます。
これの手がありました。
わずか、20行。
頭が悪いという事は、不幸です~~~~~。
Min = Split("0,63000,73000,83000,93000,101000,107000,114000,122000,130000,138000,146000,155000,165000,175000,185000,195000,210000,230000,250000,270000,290000,310000,330000,350000,370000,395000,425000,455000,485000,515000,545000,575000,605000,635000,665000,695000,730000,770000,810000,855000,905000,955000,1005000,1055000,1115000,1175000,1235000,1295000,1355000", ",")
mx = Split("63000,73000,83000,93000,101000,107000,114000,122000,130000,138000,146000,155000,165000,175000,185000,195000,210000,230000,250000,270000,290000,310000,330000,350000,370000,395000,425000,455000,485000,515000,545000,575000,605000,635000,665000,695000,730000,770000,810000,855.ooo,905000,955000,1005000,1055000,1115000,1175000,1235000,1295000,1355000,1355000", ",")
gr1 = Split("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50", ",")
std1 = Split("58000,68000,78000,88000,98000,104000,110000,118000,126000,134000,142000,150000,160000,170000,180000,190000,200000,220000,240000,260000,280000,300000,320000,340000,360000,380000,410000,440000,470000,500000,530000,560000,590000,620000,650000,680000,710000,750000,790000,830000,880000,930000,980000,1030000,1090000,1150000,1210000,1270000,1330000,1390000", ",")
gr2 = Split("1,1,1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", ",")
std2 = Split("88000,88000,88000,88000,98000,104000,110000,118000,126000,134000,142000,150000,160000,170000,180000,190000,200000,220000,240000,260000,280000,300000,320000,340000,360000,380000,410000,440000,470000,500000,530000,560000,590000,620000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000,650000", ",")
For i = 1 To 49
If x >= Min(i) And mx(i) Then
gr = gr1(i)
std1 = std1(i)
gr2 = gr2(i)
std2 = std2(i)
Exit For
Else
gr = gr1(50)
std1 = std1(50)
gr2 = gr2(50)
std2 = std2(50)
End If
Next
x >= 63000 And x < 73000に対応できる、accessのデータ型をご存じでしたら、ご教授ください。
最大値と最小値を登録して検索させるというのであれば、寿限無地獄です。
ごめん、この質問はMsAccess掲示板にあっているのかしら?hatenaさん、教えて下さい。
連想配列などコードでごりごりデータベースをやっていた時代があって、画期的なMsAccessが登場したおかげでそんな事をやらなくていい時代になって、労働生産性が改善されたんじゃなかったっけー?
これ、残業加算される場合や、24時間以上、休憩時間がからむので、かなりやっかいなのです。
特に厄介なのは、休憩時間の処理でした。
どこで休憩したかによって、単価が違ってくるからです。
逆に、休憩時間を無視していいなら、なんの工夫も必要ないです。
私の場合は、勤務開始から終了まで追っていく過程で、集計中の時間が通常時間帯と、深夜時間帯のどちらのブロックに属しているかを判定することで、正しく計算できるようになりました。
4打刻制から、6打刻制に対応させることも可能です。
端的に、説明する事が出来なくてすみません。
これは、プログラムの技術的な問題というより、処理する方法の問題だと思います。
正解も、たくさんあるはずです。
hirotonさん・hatenaさん ありがとうございます。
コンボボックスとオプショングループは同一フォームにあります。
hatenaさんのコードを編集して記述したら上手くいきました。簡素化できてありがたいです。
ちょっとした事ならSQLでした方が断然楽ですね。
お世話になりました。
RowSourceに設定したクエリに抽出条件を設定するなら、hirotonさんの回答のような条件になりますね。
オプショングループとコンボボックスが同じフォームにあるのなら、フォーム名は省略することができますので下記でもいいですね。
コンボボックスのフォーカス取得後イベントでコンボボックスを再クエリします。
RowSourceにはSQLも設定できますので、VBAを使うなら、RowSourceにSQLを設定してもいいですね。
そうするとクエリ自体が不必要になりクエリが増えて管理が煩雑ということがなくなります。
フォームの内容を参照することになるので、フォームの名前も質問内に入れるようにしましょう
全て含める(条件を設定しない)場合と、絞り込みをする場合を切り替えたいとなると、単純な保存済みクエリにするには悩むところですね。今回はYes/Noなので、例えば
とすると、
「『全て含める』ときはYesもNoも抽出対象にする(終息=False Or 終息=True)」
「『終息除く』ときはNoだけを抽出対象にする(終息=False Or 終息=False)」
として実現できます
SQL構文的には無駄な記述になりますが、保存済みクエリで対応するときにはこういう一捻りが必要になることも多いですね
やはり難しいですかね
hatena様
ありがとうございました。
通常気勤務時間分と深夜勤務時間分に分けて表示したいのだと思います。
下記の3パターンが考えられます。
通常勤務時間のみ
例 15:00 ~ 22:00
通常勤務時間から深夜勤務時間まで
例 16:00 ~ 23:00
18:00 ~ 01:00
深夜勤務時間のみ
例 22:00 ~ 03:00
最後のパターンはない、考慮しないということなら、下記のような式を作成すればいいでしょう。
退勤1 は後の式で参照するための式です。
もし、深夜勤務時間のみ、あるいは 03:00 ~ 10:00 というような勤務がありえる、となるともっと複雑な式になります。
hiroton様
ありがとうございます。
データ型を日付/時刻型にしてあり、時刻のみ保存しているならば、
なんて方法でもいいかもしれません
hatena様、hiroton様 回答ありがとうございました。
感謝します。
#0:00:00#
はデータ的には数値の「0」です。[退勤]<=#0:00:00#
は基本的にFalse
になるでしょうSwitch 関数
質問の式では、Switch関数はNullを返しているので空白になっているのでしょう
【Excel VBA】24時間以上の合計を求める方法(後編)(prtn-blogさん)
タイトルはExcelですが、VBA部分がACCESSに相当します。要約すると、24以上の時間表示はそのままでは使えません(「以上」です。24:00もNGです)
24時以降の場合、「[退勤]」をどのように記録してるのでしょうか?
最終的にはTimeSerial関数を経由して時間計算させるのがいいんじゃないでしょうか?
[退勤]<=#0:00:00# になることはないはずですからそうなりますね。(0以下の時刻をどのように入力するのか?)
退勤管理では、[出勤]、[退勤]フィールドに日付成分も含める方法と、時刻成分のみににする方法があります。
おそらく時刻成分のみの方法を採用しているということだと思いますが、その場合、#0:00:00#を超えて勤務した場合の対策に工夫が必要です。
24時間以上連続で勤務することはないはずですから、[出勤] > [退勤] なら#0:00:00#を超えて勤務していると判断できます。その場合は、[退勤]に24時間(1440分)を加算すればいいでしょう。
返信が遅くなり申し訳ありません。
hirotonさん、Hatenaさんりがとうございました。
テーブル内に取消日というフィールドがあったので、そこに日付を入れる形で論理削除にしようと思います。
Hatena様
りんご様
返信がいつも遅く申し訳ありません。
hatena様のORでのサブフォーム表記とりんご様の親リンク子リンクにする方法をともに実行したところ当初計画していたものよりもいいものができました。
ありがとうございます。
今回は説明不足など不手際があり大変失礼いたしました。またご相談させていただければ幸いです。
hatena様
スマホの画像でのsql読み上げは、これが限界です。すみません。画像はこの様な感じでよろしいでしょうか?
hirotonさん、hatenaさん
詳しい説明ありがとうございました。
リンク先の質問でも回答がありますし、今回もhatenaさんが回答していますが、
通常、32bit版ACCESSで作成したものが64bit版ACCESS環境で開けないのは、mde、accde形式のファイルです
ACCESSの基礎知識になりますが、ACCESSは2007から標準のファイル形式(の拡張子)がaccdbに変わりました。それ以前の標準のファイル形式(の拡張子)がmdbです
使用が推奨される Access ファイル形式
mdbやaccdbの形式であれば、それを64bit環境で開けるか?というのは基本的に問題になりません(正常に動作するか?は別問題です)
「mdb→accdbに変換」すべきかどうかは、上記リンク先を参考に決定してください
これにたいして、mde、accdeの拡張子を持つファイルは、(それを表す名称は不明ですが)コンパイル済みのACCESSデータベースファイルになります
32bitACCESSでコンパイルを実行すれば、32bit環境で動作するデータベース、64bitACCESSでコンパイルを実行すれば、64bit環境で動作するデータベースになる(互換性はない)ということなのでしょう。これも、mde、accdeどちらの拡張子で保存するか?ということ自体は無関係なので、ファイル形式によって制限のある機能を考慮した上で決定する必要があります
(現状、mdb,mdeファイルが即座に排除されるという状況でもなさそうなので、特別新しい形式に保存しなおす必要はないというのが持論です)