関数:PDFからメタデータ(XMP)を抽出する

TOP > サンプル/関数 > 関数:PDFからメタデータ(XMP)を抽出する      []


概要

  

PDFファイルには文書に関する詳細な情報を明記したメタデータ(XMP)がXML形式で入っています。

それをXML形式でテキスト抽出します。

抽出したXMLから、要素名での値の抽出も行います。

  

機能

 

以下の2つの関数で連携して、機能を提供します。

A. 関数名 : Get_XML_nnn2

  1. PDFファイルをテキスト形式で読み込みます。
    PDFファイルはUTF-8 なのでコード変換して読み込みます。
  2. メタデータはPDFが更新されるたびに新しいのが後ろに追加されます。
    PDFファイルの更新日時情報と一致するメタデータのみを検索します。
    ※最適化時に古いのは削除される?
  3. メタデータはXML形式で登録されているので、要素名[x:xmpmeta]で検索します。
  4. 該当するメタデータが見つかった時に、その内容をXMLのテキストで抽出します。

B. 関数名 : Get_XML_Node_nnn2

  1. 抽出したテキストのXMLからメタデータの形式にしたがって、要素名に該当する値を抽出します。

  

制限、注意事項

  

  1. パスワード保護によりメタ情報が暗号化されているPDFファイルからは
    メタデータの抽出は出来ません
    (しかし、xpdf-utils を使えば一部のメタ情報の取得は出来ます。)
  2. PDFファイル全体をメモリ内に一括で読み込みます。 よって、20Mバイトのファイルにもなると実行中にも関わらず、停止しているかのように感じます。
    ご注意ください。
  3. メタデータのXML内容については十分に調査していないので、問題等があった場合にはコメントで頂けると助かります。
    ただし、対応出来るかの保証は全く無いです。

  

Get_XML_nnn2

 

形式

[Long] = Get_XML_nnn2 (
    string sFilePath , 
    string sGetXml ,
    string sMsg )

  

引数

  1. 第一引数 ( string sFilePath ) : In
    PDF ファイルのフルパス
  2. 第二引数 ( string sGetXml ) : Out
    取得したXML形式のメタデータ
  3. 第三引数 ( string sMsg ) : Out
    処理結果のメッセージ
    エラーメッセージも含む

 

戻り値

  • 0  : 正常処理
  • 1 以上  : エラーが発生した
    エラーの詳細は第3引数 sMsg にセットされる   

    

Get_XML_Node_nnn2

  

形式

[string] = Get_XML_Node_nnn2 (
    string sXml , 
    string sNodeName )

 

引数

  1. 第一引数 ( string sXml ) : 
    XML形式のメタデータ
  2. 第二引数 ( string sNodeName ) :
    検索する要素名

  

戻り値

  • ""以外 : 正常処理。 要素名に該当する値がセットされる。
  • ”” : 検索したノードデータが存在しない、値が無い、又はエラーが発生。

  






サンプル

  

事前に以下の参照設定を行う

サンプルのダウンロード : GetPdfMetaData_100.zip

 

Option Explicit

'x1. 取得できたPDFのOLE(IAC)情報
Private msGetInfo_Title         As String
Private msGetInfo_Author        As String
Private msGetInfo_Subject       As String
Private msGetInfo_Keywords      As String
Private msGetInfo_Creator       As String
Private msGetInfo_Producer      As String
Private msGetInfo_CreationDate  As String
Private msGetInfo_ModDate       As String
Private msGetInfo_Trapped       As String
Private msGet_GetPermanentID    As String
Private msGet_FileName          As String
Private mbGet_DeletPage         As Boolean

'x2. デバッグ・モード ★変更必須
'   True  : ログ出力有り
'  False : ログ出力無し
Const CON_DEBUG_MODE = True
'x3. 作業フォルダ ★変更必須
'   変更しないと動作しません
Const CON_WORK_FOLDER = "D:¥work"

'x4. 作業用
Private msDuegLogFilePath       As String   'LOGファイルパス
Private mlDuegLogFileNo         As Long     'LOGファイルNO
Private msDuegLogCnt            As Long     'LOGの出力数

Const CON_SELECT_NODES = "/x:xmpmeta/rdf:RDF/rdf:Description"

'**************************************************
'
' Main (Test用)
'
'**************************************************

