Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10全般 : Excel 2019)
外部リンクを発生させない方法
投稿日時: 23/09/24 23:10:30
投稿者: たっくんプードル

1.毎営業日、1ブック1シートで集計表(データベース)を作っています。
この集計表にはオートフィルタを適用しており、オートフィルタでの抽出等に関するプロシージャを作成し、当該シート上に設けたマクロボタン(フォームコントロール)に割り当てています。
2.翌営業日は、1.のブックをコピーし集計表に入力します。
3.毎営業日ごとにこれを繰り返し、当月分を翌月初めに合計集計します。
 
4.当然、毎営業日同じ形式のシートですので、集計用新規ブックに当月分のすべてのブック内のシートをコピーしてきて、串刺し計算シートにて当月分の合計集計をします。
 
4.の作業はマクロで自動化していますが、ここで、問題が発生しました。
 
毎営業日のシートコピー及び串刺し計算シートが出来上がり、保存したファイルを再度開くと、
「このブックには、安全ではない可能性のある外部ソースへのリンクが1つ以上含まれています。リンクを信頼できる場合、リンクを更新して最新データを取り込みます。信頼できない場合は、データをそのまま手元で処理してかまいません。」が表示されます。
 
集計用新規ブック内の各シートには、1.のとおりマクロボタンがあり、この各シートのマクロボタンを押すと、コピー前の毎営業日の元ブックを開いてプロシージャが実行されます。
外部へのリンクは、各シートに設けたマクロボタンに割り当てたプロシージャ以外ありませんでした。
 
上記外部リンクのエラーは、いったん「更新しない」にした後、「リンクの編集」でメッセージを出さないようにすることは可能ですが、そもそもプロシージャの記述の方法でこれを回避するような手法はあるでしょうか。

回答
投稿日時: 23/09/25 06:40:32
投稿者: WinArrow

これはエラーではなくアラームです。
 
おそらく、セルに入力してある数式の中で、外部ブックを参照しているものと思います。
 
そのあたりを説明して頂くと、対応策がでるかもしれません。

回答
投稿日時: 23/09/25 09:44:08
投稿者: WinArrow

初めに
状況を整理し、質問事項を書き出してみました。
 
1.ブックとシートの関係
(1)営業日別に1ブック、1シート
  このブックは、入力作業用ですか?
  つまり、集計表に複写した後、翌営業日棟として使用する・・・ということすか?
(2)集計用ブックには、営業日用のシートを複写する。
 複写の方法は、シート毎複写する・・・・計算式が入っていると、集計用ブックとしては
  (1)のブックへの外部参照となる可能性がたかい。
 
  翌月用の集計用ブックは、いつどのように作成するのですか?
 
 

回答
投稿日時: 23/09/25 10:55:00
投稿者: higejee

たっくんプードル さんの引用:
1.毎営業日、1ブック1シートで集計表(データベース)を作っています。
この集計表にはオートフィルタを適用しており、オートフィルタでの抽出等に関するプロシージャを作成し、当該シート上に設けたマクロボタン(フォームコントロール)に割り当てています。
〜(中略)〜
4.当然、毎営業日同じ形式のシートですので、集計用新規ブックに当月分のすべてのブック内のシートをコピーしてきて、串刺し計算シートにて当月分の合計集計をします。

ということは集計用新規ブックにコピーされたすべての営業日別シートには同じマクロボタンがあるということ。ただし登録されているマクロは各営業日のブック(つまり外部ソース)のものだから、ワーニングが出て当然です。
 
 新規ブックに集計した時点でマクロボタン自体が不要であれば、全シートのマクロボタンを削除してから保存すればよいかと。

回答
投稿日時: 23/09/25 12:31:57
投稿者: WinArrow

そうか・・・・マクロがありましたね・・・・
 
集計用ブックに複写をマクロの中でやっているのですか?
もし、そのマクロの中に、集計用ブックに複写後、マクロ起動用ボタンを削除するとよいでしょう。

