【VBA】 PDFへのコメント追加スクリプトの生成

全体フロー

Excel(コメント一覧)
       ↓  VBAマクロ実行(Alt+F8)
JavaScript コード生成 → クリップボードへ自動コピー
       ↓  PDF-XChange Editor で Ctrl+J → Ctrl+V → Enter
PDF 各ページにコメント追加完了 → Ctrl+S で保存

初回セットアップ(1回だけ)

  1. コメント一覧_テンプレート_v3.xlsx を開く
  2. Alt+F11(VBAエディタを開く)
  3. 挿入 → 標準モジュール
  4. VBAコードを貼り付け
  5. VBAエディタを閉じる
  6. 名前を付けて保存 → 種類を 「Excel マクロ有効ブック (.xlsm)」 で保存

毎回の操作

Step 1: Excel でデータ入力

「コメント一覧」シートに入力(1行目はヘッダー)

A列(図番)B列(コメント)
DWG-001承認済み
DWG-002要修正:寸法確認

※ 2行目 → PDFの1ページ目、3行目 → 2ページ目 … と対応

Step 2: 設定を調整(任意)

「設定」シートでドロップダウンから選択

項目初期値選択肢
フォントサイズ108~14 推奨
フォントHelvBHelvB / Helv / Cour / CourB / Times / TimesB
文字色redred / blue / black / green
背景色whitewhite / yellow / none(透明)
枠線なしあり / なし
枠線色blackred / blue / black / green
位置左上左上 / 右上 / 左下 / 右下

Step 3: マクロ実行

Alt+F8 → 「JS生成_クリップボードコピー」→ 実行

→ JavaScriptが自動でクリップボードにコピーされる

Step 4: PDF-XChange Editor で貼り付け

  1. PDFを開く
  2. Ctrl+J(JSコンソールを開く)
  3. Ctrl+V(貼り付け)
  4. Enter(実行)→ 完了ダイアログ
  5. Ctrl+S(保存)

技術ポイント

VBAマクロの役割

  • Excelの「コメント一覧」シートから図番・コメントを読み取り
  • 「設定」シートからフォント・色・位置の設定を読み取り
  • PDF-XChange Editor の JSコンソールで実行可能な JavaScript を自動生成
  • 生成したコードをクリップボードにコピー

生成される JavaScript の処理内容

  • this.numPages で PDF の総ページ数を取得
  • 各ページの寸法を this.getPageBox("Crop", i) で取得
  • テキスト幅を全角/半角で自動計算(全角=fontSize幅、半角=fontSize×0.55)
  • 指定位置(左上/右上/左下/右下)に応じた座標を算出
  • this.addAnnot() で FreeText アノテーションとして追加

必要な環境

  • Excel(マクロ有効)
  • PDF-XChange Editor(無料版OK)
  • 追加インストール:なし