Sub Test_Main()
    
    Dim sFilePath   As String   'PDFのフルパス
    Dim sXml        As String   '抽出されたメタデータ(XML)
    Dim lRet        As Long     '戻り値
    Dim sMsg        As String   'メッセージ
    
    sFilePath = "D:¥work¥AFormAut.pdf"
    
    '1. 前処理:メタデータの抽出
    lRet = Get_XML_nnn2(sFilePath, sXml, sMsg)
    
    '2. メタデータから該当する要素名で値を抽出
    If sXml <> "" Then
        '1.タイトル(dc:title)
        Debug.Print "タイトル(dc:title)=" & _
            Get_XML_Node_nnn2(sXml, "dc:title")
        '2.作成者(dc:creator)
        Debug.Print "作成者(dc:creator)=" & _
            Get_XML_Node_nnn2(sXml, "dc:creator")
        '3.作成者の役職(photoshop:AuthorsPosition)
        Debug.Print "作成者の役職(photoshop:AuthorsPosition)=" & _
            Get_XML_Node_nnn2(sXml, "photoshop:AuthorsPosition")
        '4.説明(dc:description)
        Debug.Print "説明(dc:description)=" & _
            Get_XML_Node_nnn2(sXml, "dc:description")
        '5.説明記入者(photoshop:CaptionWriter)
        Debug.Print "説明記入者(photoshop:CaptionWriter)=" & _
            Get_XML_Node_nnn2(sXml, "photoshop:CaptionWriter")
        '6.キーワード(pdf:Keywords)
        Debug.Print "キーワード(pdf:Keywords)=" & _
            Get_XML_Node_nnn2(sXml, "pdf:Keywords")
        '7.著作権のステータス(xmpRights:Marked)
            'False:著作権フリー
            'True:著作権取得済み
            '無い:不明
        Debug.Print "著作権のステータス(xmpRights:Marked)=" & _
            Get_XML_Node_nnn2(sXml, "xmpRights:Marked")
        '8.著作権情報(dc:rights)
        Debug.Print "著作権情報(dc:rights)=" & _
            Get_XML_Node_nnn2(sXml, "dc:rights")
        '9.著作権情報URL(xmpRights:WebStatement)
        Debug.Print "著作権情報URL(xmpRights:WebStatement)=" & _
            Get_XML_Node_nnn2(sXml, "xmpRights:WebStatement")
        '(xmp:MetadataDate)
        Debug.Print "xmp:MetadataDate=" & _
            Get_XML_Node_nnn2(sXml, "xmp:MetadataDate")
        
        'フォーマット(dc:format)
        Debug.Print "dc:format=" & Get_XML_Node_nnn2(sXml, "dc:format")
        '(xmp:CreateDate)
        Debug.Print "xmp:CreateDate=" & _
            Get_XML_Node_nnn2(sXml, "xmp:CreateDate")
        '(xmp:ModifyDate)
        Debug.Print "xmp:ModifyDate=" & _
            Get_XML_Node_nnn2(sXml, "xmp:ModifyDate")
        '(xmp:CreatorTool)
        Debug.Print "xmp:CreatorTool=" & _
            Get_XML_Node_nnn2(sXml, "xmp:CreatorTool")
        '(pdf:Producer)
        Debug.Print "pdf:Producer=" & _
            Get_XML_Node_nnn2(sXml, "pdf:Producer")
        '(xmpMM:DocumentID)
        Debug.Print "xmpMM:DocumentID=" & _
            Get_XML_Node_nnn2(sXml, "xmpMM:DocumentID")
        '(xmpMM:InstanceID)
        Debug.Print "xmpMM:InstanceID=" & _
            Get_XML_Node_nnn2(sXml, "xmpMM:InstanceID")
        '?(dc:subject)
        Debug.Print "dc:subject=" & Get_XML_Node_nnn2(sXml, "dc:subject")
        
    End If

    If lRet = 0 Then
        MsgBox "正常終了", vbInformation
    Else
        MsgBox sMsg, vbCritical, "エラー発生"
    End If
    
    'メモ帳を起動してログを表示
    If CON_DEBUG_MODE Then
        sMsg = "ログの画面を表示しますか?"
        If msDuegLogCnt > 50 Then
            sMsg = "ログ内容が沢山あります。 " & vbCrLf & sMsg
        End If
        If MsgBox(sMsg, vbInformation + vbOKCancel, "確認") = vbCancel _
            Then Exit Sub
        Dim ReturnValue
        ReturnValue = Shell("NOTEPAD.EXE " & msDuegLogFilePath, 1)
        AppActivate ReturnValue
    End If

