エクセルマクロVBA「Web連携」DOMを使った解析_基礎

この講座は有料講座です。
講座の購入後ご覧になれます。

ログインアカウントの新規作成

解説

この動画では、WinHttp Services 5.1を使って取ってきたWebのコンテンツをDOMを使って解析する方法について、具体例を使って解説しています。

DOM解析のためのライブラリとしてベストなものは?
DOMをたどるときによく活用されるメソッドは?
DOMオブジェクトへの参照をする際に使うデータ型は?

学ぶべきことはたくさんあります。

この教材についての過去の質問・感想

12800 : 小川慶一の回答 (2021-01-10 23:01:25)

田中 宏明さん:

あとから提案する人の出すコードのほうが、おのずと、洗練されたものになるものです。
ベースがあって、それをリファクタリングしていくわけですので (^_^;

ともあれ、みなさんであれこれやっている間に、かなり汎用性の高い部品になった感じがありますね (^^*


12790 : 田中 宏明さんのコメント (2021-01-09 18:27:18)

小川慶一さん:

私が提案したコードよりもシンプルになっています。恐れ入りました。
> 続きです。さらに書くと、たとえばこんな雰囲気で。


12789 : 小川慶一の回答 (2021-01-09 13:08:08)

田中 宏明さん:

続きです。さらに書くと、たとえばこんな雰囲気で。

Public Sub get_response_text_for_various_webpages()
    get_charset_sample_with_func url:="https://www.sej.co.jp/products/area.html"
    get_charset_sample_with_func url:="https://www.yahoo.co.jp/"
    get_charset_sample_with_func url:="https://www.facebook.com/"
    get_charset_sample_with_func url:="https://www.amazon.co.jp/" '結果は文字化けする理由は未調査
    get_charset_sample_with_func url:="https://www.amazon.com/" '503エラーで終わる。たぶん、リクエストヘッダーを参照してエラーを返しているのであろう
End Sub
Private Sub get_charset_sample_with_func(url As String)
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
      
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If

    Dim charset As String, response_body As String
    charset = get_charset(xh)
    Debug.Print charset
    Select Case charset
        Case "shift_jis", "euc_jp", "utf-8" '既知のタイプの場合
            response_body = get_response_body_encoded(xh, charset)
        Case Else
            Debug.Print "unknown charset"
            response_body = get_response_body_encoded(xh, "_autodetect") 'ダメ元で autodetect
    End Select
    Debug.Print response_body
End Sub
Private Function get_response_body_encoded(xh As WinHttp.WinHttpRequest, charset As String)
    Dim byte_body() As Byte
    byte_body = xh.responseBody
    
    Dim ado_stream As New ADODB.Stream
    Dim result As String
     
    ado_stream.Open
    ado_stream.Position = 0
    ado_stream.Type = 1
    ado_stream.Write byte_body
     
    ado_stream.Position = 0
    ado_stream.Type = 2
    ado_stream.charset = charset
    result = ado_stream.ReadText
    ado_stream.Close
    get_response_body_encoded = result
End Function
Private Function get_charset(xh As WinHttp.WinHttpRequest)
    Dim ct As String
    ct = xh.getResponseHeader("Content-Type") 'text/html; charset=UTF-8 等の文字列を得る
    
    Dim stct() As String
    stct = Split(ct, ";")
    
    Dim c As Long
    Dim charset As String
    For c = LBound(stct) To UBound(stct)
        If InStr(LCase(stct(c)), "charset") Then
            charset = Trim(LCase(Split(stct(c), "=")(1)))
            get_charset = charset
        End If
    Next
End Function


12788 : 小川慶一の回答 (2021-01-09 12:38:09)

田中 宏明さん:

charsetを取得するサンプルを僕も作ってみました。
こんな感じですかね。

Sub get_charset_sample()
    Dim url As String
    url = "https://www.sej.co.jp/products/area.html"
  
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
      
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
        
    Dim ct As String
    ct = xh.getResponseHeader("Content-Type") 'text/html; charset=UTF-8 等の文字列を得る
    
    Dim stct() As String
    stct = Split(ct, ";")
    
    Dim c As Long
    Dim charset As String
    For c = LBound(stct) To UBound(stct)
        If InStr(LCase(stct(c)), "charset") Then
            charset = Trim(LCase(Split(stct(c), "=")(1)))
            Debug.Print "charsetは" & charset & "です。"
        End If
    Next
End Sub


12787 : 小川慶一の回答 (2021-01-09 12:14:50)

田中 宏明さん:

スキル情報からご経験から、いろいろシェアいただいていて、いつもありがたく思っています。

> 最初の投稿はとてもドキドキしたものですが、投稿を繰り返しているうちに、他の受講生の質問に対してコメントすることもでき、また更に学びの機会を得ることができました。

新システムのほうでは、こういう交流をもっとやりやすくなるようにしたいと思っています。

ひきつづき、よろしくお願いいたします。


12786 : 小川慶一の回答 (2021-01-09 12:12:16)

たかちゃんさん:

> ガラパゴススタディのレッスンは、本当に凄いです。
> 動画編集とか多少地味めですが、内容が素晴らしい。こんなに分かりやすい講座は初めてです。

こちらこそ、ありがとうございます。

もっとも、演習問題も2周、3周とくり返されていますし、丁寧に理解の足場を固めつつ学習を進められている印象ですし、成果は妥当なものと思います。

> 動画編集とか多少地味め

「DPR」の講座でもお伝えしていることですが、Dがしっかりしていれば(伝えたいことが、構造化されて整理されていれば)、Rはそれほど作り込まなくて良いと考えています。


12785 : 田中 宏明さんのコメント (2021-01-09 12:06:47)

たかちゃんさん:

文字化け対策に再チャレンジ。charsetを読み取って条件分岐させました。

Dim nnn As Long
    nnn = InStr(1, xh.responseText, "charset=")
    If nnn > 0 Then
        Select Case True

            Case InStr(1, UCase(Mid(xh.responseText, nnn, 20)), "SHIFT_JIS") > 0
                htmlDoc.body.innerHTML = ADODB_SHIFT_JIS(xh)
        
            Case InStr(1, UCase(Mid(xh.responseText, nnn, 20)), "SHIFT-JIS") > 0
                htmlDoc.body.innerHTML = ADODB_SHIFT_JIS(xh)
                
            Case InStr(1, UCase(Mid(xh.responseText, nnn, 20)), "EUC-JP") > 0
                htmlDoc.body.innerHTML = ADODB_EUC_JP(xh)
                        
            Case InStr(1, UCase(Mid(xh.responseText, nnn, 20)), "UTF-8") > 0
                htmlDoc.body.innerHTML = ADODB_UTF8(xh)
    
            Case Else
                htmlDoc.body.innerHTML = ADODB_autodetect(xh)
        
        End Select
    Else
        htmlDoc.body.innerHTML = xh.responseText
    End If


> ADODB.StreamオブジェクトのCharsetプロパテの"_autodetect_all"について気になって調べてみました。("_autodetect"は、日本語用)
> 解読先の文字コードが、ANSIとutf-8だと、正常に判別できないらしいです。


12782 : 田中 宏明さんのコメント (2021-01-08 05:24:54)

小川先生、たかちゃんさん:

私はガラパゴススタディのオンライン講座で会社人生に変化がありました。多分良い方に。

実はVBAでコードを仕上げるのも自動記録しかできない初学者並みに遅いですが、それなりに質が高いマクロを書けるようになりました。そのマクロが私の苦手とするスピーディーな実務処理を助け、更には他人の実務を手助けできる場面もあります。

最初の投稿はとてもドキドキしたものですが、投稿を繰り返しているうちに、他の受講生の質問に対してコメントすることもでき、また更に学びの機会を得ることができました。

引き続き、よろしくお願いします。


12781 : たかちゃんさんのコメント (2021-01-08 00:42:48)

田中 宏明さん:

おはようございます。
田中さんのレベルって、私からしたら雲の上の神様のようです。(゚Д゚ )
本当になんとお礼をいったら、いつも本当にありがとうございます。
これからも宜しくお願いします!

> たかちゃんさん
> もう追い越されそうです。
> > ホント、すごいです。
> >
> > 実務に関係ない場でのトレーニングは、このくらいで本当に十分…


12780 : たかちゃんさんのコメント (2021-01-08 00:33:21)

小川慶一さん:

嬉しいお言葉、励みになります。本当にありがとうございます。
ガラパゴススタディのレッスンは、本当に凄いです。
動画編集とか多少地味めですが、内容が素晴らしい。こんなに分かりやすい講座は初めてです。
しかも、価格もお手頃。過去のコメントも大変勉強になりました。

また元生徒さんともコメント欄を通して交流できて、本当にラッキーでした。
MACの件で調べて頂いて、、。あの辺りからプログラミングに対する意識が変わっていき一気に
上達したように思います。(以前は、諦めが早すぎる所がありました。)

レッスンも残り僅かですが、今後は実務を意識して日々精進していきます。
> たかちゃんさん:
>
> おはようございます。

> 実務に関係ない場でのトレーニングは、このくらいで本当に十分かと思います。
> むしろ、実務でガンガンコードを書くことによりリソースを注いでください。


12779 : 田中 宏明さんのコメント (2021-01-07 17:49:35)

たかちゃんさん
もう追い越されそうです。
> ホント、すごいです。
>
> 実務に関係ない場でのトレーニングは、このくらいで本当に十分…


12778 : 小川慶一の回答 (2021-01-07 10:01:04)

たかちゃんさん:

おはようございます。

ホント、すごいです。

実務に関係ない場でのトレーニングは、このくらいで本当に十分かと思います。
むしろ、実務でガンガンコードを書くことによりリソースを注いでください。

> 単純ですが、慣れていないので苦労しました。

Excel VBAでの辞書の活用は、構文的にちょっと面倒くさいんですよね。
僕の場合は、辞書を使ったコードの構想が湧いても、実装を思い浮かべようとしたところでゴチャゴチャしてきます。

> 早くパッと閃くレベルになりたいです。

そこは、もう、十分かと。
たかちゃんさんに提示いただいたコードに対しては、「ここまでの実装の要求をされたら酷だろうな」と考えて通常なら控えるであろうレベルの提案をしています。アルゴリズムについては、かなり鍛えられているのではないかと。

都度つど提示されるコードも、かなりのレベルで整理されていて、本当に素晴らしいです。
それどころか、いただいた投稿から僕が学んでいることも多いです。

「ほんの数ヶ月でここまで来られるとは...」と、社内のスタッフとも話しています。

引きつづき、良い学びと実践を! (^^*


12777 : たかちゃんさんのコメント (2021-01-07 02:35:30)

以下の課題に挑戦し、成功しましたので記念に投稿します。
(添削は不要です。)

GetArea
地域名が羅列されたサイトからデータを取得
key->地域名 item->書き出し先の行

GetOnigiri
商品名と販売地域データを取得
Key->地域名 item->おにぎり名(Variant型配列に入れる)

2つのDictionaryから地域名をKeyに、指定の行へおにぎり名を書き出す。

早くパッと閃くレベルになりたいです。単純ですが、慣れていないので苦労しました。良い練習になりました。(^^;;


12776 : たかちゃんさんのコメント (2021-01-07 02:33:47)

Option Explicit

'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
'Microsoft Scrintping Runtime -> Dictionaryを使用するため
Dim dicTiku As New Dictionary
Dim dicNigi As New Dictionary
Dim ar As Variant

Public Sub Matome()
    GetArea
    GetOnigiri
    Dim i As Long
    Dim j As Long
    Dim k As Long
    
    For i = LBound(dicTiku.Keys) To UBound(dicTiku.Keys)
        Range("A1").Offset(i).Value = dicTiku.Keys(i)
        For j = LBound(dicNigi.Keys) To UBound(dicNigi.Keys)
            ar = dicNigi.Items(j) 'ar配列を使う前に、必ずこのようにしておくこと!
            If dicTiku.Keys(i) = dicNigi.Keys(j) Then
                For k = LBound(ar) To UBound(ar)
                    Range("B" & dicTiku.Items(i)).Offset(, k).Value = ar(k)
                Next
            End If
        Next
    Next

End Sub


Private Sub GetOnigiri()
    Dim url2 As String
    url2 = "https://www.sej.co.jp/products/a/cat/010010010000000/1/l100/"
    
    Dim xh2 As New WinHttp.WinHttpRequest
    xh2.Open "GET", url2, False
    xh2.send
     
    Dim sCode2 As String
    sCode2 = xh2.Status
    If sCode2 <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode2
    End If
     
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml2 As New MSHTML.HTMLDocument
    oHTml2.body.innerHTML = xh2.ResponseText 'htmlボディーをDOMとして取得

    Dim LInner As MSHTML.HTMLDivElement '<div class="list_inner~">
    Dim iTEm As MSHTML.HTMLDivElement '<div class="item_ttl">
    Dim iReg As MSHTML.HTMLDivElement '<div class="item_region">
    Dim tiiki As String
    Dim spTiiki As Variant
    Dim c As Long
   
    Dim oNigiri As String
    Dim yoko As Long
    yoko = 0
    For Each LInner In oHTml2.getElementsByClassName("list_inner")
        'おにぎり名
        For Each iTEm In LInner.getElementsByClassName("item_ttl")
            oNigiri = iTEm.innerText
            'おにぎり名をエクセルに書き出す
'            Range("B1").Offset(, yoko).Value = oNigiri
'            yoko = yoko + 1
        Next
        '販売地域
        '地域名をKey、おにぎり名をItemにしてDictionaryを作成
        For Each iReg In LInner.getElementsByClassName("item_region")
            tiiki = Mid(iReg.innerText, InStr(iReg.innerText, ":") + 1)
            spTiiki = Split(tiiki, "、")
            
            For c = LBound(spTiiki) To UBound(spTiiki)
                If Not dicNigi.Exists(spTiiki(c)) Then
                    dicNigi.Add spTiiki(c), Array(oNigiri)
                Else
                    ar = dicNigi.iTEm(spTiiki(c))
                    ReDim Preserve ar(UBound(ar) + 1)
                    ar(UBound(ar)) = oNigiri
                    dicNigi.iTEm(spTiiki(c)) = ar
                End If
            Next
            
        Next
        
    Next
    
End Sub


Private Sub GetArea()
    Dim url As String
    url = "https://www.sej.co.jp/products/area.html"
 
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
     
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
     
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
     
     
    '地域名を取得、dicTikuを作成。地域名(Key)、書き出し先の行(item)
    Dim tr As MSHTML.HTMLTableRow
    Dim spa As MSHTML.HTMLSpanElement
    Dim tiku As String
    Dim cnt As Long '地区を入力する行
    cnt = 1
     
    For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
        '北海道と沖縄は別の所にもある為、ここでは出力しない
        If Trim(tiku) <> "北海道" And Trim(tiku) <> "沖縄" Then
            Debug.Print Trim(tiku)
            
            dicTiku.Add Trim(tiku), cnt
            cnt = cnt + 1
        End If
         
        'TRタグ内の1番目の子要素(TDタグ)内のSpanタグ内のデータを取得
        For Each spa In tr.ChildNodes(1).getElementsByTagName("span")
            Debug.Print spa.innerText
            
            dicTiku.Add spa.innerText, cnt
            cnt = cnt + 1
        Next
         
    Next
    
    Dim lis As MSHTML.HTMLLIElement
    Dim Nlis As String
    
    For Each lis In oHTml.getElementById("pbBlock1155021").getElementsByTagName("li")
'            Debug.Print lis.innerText
            Nlis = Left(lis.innerText, InStr(lis.innerText, ":") - 1)
            '北陸は別の所にもある為、ここでは出力しない
            If Nlis <> "北陸" Then
                Debug.Print Nlis
                
                dicTiku.Add Nlis, cnt
                cnt = cnt + 1
            
            End If
    Next
     
End Sub
 


12768 : 小川慶一の回答 (2021-01-06 00:07:48)

たかちゃんさん:

> 色々お騒がせしました。昨日は色々テストし過ぎてパニックになっていたようです。
> 改めて、テストをした所、何故昨日うまくいかなかったか理由がハッキリしました。

よくあることです v(^_^;

Webページの解析は、DPRで言うところの「RからR」ですので、なかなかすんなりとは行かないものがあります。


12766 : たかちゃんさんのコメント (2021-01-05 23:40:28)

小川先生、田中さん:

色々お騒がせしました。昨日は色々テストし過ぎてパニックになっていたようです。
改めて、テストをした所、何故昨日うまくいかなかったか理由がハッキリしました。

まず、北海道の後ろについていた謎の半角は、TRIM関数だけで除去できました。(^^;

問題は、If文にありました。
実は、北海道以外にも沖縄も同様に2回出力したくない為、IF文の条件にいれていました。
投稿する時は、簡潔にするため、沖縄の条件は省いて投稿していました。

自分の中では、北海道だけが条件のプログラムでもTrim関数でテストしたと思っていたのですが・・・。
昨日調査した際も、文字コードが32(普通の半角)でしたし、恐らくパニックになって以下のようなIF文でテストしていたのだと思います。



 For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
       
        If Trim(tiku) <> "北海道" Or Trim(tiku) <> "沖縄" Then
            Debug.Print Trim(tiku)
        End If
         
        'TRタグ内の1番目の子要素(TDタグ)内のSpanタグ内のデータを取得
        For Each spa In tr.ChildNodes(1).getElementsByTagName("span")
            Debug.Print spa.innerText
        Next
         
    Next 


イミディエイトウィンドウにはこの様に表示されます。
北海道
北海道
東北
.
. 
沖縄
沖縄県

For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
       
        If Trim(tiku) <> "北海道" And Trim(tiku) <> "沖縄" Then
            Debug.Print Trim(tiku)
        End If
         
        'TRタグ内の1番目の子要素(TDタグ)内のSpanタグ内のデータを取得
        For Each spa In tr.ChildNodes(1).getElementsByTagName("span")
            Debug.Print spa.innerText
        Next
         
    Next 


イミディエイトウィンドウにはこの様に表示されます。
北海道
東北
.
.
鹿児島県
沖縄県


12764 : 小川慶一の回答 (2021-01-05 16:24:44)

たかちゃんさん、田中さん:

おもしろいです。

Byte配列にして解析する処理がなくても、Trimは効いていそうに思います。
この投稿下部に載せたコードは、検証用に書いたものです。どうでしょうか。(僕が、状況をちょっと理解しきれていない?)

あと、

https://thom.hateblo.jp/entry/2016/09/20/150650

このページでさらに紹介されているteratailのサイト( https://teratail.com/questions/136057 )で、AscW関数、ChrW関数が紹介されています。
これらを使うと、Byte配列を使わないでもNBSP等の文字を調査をできそうです。(手元にサンプルがないので試せていませんが)

Sub GetArea()
    Dim url As String
    url = "https://www.sej.co.jp/products/area.html"
 
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
     
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
     
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
     
    Dim tr As MSHTML.HTMLHeadElement
    Dim spa As MSHTML.HTMLHeadElement
    Dim tiku As String
    For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
        inspect_string tiku
    Next
End Sub
Sub inspect_string(tiku As String)
    Dim nazo As String
    Dim naz() As Byte
    Dim hankakuSP() As Byte
    Dim Ntiku As String
    If Len(tiku) > Len(Trim(tiku)) Then
        Debug.Print "Trimに成功したので検査をスキップ"
        Exit Sub
    End If

    'この行以下は実行されない
    Debug.Print "Trimに成功しなかったので、以下でさらに検査" 
    Debug.Print tiku; Len(tiku)
    
    nazo = Right(tiku, 1)
     
    Debug.Print nazo
    Debug.Print nazo = " "
    Debug.Print nazo = " "
    Debug.Print Asc(nazo)

    'Byte型配列に入れて、謎のスペースの正体を調査
    naz = Right(tiku, 1)
    Debug.Print "謎の半角スペース"
    Debug.Print naz(0)
    Debug.Print naz(1)

    hankakuSP = " "
    Debug.Print "普通の半角スペース"
    Debug.Print hankakuSP(0)
    Debug.Print hankakuSP(1)


    'Byte型配列で調べた時に文字コード160ではなかったので
    'HTMLでよく利用される、NBSP(ノーブレークスペース)では
    'ないようでしたが、念の為、NBSPを普通の半角スペースに置き換えてから
    'Trimした所、スペースが除去できました。
     
    Ntiku = Trim(Replace(tiku, Chr(160), " "))
     
    If Ntiku = "北海道" Then
        Debug.Print "TRUE"
    Else
        Debug.Print "FALSE"
    End If
End Sub


12763 : たかちゃんさんのコメント (2021-01-05 11:10:47)

小川先生、田中さん:

とても勉強になりました、ありがとうございます!
なんとか解決しました。(^^) ノーブレイクスペースが原因のようです。

何故かTRIM関数で、解決せず。。。1文字づつ確認すると、明らかに最後に半角スペースがあり文字数も1文字多い状況。
しかも、謎の半角スペースは、普通の半角スペースと文字コード(32)も同じでした。

ダメ元で、ノーブレイクスペース(文字コード:160)の対策を試した所TRIM関数で謎の半角スペースを除去できました。

参考ページ:
https://thom.hateblo.jp/entry/2016/09/20/150650


'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
'Microsoft Scrintping Runtime -> Dictionaryを使用するため
Sub GetArea()
    Dim url As String
    url = "https://www.sej.co.jp/products/area.html"

    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
    
    Dim tr As MSHTML.HTMLHeadElement
    Dim spa As MSHTML.HTMLHeadElement
    Dim tiku As String
    Dim nazo As String
    Dim naz() As Byte
    Dim hankakuSP() As Byte
    Dim Ntiku As String
    
    For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
        
        nazo = Right(tiku, 1)
        
        Debug.Print nazo
        Debug.Print nazo = " "
        Debug.Print nazo = " "
        Debug.Print Asc(nazo)

        'Byte型配列に入れて、謎のスペースの正体を調査
        naz = Right(tiku, 1)
        Debug.Print "謎の半角スペース"
        Debug.Print naz(0)
        Debug.Print naz(1)

        hankakuSP = " "
        Debug.Print "普通の半角スペース"
        Debug.Print hankakuSP(0)
        Debug.Print hankakuSP(1)


        'Byte型配列で調べた時に文字コード160ではなかったので
        'HTMLでよく利用される、NBSP(ノーブレークスペース)では
        'ないようでしたが、念の為、NBSPを普通の半角スペースに置き換えてから
        'Trimした所、スペースが除去できました。
        
        Ntiku = Trim(Replace(tiku, Chr(160), " "))
        
        If Ntiku = "北海道" Then
            Debug.Print "TRUE"
        Else
            Debug.Print "FALSE"
        End If
    Next
    
End Sub
 


12762 : 小川慶一の回答 (2021-01-05 08:17:23)

追記:
「丸」と「大きな丸」とか、ホント分からないです。「MS ゴシック」で見ると、比較すればわずかに大きさが違うと気づけるくらい。
機種依存文字や絵文字の丸も含めると、判別は本当に大変です。
これらを形で判別するのは至難の業。そういうとき、Asc関数は便利です。

Sub maru_iroiro()
    Const maru_normal As String = "○" '丸
    Const maru_grande As String = "◯" '大きな丸
    Debug.Print maru_normal; Asc(maru_normal)
    Debug.Print maru_grande; Asc(maru_grande)
End Sub


出力結果:
○-32357 
◯-32260


12761 : 小川慶一の回答 (2021-01-05 08:08:13)

お二人のやりとり、僕にとってもとても勉強になります。

文字列比較の件、たとえば、If文内を以下のようにしてみます。

If tiku <> "北海道" Then
    Debug.Print tiku
    If InStr(tiku, "北海道") Then
        Debug.Print Len("北海道"); Len(tiku); Len(tiku) = Len("北海道") '最後のは、文字列長さについて比較演算をして、true/falseを出力
    End If
End If


北海道ならまだしも、#、♯、井のようなよく似た記号が混ざっていて判別できないこともあります
そういうときは、一文字ずつ比較します。
Asciiコードを出力するのも、違う記号かどうか人間が視覚的に判別しやすいので良いです。
以下は一例です。

Sub compare_strings_one_to_one()
    Dim target As String
    target = "北海道♯"
    Dim moji_from_website As String
    moji_from_website = "北海道#"
    
    If Not Len(target) = Len(moji_from_website) Then
        Debug.Print "文字列の長さ異なります。"; Len(target); Len(moji_from_website)
        Exit Sub
    End If
    
    Dim c As Long
    For c = 1 To Len(target)
        If Mid(target, c, 1) <> Mid(moji_from_website, c, 1) Then
            Debug.Print c & "文字目がおかしいです"
            Debug.Print Mid(target, c, 1) & vbTab & Asc(Mid(target, c, 1))
            Debug.Print Mid(moji_from_website, c, 1) & vbTab & Asc(Mid(moji_from_website, c, 1))
        End If
    Next
End Sub


以下は、出力結果:
4文字目がおかしいです
♯  -32270
#  -32364


12759 : 田中 宏明さんのコメント (2021-01-05 06:42:33)

たかちゃんさん:
> 何故かIf文が適用されない状況です。

余分な空白を取り除いてみたらどうなるでしょうか。

If LTrim(tiku) <> "北海道" Then
'If tiku <> "北海道" Then


12758 : たかちゃんさんのコメント (2021-01-05 04:55:19)

いつもありがとうございます。お忙しい中、すみません。一つ質問させて下さい。

以下のような作りのWebページのTableタグから、各地域のデータを取得したいと考えています。
但し、北海道は、THタグの見出しとSPANタグの件名の両方が"北海道"となっているため、
If文でTHタグの内容が"北海道"の時は、Debug.printで書き出さないと設定したのですが
何故かIf文が適用されない状況です。


HTMLの中身
<TBODY>
<TR>
 <TH>北海道 </TH>
 <TD><SPAN>北海道</SPAN> </TD>
</TR>

<TR>
 <TH>東北 </TH>
 <TD><SPAN>青森県</SPAN><WBR><SPAN>秋田県</SPAN>...</TD>
</TR>

'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
'Microsoft Scrintping Runtime -> Dictionaryを使用するため
Sub GetArea()
    Dim url As String
    url = "https://www.sej.co.jp/products/area.html"

    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
    
    Dim tr As MSHTML.HTMLHeadElement
    Dim spa As MSHTML.HTMLHeadElement
    Dim tiku As String
    
    For Each tr In oHTml.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        tiku = tr.ChildNodes(0).innerText
        'TRタグ内の0番目の子要素(THタグ)内のデータを取得
        '北海道はSpanタグ内にもあるため、ここでは北海道の時はDebug.printしないようIf文追加
        'なぜかIf文が適用されない状況です。
        If tiku <> "北海道" Then
            Debug.Print tiku
        End If
        
        'TRタグ内の1番目の子要素(TDタグ)内のSpanタグ内のデータを取得
        For Each spa In tr.ChildNodes(1).getElementsByTagName("span")
            Debug.Print spa.innerText
        Next
        
    Next
    
End Sub 


12757 : たかちゃんさんのコメント (2021-01-05 01:04:56)

田中 宏明さん:
いつもありがとうございます。
ADODB.StreamオブジェクトのCharsetプロパテの"_autodetect_all"について気になって調べてみました。("_autodetect"は、日本語用)
解読先の文字コードが、ANSIとutf-8だと、正常に判別できないらしいです。
きっとそれ以外のWebページだったら上手く動くのだと思います。(^^)
> たかちゃんさん:
>
> Charsetプロパティに"_autodetect_all"を指定し、実際に動かしてみると「文字化け」だらけの結果になりました。
> すみません。忘れてください。
>
>


12756 : 田中 宏明さんのコメント (2021-01-04 22:36:52)

たかちゃんさん:

Charsetプロパティに"_autodetect_all"を指定し、実際に動かしてみると「文字化け」だらけの結果になりました。
すみません。忘れてください。


12755 : 田中 宏明さんのコメント (2021-01-04 22:20:41)

たかちゃんさん:

なんと文字化け対策もマスターですね。
文字コードを自動的に判定する方法があるようなので、機会があれば実験してみてください。
ADODB.StreamオブジェクトのCharsetプロパティに"_autodetect_all"
を指定します。

Private Function ADODB_autodetect(ByRef xh As Object) As String
    '生の情報は文字化けの可能性があるので、ADOを用いた。
    Dim strm As  ADODB.Stream
    Set strm = New ADODB.Stream

    strm.Open
    strm.Position = 0
    strm.Type = 1 'adTypeBinary
    strm.Write xh.responseBody

    strm.Position = 0
    strm.Type = 2 'adTypeText
    strm.Charset = "_autodetect"
    ADODB_autodetect = strm.ReadText    
    strm.Close
End Function 


上記関数をメインから呼び出すための変更
 htmlDoc.body.innerHTML = ADODB_autodetect(xh)
'htmlDoc.body.innerHTML = xh.responseText


12753 : たかちゃんさんのコメント (2021-01-04 04:20:41)

課題に使う新たなデータを求めスクレイピングをした所、いつもの方法ではBodyが文字化けした為、ADODB.Streamを使用した文字化け対策に挑戦しました。以下の過去コメントを参照しコピペで作成。
備忘録として記念投稿します。
因みに、文字化けしたWebページは、文字コードが「utf-8」でした。

結局、取得したかった数字は全て画像データ?となっていたので、文字化け解消してもデータ取得は不可でした。。。

ADODB.stream使う際は、該当の文字をByte型の配列に入れて、
下にある手順で設定をすれば何とかなる所までは分かりました。(^^)
(Byte型で読み込ませて、設定後、テキスト型で出力。)

'必要なライブラリ:
'[1] Microsoft ActiveX Data Object x.x Library -> 文字コード変更のため(x.x の部分は一番大きいバージョンを選べばまず間違いなくOK)
'[2] Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため

Sub GetRequestSimple1()
    Dim url As String
    url = "ここにhttp://~のURLを記入"

    Dim xh As New WinHttp.WinHttpRequest 'HTTPリクエストを制御するクラスのインスタンスを生成
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then 'ステータスコードを調べる
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    '普通にボディを取ってくると何故か文字化けする為、ADODB.Streamで文字化け対策
    '因みに上記のWebページの文字コードはutf-8
    '1.ボディを取ってきて、Byte型の配列に入れる
    Dim get_body() As Byte
    get_body = xh.ResponseBody
    
    
    Dim msg1 As String
    Dim msg2 As String
    msg1 = get_body 'Byte()を文字列に変換(msg1 as string だから)
    MsgBox msg1
    
    
    '2.ADODB.streamで、文字化け対策
    Dim ado_stream As New ADODB.Stream
    
    ado_stream.Open
    ado_stream.Position = 0
    ado_stream.Type = 1
    ado_stream.Write get_body
    
    ado_stream.Position = 0
    ado_stream.Type = 2
    ado_stream.Charset = "utf-8"
    msg2 = ado_stream.ReadText
    ado_stream.Close
    
    MsgBox msg2
    
    Range("B2").Value = msg2
    
End Sub
 


12745 : 小川慶一の回答 (2021-01-03 10:40:08)

たかちゃんさん:

さすがです。
あとは、さらにやるなら、北から順に出力したい順に地域名が書き出されたリストを用意して、辞書のキーごとに、表の適切な箇所に出力するようにするくらいですかね。
これも、「地域名が書き出されたリスト」自体を地域名をキー、出力先の行を値とした辞書(*1)を作ってそれと照合するように書くと早いです。

その場合も、値がひとつも入らないセルが出現しないように書き出すための工夫もいくつか考えられそうです。
スマートな例のひとつは、(*1)の辞書のキーと同じキーがウェブページから拾ってきた値を元に生成した辞書のキーにあるかどうかを調べ、あった場合のみ、(*1)の元データとはまた別の出力先に書き出すという感じでしょうか。

そうなると、もはや、ウェブページ解析ではなく、連想配列の取り扱いの話ですが。


12740 : たかちゃんさんのコメント (2021-01-03 05:00:28)

田中 宏明さん:
ありがとうございます!
先生と田中さんのコードを、ウォッチ式を使って注意深く動きを確認。その後2つのコードを自分でも書いてみてから、例のおにぎりのコードも書き直してみたところ成功しました。

ウォッチ式、動きを理解するのに本当に便利です。
dicとar(Variantの配列)の2つにセットして、1つ1つ動かしながら見たら理解できました。動きを見るのが一番理解しやすいです。
いつもありがとうございます。(^^)


> こちらは連想配列の応用技登場ですね。
>
> エクセルマクロ・VBA発展編2演習と回答に記念投稿しました。
> https://online.pc5bai.com/movie/index/85/1362


12739 : 田中 宏明さんのコメント (2021-01-02 12:08:21)

たかちゃんさん:

リンクを取得するコードを整理していただき、ありがとうございます。

> もう一つのコードはこれから読み解きます。(^^)

こちらは連想配列の応用技登場ですね。

エクセルマクロ・VBA発展編2演習と回答に記念投稿しました。
https://online.pc5bai.com/movie/index/85/1362


12736 : たかちゃんさんのコメント (2021-01-02 03:48:21)

小川先生、田中さん

いつもありがとうございます! ちょっとした事でも何もかもが
本当に勉強になります。
将来、別の生徒さんが見た時に簡単に読み解けるよう
調べた事を備忘録としてコメントします。
まずは、以下について、もう一つのコードはこれから読み解きます。(^^)


【地域ごとのリンクを取ってくるコードについて】

●該当の部分、HTMLはこんな風になっている。
<div class="ac_detail">
<ul>
<li><a href="/products/a/onigiri/hokkaido/">北海道</a></li>
<li><a href="/products/a/onigiri/tohoku/">東北</a></li>
</ul>
</div>
因みに、href="/~"は、ドメインを省略するhrefの書き方。
【参考サイト】
https://allabout.co.jp/gm/gc/475758/


コードを読んでいて「何故、about:を取り除いているのだろう?」と思い
Debug.Printで調査しました。

Debug.Print HElem.outerHTMLをした所、以下のようにabout:がついていました。
ドメインを省略した書き方をしたりすると、多少見え方が変わったりするんだと納得。

<DIV class=ac_detail><UL>
<LI><A href="about:/products/a/onigiri/hokkaido/">北海道</A></LI>
</UL>
</DIV>

Debug.Print AElem.outerHTML
<A href="about:/products/a/onigiri/hokkaido/">北海道</A>

Debug.Print AElem.innerText
北海道

aタグ アンカータグの中身を取りたい時は、こう書けば良いんですですね。
Debug.Print AElem.getAttribute("href")
about:/products/a/onigiri/hokkaido/

その他参考リンク
https://excel-ubara.com/excelvba8/EXCELVBA819.html
https://www.relief.jp/docs/002097.html
https://docs.microsoft.com/ja-jp/dotnet/api/system.xml.xmlelement.hasattribute?view=net-5.0


> 地域のページURLを取得してみましたので、ご参考まで。


12734 : 小川慶一の回答 (2021-01-01 23:14:47)

田中 宏明さん:

> 短期間でここまでできるなるとは驚きで言葉が見つかりません。

すごいですよね。

辞書のItemに配列を格納することもできます。

以下のサンプルを作りました。参考にしてください。
「区切り文字を自分で考えて用意し、取り出し時にSplit関数を使う」というのも良いですが、このほうがスマートかと。

動作確認時には、B2:B11に重複した都市名、C2:C11に任意の文字列を入れて実行してみてください。

Array関数は、Variant型の配列を作る関数です。講座本編では紹介していないと思いますが、手っ取り早いのでここではあえてこれを使いました。

Sub dic_value_array_sample()
    Dim dic As New Scripting.Dictionary
    Dim i As Long, pref As String, okashi As String
    Dim ar As Variant
    For i = 2 To 11
        pref = Range("B" & i).Value
        okashi = Range("C" & i).Value
        If Not dic.Exists(pref) Then
            dic.Add pref, Array(okashi)
        Else
            ar = dic.Item(pref)
            ReDim Preserve ar(UBound(ar) + 1)
            ar(UBound(ar)) = okashi
            dic.Item(pref) = ar
        End If
    Next
    
    Dim j As Long
    Range("E1").Value = "pref"
    Range("F1").Value = "values"
    With Range("E2")
        For i = LBound(dic.Keys) To UBound(dic.Keys)
            pref = dic.Keys(i)
            ar = dic.Item(pref)
            .Offset(i, 0).Value = pref
            For j = LBound(ar) To UBound(ar)
                .Offset(i, j + 1).Value = ar(j)
            Next
        Next
    End With
End Sub


12733 : 田中 宏明さんのコメント (2021-01-01 17:13:09)

たかちゃんさん:

短期間でここまでできるなるとは驚きで言葉が見つかりません。
地域のページURLを取得してみましたので、ご参考まで。

'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
 Sub GetRequestSimple_Tanaka()
 
    Dim url As String
    url = "https://www.sej.co.jp/products/a/onigiri/"
 
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
     
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
     
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得

    Dim HElem As MSHTML.HTMLHeadElement
    Dim AElem As MSHTML.HTMLAnchorElement
    
    'URL取得
    For Each HElem In oHTml.getElementsByClassName("ac_detail")
        For Each AElem In HElem.getElementsByTagName("a")
            If AElem.hasAttribute("href") Then
                '余計な文字をMidとInStrで取り除く
                Debug.Print "https://www.sej.co.jp" & _
                Mid(AElem.getAttribute("href"), InStr(1, AElem.getAttribute("href"), "about:") + 6)
            End If
        Next AElem
    Next HElem
End Sub


12732 : たかちゃんさんのコメント (2021-01-01 00:48:12)

小川慶一さん:
販売地域をDictionaryのkeyにして、おにぎりの販売地域一覧表を作成する
コードを書いてみました。記念に投稿します。(^^)


'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
'Microsoft Scrintping Runtime -> Dictionaryを使用するため
Sub GetRequestSimple1()
    Dim dic As Scripting.Dictionary
    Set dic = CreateObject("Scripting.Dictionary")

    Dim url As String
    url = "https://www.sej.co.jp/products/a/onigiri/"

    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode &lt;> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
    
    'oH2--> 1つのおにぎり紹介のdiv(この中に、商品名や値段の情報が記載)
    'oH3-->商品名のdiv
    Dim oH2 As MSHTML.HTMLHeadElement
    Dim oH3 As MSHTML.HTMLHeadElement
    Dim tiku As String
    Dim spTiku As Variant
    Dim c As Long
    Dim idx As Long
    idx = 0
  'ーーーーーーーーーーーーーーここから上は前回と同じ。
    
    For Each oH2 In oHTml.getElementsByClassName("list_inner")
        For Each oH3 In oH2.getElementsByClassName("item_ttl")
            '商品名の書き出し
            Range("A2").Offset(idx).Value = oH3.innerText
            idx = idx + 1
            
            '販売地域の余計な文字をMidとInzStrで取り除く
            tiku = Mid(oH3.parentElement.Children(2).innerText, InStr(oH3.parentElement.Children(2).innerText, ":") + 1)
            spTiku = Split(tiku, "、")
            '販売地域をKeyにして登録。北海道 ツナ|おかか|梅干し の様にDictionaryへ格納
            For c = LBound(spTiku) To UBound(spTiku)
                If Not dic.Exists(spTiku(c)) Then
                    dic.Add spTiku(c), oH3.innerText
                Else
                    dic.Item(spTiku(c)) = dic.Item(spTiku(c)) & "|" & oH3.innerText
                End If
            Next
        Next
    Next
    
    'ディクショナリの内容を一気に書き出し。
    Dim spItem As Variant
    Dim cnt As Long
    
    For c = LBound(dic.Keys) To UBound(dic.Keys)
        '地域の項目を書き出し
        Range("B1").Offset(, c).Value = dic.Keys(c)
        
        spItem = Split(dic.Items(c), "|")
        For cnt = LBound(spItem) To UBound(spItem)
            '販売されているおにぎりの行に〇を入力
            For idx = 0 To Range("A" & Rows.Count).End(xlUp).Row - 2
                If Range("A2").Offset(idx).Value = spItem(cnt) Then
                    Range("B2").Offset(idx, c).Value = "〇"
                    Exit For
                End If
            Next
            
        Next
    Next
    
    '罫線を引く
    Range("A1").CurrentRegion.Borders.LineStyle = True
End Sub

 


> 演習としてチャレンジするなら、地域ごとに販売されている商品のリストを作るとかもおもしろいかもしれません。


12730 : 小川慶一の回答 (2020-12-31 06:22:33)

たかちゃんさん:

お二人ともすごいです (^^

演習としてチャレンジするなら、地域ごとに販売されている商品のリストを作るとかもおもしろいかもしれません。
やり方はいろいろありますが...例えば、以下の流れで。

[1] 各商品の販売地域を取得したところで、販売地域をキーとした辞書に、商品の配列を追加していく。
[2] 全商品について調べきったところで、辞書のすべてのキーと値を吐き出す。


12727 : たかちゃんさんのコメント (2020-12-30 22:57:44)

田中 宏明さん:

ありがとうございます!これは凄い。。
更に、以下を付け足したところ、販売地域も取得してきました。
Debug.Print oH3.parentElement.Children(2).innerText

参考サイトで意味も確認してきました。
【参考ページ】
https://www.vba-ie.net/element/parent-children.php#a12

まだ、各プロパティの調べ方が良く分らず。。
今回はとても勉強になりました。(^^)

> たかちゃんさん:
>
> それで、値段も取得できるよう追記してみました。いろいろな方法がありそうですが、ご参考まで。
>


12725 : 田中 宏明さんのコメント (2020-12-30 12:03:34)

たかちゃんさん:

Web連携にチャレンジされているのですね。
コピペで動きました。すごいですね。

それで、値段も取得できるよう追記してみました。いろいろな方法がありそうですが、ご参考まで。

Sub GetRequestSimple1_Tanaka()
    Dim url As String
    url = "https://www.sej.co.jp/products/a/onigiri/"

    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
    
    'oH2--> 1つのおにぎり紹介のdiv(この中に、商品名や値段の情報が記載)
    'oH3-->商品名のdiv
    Dim oH2 As MSHTML.HTMLHeadElement
    Dim oH3 As MSHTML.HTMLHeadElement
    For Each oH2 In oHTml.getElementsByClassName("list_inner")
        For Each oH3 In oH2.getElementsByClassName("item_ttl")
            '商品名(おにぎり名)を書き出し
            Debug.Print oH3.innerText & vbTab;
            '値段を書き出し by Tanaka
            Debug.Print oH3.parentElement.Children(1).innerText
        Next
    Next
End Sub 


> セブンイレブンのおにぎり紹介ページより、おにぎりの名前を取得することに成功しました。
>…
>動いた時は本当に嬉しかったです。(^^)


12724 : たかちゃんさんのコメント (2020-12-30 05:21:56)

セブンイレブンのおにぎり紹介ページより、おにぎりの名前を取得することに成功しました。

企業のWebページの作りは複雑すぎて、ブラウザからHTMLを確認した時は、もう読めないと思いました。(T_T)
しかし、一度Bodyの部分を、このコースで使っているマクロを使ってExcelに取り込んで、更にメモ帳にはりつけて
全体を眺めたら、商品名を発見し、このページに関してはなんとかその部分だけは仕組みが分かったかなという感じです。
例題のプログラムを再利用して、ちょこっと書き直しただけですが、、動いた時は本当に嬉しかったです。(^^)

HTMLの中身はこんな感じ。
<div class=""list-inner-~~~"">
<figure> 写真
<div class=""detail"">
<div class=""item_ttl"">  商品のおにぎりの名前
<div class=""item_price"">  価格
<div class=""item_region""> 販売地域

'以下に紹介するライブラリの参照設定をしてください
'Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'Microsoft HTML Object Library -> コンテンツのDOMを解析するため
Sub GetRequestSimple1()
    Dim url As String
    url = "https://www.sej.co.jp/products/a/onigiri/"

    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    'htmlをDOMとして取得する。そのための変数を宣言。
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得
    
    'oH2--> 1つのおにぎり紹介のdiv(この中に、商品名や値段の情報が記載)
    'oH3-->商品名のdiv
    Dim oH2 As MSHTML.HTMLHeadElement
    Dim oH3 As MSHTML.HTMLHeadElement
    For Each oH2 In oHTml.getElementsByClassName("list_inner")
        For Each oH3 In oH2.getElementsByClassName("item_ttl")
            Debug.Print oH3.innerText '商品名(おにぎり名)を書き出し
        Next
    Next
End Sub
 


12008 : 小川慶一の回答 (2020-05-02 02:26:02)

受講生 さん:

無事解決したようで良かったです。
複数の手順や機能組み合わせになっているものについては、なるべくそれぞれ分離して取り扱える状態にするのが理解のコツです。

今回僕が示したプロシージャ分割の粒度も参考にしてください。


ひきつづき、よい学びを (^^




> 小川慶一さん:
>
> お世話になっております。
>
> > 「DOMとしてレスポンスを取得」はしていません。
> > 以下の[1]→[2]の手順で仕事が進みます。そして、[2]より以前に、[1]の段階で文字化けしています。
> >
> > [1] レスポンスを取得する
> > [2] レスポンスのDOMを解析する
>
> 以上を意識して再度挑戦しまして、どうにか解消できました。
> 関連する箇所のコードを以下のようにしました。
>
> ' sBody = xh.ResponseText' ←とにかくこれだと文字化け
> sBody = StrConv(xh.ResponseBody, vbUnicode) 'ここを変更した
>
>  Dim oHTml As New MSHTML.HTMLDocument
> oHTml.body.innerHTML = sBody '←文字化け解消後のsBodyを左辺に格納
>
> > 各行で行っている作業に対して、日本語でご自身でコメントをつけてみてください。
>
> これも今後行っていこうと思います。
> ありがとうございました。


12006 : 受講生さんのコメント (2020-05-01 14:42:59)

小川慶一さん:

お世話になっております。

> 「DOMとしてレスポンスを取得」はしていません。
> 以下の[1]→[2]の手順で仕事が進みます。そして、[2]より以前に、[1]の段階で文字化けしています。
>
> [1] レスポンスを取得する
> [2] レスポンスのDOMを解析する

以上を意識して再度挑戦しまして、どうにか解消できました。
関連する箇所のコードを以下のようにしました。

' sBody = xh.ResponseText' ←とにかくこれだと文字化け
sBody = StrConv(xh.ResponseBody, vbUnicode) 'ここを変更した

 Dim oHTml As New MSHTML.HTMLDocument
oHTml.body.innerHTML = sBody '←文字化け解消後のsBodyを左辺に格納

> 各行で行っている作業に対して、日本語でご自身でコメントをつけてみてください。

これも今後行っていこうと思います。
ありがとうございました。


11997 : 小川慶一の回答 (2020-04-30 12:22:14)

受講生 さん:

こんにちは。

> > 対処法のひとつは、StrConv関数を実行する対象を変更することです。
> こちらに関しては、自分なりにいろいろ試しましたが、解消しませんでしたが、

解消しませんでしたか...。
念のため書きますが、以下のとおり、 GetRequestSimple1_revised でのStrConvの対象は、responseBodyのほうです。それでもダメでしたでしょうか。(僕の環境ではうまくいきます)

'    sBody = xh.ResponseText
    sBody = StrConv(xh.responseBody, vbUnicode) 'ここを変更した


「Web連携」の「基礎」の講座ですので。
お伝えできる内容には限界があります。

今回紹介したスクリプトのようなものを自力でなんとか作れるようになるには、前のコメントでも書きましたが、それなりに事前知識が必要です。
(あと、試行錯誤をいとわないで済むだけのPC操作スキルも)

> 今回DOMとしてレスポンスを取得(1)しようとして、文字化けの問題に遭遇しました。

「DOMとしてレスポンスを取得」はしていません。
以下の[1]→[2]の手順で仕事が進みます。そして、[2]より以前に、[1]の段階で文字化けしています。

[1] レスポンスを取得する
[2] レスポンスのDOMを解析する

各行で行っている作業に対して、日本語でご自身でコメントをつけてみてください。
全体の流れを頭の中で理解するのに良いかと思います。
あと、前回投稿の2つ目で示したモジュールのように、機能ごとに複数のプロシージャに分割してみるとかもよい学びになります。


11994 : 受講生さんのコメント (2020-04-29 10:09:05)

小川慶一さん:

お世話になっております。
講義内容を超えるご回答に大変恐縮しておりますと同時に大変感謝しております。

> 受講生 さん:
> 'ADODB.Stream オブジェクトを使って文字化けを解消する

教えていただいたというか、わざわざ作ってくださったマクロで見事に
文字化けせず、DOMとしてHTMLボディを取得できました。理解するのはだいぶ先になりそうですが、とにかく実装して利用させていただきます。


> 対処法のひとつは、StrConv関数を実行する対象を変更することです。

こちらに関しては、自分なりにいろいろ試しましたが、解消しませんでしたが、もしこちらで解消するなら'ADODB.Stream オブジェクトを
利用するよりも自分では理解しやすいですし、コードも単純になりそうですので、マクロ全体の理解が深まったところで、もう一度チャレンジしたいと思います。今回は、いただいたマクロで解決しましたので、チャレンジはしばらく後になりそうですが。

最後に確認のための質問です。
今回DOMとしてレスポンスを取得(1)しようとして、文字化けの問題に遭遇しました。DOMを使わずに取得したHTMLコンテンツ(2)の場合は、文字化けの問題があったとしてもStrConv関数でなんとかなりました。ということは、DOMを使った場合(1)と、使わない場合(2)で、大きな違いがあるということでしょうか。とすれば、何が違うのか。ご指導いただけますと幸いです。


11991 : 小川慶一の回答 (2020-04-28 23:29:03)

受講生 さん:

がんばってますね。

対処法のひとつは、StrConv関数を実行する対象を変更することです。
以下を参考にしてください。

Sub GetRequestSimple1_revised()
    Dim url As String
    url = "http://www.exvba.com/ws/dombasic_shift_jis.html"

    Dim xh As New WinHttp.WinHttpRequest 'HTTPリクエストを制御するクラスのインスタンスを生成
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then 'ステータスコードを調べる
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    
    Dim sHead As String
    Dim sBody As String
    sHead = xh.GetAllResponseHeaders
'    sBody = xh.ResponseText
    sBody = StrConv(xh.responseBody, vbUnicode) 'ここを変更した
    
    Worksheets("response").Range("B1").Value = sHead
    Worksheets("response").Range("B2").Value = sBody
    
    Debug.Print xh.GetResponseHeader("Content-Length")
End Sub


使いこなすために必要な知識が高度(発展編2レベル+外部連携レベル+さらにα)なので講座では紹介していませんが、ADODB.Stream のインスタンスを使って文字コードを変更して出力することもできます。
これだと、種々の文字コードに対して対応できます。

以下はサンプルです。
冗長だとかえって分かりにくいので、受講生さんの現状のスキルで全体を追えるかということは考えず、サンプルコードでは構造化にあまり遠慮をしていません。追いかけるのは大変かもしれませんが、まずは読み込んで動作確認してみて、としてみてください。

上で示したような小手先の方法では対処できないという場合は僕も ADODB.Stream を使います。
こういうコーディングは日常的にやるようなことではないので、細かいオプションの指定については僕も脳内には入れていません。僕が書く場合も、調べ物をしつつ、試行錯誤しつつ、(あるいは、過去に自分が書いたコードを参考にしつつ)という感じです。

Option Explicit

'概要:
'ADODB.Stream オブジェクトを使って文字化けを解消する

'必要なライブラリ:
'[1] Microsoft ActiveX Data Object x.x Library -> 文字コード変更のため(x.x の部分は一番大きいバージョンを選べばまず間違いなくOK)
'[2] Microsoft WinHTTP Services, version 5.1 -> HTTPリクエストをするため
'[3] Microsoft HTML Object Library -> コンテンツのDOMを解析するため

'以下の2つは、UTF8エンコードされたページ、Shift_JISエンコードされたページ
'後者は、このデモスクリプトの参照先として新たに作りました。ただし、ブラウザで見ると、文字化けするものと思います。
Const S_UTF8_URL As String = "http://www.exvba.com/ws/dombasic.html"
Const S_SHIFTJIS_URL As String = "http://www.exvba.com/ws/dombasic_shift_jis.html"

'まずは、以下の2つのプロシージャで感触を確かめてください。
Public Sub get_utf8_content()
    'utf8エンコードされたコンテンツを取得し、エクセルシートに出力してみます
    Dim url As String
    Dim response_body() As Byte '型に注意! Byte型の配列です。
    response_body = get_body(S_UTF8_URL)
    
    'responseBody の文字コードを utf-8 とみなして処理し、最終的に出力します
    change_and_message "A", response_body, "utf-8" '明示的に変換後の文字コードを指定する場合。"utf-8"は一例。候補たる文字列は、レジストリの HKEY_CLASSES_ROOT\MIME\Database\Charset を参照のこと。
End Sub
Public Sub get_shift_jis_content()
    'shift_jisエンコードされたコンテンツを取得し、エクセルシートに出力してみます
    Dim url As String
    Dim response_body() As Byte '型に注意! Byte型の配列です。
    response_body = get_body(S_SHIFTJIS_URL)
    
    'responseBody の文字コードを 自動判別して処理し、最終的に出力します
    change_and_message "B", response_body, "_autodetect" '文字コードを自動判別する場合
End Sub
Private Function get_body(url) As Byte() '型に注意! Byte型の配列です。
    Dim xh As New WinHttp.WinHttpRequest
    xh.Open "GET", url, False
    xh.send
    
    Dim sCode As String
    sCode = xh.Status
    If sCode <> 200 Then
        MsgBox "リクエストに失敗しました" & vbNewLine & sCode
    End If
    get_body = xh.responseBody
End Function
Private Function change_and_message(data_column As String, response_body() As Byte, char_set As String) As String
    Dim msg1 As String, msg2 As String 'msgboxでの途中経過出力用
    
    msg1 = response_body 'Byte()を文字列に変換(msg1 as string だから)
    MsgBox msg1
    
    'Microsoft ActiveX Data Object x.x Library を使います
    'すごく乱暴に書くと、以下の流れ:
    'ADODB.Stream型のインスタンスについて
    '   Openする
    '   入力するデータにかかる設定をする
    '   データを流し込む
    '   出力するデータにかかる設定をする
    '   データを出力する
    '   Closeする
    Dim ado_stream As New ADODB.Stream
    ado_stream.Open 'Openする
    ado_stream.Position = 0 'すごく乱暴に書くとおまじない
    ado_stream.Type = 1 '受け取るデータの型を指定。 1:adTypeBinary(バイト型) 2:adTypetext(テキスト型)
    ado_stream.Write response_body 'データを流し込む
    
    ado_stream.Position = 0 'すごく乱暴に書くとおまじない。ときどき0でないことも。文字コードの話は深いのでこれ以上今は書けません。
    ado_stream.Type = 2 '出力するデータの型を指定。 2:adTypetext(テキスト型)
    ado_stream.charset = char_set '"_autodetect" とか "utf-8" とかを指定する部分。何が入るかはケースバイケース。
    
    msg2 = ado_stream.ReadText 'データを出力する
    ado_stream.Close 'Closeする
    
    MsgBox msg2
    
    Range(data_column & 1).Value = msg2
End Function

'ということで、本丸。shift_jisのウェブページを取得して解析してみる
Public Sub analyze_shift_jis_content()
    Dim url As String
    Dim response_body() As Byte '型に注意! Byte型の配列です。
    Dim new_response_body As String
    response_body = get_body(S_SHIFTJIS_URL)
    new_response_body = change_encode(response_body, "_autodetect")
    analyze_response_body new_response_body
End Sub
Private Function change_encode(response_body() As Byte, char_set As String) As String
    Dim result_text As String
    Dim ado_stream As New ADODB.Stream
    ado_stream.Open
    ado_stream.Position = 0
    ado_stream.Type = adTypeBinary
    ado_stream.Write response_body
    
    ado_stream.Position = 0
    ado_stream.Type = adTypeText
    ado_stream.charset = char_set
    
    result_text = ado_stream.ReadText
    ado_stream.Close
    
    change_encode = result_text
End Function
Private Sub analyze_response_body(new_response_body As String)
    Dim oHTml As New MSHTML.HTMLDocument
    oHTml.body.innerHTML = new_response_body

    '所定のIDの要素を取得します
    Dim oH1 As MSHTML.HTMLHeadElement
    Set oH1 = oHTml.getElementById("h1_01")
    Debug.Print oH1.outerHTML
    Debug.Print oH1.innerHTML
    Debug.Print oH1.innerText
    
    '所定の要素の次の要素を取得します
    Debug.Print oH1.NextSibling.outerHTML
    Debug.Print oH1.NextSibling.innerHTML
    Debug.Print oH1.NextSibling.innerText
    
    'HTMLBody全体を取得します
    Dim oH As MSHTML.HTMLBody
    Set oH = oHTml.getElementsByTagName("body")(0)
    Debug.Print oH.outerHTML
    Debug.Print oH.innerHTML
    Debug.Print oH.innerText
    
    'HtmlBodyの子要素のうち4番目のものを取得します
    Debug.Print oH.ChildNodes(3).outerHTML
    Debug.Print oH.ChildNodes(3).innerHTML
    Debug.Print oH.ChildNodes(3).innerText
    
    'H2タグのついた要素すべてを順番に調べます
    Dim oH2 As MSHTML.HTMLHeadElement
    For Each oH2 In oHTml.getElementsByTagName("h2")
        Debug.Print oH2.outerHTML
        Debug.Print oH2.innerHTML
        Debug.Print oH2.innerText
    Next
End Sub



> 小川さん
>
> お世話になっております。
> 本日は少し長いですが、よろしくお願いいたします。
> DOMとして取得したレスポンスボディの文字化けに関する質問です。
>
> 以下のコードは本講座のエクセルテキストの01_WinHttp_基本の中にあるm01010_getモジュールのGetRequestSimple1()サブプロシージャです。


11988 : 受講生さんのコメント (2020-04-28 10:13:22)

小川さん

お世話になっております。
本日は少し長いですが、よろしくお願いいたします。
DOMとして取得したレスポンスボディの文字化けに関する質問です。

以下のコードは本講座のエクセルテキストの01_WinHttp_基本の中にあるm01010_getモジュールのGetRequestSimple1()サブプロシージャです。

Sub GetRequestSimple1()
Dim url As String
url = "http://www.exvba.com/ws/dombasic.html";

Dim xh As New WinHttp.WinHttpRequest 'HTTPリクエストを制御するクラスのインスタンスを生成
xh.Open "GET", url, False
xh.send

Dim sCode As String
sCode = xh.Status
If sCode <> 200 Then 'ステータスコードを調べる
MsgBox "リクエストに失敗しました" & vbNewLine & sCode
End If

'まずは、レスポンスヘッダー、レスポンスボディをざっくり取得してみよう
Dim sHead As String
Dim sBody As String
sHead = xh.GetAllResponseHeaders
sBody = xh.ResponseText

Worksheets("response").Range("B1").Value = sHead
Worksheets("response").Range("B2").Value = sBody

'レスポンスヘッダーの所定の項目を取得したいときは以下の要領
Debug.Print xh.GetResponseHeader("Content-Length")
End Sub

当然問題なく動いてレスポンスヘッダ、ボディともにちゃんと取れます。
しかし、対象のurlをShift_JISで記載されているページにしたら、とれてきたレスポンスボディの日本語部分が文字化けしていました。
そこで自分なりに調べて、
sBody = xh.ResponseText の部分を
→ sBody = StrConv(xh.ResponseBody, vbUnicode)  に変更したら
文字化けが解消しました。

ここまでだったらよかったのですが、次に、本講義テキストの02_WinHttp_DOM解析ファイルのm02010_get_DOMモジュールの
GetRequestSimple1()プロシージャを使って、上記と同じようにurlを
Shift_Jisで記載されているページにしたら、取得したレスポンスはやはり文字化けします。
しかし、こちらは自力では解決できませんでした。上記で解決したコードも試しましたが、よけい変な文字になってしまいました。
たとえば以下のようにしてみました。

本講義のテキストのコード
Sub GetRequestSimple1()
Dim url As String
url = "http://www.exvba.com/ws/dombasic.html";

Dim xh As New WinHttp.WinHttpRequest
xh.Open "GET", url, False
xh.send

Dim sCode As String
sCode = xh.Status
If sCode <> 200 Then
MsgBox "リクエストに失敗しました" & vbNewLine & sCode
End If

'htmlをDOMとして取得する。そのための変数を宣言。
Dim oHTml As New MSHTML.HTMLDocument
oHTml.body.innerHTML = xh.ResponseText 'htmlボディーをDOMとして取得

'所定のIDの要素を取得します
Dim oH1 As MSHTML.HTMLHeadElement
Set oH1 = oHTml.getElementById("h1_01")
Debug.Print oH1.outerHTML
Debug.Print oH1.innerHTML
Debug.Print oH1.innerText

'所定の要素の次の要素を取得します
Debug.Print oH1.NextSibling.outerHTML
Debug.Print oH1.NextSibling.innerHTML
Debug.Print oH1.NextSibling.innerText

'HTMLBody全体を取得します
Dim oH As MSHTML.HTMLBody
Set oH = oHTml.getElementsByTagName("body")(0)
Debug.Print oH.outerHTML
Debug.Print oH.innerHTML
Debug.Print oH.innerText

'HtmlBodyの子要素のうち4番目のものを取得します
Debug.Print oH.ChildNodes(3).outerHTML
Debug.Print oH.ChildNodes(3).innerHTML
Debug.Print oH.ChildNodes(3).innerText

'H2タグのついた要素すべてを順番に調べます
Dim oH2 As MSHTML.HTMLHeadElement
For Each oH2 In oHTml.getElementsByTagName("h2")
Debug.Print oH2.outerHTML
Debug.Print oH2.innerHTML
Debug.Print oH2.innerText
Next
End Sub

上記テキストコードの中で以下の部分を
'HTMLBody全体を取得します
Dim oH As MSHTML.HTMLBody
Set oH = oHTml.getElementsByTagName("body")(0)
Debug.Print oH.outerHTML

変更後
'HTMLBody全体を取得します
Dim oH As MSHTML.HTMLBody
Set oH = oHTml.getElementsByTagName("body")(0)
Debug.Print StrConv(oH.outerHTML, vbUnicode)

としましたが、余計、文字化けがひどくなってしまった例です。

根本的なところが分かっていないと思いますが、ご指導いただけますと幸いです。
よろしくお願いいたします。


3日がかりのその仕事、3分で終わらせる方法教えます。ガラパゴスタディーオンライン講座 ユーザー登録

本講座の動画一覧

  1. 【動画1】 エクセルマクロVBA「Web連携」講座の概要
    【動画1】 エクセルマクロVBA「Web連携」講座の概要 未習得
  2. 【動画2】 エクセルマクロVBA「Web連携」サーバとクライアント
    【動画2】 エクセルマクロVBA「Web連携」サーバとクライアント 未習得
  3. 【動画3】 エクセルマクロVBA「Web連携」ApacheとCGI
    【動画3】 エクセルマクロVBA「Web連携」ApacheとCGI 未習得
  4. 【動画4】 エクセルマクロVBA「Web連携」セッションとポート
    【動画4】 エクセルマクロVBA「Web連携」セッションとポート 未習得
  5. 【動画5】 エクセルマクロVBA「Web連携」クライアントとは
    【動画5】 エクセルマクロVBA「Web連携」クライアントとは 未習得
  6. 【動画6】 エクセルマクロVBA「Web連携」リクエストとレスポンスとは
    【動画6】 エクセルマクロVBA「Web連携」リクエストとレスポンスとは 未習得
  7. 【動画7】 エクセルマクロVBA「Web連携」GETリクエスト
    【動画7】 エクセルマクロVBA「Web連携」GETリクエスト 未習得
  8. 【動画8】 エクセルマクロVBA「Web連携」POSTリクエスト
    【動画8】 エクセルマクロVBA「Web連携」POSTリクエスト 未習得
  9. 【動画9】 エクセルマクロVBA「Web連携」Cookieを使ったリクエスト
    【動画9】 エクセルマクロVBA「Web連携」Cookieを使ったリクエスト 未習得
  10. 【動画10】 エクセルマクロVBA「Web連携」HTMLコンテンツの取得と解析_概要
    【動画10】 エクセルマクロVBA「Web連携」HTMLコンテンツの取得と解析_概要 未習得
  11. 【動画11】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_GETリクエスト
    【動画11】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_GETリクエスト 未習得
  12. 【動画12】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_POSTリクエスト
    【動画12】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_POSTリクエスト 未習得
  13. 【動画13】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_Cookie
    【動画13】 エクセルマクロVBA「Web連携」Microsoft WinHTTP Services 5.1_Cookie 未習得
  14. 【動画14】 エクセルマクロVBA「Web連携」DOM(Document Object Model)を使った解析_概要
    【動画14】 エクセルマクロVBA「Web連携」DOM(Document Object Model)を使った解析_概要 未習得
  15. 【動画15】 エクセルマクロVBA「Web連携」DOMを使った解析_基礎
    【動画15】 エクセルマクロVBA「Web連携」DOMを使った解析_基礎 未習得
  16. 【動画16】 エクセルマクロVBA「Web連携」DOMを使ったサンプル
    【動画16】 エクセルマクロVBA「Web連携」DOMを使ったサンプル 未習得
  17. 【動画17】 エクセルマクロVBA「Web連携」DOM活用のテクニック
    【動画17】 エクセルマクロVBA「Web連携」DOM活用のテクニック 未習得
  18. 【動画18】 エクセルマクロVBA「Web連携」DOMの活用例_メルマガのタイトルを取得
    【動画18】 エクセルマクロVBA「Web連携」DOMの活用例_メルマガのタイトルを取得 未習得
  19. 【動画19】 エクセルマクロVBA「Web連携」DOMの活用例_複数のメルマガ解除を自動化
    【動画19】 エクセルマクロVBA「Web連携」DOMの活用例_複数のメルマガ解除を自動化 未習得
  20. 【動画20】 エクセルマクロVBA「Web連携」Microsoft XMLを活用したコンテンツ取得
    【動画20】 エクセルマクロVBA「Web連携」Microsoft XMLを活用したコンテンツ取得 未習得
  21. 【動画21】 エクセルマクロVBA「Web連携」Microsoft XML_活用例
    【動画21】 エクセルマクロVBA「Web連携」Microsoft XML_活用例 未習得
  22. 【動画22】 エクセルマクロVBA「Web連携」Microsoft XMLとDOMの活用例
    【動画22】 エクセルマクロVBA「Web連携」Microsoft XMLとDOMの活用例 未習得
  23. 【動画23】 エクセルマクロVBA「Web連携」Microsoft Internet ControlsならではのWebコンテンツの取得
    【動画23】 エクセルマクロVBA「Web連携」Microsoft Internet ControlsならではのWebコンテンツの取得 未習得
  24. 【動画24】 エクセルマクロVBA「Web連携」Microsoft Internet Controls_Webコンテンツの取得
    【動画24】 エクセルマクロVBA「Web連携」Microsoft Internet Controls_Webコンテンツの取得 未習得
  25. 【動画25】 エクセルマクロVBA「Web連携」DOMを使ってXMLを解析
    【動画25】 エクセルマクロVBA「Web連携」DOMを使ってXMLを解析 未習得
  26. 【動画26】 エクセルマクロVBA「Web連携」Web連携のよくある問題
    【動画26】 エクセルマクロVBA「Web連携」Web連携のよくある問題 未習得
  27. 【動画27】 エクセルマクロVBA「Web連携」総括
    【動画27】 エクセルマクロVBA「Web連携」総括 未習得
  28. 【動画28】 AJAX通信の解析1: 背景、対応、流れの簡単な説明
    【動画28】 AJAX通信の解析1: 背景、対応、流れの簡単な説明 未習得
  29. 【動画29】 AJAX通信の解析2: 流れと事例の詳細
    【動画29】 AJAX通信の解析2: 流れと事例の詳細 未習得
  30. 【動画30】 クッキーを取得する方法
    【動画30】 クッキーを取得する方法 未習得
  31. 【動画31】 セッションの解析と実装-イントロダクション
    【動画31】 セッションの解析と実装-イントロダクション 未習得
  32. 【動画32】 「セッション」とは?その目的と、ウェブページでの事例
    【動画32】 「セッション」とは?その目的と、ウェブページでの事例 未習得
  33. 【動画33】 セッション解析と実装の落とし穴
    【動画33】  セッション解析と実装の落とし穴 未習得
  34. 【動画34】 セッション解析と実装のサンプルデータ解説
    【動画34】 セッション解析と実装のサンプルデータ解説 未習得

塾長 小川慶一

メニュー

コメント紹介

もっと見る

ページの先頭へ