質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Office 365

Office 365は、マイクロソフトが販売している企業向けクラウドベースのグループウエアサービス。電子メールや予定表、Webサイト構築、オンラインストレージ、ビデオ会議などビジネスで必要な機能を備えています。クラウドサービスのため、自社での専用サーバーの設置の必要がないことが特徴です。

Q&A

解決済

2回答

2050閲覧

VBA changeイベント 別ブックと連携

tttkkk

総合スコア38

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Office 365

Office 365は、マイクロソフトが販売している企業向けクラウドベースのグループウエアサービス。電子メールや予定表、Webサイト構築、オンラインストレージ、ビデオ会議などビジネスで必要な機能を備えています。クラウドサービスのため、自社での専用サーバーの設置の必要がないことが特徴です。

0グッド

0クリップ

投稿2021/03/29 13:24

いつもお世話になっております。
changeイベントを勉強し始めたばかりで拙い質問とかもしれませんが、よろしくお願いいたします。

changeイベントを使うことで、vlookupでできるような、あるIDを打ち込まれたらそのIDを参照して名前などの値を出力することを考えています。
changeイベントですと別ブックを参照する際に、効率的な方法はございますでしょうか。

データリストはchangeイベントが発火するブックには無く、別ブックにまとめられて管理されています。
changeイベントが発火するブックと同一のブックにデータリストがあるという状況でしたら、今の私であってもvlookupのように入力したIDに従ったデータを引っ張ることができます。
しかしデータリストが別ブックにあるとなりますと、changeイベントが発火するたびに別ブックのデータリストを開いて、閉じてというのを繰り返す必要が出てきてしまい、動作が重くなってしまうということが起きました。

changeイベントを使い、vlookupを使わない理由は、関数ですと常にセットし置かねばならず、ファイルが重くなってしまうのと、実際どの行まで関数をセットし置くのかという問題があったからです。

以下に私が書いたサンプルコードを載せさて頂きます。
このサンプルコードは別ブックのデータリストを開いて、閉じてというコードでは無く、同一ブックにデータリストがあるとした時のコードとなりますが、
私の行いたいことが伝わりましたら幸いです。

VBA

1Private Sub Worksheet_Change(ByVal Target As Range) 2 3Dim foundId As Range 4Dim foundName As Range 5Dim foundAddress As Range 6'sheet17がデータリストになります。 7Set foundId = Sheet17.Cells.Find(what:="id", lookat:=xlWhole) 8Set foundName = Sheet17.Cells.Find(what:="name", lookat:=xlWhole) 9Set foundAddress = Sheet17.Cells.Find(what:="address", lookat:=xlWhole) 10 11'targetがA列でさらにデータ型が数値だった時 12If (VarType(Target.Value) = 5 And Target.column = 1) Then 13 Dim foundInputId As Range 14 Set foundInputId = Sheet17.Cells.Find(what:=Target.Value, lookat:=xlWhole) 15 Target.Offset(, 1).Value = Sheet17.Cells(foundInputId.Row, foundName.column).Value 16 Target.Offset(, 1).Value = Sheet17.Cells(foundInputId.Row, foundAddress.column).Value 17End If 18 19End Sub

上記のコードではsheet17がデータリストですが、このsheet17のデータリストが別ブックにある場合にどうしたらよいかということになります。

分かりにくい点がございましたら申し訳ありませんが、
宜しくお願い致します。イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

外部参照式を使うというのもありかな。

vba

1Private Sub Worksheet_Change(ByVal Target As Range) 2 Const datalist = ",'C:\test[datalist.xlsx]Sheet1'!$A:$C" 3 4 'targetがA列でさらにデータ型が数値だった時 5 If (VarType(Target.Value) = 5 And Target.Column = 1) Then 6 7 With Target.Offset(, 1) 8 .Formula = "=VLOOKUP(" & Target.Address & datalist & ",2,FALSE)" 9 .Value = .Value 10 End With 11 With Target.Offset(, 2) 12 .Formula = "=VLOOKUP(" & Target.Address & datalist & ",3,FALSE)" 13 .Value = .Value 14 End With 15 End If 16 17End Sub

項目数が多いときはループにするといいでしょう。

vba

1Private Sub Worksheet_Change(ByVal Target As Range) 2'参照先 A列からZ列まで(26列) 3 Const datalist = ",'C:\test[tera330470_list.xlsx]Sheet1'!$A:$Z" 4 Const colCnt = 26 5 'targetがA列でさらにデータ型が数値だった時 6 If (VarType(Target.Value) = 5 And Target.Column = 1) Then 7 Dim i As Long 8 For i = 2 To colCnt 9 With Target.Offset(, i - 1) 10 .Formula = "=VLOOKUP(" & Target.Address & datalist & "," & i & ",FALSE)" 11 .Value = .Value 12 End With 13 Next 14 End If 15End Sub

投稿2021/03/30 01:41

編集2021/03/31 13:52
hatena19

総合スコア33699

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tttkkk

2021/03/31 12:14

私もchangeイベントで関数を入れるというのは思い付いた部分ではありますが、そうなると項目が増えるに従ってコードの行数が増えてしまうことが悩みでした…。 でもやはりこれが一番簡単なやり方になりますよね。 ありがとうございます。
hatena19

2021/03/31 13:22 編集

コードをよくみてください。関数をセルに入れているわけではないですよ。 関数で外部データを取得はしてますが、取得した後、.Value = .Value の部分で値に変換してます。ですのでシートが重くなることはありません。 また、外部参照式はブックを開くわけではないので、動作も軽いです。 項目数が多い場合は、ループを使えばコードが増えることはないですね。回答に追記しておきます。
xail2222

2021/03/31 13:47 編集

そうですね。コード量的にDictionaryでやる方が多くなると思います。 テストしてみましたが外部参照って重い印象があったのですが1セルだけなら それほど遅くないんですね。知りませんでした。
hatena19

2021/03/31 14:18

Worksheet_Change時の速度はDictionaryの方が高速だと思います。 ただ、Workbook_Open時に別ブックを開くことになりますので、開くのがちょっと遅くなりますね。 どちらにしも体感できる差はでないかと思います。
guest

0

ベストアンサー

私ならどうするかで回答します。

データリストは別のExcelファイルで管理したい。これが前提条件だとすると
何度も開くのは確かに大変なので、一度だけ開いてDictionaryに格納して
その後はDictionaryから値を参照する。という手法をとるかと思います。

Dictionaryのキーはidで値がArray([name],[address])という感じですね。

初めに格納する方法としては、Dictionaryを標準モジュールで定義して
changeイベントが発火するブックのWorkbook_Openイベントで
データリストを(表示せずの方がいいかも?)オープンして
Dictionaryにデータをセットしてって感じでしょうか。

投稿2021/03/29 13:50

xail2222

総合スコア1497

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tttkkk

2021/03/31 12:05

ありがとうございます! dictinaryという方法は初めて知りました。 どの程度私のやりたいことに使えるか調べてみたいと思います!
tttkkk

2021/03/31 12:39

私のやりたいことをdictinaryを使うことで実現できそうでしたので、ベストアンサーにさせていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問