投稿日時: 23/09/25 23:28:23
投稿者: たっくんプードル

WinArrow さんの引用:
これはエラーではなくアラームです。
 
おそらく、セルに入力してある数式の中で、外部ブックを参照しているものと思います。

セル内の可能性は確認しましたのでないはずです。文字列内に「!」が含まれていないか、名前の定義、条件付き書式等、外部参照の可能性がある場所は検索しました。
プロシージャ内しか考えられない、という結論に至っています。

投稿日時: 23/09/25 23:41:56
投稿者: たっくんプードル

WinArrow さんの引用:
1.ブックとシートの関係
(1)営業日別に1ブック、1シート
  このブックは、入力作業用ですか?
  つまり、集計表に複写した後、翌営業日棟として使用する・・・ということすか?
(2)集計用ブックには、営業日用のシートを複写する。
 複写の方法は、シート毎複写する・・・・計算式が入っていると、集計用ブックとしては
  (1)のブックへの外部参照となる可能性がたかい。
 
  翌月用の集計用ブックは、いつどのように作成するのですか?
 
 

(1)毎営業日のブックは単純な入力&集計表(最終行に合計がある)です。
主なフィールド・・・[項目][単価][件数][単価*件数]
(質問に記載の1.のとおり)
次の日は、前日のブックをコピーして新規作成し、入力していきます。(毎日繰り返し)
(質問に記載の2.のとおり)
 
(2)翌月初めに集計用の月締めブック内には、前月毎営業日(1-31日)のブックを順に開いて、シートごとコピーしてくる、というマクロがあります。
(質問に記載の3.4.のとおり)

投稿日時: 23/09/25 23:59:10
投稿者: たっくんプードル

higejee さんの引用:

ということは集計用新規ブックにコピーされたすべての営業日別シートには同じマクロボタンがあるということ。ただし登録されているマクロは各営業日のブック(つまり外部ソース)のものだから、ワーニングが出て当然です。
 
 新規ブックに集計した時点でマクロボタン自体が不要であれば、全シートのマクロボタンを削除してから保存すればよいかと。

 
複写してきたシートには、もともとのマクロボタンがそのままあるのは、おっしゃるとおりです。また、マクロ自体が元ブックに依存しているので、ワーニングが出て当然なのも、おっしゃるとおりです。
ですが、このマクロボタンは、集計表のオートフィルタによる抽出を楽にするために設けたボタンなので、月締め集計ブックに複写してきた後もボタンは必要なので、消すわけにはいかないのです。
ですので、今回の質問に至った次第です。
 
想定される解決法として思いつくのは、
1.日々の毎営業日用シートのマクロボタンに割り当てられたプロシージャを、シートが別ブックにコピーされても影響されないような書き方にする。
2.月締め集計ブックに複写された後、このブック内に複写された全シート内の外部リンクとなった部分を書き換える。
くらいかな、と想定はするものの具体的にどうプロシージャを記述するかまでは思いつけません・・・

回答
投稿日時: 23/09/26 08:25:23
投稿者: higejee

たっくんプードル さんの引用:
複写してきたシートには、もともとのマクロボタンがそのままあるのは、おっしゃるとおりです。また、マクロ自体が元ブックに依存しているので、ワーニングが出て当然なのも、おっしゃるとおりです。

 であるなら
たっくんプードル さんの引用:
想定される解決法として思いつくのは、
1.日々の毎営業日用シートのマクロボタンに割り当てられたプロシージャを、シートが別ブックにコピーされても影響されないような書き方にする。

ということが無意味(というか不可能)だと理解できるかと思います。なぜならボタンマクロ登録されたプロシージャ名には元のブック名がひっついてますから。
 
 ボタン自体を消したくないなら集計用ブックに同じ処理を行うプロシージャを用意して、OnAction でボタンのマクロ登録を変更すればよいと思います。

