<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Japan Office Developer Support Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/feed.xml</link>
    <description />
    <lastBuildDate>Fri, 01 Mar 2019 12:47:25 GMT</lastBuildDate>
    <language>ja</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Japan Office Developer Support Blog のフォーラム移行のお知らせ</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/migration-of-thisblog</link>
      <pubDate>Thu, 21 Feb 2019 16:35:39 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1865</guid>
      <description><![CDATA[こんにちは、Office 開発サポート チームの中村です。

&nbsp;

しばらく更新ができていないところのご案内となり申し訳ございませんが、2019 年 3...]]></description>
      <content:encoded><![CDATA[こんにちは、Office 開発サポート チームの中村です。

&nbsp;

しばらく更新ができていないところのご案内となり申し訳ございませんが、2019 年 3 月をもちまして、弊社システム刷新の都合により本ブログを終了いたします。

今後は、これまで別のブログで公開しておりました <span>Office </span>サポート チームからの一般的な Office 利用に関する情報と合わせ、以下のフォーラムで情報発信を行います。本ブログの過去の記事も、本ブログの終了までにフォーラムへの移行を進めて参ります。

&nbsp;

Office サポートチーム フォーラム

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/home?forum=officesupportteamja">https://social.msdn.microsoft.com/Forums/ja-JP/home?forum=officesupportteamja</a>

&nbsp;

フォーラムの運用については、以下のお知らせをご一読ください。

【お知らせ】 Office サポートチーム フォーラムについて

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/cf34463d-39ed-4b6f-a49c-85749383c443/123041236230693124251237912305office?forum=officesupportteamja">https://social.msdn.microsoft.com/Forums/ja-JP/cf34463d-39ed-4b6f-a49c-85749383c443/123041236230693124251237912305office?forum=officesupportteamja</a>

&nbsp;

これまで多くのお客様にご覧いただき、誠にありがとうございました。

読者の皆様のビジネスに多少なりとも貢献できておりましたら幸甚です。

ぜひ今後も Office サポートチーム フォーラムをご愛顧ください。

<span> </span>]]></content:encoded>
    </item>
    <item>
      <title>Office 開発におけるパフォーマンス トラブルシュート (その 2 : ボトルネックの特定)</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/office-perf-troubleshoot-part2</link>
      <pubDate>Thu, 12 Jul 2018 15:20:19 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1825</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/2affb5ed-a03a-45e9-8cc5-5f41ea7a691c/office?forum=officesupportteamja">https://social.msdn.microsoft.com/Forums/ja-JP/2affb5ed-a03a-45e9-8cc5-5f41ea7a691c/office?forum=officesupportteamja</a>

&nbsp;

&nbsp;

こんにちは、<span>Office </span>開発サポート チームの中村です。

<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/06/20/office-perf-troubleshoot-part1/">前回の投稿</a>で、<span>Office </span>開発のパフォーマンスに関する調査の進め方をご紹介しました。その中で予告した通り、今回の記事ではボトルネックとなるコードの特定手法について、特定作業に使えるサンプル コードとともに詳しく解説していきます。

今回も、「<span>Office </span>バージョンアップに伴い、これまで利用していたプログラムのパフォーマンスが低下した」という場合を例に説明します。コードの掲載などのため記事が長くなりますがご容赦ください。

&nbsp;

<strong>目次</strong>
<a href="#chapter1">1. 説明用サンプル プログラムの紹介</a>
<a href="#chapter2">2. デバッグ ログの追加<span> (</span>関数単位<span>)</span></a>
<a href="#chapter3">3. デバッグ ログの解析</a>
<a href="#chapter4">4. デバッグ ログの追加<span> (</span>行単位<span>)</span></a>
<a href="#chapter5">5. 関数単位の時刻ログ出力処理追加プログラム</a>

<a id="chapter1"></a>
<h4><span style="color: #333399"><strong>1. 説明用サンプル プログラムの紹介</strong></span></h4>
かなりシンプルな例ですが、以下の<span> VBA </span>マクロ<span> (TestProgram.xlsm) </span>を例に説明します。<span>(</span>この<span> VBA </span>マクロの内容で大きくパフォーマンスが低下するわけではありません。あくまでも調査の流れを説明するためのサンプルです。そして説明用にあえて効率の悪い処理などを書いています。<span>)</span>

前回の記事でも述べた通り、業務で使用するプログラムは膨大なステップ数となり、多くの場合は処理の内容ごとに関数を分け、これを呼び出すよう実装されています。今回のサンプルでは、<span>OpenWorkBook / SetValue / ChangeFontColor / CloseWorkBook </span>の<span> 4 </span>つの関数を呼び出しています。

[caption id="attachment_1835" align="alignnone" width="573"]<img width="573" height="362" class="size-full wp-image-1835" alt="図 1. テスト プログラム実行結果" src="https://msdnshared.blob.core.windows.net/media/2018/07/Testprogram_result.png" /> 図 1. テスト プログラム実行結果[/caption]

&nbsp;

<strong>&lt;</strong><strong>テスト プログラム 処理概要<span>&gt;</span></strong>

ボタン コントロールをクリックすると、データ ブック<span> (sample.xlsx) </span>を開き、<span>A1</span>～<span>A3 </span>セルの値を、このマクロ ブックの<span> A4~A6 </span>に転記します。その後、<span>A4~A6 </span>セルの書式をいくつか設定した後、ボタン コントロールの表示を「転記済み」に変更し、データブックを閉じて処理終了のメッセージボックスを表示します。

&nbsp;

<strong>テスト プログラム コード</strong>

&lt;Sheet1 オブジェクト<span>&gt;</span>
<pre><code>Private Sub CommandButton1_Click()
    Dim dataFilePath As String
    Dim dataBook As Workbook
    Dim i As Integer
    
    '① マクロ ブックのシート上のデータを取得
    dataFilePath = ThisWorkbook.Worksheets(1).Range("B1").Value
    
    '② データブックをオープン
    Set dataBook = OpenWorkBook(dataFilePath)
    If dataBook Is Nothing Then
        MsgBox "データ ブックが存在しないため処理中断"
        Exit Sub
    End If
    
    '③ データブックの A1 ～ A3 の値をマクロブックの A4 ～ A6 に転記
    For i = 1 To 3
        Call SetValue(dataBook, i)
    Next
    
    Call ChangeFormat '④ 書式設定を変更
    Call CloseBook(dataBook) '⑤ データ ブックを閉じる
    
    '⑥ 処理完了時にコントロールの Caption を変更
    CommandButton1.Caption = "転記済み"
    
    MsgBox "処理終了"
End Sub

Function OpenWorkBook(filePath As String) As Workbook
    Dim wb As Workbook
    If Dir(filePath) = "" Then
        Exit Function
    End If
    
    Set wb = Workbooks.Open(filePath)
    Set OpenWorkBook = wb
End Function

Sub SetValue(dataBook As Workbook, i As Integer)
    ThisWorkbook.Worksheets(1).Range("A" &amp; 3 + i).Value = dataBook.Worksheets(1).Range("A" &amp; i).Value
End Sub

Sub ChangeFormat()
    With ThisWorkbook.Worksheets(1).Range("A4:A6")
        .Font.ColorIndex = 3
        .Font.Bold = True
        .Borders.LineStyle = xlDouble
        .Borders.ColorIndex = 5
    End With
End Sub

Sub CloseBook(dataBook As Workbook)
    dataBook.Close
End Sub
</code></pre>
<a id="chapter2"></a>
<h4><strong><span style="color: #333399">2. デバッグ ログの追加 (関数単位)</span></strong></h4>
通常、パフォーマンスが低下したと気づいたときの出発点では、「<span>CommandButton1_Click() </span>全体の処理が遅くなった」という状況から調査を開始するかと思います。この段階では、①～⑥のどこが遅くなったのか、まだ分かりません。またさらに、例えば<span> ChangeFormat() </span>の中であれば、いくつかの書式を変更しているので、どの書式変更が遅いのかが分かりません。

前回の記事で述べたように、ボトルネックとなる処理の内容によって、検討される対応方法は異なります。このため、まずはこのコードの中のどこが遅いのか、<span>1 </span>行レベルでの特定を行うことを目指します。

&nbsp;

いきなり<span> 1 </span>行レベルの特定を行うのは効率が悪いので、まずは、大まかに関数単位で切り分けを行うことをお勧めします。

ここで役立つのが、「<a href="#chapter5">5. 関数単位の時刻ログ出力処理追加プログラム</a>」のコードです。<span>5. </span>で後述する使い方に従ってこのプログラムを実行すると、先述のテスト プログラムは以下のようなコードに変更されます。

&nbsp;

&lt;Sheet1 オブジェクト<span>&gt;</span>
<pre><code>Private Sub CommandButton1_Click()
LogWriteToBuffer "IN,Sheet1,CommandButton1_Click"
    Dim dataFilePath As String
    Dim dataBook As Workbook
    Dim i As Integer
    
    '① マクロ ブックのシート上のデータを取得
    dataFilePath = ThisWorkbook.Worksheets(1).Range("B1").Value
    
    '② データブックをオープン
    Set dataBook = OpenWorkBook(dataFilePath)
    If dataBook Is Nothing Then
        MsgBox "データ ブックが存在しないため処理中断"
LogWriteToBuffer "OUT,Sheet1,CommandButton1_Click"
        Exit Sub
    End If
    
    '③ データブックの A1 ～ A3 の値をマクロブックの A4 ～ A6 に転記
    For i = 1 To 3
        Call SetValue(dataBook, i)
    Next
    
    Call ChangeFormat '④ 書式設定を変更
    Call CloseBook(dataBook) '⑤ データ ブックを閉じる
    
    '⑥ 処理完了時にコントロールの Caption を変更
    CommandButton1.Caption = "転記済み"
    
    MsgBox "処理終了"
LogWriteToBuffer "OUT,Sheet1,CommandButton1_Click"

'★以下は手動で追加
LogWrite logOutputCollection
End Sub

Function OpenWorkBook(filePath As String) As Workbook
LogWriteToBuffer "IN,Sheet1,OpenWorkBook"
    Dim wb As Workbook
    If Dir(filePath) = "" Then
LogWriteToBuffer "OUT,Sheet1,OpenWorkBook"
        Exit Function
    End If
    
    Set wb = Workbooks.Open(filePath)
    Set OpenWorkBook = wb
LogWriteToBuffer "OUT,Sheet1,OpenWorkBook"
End Function

Sub SetValue(dataBook As Workbook, i As Integer)
LogWriteToBuffer "IN,Sheet1,SetValue"
    ThisWorkbook.Worksheets(1).Range("A" &amp; 3 + i).Value = dataBook.Worksheets(1).Range("A" &amp; i).Value
LogWriteToBuffer "OUT,Sheet1,SetValue"
End Sub

Sub ChangeFormat()
LogWriteToBuffer "IN,Sheet1,ChangeFormat"
    With ThisWorkbook.Worksheets(1).Range("A4:A6")
        .Font.ColorIndex = 3
        .Font.Bold = True
        .Borders.LineStyle = xlDouble
        .Borders.ColorIndex = 5
    End With
LogWriteToBuffer "OUT,Sheet1,ChangeFormat"
End Sub

Sub CloseBook(dataBook As Workbook)
LogWriteToBuffer "IN,Sheet1,CloseBook"
    dataBook.Close
LogWriteToBuffer "OUT,Sheet1,CloseBook"
End Sub</code></pre>
&lt;Module1 オブジェクト<span>&gt; </span>※ 共通関数記述用に追加されます
<pre><code>Public logOutputCollection As Collection
Public Sub LogWriteToBuffer(strMsg As String)
   If logOutputCollection Is Nothing Then
      Set logOutputCollection = New Collection
   End If
   logOutputCollection.Add getNowWithMS &amp; "," &amp; strMsg
End Sub

Public Sub LogWrite(logOutputCollection As Collection)
    Dim j As Integer
    Dim iFileNo As Integer
    iFileNo = FreeFile
    Open "C:\temp\VBAPerf.log" For Append As #iFileNo
    If Not logOutputCollection Is Nothing Then
        For j = 1 To logOutputCollection.Count
           Print #iFileNo, logOutputCollection(j)
        Next
    End If
    Close #iFileNo
End Sub

Function getNowWithMS() As String
   Dim dtmNowTime      ' 現在時刻
   Dim lngHour         ' 時
   Dim lngMinute       ' 分
   Dim lngSecond       ' 秒
   Dim lngMilliSecond  ' ミリ秒
   dtmNowTime = Timer
   lngMilliSecond = dtmNowTime - Fix(dtmNowTime)
   lngMilliSecond = Right("000" &amp; Fix(lngMilliSecond * 1000), 3)
   dtmNowTime = Fix(dtmNowTime)
   lngSecond = Right("0" &amp; dtmNowTime Mod 60, 2)
   dtmNowTime = dtmNowTime \ 60
   lngMinute = Right("0" &amp; dtmNowTime Mod 60, 2)
   dtmNowTime = dtmNowTime \ 60
   lngHour = Right("0" &amp; dtmNowTime, 2)
   getNowWithMS = lngHour &amp; ":" &amp; lngMinute &amp; ":" &amp; lngSecond &amp; "." &amp; lngMilliSecond
End Function</code></pre>
&nbsp;

Sub や<span> Function </span>に入った直後と出る直前に、「<span>LogWriteToBuffer "IN </span>または<span>OUT,&lt;</span>モジュール名<span>&gt;,&lt;</span>関数名<span>&gt;"</span>」という処理が自動的に追加されているのがお分かりでしょうか。また、標準モジュールにモジュールが追加され、ログ出力関数<span> (LogWriteToBuffer() / LogWrite()) </span>と、時刻をミリ秒まで取得する関数<span> (getNowWithMS()) </span>が追加されます。

<a id="chapter3"></a>
<h4><span style="color: #333399"><strong>3. デバッグ ログの解析</strong></span></h4>
この状態でプログラムを実行すると、「<a href="#chapter5"><span>5. </span>関数単位の時刻ログ出力処理追加プログラム</a>」の中で指定しているログ ファイル<span> (</span>上記では<span> C:\temp\VBAPerf.log) </span>に以下のようにログが出力されます。

&nbsp;

&lt;ログ出力結果 サンプル<span>&gt; (</span>数値は説明用に作成しているので、実際はこんなにかかりません。<span>)</span>
<pre><code>19:08:08.562,IN,Sheet1,CommandButton1_Click
19:08:08.562,IN,Sheet1,OpenWorkBook
19:08:09.210,OUT,Sheet1,OpenWorkBook
19:08:09.210,IN,Sheet1,SetValue
19:08:10.230,OUT,Sheet1,SetValue
19:08:10.230,IN,Sheet1,SetValue
19:08:11.732,OUT,Sheet1,SetValue
19:08:12.733,IN,Sheet1,SetValue
19:08:14.221,OUT,Sheet1,SetValue
19:08:14.221,IN,Sheet1,ChangeFormat
19:08:23.123,OUT,Sheet1,ChangeFormat
19:08:23.125,IN,Sheet1,CloseBook
19:08:23.532,OUT,Sheet1,CloseBook
19:08:23.541,OUT,Sheet1,CommandButton1_Click</code></pre>
&nbsp;

このログを分析してどこで時間がかかっているかを特定していきます。<span>Excel </span>にカンマを区切り文字として貼り付けると、<span>Excel </span>の機能やシート関数を使って様々な観点で分析できます。

(例<span>)</span>
<ul>
 	<li>直前の処理との時間差<span> (</span>「<span>=A3-A2</span>」ような数式で求められます<span>) </span>を算出し、特に時間がかかっている箇所を見つける</li>
 	<li>関数名のカウントを数え、繰り返し行われている処理を特定する</li>
</ul>
&nbsp;

今回の場合、上記のログを解析すると、以下のあたりがボトルネックとなっていることが分かります。
<ol>
 	<li>ChangeFormat 関数の<span> IN ~ OUT </span>の間が<span> 1 </span>回で<span> 8.902 </span>秒かかっている</li>
 	<li>SetValue 関数の<span> IN </span>～<span> OUT </span>の間が <span>3 </span>回の合計で約<span> 4 </span>秒かかっている</li>
</ol>
<a id="chapter4"></a>
<h4><span style="color: #333399"><strong>4. デバッグ ログの追加 (行単位)</strong></span></h4>
SetValue 関数の中は<span> 1 </span>行しか処理がないのでこれ以上の切り分けは必要ありませんが、<span>ChangeFormat </span>関数の中ではいくつかの処理を行っているので、さらにボトルネックとなる処理を特定します。ここは手動で<span> 1 </span>行ごとにログを追加します。関数内のコード量に応じて、いきなり<span> 1 </span>行単位にログを追加するのではなく、何段階かに分けて絞り込んでも良いかと思います。

<strong>ログ追加の例</strong>
<pre><code>Sub ChangeFormat()
LogWriteToBuffer "IN,Sheet1,ChangeFormat"
    With ThisWorkbook.Worksheets(1).Range("A4:A6")
        .Font.ColorIndex = 3
LogWriteToBuffer "①,Sheet1,FontColorIndex"
        .Font.Bold = True
LogWriteToBuffer "②,Sheet1,FontBold"
        .Borders.LineStyle = xlDouble
LogWriteToBuffer "③,Sheet1,BorderLineStyle"
        .Borders.ColorIndex = 5
LogWriteToBuffer "④,Sheet1,BorderColorIndex"
    End With
