web-dev-qa-db-ja.com

VBAを使用してドキュメントのプロパティを正しく設定するにはどうすればよいですか?

問題

Word2010でVBAを使用してドキュメントのプロパティを設定するのに問題があります。

いくつかのHeading 1セクションを含むドキュメントがあり、マクロを使用して、選択したセクションを(その内容とともに)抽出し、新しいドキュメントに貼り付けます。

この部分は正常に機能しますが、最後にいくつかのドキュメントプロパティを設定する必要がありますが、どれも設定されていません。

組み込みプロパティとカスタムプロパティの両方を設定しようとしていますが、この質問の目的のために、titlesubjectおよびcategory

必要なプロパティを設定する関数を作成しましたが(以下のように)、VBAはエラーをスローしません(関数でエラー処理を削除しても)。

誰かが私が間違っていることを知っていますか?


関数のしくみ

これは関数が何をすべきかについての簡単な要約ですが、それをチェックするのがより簡単であるとわかるなら、完全な関数は以下にあります-

  1. プロパティがすでに存在するかどうかを確認します
    • あり、それはdefaultプロパティです。
      • デフォルトのプロパティを設定する
      • PropertyTypeUsed変数をdefaultに設定します
    • そうして、それはcustomプロパティです。
      • カスタムプロパティを設定する
      • PropertyTypeUsed変数をcustomに設定します
    • まったく存在しません
      • 新しいカスタムプロパティを作成する
      • カスタムプロパティを設定する
      • PropertyTypeUsed変数をcustomに設定します
  2. 値が正常に設定されているかどうかを確認してください
    • defaultプロパティが設定されている必要があります
      • プロパティは正常に設定されましたか?
    • customプロパティが設定されている必要があります
      • プロパティは正常に設定されましたか?
  3. 結果を返す

私が信じる機能が問題を引き起こしている

Function UpdateDocumentProperty(ByRef doc As Document, _
                                ByVal propertyName As String, _
                                ByVal propertyValue As Variant, _
                                Optional ByVal propertyType As Office.MsoDocProperties = 4)

    '** Set the result to 'False' by default '*
    Dim result As Boolean
    result = False

    '** A property to hold whether or not the property used is default or custom *'
    Dim propertyTypeUsed As String

    '** Check to see if the document property already exists *'
    If PropertyExists(doc, propertyName) Then                           ' A default property exists, so use that
        doc.BuiltInDocumentProperties(propertyName).value = propertyValue
        propertyTypeUsed = "default"
    ElseIf PropertyExists(doc, propertyName, "custom") Then             ' A custom property exists, so use that
        doc.CustomDocumentProperties(propertyName).value = propertyValue
        propertyTypeUsed = "custom"
    Else                                                                ' No property exists, so create a custom property
        doc.CustomDocumentProperties.Add _
            name:=propertyName, _
            LinkToContent:=False, _
            Type:=propertyType, _
            value:=propertyValue
        propertyTypeUsed = "custom"
    End If

    '** Check whether or not the value has actually been set *'
    On Error Resume Next
    If propertyTypeUsed = "default" Then
        result = (doc.BuiltInDocumentProperties(propertyName).value = propertyValue)
    ElseIf propertyTypeUsed = "custom" Then
        result = (doc.CustomDocumentProperties(propertyName).value = propertyValue)
    End If
    On Error GoTo 0

    UpdateDocumentProperty = result

End Function

完全なプロジェクトコード

このプロジェクトの完全なコードは、2つのペーストビンにあります-

フォームを実際に作成するためのコードを取得できるかどうかはわかりませんが(エクスポートする以外に、どこに配置するかはわかりません)、いずれにしても非常に簡単です-

  1. フォーム-frmChooseDocument
  2. ラベル-lblChooseDocument(どの新しいスタータードキュメントをエクスポートしますか?)
  3. コンボボックス-comChooseDocument
  4. キャンセルボタン-btnCancel
  5. [OK]ボタン-btnOK(最初は無効)

実際には、このコードを含むドキュメントを、さまざまなアプリケーションの使用方法に関する詳細な手順を含む、新しいスタートの「マスター」ドキュメントとして使用しています。

コード自体は、ドキュメント内でHeading 1形式のテキストを検索し、それらをフォームのコンボボックスに追加して、ユーザーがエクスポートするセクションを選択できるようにします。次に、新しいドキュメントが作成され、PDFとして保存されます。


更新

コメントで示唆されているように、設定されている値のタイプが関数に渡されている値のタイプと一致していることを確認しました。

上記の3つのプロパティすべての場合、渡す値とドキュメントに対して保存されているプロパティの両方のタイプはstringです。

結果を設定しているタイプと値を出力するために数行を追加しましたが、すべてうまく見えますが、明らかにそうではありません!

Debug.Print "My value:        (" & TypeName(propertyValue) & ")" & propertyValue
Debug.Print "Stored property: (" & TypeName(doc.BuiltInDocumentProperties(propertyName).value) & ")" & doc.BuiltInDocumentProperties(propertyName).value

これが出力です-

My value:        (String)New Starter Guide - Novell
Stored property: (String)New Starter Guide - Novell
My value:        (String)New starter guide
Stored property: (String)New starter guide
My value:        (String)new starters, guide, help
Stored property: (String)new starters, guide, help
11
David Gard

プロパティを変更した後、ドキュメントを保存することで、Wordドキュメントのタイトルを設定することができました。最初に「保存済み」プロパティをfalseに設定して、Wordが状態の変化を登録するようにしました。

Function ChangeDocumentProperty(doc As Document, sProperty As String, sNewValue As String)

    Debug.Print "Initial Property, Value: " & sProperty & ", " & doc.BuiltInDocumentProperties(sProperty)

    doc.BuiltInDocumentProperties(sProperty) = sNewValue

    doc.Saved = False
    doc.Save

    ChangeDocumentProperty = (doc.Saved = True And doc.BuiltInDocumentProperties(sProperty) = sNewValue)

    Debug.Print "Final Property, Value: " & sProperty & ", " & doc.BuiltInDocumentProperties(sProperty)

End Function

イミディエイトウィンドウ:

? ThisDocument.ChangeDocumentProperty(ThisDocument, "Title", "Report Definitions")
Initial Property, Value: Title, Report Glossary
Final Property, Value: Title, Report Definitions
True
2
TehJake

永続オブジェクトのプロパティは、関数で設定できません。つまり、VBAでは、関数の実行が終了した後も関数に副作用が持続することはできません。

関数をSubとして書き直すと、機能するはずです。

1
tpkaplan