Hey, Scripting Guy!

Scripting Guys が皆さんの質問にお答えします

Hey, Scripting Guy!

TechNet コラムへようこそ。このコラムでは、よく寄せられるシステム管理スクリプトに関する質問に Scripting Guys がお答えします。システム管理スクリプトについて質問がある場合は、scripter@microsoft.com (英語のみ) までお送りください。すべての質問に回答することはできないかもしれませんが、可能な限り対応いたします。

詳細情報

Hey, Scripting Guy! カテゴリ別アーカイブ

Hey, Scripting Guy! 日付別アーカイブ

Hey, Scripting Guy! ダウンロード

Spacer

*

Excel ワークシート内のすべてのリンクを更新してから解除する方法はありますか

Hey, Scripting Guy! Question

Scripting Guy さん、よろしくお願いします。Excel ワークシートを開き、別の Excel ワークシートへのリンクをすべて更新してから、それらのリンクを解除する方法はありますか。

-- YH

SpacerHey, Scripting Guy! AnswerScript Center

YH さん、こんにちは。まず最初に、1 つ発表があります。このコラムを執筆している Scripting Guy は降参します。

正直なところ、そんなことを言うつもりはありませんでした。というのも、このコラムを執筆している Scripting Guy は、決してあきらめたりしないからです。たとえば、1 週間ほど前、この Scripting Guy は自分の息子と 100 メートル走の勝負をしました。父親よりも体が大きく、俊敏で、(若干) 若い息子が、少なくとも 5 〜 6 メートルの差で勝ちました。では、父親はあきらめたでしょうか。いいえ。それどころか、その競争以降、再度勝負を挑んだときに勝てる方法をひたすら考え続けました。

: ご参考までに、これまでに彼が思い付いたのは、アクメ社の筋肉増強ビタミンを 1 瓶購入して飲むという作戦だけです。確かに、たいした作戦ではありません。とは言え、ワイリー コヨーテにとっては非常に良い作戦でした。

まあ、少なくとも私たちはそうだったと思っています。実は、その作戦が実行される回のストーリーの結末を見たことはありません。

しかし、100 メートル走は簡単です。筋肉増強ビタミンを摂取して、進んでズルをしようという場合にはなおさらです。ただ残念なことに、このコラムを執筆している Scripting Guy でも対処できない問題が 1 つあります。それは、スーパーのエクスプレス レーンです。

他の地域のスーパーにエクスプレス レーンの設置状況はわかりませんが、米国の大型スーパーには通常 1 つ以上のエクスプレス レーンが設置されています。それは、購入する品物の数が x 個以下の人のためのレジです。

余談 : 「他の地域」という表現を使用しましたが、このコラムを執筆している Scripting Guy は、それで最近参加した会議を思い出しました。その会議では、「ユーザーの 42% がアメリカ人で、39% が外国人です」という説明がありました。42% と 39% を足してみると、この統計値のおもしろさがわかっていただけると思います。

とにかく、エクスプレス レーンの背景には優れた考えがあります。それは、購入する品物がパン 1 斤や牛乳 1 パックだけの場合には、この 1000 年間を通じて足りるだけの食料を買おうとしている生存主義者の集団の列に並ぶ必要がない、ということです。エクスプレス レーンにひょいと入って、パン 1 斤分の支払いをし、普段の生活に戻れます。良い考えですね。しかし、実際のことろ、別の面ではまともで法に従う市民が、エクスプレス レーンを台無しにしています。列をすり抜けようとして入念に練ったたくらみをやってのけることもあれば、品物の数が 10 個までの列に平然と 13 個の品物を持っていき、止めれるものなら止めてみろと店員を挑発することもあります。では、スーパーはこの状況にどう対応しているでしょうか。数年前、このコラムを執筆している Scripting Guy が買い物をするスーパーでは、持ち込める品数を 10 個までから 15 個までに増やしました。残念ながら、それはうまくいきませんでした。うまくいくどころか、人々は、15 個までの列にこっそり 18 個の品物を持ち込もうとするようになりました。では、それに対してスーパーは何をしたでしょうか。そうです、そのとおりです。先日、そのスーパーでは、エクスプレス レーンの制限を 20 個にまで増やしました。

言うまでもなく、エクスプレス レーンでの不正行為について、これ以上怒ってわめき散らしても意味はありません。ですから降参します (それに、どのみち近いうちに、制限を超えた数の品物をカートで運ぶことが物理的に不可能になるところまで、その制限数が引き上げられますから)。これからは、何個の品物を持っていても自由にエクスプレス レーンを通ってください。もう何も言いません。

何とおっしゃいましたか。はい、確かに、Excel ワークシート内のすべてのリンクを更新してから解除するスクリプトについても、まだ一言も触れていませんね。でも、心配はいりません。やはり、百聞は一スクリプトにしかず (もとい、百聞は一見にしかず)、ですよね。では、そうしましょう。

Const xlLinkTypeExcelLinks = 1
Const xlExcelLinks = 1

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True

Set objWorkbook = objExcel.Workbooks.Open("C:\Scripts\Test.xls", 3)

arrLinks = objWorkbook.LinkSources(xlLinkTypeExcelLinks)

For i = 1 to Ubound(arrLinks)
    objWorkbook.BreakLink arrLinks(i), xlLinkTypeExcelLinks
Next