End Sub

'**************************************************
'
' Get XML Data for PDF file
'
'   PDFファイルにXML形式で入っているメタデータ(XMP)を
'   をテキストで抽出する。
'
' Create  : 2014/12/07
' Update  : 2014/12/07
' Vertion : 1.0.0
'
' 引数1   : sFilePath As String (IN)
'           PDFファイルのフルパス
' 引数2   : sGetXml  As String (OUT)
'           取得したXML形式のメタデータ
' 引数3   : sMsg     As String (OUT)
'           エラー時の詳細なメッセージ
'
' 戻り値  : 0 は正常終了
'           1 以上はエラー有り
'
' 備考    : PDFファイルのメタデータがパスワードで
'           暗号化されている場合は取得できない。
'
' URL     : http://pdf-file.nnn2.com/?p=791
'
' その他  : 著作権等は主張しません。
'           上記URLにコメントを頂けると嬉しいです。
'
'**************************************************

Private Function Get_XML_nnn2( _
    ByVal sFilePath As String, _
    ByRef sGetXml As String, _
    ByRef sMsg As String) As Long
    
    Dim objStm          As New ADODB.Stream
    Dim objXDoc         As New MSXML2.DOMDocument
    Dim objXNode        As MSXML2.IXMLDOMNode
    
    Dim sDeugMsg        As String
    Dim sOutPdfPath     As String
    Dim lRet            As Long
    Dim bRet            As Boolean
    Dim i               As Long
    Dim j               As Long
    Dim k               As Long
    
    Dim sXml            As String
    Dim lXMLcnt         As Long
    Dim sInput          As String
    Dim sXmlPath        As String
    Dim iLineCnt        As Long
    Dim lInStr_Cnt1     As Long
    Dim lInStr_Cnt2     As Long
    Dim lIndex_S        As Long
    Dim lsInputLen      As Long
    Dim sValue          As String
    
    '取得できたXMLの要素名と値
    '   sXmlData(*, 0) : 要素名
    '   sXmlData(*, 1) : 値
    Dim sXmlData(999, 1)    As String
    
    Const CON_METADATA_START = "<x:xmpmeta "
    Const CON_METADATA_END = "</x:xmpmeta>"
    Const COM_XML_HEAD = _
        "<?xml version=""1.0"" encoding=""Shift_JIS"" ?>" & vbCrLf
    
    '初期化
    sMsg = ""
    sGetXml = ""
    Get_XML_nnn2 = 0
    
    '▼ログ・ファイルの前処理
    If CON_DEBUG_MODE Then
        msDuegLogCnt = 0
        mlDuegLogFileNo = FreeFile
        msDuegLogFilePath = CON_WORK_FOLDER & "\log-" & _
            Format(Date, "yyyymmdd-") & Format(Time, " hhmmss") & ".txt"
        sDeugMsg = "PDF-File : " & sFilePath
        Call Put_Degug_log(sDeugMsg)
    End If

    '▼事前チェック
    '作業フォルダの存在チェック
    If Dir(CON_WORK_FOLDER, vbDirectory) = "" Then
        sMsg = CON_WORK_FOLDER & vbCrLf & _
            "の作業フォルダが存在しない。" & vbCrLf & _
            "処理は中断しました。"
        Get_XML_nnn2 = 1
        GoTo Get_XML_nnn2_End:
    End If
    'PDFファイルの存在チェック
    If Dir(sFilePath) = "" Then
        sMsg = sFilePath & vbCrLf & _
            "PDFファイルが存在しない。" & vbCrLf & _
            "処理は中断しました。"
        Get_XML_nnn2 = 2
        GoTo Get_XML_nnn2_End:
    End If
    
    '▼OLEでPDF-Infoの取得
    If AcroExch_PDDoc_GetInfo(sFilePath) = False Then
        sMsg = "PDFファイルがOLEで読み込めなかった。" & vbCrLf & _
               "処理は中断しました。"
        Get_XML_nnn2 = 3
        GoTo Get_XML_nnn2_End:
    End If
    
    '▼PDFファイル内のMetaData(XML)を取得
    sXml = ""
    lXMLcnt = 0
    iLineCnt = 0
     
    With objStm
        .Type = adTypeText        '文字列型を指定
        .Charset = "UTF-8"        '文字コード
        .LineSeparator = adCRLF   '改行
        .Open                     'Streamのオープン
        .LoadFromFile (sFilePath) 'Streamへ読み込む
    End With
    
    'EOSになるまでループ ※実際は1回のみ
    Do While Not objStm.EOS
    
        sInput = objStm.ReadText(adReadAll) '一気にEOS(最後)まで読み込む
        
        iLineCnt = iLineCnt + 1
        lsInputLen = Len(sInput)
        lIndex_S = 1
        
        Do While lIndex_S < lsInputLen
            
            '開始要素と終了要素の位置を検索
            lInStr_Cnt1 = InStr(lIndex_S, sInput, CON_METADATA_START)
            If lInStr_Cnt1 = 0 Then Exit Do
            lInStr_Cnt2 = InStr(lInStr_Cnt1, sInput, CON_METADATA_END)
            If lInStr_Cnt2 = 0 Then Exit Do
                
            '開始要素、終了要素が有る
            k = lInStr_Cnt2 + Len(CON_METADATA_END) - lInStr_Cnt1
            sXml = COM_XML_HEAD & Mid$(sInput, lInStr_Cnt1, k)
            lXMLcnt = lXMLcnt + 1
            
            If CON_DEBUG_MODE Then
                Call Put_Degug_log("XML-NO:" & lXMLcnt & vbCrLf & sXml)
            End If
            
            'XMLデータのチェック
            If objXDoc.LoadXML(sXml) = False Then
                'エラー:読み込み失敗
                With objXDoc.parseError
                    sMsg = "** XML 読み込み エラー ** " & lXMLcnt & vbCrLf & _
                        .ErrorCode & " / " & Replace(.reason, vbCrLf, "") & vbCrLf & _
                        "行 :" & .Line & " , カラム :" & .linepos & vbCrLf & _
                        "内容 :" & .srcText & vbCrLf & _
                        "データ先頭からの位置 :" & .filepos
                End With
                Get_XML_nnn2 = 10
                GoTo Get_XML_nnn2_End:
            End If
            
            'ノードデータ格納の初期化
            For i = LBound(sXmlData) To UBound(sXmlData)
                For j = LBound(sXmlData, 2) To UBound(sXmlData, 2)
                    sXmlData(i, j) = ""
                Next j
            Next i
            
            'ノードデータの抽出
            i = 0
            For Each objXNode In objXDoc.SelectNodes(CON_SELECT_NODES)
                For j = 0 To objXNode.ChildNodes.Length - 1
                    If i > UBound(sXmlData) Then
                        '※発生時はsXmlData配列を大きくする
                        sMsg = "エラー発生:sXmlData配列のインデックス・オーバー"
                        Get_XML_nnn2 = 11
                        GoTo Get_XML_nnn2_End:
                    End If
                    sXmlData(i, 0) = objXNode.ChildNodes(j).nodeName
                    sXmlData(i, 1) = objXNode.ChildNodes(j).nodeTypedValue
                    i = i + 1
                Next j
            Next
            
            'ノードデータ内で指定メタデータの存在チェック
            If i = 0 Then
                If CON_DEBUG_MODE Then
                    Call Put_Degug_log("XML-NO:" & lXMLcnt & _
                        " にノードが存在しない。")
                End If
            Else
                For i = LBound(sXmlData) To UBound(sXmlData)
                    If sXmlData(i, 0) = "" Then Exit For
                    If sXmlData(i, 0) = "xap:MetadataDate" Or _
                       sXmlData(i, 0) = "xmp:MetadataDate" Then
                        sValue = sXmlData(i, 1)
                        If sValue <> "" Then
                            sValue = Mid$(sValue, 1, 4) & _
                                     Mid$(sValue, 6, 2) & _
                                     Mid$(sValue, 9, 2) & _
                                     Mid$(sValue, 12, 2) & _
                                     Mid$(sValue, 15, 2) & _
                                     Mid$(sValue, 18, 2)
                            
                            If sValue = Mid$(msGetInfo_ModDate, 3, 14) Then
                                '該当するXMLが見つかった
                                sGetXml = sXml
                                If CON_DEBUG_MODE Then _
                                    Call Put_Degug_log("Match XML-No=" & lXMLcnt)
                                Exit Do
                            End If
                            '見つからなかったので、次のXMLを検索する
                            Exit For
                        End If
                    End If
                Next i
            End If
            
            Set objXDoc = Nothing
            Set objXNode = Nothing

            '次のXMLを探す
            lIndex_S = lInStr_Cnt1 + j
        
        Loop
        
        '該当するXMLが見つかったらLoopを抜ける
        If sGetXml <> "" Then Exit Do
    Loop
        
