AccessおよびVBAを勉強しています。
UPDATE文について質問します。
サブフォームにある"T_特記事項"と"T_クレーム履歴"には、それぞれ10個のテキストボックスがあって、
そこにPC上の関連ファイルのパスを入力して、ハイパーリンク型フィールド"特記事項詳細"と"クレーム詳細"に
UPDATEをしたいのですが、更新の度に直前にUPDATEしたパスが消えてしまう現象が出ました。
Debug"1"、Debug"2"を使って確認しましたが、イミディエイトウィンドウには順当に1が10個、2が10個出力されました。
他所で同じ質問をして、Null、"" 、" "とでは違うのだという指摘をもらっています。
http://access2genzo.blog6.fc2.com/blog-entry-37.html
↑コチラに書いていることと同様の指摘だと認識しているのですが、
私の文の作り方が悪いのか?うまく走りませんでした。
どうしたら、直前までのレコードが消えなくなるのか?ご教授いただけたらと思います。
Dim R As Long
For R = 1 To 10
If IsNull(Me("txt_詳細リンク" & R).Value) Then
Me("txt_詳細リンク" & R).Value = Nz((Me("txt_詳細リンク" & R).Value), "")
End If
Debug.Print "1"
If Not IsNull(Me("txt_特記ID" & R).Value) Then
strSQL = _
"UPDATE T_特記事項 " & _
"SET " & _
"口座番号 = '" & Me.txt_口座番号.Value & "', " & _
"特記事項 = '" & Me("txt_特記事項" & R).Value & "', " & _
"特記事項詳細 = '#" & Replace(Me("txt_詳細リンク" & R).Value, """", "") & "#' " & _
"WHERE ID = " & Me("txt_特記ID" & R).Value & ";"
sqlList.Add strSQL
ElseIf Not IsNull(Me("txt_特記事項" & R).Value) Then
strSQL = _
"INSERT INTO T_特記事項 (口座番号, 特記事項, 特記事項詳細) " & _
"VALUES" & _
"('" & Me.txt_口座番号.Value & "', " & _
"'" & Me("txt_特記事項" & R).Value & "', " & _
"'" & Me("txt_詳細リンク" & R).Value & "');"
sqlList.Add strSQL
End If
Next R
Dim Z As Long
For Z = 1 To 10
Debug.Print "2"
If IsNull(Me("txt_クレーム詳細リンク" & Z).Value) Then
Me("txt_クレーム詳細リンク" & Z).Value = Nz((Me("txt_クレーム詳細リンク" & Z).Value), "")
End If
If Not IsNull(Me("txt_クレームID" & Z).Value) Then
strSQL = _
"UPDATE T_クレーム履歴 " & _
"SET " & _
"口座番号 = '" & Me.txt_口座番号.Value & "', " & _
"発生年月 = '" & Me("txt_発生年月" & Z).Value & "', " & _
"クレーム内容 = '" & Me("txt_クレーム内容" & Z).Value & "', " & _
"是正処置 = '" & Me("txt_是正処置" & Z).Value & "', " & _
"クレーム詳細 = '#" & Replace(Me("txt_クレーム詳細リンク" & Z).Value, """", "") & "#' " & _
"WHERE ID = " & Me("txt_クレームID" & Z).Value & ";"
sqlList.Add strSQL
ElseIf Not IsNull(Me("txt_クレーム内容" & Z).Value) Then '「txt_クレーム内容」が空でなければ
strSQL = _
"INSERT INTO T_クレーム履歴 (口座番号, 発生年月, クレーム内容, 是正処置, クレーム詳細) " & _
"VALUES" & _
"('" & Me.txt_口座番号.Value & "', " & _
"#" & Me("txt_発生年月" & Z).Value & "#, " & _
"'" & Me("txt_クレーム内容" & Z).Value & "', " & _
"'" & Me("txt_是正処置" & Z).Value & "', " & _
"'" & Me("txt_クレーム詳細リンク" & Z).Value & "');"
sqlList.Add strSQL
End If
Next Z
一部を略しましたが、更新文です。
複数のSQL実行のためのプロシージャ
一度、連結フォームで作成したものを書籍を参考にVBAでチャレンジしています。
2つのハイパーリンク型のフィールド以外は、難なく更新できています。
"#"で囲っているのが余計だからでしょう。
ハイパーリンク型フィールドのURLは"#"で囲むのが仕様だと思います。
Access Tips #526 ハイパーリンク型フィールドにSQLでデータを保存するには? | T'sWare
Application.HyperlinkPart メソッド (Access) | Microsoft Learn
ハイパーリンク型の実体とは、「ハイパーリンク属性を付与されたメモ型(長いテキスト)」である。
ハイパーリンク型の内部処理上の値は、"#" をセクション区切り記号(囲み記号ではない)とした最大4つのセクションで構成された文字列である。
仮に[txt_詳細リンク]および[txt_クレーム詳細リンク]が共にハイパーリンク型のフィールドをコントロールソースとする連結テキストボックスであるとした場合、そのフィールドの値を"#"で囲む(厳密には「先頭に"#"を挿入する」)という操作は、ハイパーリンクの各セクションを1つ右のセクションにずらすことと同義である。
したがって、件の UPDATE 文が繰り返し実行されれば、やがてハイパーリンクの表示テキスト、ハイパーリンクアドレス、サブアドレスが全て空の状態となり、表示上は「パスが消えてしまう」かのように見えてしまうことになる。
また、[txt_詳細リンク]および[txt_クレーム詳細リンク]が連結テキストボックスではなく非連結テキストボックスであるならば、INSERT INTO ... VALUES ... 文の実行結果も適切ではない可能性があります。
"#"で区切られていない文字列をそのまま代入しているなら、ハイパーリンクの構文上においては「表示テキストのみが設定されている(ハイパーリンクアドレスが2番目ではなく1番目のセクションに入っている)」状態になっているはず。
質問文より
このテキストボックスがハイパーリンク型フィールドとの連結コントロールだとしたらskさんの通りですね。
私としては、
1から10の連番の付加された10個のテキストボックスである、
SQLでは追加するテーブル側のフィールドは一つである、
ということからこのテキストボックスは非連結コントロールだろうと推測してます。
「サブフォームにある"T_特記事項"と"T_クレーム履歴"には」という表現が連結フォームを連想させるのが紛らわしいですが。
連結テキストボックスであれ非連結テキストボックスであれ、(ハイパーリンクの構文規則を無視して)無条件で「"#"で区切られた文字列」を更に"#"で囲んだ結果に更新する処理を繰り返し実行すれば、同様の結果がもたらされることは明白です。
もし非連結テキストボックスであるならば、恐らくそれらのテキストボックスの[ハイパーリンクあり]プロパティを「はい」、[ハイパーリンクとして表示]プロパティを「ハイパーリンクである場合」か「常にハイパーリンクにする」に設定されているだと思われますが、そのテキストボックスに"
###https://zawazawa.jp/ms-access/###
"のような文字列を代入すれば、画面表示上は「何も表示されていない」状態となるでしょう。INSERT INTO の方は見落としてました。
どちらにしても、連結なのか、非連結なのか、
非連結ならハイパーリンクの設定がどうなっているのか、
まずはそれを明確にしてもらうのが先決ですね。
コードをどのように修正するかはともかくとして、テーブル[T_特記事項]のフィールド[特記事項詳細]、およびテーブル[T_クレーム履歴]のフィールド[クレーム詳細]の値が、現時点においてどのように格納されているのかについても、併せて確認された方がよいでしょう。
既に誤った形式のハイパーリンクが格納されてしまっているでしょうから、それらを修正する必要があります。
上記のコードで、詳細リンクがNullの場合、""(空文字列)に変換しています。
下記の次のコードで、
IsNullでNullかどうかをチェックしていますが、その前でNullは""に変換されてますので、このSQLは必ず実行されます。
つまり、""に更新されてしまう。これが下記の原因かと思います。
対策としては、前者のコードは削除して、後者のコードを下記に修正すればどうでしょうか。
上記以外の該当部分も同様に修正してください。
遅くなりました。
私の説明不足によりお二方には色々と推測させてしまい誠に申し訳ないです!
取り急ぎ、テキストボックスは「非連結」であり「ハイパーリンクあり」かつ「ハイパーリンクである場合」です。
試しに、このテキストボックスを「ハイパーリンクなし」に変換して、消えたレコードを読み込ませると
消えたレコードは「######・・・」と表示されました。
この該当テーブルのハイパーリンク型のフィールドを覗くと、「######・・・」であろうレコードはブランクでした。
hatenaさんが提示された通りコードを修正してみましたが、結果は「######・・・」となりました。
よろしくお願いします!
了解です。回答に必須にな情報でした。
この「レコードを読み込ませる」とは具体的にどのように読み込ませているのでしょうか。
「非連結」なので、何かしないと何も表示されません。
『消えたレコードは「######・・・」と表示されました』ということは、UPDATE で前後に"#"を付加することを繰り返した結果でしょう(すでにskさんの回答で指摘されてます)。
誤った状態で保存されているのでまずはそれを修正する必要がありますね。
「######・・・」というのは、例えば「######https://zawazawa.jp/ms-access/######」というような表示でしょうか。(URL部分は一例)
とりあえずskさんの回答の12のSQLのクエリを作成して、それを開いてテーブルにどのような状態で格納されているか確認する必要があります。
すべたのレコードが「######https://zawazawa.jp/ms-access/######」というような状態(#の数はまちまちだがURLの前後に#)でしょうか。
それ以外の書式のものもありますか。あるなら、それを例示してください。
hatenaさん、ありがとうございます!
「btn_読込」に、下記のようなクリック時のイベント(一部抜粋)を設けて、格納させています。
その通りです。
既存レコードには、更新回数分であろう#が前後に増えていて、
レコードの無いところには、同じく更新回数分であろう#で埋め尽くされていました。
現時点ではレコード数も20件と少ないので、skさんからご提示して頂いたSQL文は使わず、
一個一個#を削除して、「#[特記詳細事項]#」のようなあるべき姿にしたところです。
提示いただいたコードは、「T_機械設定」テーブルのデータを読み込んでいます。
質問のコードは、「T_特記事項」「T_クレーム履歴」への書き込みです。
「T_特記事項」「T_クレーム履歴」からの読み込みの部分のコードを提示してもらえますか。
あと、連結フォームでなく非連結フォームで読み込み、書き込みしている理由はなんでしょうか。
見当違いのコードを送ってしまい、
申し訳ありません。
該当コードは後ほどお送りします。
冒頭3でも書き込みましたが、
連結フォームで作って運用中のものを、
VBAの勉強を目的として取り組んでいる次第です。
その為、非連結となっております。
そのように修正済みで、[特記詳細事項]の部分がURLということで、テキストボックスが「ハイパーリンクあり」かつ「ハイパーリンクである場合」の設定なら、
の部分を
でよさそうです。
あるいは、HyperlinkPart関数でアドレス部分のみ取り出して、
遅くなりました。
まずは「T_特記事項」「T_クレーム履歴」に関するSELECT文です。
そして、修正文ありがとうございます。
早速試してみました。
下記の文ですと、パスの前後に"が付いた状態で書き込まれていました。
こんな感じでどうでしょうか。
hatenaさん
提示していただいた文に差し替えてみたところ
「コンパイルエラー 変数が定義されていません」となり
If sAddress <> "" Then s = "#" & Address & "#"
となりました。
HyperlinkPartという関数、初め見たかもしれません。
勉強になります!
あっ、すみません。タイプミスです。下記に修正してください。
If sAddress <> "" Then s = "#" & sAddress & "#"
私の 6 の回答でリンクを置いてます。
何度もスミマセン。
今度は下記で「コンパイルエラー 変数が定義されていません」となりました。
If sAddress <> "" Then s = "#" & sAddress & "#"
hatenaさん
コンパイルエラーは解消されましたが、今度は直前にテキストボックスに入力したPC内のファイルパスが
更新ボタンをクリックしたと同時に消えてしまいます。私の書き方に問題ありますか?
skさんの#12の回答のSQLでどのような状態で格納されているか確認して、表示されない原因と対策を考えましょう。
私が思うに非連結でいくなら、テキストボックスの「ハイパーリンクあり」は「いいえ」に設定しておいた方がいいように思います。
実際にサンプルを作成して動作確認しているわけではないので、推測で提案しています。
非連結フォームの設計はかなりのスキルが要求されます。
連結でできていたものを、勉強のために非連結に変更しているということなので、
このような不具合を自分で解決できるようなスキルアップが必要ということです。
そのためにはまずはデバッグ方法を学習しましょう。
これを使って原因の追究、解決を繰り返すことによってスキルがアップします。
「VBA デバッグ」をキーワードにググれはいろいろ解説ページが見つかるので、
そこでデバッグの方法の理解を深めることをお勧めします。
hatenaさん、長々とお付き合い頂いてありがとうございます。
skさんもありがとうございます!とても感謝しております!!
デバック方法については書籍を参考に試してみます。
特に急ぐようなことでは無いので、時間をかけて学習してみます。
ありがとうございました。
以下に関しては私の推測です。試してみたわけではありまん。
まず、skさんの回答にもありましたがハイパーリンクの内部的な書式は下記になります。
ハイパーリンクを設定した非連結テキストボックスで、入力すると表示テキストのみになるのだと思われます。
つまりハイパーリンクアドレスは無し""という状態
対応策としては、ハイパーリンクアドレスがあればその前後に"#"を付ける。
なければ、表示テキストの前後に"#"を付ける。
このように状況、原因を調べて、対策を考えるという手順を踏みます。
あくまで、推測なのでこれでうまくいくとは限りません。
非連結フォームの設計は、連結フォームならAccessが自動でいろいろしてくれていることをすべて自前で処理する必要がでてきます。
非連結で設計するということは、このAccessが裏でやっていてくれてることを理解、把握しておく必要があります。
ハイパーリンクは格納されているデータと表示されているテキストが一致していないというのが、難しくなる原因です。
他にも日付/時刻型もそうです。
他にも型チェック、参照整合性チェックなど、考慮しなければならないことか多数あります。
複数ユーザーで共有する場合、排他処理なども必要になってきます。
これらのことをすべて実装するとなるとなまはんかのスキルでは無理です。
これらを実装できたとして、連結にくらべてどれほどのメリットがあるのかはなはだ疑問なので、
私自身は非連結はほとんど使いません。
複数ユーザーで共有する場合は、安定性を高めるために非連結にすべきという意見も散見しますが、
上記の点についての言及はほとんど見ません。
複数ユーザーで共有することで不安定になるような規模のシステムなら、すでにAccessではなく他のRDBを検討すべきだと思います。
あくまで私見ですので参考程度に。
hatenaさん
先程ご提示していただいた文で、問題解決出来ました!!
ありがとうございます!
ハイパーリンクの構造を理解していない上に、非連結を使って入力をした事で混乱を招いてしまったのですね...。
申し訳ございませんでした。
VBA関連の書籍のキャッチフレーズに「現場で即使える」と謳われるものが沢山ありますが
現場から要求されるリクエストは、書籍に載っていないものが圧倒的多いように感じますので
hatenaさんの仰る通り、全ての要求に応えられるにはハイレベルのスキルが求められますね。
今回はハイパーリンクについて、hatenaさん・skさんに沢山学ばせていただきました。
長々とお付き合いいただき、改めてお礼申し上げます!ありがとうございます!
まだまだ聞きたいことは沢山あるのですが、それはまた改めて聞きたいと思います。
ありがとうございました!!これからもよろしくお願いいたします!