回答編集履歴

1

コメントを大量に付与&一部コード修正

2015/04/19 16:26

投稿

htsign
htsign

スコア870

test CHANGED
@@ -2,14 +2,30 @@
2
2
 
3
3
  ```lang-vbscript
4
4
 
5
+ 'Option Explicitは宣言されていない変数を認めないようにするための特殊な宣言です。
6
+
7
+ 'これがないといきなり新しい変数を作ることができるようになるため、手軽な反面ミスタイプに気づきにくくなります。
8
+
5
9
  Option Explicit
6
10
 
7
11
 
8
12
 
13
+ 'ここが起点になります。
14
+
9
15
  Private Sub Main()
10
16
 
11
17
  Dim cell As Range
12
18
 
19
+ 'Selection とは選択範囲を表す特殊なオブジェクトです。
20
+
21
+ 'このオブジェクトはセルを選択していればRangeオブジェクトになるし、
22
+
23
+ '画像を選択していればShapeオブジェクトになるなど、実行時まで型が判別できません。
24
+
25
+ 'For Each ~ Nextは範囲を持ったオブジェクト(配列や連想配列など)をすべて舐めるための構文です。
26
+
27
+ 'Excel VBAにおいてはRangeオブジェクトにも使えるため、このようにしています。
28
+
13
29
  For Each cell In Selection
14
30
 
15
31
  Call GoogleSearch(cell)
@@ -20,62 +36,92 @@
20
36
 
21
37
 
22
38
 
39
+ 'Google画像検索して貼り付けるまでの一連の流れを取りまとめるためのプロシージャです。
40
+
23
41
  Private Sub GoogleSearch(ByRef cell As Range)
24
42
 
25
43
  Dim query As String
26
44
 
45
+ 'セルに含まれる値を取り出し、文字列型にします。数字や時刻であっても文字列になります。
46
+
27
47
  query = CStr(cell.Value2)
28
48
 
29
49
 
30
50
 
31
51
  Dim html As String
32
52
 
53
+ '指定のURLにアクセスして、サーバから返ってくるHTMLをテキストで取得します。
54
+
33
55
  html = FetchHtml("https://www.google.co.jp/search?tbm=isch&q=" & query)
34
56
 
35
57
 
36
58
 
37
59
  Dim nextUrl As String
38
60
 
61
+ 'HTMLテキストを探索して、最初に見つかる画像URLを取り出します。
62
+
39
63
  nextUrl = FindFirstUrlFromGoogleImageSearch(html)
40
64
 
41
65
 
42
66
 
67
+ '上で得た画像URLにアクセスし、ファイルをダウンロードして一時フォルダに保存します。
68
+
43
69
  DownloadFileToTempDir nextUrl
44
70
 
45
71
 
46
72
 
73
+ '一時フォルダに保存された画像をシートに貼り付けます。
74
+
47
75
  AddPicture cell
48
76
 
49
77
  End Sub
50
78
 
51
79
 
52
80
 
81
+ '変数[url]にアクセスしてHTMLをテキストで返します。
82
+
53
83
  Private Function FetchHtml(ByVal url As String) As String
54
84
 
85
+ 'JavaScriptではXMLHttpRequestと呼ばれるオブジェクトです。
86
+
55
87
  Dim xhr As Object
56
88
 
57
89
  Set xhr = CreateObject("MSXML2.XMLHTTP")
58
90
 
59
91
 
60
92
 
93
+ 'GETリクエストを非同期で要求するよう接続をオープンします。
94
+
61
95
  xhr.Open "GET", url, True
62
96
 
97
+ '要求を送信します。
98
+
63
99
  xhr.send
64
100
 
65
101
 
66
102
 
103
+ 'Do (While|Until) ~ Loopは与えられた条件が成り立っている間、あるいは成り立つまで繰り返します。
104
+
67
105
  Do Until xhr.readyState = 4
68
106
 
107
+ 'DoEventsはウィンドウメッセージを処理させる命令です。
108
+
109
+ '待機中、画面が応答なしになるのを防ぐ、くらいに思っておけばいいでしょう。
110
+
69
111
  DoEvents
70
112
 
71
113
  Loop
72
114
 
73
115
 
74
116
 
117
+ '応答結果を返り値に設定します。
118
+
75
119
  FetchHtml = xhr.responseText
76
120
 
77
121
 
78
122
 
123
+ 'オブジェクト解放
124
+
79
125
  Set xhr = Nothing
80
126
 
81
127
  End Function
@@ -86,6 +132,12 @@
86
132
 
87
133
  'ref: http://www.ka-net.org/blog/?p=4855
88
134
 
135
+
136
+
137
+ '定数宣言です。
138
+
139
+ '定数とは、変数と違って一度定義したら変えられない特殊な変数のようなものです。
140
+
89
141
  Const adTypeBinary = 1
90
142
 
91
143
  Const adSaveCreateOverWrite = 2
@@ -100,6 +152,8 @@
100
152
 
101
153
  xhr.Open "GET", url, True
102
154
 
155
+ 'HTTPヘッダを設定します。詳しくはネットワーク系の基礎を勉強してください。
156
+
103
157
  xhr.setRequestHeader "Pragma", "no-cache"
104
158
 
105
159
  xhr.setRequestHeader "Cache-Control", "no-cache"
@@ -118,74 +172,128 @@
118
172
 
119
173
 
120
174
 
175
+ 'ADODB.Streamはデータストリームを汎用的に扱うためのAPI群を提供します。
176
+
121
177
  With CreateObject("ADODB.Stream")
122
178
 
179
+ '保存するものは画像なので、扱うデータはバイナリであることを設定しています。
180
+
181
+ 'ファイルをメモ帳で開いて文字化けしていなかったら「テキスト」、それ以外はすべて「バイナリ」くらいの認識でいいです。
182
+
123
183
  .Type = adTypeBinary
124
184
 
185
+ 'ストリームをオープンします。
186
+
125
187
  .Open
126
188
 
189
+ 'ストリームにデータを書き込みます。中身はバイナリなので人間には読めません。
190
+
127
191
  .Write xhr.responseBody
128
192
 
193
+ 'ストリームの中身をファイルに出力します。
194
+
129
195
  .SaveToFile Environ("TEMP") & "\vbatemp", adSaveCreateOverWrite
130
196
 
197
+ 'ストリームを閉じます。
198
+
131
199
  .Close
132
200
 
133
201
  End With
134
202
 
203
+
204
+
205
+ 'オブジェクト解放
206
+
207
+ Set xhr = Nothing
208
+
135
209
  End Sub
136
210
 
137
211
 
138
212
 
213
+ 'HTMLテキストから最初に見つかる画像URLを返します。
214
+
139
215
  Private Function FindFirstUrlFromGoogleImageSearch(ByVal html As String) As String
140
216
 
141
217
  Dim partOfHtml As String
142
218
 
219
+ 'Long型は32bit長のビットで表せる整数です。VB.NETでのLong(こちらは64bit)とは別物です。
220
+
143
221
  Dim idx As Long
144
222
 
145
223
 
146
224
 
225
+ 'HTMLソースの何文字目に "imgurl=" という文字列が含まれるのかを idx に格納します。
226
+
147
227
  idx = InStr(html, "imgurl=")
148
228
 
229
+ 'idx + 7 番目から後の文字列を抽出します。
230
+
149
231
  partOfHtml = Mid(html, idx + 7)
150
232
 
233
+ '抽出後の文字列の何番目に "&" という文字列が含まれるのかを idx に格納します。
234
+
151
235
  idx = InStr(partOfHtml, "&")
152
236
 
153
237
 
154
238
 
239
+ '最初から idx - 1 番目までを抽出して、返り値に設定します。
240
+
155
241
  FindFirstUrlFromGoogleImageSearch = Left(partOfHtml, idx - 1)
156
242
 
157
243
  End Function
158
244
 
159
245
 
160
246
 
247
+ '与えられたRange型(セル)の右隣に、あらかじめ保存された画像を貼り付けます。
248
+
161
249
  Private Sub AddPicture(ByRef cell As Range)
162
250
 
163
251
  Dim shape As shape
164
252
 
253
+ 'ここの詳しいパラメータの機能は私もよくは知りません。
254
+
165
255
  Set shape = ActiveSheet.Shapes.AddPicture( _
166
256
 
167
257
  Filename:=Environ("TEMP") & "\vbatemp", _
168
258
 
259
+ 'Excelでの画像貼り付けには複数の方法があり、
260
+
261
+ 'ファイルへのリンクとするのかExcelファイル自体に画像を含ませるのかを選択できます。
262
+
263
+ 'ここではExcelファイルに埋め込んでいます。
264
+
169
265
  LinkToFile:=False, _
170
266
 
171
267
  SaveWithDocument:=True, _
172
268
 
269
+ 'シートのA1の左上隅を頂点として、右にどのくらいずらすのかを指定します。
270
+
173
271
  Left:=cell.Left + cell.width, _
174
272
 
273
+ 'シートのA1の左上隅を頂点として、下にどのくらいずらすのかを指定します。
274
+
175
275
  Top:=cell.Top, _
176
276
 
277
+ '貼り付ける画像の縦幅、横幅を指定します。
278
+
279
+ 'ここでは両方とも 0 に指定していますが、下でさらに別の設定をしています。
280
+
177
281
  width:=0, _
178
282
 
179
283
  height:=0)
180
284
 
181
285
 
182
286
 
287
+ '貼り付けられた画像の縦幅横幅を、画像そのものの大きさに一致するようにします。
288
+
183
289
  shape.ScaleHeight 1, msoTrue
184
290
 
185
291
  shape.ScaleWidth 1, msoTrue
186
292
 
187
293
 
188
294
 
295
+ 'オブジェクト解放
296
+
189
297
  Set shape = Nothing
190
298
 
191
299
  End Sub