Access (VBA)

Access VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(指定なし : 指定なし)
ドラッグアンドドロップというか、他の何か
投稿日時: 26/01/28 01:25:32
投稿者: うみねこ@かもめ

Accessのフォームに、ファイルをドラッグアンドドロップした時にイベントを起こしたいです。しかしよくダウンしてしまいます。
そのイベントの中身はファイルをとあるフォルダに移動し、その共有URLをD&Dしたテキストボックスに貼り付けるというもの。
共有URLを取得するのはPythonでやらせ、VBAとは分離していますが、取得できないエラーみたいなのが張り付けられたり、くるくる輪っかが回ってダウンなどの症状が出ます。その時のレコードは飛んでいます。
簡単に言って不安定なのです。
絶対パスの取得までは安定してできるので、このパスとユニークのテーブルを作りエクセル側に射出しPythonで共有URLに変換、のちにAccessに取り込むなどの工夫をすればこのような不安定からかいほうされるのでしょうか? どのようなアプローチが有効でしょうか、これ以上は一人の発想では抜け出せなくなっている気がしてアドバイスを求めたい次第です。

回答
投稿日時: 26/01/29 09:52:32
投稿者: Suzu

どんな コントロールのどんなイベントを使用し
Python を 呼び出し、 戻り値? をどのように VBA 内で使用しているのか
 
質問文からは具体的な内容が読み取れないので、
どのように対応すればよいか聞かれても 回答に窮してしまいます。
 
とりあえず、エラーみたいなの が張り付けられる との事ですが
そのエラーが どこ で起こっているのか を明らかにしましょう。
 
また、ファイルを「移動」との事ですが、
そのファイルを ドラッグアンドドロップ という事は、そのファイルを使っている事になるはずです。
その後始末はきちんと行っていますか?
 
後始末をおろそかにして、そのまま移動させようとすると、
・ファイルを使っているので移動できない
・後始末の前に 先にファイル移動が実行されてしまい、後始末に失敗する
の様な事が考えられます。
 
単にパスを取得する『だけ』なら、どんな方法でも良いでしょうが
その結果をどう使うのかまで考えてコード設計を行いましょう。
 終了まで監視できる様に 全てVBA内で処理するとか、移動ではなく、コピー後、削除するとか・・
 
 

引用:
その時のレコードは飛んでいます。
簡単に言って不安定なのです。
絶対パスの取得までは安定してできるので、このパスとユニークのテーブルを作りエクセル側に射出しPythonで共有URLに変換、のちにAccessに取り込む

 
説明から、処理内容が判断できません。
D&D を行った ファイルの フルパスは取得できている。ってのは理解できるのですが・・
 
ユニークのテーブルってなんでしょう? フルパスと、共有URL の対応テーブル?
それができるなら、Python で共有URL で 変換する必要は無いのでは?
 
それをエクセルにエクスポートして Python に渡し Access に戻す? 何のためにExcelを間に挟むの?
 
 
全体感は判っても、それらをどのように処理しているのか分からないので
一般的なデバック方法をお知らせして終わりにします。
 
具体的にどの処理で問題が発生しているのかを明らかにする。
 ・シングルステップで実行しながら、ローカルウィンドで変数を追っていき
  ローカルウィンドの変数が 想定通りになっているか 確認
 ・変数により処理フローが変わるでしょうから、
  その想定した処理フロー通りの分岐になっているか 確認
 
シングルステップでは、処理遅延の関係等でエラーが再現できない場合があります。
・Debug.Print を使い、処理位置と共に、変数内容 をイミディエイトウィンドウに出力し確認
・条件分岐や、処理内容 を すこしづつ コメントアウトして エラーが発生しなければ問題ないので
 問題が発生する場所を逆に特定させる
の様におこない、問題が発生する位置を特定し
 
その処理内でどこに問題が発生しているのかを明らかにして対策を講じます。
 
頑張ってください。

投稿日時: 26/02/04 23:20:18
投稿者: うみねこ@かもめ

なかなか時間が取れず、コメントが遅くなりますがお付き合いいただきありがとうございます。
D&Dするという意味でのVBAです。
 
