Wordドキュメントの編集中のページをサクッとPDF化する
WordドキュメントのアクティブなページのみPDF化
以前、
コチラの記事で、クリック一発で編集中のドキュメントをPDF化するマクロを紹介した。
今回は、題名のとおり、
現在アクティブなページのみPDF化
するマクロを考える。
使い道があるかどうかは不明なれどw
DocumentオブジェクトのExportAsFixedFormatメソッド
「PDF化」といえば、DocumentオブジェクトのExportAsFixedFormatメソッドの出番。
このメソッド、
実は、ご覧のように異様にたくさんの引数を持っている。その数実に 15。まさに引数祭りw
たいていは必須の「OutPutFileName」と「ExportFormat」の2つしか指定しないので、
Document.ExportAsFixedFormat "hogehoge.pdf",wdExportFormatPDF
みたいに記述すると思う。
実は、このメソッドの引数の中には、
Range
という引数がある。
面白いのは、この引数、データ型が
WdExportRange型 という独自の型なんである。
ちょっと調べてみると、WdExportRangeというのは列挙体で、
名前 | 値 | 説明 |
---|---|---|
wdExportAllDocument | 0 | 文書全体 |
wdExportCurrentPage | 1 | 現在のページ |
wdExportFromTo | 2 | 開始・終了ページを指定 |
wdExportSelection | 3 | 現在の選択範囲 |
それぞれ実際の値と意味するところはこうなっている。
つまり、ExportAsFixedFormatメソッドの引数「Range」に「wdExportCurrentPage(正体は整数の"2")」を渡してやれば、現在のページのみPDF化できるということだ。
ちなみに、コーディングの際は、
こんなふうにインテリセンスが働くので、楽ちん。
ところで、列挙体だけど
WdExportRange.wdExportAllDocument
みたいに書かなくても良いのはなぜなんでしょうね?(←素人丸出しの疑問?)
ファイル名にページ番号を付加する
現在選択中のページのみをPDF化するのだから、できあがったPDFファイルのファイル名にページ番号を付加するぐらいの気は利かせたいところ。
となると、現在選択中のページのページ番号を取得しなければならない。
SelectionオブジェクトのInformationプロパティ
結論から言うと、SelectionオブジェクトのInformationプロパティを参照すれば良い。
このInformationプロパティには引数が何と
41種類
もあった。
そのうち、「wdActiveEndPageNumber」を渡すと、Informationプロパティは、現在カーソルのあるページのページ番号を返してくれる。
Selection.Information(wdActiveEndPageNumber)
こう書く。
ちなみに、「Selection.Information(」まで入力すると、
このようにインテリセンスが働くので、入力は簡単。
コーディング
以上のことを踏まえてコーディングしてみる。
リスト1 標準モジュール
Public Sub convertActivePageToPDF() '///アクティブドキュメントをPDF化する。' Dim objDoc As Document Set objDoc = ActiveDocument Dim pathStr As String pathStr = objDoc.FullName Dim pageNum As Integer pageNum = Selection.Information(wdActiveEndPageNumber) '……(1)' 'フルパスから拡張子の「.」の位置を取得。' Dim n As Integer n = InStrRev(pathStr, ".") '「.」の位置を元に、PDFファイルのフルパスを作る。' 'ページ番号3ケタゼロ埋め文字列をファイル名に付加する。' pathStr = Left(pathStr, n - 1) & _ "_P." & Format(pageNum, "00#") & ".pdf" '……(2)' With objDoc .ExportAsFixedFormat OutputFileName:=pathStr, _ ExportFormat:=wdExportFormatPDF, _ Range:=wdExportCurrentPage '……(3)' End With Set objDoc = Nothing End Sub
(1)の
pageNum = Selection.Information(wdActiveEndPageNumber)
では、SelectionオブジェクトのInformationプロパティに引数として「wdActiveEndPageNumber」を渡すことによって、現在カーソルのあるページの番号を取得し、変数pageNumに格納している。
(2)の
pathStr = Left(pathStr, n - 1) & _ "_P." & Format(pageNum, "00#") & ".pdf"
について。
この行にたどり着いた段階で、変数 pathStr には編集中のドキュメントのフルパスが格納されており、変数 n には拡張子の「.」(ピリオド)の位置(前から何番目にあるか)が格納されている。
まず
Left(pathStr, n - 1)
で、Left関数を用いて、フルパスのうち、拡張子の「.」(ピリオド)の左側の文字列を取得する。
次に
& "_P."
で文字列「_P.」を連結し、
さらに
Format(pageNum, "00#")
でFormat関数を用いてページ番号を3ケタ0埋めにした文字列を連結し、最後に「.pdf」を連結して、出力PDFファイルのファイルフルパスを作成している。1000ページを超すようなドキュメントを扱うことはまあないので3ケタにしているが、4ケタとか5ケタとか必要だったら、Format関数の第2引数を変えたら良いと思う。
(3)の
objDoc.ExportAsFixedFormat OutputFileName:=pathStr, _ ExportFormat:=wdExportFormatPDF, _ Range:=wdExportCurrentPage
で、ExportAsFixedFormatメソッドを実行する。引数「Range」に「wdExportCurrentPage」を指定しているので、現在カーソルのあるページだけがPDF化されることになる。
実行
実験用として、
こんなドキュメントを用意して、3ページ目にカーソルを置いて実行。
実に分かりにくいけど、3ページ目だけがPDF化された。
おわりに
現在のページのみPDF化する、という場面がそんなにあるかどうかは不明だけれど、そういう作業が頻繁に発生するようなら、アドインとして登録しておいたら便利だと思う。
アドイン登録の方法については、
コチラをどうぞ。
Word初心者なので、なかなかオブジェクト構造が飲み込みづらいけれど、分かってくると結構いじり甲斐がありそうな気もするなあ。
ユーザーフォームへのコントロール配置――ControlsコレクションのAddメソッド
ユーザーフォームへのコントロール配置――ControlsコレクションのAddメソッド
ControlsコレクションのAddメソッドによるコントロールの動的配置
この本の162ページによると、
ユーザーフォームにコントロールを追加するには、Controlsコレクション(集合体)のAddメソッドを使います。第1引数には、コントロールのクラス文字列を指定します。第2引数はコントロール名を指定します。
とのこと。ふむふむ、なるほど。
んで、
クラス文字列
については、同書184ページによると、
コントロール | クラス文字列 |
---|---|
コマンドボタン | Forms.CommandButton.1 |
テキストボックス | Forms.TextBox.1 |
ラベル | Forms.Label.1 |
コンボボックス | Forms.ComboBox.1 |
リストボックス | Forms.ListBox.1 |
チェックボックス | Forms.CheckBox.1 |
オプションボタン | Forms.OptionButton.1 |
イメージ | Forms.Image.1 |
トグルボタン | Forms.ToggleButton.1 |
スクロールバー | Forms.ScrollBar.1 |
スピンボタン | Forms.SpinButton.1 |
タブストリップ | Forms.TabStrip.1 |
マルチページ | Forms.MultiPage.1 |
とのこと。(ふう。しっかしHTMLで表書くのしんどいな。)
つまり、
Dim ctrl As Control Set ctrl = Controls.Add("Forms.CommandButton.1","BtnHogeHoge")
としてやれば、「BtnHogeHoge」という名前のCommandButtonコントロールを追加することができる、ということだ。
で、やってみた。
前回
のフォーム及びコードを流用する。
まずは、前回のリスト1の書き換えから。
リスト1 フォームモジュール
Public Sub init_ver2(ByVal numOfBtns As Integer, _ ByVal btnHeight As Double, _ ByVal btnWidth As Double, _ ByVal offsetBtnsRow As Double, _ ByVal offsetBtnsCol As Double, _ ByVal numOfCols As Integer, _ ByVal btnName As String) numOfBtns_ = numOfBtns Dim i As Integer Dim ctrl As Control '……(1)' For i = 1 To numOfBtns_ Set ctrl = Controls.Add("Forms.CommandButton.1", _ "Btn" & Format(i, "0#")) '……(2)' With ctrl .height = btnHeight .width = btnWidth .Top = offsetBtnsRow + ((offsetBtnsRow + btnHeight) * ((i - 1) \ numOfCols)) .Left = offsetBtnsCol + ((offsetBtnsCol + btnWidth) * ((i - 1) Mod numOfCols)) .Caption = btnName & StrConv(i, vbWide) & "号" End With Next With Me .height = offsetBtnsRow _ + ((btnHeight + offsetBtnsRow) * (((numOfBtns_ - 1) \ numOfCols) + 1)) _ + TOP_BOTTOM_MARGIN .width = offsetBtnsCol + ((btnWidth + offsetBtnsCol) * numOfCols) + offsetBtnsCol End With End Sub
変えたのは(1)からの12行(実質11行)
Dim ctrl As Control For i = 1 To numOfBtns_ Set ctrl = Controls.Add("Forms.CommandButton.1", _ "Btn" & Format(i, "0#")) '……(2)' With ctrl .height = btnHeight .width = btnWidth .Top = offsetBtnsRow + ((offsetBtnsRow + btnHeight) * ((i - 1) \ numOfCols)) .Left = offsetBtnsCol + ((offsetBtnsCol + btnWidth) * ((i - 1) Mod numOfCols)) .Caption = btnName & StrConv(i, vbWide) & "号" End With Next
Control型の変数に、ControlsコレクションのAddメソッドを用いて、新しいボタンをセット。With以下のところは前回同様。Forループでボタンの数だけ繰り返している。
(2)の
Set ctrl = Controls.Add("Forms.CommandButton.1", _ "Btn" & Format(i, "0#"))
が今回の主役。
Addメソッドの第1引数に、コマンドボタンのクラス変数「Forms.CommandButton.1」を指定。最後の「1」まで必要なので注意。最初、オブジェクトの通し番号だと思って
Controls.Add("Forms.CommandButton." & i,"Btn" & Format(i, "0#"))
と書いて、i = 2 になったところでエラーが出たw
第2引数では、変数 i を用いて、名前が「Btn01」、「Btn02」、……となるようにした。
実行
ついでに実行方法も変更した。
ワークシート上に、こんなふうにボタンと表を作って、次のコードで実行するようにした。
リスト2 標準モジュール
Public Sub controlTest2() Dim testFrm As TestForm Set testFrm = New TestForm Dim num As Integer Dim str As String Dim height As Double Dim width As Double Dim frmName As String Dim numOfButtons As Integer With ActiveSheet '……(1)' num = .Range("C2").Value str = .Range("C3").Value height = .Range("C4").Value width = .Range("C5").Value frmName = .Range("C6").Value numOfButtons = .Range("C7").Value End With If num = 0 Or num > 10 Then Exit Sub '……(2)' If height < 10 Or height > 400 Then Exit Sub If width < 10 Or width > 400 Then Exit Sub If numOfButtons < 1 Or numOfButtons > 100 Then Exit Sub With testFrm .init_ver2 numOfBtns:=numOfButtons, _ btnHeight:=height, _ btnWidth:=width, _ offsetBtnsRow:=10, _ offsetBtnsCol:=5, _ numOfCols:=num, _ btnName:=str .Caption = frmName .Show End With End Sub
(1)からの8行
With ActiveSheet num = .Range("C2").Value str = .Range("C3").Value height = .Range("C4").Value width = .Range("C5").Value frmName = .Range("C6").Value numOfButtons = .Range("C7").Value End With
で、init_ver2メソッドに渡す引数のうち5つと、フォームのCaptionプロパティに渡す文字列をシートから取得する。
変数の名前を見てもらったら、どれが何に当たるかは分かると思う。
(2)からの4行
If num = 0 Or num > 10 Then Exit Sub If height < 10 Or height > 400 Then Exit Sub If width < 10 Or width > 400 Then Exit Sub If numOfButtons < 1 Or numOfButtons > 100 Then Exit Sub
はガード節。不適切な値が設定されていたら処理をやめるようにしている。
ただし、条件設定はかなりテキトー。
実行結果
なんと、最初に設置した10個のコマンドボタンが設置されたまま、今回、Addメソッドで追加したコマンドボタンが上から配置されている……。
試しに、リスト1の最後に
For Each ctrl In Controls Debug.Print ctrl.name Next
を追加して実行してみると、イミディエイト・ウインドウは、
こうなる。
どうやら、「Btn01」とか「Btn02」というのは「オブジェクト名」のことではないらしい。ま、当たり前か。
こんなふうに、もともと置いてあったコマンドボタンを全部削除してから実行すると、
無事、思い通りの結果が得られた。
おわりに
ついついムキになってユーザーフォーム・コントロール関係にハマってしまったが、実用的なものにするには、動的に配置したコントロールのイベントをどうするか、ということだと思う。ただ、ちょっとまだ今の私の力では手に負えない気もする。
まだまだ勉強が足りないね。
ユーザーフォームへのコントロール配置――このやり方があったじゃないか!
Controlsコレクションの引数
このやり方があったじゃないか!
前回
コチラの記事で、
オブジェクト名を「Object1」、「Object2」、……とかにしておいて、「Object & i」とかで指定できるか
ということなんだが、当然そんなことはできない。
などと、テキトーなことをぶっこいてしまったが、そんなことはない。
Controls("Object" & i)
という指定の仕方があったじゃないか!
コードの書き換え
というわけで、コードを修正。
前回記事のリスト1を次のように書き換える。
リスト1 フォームモジュール
Public Sub init(ByVal btnHeight As Double, _ ByVal btnWidth As Double, _ ByVal offsetBtnsRow As Double, _ ByVal offsetBtnsCol As Double, _ ByVal numOfCols As Integer, _ ByVal btnName As String) numOfBtns_ = 10 Dim i As Integer For i = 1 To numOfBtns_ With Controls("Btn" & Format(i, "0#")) .Height = btnHeight .Width = btnWidth .Top = offsetBtnsRow + ((offsetBtnsRow + btnHeight) * ((i - 1) \ numOfCols)) .Left = offsetBtnsCol + ((offsetBtnsCol + btnWidth) * ((i - 1) Mod numOfCols)) .Caption = btnName & StrConv(i, vbWide) & "号" End With Next With Me .Height = offsetBtnsRow _ + ((btnHeight + offsetBtnsRow) * (((numOfBtns_ - 1) \ numOfCols) + 1)) _ + TOP_BOTTOM_MARGIN .Width = offsetBtnsCol + ((btnWidth + offsetBtnsCol) * numOfCols) + offsetBtnsCol End With End Sub
ちょっとスッキリした。
実行
次のコードで実行。
リスト2 標準モジュール
Public Sub controlTest() Dim testFrm As TestForm Set testFrm = New TestForm With testFrm .init btnHeight:=20, _ btnWidth:=50, _ offsetBtnsRow:=10, _ offsetBtnsCol:=5, _ numOfCols:=5, _ btnName:="クズ" .Caption = "ち~んw" .Show End With End Sub
第6引数だけちょっと変えてみたw
実行結果
うまくいった。
おわりに
同じ種類のコントロールを規則正しく配置するだけならこのやり方が一番いいかも。
ただ、実用的なものにするには当然イベント処理を追加していく必要があるわけで、そういうところも工夫する必要がありそうだ。
ユーザーフォームへのコントロール配置の効率化に挑む
コントロールの配置の効率化
コントロールを規則的に配置する
前回、
は、コントロールを配列にぶち込んでまとめて処理、という方法を試みた。
配列にぶち込みさえすれば、後はループを回すだけなのだが、そもそも配列にぶち込む段階で、
Dim btns(2) As CommandButton Set btns(0) = Me.BtnLeft Set btns(1) = Me.BtnCenter Set btns(2) = Me.BtnRight
こんな書き方をするなんて、エレガントさのかけらもない。もっと言えば、ダサい。
かと言って、Array関数を使っても、
Dim btns As Variant btns = Array(Me.BtnLeft, Me.BtnCenter, Me.BtnRight)
になるだけなので、ダサいことには違いない。
オブジェクト名を変数で合成して呼び出せるか
分かりにくい見出しだが、要するに、
オブジェクト名を「Object1」、「Object2」、……とかにしておいて、「Object & i」とかで指定できるか
ということなんだが、当然そんなことはできない。
For Each を使えばいいんじゃね?
オブジェクト名は、Control型オブジェクトのNameプロパティで取得できるから、For Each XX In Controlsで全てのコントロールをループして、オブジェクト名が条件に合うときだけ処理したら良いと考えた。
準備
ユーザーフォームを挿入して、オブジェクト名を「TestForm」にし、コマンドボタンを10個配置した。画面では整然と並べているけれども、別にグチャグチャに並べておいても良い。
それぞれのコマンドボタンには、「Btn01」~「Btn10」と通し番号付きのオブジェクト名を付けておく。めんどくさいけど。
あとは、コーディング。
リスト1 フォームモジュール
Option Explicit Private numOfBtns_ As Integer Public Sub init(ByVal btnHeight As Double, _ ByVal btnWidth As Double, _ ByVal offsetBtnsRow As Double, _ ByVal offsetBtnsCol As Double, _ ByVal numOfCols As Integer, _ ByVal btnName As String) '……(*)' Dim ctrl As Control Dim i As Integer numOfBtns_ = 0 For Each ctrl In Controls '……(1)' If Left(ctrl.name, 3) = "Btn" Then '……(2)' numOfBtns_ = numOfBtns_ + 1 With ctrl '……(3)' .Height = btnHeight .Width = btnWidth i = numOfBtns_ .Top = offsetBtnsRow + ((offsetBtnsRow + btnHeight) * ((i - 1) \ numOfCols)) .Left = offsetBtnsCol + ((offsetBtnsCol + btnWidth) * ((i - 1) Mod numOfCols)) .Caption = btnName & StrConv(i, vbWide) & "号" End With End If Next With Me '……(4)' .Height = offsetBtnsRow _ + ((btnHeight + offsetBtnsRow) * (((numOfBtns_ - 1) \ numOfCols) + 1)) _ + TOP_BOTTOM_MARGIN .Width = offsetBtnsCol + (btnWidth + offsetBtnsCol) * numOfCols + offsetBtnsCol End With End Sub
まずは(*)のところ。まさに引数祭りwww
ByVal btnHeight As Double, _ ByVal btnWidth As Double, _ ByVal offsetBtnsRow As Double, _ ByVal offsetBtnsCol As Double, _ ByVal numOfCols As Integer, _ ByVal btnName As String
上から順に、
- btnHeight――ボタンの高さ
- btnWidth――ボタンの幅
- offsetBtnsRow――タテ方向のボタンとボタンの間隔
- offsetBtnsCol――ヨコ方向のボタンとボタンの間隔
- numOfCols――1行あたりのボタンの数
- btnName――ボタンの名前
とまあ、これだけの引数を渡して初期化することにしている。
(1)の
For Each ctrl In Controls
からNextまでのブロックで、フォーム内の全コントロールをループ。
(2)の
If Left(ctrl.name, 3) = "Btn" Then
でコントロールのオブジェクト名を調べる。今回配置したコマンドボタンは、全て最初の3字が「Btn」となっているので、この条件がTrueになるということは、Control型変数ctrlにコマンドボタンがぶち込まれているということ。
(3)からの8行
With ctrl .Height = btnHeight .Width = btnWidth i = numOfBtns_ .Top = offsetBtnsRow + ((offsetBtnsRow + btnHeight) * ((i - 1) \ numOfCols)) .Left = offsetBtnsCol + ((offsetBtnsCol + btnWidth) * ((i - 1) Mod numOfCols)) .Caption = btnName & StrConv(i, vbWide) & "号" End With
は、ボタンに対する処理。
Top及びLeftプロパティでは、一見ややこしそうな計算をしているようだが、中身は実に単純。図を書いてみたら良いと思う。説明はめんどくさいので省略。
(4)からの6行(実際は4行)
With Me .Height = offsetBtnsRow _ + ((btnHeight + offsetBtnsRow) * (((numOfBtns_ - 1) \ numOfCols) + 1)) _ + TOP_BOTTOM_MARGIN .Width = offsetBtnsCol + (btnWidth + offsetBtnsCol) * numOfCols + offsetBtnsCol End With
は、フォーム本体の設定。
高さ、幅ともに、
[上下 or 左右の余白]プラス
([ボタンの高さ or 幅]+[ボタン間の隙間の寸法])×[行数 or 列数]
で良いはずなんだが、その通りに式を書くと、
このような残念な形になってしまう。
よって、定数TOP_BOTTOM_MARGIN(中身は「20」)をプラスすることにしている。
実行
次のコードで実行する。
リスト2 標準モジュール
Public Sub controlTest() Dim testFrm As TestForm Set testFrm = New TestForm With testFrm .init btnHeight:=20, _ btnWidth:=50, _ offsetBtnsRow:=10, _ offsetBtnsCol:=5, _ numOfCols:=5, _ btnName:="アホ" .Caption = "ち~んw" .Show End With End Sub
コードについては特に説明はいらないと思う。
実行結果
ボタンが美しく整列している。
おわりに
ただ、このやり方でも、そもそも各コマンドボタンにオブジェクト名をポチポチ書いていかないといけないのはメンドクサイ。配置するコントロールの数を指定して、一気に大量のコントロールを配置する方法もあるんだろうなあ……。
やっぱり、現状では何かの役には立ちそうもないねえ。
ユーザーフォームへのコントロール配置を効率的に行う?
ユーザーフォームを効率的に作る
コントロールはNewできるか
やってみた。
なお、ユーザーフォームは、
このときのものを使う。
オブジェクト名が「BtnLeft」なので、BtnLeft型の変数が宣言できると思ったが、
あえなく撃沈w Newする以前の問題www
コントロールをNewして量産し、フォーム上に動的に配置していく、ということはできない模様。
コントロールをまとめて扱う
ならば、複数のコントロールを配列にぶち込んで、まとめて設定できないか、やってみた。
CommandButton型の変数が宣言できるので、
Dim btns(2) As CommandButton Set btns(0) = Me.BtnLeft Set btns(1) = Me.BtnCenter Set btns(2) = Me.BtnRight
みたいにしたらぶち込めるんじゃないかと思ってやってみたら、
おお、無事通過! できたみたい。
ということは、まとめて取り扱えるということか。
各コマンドボタンのプロパティをまとめて設定する
無事に3つのコマンドボタンを配列にぶち込むことができたので、Forループを使えば、規則的にプロパティを設定できるはず。
次のようなコードで設定を試みた。
リスト1 フォームモジュール
Public Sub init(ByVal formCaption As String, _ ByVal btnLeftName As String, _ ByVal btnCenterName As String, _ ByVal btnRightName As String) With Me .Caption = formCaption .BtnLeft.Caption = btnLeftName .BtnCenter.Caption = btnCenterName .BtnRight.Caption = btnRightName End With Dim btns(2) As CommandButton Set btns(0) = Me.BtnLeft Set btns(1) = Me.BtnCenter Set btns(2) = Me.BtnRight Dim i As Integer For i = 0 To 2 With btns(i) '……(1)' .Height = 25 '……(2)' .Width = 90 .Top = 10 '……(3)' .Left = 5 + ((90 + 5) * i) End With Next Me.Height = 65 '……(4)' Me.Width = 295 End Sub Private Sub UserForm_Terminate()_ '……(5)' MsgBox Me.secretName End Sub
このユーザーフォームの擬似コンストラクタ。引数を渡したいので、UserForm_Initializeは使わない。
(1)からの6行
With btns(i) .Height = 25 .Width = 90 .Top = 10 .Left = 5 + ((90 + 5) * i) End With
は全てWithでまとめているので、配列btnsにぶち込んだそれぞれのコマンドボタンに対する処理。
(2)からの2行
.Height = 25 .Width = 90
でボタンの大きさを設定し、
(3)からの2行
.Top = 10 .Left = 5 + ((90 + 5) * i)
でフォーム上の位置を設定。
Topプロパティは固定で良いが、Leftプロパティはボタンの横幅とボタン同士の間隔分だけ右へずらしていかないといけないので、こんなふうに設定している。まあ、中学校レベルの数学ですわな。
あとは、(4)からの2行
Me.Height = 65 Me.Width = 295
でフォーム全体の大きさを設定しておしまい。
あと、ユーザーフォーム終了時に、追加したプロパティ「secretName」をメッセージ表示するように、(5)の
Private Sub UserForm_Terminate() MsgBox Me.secretName End Sub
デストラクタを作った。
実行
次のコードで実行。
リスト2 標準モジュール
Option Explicit Public Sub userFormTest() Dim uFrm As UserFormTemplate Set uFrm = New UserFormTemplate With uFrm .init "アホ", "ボケ", "クズ", "デコスケ" .secretName = "ち~んw" .Show End With End Sub
これは、このときとほとんど同じ。追加プロパティ「secretName」をイミディエイトに表示する代わりに、ユーザーフォーム終了時のメッセージ表示にした関係でDebug.Printがなくなっただけ。
実行結果
おおっ、ボタンが整然と配置されておる!
で、フォームを閉じると、
むかつくwww
おわりに
未だに便利な使いどころは思いつかないけれど、何らかの有効な使い道はある……はず……だよね?(弱気)
大発見!
プロパティ・ウインドウの表示
項目別?
VBEのプロパティ・ウインドウ。私は常時表示しているんですが、あまり気に掛けることはなかった。
ユーザーフォームを使うときに、フォームやコントロールのプロパティを、コードで設定するのがメンドウなときに見ていじくるぐらいだった。
だから、全然気づいていなかったんだが、
表示方法が「全体」と「項目別」の2種類ある
んですよ。知ってました?(吉高由里子風)
私は知りませんでした。
当然、ずっと表示形式は「全体」。
んで、「項目別」に切り替えてみたんですよ。そしたらね……、
メチャクチャ分かりやすい!!!!!!!!
便利!!!!!!!!!
今まで、
なんでプロパティ名のアルファベット順なんだよ!?
探しにくくてしょうがねえじゃんかよ!!
だなんて思っていましたけど、何だよ、いいとこあるじゃんかよお!
おわりに
「それだけかよ?」って感じですか?
はい。それだけです!!!!!!!!
編集中のWordドキュメントをサクッとPDF化するアドイン
素早く手軽にPDF化
WordドキュメントのPDF化
大量のWordドキュメントを自動でPDF化する、というのは、かなり前に対応済みだった。
Wordドキュメント1つとか2つだけをPDF化する、などというシチュエーションはほとんどなかったので、そういうときは[印刷]メニューでプリンタをJUST PDFとかCubePDFとかに設定してPDFを吐かせていた。
ただコレ、意外とヒマかかるんですよ。
編集中のWordドキュメントをサクッとPDF化したい、というときには不便だった。たった1つや2つのためにわざわざExcelで作ったPDF化ツールを立ち上げるのもばかげているし。
そこで、アドインですよ!
そこでひらめいたのが、最近ハマり気味の「アドイン」。
で、やってみた……んですけどね、
なんでExcelとアドインの登録方法が違うねん!
あれこれ調べまくって、やっとある程度方法が分かったので、紹介する。もっといいやり方があったら教えろてください。
Wordへのアドインの登録
まず、マクロを書いたファイルを、「Word マクロ有効テンプレート(*.dotm)」の形式で保存する。
保存先は、
C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\Word\STARTUP
フォルダ。
テキトーにWordドキュメントを開いて、[ファイル]タブをクリック。
[オプション]をクリック。
[アドイン]をクリック。
「管理」のところのドロップダウンリストで「Wordアドイン」を選択。
[設定]をクリック。
アドイン化したいマクロ名を選んで、
[OK]をクリック。
ここまでで登録はおk。
次に、クイック アクセス ツール バーに登録する。ここからはExcelのときと全く同じだけれど、一応書いとく。
[ファイル]タブ→「クイック アクセス ツール バー」をクリック。
「コマンドの選択」ドロップダウンリストから「マクロ」を選び、
アドイン化したいマクロ名を選択して、
[追加]をクリック。
アイコンが気に食わなければ、テキトーに変更して、
[OK]をクリック。
クイック アクセス ツール バーに登録された。
フォルダ内に「test.docx」1つだけがある状態で、こいつを開いてクイック アクセス ツール バーのアイコンをクリックすると、
次の瞬間に、PDFファイルが生まれている。
結構一瞬でPDF化できる。
もちろん、特定のページだけをPDF化、みたいな手の込んだことはできない。そんなときは素直にフツーのやり方をすればよろしい。
今回使用したマクロのコード
リスト1 標準モジュール
Option Explicit Public Sub convertToPDF() '///アクティブドキュメントをPDF化する。' Dim objDoc As Document Set objDoc = ActiveDocument Dim pathStr As String pathStr = objDoc.FullName 'フルパスから拡張子の「.」の位置を取得。' Dim n As Integer n = InStrRev(pathStr, ".") '「.」の位置を元に、PDFファイルのフルパスを作る。' pathStr = Left(pathStr, n) & "pdf" With objDoc .ExportAsFixedFormat OutputFileName:=pathStr, _ ExportFormat:=wdExportFormatPDF End With Set objDoc = Nothing End Sub
コードの説明は省略。お望みでしたらコメントください。
おわりに
こういうちょっとした処理をアドイン化しといたら便利だなあ。