質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

2519閲覧

VBAで、一部の処理をfunctionで外部化すると戻り値がとれない

junko12345

総合スコア15

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2021/10/01 07:51

前提・実現したいこと

VBAで、エクセルのセルに入力された値を元にHTTP通信し、結果を受け取りセルに出力したいです。
自身のスキルとしては、プログラミング初心者です。nodejs少々、VBAは記録マクロからスタートの独学のみなので、基本が理解できていないのは自覚しています。。
お分かりになる方がいらっしゃいましたらご教示いただけると幸いです。
また基本的な事項のご指摘も、お気付きの点がございましたらお願い致します。

発生している問題・エラーメッセージ

一通り動くことは確認でき、一部の処理を流用するのでfunctionで外部化したいのですが、戻り値が取得できません。
変数= 戻り値.lengthで「書き込みできません」のエラーメッセージが表示されます。

該当のソースコード

VBA

1Function getStatus(ByVal number As String) As Object 2 Dim http As Object 3 Set http = CreateObject("MSXML2.XMLHTTP") 4 5 http.Open "POST", "http://対象のURL", False 6 http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" 7 http.send number 8 9 Do While http.readyState < 4 10 DoEvents 11 Loop 12 13 Dim html As Object 14 Set html = CreateObject("htmlFile") 15 html.write http.responseText 16 17 Dim statusData As Object 18 Set statusData = html.getElementsByClassName("aaa") 19 Do While statusData(0) = Empty 20 DoEvents 21 Loop 22 Set getStatus = statusData 23End Function 24 25Sub aaa() 26 Dim number As String 27 number = Range("A2").Value 28 29 Dim status As Object 30 Set status = getStatus(number) 31 32 Dim cnt As Long 33 cnt = status.Length 34 ・・・この先はエクセルへの出力処理 35 36End Sub

試したこと・確認したこと

処理を外部化する前は、動いていました。上記コードの通り外部化すると、戻り値が取れなくてエラーになってしまいます。
End Functionでブレークポイント入れて、その時点ではstatusDataに欲しいデータは入っています。
cnt = status.Lengthでブレークポイント入れるとstatusの値はなにもない(nothingもemptyも空文字もなし)状態です。

補足情報

OS Microsoft Windows 10 Home
EXCEL Microsoft Excel 2019 MSO (16.0.14326.20344) 32bit

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こんにちは。

少し気になったのですが、そもそも戻そうとしているオブジェクトのstatusData は 
Set html = CreateObject("htmlFile")
で、インスタンス化したhtml オブジェクトの一部ですが、
このhtml という変数がFunction の中でローカル変数として定義されているので
ファンクションを抜けたところで、htmlオブジェクトがなくなってしまい、結果
statusもデータが消えてるのではないでしょうか?

試しに、html 変数をfunction の外でpublic で宣言すると直ったりしませんか?

投稿2021/10/01 11:17

beadv

総合スコア144

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

junko12345

2021/10/01 13:44

回答ありがとうございます!できました!! インスタンス化したオブジェクト。。。 そのあたりの基礎になる知識が不足しておりました。。 とても勉強になりました、ありがとうございます!
guest

0

以下の部分ですが、

VBA

1Do While statusData(0) = Empty 2 DoEvents 3Loop

以下にして試してみていただけないでしょうか?
statusData はオブジェクト変数なので、こちらでの判定のほうが良い気がします。

VBA

1Do While statusData Is Nothing 2 DoEvents 3Loop

投稿2021/10/01 09:03

hex309

総合スコア761

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

junko12345

2021/10/01 09:08

ご回答ありがとうございます! 試してみましたが、結果は同じでした。。
guest

0

vba

1Set status = getStatus(number)

ここにbreakpoint置いて、statusを確認してみては?

投稿2021/10/01 07:55

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

junko12345

2021/10/01 08:01

早速ご回答ありがとうございます! Set status = getStatus(number) ここにbreakpoint置いてstatusを確認すると「empty」となっています。 functionの最後にbreakpointを置くと、functionの中の処理は実行されているのですが。。
hex309

2021/10/01 08:05

確か、ブレークポイントだとその行の実行前だったかと。 その行の次に Stop といれて「status 」を確認してみてください。
退会済みユーザー

退会済みユーザー

2021/10/01 08:06

↑そのとおり breakpointはこれから実行する命令で止まります
junko12345

2021/10/01 08:11

>stop ご指摘ありがとうございます!勉強になります! stopを入れてbreakpointを置くと、statusの値はなにもない(nothingもemptyも空文字もなし)状態です。
退会済みユーザー

退会済みユーザー

2021/10/01 08:19

ということはまだ、取得処理が終わってないってことですね
junko12345

2021/10/01 08:50

>取得処理が終わってない sleepやApplication.waitで待つ、ということかと思って試しましたがダメでした。。認識違いでしょうか。。。
退会済みユーザー

退会済みユーザー

2021/10/01 09:03

Do While http.readyState < 4 これでチェックしているからOKそうですね もしかして、そもそもhtmlが取得できていないのかも http.responseText の内容が正しいかチェックですね 関数化したのは無関係かもしれませんよ
junko12345

2021/10/01 09:10

End Functionの時点ではデータは期待通りに取得できており、 外部化する前は期待通りの動作をしていたのです。。 外部化のやり方が悪いのか、何かの処理のタイミングが悪いのか、いろいろ調べてみたのですがわからず、の状態です。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問