Private Sub 見積書_AfterUpdate()
    Dim rawPath As String
    Dim srcPath As String
    Dim newName As String
    Dim destFolder As String
    Dim destPath As String
    Dim accDD As String
    Dim pythonExe As String
    Dim scriptPath As String
    Dim shareUrl As String
    Dim f As Integer
 
    If gIsProgrammaticUpdate Then Exit Sub
 
    ' D&D された生の文字列
    rawPath = Nz(Me.見積書.Value, "")
 
    ' 空なら(Delete や Cut)スルー
    If Trim(rawPath) = "" Then Exit Sub
 
    ' # で区切られているので、最初の部分だけ使う
    srcPath = Split(rawPath, "#")(0)
 
    ' 相対パスなら絶対パスに変換
    If left(srcPath, 2) = ".." Then
    srcPath = GetAbsolutePath(srcPath)
    End If
 
 
    ' ★ ここが重要:ファイルが存在しなければスルー(ペースト対応)
    If Dir(srcPath) = "" Then Exit Sub
 
    ' 保存先フォルダ
    destFolder = "C:\Users\展也園部\OneDrive - 有限会社いわき\Docu_yuhgeniwaki\電子書類\リフォーム仕様書"
 
    ' 新しいファイル名
    newName = Me.txb_書名.Value & ".pdf"
    destPath = destFolder & "\" & newName
 
    ' ファイル移動(エラー75などが出たらスキップ)
    On Error Resume Next
    FileCopy srcPath, destPath
     
    If Err.Number <> 0 Then
        Err.Clear
        On Error GoTo 0
        Exit Sub
    End If
    On Error GoTo 0
     
    Kill srcPath
     
    ' 絶対パス欄に反映
    gIsProgrammaticUpdate = True
    Me.txb_絶対パス.Value = destPath
    gIsProgrammaticUpdate = False
 
 
    ' AccDD.txt のパス
    accDD = "C:\PythonScripts\AccDD.txt"
 
    ' AccDD に引数(移動後のパス)を書き込む
    f = FreeFile
    Open accDD For Output As #f
    Print #f, destPath
    Close #f
 
    ' Python 実行
    pythonExe = "C:\Users\展也園部\AppData\Local\Programs\Python\Python314\python.exe"
    scriptPath = "C:\PythonScripts\get_share_url.py"
    shareUrl = RunPythonAndReadAccDD(pythonExe, scriptPath, accDD)
 
    ' テキストボックスにセット
    gIsProgrammaticUpdate = True
    Me.見積書.Value = shareUrl
    gIsProgrammaticUpdate = False
End Sub
 
ここで別の考えでデータをエクセルに射出というのは、ユニークIDと絶対パスのクエリから、共有リンクを作成をエクセル側でやれば、アクセス側のダウンをふせげるのではと考えたからです。
しかしこれから張り付けるPython側からの戻り値によって処理を分岐させればいい。というよりそうしなければならないという考えに至らなかったから迷っている状態なんではと思い始めています。
 

回答
投稿日時: 26/02/05 11:09:29
投稿者: Suzu

から、

引用:
取得できないエラーみたいなのが張り付けられたり、くるくる輪っかが回ってダウンなどの症状が出ます。

が発生しているのは、ドラッグアンドドロップ の戻り値で そんな文字列が返されている。
と推測されます。
引用:
' D&D された生の文字列
    rawPath = Nz(Me.見積書.Value, "")

となっており、ドラッグアンドドロップ の実装部分は何も含まれていません。
 
 
その、取得できないエラーを回避するためには、そのドラッグアンドドロップの中身を見ないと判りません。
 
 
 
提示のコード内で くるくる輪っか が発生しているのですか?
であるなら、どこで発生しているのか、確認しましょう。
 
コードにて気づく点としては
 
    ' D&D された生の文字列
    rawPath = Nz(Me.見積書.Value, "")
 
 
これは、ファイルがDelete/Cut という意味であればそうはなりません。
単に、ドラッグアンドドロップをしていないという意味だけ。
    ' 空なら(Delete や Cut)スルー
    If Trim(rawPath) = "" Then Exit Sub
エラー文字が入っている場合 上記でExit Sub にはならない。
 
 
エラー文字に「#」が含まれていても文字列取得だけなので問題なし。
    ' # で区切られているので、最初の部分だけ使う
    srcPath = Split(rawPath, "#")(0)
 
 
 
ここ。エラー文字の2文字 .. は含まれませんか?
    ' 相対パスなら絶対パスに変換
    If left(srcPath, 2) = ".." Then
    srcPath = GetAbsolutePath(srcPath)
    End If
 
 
エラー文字をそのままDir に渡しています。
ファイルパス文字列に使用できない文字を渡す可能性あり。
その場合の動作については当方には判りません。
    ' ★ ここが重要:ファイルが存在しなければスルー(ペースト対応)
    If Dir(srcPath) = "" Then Exit Sub
 
このコード内で行うとすれば、
この張り付けられた文字列がファイルパス以外であるかをきちんと判定し
ファイルが存在するパス以外であるなら、コードを終了する様にしてはどうでしょうか。
 
 
 
引用:
ここで別の考えでデータをエクセルに射出というのは、ユニークIDと絶対パスのクエリから、共有リンクを作成をエクセル側でやれば、アクセス側のダウンをふせげるのではと考えたからです。

引用:
しかしこれから張り付けるPython側からの戻り値によって処理を分岐させればいい。というよりそうしなければならないという考えに至らなかったから迷っている状態なんではと思い始めています。