Sub JS生成_クリップボードコピー()
    '-------------------------------------------
    ' PDFコメント貼付ツール - JS生成マクロ(回転対応版
    '-------------------------------------------
    Dim wsData As Worksheet
    Dim wsSetting As Worksheet
    Dim fontSize As Long
    Dim textColor As String

    Set wsData = ThisWorkbook.Sheets("コメント一覧")

    ' 設定読み込
    On Error Resume Next
    Set wsSetting = ThisWorkbook.Sheets("設定")
    On Error GoTo 0

    If Not wsSetting Is Nothing Then
        fontSize = wsSetting.Cells(2, 2).Value
        textColor = CStr(wsSetting.Cells(3, 2).Value)
    End If
    If fontSize = 0 Then fontSize = 10
    If textColor = "" Then textColor = "red"

    ' 色マッピン
    Dim jsColor As String
    Select Case LCase(textColor)
        Case "red":   jsColor = "color.red"
        Case "blue":  jsColor = "color.blue"
        Case "black": jsColor = "color.black"
        Case "green": jsColor = "color.green"
        Case Else:    jsColor = "color.red"
    End Select

    ' データ読み込
    Dim row As Long
    Dim dataCount As Long
    row = 2
    dataCount = 0
    Do While wsData.Cells(row, 1).Value <> "" Or wsData.Cells(row, 2).Value <> ""
        dataCount = dataCount + 1
        row = row + 1
    Loop

    If dataCount = 0 Then
        MsgBox "コメントデータがありません。" & vbCrLf & _
               "「コメント一覧」シートの2行目以降にデータを入力してください。", vbExclamation
        Exit Sub
    End If

    ' JavaScript生
    Dim js As String
    Dim Q As String
    Q = Chr(34) ' ダブルクォー

    js = "// PDF コメント貼付スクリプト(回転対応版)" & vbLf
    js = js & "// 生成: " & Format(Now, "yyyy/mm/dd hh:nn:ss") & vbLf
    js = js & "var comments = [" & vbLf

    row = 2
    Do While wsData.Cells(row, 1).Value <> "" Or wsData.Cells(row, 2).Value <> ""
        Dim figNum As String
        Dim comment As String
        Dim displayText As String

        figNum = CStr(wsData.Cells(row, 1).Value)
        comment = CStr(wsData.Cells(row, 2).Value)

        ' エスケー
        displayText = Replace(comment, "\", "\\")
        displayText = Replace(displayText, Q, "\" & Q)

        If figNum <> "" Then
            figNum = Replace(figNum, "\", "\\")
            figNum = Replace(figNum, Q, "\" & Q)
            displayText = "[" & figNum & "] " & displayText
        End If

        js = js & "  " & Q & displayText & Q & "," & vbLf
        row = row + 1
    Loop

    js = js & "];" & vbLf
    js = js & "" & vbLf

    ' ============================================================
    ' 回転対応のコアロジッ
    ' getPageBox は「PDFの生座標系(回転前)」を返
    ' getPageRotation で回転角を取得し、座標を補正す
    '
    ' 各回転角での座標変換
    '   回転0°  : そのまま。左上 = (x0, y1)
    '   回転90° : 幅と高さが入れ替わる。左上 = (y0, x1)
    '   回転180°: 左上が右下になる。左上 = (x1, y0)
    '   回転270°: 幅と高さが入れ替わり反転。左上 = (y1, x0)
    '
    ' 目標どの回転でも表示上の左上端にコメントを配置する
    ' ============================================================

    js = js & "// ページ回転を考慮してrectを計算するヘルパー関数" & vbLf
    js = js & "function calcRect(box, rotation, textLen, fSize) {" & vbLf
    js = js & "  // box = [x0, y0, x1, y1] (PDF生座標系、左下原点)" & vbLf
    js = js & "  // x0,y0=左下  x1,y1=右上" & vbLf
    js = js & "  var x0 = box[0], y0 = box[1], x1 = box[2], y1 = box[3];" & vbLf
    js = js & "  var w = x1 - x0;  // ページ幅(生座標)" & vbLf
    js = js & "  var h = y1 - y0;  // ページ高さ(生座標)" & vbLf
    js = js & "  var margin = 8;" & vbLf
    js = js & "  var tW = textLen * fSize * 0.55;" & vbLf
    js = js & "  var tH = fSize + 4;" & vbLf
    js = js & "  var rx0, ry0, rx1, ry1;" & vbLf
    js = js & "  // 「表示上の左上」を生座標に変換してrectを組み立てる" & vbLf
    js = js & "  if (rotation === 0) {" & vbLf
    js = js & "    // 表示: 左上 = PDF座標(x0, y1)" & vbLf
    js = js & "    rx0 = x0 + margin;" & vbLf
    js = js & "    ry1 = y1 - margin;" & vbLf
    js = js & "    rx1 = rx0 + tW;" & vbLf
    js = js & "    ry0 = ry1 - tH;" & vbLf
    js = js & "  } else if (rotation === 90) {" & vbLf
    js = js & "    // 表示: 左上 = PDF座標(x0, y0)  ※幅と高さが見かけ上入れ替わる" & vbLf
    js = js & "    rx0 = x0 + margin;" & vbLf
    js = js & "    ry0 = y0 + margin;" & vbLf
    js = js & "    rx1 = rx0 + tH;" & vbLf
    js = js & "    ry1 = ry0 + tW;" & vbLf
    js = js & "  } else if (rotation === 180) {" & vbLf
    js = js & "    // 表示: 左上 = PDF座標(x1, y0)" & vbLf
    js = js & "    rx1 = x1 - margin;" & vbLf
    js = js & "    ry0 = y0 + margin;" & vbLf
    js = js & "    rx0 = rx1 - tW;" & vbLf
    js = js & "    ry1 = ry0 + tH;" & vbLf
    js = js & "  } else if (rotation === 270) {" & vbLf
    js = js & "    // 表示: 左上 = PDF座標(x1, y1)  ※幅と高さが見かけ上入れ替わる" & vbLf
    js = js & "    rx1 = x1 - margin;" & vbLf
    js = js & "    ry1 = y1 - margin;" & vbLf
    js = js & "    rx0 = rx1 - tH;" & vbLf
    js = js & "    ry0 = ry1 - tW;" & vbLf
    js = js & "  } else {" & vbLf
    js = js & "    // フォールバック(想定外の回転値)" & vbLf
    js = js & "    rx0 = x0 + margin;" & vbLf
    js = js & "    ry1 = y1 - margin;" & vbLf
    js = js & "    rx1 = rx0 + tW;" & vbLf
    js = js & "    ry0 = ry1 - tH;" & vbLf
    js = js & "  }" & vbLf
    js = js & "  return [rx0, ry0, rx1, ry1];" & vbLf
    js = js & "}" & vbLf
    js = js & "" & vbLf

    js = js & "var n = this.numPages;" & vbLf
    js = js & "var added = 0;" & vbLf
    js = js & "for (var i = 0; i " & Chr(60) & " n " & Chr(38) & Chr(38) & " i " & Chr(60) & " comments.length; i++) {" & vbLf
    js = js & "  if (comments[i] === " & Q & Q & ") continue;" & vbLf
    js = js & "  var page = this.getPageBox(" & Q & "Crop" & Q & ", i);" & vbLf
    js = js & "  var rot = this.getPageRotation(i);  // 0, 90, 180, 270 のいずれか" & vbLf
    js = js & "  var tLen = comments[i].length;" & vbLf
    js = js & "  var r = calcRect(page, rot, tLen, " & fontSize & ");" & vbLf
    js = js & "  this.addAnnot({" & vbLf
    js = js & "    type: " & Q & "FreeText" & Q & "," & vbLf
    js = js & "    page: i," & vbLf
    js = js & "    rect: r," & vbLf
    js = js & "    contents: comments[i]," & vbLf
    js = js & "    textFont: font.HelvB," & vbLf
    js = js & "    textSize: " & fontSize & "," & vbLf
    js = js & "    textColor: " & jsColor & "," & vbLf
    js = js & "    strokeColor: [" & Q & "RGB" & Q & ",1,1,1]," & vbLf
    js = js & "    fillColor: [" & Q & "RGB" & Q & ",1,1,1]," & vbLf
    js = js & "    opacity: 0.9," & vbLf
    js = js & "    borderEffectStyle: " & Q & Q & "," & vbLf
    js = js & "    width: 0" & vbLf
    js = js & "  });" & vbLf
    js = js & "  added++;" & vbLf
    js = js & "}" & vbLf
    js = js & "app.alert(" & Q & "完了! " & Q & "+added+" & Q & " ページにコメントを追加しました。\nCtrl+S で保存してください。" & Q & ", 3);" & vbLf

    ' クリップボードにコピー(MSForms.DataObject使用
    Dim objData As Object
    Set objData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    objData.SetText js
    objData.PutInClipboard
    Set objData = Nothing

    MsgBox dataCount & " 件のコメントからJavaScriptを生成しました!(回転対応版)" & vbCrLf & vbCrLf & _
           "クリップボードにコピー済みです。" & vbCrLf & vbCrLf & _
           "【次の手順】" & vbCrLf & _
           "1. PDF-XChange Editor でPDFを開く" & vbCrLf & _
           "2. Ctrl+J (JSコンソール)" & vbCrLf & _
           "3. Ctrl+V (貼り付け)" & vbCrLf & _
           "4. Enter (実行)" & vbCrLf & _
           "5. Ctrl+S (保存)", vbInformation, "PDF コメント貼付ツール(回転対応版)"

End Sub

コメント

タイトルとURLをコピーしました