'    Debug.Print "iLineCnt=" & iLineCnt
    
    '▼終了状態のチェック
    If lXMLcnt = 0 Then
        sMsg = "XMLデータがPDFに存在しない。" & vbCrLf & _
            "PDFのパスワード設定により" & vbCrLf & _
            "メタデータ(XMLデータ)が暗号化されている可能性が有ります。"
        Get_XML_nnn2 = 21
    ElseIf sGetXml = "" Then
        sMsg = "該当するXMLデータが検索できなかった。" & vbCrLf & _
            "上記エラー番号から関数プログラムをチェックして下さい。"
        Get_XML_nnn2 = 22
    Else
        sMsg = "正常終了:XMLデータが取得できた。"
        Get_XML_nnn2 = 0
    End If
    
Get_XML_nnn2_End:
    
    'PDFファイルを閉じる(Streamのクローズ)
    objStm.Close
    Set objStm = Nothing
    Set objXDoc = Nothing
        
    If CON_DEBUG_MODE Then Call Put_Degug_log(sMsg)

End Function

'**************************************************
'
' Get XML Node Data for Text String
'
'   テキストのXML形式で入っているメタデータから
'   該当する要素に対するノードデータを抽出する。
'
' Create  : 2014/12/07
' Update  : 2014/12/07
' Vertion : 1.0.0
'
' 引数1   : sXml As String (IN)
'           XML形式のメタデータ
' 引数2   : sNodeName As String (IN)
'           検索する要素名
'
' 戻り値  : 要素名と一致したテキストのノードデータ。
'           抽出できなかった時は""を返す。
'
' 備考    : 特に無し
'
' URL     : http://pdf-file.nnn2.com/?p=791
'
' その他  : 著作権等は主張しません。
'           上記URLにコメントを頂けると嬉しいです。
'
'**************************************************