LogWriteToBuffer "OUT,Sheet1,ChangeFormat"
End Sub</code></pre>
このようにログを追加したプログラムを再度実行し、<span>3. </span>と同じようにログを解析していきます。

注<span> : </span>本記事のログ出力処理追加サンプルプログラムでは、<span>1 </span>回の<span> Excel </span>起動で複数回現象再現処理が実行されることは想定していません。<span>(</span>出力ログのコレクションが前回実行分と重複します<span>) </span>実行の都度、<span>Excel </span>プログラムを開き直してください。

&nbsp;

<strong><u>対応方法の検討について</u></strong>

これについては前回の記事で詳しく説明しているため今回はあまり触れませんが、例えば<span> Font.ColorIndex </span>の設定箇所が遅かったとします。この場合、前回の記事でいう<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/06/20/office-perf-troubleshoot-part1/#chapter3-1"><span>3-1. </span>ボトルネックとなる処理の速度改善</a>として、<span>Font.ColorIndex </span>の代わりに <span>Font.Color </span>だったらどうか？などを試すことが検討できます。また、システム全体の流れによっては、マクロ ブックのテンプレートの段階でフォント色を設定しておき、マクロ内では変更しないといった対応も検討できるかもしれません。

SetValue については、ループ処理ではなく複数セルをまとめて貼り付けることが効果的です<span> (</span>前回記事<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/06/20/office-perf-troubleshoot-part1/#chapter3-2"><span> 3-2. </span>プログラム構成の見直し</a> に当たります<span>)</span>。

また、もし例えば⑤のコントロールの<span> Caption </span>変更が遅いようであれば、フォーム コントロールに変更したらどうか<span> (</span>前回記事<span> 3-1. </span>ボトルネックとなる処理の速度改善<span>)</span>、<span>Caption </span>変更以外の方法で処理完了が分かるようにできないか<span> (</span>前回記事<span> 3-2. </span>プログラム構成の見直し<span>)</span>、などの対応方法が検討できます。

<a id="chapter5"></a>
<h4><span style="color: #333399"><strong>5. 関数単位の時刻ログ出力処理追加プログラム</strong></span></h4>
<span style="color: #000000">2. プログラム上のボトルネックの特定 で触れた、関数単位にログ出力処理を自動追加できるサンプル コードを以下に記載します。VBA の標準モジュールなどにコピーして利用できます。</span>

なお、このサンプル コードはあらゆる<span> VBA </span>上の記述方法に対応することを保証するものではありません。必要に応じて、お客様ご自身で修正してご利用ください。

&nbsp;

<strong>利用上の諸注意</strong>
<ul>
 	<li><span style="color: #ff0000">このサンプル コードの実行時</span>、ログ出力処理を追加する対象のファイルを開く<span> Office </span>アプリケーションのオプション設定で、<span>[</span>セキュリティ センター<span>] – [</span>セキュリティ センターの設定<span>] – [</span>マクロの設定<span>] – <span style="color: #ff0000">[VBA </span></span><span style="color: #ff0000">プロジェクト オブジェクト モデルへのアクセスを信頼する] を有効にする必要があります。</span><span>(</span>パフォーマンス計測時には有効にする必要はありません<span>)</span></li>
 	<li>VBAProject を参照・変更するため、<span>VBAProject </span>のパスワードは解除してください。</li>
 	<li>ご利用の際は、<span>AddToLogFunc() </span>内初めの<span> 2 </span>行の<span> Const </span>定義をご自身の環境に合わせて変更してください。</li>
 	<li>VBA 関数がどの順序で呼び出されるかは判断できないため、処理全体の最後に行うログのファイル出力処理呼び出しが含まれていません。<span style="color: #ff0000">手動で、処理全体の最後に「LogWrite logOutputCollection」 を追加してください。</span>(2. のサンプルでは<span> CommandButton1_Click() </span>の最後に「<span>'</span>★以下は手動で追加」とコメントを入れている箇所です。<span>)</span></li>
</ul>
&nbsp;

<strong>利用手順</strong>

事前準備<span> : </span>上記の通り、<span>Excel </span>のオプション変更と<span> VBAProject </span>のパスワード解除を行っておきます。
<ol>
 	<li>新規<span> Excel </span>ブックの標準モジュールに以下のサンプル コードを貼り付けます。</li>
 	<li>AddToLogFunc() 内の<span> Const </span>定義をご自身の環境に合わせて変更します。</li>
 	<li>AddToLogFunc() を実行します。ログ追加対象ファイルが開かれ、ログの追加が行われます。</li>
 	<li>"ログ出力処理追加完了<span> : </span>該当ファイルを別名で保存し、<span>VBA </span>の内容に問題がないか確認してください<span>" </span>と表示されたらVBE でログ追加対象ファイルのコードを開き、現象再現手順の処理全体の最後に「<span>LogWrite logOutputCollection</span>」を追記します。</li>
 	<li>ログ追加対象ファイルに別名を付けて保存します。</li>
 	<li>Excel をいったん閉じ、ログを追加したファイルを再度開いて再現手順を実行します。</li>
 	<li>出力されたログファイル<span> (</span>手順<span> 2. </span>で設定したファイル パスに出力<span>) </span>を開き、ログを解析します。</li>
</ol>
&nbsp;

<strong>サンプル コード</strong>
<pre><code>'2018/7/12 公開版
'注 : このログ追加コードは、":" を用いて複数行を 1 行にまとめたコードには対応していません。

'Exit Sub / Exit Function へのログ出力処理追加
Function CheckExit(CurrentVBComponent As Object, strProcName As String, InProcCurrentLine As Long)

    Dim strCurrentCode As String
    Dim FoundPos As Long

    strCurrentCode = Trim(CurrentVBComponent.CodeModule.Lines(InProcCurrentLine, 1))

    'コメント行は除外
    If Left(strCurrentCode, 1) = "'" Or UCase(Left(strCurrentCode, 4)) = "REM " Then
        Exit Function
    End If

    'If xxx Then Exit Sub のような行の先頭以外に Exit がある書き方を考慮し InStr で合致確認
    FoundPos = InStr(strCurrentCode, "Exit ")
    
    '"Exit " に合致しても以下のケースは除外
    'a) Exit Sub の位置が先頭以外で、前にスペースがなく "xxxExit " のように文字列がある場合
    'b) 行の途中からコメントで、コメント部分に "Exit " がある場合
    'c) "Exit Sub" と "Exit Function" 以外の "Exit aaa" のような場合
    If FoundPos &gt; 0 Then
        If (FoundPos &gt; 1 And InStr(strCurrentCode, " Exit ") = 0) _
            Or (InStr(strCurrentCode, "'") &gt; 0 And InStr(strCurrentCode, "'") &lt; FoundPos) _
            Or (InStr(strCurrentCode, "Exit Sub") = 0 And InStr(strCurrentCode, "Exit Function") = 0) Then
            FoundPos = 0 'Exit Sub / Exit Function は見つからなかったものとみなす
        End If
    End If

    'Exit Sub / Exit Function のいずれかがある場合、その前に関数を抜けるログ出力処理追加
    If FoundPos &gt; 0 Then
    
        'If xxx Then Exit Sub の書き方を考慮しコード整形
        If Left(strCurrentCode, 3) = "If " Then
        
            'いったん End If を入れる (If xxx Then Exit Sub + 改行 + End If)
            strCurrentCode = strCurrentCode &amp; vbCrLf &amp; "End If"
            
            '以下のように If 文を分割してコードを置き換え
            'Exit Sub の手前まで (If xxx Then )
            'ログ出力 (LogWriteToBuffer "OUT : " &amp; CurrentVBComponent.Name &amp; " : " &amp; strProcName &amp; "")
            'Exit Sub 以降 (Exit Sub + 改行 + End If)
            CurrentVBComponent.CodeModule.ReplaceLine InProcCurrentLine, _
                        Left(strCurrentCode, FoundPos - 1) &amp; vbCrLf &amp; _
                        "LogWriteToBuffer ""OUT," &amp; CurrentVBComponent.Name &amp; "," &amp; strProcName &amp; """" &amp; vbCrLf &amp; _
                        Mid(strCurrentCode, FoundPos)
        Else
            'その他通常の Exit の場合は直前に関数を抜けるログ追加
            CurrentVBComponent.CodeModule.InsertLines InProcCurrentLine, "LogWriteToBuffer ""OUT," &amp; CurrentVBComponent.Name &amp; "," &amp; strProcName &amp; """"
        End If
    End If
    
End Function


'メイン モジュール
Sub AddLogToFunc()
    
    '****************************************************
    'お客様環境に合わせて書き換えてください
    Const szBookFile = "C:\work\testProgram.xlsm" 'ログ出力処理を追加するファイルのフルパス
    Const szLogFile = "C:\work\VBAPerf.log" 'ログ出力ファイルのフルパス
    '****************************************************
    
    Const vbext_ct_StdModule = 1 'VBComponent Type 定数 : 標準モジュール
    Const vbext_pk_Proc = 0 'prockind 定数 : プロパティ プロシージャ以外のすべてのプロシージャ
    
    Dim xlBook As Workbook
    Dim CurrentVBComponent As Object 'VBComponent
    Dim TotalLine As Long
    Dim CurrentLine As Long
    Dim strProcName As String
    Dim strCurrentCode As String
    Dim ProcStartLine As Long
    Dim ProcEndLine As Long
    Dim InProcCurrentLine As Long
    Dim FoundPos As Long
    Dim strFunc As String
    
    Application.EnableEvents = False
    
    Set xlBook = Workbooks.Open(szBookFile) 'ログ出力処理追加対象ブック オープン

    ' 対象ブックに含まれる各モジュール内関数の最初と最後にログ出力関数呼び出しを追加
    For Each CurrentVBComponent In xlBook.VBProject.VBComponents
    
        TotalLine = CurrentVBComponent.CodeModule.CountOfLines
        
        'コード末尾から 1 行ごとに確認
        For CurrentLine = TotalLine To 1 Step -1
        
            strProcName = CurrentVBComponent.CodeModule.ProcOfLine(CurrentLine, vbext_pk_Proc) 'その行が属するプロシージャ名を取得
            strCurrentCode = LTrim(CurrentVBComponent.CodeModule.Lines(CurrentLine, 1))
            
            'End で始まる場合 : そのプロシージャの初めと終わりに処理追加
            If strProcName &lt;&gt; Empty And Left(strCurrentCode, 4) = "End " Then
            
                ProcStartLine = CurrentVBComponent.CodeModule.ProcBodyLine(strProcName, vbext_pk_Proc) + 1 'プロシージャの先頭行を取得
                ProcEndLine = CurrentLine
                
                'End 行の前に関数を抜けるログ出力処理追加
                CurrentVBComponent.CodeModule.InsertLines ProcEndLine, "LogWriteToBuffer ""OUT," &amp; CurrentVBComponent.Name &amp; "," &amp; strProcName &amp; """"
                'プロシージャ開始行の直後に関数に入るログ出力処理追加
                CurrentVBComponent.CodeModule.InsertLines ProcStartLine, "LogWriteToBuffer ""IN," &amp; CurrentVBComponent.Name &amp; "," &amp; strProcName &amp; """"
                
                'さらにこのプロシージャ内の途中で処理追加すべき箇所 (Exit Sub / Exit Function) をチェック
                '(OUT ログ追加により CurrentLine は End Sub の 1 行前を指す)
                For InProcCurrentLine = CurrentLine To ProcStartLine Step -1
                    CheckExit CurrentVBComponent, strProcName, InProcCurrentLine
                Next
                
                'このプロシージャの処理は終わっているためプロシージャ先頭までスキップ
                CurrentLine = ProcStartLine - 1
                
            End If
        Next
    Next

    '*************************************************************************
    'サブ関数追加処理
    '*************************************************************************
    
    ' ファイル出力時のディスク アクセスによるパフォーマンス影響を抑えるため、
    ' 処理実行中のログはいったん配列に書き込み、最後にファイル出力する

    'ログを配列に格納するための関数
    strFunc = "" &amp; vbCrLf &amp; _
              "Public logOutputCollection As Collection" &amp; vbCrLf &amp; _
              "Public Sub LogWriteToBuffer(strMsg As String)" &amp; vbCrLf &amp; _
              "   If logOutputCollection Is Nothing Then" &amp; vbCrLf &amp; _
              "      Set logOutputCollection = New Collection" &amp; vbCrLf &amp; _
              "   End If" &amp; vbCrLf &amp; _
              "   logOutputCollection.Add getNowWithMS &amp; "","" &amp; strMsg" &amp; vbCrLf &amp; _
              "End Sub"

    '配列からログファイルへの出力のための関数
    strFunc = strFunc &amp; vbCrLf &amp; _
              "" &amp; vbCrLf &amp; _
              "Public Sub LogWrite(logOutputCollection As Collection)" &amp; vbCrLf &amp; _
              "    Dim j As Integer" &amp; vbCrLf &amp; _
              "    Dim iFileNo As Integer" &amp; vbCrLf &amp; _
              "    iFileNo = FreeFile" &amp; vbCrLf &amp; _
              "    Open ""[LOG_FILE]"" For Append As #iFileNo" &amp; vbCrLf &amp; _
              "    If Not logOutputCollection Is Nothing Then" &amp; vbCrLf &amp; _
              "        For j = 1 To logOutputCollection.Count" &amp; vbCrLf &amp; _
              "           Print #iFileNo,  logOutputCollection(j)" &amp; vbCrLf &amp; _
              "        Next" &amp; vbCrLf &amp; _
              "    End If" &amp; vbCrLf &amp; _
              "    Close #iFileNo" &amp; vbCrLf &amp; _
              "End Sub"


    '現在時刻取得関数
    strFunc = strFunc &amp; vbCrLf &amp; _
              "" &amp; vbCrLf &amp; _
              "Function getNowWithMS() As String" &amp; vbCrLf &amp; _
              "   Dim dtmNowTime      ' 現在時刻" &amp; vbCrLf &amp; _
              "   Dim lngHour         ' 時" &amp; vbCrLf &amp; _
              "   Dim lngMinute       ' 分" &amp; vbCrLf &amp; _
              "   Dim lngSecond       ' 秒" &amp; vbCrLf &amp; _
              "   Dim lngMilliSecond  ' ミリ秒" &amp; vbCrLf &amp; _
              "   dtmNowTime = Timer" &amp; vbCrLf &amp; _
              "   lngMilliSecond = dtmNowTime - Fix(dtmNowTime)" &amp; vbCrLf &amp; _
              "   lngMilliSecond = Right(""000"" &amp; Fix(lngMilliSecond * 1000), 3)" &amp; vbCrLf &amp; _
              "   dtmNowTime = Fix(dtmNowTime)" &amp; vbCrLf &amp; _
              "   lngSecond = Right(""0"" &amp; dtmNowTime Mod 60, 2)" &amp; vbCrLf &amp; _
              "   dtmNowTime = dtmNowTime \ 60" &amp; vbCrLf &amp; _
              "   lngMinute = Right(""0"" &amp; dtmNowTime Mod 60, 2)" &amp; vbCrLf &amp; _
              "   dtmNowTime = dtmNowTime \ 60" &amp; vbCrLf &amp; _
              "   lngHour = Right(""0"" &amp; dtmNowTime, 2)" &amp; vbCrLf &amp; _
              "   getNowWithMS = lngHour &amp; "":"" &amp; lngMinute &amp; "":"" &amp; lngSecond &amp; ""."" &amp; lngMilliSecond" &amp; vbCrLf &amp; _
              "End Function"


    strFunc = Replace(strFunc, "[LOG_FILE]", szLogFile) '冒頭で設定したログファイル パスに書き換え
    xlBook.VBProject.VBComponents.Add(vbext_ct_StdModule).CodeModule.AddFromString strFunc '新しい標準モジュールを作成し関数を追記

    Application.EnableEvents = True
    
    MsgBox "ログ出力処理追加完了 : 該当ファイルを別名で保存し、VBA の内容に問題がないか確認してください"
    
End Sub
</code></pre>
&nbsp;

今回の投稿は以上です。

<strong>本情報の内容<span> (</span>添付文書、リンク先などを含む<span>) </span>は、作成日時点でのものであり、予告なく変更される場合があります</strong><strong>。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Office 開発におけるパフォーマンス トラブルシュート (その 1 : 概要と対処方法)</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/office-perf-troubleshoot-part1</link>
      <pubDate>Wed, 20 Jun 2018 17:09:10 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1795</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/8e49ab2a-2f09-47c8-9540-3744203dcdbb/office-1-">https://social.msdn.microsoft.com/Forums/ja-JP/8e49ab2a-2f09-47c8-9540-3744203dcdbb/office-1-</a>

&nbsp;

こんにちは、<span>Office </span>開発サポート チームの中村です。

<strong><span style="color: #ff0000">2018/7/12 Update</span></strong>
<span style="color: #339966">ボトルネック特定手法についてのパート 2 記事を公開しました。</span>

&nbsp;

Office 開発において、「期待するパフォーマンスが出ない」「利用する<span> Office </span>のバージョンによってパフォーマンスが低下する」といったお問い合わせを頂くことがあります。今回の記事では、このような状況で改善を図るためにどのように調査・検討を進めればよいかを記載します。

今回は全体の流れと Office におけるパフォーマンスの考え方などを紹介しています。ボトルネックの特定手法については、以下のパート 2 の記事をご参照ください。

タイトル : Office 開発におけるパフォーマンス トラブルシュート (その 2 : ボトルネックの特定)
アドレス : <a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/07/12/office-perf-troubleshoot-part2/">https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/07/12/office-perf-troubleshoot-part2/</a>

&nbsp;

<strong><b>目次</b></strong>
<a href="#chapter1">1. はじめに<span> : Office </span>におけるパフォーマンス</a>
<a href="#chapter2">2. プログラム上のボトルネックの特定</a>
<a href="#chapter3">3. 対処方法の検討</a>
<p style="padding-left: 30px"><a href="#chapter3-1">3-1. ボトルネックとなる処理の速度改善</a>
<a href="#chapter3-2">3-2. プログラム構成の見直し</a>
<a href="#chapter3-3">3-3. プログラム全体のパフォーマンス チューニング</a>
<a href="#chapter3-4">3-4. 他の言語から VBA に変更する</a>
<a href="#chapter3-5">3-5. マシン リソースの増強</a></p>

<a id="chapter1"></a>
<h4><span style="color: #333399"><strong>1. はじめに : Office におけるパフォーマンス</strong></span></h4>
Office はデスクトップ アプリケーションとして設計されています。このため、ユーザー操作では大きく気にならないような短い処理時間のパフォーマンスは、機能設計上それほど優先される考慮事項ではありません。このため、例えばデータベース製品のように、大量の要求が常に送られれてくることを想定した精度のパフォーマンス設計は行われていません。プログラムにより大量の処理を繰り返し行うと、ユーザー操作では許容される程度の小さな積み重ねが全体としてパフォーマンスに大きく影響を与えることがあります。

また例えば、「<span>Office 2010 </span>から<span> Office 2016 </span>にバージョンアップしたら以前の処理時間の<span> 3 </span>倍になった」といったご報告を頂くことがあります。しかしながら、これは製品の設計上、やむを得ない変更であることが多いです。

アプリケーションのバージョンアップを行うと、より新しい製品だからパフォーマンスも向上しているだろう、と考えられることがありますが、必ずしもそうではありません。セキュリティ脆弱性への対応、機能拡張、不具合の修正などによって、どちらかといえば<span> Office </span>プログラム はバージョンを重ねるごとに複雑化していきます。同じメソッドの呼び出しであっても、そのメソッドにより実行される<span> Office </span>内部の実装が複雑になる<span> (</span>コード量が増える<span>) </span>と、パフォーマンスは低下します。

例えば、ファイルの<span> Open </span>メソッドが以前のバージョンの<span> Office </span>より遅くなるという場合、ファイルを開く際にそのファイルがセキュリティ上問題ないかのチェック処理の追加、新しく追加されたリッチな表現の描画などの影響で遅くなる、といったイメージです。
パフォーマンス低下が著しい場合には、<span>Office </span>製品としても可能な限りパフォーマンス向上の対応を行います。ただ、これは単純に処理時間が<span> x </span>倍になった、というだけではなく、実際の時間としてユーザー利用で耐えうる処理時間であるか、また、その処理がどの程度一般的に利用されるか、といった観点から判断しています。先述のように、ユーザー操作では気にならない程度の低下と判断されるような場合は、ある程度のパフォーマンス低下は仕様上想定されたものとなります。

先程の例でいえば、ファイル オープンが<span> 1 </span>秒から<span> 3 </span>秒に延びたとします。ファイルのオープンは一般的な操作ですが、ユーザー操作で開いては閉じ、を短時間で繰り返し行うことは稀で、<span>1 </span>度ファイルを開いたらしばらくそのファイル上で作業を行うことが一般的と考えられます。このような状況で、<span>1 </span>回のオープンあたり<span> 2 </span>秒の増加はユーザー操作上大きく使用感を損なうほどではなく、機能向上とのトレードオフとして許容される場合がある、ということです。

本記事では、このような背景をふまえた上で、パフォーマンス向上を図るための調査手法、とり得る対応方法について記載します。個別の現象は、弊社サポートでないと判断が難しい部分もありますが、調査や対処の進め方のイメージを掴んでいただいたり、サポートのご利用が難しい開発者の皆様へ、少しでも解決にお役立ていただければと思います。

ここからは、「<span>Office </span>バージョンアップに伴い、これまで利用していたプログラムのパフォーマンスが低下した」というシナリオを想定して記載していきます。

<a id="chapter2"></a>
<h4><span style="color: #333399"><strong>2. プログラム上のボトルネックの特定</strong></span></h4>
ビジネスで利用される<span> Office </span>を利用するプログラムは多くの場合、数百～数千行に及ぶ複雑なプログラムで構成されています。<span>Office </span>をバージョンアップすると、このプログラム全体としてパフォーマンスが以前より低下することが分かったとします。ここで次に行うべき作業は、ボトルネックとなる処理の特定です。

特定方法として、<strong><u>プログラム処理の各所で時刻付きのデバッグ ログを出力することが有効</u></strong>です。このようなログ出力処理を追加してプログラムを実行し、ログからどの処理で時間がかかっているのかを確認していきます。ここでは、<span>Workbooks.Open </span>が遅い、<span>Range("A1").Value = "aaa" </span>が遅い、といったように<span> 1 </span>つの関数レベルまで絞り込むのが理想です。そうすると、次の対処方法が検討しやすくなります。

とはいえ、大きなプログラムにデバッグ ログを追加する作業は容易ではないと思います。これについては、<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2018/07/12/office-perf-troubleshoot-part2/">次の記事</a>でログ出力処理を自動追加するコードのサンプル<span> (VBA </span>向け<span>) </span>や、具体的な特定の進め方について詳しく記載しています。

<a id="chapter3"></a>
<h4><span style="color: #333399"><strong>3. 対処方法の検討</strong></span></h4>
ボトルネックとなっている処理の特定を行ったら、次に、その処理のパフォーマンス向上が可能かの調査を行います。パフォーマンスを向上させる方法として取り得るアプローチはいくつか考えられます。

<a id="chapter3-1"></a>
<h5><span style="color: #333399"><strong>3-1. </strong><strong>ボトルネックとなる処理の速度改善</strong></span></h5>
ボトルネックとなる処理によっては、例えばメソッドの呼び出し引数の変更、類似の別の関数の利用、<span>Office </span>のオプション設定の変更、文書やワークシートなどの構成の見直しなどの方法によってパフォーマンスが改善できる場合があります。

ただ、何が有効であるかは、ボトルネックとなる処理によって様々なので一概にお伝えできず、関数のヘルプを見ながら動作が変わりそうな引数を試す、オプション設定を見て影響がありそうな設定を変更してみる、というように、推測を基に試していただくことになります。既知の現象として、サポート技術情報などで情報が公開されている場合もあります。

<a id="chapter3-2"></a>
<h5><span style="color: #333399"><strong>3-2. </strong><strong>プログラム構成の見直し</strong></span></h5>
ボトルネックとなる処理自体を速くすることは難しい場合、その処理の実行回数を減らしたり、同じ結果を得られる別の実装方法に変更するといった方法が検討できます。

例えば、<span>Excel </span>でセルに値を設定する処理がボトルネックとなっており、現在の実装では数千個のセルに<span> 1 </span>つずつループ処理で値を書き出しているような場合を考えます。この処理を、二次元配列にセルに書き出すデータを全て格納した上で、配列のデータを一括してセルに出力する実装に変更すると、ボトルネックとなる処理の実行回数が数千回から<span> 1 </span>回になり、パフォーマンスは向上します。

参考<span>) </span>二次元配列を用いたセル操作については公開情報にサンプル コードなどの記載があります。

タイトル<span> : Visual Basic .NET </span>で<span> Excel </span>を自動化し、配列による範囲内へのデータ入力および範囲内からのデータ取得を行う方法
アドレス<span> : <a href="https://support.microsoft.com/ja-jp/kb/302094">https://support.microsoft.com/ja-jp/kb/302094</a> </span>

タイトル<span> : Visual C# </span>で<span> Excel </span>を自動化して、配列による範囲内へのデータ入力および範囲内からのデータ取得を行う方法
アドレス<span> : <a href="https://support.microsoft.com/ja-jp/kb/302096">https://support.microsoft.com/ja-jp/kb/302096</a></span>

また別の例として、セルへの値書き込みが、今回の処理結果を次回起動時に引き継ぐためのプログラム用の情報保持が目的である、といった場合、必ずしもセルに書き込む必要はありません。ブックのプロパティに書き込む、他のテキストファイルに出力する、などの保持方法に変更するといったアイデアもあります。<span>(</span>このような方法が実際にパフォーマンス向上となるかは状況によります。あくまで、考え方の例となります。<span>)</span>
このように、セルへの値書き込み処理自体を速くすることはできない場合も、その処理によって実現したい目的を満たす他の実装方法にすることでパフォーマンス向上を図るアプローチが検討できます。

<a id="chapter3-3"></a>
<h5><span style="color: #333399"><strong>3-3. </strong><strong>プログラム全体のパフォーマンス チューニング</strong></span></h5>
ボトルネック箇所の変更が難しい場合、プログラムの他の箇所のパフォーマンスを向上させることで全体の処理時間を短縮し、パフォーマンス要件を満たす方法も検討できます。

例えば、<span>3-2. </span>で記載した配列を用いたセル操作は、それ自体がボトルネックでない場合にも、大量のセル操作を含むプログラムのパフォーマンス改善に大きく貢献できます。また例えば、<span>Application.ScreenUpdating </span>プロパティをプログラムの処理開始時に<span> False </span>に設定すると、プログラム実行中の描画処理が抑止され、一般的にパフォーマンスが向上します。

このような一般的なパフォーマンス向上施策については、以下の公開情報でご紹介しています。<span>(</span>情報が古いバージョンの<span> Office </span>向けのものもありますが、ほとんどの内容が<span> Office </span>バージョンによらず有効です。<span>)</span>

&nbsp;

タイトル<span> : Excel </span>のパフォーマンス<span>: </span>パフォーマンスの障害物を最適化するためのヒント
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/excel-tips-for-optimizing-performance-obstructions">https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/excel-tips-for-optimizing-performance-obstructions</a></span>

タイトル<span> : </span>少ないメモリを使用するように、<span>Excel </span>ブックをクリーンアップする方法
アドレス<span> : <a href="https://support.microsoft.com/ja-jp/help/3070372">https://support.microsoft.com/ja-jp/help/3070372</a> (</span>日本語機械翻訳版<span>)</span>
アドレス<span> : <a href="https://support.microsoft.com/en-us/help/3070372">https://support.microsoft.com/en-us/help/3070372</a> (</span>英語版<span>)</span>

タイトル<span> : Word 2007 </span>と<span> Word 2010 </span>を最適化する方法
アドレス<span> : <a href="https://support.microsoft.com/ja-jp/help/918793">https://support.microsoft.com/ja-jp/help/918793</a> (</span>日本語機械翻訳版<span>)</span>
アドレス<span> : <a href="https://support.microsoft.com/en-us/help/918793">https://support.microsoft.com/en-us/help/918793</a> (</span>英語版<span>)</span>

タイトル<span> : </span>プレゼンテーションのパフォーマンスを向上させるためのヒント
アドレス<span> : <a href="https://support.office.microsoft.com/ja-jp/article/34c82835-5f23-4bf0-98cc-72235bbd2949">https://support.office.microsoft.com/ja-jp/article/34c82835-5f23-4bf0-98cc-72235bbd2949</a></span>

タイトル<span> : Access </span>のパフォーマンスを向上させる
アドレス<span> : <a href="https://support.office.microsoft.com/ja-jp/article/f6827763-bb5c-4f48-8457-7a14addab6be">https://support.office.microsoft.com/ja-jp/article/f6827763-bb5c-4f48-8457-7a14addab6be</a></span>

<a id="chapter3-4"></a>
<h5><span style="color: #333399"><strong>3-4. </strong><strong>他の言語から VBA に変更する</strong></span></h5>
Office のオートメーションにおいては、同じプログラムを<span> VBA </span>と、<span>.NET </span>や<span> C++ </span>などを用いて記述した場合では、<span>VBA </span>の方が若干高速です。これは、以下のような理由によります。

&nbsp;
<ul>
 	<li>Office では、プログラム処理の最後に画面描画やデータの同期等、処理に伴う結果を<span> Office </span>全体に反映させるクリーンナップ処理を行います。<span>VBA </span>で実装した場合は、<span>Office </span>は「一連の処理」がどこからどこまでか範囲を認識可能なため、処理全体が完了したときにクリーンナップ処理を行います。一方、他の言語を用いてオートメーションされる場合は、「一連の処理」の範囲を認識できません。このため、<span>1 </span>つ<span> 1 </span>つの処理呼び出し<span> (</span>メソッド呼び出し<span> 1 </span>回、プロパティ変更<span> 1 </span>回、など<span>) </span>ごとにクリーンナップ処理を行います。このため、他の言語では<span> VBA </span>と比較して非常に多くのクリーンナップ処理が呼び出され、その分のパフォーマンス コストがかかります。</li>
</ul>
&nbsp;
<ul>
 	<li>他の言語から<span> Office </span>の<span> COM </span>オブジェクトへの処理呼び出しに伴い、マーシャリングが行われます。僅かなコストではありますが、各処理においてマーシャリングが行われることの積み重ねでパフォーマンスに影響を与えます。<span>VBA </span>の場合は、内部呼び出しのためこのコストはかかりません。<span>(</span>特に<span> .NET </span>プログラムからの呼び出しの場合は、ランタイム呼び出し可能ラッパー<span> (RCW) </span>によるマーシャリングが行われ、アンマネージド コードと比較するとさらに低速となります。<span>)</span></li>
</ul>
<p style="padding-left: 60px">参考<span>)</span></p>
<p style="padding-left: 60px">タイトル<span> : </span>ランタイム呼び出し可能ラッパー
アドレス<span> : <a href="https://docs.microsoft.com/ja-jp/dotnet/framework/interop/runtime-callable-wrapper">https://docs.microsoft.com/ja-jp/dotnet/framework/interop/runtime-callable-wrapper</a></span></p>
&nbsp;
<ul>
 	<li>.NET プログラムの場合は、以下の資料で説明するように適切なタイミングで<span> COM </span>オブジェクトの解放が必要です。ガベージ コレクトはパフォーマンス コストの高い処理のため、これを適宜呼び出すことによって、<span>(</span>適切な実装が行われた<span>) .NET </span>プログラムではプログラム全体としてパフォーマンスが低下します。</li>
