dポイントプレゼントキャンペーン実施中!

 初心者です。
エクセルVBAでWordのプロパティ値を取得するためBuiltinDocumentProperties("Number of Pages")を使っているのですが、なぜかページ数が正しく表示されません。
 例えば6ページある文書の総ページ数が2というふうに全然関係ない数字が返ってきます。念のためマクロ後にプロパティ値を再確認すると、表示された2に変わってしまっているんです。もちろん実際の文書に存在するページ枚数は変わっていません。
 文書自体を開いて上書きしてやると、ページ数の数字は戻るのですが、マクロを実行すると同じ結果になります。どうしてでしょうか?
 EXCEL2000です。詳しい方お願いします。



 

A 回答 (11件中1~10件)

> なぜかウチのEXCELはページ数ではなくて、総文字数を返します。



それは、恐らく参照設定の問題ですね。実行時バインド(CreateObject)
方式では ComputeStatistics に渡す引数のインデックス番号が正しく
渡らないのだと思います。参照設定を行えば問題なく動作します。

ちなみに私は昔から BuiltinDocumentProperties は当てにならない、、
と思いこんでましたから、ComputeStatistics を使ってました。
今回、Wendy02 さんが良い情報を提供して下さいましたので、私も今後は
BuiltinDocumentProperties 派でいこうと思います。
ただ、今回このスレッドで紹介された方法はいずれもファイル全体を一度
は読み込む方法ですから、処理速度は遅いですね。機会があれば、
バイナリー解析でページ数を取得する関数を作ってみたいと思います。

それから、蛇足で恐縮ですが、#8 発言の手前、一応アップしておきます。

ユーザー定義関数を作ってみました。が、、関数にする必要性はあまり
無かったです(;-ω-) =3

Word ファイルのパスを渡すと、各種情報が一次元配列で返されます。
使いかたは、サンプルコードを見てください。

Variant型の変数で関数の戻り値を一次元配列で受けます。その変数の
添え字に取得したい BuiltinDocumentProperties のインデックス番号
を指定します。

まぁ。。ファイル処理周りの例外処理をメインルーチン側で省けるので
意義は在ると言えば在るのですが。


Sub 使い方サンプルコード()

  Dim Fname  As String
  Dim aryInfo As Variant
  Dim sMes(8) As String
  Dim Sp   As String
 
  Fname = Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")
  If UCase$(Fname) = "FALSE" Then
    Exit Sub
  End If
  '関数の戻り値は一次元配列なので Variant型 の変数で受ける
  aryInfo = GetMsWordBuiltinProperties(Fname)
  '結果表示
  If IsArray(aryInfo) = False Then Exit Sub
 
  Sp = vbTab & ": "
  sMes(0) = "ファイル名" & Sp & Dir(Fname)
  sMes(1) = "バイト数" & Sp & Format(aryInfo(22) / 1024, "#,##0") & " KB"
  sMes(2) = "タイトル" & Sp & aryInfo(1)
  sMes(3) = "文字数" & Sp & aryInfo(16)
  sMes(4) = "(SP含む)" & Sp & aryInfo(30)
  sMes(5) = "行数" & Sp & aryInfo(23)
  sMes(6) = "ページ数" & Sp & aryInfo(14)
  sMes(7) = "段落数" & Sp & aryInfo(24)
  sMes(8) = "単語数" & Sp & aryInfo(15)
  MsgBox Join$(sMes, vbCr)
 
End Sub

'MsWord ドキュメントの各種統計情報を取得
Function GetMsWordBuiltinProperties(strFilePath As String) As Variant

  '要参照設定:Microsoft Word x.x Object Library
  
  Dim wdApp   As Word.Application
  Dim wdDoc   As Word.Document
  Dim aryRet(1 To 30) As Variant
 
  On Error GoTo ErrorHandler
  
  '初期化
  GetMsWordBuiltinProperties = False
  'ファイルが無いまたは拡張子が異なる場合は False を返す
  If Dir(strFilePath) = "" _
    Or UCase$(Right$(strFilePath, 4)) <> ".DOC" Then
    Exit Function
  End If
 
  'MsWord ファイルオープン
  Set wdApp = New Word.Application
  Set wdDoc = wdApp.Documents.Open(strFilePath, ReadOnly:=True)
  'ドキュメントの統計情報を取得
  With wdDoc
    .Repaginate 'Thanks Wendy02 san!
    For i = 1 To 30
      aryRet(i) = .BuiltinDocumentProperties(i)
      'Index 24-29 は Word では使わないと思います
      If i = 24 Then i = 29
    Next i
  End With
  '戻り値をセット
  GetMsWordBuiltinProperties = aryRet
 