Private Function Get_XML_Node_nnn2( _
    ByVal sXml As String, _
    ByVal sNodeName As String) As String

    Dim objXDoc    As New MSXML2.DOMDocument
    Dim objXNode   As MSXML2.IXMLDOMNode
    
    Get_XML_Node_nnn2 = ""
    
    If objXDoc.LoadXML(sXml) = False Then
        ' 読み込み失敗時
'        Debug.Print "読み込み失敗時:Get_XML_Node_nnn2"
        Exit Function
    End If
    
    'ノードデータの抽出
    For Each objXNode In objXDoc.SelectNodes( _
            CON_SELECT_NODES & "/" & sNodeName)
        Get_XML_Node_nnn2 = objXNode.Text
        Exit Function
    Next
    
    Set objXDoc = Nothing
    Set objXNode = Nothing
    
End Function

'**************************************************
'
' PDFファイルの情報をOLE(IAC)のみで取得する
'
' 備考
'     msGetInfo_ModDate = objAcrobatPDDoc.GetInfo("ModDate")
'     のみ実行できればOK。
'
'**************************************************

Private Function AcroExch_PDDoc_GetInfo( _
    ByVal sFilePaht As String) As Boolean

    Dim objAcrobatPDDoc As New Acrobat.AcroPDDoc
    Dim lRet            As Long
    Dim sDeug           As String

    'PDFオブジェクトをオープンする。
    '注意)Acrobatは画面に表示されない。
    lRet = objAcrobatPDDoc.Open(sFilePaht)
    If lRet = 0 Then
        If CON_DEBUG_MODE Then _
            Call Put_Degug_log("ERROR: PDFをOPEN出来なかった")
        AcroExch_PDDoc_GetInfo = False
        Exit Function
    End If
    
    '文書プロパティの更新日
    msGetInfo_ModDate = objAcrobatPDDoc.GetInfo("ModDate")
    
    If CON_DEBUG_MODE Then
        '文書プロパティのタイトル
        msGetInfo_Title = objAcrobatPDDoc.GetInfo("Title")
        '文書プロパティの作成者
        msGetInfo_Author = objAcrobatPDDoc.GetInfo("Author")
        '文書プロパティのサブタイトル
        msGetInfo_Subject = objAcrobatPDDoc.GetInfo("Subject")
        '文書プロパティのキーワード
        msGetInfo_Keywords = objAcrobatPDDoc.GetInfo("Keywords")
        '文書プロパティのアプリケーション
        msGetInfo_Creator = objAcrobatPDDoc.GetInfo("Creator")
        '文書プロパティのPDF変換
        msGetInfo_Producer = objAcrobatPDDoc.GetInfo("Producer")
        '文書プロパティの作成日
        msGetInfo_CreationDate = objAcrobatPDDoc.GetInfo("CreationDate")
        '文書プロパティの
        msGetInfo_Trapped = objAcrobatPDDoc.GetInfo("Trapped")
        'PermanentID
        msGet_GetPermanentID = objAcrobatPDDoc.GetPermanentID
        'ファイル名
        msGet_FileName = objAcrobatPDDoc.GetFileName
        '変更可能かチェック:先頭ページの削除を試みる
        mbGet_DeletPage = objAcrobatPDDoc.DeletePages(0, 0)
    
        sDeug = _
        "GetInfo(""Title"")=(" & msGetInfo_Title & ")" & vbCrLf & _
        "GetInfo(""Author"")=(" & msGetInfo_Author & ")" & vbCrLf & _
        "GetInfo(""Subject"")=(" & msGetInfo_Subject & ")" & vbCrLf & _
        "GetInfo(""Keywords"")=(" & msGetInfo_Keywords & ")" & vbCrLf & _
        "GetInfo(""Creator"")=(" & msGetInfo_Creator & ")" & vbCrLf & _
        "GetInfo(""Producer"")=(" & msGetInfo_Producer & ")" & vbCrLf & _
        "GetInfo(""CreationDate"")=(" & msGetInfo_CreationDate & ")" & vbCrLf & _
        "GetInfo(""ModDate"")=(" & msGetInfo_ModDate & vbCrLf & _
        "GetInfo(""Trapped"")=(" & msGetInfo_Trapped & ")" & vbCrLf & _
        "GetPermanentID=(" & msGet_GetPermanentID & ")" & vbCrLf & _
        "GetFileName=(" & msGet_FileName & ")" & vbCrLf & _
        "DeletPage=(" & mbGet_DeletPage & ")" & _
        IIf(mbGet_DeletPage = False, "PDFがパスワード設定で保護されています", "")
        Call Put_Degug_log(sDeug)
    End If
    
    'PDFオブジェクトを解放する。
    objAcrobatPDDoc.Close   '※変更は反映されない
    Set objAcrobatPDDoc = Nothing
    
    AcroExch_PDDoc_GetInfo = True