回答
投稿日時: 23/09/26 09:31:05
投稿者: simple

要するに、ボタンに登録されたマクロがリンクされている実体ですね?
フォームボタンに登録されたマクロということは、
・それは標準モジュールに書かれたマクロであり、
・それらは全て同一内容のコードであり、
・操作対象シートは(ひとつしかシートはないので)特に指定しておらず、アクティブシートである。
ということですね?
 
そうであれば、
(1)そのマクロをひとつだけ(同一なので)、
   集計用ブック(つまり、自分自身)の標準モジュールに手でコピーしておき、
(2)リンク元を、強制的に自分自身(つまり、集計用ブック)に付け替えてしまえばいいですね。
 
例えば、以下のようなマクロを実行すればよいのでは?

Sub test()
    Dim linksource As Variant
    For Each linksource In ThisWorkbook.LinkSources
        ThisWorkbook.ChangeLink Name:=linksource, _
            NewName:=ThisWorkbook.Name, _
            Type:=xlExcelLinks
    Next
End Sub

# 個人的には、ボタンに登録されたマクロを使う機会が無いような気がしないでもありません。

回答
投稿日時: 23/09/26 10:01:48
投稿者: WinArrow

私見です。
 
マウロは、
営業日ブック内での処理で、完結していると思います。
 
マクロ起動用ボタンを
別の集計用ブックに複写するということは、
営業日ブックのマクロが実行される可能性を含んでいます。
間違って、そのボタンをクリックすると、(どのブックかわからない状態で)
実行されることを想定しなくてよいのか?
という疑問(懸念)があります。
 

回答
投稿日時: 23/09/26 13:02:03
投稿者: WinArrow

>月締め集計ブックに複写してきた後もボタンは必要なので、消すわけにはいかないのです。
しかし、マクロボタンだけでは、機能しないので、
マクロを月締め集計ブックに取込む(複写or変更)が必要です。
 
なるべく、手間を掛けずに対処する方法を提案します。
 
月締め集計ブックを作成する際、新しいブックを用意するのではなく、
当該月最初の営業日ブックを複写し、ファイル名を変更することです。
そうすれば、マクロも一緒に複写されるし、
プロシジャ名もそのまま使えます。
2番目以降は、いままでシートを複写すればよいです。

回答
投稿日時: 23/09/26 13:28:47
投稿者: WinArrow

>2番目以降は、いままでシートを複写すればよいです。
 
と、思ったんですが、リンク先を自ブックにはなりませんね?
シート複写をマクロ化して、その中に、リンク先を変更する処理を組み込むしかないようですね?・
 
 

回答
投稿日時: 23/09/26 17:08:53
投稿者: WinArrow

WinArrow さんの引用:
>2番目以降は、いままでシートを複写すればよいです。
 
と、思ったんですが、リンク先を自ブックにはなりませんね?
シート複写をマクロ化して、その中に、リンク先を変更する処理を組み込むしかないようですね?・
 
 

代案
元ブックを一時的にシートを1つ増やして、
シート複写ではなく、シート移動にすれば、外部リンクにはなりません。
元ブックは、上書き保存しないで閉じれば、よいでしょう。

回答
投稿日時: 23/09/27 11:21:17
投稿者: simple

先日の投稿内容について補足します。
 

たっくんプードル さんの引用:
想定される解決法として思いつくのは、
1.日々の毎営業日用シートのマクロボタンに割り当てられたプロシージャを、シートが別ブックにコピーされても影響されないような書き方にする。
2.月締め集計ブックに複写された後、このブック内に複写された全シート内の外部リンクとなった部分を書き換える。
くらいかな、と想定はするものの具体的にどうプロシージャを記述するかまでは思いつけません・・・
このうち、2番目の方法に対応するマクロを提案しました。
なお、このコードのイメージを示すと、
「データ」 − 「リンクの編集」から入って、「リンク元の変更」を使って、
すべてのリンク先を、自分自身に変更する動作、をマクロにしたものです。
こちらで動作を確認してから投稿しています。そちらでも試してみてください。
 
