Private Sub Form_Error(DataErr As Integer, Response As Integer)
If DataErr = 2113 Then 'データ型違反
Response = acDataErrContinue '規定のエラーメッセージを出さない
MsgBox "数値を入力して下さい"
End If
ActiveControl.Undo '元に戻す
End Sub
Private Sub コマンド0_Click()
' On Error Resume Next
'変数定義
Dim intRet As Integer 'ダイアログ用変数
Dim GetFileName As String 'フルパスの値
With Application.FileDialog(msoFileDialogFilePicker)
'ダイアログのタイトルを設定
.Title = "ファイルを開くダイアログ"
'ファイルの種類を設定
.Filters.Clear
.Filters.Add "csvファイル", "*.csv"
'複数ファイル選択を許可しない
.AllowMultiSelect = False
'初期パスを設定
.InitialFileName = CurrentProject.Path
'ダイアログを表示
intRet = .Show
If intRet <> 0 Then
'ファイルが選択されたとき
'そのフルパスを返り値に設定
GetFileName = Trim(.SelectedItems.Item(1))
Else
'ファイルが選択されなければブランク
GetFileName = ""
End If
End With
'選択されたフルパスをテキストボックスへ表示
Me.テキスト1.Value = GetFileName
DoCmd.TransferText acImportDelim, , "テーブル1", GetFileName, True
End Sub
If intRet <> 0 Then
'ファイルが選択されたとき
'そのフルパスを返り値に設定
GetFileName = Trim(.SelectedItems.Item(1))
Else
'ファイルが選択されなければブランク
GetFileName = ""
End If
End With
'選択されたフルパスをテキストボックスへ表示
Form_F_Form.テキストn.Value = GetFileName
LostFocusイベントが発生する前にエラーメッセージが出ますので、LostFocusイベントでは手遅れですね。
LostFocusイベントより前に発生するBeforeUpdate(更新前処理)イベントでも手遅れです。
どうするかというと、フォームの方の「エラー時」イベントで処理します。
Form.Error イベント (Access) | Microsoft Learn
ご教授ありがとうございます。
フォームの作業ウインドウ固定を(はい)にしているとこの状態になるそうで、それを設定しているフォームがあったのですが、(いいえ)にしても復旧しませんでした。ので、当該のフォーム以外をご提案のとおり新規にインポートし、使用することにしました。
その後元のAccessファイルを何度か開いたり閉じたりすると、なぜか復旧していました。
明確な原因の解明はできませんでしたが、復旧し一安心です。
本当に助かりました。ありがとうございます。
そのような現象に遭遇したことがないので、Accessの動作がおかしくなった時の一般的な対象法を紹介しておきます。
まずは、「データベースの最適化/修復」を実行してみてください。
それで改善しないなら、
新規にAccessファイルを作成し、そのファイルではナビゲーションウインドウが使用できるか確認してみてください。
使用できるようでしたら、そのファイルの問題のファイルから、すべてのオブジェクトをインポートしてください。
これで問題なく動作するなら、今後はこのAccessファイルを使用するようすればいいでしょう。
「VBA 変数 適用範囲」とか「VBA 変数 スコープ」などをキーワードにググればいろいろ解説ページが見つかりますので、それで研究してみてください。より、理解が深まると思います。
VBA 変数 適用範囲 - Google 検索
hatena様
ご回答ありがとうございます。
プロシージャ内でのみ有効ということで理解しました。
変数が引き継がれないということで、安心しました。
ありがとうございました。
プロシージャ内で宣言した変数はプロシージャ内でのみ有効ですので、別のプロシージャに同じ名前の変数があっても問題ないです。(プロシージャレベルの変数といいます。)
りんご様
「tbl見積Subとtbl見積品で不一致クエリ。」で出来ました。
ありがとうございました。
りんご様
追加のご回答で、理解出来ました。
見積データを削除する前に見積品IDを削除することを考えていたので、複雑になってしまっていたようです。
削除後なら、単純に「tbl見積Subとtbl見積品で不一致クエリ。」で出来そうです。
ちょっとやってみます。
ありがとうございます。
りんご様
ご回答ありがとうございます。
会社が修理業を行なっていて、修理品ごとに修理IDが振られています。
修理IDは実際に受注してから発番されます。
以下は見積業務に基づいて設計した内容です。
見積は1つの見積案件の中に複数の修理品があり、同修理品の別途の追加見積や再見積があります。
以下は設計したものです。
1つの案件を「見積案件番号」として管理して、その案件に追加や再見積はサフィックスで追加しています。
例)見積案件番号10001、サフィックス0、見積番号10001-00
見積番号は、ハイフン前が見積案件番号で、後ろがサフィックス(99件まで考慮しています。100件目には作成できないとメッセージされます。)
最初の新規見積は、10001-00、同案件の次の見積は10001-01。別案件の新規見積は10002-00。
つまり、1つの案件で複数の見積があります。
また、見積の修理品を見積品IDとしています。
同じ見積案件内で別の見積でも、同じ修理品(見積品ID)を見積もっています。
そのため、ある見積を削除するに伴い、その見積内で使用されている見積品IDが、同案件の別の見積で使われていなければ、一緒に見積品IDも削除したく考えました。
見積品IDを必要とする理由は、見積もった修理品(見積品ID)と実際受注して修理した修理品(修理ID)をリンクさせるためです。
見積品IDの見積原価と修理IDの実際原価の比較等のためです。
tbl見積Subとtbl見積品で不一致クエリ。
↓Nullで抽出
選択クエリの場合、削除クエリに変更。親子テーブルの連鎖削除に続けて、担当者に削除の是非を判断させるとか。
あまりやらないような事をやろうとしているように見えてしまいました。
親子テーブルとtbl見積品は別々に削除する、必要に応じて。これでは駄目なのでしょうか?
お世話になります。
自己解決しましたので報告します。
該当のテーブル内フィールドのデータ型に【大きな数値】を設定していたことが原因のようです。
https://learn.microsoft.com/ja-jp/office/troubleshoot/access/database-requires-newer-access
ありがとうございました。
外注がお勧めですし、経営・人事が変わって後から大問題になると泣きっ面に蜂です。
ご回答ありがとうございます。
やはりそういう機能はないんですね。知れたことでスッキリしました。
代替案のご提案ありがとうございます!早速ためしてみます。
いつもこちらのサイトで非常に助けられています。
今後ともよろしくお願いいたします。
Accessデータベースに接続しているユーザー名の列挙は下記のリンク先の方法で可能です。
データベースにログオンしているユーザーを特定する - Office | Microsoft Learn
が、特定のレコードを編集中のユーザーを特定するという機能はないと思います。
代替案になりますが、テーブルに編集中ユーザー名を格納しておくフィールドを追加しておいて、
編集を開始する前に、そのユーザー名をフィールドに入力して保存しておく。
編集が終了してレコード保存するときにフィールドからユーザー名を削除する。
というような処理をVBAで構築するということになると思います。
hatenaさんのおっしゃるようにデータベース化するにあたり、最適なフィールドになっていないのは承知です。
電子化するために部署内でバラバラだった帳票を整理しているところなのです。
以前はWordだった帳票をAccessに移行しているのでちょっとデータの型がバラバラなので整理するために
下限値と上限値の抽出を自動でできたら便利だと思って作ったのですが
作成者によって書き方がバラバラで、上限値、下限値以外のことも入力しているので
それはこちらで修正が必要なのです。
一度、フォームモジュールレベルの変数として格納するとか、テキストボックスのTagプロパティに格納する方法も検討してみます。
コメントありがとうございます。
試行錯誤の結果なんとか希望する動作になりました。
リンク先の方法を参考にSetWindowPos > 最大化(docmd(acCmdAppMaximize))でwindows10では動作しました。
windows11はShowWindow(SW_SHOWNORMAL) > SetWindowPos > ShowWindow(SW_SHOWMAXIMIZED)で指定したモニターに
最大化状態で表示されました。
理由は不明のため、将来動作結果が変わる事が無いよう祈るしかなさそうです。
ありがとうございました。
この例の場合は、そのフォームを開いたときに、初期値(規定値)として、11.00~15.00 という値が表示されているということでしょうか。だとしたら、その初期値はどのように表示してますか。
抽出条件を設定するためのテキストボックスなら、そのような状態にならないような設計(時刻しか入力できないような入力規則)にする、あるいはそのようなことになったら再入力を求めるメッセージを表示するなど、とするのが普通だと思いますが。
ちょっと、状況が理解できません。
どちらにしても、何と比較して変更とするか、ですので、チョコラブさんが考える変更前の値をどこかに保存しておいて、それと比較するというブログラムを自前で作成することになるでしょう。保存する場所としては、フォームモジュールレベルの変数として格納するとか、テキストボックスのTagプロパティに格納するとか、、、でしょうか。
「一旦すべて登録してしまい」というのがどのような意味があるのが理解できませんが、
読み込み時のテーブルの値と、テキストボックスの値と比較すれば、変更があったかどうか確認できるのと違いますか。
そのプログラムは難しそうですね。
クラスモジュール、あまり触ったことがなく...。
検索してみます。
コメントありがとうございます。
お返事が遅くなり申し訳ありません。
非連結テキストボックスをもう一つ用意しておく…なるほどです。
ですが、もうすでにテキストボックスが膨大にたくさんあるのでこれ以上は操作が重たくなってしまいますね…。
もう少し検討します。
コメントありがとうございます。
hatenaさん
お返事が遅くなり申し訳ありません。
この以前の値が何かというのは二つあり、
例としてひとつは
11.00~15.00という値があるテキストボックスから抽出し、下限11.00、上限15.00という風に
一つのテキストボックスから下限の値と上限の値を自動で抽出してくれるようにプログラムを作りました。
ただ、テキストボックスにも下限、上限の値だけではなく他の文字列が混ざることがありうまく抽出できないので
抽出できなかった場合はテーブルに登録をしたいのです。
そこで、下限と上限の値に変更があれば登録をしたいんですが、プログラムでテキストボックスから自動で抽出された値に変更があれば登録しますか?という画面を出したいのです。
もう一つはhatenaさんのおっしゃるようにテーブルに登録した後に修正したい場合は読み込み時のテーブルがOldValueに該当するというのがこれですね。
一旦すべて登録してしまい、修正する形のほうがやりやすいでしょうか。
どのようなやり方がいいのか迷っています。
当方、現在、マルチモニターの環境ではないので、これに関してのアドバイスは難しいです。
他の方の回答を待つか、別の掲示板などで質問してください。
hatena様
情報を頂きありがとうございます。
表示するモニター(座標)指定まではうまくいきましたが、
Accessを最大化すると表示が崩れてしまいます。
Windows11ではAPIの動作が異なる様です。
標準の機能ではないので、Windows APIを使うことになりますね。
下記でも議論されてますが、かなり面倒そうです。
【2つモニターを使用している際のフォームの表示位置】
この以前の値というのがなんなのかをまずは明確にしてください。
あるいはその非連結コントロール(非連結フォーム)の使用目的も明確にしてください。
連結コントロールの場合のOldValueは下記の公式ドキュメントに解説があります。
連結フォーム上でコントロールを編集しても保存アクションを実行しないかぎりテーブルは更新されません。この更新前のテーブルの値がOldValue、編集中のコントロールの値がValueということになります。
その非連結フォームが、
テーブルから値を読み込みコントロールに設定する。
ユーザーがコントロールを編集する。
保存ボタン等で編集内容をテーブルに保存する。
という機能を持っているものなら、
読み込み時のテーブルの値が、連結コントロールのOldValueと同等のものいうことになります。
うろ覚えですが、テキストプロパティとバリュープロパティがあったと思う。違いを利用すれば、出来そうな気もするが、最近触ってないので外しているかもしれない。他には、もうひとつ非連結テキストボックスを用意してコピーしておくとか。
それはさておき、前後の流れを踏まえた上で、そのフラグ立てに本当に何か意味があるのか、と検討するほうが大変です。
OldValue の代わりになる Variant 型の変数をモジュールレベルで宣言しておき、
適当なイベントであらかじめ「更新前の値」をその変数に保存しておくしかないでしょう。
あらゆる非連結テキストボックスで使い回しできるようになさりたいのであれば、
そういうクラスモジュールを作成することになります。
自己解決しました。
TBLをSUBFORMで表示する際に、COLUMNの幅設定を間違えていたようです。
ちなみに当時の回線環境は次のとおりです。
PC→ルーター:ギガビットイーサ
インターネット回線:フレッツ光 1G(一般に契約できる普通の回線です)
5年ほど前にAzureのSQLSeverとVBの組み合わせで構築したことがあります。
ODBC接続で行っていたので、AccessとVBの違いはあまり無いと思います。
ご質問は「インターネット回線を使う場合とローカルの環境とでは速度差があるのか」「インターネット回線での速度が実運用レベルなのか?」ということですね。
速度差はあるかないか、でいうとあると思いますが、認識できるほどか、ということかと思います。
わたしが実現した際は速度差はほぼ無い、でした。
※もちろんこれは回線以外、サーバー性能等は同一と仮定した場合です。
例えば1000人程度の社員の情報から帳票を出力するDB程度であれば、ローカルでもネット回線でも動作速度はほとんど変わらないのではないかと思います。
結局回線を通るデータ量が対した量にならないから、というのが理由です。
やったことはないですが、何千万件のデータをドカドカ回線越しにアプリへ送る、というような内容であれば違いがあるかもしれません。
少なくとも当時構築していた勤怠管理システムでは、Azureでもまったく問題ありませんでした(ただし別の理由で使用は断念しました)
「AZUREでの構成の場合コードなどの書き方注意点」に関してはあまり記憶にありませんので、御役に立てません。
当時はAZURE SQLとオンプレミスのSQL Serverでは同じ命令が使えなかったり、動作制限があったりしたのでいまいちでした。
もしかすると現在は改善済かもしれません。
単なる体験談になりましたが、御役に立てれば幸いです。
hatena 様
ありがとうございました。
プログラムを停止させれば良かったのですね!
勉強になりました。
下記でどうでしょう。
hatena 様
インポート定義を追加したらできました。
DoCmd.TransferText acImportDelim, "インポート定義", "テキスト1", GetFileName, True
※ダイアログ開いてから「キャンセル」を選ぶとエラーになります。
解決策はありますでしょうか?
なんども申し訳ありません。
hatena 様
前投稿の
説明が不足してました。申し訳ありません。
あらかじめ用意したインポート用のテーブルがあり
そのテーブルにインポートするとエラーになります。(先投稿の)
(ウィザードで手動ではインポートできます。)
勘違いでした。
インポートできてましたが文字化けと
インポートエラーのテーブルができます。
また、望んでいる状態のデータインポートに
なっておりませんでした。
画像の順番は
インポートエラーの画像
テーブル1の状態
手動での状態です(理想状態)
手動手順
※インポートしたいCSVファイルのアップロードはできないのでしょうか?
宜しくお願いします。
hatena 様
説明が不足してました。申し訳ありません。
あらかじめ用意したインポート用のテーブルがあり
そのテーブルにインポートするとエラーになります。(先投稿の)
(ウィザードで手動ではインポートできます。)
hatena様
ありがとうございます。
ダイアログからCSVファイルを選択しますと
テキストボックスにフルパスが入りますが
以下のエラーが表示されました。
何度か試しましたが同じ状態です。
CSVファイルのインポートは DoCmd.TransferTextメソッドでできます。
詳細は下記で確認してください。
DoCmd.TransferText メソッド (Access) | Microsoft Learn
フォーム上にコマンドボタン「コマンド0」、テキストボックス「テキスト1」か配置してあり、
「テーブル1」にインポートするとすると下記のコードになります。
ダイアログの表示方法は分かりました。
ダイアログから選択したファイルを「テキストボックス」に
表示させインポートする方法を教えてください。
ダイアログ表示は下記のようにしました
Private Sub コマンド6_Click()
On Error Resume Next
'変数定義
Dim intRet As Integer 'ダイアログ用変数
Dim GetFileName As String 'フルパスの値
With Application.FileDialog(msoFileDialogOpen)
'ダイアログのタイトルを設定
.Title = "ファイルを開くダイアログ"
'ファイルの種類を設定
.Filters.Clear
.Filters.Add "Microsoft Office Excelファイル", ".xls,.csv"
.FilterIndex = 1
'複数ファイル選択を許可しない
.AllowMultiSelect = False
'初期パスを設定
.InitialFileName = CurrentProject.Path
'ダイアログを表示
intRet = .Show
If intRet <> 0 Then
'ファイルが選択されたとき
'そのフルパスを返り値に設定
GetFileName = Trim(.SelectedItems.Item(1))
Else
'ファイルが選択されなければブランク
GetFileName = ""
End If
End With
'選択されたフルパスをテキストボックスへ表示
Form_F_Form.テキストn.Value = GetFileName
End Sub
ということなら、
の部分は、下記に修正してください。
テキスト型のフィールドのSQL条件式は値を引用符(')で囲む必要があります。(あと、読みやすくするために改行も入れてます。)
コード中での引用符の使い方については下記で解説していますので、参照して内容をよく理解しておくことをお勧めします。
Access上のコード内で引用符(")と単引用符(')の使い分けについて - hatena chips
もしも、外部サイトのカレンダー形式のスケジュール管理フォームを参考にしているのであれば、何を参考にどこまで取り入れていますか?中途半端に真似していないと、情報開示したほうが解決に近づくと思います。