SELECT x.TableName
, x.[item#] As item
, dlookup(
"[qty]"
, "[" & x.TableName & "]"
, "[item#] = '" & x.[item#] & "'"
) As qty
FROM Search x
INNER JOIN MSysObjects y
ON x.TableName = y.[Name]
WHERE y.[Type] = 6
AND y.[connect] Like '*FMT=Delimited*'
AND y.foreignname Like '*[#]csv'
;
'フォーム 開くとき
Private Sub Form_Open(Cancel As Integer)
Dim i As Integer
For i = 1 To 42
Me("T" & i).OnClick = "=SetDate(" & i & ")"
Next
Me.cmdPrev.OnClick = "=MoveMonth(-1)"
Me.cmdNext.OnClick = "=MoveMonth(1)"
SetCalendar Date '<--修正
End Sub
'フォーム 開くとき
Private Sub Form_Open(Cancel As Integer)
Dim i As Integer
For i = 1 To 42
Me("T" & i).OnClick = "=SetDate(" & i & ")"
Next
Me.cmdPrev.OnClick = "=MoveMonth(-1)"
Me.cmdNext.OnClick = "=MoveMonth(1)"
Me.txtDate = Date '<--修正
SetCalendar
End Sub
Surface Pro 3(Windows8.1)に、プリインストールのOffice HOME and business2013と追加でAccess2013をインストールして使っています。 Access2013ですが、ネットワークにつながっていないときは普通に動作するのですが、ネットワークにつながっていると、起動したあとDBを開くときに1~2分くらい時間がかかります。
Option Explicit
Private WithEvents コマンド As CommandButton
Private WithEvents テキスト As TextBox
'初期化メソッド 引数はコマンドボタン コマンドボタンのTagにテキストボックス名を設定しておく
Public Sub Init(objコマンド As CommandButton)
Set コマンド = objコマンド
Set テキスト = objコマンド.Parent.Controls(objコマンド.Tag)
コマンド.OnClick = "[イベント プロシージャ]"
End Sub
Private Sub コマンド_Click()
テキスト.Value = IIf(Nz(テキスト.Value) = "有", "無", "有")
End Sub
'自身を返すプロパティ
Public Property Get Self() As Variant
Set Self = Me
End Property
フォームモジュール
Private Sub Form_Load()
Static co As New Collection 'Class1保存用
Dim ctl As Control
For Each ctl In Me.Controls
If ctl.ControlType = acCommandButton And ctl.Tag <> "" Then
With New Class1
.Init ctl
co.Add .Self
End With
End If
Next
End Sub
それぞれのデータは全く別物で、まとめて集計するとか検索するとかのように同じに扱うことはない、なら別にテーブルを作りますが、そうでないなら、テーブルは別にしないですね。
また、親レコードなしに子レコードのみというのもデータベースとしてはありえない状態なのでそのようなこともしないです。何らかの親レコードを作成してから、子レコードを入力します。親の項目名はなにか適当に決めておきます(「元請けなし」とか)。
私なら、そうしますね。
1取引1レコードがほとんど、稀に1取引複数レコード(一対多)のものがあるということですね。
方法はいろいろあると思います。
それぞれ一長一短がありまするので、実際の業務や運用によって適切なものを選択することになると思います。
取引テーブルと売上明細テーブルというように一対多のテーブルに分けて、
1取引1レコードの場合は、明細テーブルは1レコードのみ、とする。
取引テーブルには金額フィールドは持たない。
取引テーブルと売上明細テーブルというように一対多のテーブルに分ける。
取引テーブルには金額フィールドを持たせる。
1取引1レコードは、取引テーブルに金額を入力、明細テーブルは入力しない。
1取引複数レコードは、明細テーブルに入力して、取引テーブルに集計値を入力(VBAで自動入力するといいでしょう)。
通常はどちらかを選択することになるでしょう。
あるいは、過去にやったことがある方法としては、下記のようなものがありました。
取引テーブルに金額フィールドの他にテキスト型で内訳フィールドというのを追加して、
そこにCSV形式のデータとして格納しておく。
品名,個数,単価
商品1,2,1000
商品2,3,2000
複数レコードの場合、非連結のフォームを別に表示して、そこで入力して、
VBAでCSV形式にして内訳フィールド格納、というようなことを作りこみます。
Windowsでは実はバックスラッシュと¥は同じものです。
英字フォントのバックスラッシュが日本語フォントだと¥で表示されます。
下記参考。
円マーク(¥)とバックスラッシュ(\)は何が違う? | apiless blog
hirotonさんの回答のようにフォントを変更すればいいのですが、
見た目が違うだけで実体は同じものだと理解しておけば、フォントはお好みのものにしておけばいいでしょう。
ACCESSのバージョンはいくつですか?
こちら2013ですが、オプション→オブジェクト デザイナー→クエリ デザインでクエリ デザインのフォントを例えば「Arial」にすればバックスラッシュがそのまま表示できます
バージョンによってオプションの場所が異なるので同様の内容を探してください
クエリデザインであればグループ化の設定で出来ます。フィールドを記述する欄で右クリックして集計をマークすると集計:行が表示されるので重複排除したいフィールドに「グループ化」と設定します。その他のフィールドにはそれぞれ適切な集計方法を設定する必要があります
リンク元となっているファイルの種別をCSVに限定したいということでしたら
MSysObjects テーブルの connect フィールドあたりを参照すればいいでしょう。
( 厳密な判定なら他のシステムテーブルも併用する必要がありそうですが面倒です )
同様に、MSysObjects テーブルの database フィールドの値を参照すればいいでしょう。
といった感じで各フィールドの値を確認した後、
任意の抽出条件を指定すればいいのではないでしょうか。
例えば、CSVリンクテーブルに限定して Lookup するのでしたら、以下のような感じになるでしょう。
ちなみに、DLookUp関数を使ったクエリは
Searchテーブルのデータが 1,000 件程度でも画面のちらつきと重さが半端ないですね。
扱うデータ件数が20万ということですと、運用構築とも
どんなに高性能な端末であっても、ちょっと現実的ではないと思います。
CSVをリンクテーブルとして取り込んでおけば、前回の回答のSQLでできるはずです。
ただし、実用的な速度になるかどうかはわかりません。
もし、実用的な速度がでないなら、SQLでやるのはあきらめて、
VBAでCSVを読み込んで、処理する方向で検討したほうがいいでしょう。
上記の測定器の例ですが、テーブルが同じ構造の複数のCSVの場合を教えて頂けないでしょうか。
皆様のアドバイスありがとうございます。
Dlookupを勉強します。
悪い例でも解説、本当にありがとうございます。
背景として、①各テーブルは数GBあり一つにできないのと、②テーブル数がたくさん有るのと、③一つのテーブルから取り出すデータは20万行ぐらい、④一度に検索するテーブル数は20程度、となっています。
例と出したのが、よくないことも理解できました。
実態ですが、このProjectではテーブルはCSVで特定のパスにあります。
このProjectでは、数百ある測定器で、その測定器のデータが、「計測ポイントIDと年」をファイル名として、特定のフォルダに入っており、月日時分秒の時間と、item#が計測器内の温度、湿度等の種類、QTYが計測値です。
どのような解析をするかが毎回変わるため、今回のような使い方を想定しています。
設計の問題点と解決手法は hatenaさんが完璧な回答をなさっているので、あくまで補足として。
フィールドの名前に記号や予約語が含まれる
TableNameフィールドに
カレントデータベースに存在しないテーブル名が誤って記述されていた場合、
DLookupを使った演算フィールドはエラーになる
という理由で、SQLは念入りに記述したほうがいいかもしれないですね。
Accessのテーブルでしょうか。Accessではテーブル名にピリオドを含めることはできません。
table001.tbl は table001、Search.tbl は Search としたら、下記のようなSQLで可能です。
(ただしitem#に重複があっても1件のデータしか返しません。 )
ただ、同じ構造のテーブルが数百もあるという設計はデータベースとしては完全にNGです。
上記のSQLも標準のSQLではないDLookupというAccess独自の関数が使えたのでシンプルにできましたが、本来のSQLではないです。
データベースの機能を活かすなら設計を変更すべきです。
hatena様
ご教授ありがとうございます。
できました。
ありがとうございます。いろいろアレンジして、またわからなかったら教えてください。
カレンダー形式のスケジュール管理フォーム作成 その4 - hatena chips
上記のサンプルを使用しているなら、下記に修正してください。
前の回答のコードはその3用のコードでした。
hatena様
ご教授ありがとうございます。
やはり同じエラーが表示されます。
頂いた部分ですが
SetCalendarのままですと、コンパイルエラーになり、”引数は省略できません”と表示されるため
SetCalendar DLookup("日付", "T_予定")としていますが、こちらがまずいのでしょうか?
本カレンダー重宝しておりグループでの運用を検討しております。
予定者毎に色を変えたり、やりたいことがいろいろあります。たびたびになり申し訳ございませんが是非ご教授ください。
F_Calendarフォームのコードを修正した後、フォームを閉じずにフォームビューにすると、そのエラーになります。
いったん、フォームを閉じてから開くとどうでしょう。
hatena様
直接早々にご返事ありがとうございます。
実行時エラー'2465':
指定された式で参照されている'T44463'フィールドが見つかりません。
デバッグすると
'カレンダー 日にち設定関数
Private Sub SetCalendar(aDate As Date)
Dim i As Integer, D As Date, m As Integer, n As Integer
If Not IsNull(Me.txtDate) Then
Me("T" & Me.txtDate - FirstDay).BackStyle = 0 '透明
と表示されてしまいます。
再度お願いできますでしょうか?
F_Calendarフォームの開く時のイベントプロシージャを下記のように修正してください。
Me.txtDate に代入した日付の月が表示されます。
丁寧なご返事ありがとうございます。
私が製造者ですが、Date()みたいなのを
入れたり消したりした記憶はあります。その辺が
まずいんでしょうね。
後は、再クエリとか、値の代入とか
色々思うような動きをさせるために、
イベントに設定しています。
それがエラーになっている危険性が大と思いました。
また調べてご報告します!
自己解決しました。
DAOのworkspaceを処理の最後でcloseしたところ書き込めるようになりました。
(先日までは書き込めていたのによくわからない・・・)
調査していまして気になることが出てきました。
このデータベースは、マシン'PC名'のユーザー'Admin'が開いています。データベースが使用可能になった時点で、再度実行してください。
とポップアップが出ます。
おそらくDB開いたままロックがかかっているので書き込めないのだと思いますが、原因が分かりません。
(トランザクションかけた後にコミットがうまく動作していない?)
hiroton様 回答ありがとうございました。
りんご様 仰る通りですね。ちょっと事情がありまして、質問しました。
hatena様 いつも素晴らしいコードありがとうございます。Tagプロパティは初めて知りました。
返信が遅れて申し訳ありません。
本当にありがとうございました。
りんご様
度々ご回答ありがとうございます。
こちらの設定もしてみたのですが、この設定をするとAccessのロゴが20秒くらい表示されAccessが起動します。
結局20秒待つ事には変わりがないので、設定を戻している状態です…。
>> 1
外部に接続出来ないPCなので、これも的外れかもしれませんが、念のため。
「Officeのインターネット接続を許可する」を無効にする。[ファイル] - [オプション] - [トラスト センター] - [トラスト センターの設定] - [プライバシーオプション] - [プライバシー設定]
規定値を設定しない、イベントスタート後、Me.Undoするとか、でしょうか?そもそも論から的外れでしたら、ごめん。
りんご様
ご回答ありがとうございます。こちらのサイトも見ていたのですが、
そもそも外部に接続できないPCですので、この設定はできませんでした…。
ググッただけです。知識が無いので責任は負えません。
テーブルの日付フィールドが、規定値:Date()だという前提で、当てずっぽうですが。
⬇レコードの編集中に、うっかりクリックを押して、確定されてしまった。
こんな経験はないですか?同様に、レコードの編集中に、イベントが発生したので取り敢えず確定されてしまった。その後、イベントスタート。新規レコードの日付フィールドには、本日の日付が自動入力されているので、フォームの日付を代入・上書き。テーブルを開いてみると、あら不思議、2つのレコードが出来ました。もしかして、こんな状況なのではないでしょうか?
3件目からは、既存レコードの編集中にイベントが発生しているから、影響しないという事かもしれない。(新規レコードの日付フィールドに代入・上書きされるだけ)。
フォームがテーブルやクエリに連結している前提ですが、新規レコードに移動して、イベントを発生させると…。
既に回答した通りですが、質問のコード部分には勝手にデータを登録するような仕組みはありません。入力したことのない値(本日の日付)のデータが作られるということは何かを条件に自動でデータを登録する仕組みがどこかにあるということです
作った人なら当然知っている仕様だと思いますが確認できませんか?
作った人がすでに連絡を取れない状態でどうにかしなければならないということであれば、その動作からどこかの何かを探すという作業が発生します。大本の質問とは全く関係ない仕事だということは理解してください
とりあえず見るべきはフォームのプロパティのイベントタブですね
未確認の
[イベント プロシージャ]
やマクロが設定されていませんか?りんごさんへ
テキストボックスですが、非連結です。
新規に質問項目を立ち上げました。
どうぞ宜しくお願い致します。
hiroton さんへ
ところで、エラーですが、
色々調査した結果、
必ず、本日の日付が自動入力されるようになっているようです。
そうして、本日の日付を入力しようとしたら重複エラーが出て、
日付を変えると入力できて、でも、本日の日付のデーターが
必ず入っているという感じみたいです。
最初から、違う日付を入れた場合、
本日の日付のデーターが自動で入力され、
1件登録しただけのつもりなのに、
本日の日付のデーターと別の日の日付データー
2件が入力されるみたいです。
3件目のデーターからは
ちゃんと重複エラーも出るし、
データーも1件入力したら
1件だけしか登録されません。
大変お手数ですが、御指南を
宜しくお願い致します。
新しく質問記事を立ち上げました。
宜しくお願い致します。
いまいち、状況が伝わらないのですが、フィールドA、フィールドBをもとに、フィールドCを絞り込みたいという事でしょうか?
範囲内の抽出が出来るという事なので、下記、情報で解決しませんか?
クエリの抽出条件の例 - Microsoft Support
値が指定範囲外にある
<5000 or >10000
範囲外の値を含む
<#2006/2/2# or >#2006/2/4#
汎用性を持たせるのは凄い事だけど、貴方にしか保守出来なくなるのではないかと心配です。
>> 5
AccessVBAで画像を作りたいのであれば、『テキストボックス配置、ボタン配置、クリック時イベント:[イベントプロシージャ]』、ここまでノーコードじゃダメなの?
教えていただきありがとうございました。
内部処理を見直してhirotonさんにご教示いただいたNZを使ってみたのですが、それでもやはり単体では厳しかった(クエリが複雑過ぎますがでました)ため、りんごさんにご教示いただいた追加クエリ等を使った結果、想定していたイメージの通りのものができました。
大変助かりました。
本当にありがとうございました。
hirotonさんも指摘していますし、上の回答でも、下記のように仕様を提示してます。
もし、コントロールの名前を変更せずにということなら、下記のような仕様でどうでしょうか。
(こちらの仕様の方がコードがシンプルになるし、変更に強いコードになります。)
仕様
コマンドボタンのTagプロパティに関連付けるテキストボックス名を設定しておく。
例
コマンドボタン名「コマンド51」
テキストボックス名「テキスト0」
の場合、コマンドボタン「コマンド51」のTagプロパティに「テキスト0」と設定する。
クラスモジュール
フォームモジュール
おお、なるほど。
お二人の回答を見て大分回りくどいことをやっていたことに気づきました。
かなりごてごて書き込んでしまっているので、少し中身を見直してみます。
追加クエリという手がありましたね。うっかりしていました。
選択クエリとテーブル作成クエリで作ることばかりを考えていました
中身の見直しと追加クエリで再挑戦してみます
項が分かれていたほうが入れ子少なくてわかりやすいかと思ったけど
長くてもこのくらいなら全部Nzの入れ子の形でも問題なさそう
テキスト0の名前を、
txt0
コマンド51の名前を、
cmd0
に変更してみましょう
りんご様 回答ありがとうございました。
hatena様 いつもご教示ありがとうございます。
私の書き方が悪かったとおもいます。
図のように、コマンド51をクリックすると、テキスト0に、有、無が表示されるようにしたいのです。
テキスト0の名前は、txtテキスト0
コマンド51の名前は、cmdコマンド51です。
色々試したのですが、作動しません。
できましたら、もう一度、コードのご教示をお願いします。
本当に申し訳ありません。
NzはNullを判定するだけなんでIIf条件分岐でIsNull判定するのと同じですけどね。式が短く書けるだけです(大事)
残業3は残業代の切り替わりをわかりやすくしてるだけかな?データ上では意味ないですが業務上ではよくある話ですかね
休日2がある場合に中抜け扱いとすると、平日の時間休に申請があるとき、申請上の時間合計とデータ上の中抜けの時間合計が合わないってことになります。
休日のデータには休日フラグを立てて、そのレコードは集計から省くようにすれば問題ないんですが、hiroton的には元データから存在しないような作りのほうが好きですね
休日1と休日2の間には中抜けがあるけど休日2と休日3(2レコード目の休日1)の間には中抜けがないっていうのも混乱のもとですし
ちょっと挙げたようにUNION使えばできないことでもないですが、ほしい結果次第ですかね。今回は使わなくてもよさそうでそのほうが高速そうでもあります。
>> 8にイメージを出していますが、「休日2発生時は中抜け扱いをする」ならフィールドの位置をうまい具合に入れ替えるような条件判断を作ってあげればいいので考えてみてください