では、このスクリプトのしくみについて簡単にご説明しましょう。まず、xlLinkTypeExcelLinks という名前の定数を定義して値を 1 に設定します。この定数を使用して、"Excel の種類のリンク"、つまり、別のセル、ワークシート、またはブックへのリンクを操作することをスクリプトに指示します。その他に、ここで使用できる定数はあるでしょうか。1 つには、xlLinkTypeOLELinks 定数 (値は 2) があります。OLE オブジェクト (ワークシート内に埋め込まれた Word 文書や PowerPoint プレゼンテーションなど) を操作する場合には、この定数を使用します。ただし、今回は OLE オブジェクトを操作する必要はないので、この話は忘れてください。

次に、別の定数 (xlExcelLinks) を定義してその値を 1 に設定します。この定数は、ブックに含まれる Excel の種類の全リンクのコレクションを取得する際に使用します。もちろん、単に同じ定数 (xlLinkTypeExcelLinks) を両方の場所で使用することもできました。というのも、どちらの値も同じ (1) で、共に同じ種類のリンクを指しているからです。とは言え、ここでは 2 つの異なる定数を使用することにしました。それは、スクリプトを公式な Excel ドキュメントの内容に合わせるためという単純な理由からです。

2 つの定数を定義したら、Excel.Application オブジェクトのインスタンスを作成し、Visible プロパティを True に設定します。この設定により、画面上に表示される Execl の実行インスタンスが作成されます。では、次の行に移りましょう。

Set objWorkbook = objExcel.Workbooks.Open("C:\Scripts\Test.xls", 3)

ご覧のとおり、ここでは、Open メソッドを呼び出して C:\Scripts\Test.xls というブックを開きます。既に何度も見たことがあると思うので、これについては問題ありませんよね。しかし、メソッド呼び出しの最後にある 2 つ目のパラメータ "3" は何でしょうか。

よくぞ聞いてくれました。Open メソッドの省略可能な 2 つ目のパラメータでは、これから開くワークシート内のすべてのリンクに対する処理を指定します。3 という値を追加したのは、これによって、開いたときにブック内のすべてのリンクが更新されるためです。また、この 2 つ目のパラメータに 2 を指定することもできます。この値を指定すると、どのリンクも更新されることなくファイルが開かれます。または、これは省略可能なパラメータなので省略することもできます。その場合には、ファイルを開くたびにリンクを更新するかどうかを確認するメッセージが表示されます。

つまりこういうことです。Open メソッドの 2 つ目のパラメータに 3 を指定することで、すべてのリンクを更新できます。

そして、これは、リンクの数が 20 未満であるか 20 以上であるかにかかわらず同じです。

もちろん、リンクの更新が終わっても、処理の半分が終わったにすぎません。リンクを更新したら、今度は、それらの各リンクを解除する必要があります。難しそうに聞こえますか。心配は要りません。解除したり壊したりする作業は、Scripting Guys が最も得意とするところです。

実際にあった話ですが、Scripting Guy の Jean Ross は、かつて、ドアを開けようとノブを回して手前に引いただけで、ヒンジを外してドアごともぎ取ったことがあります。それ以降、Scripting Guy の Jean Ross は欲しい物を何でも手に入れています。

私たちが知る限り、ブック内のリンクは 1 つずつ解除する必要があります。それを念頭に置いて、次のコード行を使用し、ファイルに含まれる Excel の種類の全リンクのコレクションを取得して、そのコレクションを arrLinks という名前の配列に格納します。

arrLinks = objWorkbook.LinkSources(xlLinkTypeExcelLinks)

これで、リンクの解除を開始する準備ができました。それらのリンクを 1 つずつ解除するには、1 〜 n (コレクション内のリンクの総数) 回実行される For Next ループを設定します (つまり、arrLinks 配列の上限 (Ubound) に達するまで実行されます)。

For i = 1 to Ubound(arrLinks)

: ご存じのとおり、ほとんどの配列は 0 から始まります。配列の最初の項目のインデックス番号は、ほぼ必ず 0 です。しかし、どういうわけか Microsoft Office の配列は、通常 1 から始まります。配列の最初の項目のインデックス番号は 0 ではなく 1 です。そのため、この For Next ループは 0 ではなく 1 から始まります。

ご参考までにお伝えしました。

では、この For Next ループでは何を行うのでしょうか。次のコードを実行します。

objWorkbook.BreakLink arrLinks(i), xlLinkTypeExcelLinks

ご覧のとおり、ここではそれほど変わったことは行っていません。BreakLink メソッドを呼び出して、そのメソッドに次の 2 つのパラメータを渡しているだけです。

arrLinks(i): コレクション内の個々のリンクへの参照です。1 回目のループ処理では、コレクション内の最初のリンクを操作します。それがどうしてわかるかというと、カウンタ変数 i が 1 から始まるためです。

xlLinkTypeExcelLinks: 解除する必要があるリンクの種類を識別する定数です。

これで作業はほとんど完了です。ループ処理が完了すると、ブック内のすべてのリンクは解除されます。

YH さん、これでうまくいくでしょう。質問がある場合はお知らせください。おっと、それから、質問の数が 20 個以下の場合には、Scripting Guys エクスプレス レーン宛てに送るようにしてください。そうすれば・・・。いや、何でもありません。23 個でも 29 個でも 578 個でも、質問がある場合にはすべてエクスプレス レーン宛てにお送りください。疲れているときには気付きます。


ページのトップへページのトップへ