Function base64(strMOJI As String) As String
Dim strWORK As String
Dim strCODE As String
Dim n As Integer, i As Integer
Dim nAMARI As Integer
Dim n6BOX(5) As Integer '6ビット取り出した数値
Dim nCODE As Integer
Dim strRET As String
strRET = "" 'リターン値を初期化する
For n = 1 To Len(strMOJI) Step 3
'3バイトを2進数に変換する、24ビットの数値を作成する
strWORK = ""
nAMARI = 0
For i = 0 To 2
strCODE = Mid(strMOJI, n + i, 1) '文字を取り出す
If strCODE = "" Then
nAMARI = 3 - i
strWORK = strWORK & "00000000"
Exit For
Else 'コードに変換する
strWORK = strWORK & HEX16toSTR2(Hex(Asc(strCODE)))
End If
Next i
Debug.Print strWORK
'8*3の24ビット2進数から6ビット単位で4つ取り出し、数値に変換する
For i = 0 To 3
n6BOX(i) = Val("&H0" & STR2toHEX16(Mid(strWORK, 1 + i * 6, 6)))
Debug.Print n6BOX(i)
Next i
'対応表にそって変換する
'6ビットデータの「0〜63」を以下の文字列に変換する。
' 0 〜25:A〜Z
' 26〜51:a〜z
' 52〜61:0〜9
' 62 :+
' 63 :/
For i = 0 To 3 - nAMARI
If n6BOX(i) = 63 Then strRET = strRET & "/"
If n6BOX(i) = 62 Then strRET = strRET & "+"
' 0 〜25:A〜Z
If 0 <= n6BOX(i) And n6BOX(i) <= 25 Then
strRET = strRET & Chr(Asc("A") + n6BOX(i) - 0)
End If
' 26〜51:a〜z
If 26 <= n6BOX(i) And n6BOX(i) <= 51 Then
strRET = strRET & Chr(Asc("a") + n6BOX(i) - 26)
End If
' 52〜61:0〜9
If 52 <= n6BOX(i) And n6BOX(i) <= 61 Then
strRET = strRET & Chr(Asc("0") + n6BOX(i) - 52)
End If
Next i
'あまりの文字分=を追加する
If nAMARI = 1 Then strRET = strRET & "="
If nAMARI = 2 Then strRET = strRET & "=="
Next n
base64 = strRET
End Function
'2進文字列を受け取り16進文字列を返す
Function STR2toHEX16(ByVal str2 As String) As String
Dim strHEX As String
Dim n As Integer 'ループカウンタ
Dim i As Integer 'ループのカウンタ
Dim n8421 As Integer '8 4 2 1の数値計算用
Dim nBYTE As Integer
'頭4文字単位かチェックする
n = Len(str2) Mod 4 '足りない文字数を計算する
If n <> 0 Then
str2 = String(4 - n, "0") & str2 '頭に文字0を追加する
End If
strHEX = "" '結果のエリアを初期化する
'文字数分ループする
For n = 1 To Len(str2) Step 4 '4文字(1バイト)単位にループを作る
n8421 = 8 '初期値に8を代入する(上から計算したいので)
nBYTE = 0 '1バイト計算用変数を初期化
For i = 0 To 3 '4回まわるよ(4ビット分)
'ビットが立っているかチェックする
If Mid(str2, n + i, 1) = "1" Then
nBYTE = nBYTE + n8421 'ビットに対応した数値を+する
End If
'次のビットを計算したいので2で割る
n8421 = n8421 / 2
Next i
'計算して、1倍との数値が完成したので16進文字にしてセットする
strHEX = strHEX & Hex(nBYTE)
Next n
'リターン値をセットして関数を抜ける
STR2toHEX16 = strHEX
End Function
'HEX16進文字列を受け取り2進文字列を返す
Function HEX16toSTR2(strHEX As String) As String
Dim n As Integer 'ループカウンタ
Dim i As Integer 'ループのカウンタ
Dim n8421 As Integer '8 4 2 1の数値計算用
Dim str2STR As String
Dim nCHK As Integer
str2STR = "" '結果のエリアを初期化する
'文字数分ループする
For n = 1 To Len(strHEX)
nCHK = CInt("&h" & Mid(strHEX, n, 1)) 'n文字目を数値変換
n8421 = 8 '初期値に8を代入する(上からチェックしたいので)
For i = 1 To 4 '4回まわるよ
If (nCHK And n8421) = 0 Then 'Andでビットをチェックする
str2STR = str2STR & "0" 'ビットは立ってないよ
Else
str2STR = str2STR & "1" 'ビットは立ってるよ
End If
'次のビットをチェックしたいので2で割る
n8421 = n8421 / 2
Next i
Next n
'リターン値をセットして終了
HEX16toSTR2 = str2STR
End Function
ポイントは、特に無いけど(工夫をしないでダラダラと作ってしまった・・・)
ASP系で使った、
2進数文字列を受け取りHEX16進文字列を返す(頭0を+する)
http://www.ken3.org/cgi-bin/test/test094-2.asp?DATA=111
と
16進数文字列を2進数文字列へ変換
http://www.ken3.org/cgi-bin/test/test094-1.asp?DATA=F2
を流用して 16進<−−>2進の文字列をやり取りしてます。
※この変換プログラムのバカな作成秘話は、
愚痴系No.197 テストデータは汚いデータで?(都合の悪いデータで)
http://www.ken3.org/guchi/backno/guchi197.html
↑を見て笑ってください・・・ダメだこりゃ・・・
今回のプログラムの説明に戻ると、
For n = 1 To Len(strMOJI) Step 3
で、3文字単位のループを作り(Step3で3文字飛ばす)
'3バイトを2進数に変換する、24ビットの数値を作成する
strWORK = ""
nAMARI = 0
For i = 0 To 2
strCODE = Mid(strMOJI, n + i, 1) '文字を取り出す
If strCODE = "" Then
nAMARI = 3 - i
strWORK = strWORK & "00000000"
Exit For
Else 'コードに変換する
strWORK = strWORK & HEX16toSTR2(Hex(Asc(strCODE)))
End If
Next i
上記で、24ビット8ビット*3の2進数文字列を作成し、
そこから、6ビット単位でデータを取り出し、再び数値に変換。
Debug.Print strWORK
'8*3の24ビット2進数から6ビット単位で4つ取り出し、数値に変換する
For i = 0 To 3
n6BOX(i) = Val("&H0" & STR2toHEX16(Mid(strWORK, 1 + i * 6, 6)))
Debug.Print n6BOX(i)
Next i
ここまでで、6ビット単位の4つの数値が完成する。
で、その数値を、対応表にしたがって、文字に直します。
'対応表にそって変換する
'6ビットデータの「0〜63」を以下の文字列に変換する。
' 0 〜25:A〜Z
' 26〜51:a〜z
' 52〜61:0〜9
' 62 :+
' 63 :/
For i = 0 To 3 - nAMARI
If n6BOX(i) = 63 Then strRET = strRET & "/"
If n6BOX(i) = 62 Then strRET = strRET & "+"
' 0 〜25:A〜Z
If 0 <= n6BOX(i) And n6BOX(i) <= 25 Then
strRET = strRET & Chr(Asc("A") + n6BOX(i) - 0)
End If
' 26〜51:a〜z
If 26 <= n6BOX(i) And n6BOX(i) <= 51 Then
strRET = strRET & Chr(Asc("a") + n6BOX(i) - 26)
End If
' 52〜61:0〜9
If 52 <= n6BOX(i) And n6BOX(i) <= 61 Then
strRET = strRET & Chr(Asc("0") + n6BOX(i) - 52)
End If
Next i
↑オイオイって感じのIf文の羅列ですがご勘弁を。
↓変換文字が余っていたら=をプラスしてます。
'あまりの文字分=を追加する
If nAMARI = 1 Then strRET = strRET & "="
If nAMARI = 2 Then strRET = strRET & "=="
Next n
と、こんな感じで、3文字単位で変換しました。
※漢字には非対応なので、2バイト文字を使う人は、一工夫してくださいね。
/*
* 4.処理を組み込む
*/
さて、BASE64の変換処理ができたので、前回のソースに組み込んでみます。
Dim strHEAD As String
'ID:passwordをBASE64変換してヘッダ情報を作成する
strHEAD = "Authorization: Basic " & base64("mailmaga:guest") & vbCrLf
として、ヘッダ情報を作ってみました。
※フト、ここにIDとパスワード書いたら丸見えですね(オイオイ)
別な問題があると思いつつ、、、
'BASE64でユーザーID:パスワードを変換して開く
Sub bbbb()
Dim objIE As Object 'IEオブジェクト参照用
'インターネットエクスプローラーのオブジェクトを作る
Set objIE = CreateObject("InternetExplorer.application")
objIE.Visible = True '見えるようにする(お約束)
'テスト用の認証ページに飛ぶ
Const strURL = "http://www.kurokiya.sake-ten.jp/zzz/"
Dim strHEAD As String
'ID:passwordをBASE64変換してヘッダ情報を作成する
strHEAD = "Authorization: Basic " & base64("mailmaga:guest") & vbCrLf
objIE.navigate2 strURL, , , , strHEAD
'表示終了まで待つ
Do While objIE.Busy = True
'何もしないループ(笑)
DoEvents
Loop
'テストでHTMLソースを取出す
Dim strhtml As String
strhtml = objIE.Document.all(0).innerHTML '変数に代入
MsgBox "ソースは" & strhtml & "です"
End Sub
Private Sub btnRUN_Click()
Dim time10 As Date
'広告作成ページに飛ぶ
Me.WebBrowser1.Navigate2 "http://books.rakuten.co.jp/afvc/afinfo/page03.html"
'2秒表示を強制的に待つ
time10 = DateAdd("s", 2, Now())
Do While True
DoEvents
If time10 < Now() Then Exit Do
Loop
'表示完了を待つ
While Me.WebBrowser1.Busy = True _
Or Me.WebBrowser1.ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend
'データをセットする
Me.WebBrowser1.Document.parts.isbn.Value = Me.txtISBN.Text
Me.WebBrowser1.Document.parts.sid.Value = Me.txtSID
Me.WebBrowser1.Document.parts.pid.Value = Me.txtPID
'JavaScriptを起動する(リンクで飛ぶように見せかけるの?)
Me.WebBrowser1.Navigate2 "JavaScript:parts('B')"
End Sub
Private Sub UserForm_Initialize()
Me.WebBrowser1.GoHome '初期ページを表示する
End Sub
Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
'新しいウインドウが開かれた時に呼ばれる。
If MsgBox("新しいウインドウを開きますか?", vbYesNo) = vbYes Then
Cancel = False 'Yesの時はキャンセルしない
Else
Cancel = True 'NOの時は新しいウインドウを開かない
End If
End Sub
Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
Cancel = True '必ず新しいウインドウを開かない
End Sub
/*
* 3.IE 新しいウインドウを作り オブジェクトを横取り
*/
開くタイミングはわかったけど、やりたいのは開かれた新規IEの管理でしょ。
作られたウインドウを自分で管理したいと思います。
※自分でオブジェクトをコントロールしたいんです。
まず、Dim WithEvents で 変数を作成します。
下記、簡単なテストプログラムです。
Dim WithEvents objNEW_IE As InternetExplorer
Private Sub UserForm_Initialize()
Me.WebBrowser1.GoHome '初期ページを表示する
End Sub
Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
Set objNEW_IE = CreateObject("InternetExplorer.Application")
Set ppDisp = objNEW_IE '作ったオブジェクトを代入
objNEW_IE.Visible = True
End Sub
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
MsgBox "あたらしく開かれたURLは" & URL
End Sub
ポイントは、まず、
Dim WithEvents objNEW_IE As InternetExplorer
と、イベントを横取りできるようなオブジェクトの入れ物を定義します。
次に、
WebBrowser1_NewWindow2
の新規ウインドウが開かれた時に発生するイベント内で、
Set objNEW_IE = CreateObject("InternetExplorer.Application")
と、
新しいIEを自分で作成し(Createして)、Dim WithEventsで定義した変数に代入します。
次に、その変数を
Set ppDisp = objNEW_IE '作ったオブジェクトを代入
に代入します。
この代入で、新しいウインドウ=作られたウインドウになります。
あとは、
objNEW_IE.Visible = True
で見えるようにしました。
テストで、
新しく開かれたウインドウの読み込み終了のイベント_DocumentCompleteで、
URLを表示させてみました。
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
MsgBox "あたらしく開かれたURLは" & URL
End Sub
Private Sub btnRUN_Click()
Dim time10 As Date
'広告作成ページに飛ぶ
Me.WebBrowser1.Navigate2 "http://books.rakuten.co.jp/afvc/afinfo/page03.html"
'2秒表示を強制的に待つ
time10 = DateAdd("s", 2, Now())
Do While True
DoEvents
If time10 < Now() Then Exit Do
Loop
'表示完了を待つ
While Me.WebBrowser1.Busy = True _
And Me.WebBrowser1.ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend
'データをセットする
Me.WebBrowser1.Document.parts.isbn.Value = Me.txtISBN.Text
Me.WebBrowser1.Document.parts.sid.Value = Me.txtSID
Me.WebBrowser1.Document.parts.pid.Value = Me.txtPID
'JavaScriptを起動する(リンクで飛ぶように見せかけるの?)
Me.WebBrowser1.Navigate2 "JavaScript:parts('B')"
End Sub
こんな感じで、IE新規ウインドウが開き、ソースの表示までいきました。
さてと、開いたウインドウから、テキストデータをGetしないとね。
新しく開いたウインドウを管理化に置きたいので、
'自分で新規のウインドウをコントロールしたいので、
Dim WithEvents objNEW_IE As InternetExplorer
とイベントを取れるオブジェクト型のグローバル変数を1つ作成します。
次に、フォームに貼った、
webのコントロールで、新しいウインドウが開かれた時に、
開くウインドウに勝手に自分で作成したオブジェクトをセットします。
'新しいウインドウを開くイベントをチェックする
Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
'新しいウインドウを自分の管理下に置きたいので、オブジェクトを代入してあげる
Set objNEW_IE = CreateObject("InternetExplorer.Application")
Set ppDisp = objNEW_IE '作ったオブジェクトを代入
objNEW_IE.Visible = True '念のため見えるようにする
End Sub
こんな感じで、WebBrowser1コントロールの_NewWindow2のイベントで、
自分で新たに作成したIEオブジェクトをグローバルに代入、
さらに、 Set ppDisp = objNEW_IE と 新しく開くウインドウにも指定します。
すると、新しく開かれたIE=自分の管理化のobjNEW_IE変数となります。
あとは、
Dim WithEvents objNEW_IE As InternetExplorer
とイベントを取れる宣言しているので、
テストで、URLとソースを表示してみました。
'新しく作成したウインドウが読み込まれたら、処理したいので、
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
MsgBox "あたらしく開かれたURLは" & URL
MsgBox "HTMLソースは" & objNEW_IE.Document.all(0).innerhtml
End Sub
Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
'新しいウインドウを自分の管理下に置きたいので、オブジェクトを代入してあげる
Set objNEW_IE = CreateObject("InternetExplorer.Application")
Set ppDisp = objNEW_IE '作ったオブジェクトを代入
objNEW_IE.Visible = True '念のため見えるようにする
End Sub
Dim WithEvents objNEW_IE As InternetExplorer
とイベントを取れる宣言しているので、
テストで、URLとソースを表示してみました。
'新しく作成したウインドウが読み込まれたら、処理したいので、
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
MsgBox "あたらしく開かれたURLは" & URL
MsgBox "HTMLソースは" & objNEW_IE.Document.all(0).innerhtml
End Sub
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
'読み込み完了を判断する
If objNEW_IE.ReadyState = READYSTATE_COMPLETE Then '読み込み完了
'テキストをセットする
Me.txtKCODE.Value = _
objNEW_IE.Document.getElementsByTagName("TEXTAREA").Item(0).InnerTEXT
End If
End Sub
Private Sub objNEW_IE_DocumentComplete(ByVal pDisp As Object, URL As Variant)
'読み込み完了を判断する
If objNEW_IE.ReadyState = READYSTATE_COMPLETE Then '読み込み完了
'テキストをセットする
Me.txtKCODE.Value = _
objNEW_IE.Document.getElementsByTagName("TEXTAREA").Item(0).InnerTEXT
'IEを閉じる
objNEW_IE.Quit
End If
End Sub