こちらに関しては
・「共有リンク」というのが何を指しているのか判らない
・Access-VBAでの処理内容、Excel(VBA)での処理、Python での 想定している処理が不明
・提示コードでは、
   shareUrl = RunPythonAndReadAccDD(pythonExe, scriptPath, accDD)
  の部分で Python を実行している。
 張り付け というのが、話の流れでは、D&D を行ったファイルパス と読め、
 それをPython で取得している?
 であれば、このコードは何をしているのか判らない
・Python 何を渡すのか判りませんが、Python側で Accessのレコードを操作はできないの?
とか・・
 
流れが判らないので、不明瞭な回答しかできません。
 
ご自身で 原因を突き止めたいなら、一つ一つ変数を追ってステップ毎にどう動いているのか
順番に確認する様にしてください。
 
 
コード等にアドバイスが欲しいのであれば、
全体の流れ Access/Excel/Python のそれぞれの処理内容 と関わり
が判る様に説明をお願いします。

投稿日時: 26/02/11 19:07:24
投稿者: うみねこ@かもめ

Pythonがわの処理の前に、別にエクセルでなくても、コードを埋め込んでおけば無垢のAccess側でもいいわけですが、本体側で処理をするとダウンする場合があり、何度もダウンさせていると壊れて使い物にならなくなってしまうのではというのがお聞きしたいことなのです。
もちろん完璧に仕上げてしまえばいいのかもしれませんが、不安定の不格好なままでも使えさえすればいいわけですから、時間をかけて仕上げるよりも壊れてもまた作り直す方が早いのならばそれもありかと思う次第なのです。
 
 
コードを載せると「Forbidden access」となってしまいますね。

回答
投稿日時: 26/02/11 22:32:26
投稿者: MMYS

不安定とのことですが、ソースコードを見た第一印象は、「当選だな」と思いました。
一見ソースには問題ないように見えますが。「単一責任の原則」ってご存知ですか。
 
AfterUpdateイベントの中に「すべての処理」を入れてますよね。つまり、処理が完全に終了しない限り、Windowsはドラッグアンドドロップの処理が終わるのを待つことになります。
それは不安定になる要因では。(またバグとは関係ありませんがメゾットに詰め込みすぎ)
 
あと、どこまで正常で、どこから異常動作するか、調べてますか。ちなみにこのような不安定な動作の時は、ステップ実行ではデバック出来ません。
また処理に時間が掛かり、Windowsに制御が戻らないことが不安定の要因とも考えられます。これが原因場合、ステップ実行では、デバック画面によるプログラムが停止(F8入力待ち)によるWindows制御に移行のため、バグが再現出来ません。
 
このような時は、エラーログ吐き出しを、コードに埋め込みます。
 

Private Sub 見積書_AfterUpdate()

    '<略>

    ' 保存先フォルダ
    destFolder = "C:\Users\展也園部\OneDrive - 有限会社いわき\Docu_yuhgeniwaki\電子書類\リフォーム仕様書"
    writeErrorLog Array("保存先フォルダ", destFolder)

    'ファイル移動(エラー75などが出たらスキップ)
    '<略>
     writeErrorLog Array("ファイル移動", srcPath, destPath)
         
    ' 絶対パス欄に反映
    '<略>
     writeErrorLog Array("絶対パス欄に反映", destPath)

    ' AccDD.txt のパス
    accDD = "C:\PythonScripts\AccDD.txt"
    writeErrorLog Array("AccDD.txt のパス", accDD)

    ' AccDD に引数(移動後のパス)を書き込む
    '<略>
    writeErrorLog Array("AccDD に引数", destPath)


    ' Python 実行
    '<略>
 
    ' テキストボックスにセット
    '<略>

End Sub

Sub writeErrorLog(Optional vntArray As Variant)
    Dim f As Long
    Dim o As String
    Dim i As Variant

    o = Now & "  " & vntArray(LBound(vntArray))
    For i = LBound(vntArray) + 1 To UBound(vntArray)
        o = o & " , " & vntArray(i)
    Next

    f = FreeFile
    Open ThisWorkbook.Path & "\ErrorLog.txt" For Append As #1
    Print #f, o
    Close #f
End Sub

 
異常動作した場合、どこまでは正常動作で、どこで停止しているのか。また、想定外に時間がかかっている場所を、ErrorLogファイルから推測します。
 
 
また、AfterUpdateイベントのコートは長すぎます。デバックの観点からリリファクタリング(サブルーチン化)をおすすめします。
あと、不安定要因はAfterUpdateイベントが終わらずWindowsに制御が戻らないのが要因と推測します。このよなう時はAfterUpdateイベントを一旦終了させ、別処理としてメゾットを呼び出すとうまくいくかもしれません。
 
Private Sub 見積書_AfterUpdate()
    Dim srcPath As String

    '絶対パスを取得
    srcPath = "絶対バス"

    Application.OnTime Now, "'callPython """ & srcPath & """'"

    '見積書_AfterUpdateを終了。Windowsに制御を戻す。その後、Pythonを実行
End Sub

Sub callPython(srcPath As String)
    'Pythonを実行するコード
    '<略>
End Sub

トピックに返信