</ul>
<p style="padding-left: 60px">タイトル<span> : Office </span>オートメーションで割り当てたオブジェクトを解放する –<span> Part1</span>
アドレス<span> : <a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2012/02/09/office-5/">https://blogs.msdn.microsoft.com/office_client_development_support_blog/2012/02/09/office-5/</a></span></p>
<p style="padding-left: 60px">タイトル<span> : Office </span>オートメーションで割り当てたオブジェクトを解放する –<span> Part2</span>
アドレス<span> : <a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2012/02/28/office-3/">https://blogs.msdn.microsoft.com/office_client_development_support_blog/2012/02/28/office-3/</a></span></p>
&nbsp;

以上のような理由から、もし既存コードが他の言語であるなら、<span>VBA </span>で記述することでパフォーマンス改善を図ることができます。完全に<span> VBA </span>のみで行うことは難しい場合も、例えばユーザー インターフェイスとなる<span> Windows </span>フォームは<span> .NET </span>で作成し、ボタンクリック イベントから<span> Application.Run </span>メソッドを用いて<span> Office </span>ファイル内の<span> VBA </span>を呼び出し、実際の処理の内容は<span> VBA </span>で実行するといった仕組みを検討できます。

<a id="chapter3-5"></a>
<h5><span style="color: #333399"><strong>3-5. </strong><strong>マシン リソースの増強</strong></span></h5>
ここまでに述べたようなプログラム的なアプローチが難しい場合は、<span>CPU </span>処理速度やディスク アクセスの向上、メモリ増強でページングの発生を抑えるなどのリソース面からのアプローチで、パフォーマンス改善を図ることをご検討ください。このような方向での対応を検討する場合は、ここまでの調査とは異なり、プログラム処理実行中のリソースの推移をパフォーマンス モニターなどのツールを用いて確認し、ボトルネックとなるリソースを確認し、そのリソースを増強します。

&nbsp;

結局のところ、具体的な対応方法についてはケース バイ ケースとなりますが、上記をご参考に調査・検討を進めてみていただければ幸いです。

弊社でのご支援をご希望の際はぜひプレミア サポートへお問い合わせいただければと思います。プレミア サポートでは、<span>2. </span>のボトルネックの特定のご支援からお承りしています。

&nbsp;

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容<span> (</span>添付文書、リンク先などを含む<span>) </span>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Word 2016 からメールを送信すると文字化けする</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/word2016-mail-garbled</link>
      <pubDate>Mon, 11 Jun 2018 17:42:30 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1785</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/2e6f3a5c-0116-47b0-8807-21594dc5fda3/word-2016-">https://social.msdn.microsoft.com/Forums/ja-JP/2e6f3a5c-0116-47b0-8807-21594dc5fda3/word-2016-</a>

&nbsp;

&nbsp;

こんにちは、<span>Office </span>開発サポート チームの中村です。