Terminate:
  On Error Resume Next
  wdDoc.Close False
  wdApp.Application.Quit
  Set wdDoc = Nothing
  Set wdApp = Nothing
  Exit Function

ErrorHandler:
  '想定外のエラー発生の場合には False を返す
  GetMsWordBuiltinProperties = False
  On Error GoTo 0
  GoTo Terminate

End Function
    • good
    • 0
この回答へのお礼

こんにちはidbr2です。
お礼が大変遅くなり恐縮しております。こちらが質問しておきながら済みませんでした。
ちょっと忙しくなってしまったので、ゆっくりブックを開くこともままなりません。
せっかくですので、教えていただいたコードが意味する内容も含めて、独学していく上での糧にするため色々確認したいのですが、そこはやはり初心者ということでそういった作業にさえある程度時間を要してしまいます。
よって、まだ示していただいたマクロに手を付けられずにいるのですが、用事の方がもう少しかかわりそうなので、とりあえずお礼のほうを先にいたします。

いろいろありがとうございました。今回、大変勉強になりました。

お礼日時:2005/10/01 11:53

KenKen_SPさん、idbr2さん。


こんにちは、Wend02です。

>バイナリー解析でページ数を取得する関数を作ってみたいと思います。

それは、どのようにして行われるのか、C++でも使うでしょうか?今回、私は、プロパティを取得するタイプライブラリは、すでに、存在しているはずだと思っています。理由は、

Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")

で、プロパティの内容は見てとれますですね。それは、そういう機能のあるプログラムが存在していることに他なりません。ファイルの表層部分にでも記録があるものだと思っています。私の場合は、未だ、いろんな資料が少ないもので、なかなか分らない部分も多いです。

今回、それを調べる過程で、MSの資料が出てきただけで、本来の目的とは違いました。もう少し、私も本格的な勉強をしないと、こういうところがクリアできないのです。
    • good
    • 0
この回答へのお礼

こんにちはidbr2です。
お礼が大変遅くなり恐縮しております。こちらが質問しておきながら済みませんでした。
ちょっと忙しくなってしまったので、ゆっくりブックを開くこともままなりません。
せっかくですので、教えていただいたコードが意味する内容も含めて、独学していく上での糧にするため色々確認したいのですが、そこはやはり初心者ということでそういった作業にさえある程度時間を要してしまいます。
よって、まだ示していただいたマクロに手を付けられずにいるのですが、用事の方がもう少しかかわりそうなので、とりあえずお礼のほうを先にいたします。

いろいろありがとうございました。今回、大変勉強になりました。

お礼日時:2005/10/01 11:49

Wendy02です。

以下は、修正版です。

Sub MsWordタイトル取得2()
  Dim wdApp As Word.Application
  Dim wdDoc As Word.Document
  Dim Fname As String
  Dim FileSize As Long, myWait As Long
 
  Dim wdCnt As Long, wdtitle As String
  Set wdApp = New Word.Application
  Fname = Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")
  If Fname = "False" Then
   Exit Sub
  End If
  Set wdDoc = wdApp.Documents.Open(Fname, , True)
  With wdDoc
   .Repaginate '書き換えた部分
   wdtitle = .BuiltinDocumentProperties(wdPropertyTitle)
   wdCnt = .BuiltinDocumentProperties(wdPropertyPages)
   .Close False
  End With
   wdApp.Quit
  Set wdDoc = Nothing
  Set wdApp = Nothing
  MsgBox wdtitle & vbCrLf & " 総ページ数" & wdCnt
End Sub


以下を参考にしました。