End Function

'**************************************************
'
' LOG の出力 : デバッグ&確認用
'
' 備考
'    不要時は削除してください。
'
'**************************************************

Private Sub Put_Degug_log(ByVal sDeug As String)

    Open msDuegLogFilePath For Append As #mlDuegLogFileNo
    Print #mlDuegLogFileNo, _
            Format(Date, "yyyy/mm/dd") & _
            Format(Time, " hh:mm:ss") & _
            vbCrLf & sDeug & vbCrLf
    Close #mlDuegLogFileNo
        
    msDuegLogCnt = msDuegLogCnt + 1
End Sub

 

 


実行結果のサンプル

タイトル等をセットする。 

関数:PDFからメタデータ(XMP)を抽出する

ドキュメントタイトル、作成者 等をセットする。

関数:PDFからメタデータ(XMP)を抽出する

それがXMPに反映された結果が以下の画面。

関数:PDFからメタデータ(XMP)を抽出する

以下はサンプルの実行結果です。

    

タイトル(dc:title) = ①AFormAut : Fields.Add メソッド
作成者(dc:creator) = ②nori
作成者の役職(photoshop:AuthorsPosition) = ③hira
説明(dc:description) = ④OLEでAcrobat を操作する
説明記入者(photoshop:CaptionWriter) = ⑤nori-san
キーワード(pdf:Keywords) = ⑥Acrobat; OLE; IAC; VBA
著作権のステータス(xmpRights:Marked) = False
著作権情報(dc:rights) = ⑧著作権の情報
著作権情報URL(xmpRights:WebStatement) = ⑨ pdf-file.nnn2.com
xmp:MetadataDate = 2014-12-07T17:43:13+09:00
dc:format = application/pdf
xmp:CreateDate = 2014-02-19T09:50:18+09:00
xmp:ModifyDate = 2014-12-07T17:43:13+09:00
xmp:CreatorTool = MicrosoftR Office Word 2007
pdf:Producer = MicrosoftR Office Word 2007
xmpMM:DocumentID = uuid:****6734-****-43cb-***-f73a331d****
xmpMM:InstanceID = uuid:****f7c1-****-4f62-****-5d1175d3****
dc:subject = ⑥Acrobat OLE IAC VBA