なお、普通の使い方であれば、カレントフォルダ内に集計ブックがあると思うので、
提案どおりのコード(リンク先を ThisWorkbook.Name に変更)でOKなはずです。
もしそうでないこともあるとすれば、
ThisWorkbook.Nameに代えてThisWorkbook.Path とすれば安全ではあるでしょう。
(ただし、ThisWorkbook.Pathを使う場合、集計ブックがいったん保存されていることが前提です)

回答
投稿日時: 23/09/28 09:01:42
投稿者: WinArrow

各営業日ブックと集計用ブックの両方に同一マクロが登録される
集計用ブックは、その数が増える可能性があります。
同一マクロが複数のブックに複写されます。
  
しかし、状況変化で、全てのブックのマクロをメンテナンス
というような事態が発生すると大変な労力が必要になります。
  
1つのマクロを複数のブックで共有できると、メンテナンス負荷が激減します。
とはいっても、シートデザインを意識しているマクロの場合は、万全策とは言えません。
  
ということを前提として、
マクロをアドイン化し、コマンドボタンをなくし、クイックアクセスウール、または、リボンに登録しておきます。
勿論、マクロは全部削除しいます。
アドインとして登録する手順は、必要ならば別途説明しますが、
考えてみる価値があるのか?ないのか?
検討してみるとよいでしょう。

投稿日時: 23/10/05 23:54:09
投稿者: たっくんプードル

higejee さんの引用:

たっくんプードル さんの引用:
想定される解決法として思いつくのは、
1.日々の毎営業日用シートのマクロボタンに割り当てられたプロシージャを、シートが別ブックにコピーされても影響されないような書き方にする。

ということが無意味(というか不可能)だと理解できるかと思います。なぜならボタンマクロ登録されたプロシージャ名には元のブック名がひっついてますから。
 ボタン自体を消したくないなら集計用ブックに同じ処理を行うプロシージャを用意して、OnAction でボタンのマクロ登録を変更すればよいと思います。

やはり元のブック名がひっついてくるのは不可避なのですかね。
であれば私の仮説どおり、シートを複写してきてからボタンのマクロ登録を変更するのがよいのですね。
しかし、残念ながらOnActionをまだ理解していないので、これから勉強します。ありがとうございます!

投稿日時: 23/10/06 00:15:33
投稿者: たっくんプードル

simple さんの引用:
要するに、ボタンに登録されたマクロがリンクされている実体ですね?
フォームボタンに登録されたマクロということは、
・それは標準モジュールに書かれたマクロであり、
・それらは全て同一内容のコードであり、
・操作対象シートは(ひとつしかシートはないので)特に指定しておらず、アクティブシートである。
ということですね?
 
そうであれば、
(1)そのマクロをひとつだけ(同一なので)、
   集計用ブック(つまり、自分自身)の標準モジュールに手でコピーしておき、
(2)リンク元を、強制的に自分自身(つまり、集計用ブック)に付け替えてしまえばいいですね。
 
例えば、以下のようなマクロを実行すればよいのでは?
Sub test()
    Dim linksource As Variant
    For Each linksource In ThisWorkbook.LinkSources
        ThisWorkbook.ChangeLink Name:=linksource, _
            NewName:=ThisWorkbook.Name, _
            Type:=xlExcelLinks
    Next
End Sub

# 個人的には、ボタンに登録されたマクロを使う機会が無いような気がしないでもありません。

ご質問についてはお見込みのとおりです。
そうであれば、私の仮説でも申し上げましたが、シートを複写してきてから、リンク元を付け替える処理を付け加える、という手法がよさそうなのですね。
ただ、For Each 〜 Next構文の中の部分が見たことがないキーワードなので、これから勉強してみますが、いったんこのプロシージャで挙動を確認させていただきます。
なお、ボタンに登録されたマクロを使う機会は100%ありますので悪しからず。。。

