久しぶりのVBAネタ。

このブログを訪れる人はVBA関係の検索でやって来る人がほとんど。記事が実際役立っているか分からないけど、VBAの記事でもExif関連が最も多く、デジカメ画像の撮影日時を取得したいという人が多いようだ。

そして最近は「Exif GPS」という検索ワードで来る人もいて、スマホが普及したからなんでしょうね。当然私もそれも分かるように、と思っていたがなんせスマホ持っていないのでGPSを記録した写真が無くて。

で、とうとう重い腰を上げて・・・

どうでもいいことを長々と書いたら肝心なことを読んでもらえないかもしれないので唐突に。


Option Explicit

Sub wiaImage()
  Dim x As Object 'WIA.ImageFile
  Set x = CreateObject("Wia.ImageFile")
  x.LoadFile "C:\Users\test.jpg など画像ファイルのパス"

  Application.ScreenUpdating = False
  Cells.ClearContents
  Dim p As Variant
  Dim i As Integer
  On Error Resume Next
  For Each p In x.Properties
    i = i + 1
    Cells(i, 1).Value = p.propertyid
    Cells(i, 2).Value = p.Name
    If p.propertyid = 2 Or p.propertyid = 4 Then
      Cells(i, 3).Value = getGPS(p)
    Else
      Cells(i, 3).Value = p.Value
    End If
  Next
  On Error GoTo 0
  Range("1:3").EntireColumn.AutoFit
  Application.ScreenUpdating = True
 
  Set x = Nothing
End Sub

'追記 当初記事から修正しています
Function getGPS(p As Variant) As Double
  getGPS = p.Value(1) + p.Value(2) / 60 + p.Value(3) / 3600
End Function


以前記事にした「VBAで撮影日時 for Win7?」をGPS部分も取得できるように追加しただけ(なのでVista以前だと動かないかも。WIA.ImageFileって別途インストールなどできるか分からない)。

元のままだと写真にGPS情報が格納されていてもデータは表示されない。何故かと言うと(GPSの緯度経度)データは配列に入っていて単に値を教えて(p.Value)としても「え、どれのことかな?」となって答えてくれないから(エラーになるが On Error Resume Next で回避)。

VBEのローカルウインドウでデータ構造を見ると3つの要素があるようで一つ目にXX度、二つ目にXX.XX分というGPS情報が入っている模様(単位は付いていないがそれらしき数字が入っている)。三つ目はよく分からないが何も入っていないというか、とりあえずいらないと思う。
*2014/08/17 追記
ここで検証に使用した画像ファイルにはデータが3つの要素のうち2つにしか格納されておらず、2つのデータで計算していましたが、ファイルによって3つの要素にそれぞれデータが格納されている場合もありました(カメラメーカーによる仕様の違い?)。
そのため三つ目の要素も計算するように修正しました。
   → + p.Value(3) / 3600
それぞれ計算して足すだけで、条件分岐(2つの場合、3つの場合)は不要。
*追記以上

GPSデータのIDは1〜4が当てられていて、ID2と4にそれぞれ緯度、経度が格納さてれいるので値の取得を別にしている(ここでは無視していますがID1には北緯南緯、3には東経西経の区分が入っていて、南緯(S)、西経(W)の場合は値をマイナス表示するようです)。

それを度単位の10進数にそろえている(Function getGPS)。何のことかピンと来ないかもしれないが例えば滝川市役所の緯度経度は「北緯43度33分28.2秒東経141度54分37.5秒」(Wikipediaより)。

これを度数単位で10進数にそろえると「北緯43.5578333度(43+33/60+28.2/3600) 東経141.9104167度」となる(小数点以下何位までが適当か不明)。

で、グーグルマップで検索(というかアドレスバーに入力)すると
BlogPaint
滝川市役所が表示される。

算出式がコードのgetGPSと違うのはWia.ImageFileでは先ほど書いたように、「度の値」と「分の値」しかなく、この分の値にはすでに「秒の値」が含まれているから。分の値の小数点以下の値が秒を3600(60×60)で割った値になっている。

ま、この辺分かっているような書きっぷりになっているが、WIA.ImageFileで取得した値とファイルプロパティ(ファイルを右クリック)で表示される緯度経度から推測しただけなので、正しい理解ではない可能性もあります。悪しからず。

そもそもネット上に公開されていたGPSを記録した写真一枚(GPSの説明用に使われていた写真でした)で確認しただけなので、このコードが使えるものかどうか・・・


VBAで応える デジカメ撮影日時他」で取得したGPS値でGoogleマップにハイパーリンクを貼ればちょっとしたツールになるかも?って、そこまで書けばよかったかな。

何時になるか分からないが次回のVBAネタということで。
と言うか上にも書いたように検証不十分で、使えないようなら記事を削除するので教えていただけたらありがたいです。