http://support.microsoft.com/default.aspx?scid=k …
 (http://support.microsoft.com/kb/212653/ja)

英語からの拙訳:

WD2000: BuiltInDocumentPropertiesで誤ったページ・カウント表示を返す場合。
記事ID:212653
本記事は、Q212653の元で以前に発表された。

ドキュメントにページ改行を挿入し、マクロを使ってBuiltInDocumentProperties のプロパティを用いてページ・カウントを返した時に、返されるページが誤っている場合。

そのドキュメントはページ数を返す前に、"repaginate"で再ページカウントする必要がある。

  Sub GetNumberOfPages()
   ActiveDocument.Repaginate
   MsgBox ActiveDocument.BuiltInDocumentProperties(wdPropertyPages)
  End Sub
    • good
    • 1

こんにちは、idbr2 さん、Wendy02 さん。



こちらも色々検証してみましたが、どうも CreateObject
では無理みたいですね、、原因は不明ですが。

参照設定必須みたいです、、、

関数化したものをアップしますので、よろしければ、
暫しお待ちを。
    • good
    • 0

Wendy02です。



ごめんなさい。

>基本的なミスとしては、WordのApplicationが終了していません。

その元のwdApp.Quit を入れずに書いたのは私でした。
m(__)m なんと言ってよいのか、引っ込みつきません。すぐに気が付いてよかったです。重ねてすみません。
    • good
    • 0

こんにちは。

Wendy02です。

>おそらく完全に文書を読み込み切れていないのが原因なのかなと、自分では推測しております。

確認しました。おっしゃる通りです。ただし、そのコードは、とても危険な内容です。あやうく、フリーズをするところでした。とりあえず以下のようにしてみてください。基本的なミスとしては、WordのApplicationが終了していません。もしも、Applicationをオープンしたままでしたら、GetObjectを使いながら、取得すればもっと速く取れるはずです。Visible を入れてみて気が付きました。

今回、API関数を入れ、Waitを付けてみました。その値(FileSize/50000)自体は、PCのスペックに依存するものですから、最適値は、変わります。もちろん、KenKen_SPさんのComputeStatisticsの方法でも、切り替えれば、取得可能なはずです。

それから、CreateObjectでも取れるはずですが、安定を考えて、参照設定を使いました。

Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub MsWordタイトル取得()
  Dim wdApp As Word.Application
  Dim wdDoc As Word.Document
  Dim Fname As String
  Dim FileSize As Long, myWait As Long
 
  Dim wdCnt As Long, wdtitle As String
  Set wdApp = New Word.Application
 
  Fname = Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")
  If Fname = "False" Then
   Exit Sub
  End If
  FileSize = FileLen(Fname)
  Set wdDoc = wdApp.Documents.Open(Fname, , True)
  'wdApp.Visible = True
  myWait = Int(FileSize / 50000) * 1000
  Sleep myWait
  With wdDoc
   wdtitle = .BuiltinDocumentProperties("Title")
   wdCnt = .BuiltinDocumentProperties("Number of Pages")
   .Close False
  End With
   wdApp.Quit
  Set wdDoc = Nothing
  Set wdApp = Nothing
  MsgBox wdtitle & vbCrLf & " 総ページ数" & wdCnt
End Sub
    • good
    • 0

#2のWendy02ですが、



自分の発言を撤回します。
#Wordを開いていませんか?そうすると、コードが違ってきてしまいます。

ではなくて、開け方が問題ではないでしょうか?オートメーションで開ける分には、ドキュメントが開いていようがいまいが、関係がありません。それで、私は、この問題は、環境の違いによって途中で書き換わっていると考えています。Officeのプロパティは、元々、外部ツールなどで閲覧できるように作られているので、開いて書き換えなければ、変わらないはずです。

Sub WhatTPages_inWDDoc()
  Dim WdApp As Object
  Dim WdDoc As Object
  Dim myRange As Object
  Dim myFile As String
  Dim Pagecount As Integer
  myFile = "C:\MyFavorite.Doc"
  On Error GoTo ErrHandler
  Set WdApp = CreateObject("Word.Application")
  With WdApp.Documents.Open(myFile, , True)
   Set myRange = .Content
   myRange.Collapse Direction:=0
   Pagecount = .BuiltinDocumentProperties(14)
   .Close 0
  End With
  MsgBox Pagecount & " ページ"
ErrHandler:
  Set WdApp = Nothing
End Sub
    • good
    • 0
この回答へのお礼

お礼が遅くなって済みませんでした。

さっそく教えていただいたマクロを試しましたが、やはりページ数は2と表示されます。おそらく完全に文書を読み込み切れていないのが原因なのかなと、自分では推測しております。

それと、ご質問があったマクロの最終目的なのですが、ワード文書がひとつ出来上がるごとに、作成日時と文書タイトル、総ページ数などをエクセルの一覧表に記入していくという作業をしたかったので、ダイアログから選択した文書のプロパティ値をマクロで取得して、エクセルの表に書き込んでくためのものです。
最初の状況報告があいまいで申し訳ありませんでした。
下記に途中まで作ってみたマクロを載せます。

Sub MsWordタイトル取得()

Dim wdApp As Object, Fname As String, wdDoc As Object
Dim wdCnt As Long
Dim wdtitle As String

Set wdApp = CreateObject("Word.Application")
Fname = Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")
If Fname = "False" Then
Exit Sub
End If
Set wdDoc = wdApp.Documents.Open(Fname)
wdtitle = wdDoc.BuiltinDocumentProperties("Title")
wdCnt = wdDoc.BuiltinDocumentProperties("Number of Pages")

wdDoc.Close False
MsgBox wdtitle & vbCrLf & " 総ページ数" & wdCnt
Set wdApp = Nothing


End Sub

お礼日時:2005/09/28 13:16

#1 です。

重ねて失礼しました。

#3 は変数の宣言が漏れたり、WORD のインスタンスが残ったり、お粗末なコード
でした。差し替えさせて頂きます。適当ですみません。

Sub Sample()

  Dim wdApp As Object
  Dim wdDoc As Object
  Dim lngPageCount As Long
    
  Set wdApp = CreateObject("Word.Application")
  
  'ファイルオープン
  Set wdDoc = wdApp.Documents.Open("C:\test.doc")
  'ページ数取得
  lngPageCount = wdDoc.ComputeStatistics( _
    Statistic:=wdStatisticPages, _
    IncludeFootnotesAndEndnotes:=True)
  
  'WORDを閉じる
  wdDoc.Close
  wdApp.Application.Quit
  
  'ページ数表示
  MsgBox lngPageCount
  
  'オブジェクト変数を解放
  Set wdDoc = Nothing
  Set wdApp = Nothing

End Sub
    • good
    • 0
この回答へのお礼

お礼が遅くなって済みませんでした。

さっそく教えていただいたマクロを実行してみたのですが、なぜかウチのEXCELはページ数ではなくて、総文字数を返します。
これはコードの問題ではなくて、ブック自体がおかしくなっているのかも知れないと考え、ブックを新たに作って再挑戦をしましたがこれも駄目。アプリの自動修復を試みたのですが、悪いことは続くもので、ただいまCDRのハードの方が故障していてOfficeのCDを読み込めません。
結局、現時点で打つ手なしかなと諦めモードです。

BuiltinDocumentProperties("Number of Pages")を使うと処理が不完全のまま進行する例が確かにあるということは、何とか自分でも調べられました。

教えていただいたComputeStatistics( Statistic:=wdStatisticPages)の動作確認が取れないのが残念です。

お礼日時:2005/09/28 13:18

#1 です。

失礼。Excel VBA でしたね。

ページが重たいと BuiltinDocumentProperties("Number of Pages") は不安定
みたいですね。ページを開く途中で、コードが実行されている感じがします。

コーディんグにもよると思いますが。

以下は Excel VBA で書き直しました。ご参考までに。

Sub Sample()

  Dim wdApp As Object
  
  Set wdApp = CreateObject("Word.Application")
  
  'ファイルオープン
  Set wdDoc = wdApp.Documents.Open("C:\test.doc")
  'ページ数取得
  lngPageCount = wdDoc.ComputeStatistics( _
    Statistic:=wdStatisticPages, _
    IncludeFootnotesAndEndnotes:=True)
  'WORDを閉じる
  wdDoc.Close
  
  'ページ数表示
  MsgBox lngPageCount
  
  'オブジェクト変数を解放
  Set wdDoc = Nothing
  Set wdApp = Nothing

End Sub
    • good
    • 0

こんにちは。



私も、コードを書く時は、BuiltinDocumentProperties("Number of Pages")で、ページ数は取っていますので、その取るまでのコードを見せていただけませんか?

もしかしたら、Wordを開いていませんか?そうすると、コードが違ってきてしまいます。アクセスする間に、そのWordが書き換わっている可能性がありますね。実体のある「ファイルのプロパティ」でないと、うまくいきませんからね。

それと、大事なことなのですが、そのコードの最終目的を教えてください。それがないと、見当違いな話になることがありますから。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!