初心者です。
エクセルVBAでWordのプロパティ値を取得するためBuiltinDocumentProperties("Number of Pages")を使っているのですが、なぜかページ数が正しく表示されません。
例えば6ページある文書の総ページ数が2というふうに全然関係ない数字が返ってきます。念のためマクロ後にプロパティ値を再確認すると、表示された2に変わってしまっているんです。もちろん実際の文書に存在するページ枚数は変わっていません。
文書自体を開いて上書きしてやると、ページ数の数字は戻るのですが、マクロを実行すると同じ結果になります。どうしてでしょうか?
EXCEL2000です。詳しい方お願いします。
No.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
こんにちはidbr2です。
お礼が大変遅くなり恐縮しております。こちらが質問しておきながら済みませんでした。
ちょっと忙しくなってしまったので、ゆっくりブックを開くこともままなりません。
せっかくですので、教えていただいたコードが意味する内容も含めて、独学していく上での糧にするため色々確認したいのですが、そこはやはり初心者ということでそういった作業にさえある程度時間を要してしまいます。
よって、まだ示していただいたマクロに手を付けられずにいるのですが、用事の方がもう少しかかわりそうなので、とりあえずお礼のほうを先にいたします。
いろいろありがとうございました。今回、大変勉強になりました。
No.11
- 回答日時:
KenKen_SPさん、idbr2さん。
こんにちは、Wend02です。
>バイナリー解析でページ数を取得する関数を作ってみたいと思います。
それは、どのようにして行われるのか、C++でも使うでしょうか?今回、私は、プロパティを取得するタイプライブラリは、すでに、存在しているはずだと思っています。理由は、
Application.GetOpenFilename("MsWordファイル(*.doc),*.doc")
で、プロパティの内容は見てとれますですね。それは、そういう機能のあるプログラムが存在していることに他なりません。ファイルの表層部分にでも記録があるものだと思っています。私の場合は、未だ、いろんな資料が少ないもので、なかなか分らない部分も多いです。
今回、それを調べる過程で、MSの資料が出てきただけで、本来の目的とは違いました。もう少し、私も本格的な勉強をしないと、こういうところがクリアできないのです。
こんにちはidbr2です。
お礼が大変遅くなり恐縮しております。こちらが質問しておきながら済みませんでした。
ちょっと忙しくなってしまったので、ゆっくりブックを開くこともままなりません。
せっかくですので、教えていただいたコードが意味する内容も含めて、独学していく上での糧にするため色々確認したいのですが、そこはやはり初心者ということでそういった作業にさえある程度時間を要してしまいます。
よって、まだ示していただいたマクロに手を付けられずにいるのですが、用事の方がもう少しかかわりそうなので、とりあえずお礼のほうを先にいたします。
いろいろありがとうございました。今回、大変勉強になりました。
No.9
- 回答日時:
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
No.8
- 回答日時:
こんにちは、idbr2 さん、Wendy02 さん。
こちらも色々検証してみましたが、どうも CreateObject
では無理みたいですね、、原因は不明ですが。
参照設定必須みたいです、、、
関数化したものをアップしますので、よろしければ、
暫しお待ちを。
No.7
- 回答日時:
Wendy02です。
ごめんなさい。
>基本的なミスとしては、WordのApplicationが終了していません。
その元のwdApp.Quit を入れずに書いたのは私でした。
m(__)m なんと言ってよいのか、引っ込みつきません。すぐに気が付いてよかったです。重ねてすみません。
No.6
- 回答日時:
こんにちは。
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
No.5
- 回答日時:
#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
お礼が遅くなって済みませんでした。
さっそく教えていただいたマクロを試しましたが、やはりページ数は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
No.4
- 回答日時:
#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
お礼が遅くなって済みませんでした。
さっそく教えていただいたマクロを実行してみたのですが、なぜかウチのEXCELはページ数ではなくて、総文字数を返します。
これはコードの問題ではなくて、ブック自体がおかしくなっているのかも知れないと考え、ブックを新たに作って再挑戦をしましたがこれも駄目。アプリの自動修復を試みたのですが、悪いことは続くもので、ただいまCDRのハードの方が故障していてOfficeのCDを読み込めません。
結局、現時点で打つ手なしかなと諦めモードです。
BuiltinDocumentProperties("Number of Pages")を使うと処理が不完全のまま進行する例が確かにあるということは、何とか自分でも調べられました。
教えていただいたComputeStatistics( Statistic:=wdStatisticPages)の動作確認が取れないのが残念です。
No.3
- 回答日時:
#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
No.2
- 回答日時:
こんにちは。
私も、コードを書く時は、BuiltinDocumentProperties("Number of Pages")で、ページ数は取っていますので、その取るまでのコードを見せていただけませんか?
もしかしたら、Wordを開いていませんか?そうすると、コードが違ってきてしまいます。アクセスする間に、そのWordが書き換わっている可能性がありますね。実体のある「ファイルのプロパティ」でないと、うまくいきませんからね。
それと、大事なことなのですが、そのコードの最終目的を教えてください。それがないと、見当違いな話になることがありますから。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
あるあるbotに投稿したけど採用されなかったあるある募集
あるあるbotに投稿したけど採用されなかったあるあるをこちらに投稿してください
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
複数のワードファイルで合計ページ数を知りたい
Word(ワード)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
FileDialog オブジェクトでファ...
-
動かなくなってしまった古いVBA...
-
vbaサブフォルダーをワイルドカ...
-
サブフォルダ含むフォルダ内の...
-
ffftpでファイル取得が0バイト...
-
コモンダイアログで拡張子の無...
-
タイムスタンプの更新の方法2
-
ファイルを開く時間測定のスク...
-
excel マクロ PDF化の際のエラ...
-
エクセルのVBAで開いている...
-
フォルダの中にファイルが存在...
-
AccessからOLEオブジェクト型の...
-
「エクセルファイルが開いてい...
-
ExcelVBA 文字コード変換
-
【ACCESS VBA】アクセスからデ...
-
ファイルを複数選択した時のフ...
-
フォルダ内のファイル存在監視...
-
ディレクトリ配下のファイル名...
-
複数のワークブックのVBAを変更...
-
VBA、ファイル名検索から開く、...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vbaサブフォルダーをワイルドカ...
-
動かなくなってしまった古いVBA...
-
vbs ブック共有を解除
-
サブフォルダ含むフォルダ内の...
-
ExcelVBA 文字コード変換
-
Accessのウインドウサイズの固定
-
FileDialog オブジェクトでファ...
-
「エクセルファイルが開いてい...
-
vbsでのアスタリスクとファイル...
-
VB6でUTF-8ファイルの読取りを
-
ffftpでファイル取得が0バイト...
-
excel マクロ PDF化の際のエラ...
-
VBAでフォルダ内のhtmlファイル...
-
エクセルのVBAで開いている...
-
ファイルを開く時間測定のスク...
-
Long型で表現できないファイル...
-
複数のワークブックのVBAを変更...
-
VBからExcelファイルを開くとき...
-
【ACCESS VBA】アクセスからデ...
-
VBA、ファイル名検索から開く、...
おすすめ情報