※上記結果の****部分は一部をマスクしました。

   

  

備考

  

  1. PDDoc:GetInfo メソッド では取得できない情報が取れます。
  2. 今後、メンテナンスや再調査等が発生する感じがするので、デバッグルーチンは残して置きます。
    不要ならば削除して流用ください。
  3. メタデータが抽出できないPDFでも、PDDoc:GetInfo メソッド でいくつかのプロパティは取得できます。
  4. Adobe XMP の SDK(英語)  及び XMP Utilities サービス(日本語)が公開されていますが、時間の関係上で参考にはしていません。

  

参考にしたサイト

  

メタデータ

  

XML , XMP

 

ADODB.Stream

    

メタデータとは

 

文書の特性やプロパティを明記したデータです。

文書の本文やファイルが持つコンテンツと異なる情報です。

例えばPDF文書の場合、各ページに見える文書はコンテンツでメタデータでは無いです。

PDF文書が持つ、タイトル、作成者、作成日、変更日時、等のプロパティがメタデータになります。

  

XMPとは

  

Adobe 社が制定したメタデータの標準フォーマットです。

さまざまなアプリケーションでメタデータを作成、処理および交換する為の基準となります。

XMP(Extensible Metadata Platform)の略称。

参考 : Adove XMP 仕様書  (2004年1月 日本語版)

  

動作確認環境

 

  • Windows 7 64bit Professional  (SP1 + MicrosoftUpdate) + Excel 2007 (SP3)

  

< サンプル一覧 >


  

サイト管理人のメモ

  

これ以下はサイト管理人のメモです。

見なくて結構です。

  

sInput = objStm.ReadText ( adReadAll )

ReadText の第一引数

  • adReadAll (-1) :
    既定値です。
    現在の位置から EOS マーカー方向に、すべてのバイトをストリームから読み取ります。
    これは、バイナリ ストリームに唯一有効な StreamReadEnum 値です (Type は adTypeBinary)。
  • adReadLine(-2) :
    ストリームから次の行を読み取ります (LineSeparator プロパティで指定)。

どちらの引数を指定しても結果は同じみたい。

   

xmp:MetadataDate

メタデータの要素「MetadataDate」は以下の2種類で検索してる。

  • xap:MetadataDate
  • xmp:MetadataDate

Adobe XMP 仕様書  (2004年1月 日本語版) を見ると下の「xmp:MetadataDate」の解説が有る。

しかし、PDFファイルをGREP検索すると上の「xap:MetadataDate」だけしか存在しないPDFファイルも有る。

xmp:MetadataDate の説明  Adobe XMP 仕様書  (2004年1月 日本語版) 36頁 より

このリソースのメタデータが最後に変更された日時。
このプロパティには xmp:ModifyDate と同じか、より最近の値が設定されている必要があります。

 

Do While Not objStm.EOS

ReadText ( adReadAll ) で一気にEOSまで、つまりファイルの最後まで読み込むので、

Do でループさせる必要も無いが、Stream オブジェクト自体の操作は今回が初めてなので安全策をコードに持たせる。

 

If lInStr_Cnt2 = 0 Then Exit Do

上記の条件が成り立って、Exit Do される事はありえない。

仮になっても「XMLデータが無い」等のエラーになる可能性が有るので、この時点でのエラーログ・メッセージは出さない。

  

If sValue = Mid$(mstrGetInfo_ModDate, 3, 14) Then

ModDate と同じ更新日時の XMPデータ(メタデータ)は1つしか存在しないという前提で処理を行う。

よって条件が一致したら、残りのXMPデータの抽出&検索は行わない。

  

< サンプル一覧 >

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


出来るだけ早く返答する様には心がけています。
が、遅くなる時もありますのでご了承ください。


SAMURAI Plugin