回答
投稿日時: 23/10/06 22:10:28
投稿者: WinArrow

>シートを複写してきてから、リンク元を付け替える処理を付け加える、という手法がよさそうなのですね。
 
シートを複写しただけでは、用準モジュールに記述したマウロは複写(集計用ブックに取込み)できませんよ!
 
 

投稿日時: 23/10/07 23:54:32
投稿者: たっくんプードル

WinArrow さんの引用:

代案
元ブックを一時的にシートを1つ増やして、
シート複写ではなく、シート移動にすれば、外部リンクにはなりません。
元ブックは、上書き保存しないで閉じれば、よいでしょう。

質問4.に記載したとおり、毎営業日ファイル&集計用ファイルが保存されているフォルダの中から前月の毎営業日ファイルを探して、一つずつ開いて、シートをコピーし、ファイルを閉じ、また次の日のファイルを開いて・・・という作業をマクロ化しています。
この作業を
・営業日ファイルを開く
・新規シートを1枚増やす
・目的シートを集計用ファイルに移動する
・営業日ファイルを上書き保存せず閉じる
・次の日のファイルを開く・・・・・・・
と書き換えるということでしょうか?

回答
投稿日時: 23/10/08 07:42:10
投稿者: simple

質問時の前提に沿った回答をしているわけですから、
少なくともその試行結果はきちんと報告してください。
(コードの意味は、23/09/27 11:21:17 で説明しています。)
 
手順は、既に書いたとおりです。(以下、再掲)
(1)元のブックにあるマクロを、集計用ブックの標準モジュールに手作業でコピーしておきます。
   一つだけで可。
 (コードが自動的にコピーされないのは、シートを移動しようが、コピーしようが同じです。)
(2)集計用ブックの標準モジュールに以下をコピーし、これ(test)を実行してください。

    Sub test()
        Dim linksource As Variant
        For Each linksource In ThisWorkbook.LinkSources
            ThisWorkbook.ChangeLink Name:=linksource, _
                NewName:=ThisWorkbook.Name, _
                Type:=xlExcelLinks
        Next
    End Sub
集計用ブックは一旦保存してからマクロを実行してください。

回答
投稿日時: 23/10/08 09:08:16
投稿者: WinArrow

引用:

・営業日ファイルを開く
・新規シートを1枚増やす
・目的シートを集計用ファイルに移動する
・営業日ファイルを上書き保存せず閉じる
・次の日のファイルを開く・・・・・・・
と書き換えるということでしょうか?

 
その通りです。
但し、最初に、「新しいブック」を用意するのではなく、
1回だけ「1つの営業日ファイルを開く」を追加することです。
これは、マクロを取込むためのお措置です。
その後、ソートを複写すのではなく、「移動」します。
これ(移動)に伴い「リンク情報」は消えます。
しかし、1つしか存在しないシートは移動できないので、事前に一時的にダミーシートを作成します。
複写元は、は、上書き保存せずに閉じます。
この操作を、4のマクロに組み込みます。
 

回答
投稿日時: 23/10/08 09:54:23
投稿者: Moko

higejee さんの引用:
ボタン自体を消したくないなら集計用ブックに同じ処理を行うプロシージャを用意して、OnAction でボタンのマクロ登録を変更すればよいと思います。
同意見です。
 
たっくんプードル さんの引用:
・営業日ファイルを開く
・新規シートを1枚増やす
・目的シートを集計用ファイルに移動する
・営業日ファイルを上書き保存せず閉じる
・次の日のファイルを開く・・・・・・・

 
新規シートを増やさず
シートをコピーしたあとに、そのシートのボタンの「マクロの登録」を続けて 行うのが簡単でしょう。
 
