Private Sub ほにゃらら()
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(“SQL文“)
Set Me.Recordset = rs
Me.Data1.ControlSource = rs![data1].Name
Me.Data2.ControlSource = rs![data2].Name
rs.Close
Set rs = Nothing
End Sub
Private Sub 受注選択_Click()
If Forms!F_品種マスタ_抽出_受注!F_品種マスタ_サブ.Form.Recordset.RecordCount = 0 Then
Beep
MsgBox "品種が正しく抽出されていません。", vbCritical, "在庫管理"
Else
Forms!F_受注入力_メイン!受注明細.Form!品種番号 = Me.F_品種マスタ_サブ.Form!品種番号
Forms!F_受注入力_メイン.SetFocus
Forms!F_受注入力_メイン!受注明細.Form!受注本数.SetFocus
DoCmd.Close acForm, "F_品種マスタ_抽出_受注"
End If
End Sub
mayu様
アドバイスありがとうございます。とても助かります!
10年以上にわたり使用されていた接続の方法に問題があったとは…コードしか見ていませんでした。
複雑に絡み合った古いものに手を付けるのが面倒ではありますが、良い機会ですから見直し進めてみます。
ODBCは64bitでデータソース接続しただけで安心していました。ドライバが必要なんですね。探してみます。
とても助かりました。精進いたします!
朱色様へ 度々の回答ありがとうございました。ファイルBのプロシージャ実行マクロが動作しないのです。モジュール(Module1)自体は動作するのですが。マクロのプロシージャ名をModule1にしているのですが”名前が見つからない”となります。記述が間違っているのでしょうか?
結論から申し上げると
リンクテーブルを作った時点で ADO を使う必要は無いでしょう。
Accessのオブジェクト構造とミドルウェアの選定がミスマッチという印象を受けます。
は、OLEDB 接続した SQLServer の Recordset を
ダイレクトにAccessフォームへバインドするときに有効な方法ですから
ローカルにリンクテーブルが存在する現在の構成ですと、このコードは不要です。
王道の連結フォームでAccessデータベースを運用すればいいでしょう。
これは 32bit, 64bit に関係なく問題があるでしょう。
リンクテーブルは、ローカルにあるのに
ADODB.Connection はローカルではなく、サーバーに接続しています。
また、リンクテーブルというのは 外部データベースのスキーマを
Access用に変換したテーブルですから、操作は ADO ではなく、DAO でおこないましょう。
最後に、動作がおかしくなるのは おそらく
64bitアプリにおいて、32bitアプリ用のODBCドライバを使っているからでしょう。
64bitのODBCドライバを使ってリンクテーブルを作成して下さい。
/x は Accsess起動時にこのマクロを実行してね、という意味です。
/cmd は Accsess起動時にコマンド値を持たせてね、という意味です。Commandて打つと渡したコマンド値を教えてくれます。
参照:Microsoft Office 製品のコマンド ライン スイッチ
今回の場合は「 /cmd Me.[部品構成ファイル対象ID]」で値を持っていけると思います。
取り出したい場合はCommandて打てばよいので、前回回答でいうSamoleの中身は
という形になります。
なお /x で指定できるのはマクロだけなので、
マクロ1呼び出し→マクロ1でプロシージャSamole呼び出し→Samoleでフォーム呼び出し
という流れを作っていました。
マクロでもwhere文にcommand使えるならモジュールの作成は不要ですが、
試してないので...
「取引先コード」テキストボックスの更新後処理のイベントプロシージャに下記のコードでどうでしょうか。
mayu様、りんご様
コメントありがとうございます。
mayu様
結果から申しますと、すべて変わらずで#Name?のままでした。
【 4 】のご提案は、Accessファイルのゴミが原因ならこれで解決!と思いまっさらな状態から簡単なものを作成しましたがダメでした…。
りんご様
方法はその通りです。rsをこの中でCloseしてしまうと、リンクデータが無くなってしまうのでCloseはしていません。
こちらの環境では、データはSQLServer上にあり、リンクテーブルからADOdbで読んでいます。
そこで、mayu様のご提案で作成した新しいaccdbがありましたので、これにローカルテーブルを作成して試したところ…
そちらは正しく表示されます!
ですので、ADO接続の際のリンクに何かあるのかもしれません。
新しく作成したaccdbのコードは以下で、このaccdbを32bitAccessで動作させると問題なく、64bitAccessではダメなのが再現できました。なんでか全くわからずです。
何かしょうもない見落としな気もするのですが…
Private Sub cmdADODB_Click()
Dim rs As New ADODB.Recordset
Dim strSQL As String
strSQL = "SELECT * FROM リンクテーブル WHERE DATA1 LIKE '%みかん%'"
rs.Open strSQL, cn, adOpenStatic, adLockOptimistic
' cn はADOBE.Connection としてSQLServerに接続しています。
Set Me.Recordset = rs
If rs.EOF = False And rs.BOF = False Then
Me.txtData1.ControlSource = rs![DATA1].Name
Me.txtData2.ControlSource = rs![DATA2].Name
End If
Set rs = Nothing
End Sub
Private Sub cmdlocal_Table_Click()
Dim rs As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT * FROM test_table WHERE DATA1 LIKE '%みかん%'"
Set rs = CurrentDb.OpenRecordset(strSQL)
Set Me.Recordset = rs
Me.txtData1.ControlSource = rs![Data1].Name
Me.txtData2.ControlSource = rs![Data2].Name
Set rs = Nothing
End Sub
Private Sub cmdClear_Click()
Me.txtData1.ControlSource = ""
Me.TxtData2.ControlSource = ""
Set Me.Recordset = Nothing
End Sub
その後 ファイルBの方のマクロ(MaOpenFormBという名前にして)をフォーム開くで所定のフォームは開ける様になりました(ファイルAのフォーム上のボタンには『Shell "msaccess ""C:\Users\user\Desktop\ACCESSファイル\製品部品構成.mdb"" /x MaOpenFormB", vbNormalFocus
』と記述しました)。あとやりたいことはフォームAに登録している番号(B用の)と合致する条件でファームBを開きたいのです。 "部品ID=" & Me.[部品構成ファイル対象ID] の部分です。これはどこに記述したらいいでしょうか? MaOpenFormBのWHERE条件部でしょうか?そこにはファイルAフォームの事も記述可能なのでしょうか?
度々すみません。
【解決】
hiroton様
ありがとうございます!
動きました!!
なるほど!そういう意味だったのですね。
このコード自体ネットで調べて拾ってきたものなので意味が分かっていませんでした。
ご指摘を受けてコードの意味が理解出来ました。
とても勉強になりました。
ありがとうございました!
朱色様へ回答ありがとうございました。一方通行でいいのです。下記で記述して記述直後は動作するのですが一旦アプリを終了して再度実行するとフリーズしてしますのです。
Dim acMdb As Object
Set acMdb = GetObject("C:\Users\user\Desktop\ACCESSファイル\製品部品構成.mdb")
acMdb.Application.Visible = True
acMdb.Application.UserControl = True
acMdb.Application.DoCmd.OpenForm "F部品入力", acNormal, , "部品ID=" & Me.[部品構成ファイル対象ID]
Set acMdb = Nothing
それで Shell ("msaccess ""C:\Users\user\Desktop\ACCESSファイル\製品部品構成.mdb") を記述し直ししました。
具体的に標準モジュールには同記述するといいでしょうか? そしてマクロには?
そしてShell "Accsess本体パス\MSACCESS.EXE" "DBファイル.accdb" /x マクロ1 /cmd "ファイルBに渡す内容(IDとか)"には? ちなみにマクロ1の前のXは必要でしょうか?
すみません、知識(勉強不足)で基本が理解できていなくて・・・
続きの処理(
If IsNull(MaxID) Then
以下)自体は問題ないです。最初に指摘した通り、「目的の範囲」が正しく設定されていないのが問題です具体例を見てみましょう
今日が2021/8/31ならば
AutoID
は20210831
ですLeft(受注コード,4)
はそれぞれ次の通りでAutoID
と比較するとです(Left 関数)
AutoID
は必ず8文字ですが、Left(受注コード,4)
は最大でも4文字にしかなりません。4桁の文字と8桁の文字を比較したら絶対に一致することはありません処理の前後や、実際に使っているデータがどうこうということは関係なく、>> 1の指摘だけでこのプログラムは正常ではないということがわかるわけです
目的の結果を得る方法はいくつかありますが、コードを流用するなら次のような比較を考えればいいです
ありがとうございます。
そういう事なんですね。
ご指摘を受けて、コードを触ってはみるのですがどうもうまく動きません。
どうすれば下3桁を自動連番にできますか?
教えて頂けませんか?
宜しくお願い致します。
>> 3
もしかして、こんなコード?
では、思いつく限りで あと4つほど提案してみます。
以下のいずれでもダメだった場合、ちょっとお手上げですね。
【 1 】
循環参照という可能性も無くはないと思いますから
その可能性も検証してみましょう。
Data1, Data2 というコントロール名を Recordset のカラム名とは異なる名前に変更します。
Data1 から Data_1 に変更
Data2 から Data_2 に変更
コントロールソースに値を代入する際、Recordset のカラム名を [ ] で括って
オブジェクト名であることを明記します
Me. ではなく、Forms("フォーム名").Controls("コントロール名") として
Access が誤認識する余地を完全に無くします。
※ フォーム名はご自身の環境に合わせて下さいね。
その結果、以下のようになるはずの
といった記述でも #Name? になりますか。
【 2 】
( くろさんから垣間見えるスキルからして、可能性は限りなく低いと見てはいますけど )
フォーム名やテーブルの列名といったオブジェクト名において
といった怪しい文字を使っていたら、一旦全て半角英数に変更。
【 3 】
「 ファイル 」メニューから
「 オプション 」→ 「 現在のデータベース 」と進み、
「 名前の自動修正オプション 」にあるチェック項目を全て外す
【 4 】
新規の accdb を作成し、全てのオブジェクトをインポートしてみる
mayu様、りんご様
コメントありがとうございます。
mayu様
おっしゃる通り、Me.をはずしたり Me!Data1.ControlSourceとしてみたり、
はたまた Me.Data1.ControlSource = "DATA1" など指定してみたりしましたが、
結果変わらず、テキストボックスの表示が #Name? となります。
Requery系については、少々複雑なコードでしたがそのような箇所がみあたらず、
また、これら指定の直後にPauseいれて確認したのですが、この指定直後にはすでに#Name?表示でした。
この時のControlSourceに指定した rs![data1].Name の値は期待通りの文字列で"DATA1"でした。
これも文字列として .ControlSource = "rs![DATA1]" としたり "[rs]![DATA1]"としたりして試したのですが変わらずで…
rs![data1].valueには正しくデータが見えるので、rsにデータが入っていないとか間違っているという事はありません。
りんご様
32bit版では問題なく動作しているコードですが、64bit版のAccessにおいてはその表示が#Name?となっています。
エラーは発生せず、表示が#Name?となるだけなのです。
rs にはSQLを発行した結果がすでに入っており、その抽出データをリスト表示させているものです。
64bit版Accessにおいては、.ControlSourceへの指定方法が変わったのかと思い検索しましたが良い情報もみつからず、諸先輩方に同一の経験をされた方がいらっしゃれば、と思い質問させていただきました。
検索条件「
"Left(受注コード,4)=" & AutoID
」は絶対に一致するものがないのでDMax("受注コード", "T_受注", "Left(受注コード,4)=" & AutoID)
はどんな場合でもNullになりますなので、いくらレコードが追加されても「受注コード」は「
AutoID & "001"
」にしかなりませんhiroton様
ご回答ありがとうございます。
ただ、すみません・・・。
当方のレベルでまだご回答頂いた内容が理解できていません・・・。
申し訳ございません・・・、つまりどういう事でしょうか?
宜しくお願い致します。
AutoID = Format(Date, "yyyymmdd")
→8桁(文字)Left(受注コード,4)
→4桁(文字)"Left(受注コード,4)=" & AutoID
は常に一致するものが存在しないのでMaxID
は常にNullです【自己解決】
以下コードで動作しました!
Private Sub 受注選択_Click()
If Forms!F_品種マスタ_抽出_受注!F_品種マスタ_サブ.Form.Recordset.RecordCount = 0 Then
Beep
MsgBox "品種が正しく抽出されていません。", vbCritical, "在庫管理"
Else
Forms!F_受注入力_メイン!受注明細.Form!品種番号 = Me.F_品種マスタ_サブ.Form!品種番号
Forms!F_受注入力_メイン.SetFocus
Forms!F_受注入力_メイン!受注明細.Form!受注本数.SetFocus
DoCmd.Close acForm, "F_品種マスタ_抽出_受注"
End If
End Sub
Hatena様の別サイトの投稿を見つけ解決いたしました。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11130145846
サブフォームの場合メインフォームのに埋め込んでるサブフォームのコントロール名を指定しないといけないわけですね!
どのような状況なのか文章だけでは把握しづらいです。
現状のレポートのプレビューのスクリーンショット画像をアップロードしてもらえると回答が付きやすいかと。
此方32bit版なのであれですが、『Set rs = Me.Recordset』みたいな記述をよく見ます。
32bit版の問題が起こらないコード、64bit版の問題が起きるコード、エラーメッセージの有無、もう少し詳しく出さないのでしょうか?
ご回答ありがとうございます。
そちらは確認してしましたが、@はありませんでした。
キーになる項目と当該長いテキスト型のフィールドだけを別シートに
出力するとフルで出力されました。ですので、現状、それを別シートに吐き出し、
本来出力したいフィールドは空データで出力し、最後に、VlookUp関数で、
別シートを参照するような方法でひとまずは回避いたしました。
特に根拠は無いですけど
個人的には、以下の2つを試してみます。
【 1 】
Me.Data1.ControlSource = rs![data1].Name
Me.Data2.ControlSource = rs![data2].Name
の記述を
Data1.ControlSource = rs![data1].Name
Data2.ControlSource = rs![data2].Name
として、Me. を外してみてもエラーが出るのか
【 2 】
Set Me.Recordset = rs
の後に
Requery 系メソッドを発行してる箇所があったらコメントアウト
テーブルをデザインビューで開いて
該当フィールドの 書式プロパティに「@」の記述があるようでしたら
消してみて下さい。
何をしたいのか良く分かってないんですが、
やり取りじゃなくて一方通行でいいのなら
●ファイルB側に以下を作成
標準モジュール
マクロ1
●ファイルA側で以下を実行
`
ファイルAで指定したレコードのIDをファイルBのフォームで拾ってどうのする、という考えで書いてますが、
単純にフォーム開くだけでいいならマクロ1の中身を「フォームを開く」とかにして
ファイルA側のコマンドの「/cmd」以降は不要です。
なお当方2003環境ないので試してないです。
実装しました。結果、9500行を16秒でINSERTできたのでだいぶ改善されました。
ありがとうございました。
未だWIN7にてACCESS2003を使っています。ACCESSファイルAのフォーム上ボタンからACCESSファイルBのフォームを開きたいのです。ネットで調べて”Set acApp = CreateObject("Access.Application")
acApp.OpenCurrentDatabase***等のコードを記述したところ記述直後は動作するのですが、一旦ASSESSを終了して再度動作させてみるとフリーズしてしまうのです。何度同じ事をしても一緒です。意味がわからなくて。SheLLを使うとACCESSファイルBは何度でも開くのですがそこからリンクさせた所定のフォームを開く方法がわかりませんファイルAフォームのIDと関連させたファイルBフォームを開きたいのです。
コメント追加です。
テーブルにはフルで文字列が保存されているものの、クエリのデータシートビューで開くと、そのフィールドは255文字までしか表示されいません。
有難うございます。参考情報をみてトライしてみます。
おそらくですが、VB.NET で利用なさっているのが
ADO ではなく、ADO.NET の DataSet だからではないでしょうか。
レガシーADO は OLE DB プロバイダー
ADO.NET は .NET Framework データプロバイダー
とアーキテクチャも異なっており、
名前が似てはいますけど、仕様は全くの別物になっています。
一応、SQLServer 側のテーブルから Acccess のテーブルへ
Insert文を発行する例を載せておきます。
レスありがとうございます。
VB.NETの方でしたら、レコードセットの受け渡しをしてテーブルに反映ができましたので、
Accessもできると思っていました。
残念ながら、無理でしょう。
ご自身で書かれているように、INSERT文を用いて TBL2 にデータをコピーして下さい。
理由:
RstD のインスタンスを Rst0 に単純コピーするだけでは
Rst0 は、単に RstD のクローンになるだけで無意味ですし、
コピーした後に Rst0 の ActiveConnection を Nothing に設定すると
Rst0 は、どの DB とも接続されていない 独立した ADODB.Recordset にはなります。
で、Rst0 を Access 側である TBL2 の ADODB.Recordset として扱うためには
ActiveConnection プロパティと Source プロパティを書き換える必要がありますけど
Source プロパティは Recordset.Open 後、読取り専用のプロパティになっています。
結局、Source プロパティを書き換えるためには Recordset を一度閉じる必要があるのですけど
言うまでもなく、Closeメソッドを呼び出すと
Rst0 に内包されていたデータは消滅してしまいます。
この度はいろんな方に御指南していただきまして、
ありがとうございました。
無事、hirotonさんの記載くださった方法で、
問題が解決しました。
どうもありがとうございました。
ありがとうございます
クエリで日付から単価や開始日を呼び出したりする形で使いたかったので
hatenaさんのコードをもとに標準モジュール(日付を入数化)にする形で対応できました
解決しました!
ありがとうございました。
'TBL1からTBL2へデータをコピー
'接続1
'SQL server
Dim StConnectDB As String
Dim dCnn As New ADODB.Connection
dCnn.ConnectionString = "Provider=SQLOLEDB; " & _
"Data Source=SALESSV2\ABCINSTANCE; " &
"Integrated Security=SSPI;Initial Catalog= 'AAA'"
dCnn.Open
Dim RstD As New ADODB.Recordset
Dim Sql As String
Dim fDate As Date
Dim tDate As Date
fDate = "2021/08/01"
tDate = "2021/08/31"
Sql = "select * from TBL1 " &
"where planDate between '" & fDate & "' and '" & tDate & "' " &
"order by ID"
RstD.Open Sql, dCnn, adOpenKeyset, adLockOptimistic
'接続2
'Access local
Dim Cnn As New ADODB.Connection
Dim Rst0 As New ADODB.Recordset
Set Cnn = CurrentProject.Connection
Rst0.Open "TBL2", Cnn, adOpenKeyset, adLockOptimistic
Set Rst0 = RstD.Clone
'TBL2に反映させたい
'while で addnewすれば書き込めるが、 SQLのinsertのように一気に書き込みたい
'TBL1とTBL2は構造は同じ
Cnn.Close
ありがとうございます。
クエリの抽出条件の欄に、
=[Forms]![フォーム名]![コンボボックス名]
と入力すれば良いのでしょうか?
入力してクエリを実行したのですが、パラメータの選択も求められず、何もデータのない結果のみが表示されてしまったのですが…
よろしくお願いいたします。
フォーム上にコンボボックスを配置して、クエリではそれを参照するようにすればいいでしょう。
下記のような式で参照できます。
途中でもいいので現状のコードを提示してください。
上記で紹介している関数を使えば、