今回の記事では、<span>Word 2016 </span>からテキスト形式のメールを送信するときの以下の動作について記載します。<span>1. </span>は<span> Word 2016 </span>での意図した仕様変更による動作です。<span>2. </span>は、<span>Word 2016 </span>製品の不具合によって生じます。
<ol>
 	<li>メール タイトルや本文などが<span> UTF-8 </span>で送信される</li>
 	<li>差し込み印刷でタイトルは<span> ANSI(SJIS) / </span>本文は<span> UTF-8 </span>で送信される</li>
</ol>
Word 2016 からのテキスト形式のメールの送信では、<span>Simple MAPI</span>を使用しています。以下に記載する動作変更への対応として、<span>Simple MAPI API </span>が拡張され、従来<span> ANSI </span>用であった関数で<span> UTF-8 </span>が送信可能となっています。後述の通り、お手数をおかけしますが、メール アプリケーションを作成されている開発者様には、<span>Simple MAPI </span>の<span> UTF-8 </span>対応をお願いいたします。

&nbsp;
<h4><span style="color: #333399"><strong>1. Word 2016 </strong><strong>でのテキストメールの UTF-8 への変更</strong></span></h4>
Word 2013 まで、差し込み印刷や共有などの機能で Word からテキスト形式のメールを送信すると、タイトル、本文、添付ファイル名などの文字情報は、ANSI (SJIS) で送信されていました。しかしながら、グローバルで様々な言語を扱う上で ANSI では表現できない文字が多く、これらの文字への対応要望を多くいただいていました。

これらのフィードバックを受け、<span style="text-decoration: underline"><strong>Word 2016 では UTF-8 でテキスト形式のメールを送信するように変更しました。</strong></span>

&nbsp;

内部の仕組みとしては、<span>Word </span>はテキスト形式のメール送信時に、<span>Simple MAPI</span>を使用しています。<span>MAPISendMail() </span>関数に<span> MapiMessage </span>構造体として、タイトルや本文などの情報を渡し、既定のメール クライアントにメール送信リクエストを送信します。

MAPI には、<span>Windows 8 </span>以降で利用できる<span> Unicode </span>向けの<span> MAPISendMailW() </span>関数や<span> MapiMessageW </span>構造体も用意されています。ただ、<span>Windows 7 </span>では<span> Unicode </span>向け関数や構造体は用意されておらず、送信内容として<span> Unicode </span>文字列が渡されてくるような場合は、<span>Microsoft Windows Software Development Kit (SDK) for Windows 8 </span>をインストールして<span> MAPISendMailHelper() </span>を呼び出し、<span>ANSI </span>に変換して送信します。

Word 2016 はシステム要件として、<span>Windows 7 SP1 </span>上でも動作します。テキスト形式メールの<span> UTF-8 </span>への対応にあたり、<span>Windows 7 SP1 </span>上でも<span> UTF-8 </span>として送信可能とするため、<span>MapiMessage </span>構造体の<span> ulReserved </span>パラメーターを拡張し、ここに設定された値が<span> 0 </span>であれば<span> ANSI</span>、<span>CP_UTF8 (UTF-8 </span>のコード ページ<span>) </span>であれば<span> UTF-8 </span>と見分けられるようにしました。

Word 2016 でのテキスト形式メール送信時には<span> MAPISendMail() </span>関数を引き続き呼び出し、<span>ulReserved </span>パラメーターに<span> CP_UTF8 </span>を指定して、メッセージの内容は<span> UTF-8 </span>でエンコードした状態で<span> MapiMessage </span>構造体に格納してテキスト形式のメールを送信します。<span>Outlook 2016 </span>はこの拡張に対応しており、<span>ulReserved </span>パラメーターの値を判断して<span> UTF-8 </span>の場合も正しくデコードして表示します。

&nbsp;

参考<span>)</span>

タイトル<span> : MAPISendMail function</span>
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd296721.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/dd296721.aspx</a></span>

タイトル<span> : MapiMessage structure</span>
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd296732.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/dd296732.aspx</a></span>
※<span> ulReserved </span>パラメーターの拡張後の設定値が記載されています

タイトル<span> : Code Page Identifiers</span>
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756.aspx</a></span>

&nbsp;

<strong>対応方法</strong>

メール アプリケーションの開発者様には、<span>MAPISendMail() </span>関数で<span> MapiMessage </span>構造体の<span> ulReserved </span>パラメーターに<span> CP_UTF8 </span>が指定され、文字が<span> UTF-8 </span>でエンコードされて送信される場合に正しく表示できるようご対応をお願いしております。

&nbsp;

エンド ユーザー様がこの状況に直面している場合、以下のような回避策をお試しください。
<ul>
 	<li>既定のメール アプリケーションを<span> Outlook 2016 </span>に変更する</li>
 	<li>メール アプリケーションの設定でメール受信時の文字コードを設定可能な場合は、<span>UTF-8 </span>に設定する</li>
 	<li>メール アプリケーションでメールを作成後、<span>Word </span>で作成した文書を添付、または内容をコピー＆貼り付けする</li>
</ul>
<h4></h4>
&nbsp;
<h4><span style="color: #333399"><strong>2. 差し込み印刷でタイトルのみ文字化けする</strong></span></h4>
<strong></strong>この現象は、最新バージョンをご利用の場合、ボリュームライセンス版の Office 2016 でのみ発生します。クイック実行版および Microsoft ストア アプリ版の Office 2016 では修正済みの動作です。

&nbsp;

1. で記載した変更により、<span>Word 2016 </span>からのテキスト形式のメールでは、<span>UTF-8 </span>を使用することを想定しています。しかしながら、製品の問題により、<span style="text-decoration: underline"><strong>差し込み印刷からのテキスト形式メール送信のとき、タイトルのみ ANSI (SJIS) のまま送信される現象が発生します</strong></span>。

&nbsp;

この問題は、クイック実行版、および Microsoft ストア アプリ版の<span> Office 2016 </span>では既に修正されており、タイトル、本文ともに<span> UTF-8 </span>で送信されます。

<span style="color: #999999"><del>一方で、ボリュームライセンス版 (MSI インストーラ形式) の Office 2016 は、本日 2018/6/11 時点でこの動作は修正されていません。ボリュームライセンス版の修正については現在検討中です。進展がありましたらこの記事でお伝えします。</del></span>

<span style="color: #ff0000"><strong>2018/8/20 Update</strong></span>

以下の更新プログラムで、ボリューム ライセンス版の Office 2016 にも修正を行い、タイトル、本文ともに<span> UTF-8 </span>で送信されるようになりました。

文書番号 : 4032258
タイトル : Word 2016 (KB4032258) の更新プログラムを 2018 年 8 月 7日
アドレス : <a href="https://support.microsoft.com/ja-jp/help/4032258">https://support.microsoft.com/ja-jp/help/4032258</a>

&nbsp;

<strong>回避策</strong>

ご不便をおかけして申し訳ありませんが、現象が発生するバージョンの Office を利用している場合は以下の回避策をご検討ください。
<ul>
 	<li><span>Outlook </span>を使用している場合は、<span>HTML </span>形式でメールを送信する<span> (MAPI </span>とは別の仕組みで送信されるため、この問題が生じる処理を行いません<span>)</span></li>
 	<li>メール アプリケーションでメールを作成後、<span>Word </span>で作成した文書を添付、または内容をコピー＆貼り付けする</li>
 	<li>クイック実行版の<span> Office 2016 (</span>最新バージョン<span>) </span>を利用する</li>
</ul>
&nbsp;

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容<span> (</span>添付文書、リンク先などを含む<span>) </span>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Microsoft ストア アプリ版 Office 2016 (Centennial) での開発 – その1 – (DLL の読み込み)</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/office-centennial-vol1</link>
      <pubDate>Tue, 15 May 2018 16:22:09 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1755</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/40e7a626-34ce-4508-84d6-af68b69612ce/microsoft-office-2016-centennial-1-dll-">https://social.msdn.microsoft.com/Forums/ja-JP/40e7a626-34ce-4508-84d6-af68b69612ce/microsoft-office-2016-centennial-1-dll-</a>

&nbsp;

こんにちは、Office 開発サポート チームの中村です。久しぶりの投稿になります。

このタイトルの記事では、新しい提供方法である「Microsoft ストア版 Office 2016」における、これまでの Office との違いについて、Office 開発観点から記載していきたいと思います。今後もこのテーマでは何度か投稿することになると思いますが、今回はまず、DLL 読み込み動作の違いについて記載します。

&nbsp;
<h4></h4>
<h4><span style="color: #333399"><strong>1. Microsoft </strong><strong>ストア版</strong><strong> Office 2016 </strong><strong>とは？</strong></span></h4>
Office 開発観点の話の前に、そもそも、Microsoft ストア版 Office 2016 とはどういうものかを簡単に説明します。

Office 2016 には色々なライセンス契約方式がありますが、これは単に契約上のみの違いではなく、販売方法によって、Office アプリケーション自体も異なる仕組みで提供されています。現在、以下の 3 種類の提供形式があります。

&nbsp;
<h5><strong><span style="color: #333399">1-1. クイック実行 (C2R) 形式</span></strong></h5>
Office 365、市販パッケージ (FPP)、以前のプレインストール (PIPC) がこの提供形式です。また、MSDN サブスクリプション契約でダウンロードできる検証用の Office 2016 も (プロダクト キーの入力などの認証方式はボリュームライセンスに一見見えますが) クイック実行形式です。

インターネットなどからサイズの小さいインストーラをダウンロードして実行し、インストールの中で実行モジュールのダウンロード等を行います。最低限の準備ができると Office を使い始めることができ、バックグラウンドで残りのインスト―ルが行われることから、クイック実行と呼ばれます。

Office 2016 では、現在このクイック実行形式が主流となっており、製品の修正、新機能の追加などは、基本的にこのクイック実行形式に対して行われます。

クイック実行形式は、Microsoft Application Virtualization (App-V) のテクノロジに基づいてストリーミングおよび仮想化されて提供されています。詳細は以下の公開情報をご参照ください。

参考)
タイトル : クイック実行の概要
アドレス : <a href="https://technet.microsoft.com/ja-jp/library/jj219427.aspx">https://technet.microsoft.com/ja-jp/library/jj219427.aspx</a>

&nbsp;
<h5><strong><span style="color: #333399">1-2. MSI インストーラ形式</span></strong></h5>
ボリューム ライセンスがこの提供形式です。

以前からある、DVD ディスクなどに焼かれた MSI インストーラを用いてインストールする形式で、インストールされる実行モジュールなどは全てインストーラに含まれており、オフラインでインストールできます。

Office 2016 では、MSI インストーラ形式は長期安定稼働版と位置付けており、セキュリティ更新以外の修正、新機能の追加はほとんど行われません。このため、最新の更新を適用しても、C2R 形式で利用できる機能が含まれていないことがあります。

&nbsp;
<h5><span style="color: #333399"><strong>1-3. Microsoft </strong><strong>ストア版</strong><strong> Office 2016 (Centennial </strong><strong>版</strong><strong>)</strong></span></h5>
今回の記事で説明する提供形式です。現時点でこの形式で Office 2016 が提供されているのは、最近のプレインストール (PIPC) 版の一部と、Windows 10 S が搭載された Surface Laptop のいずれかとなります。

参考)
タイトル : Office 2016 プレインストール版 (PIPC) 製品インストール - Office 2016 セットアップ
アドレス : <a href="https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_setup.aspx">https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_setup.aspx</a>

タイトル : Surface Laptop のご紹介
アドレス : <a href="https://support.microsoft.com/ja-jp/help/4037229/surface-meet-surface-laptop">https://support.microsoft.com/ja-jp/help/4037229/surface-meet-surface-laptop</a>

この形式では、Office 2016 は Microsoft ストアを通じてインストールや更新を行います。他のストア アプリと同様、この方法で提供される Office 2016 はユニバーサル Windows プラットフォーム (UWP) でパッケージ化されています (デスクトップ ブリッジという方法を用いています)。このような仕組みを Centennial とも呼ぶため、Microsoft ストア版 Office は「Office Centennial」とも呼ばれます。UWP パッケージ化されたアプリは、ファイル システムやレジストリなどが UWP パッケージ独自の構成となり、また、動作上もそのままアプリを実行する場合とは異なる点があります。

Microsoft ストア版 Office にも、不具合の修正や新機能の追加は行われていきます。更新は Microsoft ストアによって管理されます。

参考)
タイトル : ユニバーサル Windows プラットフォームの紹介
アドレス : <a href="https://docs.microsoft.com/ja-jp/windows/uwp/get-started/universal-application-platform-guide">https://docs.microsoft.com/ja-jp/windows/uwp/get-started/universal-application-platform-guide</a>

タイトル : デスクトップ ブリッジの内側
アドレス : <a href="https://docs.microsoft.com/ja-jp/windows/uwp/porting/desktop-to-uwp-behind-the-scenes">https://docs.microsoft.com/ja-jp/windows/uwp/porting/desktop-to-uwp-behind-the-scenes</a>

&nbsp;

比較的新しい技術になるため、情報がまだまだ充実しておらず申し訳ありませんが、このブログでは、Microsoft ストア版 Office 2016 で他の提供形式と異なる動作となる点や留意点などについて、Office 開発観点で注目すべき点を随時ご紹介していきたいと思います。

&nbsp;

<strong>補足</strong><strong> : Office 2016 </strong><strong>提供形式の見分け方</strong>

自身の端末がどの提供形式の Office 2016 を使っているかを確認する方法については、以下をご参照ください。

タイトル : クイック実行形式 (C2R) と Windows インストーラー形式 (MSI) を見分ける方法
アドレス : <a href="https://blogs.technet.microsoft.com/officesupportjp/2016/09/08/howto_c2r_or_msi/">https://blogs.technet.microsoft.com/officesupportjp/2016/09/08/howto_c2r_or_msi/</a>

タイトル : FAQ よく寄せられる質問
アドレス : <a href="https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_faq.aspx">https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_faq.aspx</a>
該当箇所 : "セットアップ前" – "プレインストールされた Office 2016 のアプリ形式を確認する方法がありますか。"

&nbsp;

Office アプリケーションを起動して、[ファイル] タブ – [アカウント] の以下の箇所でも確認できます。(以下は Excel の　Microsoft ストア版の例)

[caption id="attachment_1765" align="alignnone" width="397"]<img width="397" height="109" class="size-full wp-image-1765" alt="図 1. [アカウント] メニューでの提供方式の表示" src="https://msdnshared.blob.core.windows.net/media/2018/05/VerCapture_Store.png" /> 図 1. [アカウント] メニューでの提供方式の表示[/caption]&nbsp;
<h4><span style="color: #333399"><strong>2. Microsoft </strong><strong>ストア版</strong><strong> Office 2016 </strong><strong>の</strong><strong> DLL </strong><strong>読み込み動作</strong></span></h4>
さて、本題です。Microsoft ストア版 Office 2016 で C2R 版や MSI 版と動作が異なる点として、<span style="color: #ff0000">DLL 読み込み時の検索パスが異なります。</span>

例えば、VBA で以下のように記述するとします。
<pre><code>Private Declare Sub MyFunc Lib "TEST.dll" () 
Sub Sample()
    MyFunc
End Sub</code></pre>
この VBA を実行するとき、Office は TEST.dll をいくつかのフォルダから検索し、見つかったら DLL を読み込み、MyFunc を呼び出すことができます。

&nbsp;

C2R 版や MSI 版では、以下の公開情報で紹介されている OS の既定の動作に則ってフォルダを検索します。

タイトル : Windows が使用する DLL 検索パス
アドレス : <a href="https://msdn.microsoft.com/ja-jp/library/7d83bc18.aspx">https://msdn.microsoft.com/ja-jp/library/7d83bc18.aspx</a>

&nbsp;

&lt;検索対象フォルダ (上記公開情報より抜粋)&gt;

1.実行中のプロセスの実行形式モジュールがあるフォルダー。

<span style="color: #ff0000">2.現在のフォルダー。</span>

3.Windows システム フォルダー。 このフォルダーへのパスは、GetSystemDirectory 関数が取得します。

<span style="color: #ff0000">4.Windows ディレクトリ。 このフォルダーへのパスは、GetWindowsDirectory 関数が取得します。</span>

<span style="color: #ff0000">5.環境変数 PATH 内に記述されたフォルダー。</span>

&nbsp;

<span style="color: #ff0000"><strong>Microsoft </strong><strong>ストア版</strong><strong> Office </strong><strong>では、上記赤字で示した</strong><strong> 2. / 4. / 5. </strong><strong>のフォルダは検索されません。</strong></span>

以下の公開情報で述べられたカレント フォルダから DLL を読み込む危険性などを考慮し、セキュリティ強化を図る目的で、Microsoft ストア版 Office ではこのような動作になっています。

タイトル : DLL プリロード攻撃を防止するためのライブラリの安全な読み込み
アドレス : <a href="https://support.microsoft.com/ja-jp/help/2389418">https://support.microsoft.com/ja-jp/help/2389418</a>

&nbsp;

したがって、例えば Excel マクロ ファイルと一緒に DLL を配布して同じフォルダに格納し、マクロ ファイル内でファイルの格納フォルダに移動 (ChDir) した上で DLL を冒頭のサンプル マクロのようにパスを指定せずに読み込む、といった動作を期待している場合、ストア版 Office では期待した通りに動作しません。

&nbsp;
<h4><span style="color: #333399"><strong>3. 対応方法</strong></span></h4>
<h5><span style="color: #333399"><strong></strong><strong></strong><strong>3-1. </strong><strong>プログラムで検索パスを指定する</strong></span></h5>
DLL を読み込む処理の前に、SetDllDirectory API などを用いて、DLL 検索パスを明示的に指定してください。