だいたいこんな流れになるでしょう。
    Dim wb  As Workbook
    Set wb = Workbooks.Open("C:\Users\aaa\bbb\20230901.xlsm")
    wb.Sheets(1).Copy Before:=ThisWorkbook.Worksheets(1)
    ActiveSheet.Buttons("ボタン 1").OnAction = "マクロ1"
    wb.Close False

回答
投稿日時: 23/10/08 10:44:46
投稿者: simple

皆さん自分のが正しいと主張しているようですけど、色々なやり方があるんですよ。

回答
投稿日時: 23/10/08 11:01:06
投稿者: WinArrow

>4.の作業はマクロで自動化しています
  
上記のコードを掲示してみて貰えますか?
質問者さんが作成したコードを、添削した方が理解しやすいと思います。
 
 

投稿日時: 23/10/22 00:49:32
投稿者: たっくんプードル

simple さんの引用:
例えば、以下のようなマクロを実行すればよいのでは?
Sub test()
    Dim linksource As Variant
    For Each linksource In ThisWorkbook.LinkSources
        ThisWorkbook.ChangeLink Name:=linksource, _
            NewName:=ThisWorkbook.Name, _
            Type:=xlExcelLinks
    Next
End Sub


 
ありがとうございました。図形(フォームコントロール)のコピーの際、別の問題等が発生し手こずっていましたので時間がかかり申し訳ありませんでしたが、ついに問題が解決しました。
仕事のファイルなのでなかなかじっくり時間を取れず、少しずつしか前進できませんでしたが勉強になりました。

投稿日時: 23/10/22 00:57:50
投稿者: たっくんプードル

higejee さんの引用:
 ボタン自体を消したくないなら集計用ブックに同じ処理を行うプロシージャを用意して、OnAction でボタンのマクロ登録を変更すればよいと思います。

ありがとうございました。最終的には、月締め集計ブックに、毎営業日ファイルのフォームボタンに割り当てているプロシージャをコピーしておくこととし、シート複写後、OnActionでプロシージャを自ブック内のプロシージャに付け替える手法に落ち着きました。
仕事のファイルなのでなかなかじっくり時間を取れず、少しずつしか前進できませんでしたが勉強になりました。

投稿日時: 23/10/22 01:02:56
投稿者: たっくんプードル

Moko さんの引用:
新規シートを増やさず
シートをコピーしたあとに、そのシートのボタンの「マクロの登録」を続けて 行うのが簡単でしょう。
 
だいたいこんな流れになるでしょう。
    Dim wb  As Workbook
    Set wb = Workbooks.Open("C:\Users\aaa\bbb\20230901.xlsm")
    wb.Sheets(1).Copy Before:=ThisWorkbook.Worksheets(1)
    ActiveSheet.Buttons("ボタン 1").OnAction = "マクロ1"
    wb.Close False

最終的には、こちらのコードを自分の環境に合わせて少し修正して採用させていただきました。なぜなら、もう一つ別ボタンがあり、逆にこのボタンからプロシージャを削除したいという希望がありましたので、続けてOnAction = ""で簡単に消せるからです。
本当にありがとうございました。少しづつですが勉強になりました。

投稿日時: 23/10/22 01:08:23
投稿者: たっくんプードル

WinArrow さんの引用:

その通りです。
但し、最初に、「新しいブック」を用意するのではなく、
1回だけ「1つの営業日ファイルを開く」を追加することです。
これは、マクロを取込むためのお措置です。
その後、ソートを複写すのではなく、「移動」します。
これ(移動)に伴い「リンク情報」は消えます。
しかし、1つしか存在しないシートは移動できないので、事前に一時的にダミーシートを作成します。
複写元は、は、上書き保存せずに閉じます。
この操作を、4のマクロに組み込みます。
 

ありがとうございました。ご教示していただいた方法も試し、ついに問題が解決しました。皆様の手法をひとつひとつ検証しながらで時間がかかってしまい申し訳ありませんでした。