● 顧客IDが同じうちは横に値を結合していくマクロの例~SUMIF関数では条件付きの文字列の結合ができないので、その代わりのVBAコード(ただし顧客ID等々ごとにまとめるだけ)

★ はじめに

例えば以下の図ようなことをしたい時がありませんか?

顧客IDごと、あるいは、顧客の氏名・住所・TELごとに、何らかのリスト(購入品履歴など)を縦方向から横方向につなぎ変えたい場合です。

SUMIF関数はある条件のもとに数値の合計はできますが、文字列の結合ができません。(Excelのことを知らないもんですからそれができる関数が無いと知って驚きましたけど・・・。でもよく考えたらAccessでも無いかもですね。SQLでもできるみたいですけどそれだと慣れないとかえって難しいので、兼任SEさんの場合は VBAでやるほうが多分簡単な気がします。僕はSQLも音痴なので理解ができませんでした。関数、SQL、よりも、VBAのほうが簡単でした。)

Webを色々と漁ってみたのですが、汎用的に使えるとか、書き換えができそうな、とかの小さなプログラムがありませんでした。
関数だとすごくややこしくなって面倒くさいので、VBAでやることにしてみました。
(複数の関数のかけあわせができる人、本当に尊敬します。)

ここでは、あとで作り変えもできる、ちいさなプログラムを作ってみました。
(素人なので美しくないコードですみません!)

顧客IDごとに、B列の値が横に結合していき、C列の各顧客の最後の行(もとから1行しかなければその行)に、その結合された値を埋め込んでいくプログラムです。

関数でやる方法を調べたら、例えばC列の全セルに値が表示されてしまう方法がとても多かったです。

例えば、「B列の値が1つずつ結合されたものが上から順番にC列の全セルに埋め込まれてしまう方法」が多かったでした。

でもそれだと、最終的に「顧客名簿集約」を見据えたときに後の処理が面倒くさいです。

逆に例えば、A列に顧客ごとに、氏名・住所・TELが同じ値が入っている場合、「C列の各顧客ごとの最後の行だけに 結合された値が入っていれば」、上図のようにC列でオートフィルタを使って、購入製品履歴付の名簿が作成しやすいです。

なお、どの列に顧客情報が入っているかとか、どの列に、結合した値を埋め込むかは、最初のサンプルプログラムではA列、B列、C列、で決め打ちしてしまっていますが、2つ目のサンプルプログラムのように、ユーザーに問い合わせるように作り変えれば、どの列がどうでも、自由が利くと思います。

また、モトデータが全部残っているほうが、のちにまた別の加工に使えるかもしれません。

そんなこともあって、C列のすべてのセルに値を埋め込むことはやめてあります。

では以下、サンプルコードです。

冒頭の図のように、1行目に「F01」~{F03」の列名を入れ、同様に値を入れてから、以下のコードを「標準モジュール」にコピペすれば動きを確認できると思います。

★ YokoMargeTest01()・・・A、B、C、の3つの列を使ってのデータの横結合

  

※「標準モジュール」は「開発」タブを出して、「Visual Basic」のボタンを押すと「Visual Basic Editor」の画面が出ますので、「挿入」→「標準モジュール」を押します。

そのあとに、上記のコードをコピペして、実行します。

実行は、プログラムのどこでもいいのでいったんクリックして点滅カーソルを表示させてから、下図の赤枠のボタンを押すか「F5」キーを押すと実行できます。

※プログラムのどこでもいいのでいったんクリックすることで、そのプログラムを「選択した」という意味になります。それをしないと下図のような変なダイアログが出てきてしまいますのでご注意ください。


  
  
★ YokoMargeTest02()・・・ユーザーが指定した列を使ってのデータの横結合

前出の「YokoMargeTest01()」のプログラムを少し作り変えて、処理する列が変わってもいいように、自由に設定できるようにしてみました。

ただ、エラー処理やいろんな処理をしてないのでユーザーに列を指定させるときに、キャンセルを選ぶとエラーになります。

でも一応、最小限、動きますので、あと何を付け足したらエラーが出ないようになるかご自分でも考えてみてください。

これも、前出のプログラム同様に、3列を保持するシートを作成し、標準モジュールにコピペして実行すれば、動作を確認できます。

相変わらずに、レベルの低い、美しくないプログラムですが、VBA初心者の方のご参考になれば幸いです。

なお、もし「あたしゃ、どうしても書き込んだ列に空白を作りたくないんだよ!(さっきまる子ちゃん読んでたから感化されてしまいました)」という場合は、これらのプログラムにそういった処理を埋め込むよりは、別途に「次行以降の、次の異なる値までの空白はすべて現在の値で埋めるプログラム」を作って「Call」で呼び出したほうが、色んな場面で流用も効いて、共用部品として使えるので便利だと思います。

例えば、「空白を同じ値で埋める」というのはよくある作業なので、それができるプログラムを何かのプログラムからCallするほかにも、メニューバーやリボンに「ボタン」として配置して呼び出せるようにしておけば、それもとても便利だと思います。