タイトル : SetDllDirectory function
アドレス <span>: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203.aspx</a></span>

または、VBA の Declare ステートメントで DLL をフルパスで指定して読み込むようにします。ただし、DLL の構成がシンプルなものであればこの方法で問題ありませんが、DLL からさらに別の DLL を読み込むような場合は、ここでも検索パスの問題が生じますのでご注意ください。

DLL 読み込み後、必要に応じて SetDllDirectory API を Null 指定で呼び出して検索パスをリセットできます。

DLL 格納パスが複数のパスに分かれている場合などは、Windows 8 以降では AddDllDirectory API も利用できます。

タイトル : AddDllDirectory function
アドレス : <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/hh310513.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/hh310513.aspx</a>

&nbsp;
<h5><span style="color: #333399"><strong>3-2. C2R </strong><strong>版</strong><strong> Office </strong><strong>に変更する</strong></span></h5>
PIPC 向けに提供された Microsoft ストア版 Office 2016 は、再インストールによって C2R 版の Office をインストールすることができます。

再インストール手順については、以下の公開情報をご参照ください。以下で「デスクトップ アプリ版 Office 2016」と呼ばれるものが、C2R 版の Office 2016 を指します。

タイトル : Office 2016 プレインストール版 (PIPC) 製品インストール - 再インストール
アドレス : <a href="https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_re_setup.aspx">https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_re_setup.aspx</a>

Microsoft ストア版 Office 2016 からデスクトップ アプリ版 Office 2016 への入れ替えについては、FAQ にも記載がありますので合わせてご参照ください。

タイトル : Office 2016 プレインストール版 (PIPC) 製品インストール - FAQ よく寄せられる質問
アドレス : <a href="https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_faq.aspx">https://www.microsoft.com/ja-jp/office/2016/pipcsetup/pipc_faq.aspx</a>

&nbsp;

注 :
Surface Laptop の場合は、Windows 10S OS 自体がストア アプリのみの動作を許可する仕組みとなるため、デスクトップ アプリ版 Office 2016 をインストールすることはできません。

&nbsp;

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容</strong><strong> (</strong><strong>添付文書、リンク先などを含む</strong><strong>) </strong><strong>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Excel / PowerPoint / Visio 2016 バージョン 1801 以降で WebBrowser コントロールがユーザーフォーム外に表示される</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/1801-webbrowser</link>
      <pubDate>Tue, 23 Jan 2018 16:07:01 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1715</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/593f6f4d-a703-4d29-b04a-9ebaedf090c9/excel-powerpoint-visio-2016-1801-webbrowser-">https://social.msdn.microsoft.com/Forums/ja-JP/593f6f4d-a703-4d29-b04a-9ebaedf090c9/excel-powerpoint-visio-2016-1801-webbrowser-</a>

&nbsp;

こんにちは、Office 開発サポート チームの中村です。

<span style="color: #000000">今回の記事では、ユーザーフォーム上に</span> WebBrowser コントロールを貼り付けて利用している場合に、Windows 10 バージョン 1703 以降の OS で Office 2016 をバージョン 1801 以降に更新すると、WebBrowser コントロールがユーザーフォームの外に表示される動作について記載します。

<strong><span style="color: #ff0000">2018/2/5 Update</span>
</strong><span style="color: #339966">本現象が発生する要因となる機能 (後述の「ディスプレイで最適な解像度を使用」) の有効化を延期しました。このため、本記事の内容は今後の更新で発生する可能性がある現象としてご案内します。現時点で、本機能の有効化時期は未定です。</span>

<strong><span style="color: #ff0000">2018/6/8 Update</span>
</strong><span style="color: #339966">月次チャネル バージョン 1805 (16.0.9226.2114) で本機能が有効化されました。当初公開時とオプション メニュー名などが変更されたため、記事内の画面キャプチャなどを最新の状態に更新しています。</span>

&nbsp;
<h4><span style="color: #333399"><strong>再現手順</strong></span></h4>
1. 新規 Excel ブックを作成し、Visual Basic Editor でユーザーフォーム (UserForm1) を追加して、WebBrowser コントロールとボタン コントロールを貼り付けます。

[caption id="attachment_1725" align="alignnone" width="333"]<img width="333" height="250" class="size-full wp-image-1725" alt="図 1. ユーザーフォームへの WebBrowser コントロール追加" src="https://msdnshared.blob.core.windows.net/media/2018/01/01_WebBrowser_Design.png" /> 図 1. ユーザーフォームへの WebBrowser コントロール追加[/caption]

&nbsp;

2. ボタン コントロールのクリック イベント ハンドラに以下のようなコードを記述します。
<pre><code>Private Sub CommandButton1_Click()
    UserForm1.WebBrowser1.Navigate2 ("http://www.microsoft.com")
End Sub</code></pre>
&nbsp;

3. F5 キーを押下して、ユーザーフォームを表示すると、以下のように WebBrowser コントロールがユーザーフォームのウィンドウ外に表示されます。

[caption id="attachment_1735" align="alignnone" width="687"]<img width="687" height="448" class="size-full wp-image-1735" alt="図 2. WebBrowser がユーザーフォーム外に表示されている状態" src="https://msdnshared.blob.core.windows.net/media/2018/01/02_WebBrowser_Repro.png" /> 図 2. WebBrowser がユーザーフォーム外に表示されている状態[/caption]

&nbsp;
<h4><span style="color: #333399"><strong>現象詳細</strong></span></h4>
この動作は、バージョン 1801 で追加された「<span>ディスプレイで最適な解像度を使用」という新機能の影響で発生します。</span>

タイトル : 高解像度のモニターの office のサポート
アドレス : <a href="https://support.office.com/ja-jp/article/6720ca0e-be59-41f6-b629-1369f549279d">https://support.office.com/ja-jp/article/6720ca0e-be59-41f6-b629-1369f549279d</a> (日本語機械翻訳版)
アドレス : <a href="https://support.office.com/en-us/article/6720ca0e-be59-41f6-b629-1369f549279d">https://support.office.com/en-us/article/6720ca0e-be59-41f6-b629-1369f549279d</a>(英語版)

<span>この機能の動作を制御する</span>オプション項目「複数ディスプレイを使用する場合」で「表示を優先した最適化」が有効な場合に現象が発生します (更新後、既定では有効に設定されています)。

[caption id="attachment_1775" align="alignnone" width="937"]<img width="937" height="298" class="size-full wp-image-1775" alt="図 3. [複数ディスプレイを使用する場合] オプション" src="https://msdnshared.blob.core.windows.net/media/2018/01/DynamicDPI_1805.png" /> 図 3. [複数ディスプレイを使用する場合] オプション[/caption]
このオプションは、高解像度や複数のモニターを持つ PC 環境などでも最適な画面表示となるよう、バージョン 1801 で機能強化を行ったことで追加されました。このオプションが有効な場合、モニターの解像度を判断し、これに応じて適切な表示が行われます。

一方で、WebBrowser コントロールのように、コントロールによっては、表示の際にコントロール自身のウィンドウとユーザーフォーム ウィンドウとの親子関係の設定が行われます。このときに、ユーザーフォームとコントロールのウィンドウで、それぞれ解像度の認識状況が異なると、以下の SetParent 関数のリファレンス ページに記載の通り、Windows 10 バージョン 1703 以降の OS ではエラーが返され、親子関係を設定することができません。

タイトル <span>: SetParent function</span>
アドレス <span>: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms633541(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/ms633541(v=vs.85).aspx</a></span>

&lt;公開情報より抜粋&gt;
Unexpected behavior or errors may occur if hWndNewParent and hWndChild are running in different DPI awareness modes. The table below outlines this behavior:
<table width="824" border="1">
<tbody>
<tr bgcolor="#ddded3">
<td><strong>Operation</strong></td>
<td><strong>Windows 8.1</strong></td>
<td><strong>Windows 10 (1607 and earlier)</strong></td>
<td><strong>Windows 10 (1703 and later)</strong></td>
</tr>
<tr>
<td>SetParent (In-Proc)</td>
<td>N/A</td>
<td><strong>Forced reset</strong> (of current process)</td>
<td><strong>Fail</strong> (ERROR_INVALID_STATE)</td>
</tr>
<tr>
<td>SetParent (Cross-Proc)</td>
<td><strong>Forced reset</strong> (of child window's process)</td>
<td><strong>Forced reset</strong> (of child window's process)</td>
<td><strong>Forced reset</strong> (of child window's process)</td>
</tr>
</tbody>
</table>
&nbsp;

これらの動作の結果、WebBrowser コントロールとユーザーフォームの親子関係が設定されず、WebBrowser コントロールがユーザーフォームとは別に表示されます。

WebBrowser コントロールに限らず、同じようにウィンドウを持つコントロールでは、同様に現象が発生する場合があります。(MSCOMCTL.OCX に含まれる TreeView コントロールなどのように、ウィンドウを持つコントロールでも現象が発生しないコントロールもあります。)

&nbsp;

<strong>補足</strong>
<ul>
 	<li>「ディスプレイで最適な解像度を使用」機能は、Excel / Word / PowerPoint / Visio に追加されていますが、Word では本手順で現象は発生しません。</li>
 	<li>OS が <span>Windows 10 </span>バージョン 1703 より古い場合は、「ディスプレイで最適な解像度を使用」オプションは表示されません。</li>
 	<li>VBE のメニューの実行ボタン (緑色の右三角のボタン) や、[実行] – [Sub/ユーザーフォームの実行] から実行すると、現象は発生しません。F5 キーや、プロシージャから UserForm.Show を実行してユーザーフォームを表示する場合に発生します。</li>
</ul>
&nbsp;
<h4><span style="color: #333399"><strong>回避策</strong></span></h4>
<strong>1. 「ディスプレイで最適な解像度を使用」オプションを無効にする</strong>

先述の通り、この現象はこのオプションが有効な場合にのみ発生します。この機能が不要な場合、これをオフにして回避することができます。

ユーザー全体に展開したい場合やプログラムから変更したい場合には、以下のレジストリで制御できます。ただし、設定値の反映には Office アプリケーションの再起動が必要です。アプリケーションの処理中に一時的に変更するような場合には、Office アプリケーションを起動する前にこのレジストリを変更する必要があります。

キー :
&lt;Excel / Word / PowerPoint 向け&gt;
HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\&lt;アプリケーション名&gt;\Options
(&lt;アプリケーション名&gt; には、Excel / Word / PowerPointが入ります。ただ、Word は先述の通りこの手順で現象は発生しませんので回避策としての設定は必要ありません。)

&lt;Visio 向け&gt;
HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Visio\Application

名前 :
RenderForMonitorDpi
種類 :
REG_DWORD

値 :
0 (0 =無効 / 1 =有効)

<strong>2. カスタム作業ウィンドウで</strong><strong> WebBrowser </strong><strong>コントロール表示する</strong>

カスタム作業ウィンドウ内に WebBrowser コントロールを貼り付ける場合には、現象は発生しません。VSTO ソリューションなどでカスタム作業ウィンドウを追加し、この中で WebBrowser コントロールを使用するよう仕組みを変更することが検討できます。カスタム作業ウィンドウの作成手順は以下の公開情報を参照してください。

タイトル : カスタム作業ウィンドウ
アドレス : <a href="https://msdn.microsoft.com/ja-jp/library/aa942864.aspx">https://msdn.microsoft.com/ja-jp/library/aa942864.aspx</a>

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容</strong><strong> (</strong><strong>添付文書、リンク先などを含む</strong><strong>) </strong><strong>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Excel 2016 バージョン 1712 で Workbook_Open から表示したユーザーフォームを閉じるとクラッシュする</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/ver1712_userform_workbookopen_issue</link>
      <pubDate>Thu, 28 Dec 2017 15:02:24 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1685</guid>
      <description><![CDATA[こんにちは、Office 開発サポート チームの中村です。

2017 年 12 月に先行リリース チャネルに公開済みの Office 2016 の更新バージョン 1712 を適用した環境の...]]></description>
      <content:encoded><![CDATA[こんにちは、Office 開発サポート チームの中村です。

2017 年 12 月に先行リリース チャネルに公開済みの Office 2016 の更新バージョン 1712 を適用した環境の Excel 2016 で、ブック オープンと同時にユーザーフォームを表示している場合に、これを閉じると Excel がクラッシュする現象を確認しています。本記事では、現象が発生する状況と、修正、回避策についてご案内します。今後、修正状況など随時更新を予定しています。

<strong><span style="color: #ff0000">2018/1/17 Update</span></strong>
<span style="color: #339966">Insider スローへ修正を公開しました。</span>

<span style="color: #ff0000"><strong>2018/1/23 Update</strong></span>
<span style="color: #339966">Insider スローで問題が再発生する状況について追記しました。</span>

<span style="color: #ff0000"><strong>2018/1/26 Update</strong></span>
<span style="color: #339966">Insider スローに再度修正されたバージョンを公開しました。</span>

<span style="color: #ff0000"><strong>2018/2/5 Update</strong></span>
<span style="color: #339966">Insider ファーストに修正されたバージョンを公開しました。</span>

&nbsp;
<h4><strong><span style="color: #333399">1. 現象の詳細</span></strong></h4>
Office 2016 バージョン 1712 (8827.2082 以降) の環境で、Workbook_Open イベント ハンドラなどのブック オープンと同時に実行される処理からユーザーフォームをモーダル表示するマクロが組み込まれているファイルを開くときに、ユーザーフォームは正常に表示されますが、ユーザーフォームを閉じると Excel がクラッシュします。

&nbsp;

<strong>再現手順</strong>
1. 新規 Excel ファイルを作成します。
2. Visual Basic Editor を起動し、ユーザーフォームを追加します。(UserForm1)
3. ThisWorkbook オブジェクトに以下のコードを記述します。
<pre><code>Private Sub Workbook_Open()
    UserForm1.Show
End Sub</code></pre>
4. ファイルを .xlsm 形式、または .xls 形式で保存していったん閉じます。
5. 4. で保存したファイルを開きます。
6. マクロが自動実行されてユーザーフォームが表示されます。 ※ マクロのセキュリティ設定やドキュメントの信頼状況によっては、警告バーが表示されてマクロが自動実行されません。これについては、2. で詳細を記載します。
7. 表示されたユーザーフォームを閉じます。
結果 : Excel がクラッシュします。

&nbsp;

<strong>発生条件詳細</strong>
<ul>
 	<li>マクロがブック オープンと同時に自動実行される場合にのみ発生します。セキュリティの警告の黄色いバーが表示されて一旦マクロが無効化され、[コンテンツの有効化] でマクロを実行する場合は問題ありません。</li>
 	<li>ブック オープン時に動作する Workbook_Open イベント ハンドラ、Application.WorkbookOpen イベント ハンドラ、Auto_Open メソッドのいずれも現象が発生します。</li>
 	<li>ユーザーフォームを閉じる操作は、×ボタン、Unload メソッド、Hide メソッドのいずれも現象が発生します。</li>
 	<li>ユーザーフォームがモーダル表示の場合にのみ現象が発生します。モードレス表示の場合は問題ありません。</li>
 	<li>Excel アドイン (.xlam / .xla) をアドインとして登録して同様の処理を行う場合は問題ありません。</li>
</ul>
&nbsp;
<h4><strong><span style="color: #333399">2. マクロの自動実行に関する設定</span></strong></h4>
現象の再現条件であるブック オープン同時に Workbook_Open イベント ハンドラが実行される動作は、以下の設定によって制御されます。

<strong>1. オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [マクロの設定]</strong>
<ul>
 	<li> [すべてのマクロを有効にする] に設定されている場合</li>
 	<li>[デジタル署名されたマクロを除き、全てのマクロを無効にする] に設定されており、かつマクロに信頼された証明書でデジタル署名が行われている場合</li>
 	<li>[警告を表示してすべてのマクロを無効にする] または [警告を表示せずにすべてのマクロを無効にする] に設定されており、ドキュメントが信頼できる状態である場合</li>
</ul>
<strong>2. オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [信頼済みドキュメント]</strong>
<p style="padding-left: 30px">マクロのセキュリティ設定が [警告を表示してすべてのマクロを無効にする] の場合に、1 度そのブックを開いてマクロを有効にすると、そのブックは信頼できるドキュメントに登録され、次回以降マクロが自動的に有効化されます。</p>
<strong>3. オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [信頼できる場所]</strong>
<p style="padding-left: 30px">ここに登録されたフォルダに格納されたブックは信頼され、マクロが自動的に実行されます。</p>
<strong>4. オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [信頼できる発行元]</strong>
<p style="padding-left: 30px">ここに表示されている証明書 (ユーザーの証明書ストア [信頼された発行元] に登録された証明書) でマクロにコード署名が行われているブックは信頼され、マクロが自動的に実行されます。</p>
&nbsp;

<span style="color: #ff0000"><strong>2018/2/5 Update</strong></span>
<h4><strong><span style="color: #333399">3. 対応方法 </span></strong></h4>
問題が修正されたバージョンを公開しました。詳細は以下の通りです。
&nbsp;
<strong>Insider ファースト</strong>

バージョン 1802 ビルド 16.0.9026.2006 (2018/2/3 公開) で本記事の問題を修正しました。
&nbsp;
<strong>Insider スロー</strong>

以下の通り、一時的に問題が修正された後、問題が再発生するバージョンがあります。最新のバージョンでは修正されています。
バージョン 1712 ビルド 16.0.8827.2148 (2018/1/17 公開) : 本記事の問題を修正しました。
バージョン 1801 ビルド 16.0.9001.2080 (2018/1/20 公開) : 本記事の問題が再発生します。
バージョン 1801 ビルド 16.0.9001.2102 (2018/1/26 公開) : 本記事の問題を再修正しました。
&nbsp;
月次チャネル (Monthly Channel) への 1 月の更新はすでに修正されたバージョンを公開したため、月次チャネルでは今回の問題は発生しません。また、今後公開される半期チャネルにも問題が発生するバージョンは公開されません。

&nbsp;
<h4><strong><span style="color: #333399">4. 暫定回避方法</span></strong></h4>
すでに修正が公開されているため、現象の回避には修正版への更新を推奨しますが、暫定回避方法についての記載もこのまま残しておきます。更新を適用できない事情がある場合は、以下のいずれかの方法での回避をご検討ください。

<a href="#chapter4-1">4-1. Office 2016 の自動更新を停止し、バージョンを 1711 以前のままで利用する</a>
<a href="#chapter4-2">4-2. マクロが自動実行されず警告が表示されるようにする</a>
<a href="#chapter4-3">4-3. ユーザーフォームをモードレス表示にする</a>
<a href="#chapter4-4">4-4. Application.OnTime メソッドでユーザーフォームを表示する</a>

&nbsp;

以下にそれぞれ詳細を記載します。
<a id="chapter4-1"></a>
&nbsp;
<h5><strong><span style="color: #333399">4-1. Office 2016 の自動更新を停止し、バージョンを 1711 以前のままで利用する</span></strong></h5>
Office 2016 の自動更新を停止し、またすでにバージョン 1712 に更新してしまっている場合は、以前のバージョンに戻します。これらの手順は、以下の記事で以前に紹介した手順と同様となりますので、詳しい手順はリンク先を参照してください。

タイトル : Office 2016 バージョン 1708 以降で日本語の VBA モジュール名を含むファイルを開くとエラー
アドレス : <a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2017/08/23/ver1708-issue-japanesenamevbamodule/">https://blogs.msdn.microsoft.com/office_client_development_support_blog/2017/08/23/ver1708-issue-japanesenamevbamodule/</a>
該当箇所 : ”3. 対応状況" の "暫定対応手順"

&nbsp;

今回、戻すときに指定するバージョンは、それぞれ以下の通りです。

Insider ファースト : 16.0.8730.2122
Insider スロー : 16.0.8730.2127

<a id="chapter4-2"></a>
&nbsp;
<h5><strong><span style="color: #333399">4-2. マクロが自動実行されず警告が表示されるようにする</span></strong></h5>
ブックを開いたときに、以下のように [セキュリティの警告] が一旦表示される状態にし、[コンテンツの有効化] をクリックしてマクロが実行されるようにします。

[caption id="attachment_1695" align="alignnone" width="883"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/MacroSecAlert.png"><img width="883" height="405" class="size-full wp-image-1695" alt="図 1. マクロのセキュリティ警告" src="https://msdnshared.blob.core.windows.net/media/2017/12/MacroSecAlert.png" /></a> 図 1. マクロのセキュリティ警告[/caption]

&nbsp;

このような状態とするには、「2. マクロの自動実行に関する設定」に記載した自動実行される条件を満たさないように Excel を構成します。ユーザーの環境やマクロの運用によって様々な構成が想定されるため、推奨される設定を一概にご案内することは難しいですが、一般的には以下の設定としていただくとほとんどのブックでセキュリティの警告を表示できます。
<ul>
 	<li>オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [マクロの設定] を [警告を表示してすべてのマクロを無効にする] に設定 (既定)</li>
 	<li>オプションの [セキュリティ センター] - [セキュリティ センターの設定] - [信頼済みドキュメント] の [信頼済みドキュメントを無効にする] のチェックを入れる</li>
</ul>
このように設定すると、信頼できる場所にあるか、信頼済みの証明書で署名されたブック以外はセキュリティの警告が表示されます。
信頼できる場所は、既定ではアドイン格納フォルダ等の Excel で特別な意味を持つフォルダのみが登録されているため、これらのフォルダにユーザーが作成したマクロ ブックが格納されるケースは少ないかと思います。また、署名がマクロに付与されていることもあまり多くはありません。したがって、このように設定すると、一般的な構成ではほとんどのファイルでセキュリティの警告が表示されます。

ただし、組織のポリシーやご利用のシステムの要件などで、独自のフォルダを信頼できる場所に登録していたり、マクロのセキュリティ設定を変更しているといった状況も考えられますので、この方法で回避する場合には、環境構成を十分にご確認ください。

<a id="chapter4-3"></a>
&nbsp;
<h5><strong><span style="color: #333399">4-3. ユーザーフォームをモードレス表示にする</span></strong></h5>
以下のようにコードを記述すると、ユーザーフォームをモードレスで表示できます。モードレスでの表示で問題ない場合は、モードレス表示に変更することで回避できます。
<pre><code>UserForm1.Show vbModeless</code></pre>

<a id="chapter4-4"></a>
&nbsp;
<h5><strong><span style="color: #333399">4-4. Application.OnTime メソッドでユーザーフォームを表示する</span></strong></h5>
Application.OnTime メソッドを利用すると、一定時間の経過後に指定した標準モジュールの関数を呼び出すことができます。

タイトル : Application.OnTime メソッド (Excel)
アドレス : <a href="https://msdn.microsoft.com/ja-jp/library/office/ff196165(v=office.15).aspx">https://msdn.microsoft.com/ja-jp/library/office/ff196165(v=office.15).aspx</a>

例えば以下のように記述すると、1 秒後に Sample メソッドを実行します。
<pre><code>Application.OnTime Now + TimeValue("00:00:01"), "Sample"</code></pre>
&nbsp;

Workbook_Open イベント ハンドラには Application.OnTime で指定したメソッドを呼び出すように記述し、呼び出し先のメソッドでユーザーフォームの表示などの現在 Workbook_Open で行っている一連の処理を実行するように変更します。Application.OnTime メソッドでの関数呼び出しは、一旦ブック オープンの一連の処理の流れから抜けた後に実行される内部動作となりますので、今回の現象を回避できます。

&lt;実装イメージ&gt;
ThisWorkbook オブジェクト に以下を記述
<pre><code>Private Sub Workbook_Open()
    Application.OnTime Now + TimeValue("00:00:01"), "Sample"
End Sub</code></pre>
標準モジュールに以下を記述 (ThisWorkbook オブジェクトなどに記述すると呼び出せませんのでご注意ください)
<pre><code>Public Sub Sample()
    UserForm1.Show
End Sub</code></pre>
&nbsp;

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容 (添付文書、リンク先などを含む) は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Office リボンをカスタマイズ – パート7 – (TIPS 3 : 特殊メニューのカスタマイズ)</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/customize-ribbon-part7</link>
      <pubDate>Tue, 26 Dec 2017 16:42:27 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1635</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/4774ba34-72eb-4784-85d6-b48c15512645/office-7-tips-3-">https://social.msdn.microsoft.com/Forums/ja-JP/4774ba34-72eb-4784-85d6-b48c15512645/office-7-tips-3-</a>

&nbsp;

こんにちは、<span>Office </span>開発サポートの中村です。

これまで<span> 6 </span>回にわたってリボン カスタマイズについて記事を公開してきましたが、今回でいったん最後の記事の予定です。最後に、特殊なメニューである<span> BackStage </span>ビュー<span> / </span>右クリックで表示されるコンテキスト メニュー<span> / </span>クイック アクセス ツール バーのカスタマイズ方法をご紹介します。

<strong><b>目次</b></strong>
<a href="#chapter1">1. BackStage ビューのカスタマイズ</a>
<a href="#chapter2">2. 右クリック メニューのカスタマイズ</a>
<a href="#chapter3">3. クイック アクセス ツールバーのカスタマイズ</a>

<a id="chapter1"></a>
<h4><span style="color: #333399"><strong>1. BackStage </strong><strong>ビューのカスタマイズ</strong></span></h4>
BackStage ビューは、<span>Office 2010 </span>から導入された<span> [</span>ファイル<span>] </span>タブ内のメニューを指します。<span>Excel 2016 </span>の場合、以下のような画面です。

[caption id="attachment_1637" align="alignnone" width="661"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/01_BackStageView.png"><img width="661" height="462" class="size-full wp-image-1637" alt="図 1. Backstage ビュー" src="https://msdnshared.blob.core.windows.net/media/2017/12/01_BackStageView.png" /></a> 図 1. Backstage ビュー[/caption]

Office 2010 の名前空間 <span>&lt;http://schemas.microsoft.com/office/2009/07/customui&gt; </span>では、この<span> BackStage </span>ビューをカスタマイズする方法も用意されています。言い換えますと、<span>XML </span>でのカスタマイズのみとなりますので、<span>VSTO </span>でビジュアルなデザイナーから<span> BackStage </span>ビューをカスタマイズすることはできません。
また、通常のリボンは、<span>VBA </span>の<span> Comanndbars </span>を用いてカスタマイズすることもできますが、<span>BackStage </span>ビューは<span> VBA </span>ではカスタマイズできません。(なお、<span>Office 2007 </span>以降のリボン メニューでは、この VBA による方法でのカスタマイズは推奨していません<span>)</span>

リボン<span> XML </span>を使用すると、例えば、以下のような<span> BackStage </span>メニューのカスタマイズができます。
<ul>
 	<li>既存メニューを非表示にする</li>
 	<li>左側のメニューに独自メニューを追加する</li>
 	<li>メニュー内の項目に独自のメニューを追加する</li>
</ul>
これらを応用すると、既存メニューを非表示にして同じ名前でカスタマイズ メニューを追加して、見た目上は既定のメニューで独自の動作をさせることもできます。例えば、<span>[</span>名前を付けて保存<span>] </span>をクリックすると、特定のファイル形式でのみ保存できるダイアログが表示される、といった動作を実現でき、オートメーションなどでユーザーの操作を制限したい場合に活用できます。

&nbsp;

<strong>参考資料</strong>

タイトル<span> : Office UI </span>のカスタマイズ　<span>- Backstage </span>ビュー
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/bf08984t.aspx#Backstage">https://msdn.microsoft.com/ja-jp/library/bf08984t.aspx#Backstage</a></span>

タイトル<span> : Office 2010 </span>の<span> Backstage </span>ビューについて<span> (</span>開発者向け<span>)</span>
アドレス<span> : </span><a href="https://msdn.microsoft.com/ja-jp/library/office/ee691833(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ee691833(v=office.14).aspx</a>

タイトル<span> : Office 2010 </span>の<span> Backstage </span>ビューのカスタマイズ<span> (</span>開発者向け<span>)</span>
アドレス<span> : </span><a href="https://msdn.microsoft.com/ja-jp/library/ee815851(office.14).aspx">https://msdn.microsoft.com/ja-jp/library/ee815851(office.14).aspx</a>

タイトル<span> : Office 2010 Backstage </span>ビューでカスタム コマンドを追加し、コントロールの形式を変更する
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/office/ff634163(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ff634163(v=office.14).aspx</a></span>

タイトル<span> : </span>アドインを作成して<span> Office 2010 </span>の<span> Backstage </span>ビューをカスタマイズする
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/office/ff936212(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ff936212(v=office.14).aspx</a></span>

タイトル<span> : Office 2010 Backstage </span>ビューのグループとコントロールの表示を動的に変更する
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/office/ff645396(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ff645396(v=office.14).aspx</a></span>

タイトル<span> : 3.3 Backstage</span>
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/dd947358(v=office.12).aspx">https://msdn.microsoft.com/en-us/library/dd947358(v=office.12).aspx</a></span>

&nbsp;

<strong>カスタマイズの例</strong>

今回は、<span>2 </span>つのカスタマイズ例をご紹介します。

&nbsp;

<strong>例<span> 1 : </span>既存メニューを無効化する</strong>

例えば<span> Excel </span>をビューアのように使い、ユーザーに可能な限りブックに対する操作をさせたくない場合などに、リボン メニューを消したいという要望を頂くことがあります。

以前の投稿で、<span>startFromScratch </span>を利用して<span> [</span>ファイル<span>] </span>タブ以外のタブを非表示にできることをご紹介しましたが、<span>startFromScratch </span>だけでは<span> [</span>ファイル<span>] </span>タブの操作を抑止できませんでした。このような場合に、<span>BackStage </span>ビューのカスタマイズを合わせて行うことが検討できます。

BackStage ビューのカスタマイズには、<span>&lt;BackStage&gt; </span>要素を使用します。例として、<span>Excel 2016 </span>の既定のメニューをすべて非表示にする場合、以下のように<span> XML </span>を記述します。

ここでは、<span>startFromScratch </span>も合わせて設定しています。また、<span>Excel </span>のバージョンや更新適用状況次第でメニュー名は異なりますので、対象環境のバージョンでのメニューと対応するコントロール名は、パート<span> 5 </span>で紹介したコントロール一覧などからご確認ください<span> ([Tab Set] </span>列が<span> None (Backstage View) </span>の箇所<span>) 。</span>
<pre><code>&lt;customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"&gt;
	&lt;ribbon startFromScratch="true"/&gt;
	&lt;backstage&gt;
		&lt;tab idMso="TabInfo" visible="false"/&gt;
		&lt;tab idMso="TabOfficeStart" visible="false"/&gt;
		&lt;tab idMso="TabRecent" visible="false"/&gt;
		&lt;button idMso="FileSave" visible="false"/&gt;
		&lt;tab idMso="TabSave" visible="false"/&gt;
		&lt;tab idMso="TabPrint" visible="false"/&gt;
		&lt;tab idMso="TabShare" visible="false"/&gt;
		&lt;tab idMso="TabPublish" visible="false"/&gt;
		&lt;tab idMso="Publish2Tab" visible="false"/&gt;
		&lt;button idMso="FileClose" visible="false"/&gt;
		&lt;tab idMso="TabHelp" visible="false"/&gt;
		&lt;tab idMso="TabOfficeFeedback" visible="false"/&gt;
		&lt;button idMso="ApplicationOptionsDialog" visible="false"/&gt;
	&lt;/backstage&gt;
&lt;/customUI&gt;</code></pre>
&nbsp;

この<span> XML </span>を組み込むと、<span>BackStage </span>ビューは以下のようになります。

[caption id="attachment_1645" align="alignnone" width="555"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/02_DisableBackStageMenu.png"><img width="555" height="305" class="size-full wp-image-1645" alt="図 2. BackStage ビューのメニュー無効化後" src="https://msdnshared.blob.core.windows.net/media/2017/12/02_DisableBackStageMenu.png" /></a> 図 2. BackStage ビューのメニュー無効化後[/caption]

&nbsp;

<strong>例<span> 2 : BackStage </span>ビューの遷移を捕捉する</strong>

BackStage ビューが表示されたら、または<span> BackStage </span>ビューからブックに戻ったら<span> xx </span>したい、という場合には、<span>onShow / onHide </span>を使うと、これらのタイミングで指定した関数を実行することができます。先述の公開情報の中でも紹介されています。

タイトル<span> : Office 2010 </span>の<span> Backstage </span>ビューについて<span> (</span>開発者向け<span>)</span>
アドレス<span> : </span><a href="https://msdn.microsoft.com/ja-jp/library/office/ee691833(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ee691833(v=office.14).aspx</a>
該当箇所<span> : Backstage </span>ビューのコントロールの説明、属性、および子情報

&nbsp;

では、実装例です。リボン<span> XML </span>を以下のように記述します。
<pre><code>&lt;customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"&gt;
       &lt;backstage onShow="onShowMethod" onHide="onHideMethod" /&gt;
&lt;/customUI&gt;
</code></pre>
&nbsp;

また、対象ブックの<span> VBA </span>に以下を記述しておきます。
<pre><code>Sub onShowMethod(contextObject As Object)
    MsgBox "BackStage メニューに遷移しました"
End Sub

Sub onHideMethod(contextObject As Object)
    MsgBox "BackStage メニューを閉じてブックに遷移しました"
End Sub
</code></pre>
&nbsp;

このように実装すると、<span>[</span>ファイル<span>] </span>タブをクリックして<span> BackStage </span>メニューを表示したときに<span> onShowMethod </span>が、<span>BackStage </span>メニュー上部の左矢印をクリックしてブックに戻ったときに<span> onHideMethod </span>が実行され、この例の場合はメッセージボックスが表示されます。

<a id="chapter2"></a>
<h4><span style="color: #333399"><strong>2. 右クリック メニューのカスタマイズ</strong></span></h4>
右クリック メニューは、正式にはコンテキスト メニューと呼びます。このコンテキスト メニューも、リボン<span> XML </span>の<span> Office 2010 </span>の名前空間ではカスタマイズすることができます。独自メニューの追加、既存メニューの無効化などができます。

<strong>補足</strong>

Office 2007 の名前空間ではコンテキスト メニューのカスタマイズ方法は用意されていません。<span>Office 2007</span>の場合は、従来通り<span> CommandBars </span>を用いて<span> VBA </span>でカスタマイズします。また、既存メニューの無効化の場合は、リボン メニューの無効化を<span> XML </span>で行うことで、連動してコンテキスト メニューも無効化されます。ただし、<span>CommandBars </span>は、図形 メニューのように一部のメニューは対応していません。<span>(</span>なお、<span>Office 2007 </span>の製品サポートはすでに終了しています。<span>)</span>

&nbsp;

<strong>参考資料</strong>

タイトル<span> : </span>すべてのバージョンの<span> Microsoft Excel </span>でコンテキスト メニューをカスタマイズする
アドレス<span> : <a href="http://msdn.microsoft.com/ja-jp/library/gg469862.aspx">http://msdn.microsoft.com/ja-jp/library/gg469862.aspx</a></span>

タイトル<span> : </span>Office 2010 のコンテキスト メニューのカスタマイズ
アドレス<span> : </span><a href="https://msdn.microsoft.com/ja-jp/library/office/ee691832(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ee691832(v=office.14).aspx</a>

タイトル<span> : </span>3.2 Context Menu
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/dd926324(v=office.12).aspx">https://msdn.microsoft.com/en-us/library/dd926324(v=office.12).aspx</a></span>

&nbsp;

コンテキスト メニューのカスタマイズは、<span>&lt;contextMenu&gt; </span>要素を使用します。メニューの追加は上記参考資料にサンプルがありますので、本記事では既存メニューの無効化のサンプルを紹介します。

&nbsp;

<strong>例<span> : </span>図形の右クリック メニューを無効化する</strong>

右クリックする対象によってコンテキスト メニューの内容は異なりますが、今回は図形を右クリックした場合のコンテキスト メニューを例にします。またバージョンごとにメニュー構成は異なりますが、<span>Excel 2016 </span>のあるバージョンでは、以下のメニューが表示されます。

[caption id="attachment_1655" align="alignnone" width="351"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/03_ContextMenu.png"><img width="351" height="488" class="size-full wp-image-1655" alt="図 3. 図形の右クリック コンテキスト メニュー" src="https://msdnshared.blob.core.windows.net/media/2017/12/03_ContextMenu.png" /></a> 図 3. 図形の右クリック コンテキスト メニュー[/caption]

&nbsp;

以下の<span> XML </span>を既述すると、このコンテキスト メニュー<span> (</span>下側のウィンドウ<span>) </span>を全て表示しないようにできます。
<pre><code>&lt;customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"&gt;
       &lt;contextMenus&gt;
              &lt;contextMenu idMso="ContextMenuShape"&gt;
                     &lt;control idMso="Cut" visible="false"/&gt;
                     &lt;control idMso="Copy" visible="false"/&gt;
                     &lt;control idMso="PasteGalleryMini" visible="false"/&gt;
                     &lt;control idMso="ObjectEditText" visible="false"/&gt;
                     &lt;control idMso="ObjectEditPoints" visible="false"/&gt;
                     &lt;control idMso="ObjectsGroupMenu" visible="false"/&gt;
                     &lt;control idMso="ObjectBringToFrontMenu" visible="false"/&gt;
                     &lt;control idMso="ObjectSendToBackMenu" visible="false"/&gt;
                     &lt;control idMso="InsertLinkGallery" visible="false"/&gt;
                     &lt;control idMso="Insights" visible="false"/&gt;
                     &lt;control idMso="MacroAssign" visible="false"/&gt;
                     &lt;control idMso="ObjectSetShapeDefaults" visible="false"/&gt;
                     &lt;control idMso="ObjectSizeAndPropertiesDialog" visible="false"/&gt;
                     &lt;control idMso="ObjectFormatDialog" visible="false"/&gt;
              &lt;/contextMenu&gt;
       &lt;/contextMenus&gt;
&lt;/customUI&gt;
</code></pre>
&nbsp;

また、上部に表示されている「ミニ ツール バー」<span> (</span>スタイル、塗りつぶし、枠線 のメニュー<span>) </span>は、以下のプロパティかレジストリで制御できます。

&lt;プロパティ<span>&gt;</span>
タイトル<span> : Application.ShowMenuFloaties </span>プロパティ<span> (Excel)</span>
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/VBA/Excel-VBA/articles/application-showmenufloaties-property-excel">https://msdn.microsoft.com/ja-jp/VBA/Excel-VBA/articles/application-showmenufloaties-property-excel</a></span>

注<span> : </span>このプロパティに<span> False </span>を設定すると、ミニ ツール バーが表示されます。<span>True </span>で非表示になります。ただし、設定後にプロパティを取得すると、反対の値が取得されます。<span>(False </span>を設定した場合は、<span>True </span>が取得されます<span>)</span>。分かりづらい動作で申し訳ありませんが、ご注意ください。

&lt;レジストリ<span>&gt;</span>
キー<span> : HKEY_CURRENT_USER\Software\Microsoft\Office\XX.0\Common\Toolbars\Excel
(XX = Office </span>バージョンを表す数字です。<span>2016 </span>の場合、<span>16 </span>になります。<span>)</span>
名前<span> : AllowMenuFloaties</span>
種類<span> : REG_DWORD</span>
値<span> : 1 = </span>表示<span> / 0 = </span>非表示
※ このレジストリは、右クリックの都度参照されるため動的に変更できます。<span>Application.ShowMenuFloaties </span>プロパティを変更すると、このレジストリにも反映されます。

上述の<span> XML </span>とプロパティを設定すると、図形の右クリック メニューを以下のように全て無効化できます。なお、このようにすべて無効化しても、コンテキスト メニューの枠は非表示にできません。

[caption id="attachment_1665" align="alignnone" width="496"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/04_DsiableShapeContextMenu.png"><img width="496" height="204" class="size-full wp-image-1665" alt="図 4. 図形の右クリック コンテキスト メニュー無効化" src="https://msdnshared.blob.core.windows.net/media/2017/12/04_DsiableShapeContextMenu.png" /></a> 図 4. 図形の右クリック コンテキスト メニュー無効化[/caption]

<a id="chapter3"></a>
<h4><span style="color: #333399"><strong>3. クイック アクセス ツールバーのカスタマイズ</strong></span></h4>
Office のメニューには、リボンの他にクイック アクセス ツールバーも用意されています。下の画像の赤枠部分です。

[caption id="attachment_1666" align="alignnone" width="626"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/05_QAT.png"><img width="626" height="254" class="size-full wp-image-1666" alt="図 5. クイック アクセス ツール バー" src="https://msdnshared.blob.core.windows.net/media/2017/12/05_QAT.png" /></a> 図 5. クイック アクセス ツール バー[/caption]

&nbsp;

このクイック アクセス ツールバーも、<span>&lt;qat&gt; </span>というタグで<span> XML </span>からカスタマイズができます<span> (Office 2007 </span>向けの名前空間でも利用可能<span>)</span>。

ただし、<span>startFromScratch </span>が<span> True </span>の場合にしか利用できません。上記の画像のように通常通りメニューが表示されている状態で、かつクイック アクセス ツール バーもカスタマイズする、ということは、一連の記事で紹介しているリボン カスタマイズ手法ではできません。このような場合は、以下の公開情報で紹介しているように、<span>GUI </span>で編集したクイック アクセス ツール バーの情報を保持する<span> XML </span>ファイルを利用する方法が検討できます。

&nbsp;

タイトル<span> : Office 2010 </span>でカスタマイズしたリボンとクイック アクセス ツール バーを展開する
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/office/ee704589(v=office.14).aspx">https://msdn.microsoft.com/ja-jp/library/office/ee704589(v=office.14).aspx</a></span>

本記事では、<span>startFromScratch</span>を<span> True </span>にした上で、ここまでと同様の方法でのカスタマイズする例をご紹介します。
<strong>参考資料</strong>

タイトル<span> : 2.2.32 qat (Quick Access Toolbar)</span>
アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/dd948879(v=office.12).aspx">https://msdn.microsoft.com/en-us/library/dd948879(v=office.12).aspx</a></span>

&nbsp;

<strong>例<span> : </span>組み込みメニューと独自メニューの追加</strong>

以下の<span> XML </span>では、<span>[</span>上書き保存<span>] </span>メニュー<span> (FileSave) </span>と、独自に作成したメニュー<span> (Mymenu) </span>をクイック アクセス ツール バーに表示します。ここでは詳しく解説しませんが、<span>Mymenu </span>ボタンをクリックすると実行される処理<span> (MymenuCallback) </span>は、以前の投稿で解説したようにマクロを用意しておきます。
<pre><code>&lt;customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"&gt;
       &lt;ribbon startFromScratch="true"&gt;
              &lt;qat&gt;
                     &lt;documentControls&gt;
                            &lt;control idMso="FileSave" /&gt;
                            &lt;button id="Mymenu" label="Mymenu" image="MymenuIcon" onAction="MymenuCallback"/&gt;
                     &lt;/documentControls&gt;
              &lt;/qat&gt;
       &lt;/ribbon&gt;
&lt;/customUI&gt;
</code></pre>
&nbsp;

なお今回、アイコン用の画像を<span> image </span>要素で設定しています。<span>Custom UI Editor </span>の場合、独自に用意した画像を以下の赤枠で囲んだ<span> [Insert Icons] </span>メニューから簡単に追加し、アイコンとして利用できます<span> (</span>今回は、サンプルとして作成したハートの絵柄の<span> png </span>ファイルを指定しました<span>)</span>。追加した画像をツリーで右クリックすると、<span>XML </span>から指定するアイコンの<span> ID </span>を変更できます。

[caption id="attachment_1667" align="alignnone" width="1053"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/06_QATXML.png"><img width="1053" height="299" class="size-full wp-image-1667" alt="図 6. Custom UI Editor でのアイコン設定" src="https://msdnshared.blob.core.windows.net/media/2017/12/06_QATXML.png" /></a> 図 6. Custom UI Editor でのアイコン設定[/caption]

&nbsp;

このように記述すると、クイック アクセス ツール バーには以下のように表示されます。

[caption id="attachment_1676" align="alignnone" width="356"]<a href="https://msdnshared.blob.core.windows.net/media/2017/12/07_QATCustomize.png"><img width="356" height="156" class="size-full wp-image-1676" alt="図 7. クイック アクセス ツール バーのカスタマイズ後" src="https://msdnshared.blob.core.windows.net/media/2017/12/07_QATCustomize.png" /></a> 図 7. クイック アクセス ツール バーのカスタマイズ後[/caption]

今回の投稿は以上です。

リボン カスタマイズについてはまだまだ細かいテクニックなどもありますが、<span>Office 2007 </span>以降のリボン カスタマイズをこれから始める方向けに、基本的な要素、よく使われるカスタマイズなどをご紹介してきました。
Office 2007 リリースから<span> 10 </span>年が経過していますが、<span>Office </span>開発 サポートをしていて、まだなかなかこのようなカスタマイズ手法があることが浸透していないと感じます。これからリボン カスタマイズを始める方、既存のソリューションの見直しを考えている方などに、一連の記事が少しでもお役に立てば幸いです。また何かご紹介した方が良い情報がありましたら、リボン カスタマイズについての追加記事を投稿するかもしれません。

&nbsp;

<strong>本情報の内容<span> (</span>添付文書、リンク先などを含む<span>) </span>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>

<strong> </strong>]]></content:encoded>
    </item>
    <item>
      <title>Excel ユーザー定義関数に機能説明や独自ヘルプをリンクする方法</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/udf-help</link>
      <pubDate>Tue, 21 Nov 2017 18:56:45 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1555</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/427e16de-0f6c-4f32-955a-8ce6c71cad77/excel">https://social.msdn.microsoft.com/Forums/ja-JP/427e16de-0f6c-4f32-955a-8ce6c71cad77/excel</a>

&nbsp;

&nbsp;

こんにちは、<span>Office </span>開発サポート チームの中村です。

&nbsp;

Excel には、セルに設定する式として、<span>SUM() </span>のように計算に関するものや、<span>IF() </span>のように論理条件を制御するものなど、様々なワークシート関数が用意されています。既存のワークシート関数で要望を満たすものがない場合、マクロで実装した独自処理を、ユーザー定義関数として登録することができます。

このブログを訪れる方の多くは、ユーザー定義関数を登録すること自体はご存知の方が多いかと思いますが、このようなユーザー定義関数を作成するときにその関数に機能説明やヘルプを追加する方法について、公開情報からは分かりづらい点もありますので、本記事で紹介したいと思います。

&nbsp;
<h4><span style="color: #333399"><strong>1. ユーザー定義関数の作成</strong></span></h4>
関数説明の登録やヘルプのリンクの前に、まずはユーザー定義関数を登録する方法を確認します。

ユーザー定義関数の作成は、<span>VBA </span>の標準モジュールに<span> Function </span>関数を記述するだけですぐに利用できます。以下の例は、<span>TestUDF </span>という名前の関数を作成し、引数<span> 1 </span>に数値、引数<span> 2 </span>に文字列を渡すと、これらを組み合わせて文章を作成して返却する関数です。<span>(Public </span>でなくともユーザー定義関数として利用できます。アドインなどで複数ブックからの利用を想定している場合は<span> Public </span>を付与します。<span>)</span>
<pre><code>Public Function TestUDF(num As Integer, str As String) As String
    TestUDF = "No." &amp; num &amp; "は" &amp; str &amp; "です"
End Function</code></pre>
&nbsp;

このような<span> VBA </span>コードを追加した状態でシート上でセルに直接関数を入力すると、すぐに利用できます。

[caption id="attachment_1565" align="alignnone" width="466"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/01_TestUDF.png"><img width="466" height="331" class="size-full wp-image-1565" alt="図 1. TestUDF 利用イメージ" src="https://msdnshared.blob.core.windows.net/media/2017/11/01_TestUDF.png" /></a> 図 1. TestUDF 利用イメージ[/caption]

<span></span>

&nbsp;

ただこのままの状態では、<span>Excel </span>に標準で用意されているワークシート関数で表示される利用方法の説明やヘルプ ファイルなどが表示されません。

&nbsp;
<h4><span style="color: #333399"><strong>2. 関数の情報を登録する</strong></span></h4>
関数を任意のカテゴリに追加したり、リボン メニューの<span> [</span>数式<span>] </span>タブ<span> – [</span>関数の挿入<span>] </span>で確認できる関数の説明やヘルプをユーザー定義関数にも表示させるには、<span>Application.MacroOptions </span>メソッドを実行します。ユーザー定義関数の機能を提供するマクロ ファイルの<span> Workbook_Open </span>イベントなどで登録するよう実装できます。

&nbsp;

タイトル<span> : Application.MacroOptions </span>メソッド<span> (Excel)</span>
アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/application-macrooptions-method-excel">https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/application-macrooptions-method-excel</a></span>

&nbsp;

例えば以下のように記述して実行すると、下図の画面キャプチャのようにユーザー定義関数の説明を表示できます。
<pre><code>Sub RegisterTestUDF()
    Application.MacroOptions Macro:="TestUDF", Description:="引数 1 と 2 を組み合わせて文章を作成する関数です。", _
    Category:="文字列操作", ArgumentDescriptions:=Array("引数 1 : 整数", "引数 2 : 文字列"), _
    HelpFile:="http://www.microsoft.com/help/helpPage.html"
End Sub</code></pre>
&nbsp;

[caption id="attachment_1595" align="alignnone" width="434"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions1.png"><img width="434" height="421" class="size-full wp-image-1595" alt="図 2. 関数の説明 1" src="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions1.png" /></a> 図 2. 関数の説明 1[/caption]

[caption id="attachment_1605" align="alignnone" width="475"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions2.png"><img width="475" height="307" class="size-full wp-image-1605" alt="図 3. 関数の説明 2" src="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions2.png" /></a> 図 3. 関数の説明 2[/caption]

[caption id="attachment_1615" align="alignnone" width="612"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions3.png"><img width="612" height="667" class="size-full wp-image-1615" alt="図 4. 関数の説明 3" src="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions3.png" /></a> 図 4. 関数の説明 3[/caption]

<span></span>

&nbsp;

<strong>補足</strong>

なお、残念ながら以下のようなセル入力時の関数一覧のツールチップや、関数入力時のインテリセンスは、ユーザー定義関数については表示することはできません。

[caption id="attachment_1575" align="alignnone" width="507"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions_additional1.png"><img width="507" height="574" class="size-full wp-image-1575" alt="図 5. ユーザー定義関数では定義できない情報 1" src="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions_additional1.png" /></a> 図 5. ユーザー定義関数では定義できない情報 1[/caption]

[caption id="attachment_1585" align="alignnone" width="436"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions_additional2.png"><img width="436" height="324" class="size-full wp-image-1585" alt="図 6. ユーザー定義関数では定義できない情報 2" src="https://msdnshared.blob.core.windows.net/media/2017/11/02_MacroOptions_additional2.png" /></a> 図 6. ユーザー定義関数では定義できない情報 2[/caption]

<span></span>

&nbsp;
<h4><span style="color: #333399"><strong>3. ヘルプ情報を登録する</strong></span></h4>
Application.MacroOptions メソッドでは、<span>HelpFile </span>パラメーターで、ユーザー定義関数にヘルプ情報をリンクすることもできます。先述のサンプル コードにもすでに記載してあります。

ヘルプ ファイルをリンクすると、関数の一覧で「この関数のヘルプ」をクリックしたときに、リンクしたヘルプ ページが表示されます。

[caption id="attachment_1616" align="alignnone" width="434"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/03_Help1.png"><img width="434" height="421" class="size-full wp-image-1616" alt="図 7. 関数のヘルプ" src="https://msdnshared.blob.core.windows.net/media/2017/11/03_Help1.png" /></a> 図 7. 関数のヘルプ[/caption]

<span></span>

&nbsp;

<strong>注<span>:</span></strong>

以下のようにカテゴリから関数を選択するときに表示されるヒントの<span> [</span>詳細情報<span>] </span>からヘルプ ページを検索する動作はカスタマイズできません。既定の<span> Excel </span>ヘルプからの<span> Excel </span>関数に関する記事の検索結果が表示されます。<span> </span>

[caption id="attachment_1625" align="alignnone" width="476"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/03_Help2.png"><img width="476" height="519" class="size-full wp-image-1625" alt="図 8. 関数の詳細情報" src="https://msdnshared.blob.core.windows.net/media/2017/11/03_Help2.png" /></a> 図 8. 関数の詳細情報[/caption]

&nbsp;

この<span> HelpFile </span>パラメーターに指定できるファイルには、以下ような種類があります。

&nbsp;

<strong>a. Web </strong><strong>サイトの<span> URL (</span>例<span> : HelpFile:="<a href="http://www.microsoft.com/help/helpPage.html">http://www.microsoft.com/help/helpPage.html</a>")</span></strong>

Web サイト上にヘルプページを公開し、<span>URL </span>を指定することができます。最新の<span>Excel 2016 </span>では、<span>Excel </span>標準のヘルプもすべてオンラインになっています。

なお、ローカル<span> PC </span>に<span> .html </span>ファイルを格納して、ローカル パスを指定することはできません。

&nbsp;

<strong>b. .chm </strong><strong>ファイル<span> (</span>例<span> : HelpFile:="C:\AppName\HelpFile.chm")</span></strong>

インターネットに接続できない環境などでは、ローカル<span> PC </span>等に<span> .chm </span>形式で作成したファイルのパスを指定することもできます。

ただし、<span>.chm </span>を作成する「<span>HTML Help Workshop</span>」アプリケーションは既にサポートを終了した製品となります。現在も以下のリンクよりダウンロードを行うことはできますが、作成方法については開発者の皆様自身でご解決ください。

&nbsp;
<p style="padding-left: 30px"><strong>関連情報</strong></p>
<p style="padding-left: 30px">タイトル<span> : </span>カスタム ヘルプ トピックの作成</p>
<p style="padding-left: 30px">アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/cc389851.aspx">https://msdn.microsoft.com/ja-jp/library/cc389851.aspx</a></span></p>
<p style="padding-left: 30px">タイトル<span> : Microsoft HTML Help Downloads</span></p>
<p style="padding-left: 30px">アドレス<span> : <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms669985(v=vs.85).aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/ms669985(v=vs.85).aspx</a></span></p>
<p style="padding-left: 30px">タイトル<span> : HTML Help Workshop and Documentation</span></p>
<p style="padding-left: 30px">アドレス<span> : <a href="https://www.microsoft.com/en-us/download/details.aspx?id=21138">https://www.microsoft.com/en-us/download/details.aspx?id=21138</a></span></p>
&nbsp;

<strong>c. .hlp </strong><strong>ファイル<span>(</span>例<span> : HelpFile:="C:\AppName\HelpFile.htm")</span></strong>

ローカル<span> PC </span>等に格納した<span> WinHelp (.hlp) </span>形式のファイルのパスを指定することもできます。

ただし、<span>WinHelp </span>形式は古いファイル形式となりますので、<span>Windows Vista </span>以降の<span> OS </span>では既定では開くことができません。以下のサポート技術情報の<span> [</span>解決策<span>] </span>でご案内している更新プログラムを適用する必要があります。また、<span>Windows 10 </span>向けには更新プログラムは用意されておらず、<span>WinHelp </span>ファイルはサポートされません。

&nbsp;
<p style="padding-left: 30px"><strong>.hlp </strong><strong>ファイルを開くのに必要な更新プログラム</strong></p>
<p style="padding-left: 30px">文書番号<span> : 917607</span></p>
<p style="padding-left: 30px">タイトル<span> : Windows </span>ベースのプログラムでヘルプを開こうとすると、「機能は含まれていません」または「ヘルプはサポートされていません」とエラーが表示されます</p>
<p style="padding-left: 30px">アドレス<span> : <a href="https://support.microsoft.com/ja-jp/help/917607">https://support.microsoft.com/ja-jp/help/917607</a></span></p>
&nbsp;
<p style="padding-left: 30px"><strong>参考資料</strong></p>
<p style="padding-left: 30px">タイトル<span> : </span>ヘルプ ファイル<span> (WinHelp)</span></p>
<p style="padding-left: 30px">アドレス<span> : <a href="https://msdn.microsoft.com/ja-jp/library/ew744dk7.aspx">https://msdn.microsoft.com/ja-jp/library/ew744dk7.aspx</a></span></p>
&nbsp;

今回の投稿は以上です。

&nbsp;

<strong>本情報の内容<span> (</span>添付文書、リンク先などを含む<span>) </span>は、作成日時点でのものであり、予告なく変更される場合があります。</strong>]]></content:encoded>
    </item>
    <item>
      <title>Office リボンをカスタマイズ – パート6 – (TIPS 2 : 動的なカスタマイズ)</title>
      <link>https://docs.microsoft.com/archive/blogs/office_client_development_support_blog/customize-ribbon-part6</link>
      <pubDate>Thu, 09 Nov 2017 16:27:29 GMT</pubDate>
      <dc:creator><![CDATA[Office Integration Support]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/office_client_development_support_blog/?p=1525</guid>
      <description><![CDATA[※ この記事は以下の Office サポート...]]></description>
      <content:encoded><![CDATA[<span style="color: #ff6600">※ この記事は以下の Office サポート フォーラムに移行しました。</span>

<a href="https://social.msdn.microsoft.com/Forums/ja-JP/64456a56-a605-4903-bf14-93633bf6d514/office-6-tips-2-">https://social.msdn.microsoft.com/Forums/ja-JP/64456a56-a605-4903-bf14-93633bf6d514/office-6-tips-2-</a>

&nbsp;

こんにちは、Office 開発サポート チームの中村です。

今回の記事では、<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2017/11/06/customize-ribbon-part5/">前回の投稿</a>に引き続き、リボン カスタマイズ方法の例をご紹介します。

&nbsp;

<a href="https://blogs.msdn.microsoft.com/office_client_development_support_blog/2017/03/06/customize-ribbon-part2/">以前の投稿</a>で紹介した方法で、リボンのカスタマイズがファイル単位でできることはお伝えしましたが、以下のような状況の開発者の方もいるのではないでしょうか。

・アドインとして提供する 1 つのプログラムから、ファイルによってリボンの内容を変えたい (ファイルにカスタマイズを組み込みたくない)
・Office 97-2003 形式 (.xls 等) のファイルにリボン カスタマイズを行いたい
・ブック内での操作に応じて動的にリボンの状態を変えたい

&nbsp;

これらの要望は、Office 2007 形式のアドイン (.xlam 等)、または VSTO カスタマイズで実現できますので、以下に具体例を用いて紹介します。Excel のカスタマイズを行われることが多いので、(これまでの記事を含め) 以下はすべて Excel を例に説明していますが、他の Office アプリケーションでも利用できます。

&nbsp;

<strong><b>目次</b></strong>

<a href="#chapter1">1. .xls 形式のファイルのリボン カスタマイズを行う (アドインからファイルごとにリボンをカスタマイズする)</a>
<a href="#chapter2">2. 任意のタイミングでリボンの状態を変更する</a>

<a id="chapter1"></a>
<h4><strong><span style="color: #333399">1. .xls 形式のファイルのリボン カスタマイズを行う (アドインからファイルごとにリボンをカスタマイズする)</span></strong></h4>
.xlsx / .xlsm 形式のファイルであれば、リボン カスタマイズの XML をファイル内に組み込むことができました。一方、.xls 形式のファイルはバイナリ ファイルなのでファイル内に customUI14.xml を組み込むことができません。

では、.xls ファイルでこれを実現したい場合にはどうすればいいかというと、以下のような手法が考えられます。
<ul>
 	<li>.xlam 形式の Excel アドインを用意する</li>
 	<li>VSTO アドインを用意する</li>
 	<li>VSTO で Excel ブック (.xls) 形式のカスタマイズを作成する</li>
</ul>
アドインに組み込んだカスタマイズを利用して、.xls 形式のファイルにもカスタマイズ情報を反映させることができます。また VSTO の場合、VSTO の仕組みとして XML を組み込むので、.xls 形式の VSTO ブックを作成することもできます。また、.xls 形式だけでなくとも、ファイルによってリボン メニューを変えたいが、ファイルごとにカスタマイズを組み込むのは難しい・・という場合もあるかと思いますので、そういった場合にもアドインからカスタマイズする方法は検討できます。

&nbsp;

今回は、.xlam 形式のアドインで、開いたファイル名によって異なるメニューを表示する方法のサンプルを例に解説します。まずは、サンプルの作成手順です。

&nbsp;

<strong>手順</strong>

1.  新規 Excel 新規 Excel ブックを作成し、Visual Basic Editor で標準モジュールに以下のコードを記述します。
<pre><code>Public Sub GetEnabledMacro(control As IRibbonControl, ByRef Enabled)
    If control.ID = "B1_Button1" Then
        If ActiveWorkbook.Name = "Book1.xls" Then
            Enabled = True
        Else
            Enabled = False
        End If
    ElseIf control.ID = "B2_Button1" Then
        If ActiveWorkbook.Name = "Book2.xls" Then
            Enabled = True
        Else
            Enabled = False
        End If
    End If
End Sub

'以下はボタンクリック時に実行されるマクロ
Public Sub B1_Button1_Callback(control As IRibbonControl)
    MsgBox "Book1 用のボタンをクリックしました"
End Sub

Public Sub B2_Button1_Callback(control As IRibbonControl)
    MsgBox "Book2 用のボタンをクリックしました"
End Sub</code></pre>
2. ファイルを .xlam 形式で保存します。

3.  Custom UI Editor for Microsoft Office で保存した .xlam ファイルを開き、customUI14.xml を追加して以下のように記述して保存します。
<pre><code>
&lt;customUI xmlns="<a href="http://schemas.microsoft.com/office/2009/07/customui">http://schemas.microsoft.com/office/2009/07/customui</a>"&gt;
    &lt;ribbon&gt;
        &lt;tabs&gt;
            &lt;tab id="customTab" label="Custom Tab"&gt;
                &lt;group id="CustomGroup" label="Custom Menu"&gt;
                    &lt;button id="B1_Button1" label="Book1 button" imageMso="HappyFace" size="large" getEnabled="GetEnabledMacro" onAction="B1_Button1_Callback" /&gt;
                    &lt;button id="B2_Button1" label="Book2 button" imageMso="HappyFace" size="large" getEnabled="GetEnabledMacro" onAction="B2_Button1_Callback" /&gt;
                &lt;/group&gt;
            &lt;/tab&gt;
        &lt;/tabs&gt;
    &lt;/ribbon&gt;
&lt;/customUI&gt;
</code></pre>
&nbsp;

作成したアドインを有効化した状態で、ブックを開くと以下のようになります。

&lt;Bool1.xls を開いた場合&gt;

[caption id="attachment_1535" align="alignnone" width="752"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Book1.png"><img width="752" height="354" class="size-full wp-image-1535" alt="図 1. Book1.xls を開いた場合" src="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Book1.png" /></a> 図 1. Book1.xls を開いた場合[/caption]

&lt;Book2.xls を開いた場合&gt;

[caption id="attachment_1545" align="alignnone" width="752"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Book2.png"><img width="752" height="354" class="wp-image-1545 size-full" alt="図 2. Book2.xls を開いた場合" src="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Book2.png" /></a> 図 2. Book2.xls を開いた場合[/caption]

&lt;その他のブックを開いた場合&gt;

[caption id="attachment_1546" align="alignnone" width="752"]<a href="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Other.png"><img width="752" height="399" class="size-full wp-image-1546" alt="図 3. その他のブックを開いた場合" src="https://msdnshared.blob.core.windows.net/media/2017/11/DynamicEnable_Other.png" /></a> 図 3. その他のブックを開いた場合[/caption]

&nbsp;

<strong>解説</strong>
この動作は、XML で button コントロールの getEnabled プロパティを使用することで実現しています。

タイトル : Button.GetEnabled property
アドレス : <a href="https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.button.getenabled.aspx">https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.button.getenabled.aspx</a>

サンプルのこの赤字の部分です。

&lt;button id="B1_Button1" label="Book1 button" imageMso="HappyFace" size="large" <span style="color: #ff0000">getEnabled="GetEnabledMacro"</span> onAction="B1_Button1_Callback" /&gt;
&lt;button id="B2_Button1" label="Book2 button" imageMso="HappyFace" size="large" <span style="color: #ff0000">getEnabled="GetEnabledMacro"</span> onAction="B2_Button1_Callback" /&gt;

&nbsp;

getEnabled プロパティが設定されていると、リボンのロード時 (リボンを持つブックが開かれたタイミングで実行されます) に、指定したメソッドを実行してコントロールの有効化状態を取得します。
GetEnabledMacro メソッドは、アドイン ブックの標準モジュールに定義されており、ブック名とコントロール名に応じて第 2 引数 enabled に Boolean 値を返します。リボンのロード 処理は、ここで返された値に従って、コントロールを有効化 / 無効化します。

<a id="chapter2"></a>
<h4><span style="color: #333399"><strong>2. 任意のタイミングでリボンの状態を変更する</strong></span></h4>
1. の例ではリボンのロード時に制御していますが、ブック内での操作に応じて有効化状態を変更することもできます。以下のように onload プロパティと Invalidate 系メソッドを用いて実装します。

&nbsp;

<strong>手順</strong>

1. 任意のタイミングでリボン オブジェクトを操作できるよう、以下のように CustomUI クラスの onLoad プロパティを利用してリボン オブジェクトを格納しておきます。

タイトル : CustomUI.OnLoad property
アドレス : <a href="https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.customui.onload.aspx">https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.customui.onload.aspx</a>

&lt;XML&gt;
<pre><code>&lt;customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="ribbonLoaded"&gt;
    &lt;ribbon&gt;
        ・・・
    &lt;/ribbon&gt;
&lt;/customUI&gt;
</code></pre>
&lt;VBA&gt;
<pre><code>'XML の onLoad 定義から呼び出されるマクロ
Public Sub ribbonLoaded(ribbon As IRibbonUI)
    Set myRibbon = ribbon
End Sub</code></pre>
&nbsp;

onLoad プロパティで定義したメソッドはリボンのロード時呼び出されます。既定では、リボンのロードはブックごとにオープン時に行われます。上記のように実装すると、ブックが開かれて初めにリボンがロードされたときに myRibbon にブックのリボン オブジェクトが格納されます。

&nbsp;

2.  次に、リボンの制御を行いたい処理 (例えば、リボンのあるカスタム ボタンをクリックしたら、等) で、以下のいずれかのメソッドでリボンの再読み込みを実行します。これらのメソッドが実行されると、対象のコントロールの XML 定義に従ったリボンのロード処理が再実行されるので、getEnabled の再評価が行われます。

&nbsp;

タイトル : IRibbonUI.Invalidate method
アドレス : <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidate.aspx">https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidate.aspx</a>
リボン全体を再読み込みします。

タイトル : IRibbonUI.InvalidateControl method
アドレス : <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidatecontrol.aspx">https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidatecontrol.aspx</a>
引数で指定したカスタム コントロールのみを再読み込みします。

タイトル : IRibbonUI.InvalidateControlMso method
アドレス : <a href="https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidatecontrolmso.aspx">https://msdn.microsoft.com/en-us/library/office/microsoft.office.core.iribbonui.invalidatecontrolmso.aspx</a>
引数で指定した Office 組み込みのコントロールのみを再読み込みします。(既定のボタンから呼び出される処理を XML でカスタマイズしている場合などに利用します。)

&nbsp;

これらのメソッドは、以下のように 1. でリボンを格納した myRibbon オブジェクトを用いて呼び出します。(Invalidate の場合)
<p style="padding-left: 30px">myRibbon.Invalidate</p>
&nbsp;

3. あとは、getEnabled から呼び出されるメソッドで、動的に制御したい条件で Enabled フラグを設定する処理を追加します。(例 : シートの変更イベントでリボンの再ロードを呼び出し、アクティブなシートによって有効なボタンを切り替える)

前回の投稿と同じく、コントロールによって getEnabled 以外にも様々なプロパティが利用できますので、以下の資料などで確認してみてください。

タイトル : 2007 Office Fluent リボンをカスタマイズする (開発者向け) (パート 2/3)
アドレス : <a href="https://msdn.microsoft.com/ja-jp/library/aa338199(v=office.12).aspx">https://msdn.microsoft.com/ja-jp/library/aa338199(v=office.12).aspx</a>

タイトル : DocumentFormat.OpenXml.Office2010.CustomUI namespace
アドレス :<a href="https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.aspx"> https://msdn.microsoft.com/en-us/library/office/documentformat.openxml.office2010.customui.aspx</a>

&nbsp;

次回は、BackStage メニューや、右クリック メニュー (コンテキスト メニュー) などのカスタマイズ方法について紹介したいと思います。

&nbsp;

今回の投稿は以上です。

<strong>本情報の内容 (添付文書、リンク先などを含む) は、作成日時点でのものであり、予告なく変更される場合があります。</strong>

&nbsp;]]></content:encoded>
    </item>
  </channel>
</rss>