ラベル 構造化参照 の投稿を表示しています。 すべての投稿を表示
ラベル 構造化参照 の投稿を表示しています。 すべての投稿を表示

2016/02/09

[Excel] テーブルと Excel VBA

ワークシート関数を使う時、これまでの「範囲」の変化に対応することができるテーブル機能は Excel 2007 以降の最大の機能拡張、、、なんてことも言われています。

過去にこのブログでもいくつかテーブル機能について紹介しました。

テーブルのすすめシリーズ
http://road2cloudoffice.blogspot.jp/2014/10/vlookup.html
http://road2cloudoffice.blogspot.jp/2014/10/blog-post.html
http://road2cloudoffice.blogspot.jp/2014/10/blog-post_31.html
http://road2cloudoffice.blogspot.jp/2014/11/blog-post.html
http://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html
http://road2cloudoffice.blogspot.jp/2014/11/office-365-sharepoint.html

機能、関数で多くのメリットを提供するテーブルですが、Excel VBA の世界ではどうでしょう?

まず、表としての範囲が、テーブルというオブジェクト(ListObject オブジェクト)になるため、最終行+空白問題(上から End モードで下に行ったとき、空白があったら止まる)、もしくは最終行+ごみ問題(行の一番下から上に上がっても、途中にごみがあればそこで止まる)は基本的になくなります。

というのも、テーブルではテーブルの行数は End モードを使わずとも、テーブルのプロパティで確認することができるからです。テーブルの行数は ListRows.Count でわかります。

ここで標準的なテーブルを実践ワークシート協会の田中亨が推奨する「黄金テンプレート」で処理するコードを見てみると以下のようになります。

サンプルテーブル
サンプルテーブル
テーブルでも表の処理同様の VBA コードを書くことができます。
名前が田中だったら、個数X単価を合計に代入する、といった処理だと、田中亨の黄金テンプレートで考えると、

範囲はどこか? 

行は 3 から 12。もちろん、最終行の 12 が可変だとしても、End モードで特定します。

条件はなにか?

条件は、名前のセルが "田中" だったら、ですね。

処理は何か?

合計セルに個数X単価を代入する、です。

そうすると VBA のコードは以下のようになりますね。

Sub sample1()
    Dim i As Long
    For i = 3 To Range("B2").End(xlDown).Row
        If Cells(i, 2) = "田中" Then
            Cells(i, 5) = Cells(i, 3) * Cells(i, 4)
        End If
    Next i
End Sub

これをテーブルのオブジェクトを使って、テーブルらしく書いてみると、上記の表形式とは大きく違う点があります。それは「列番号」であり、「行番号」の考え方になります。

テーブル オブジェクトの世界では、ワークシートの「A列」や「D列」は意味がなく、あくまでテーブル内での列順序の番号です。上の例でいえば、名前の列は、B列で列番号2ではなく、あくまで名前フィールドであり、フィールドの番号はテーブル内で「1」になります。

さらに、テーブルというオブジェクトは「ListRowsコレクション」からデータ部分が構成されています。テーブルの行の各1行は ListRow オブジェクトとして扱うことができます。このことより、「何行あるか、わからないけど、For Each を使えば、そのテーブルのすべての行(ListRowsコレクション)を扱うことができる」として処理可能になります。

そのサンプル コードが以下です。

Sub sample2()
    ''1 名前, 2 個数, 3 単価, 4 合計 ←テーブル内での順序
    Dim tb As ListObject
    Set tb = ActiveSheet.ListObjects("TestTable")  ''テーブル名がTestTableだった場合
    Dim R As ListRow
    For Each R In tb.ListRows
        If R.Range(1) = "田中" Then
            R.Range(4) = R.Range(2) * R.Range(3)
        End If
    Next R
End Sub

たぶん、R.Range(1) という書き方ってあまり使っていなかったと思います。
この R.Range(1) という書き方は、以下の書き方と同じものです。

R.Range.Item(1)
R.Range.Cells(1)

おもしろいですね。
VBAセミナースタンダードで田中亨がよく「上級者は2次元配列は使いません。だって、Excel VBA にはワークシートがあるんですから!」と言いますが、上記の表記はその流れです。(正確にはこれは一次元配列ですけど)

For Each でとってくる R は一次元配列(的なもの)です。(要素の型が違うので配列とは言えませんが、便宜上お許しを)この1次元配列は1列または一行で複数セルを選択した「セル範囲」のイメージです。今はテーブルなので、以下のような横方向の1行のセル範囲です。

[[名前] [個数] [単価] [合計] ]

この順序です。ですから、名前は (1) で、個数が (2)、、、となるわけです。
その表記方法が R.Range(1) だったり、R.Range.Item(1) だったり、R.Range.Cells(1) になるわけです。セル範囲の Range オブジェクトを配列のイメージとして扱っているんですね。

繰り返しますが、ポイントは A列、B列といったワークシート上の絶対的な番地では無い!ということです。

上記の例はサンプルなので処理や条件がシンプルなものですが、これが複雑になってくると、Cells(行, 列) でセルを指定するやり方と、R.Range(要素) で処理すべきセルを指定する方法のどちらがいいかはだんだん変わってきます。

その意味から、変数を使って、テーブルの列順序を定義すると、さらに可読性が高まります。(IMEオン・オフの操作があるので日本語変数がいいわけではありませんが、サンプルとして定義します)

Sub sample3()
    Dim tb As ListObject
    Set tb = ActiveSheet.ListObjects("TestTable")
    Dim 名前 As Long, 個数 As Long, 単価 As Long, 合計 As Long
    名前 = tb.ListColumns("名前").Index
    個数 = tb.ListColumns("個数").Index
    単価 = tb.ListColumns("単価").Index
    合計 = tb.ListColumns("合計").Index
    
    Dim R As ListRow
    For Each R In tb.ListRows
        If R.Range(名前) = "田中" Then
            R.Range(合計) = R.Range(個数) * R.Range(単価)
        End If
    Next R
End Sub

たった5~6行の処理のための変数宣言と変数設定で7行は、、、と思いますが、通常はもっと条件や処理が複雑になるので、これだけで「行数が多い、無駄だ」と判断するのは早計だと思います。 For Each から Next R までの処理の「可読性」を見てください。実にわかりやすい表記になっています。

たぶん、テーブル ListObject オブジェクトを VBA で扱うのは、このオブジェクト変数を使ってテーブルを設定し、テーブル内のフィールドの順序を変数として設定していくのが一番良い方法だと思います。

ここでテーブル機能で重要な「構造化参照」が出てきてませんよね?

いろいろ試した結果、この「構造化参照」は VBA を編集するツールである VBE で実装されていないため、インテリセンスのような形で、文字通りの「構造化参照」という機能は実装されていないようです。テーブル名を指定すれば、そのテーブルにあるフィールドが表示される、、、ような機能は VBE には無い、ということです。

では、VBE に期待しないで表記したらどうなるでしょう?

ここでも Excel の Range オブジェクトの実装、、、「すげー」となるわけです(笑

VBE では構造化参照のメリット享受できないので使う理由がないのですが、無理やりやると以下のようなコードを書くことができます。

Sub sample4()
    ''1 名前, 2 個数, 3 単価, 4 合計 ←テーブル内での順序
    Dim R As Range
    For Each R In Range("TestTable").Rows
        If R.Cells(1) = "田中" Then
            R.Cells(4) = R.Cells(2) * R.Cells(3)
        End If
    Next R
End Sub

テーブルを ListObject として宣言しない分だけ行数が短いですが、R.Cells(1) などを番号ではなくフィールド名で、、、となると、宣言や設定のためそれなりに行数が増えます。さらに、構造化参照が VBE でサポートされていないために、複雑、長くなればなるほどめんどうなことが発生してきます。(*1 最後に追記してます)

以上のことより、通常、テーブルを VBA で扱うのであれば、テーブルは ListRow のかたまりであり、テーブルを ListRows コレクションとして処理するのが王道でしょう。
そのときの For Each として1つ1つ処理するのは ListRow オブジェクトであり、その ListRow オブジェクトの扱いは「一次元j配列」的になる、と言えるでしょうね。

今後、データ接続でテーブル形式でデータを取り込むことが多くなります。そのときは、上記の考え方でテーブルをマクロで扱うことも多くなると思います。

(*1) 構造化参照が少なすぎるとおもったので追記。
構造化参照方式で以下のような表記が可能です。

Range("テーブル1[名前]")

上記でテーブル1の名前フィールドのデータ部分の範囲を指し示すことができます。
しかし、この Range(構造化参照) は、あくまで Range による範囲(つまり、named range) のため、ListObject との関連がありません。

そのため、Range("テーブル[名前]").Column は、ワークシート上の列番号を返します。


[PR] VBAセミナーを受けた後は、これさえあれば何もいらない。

2015/01/18

Power Query を使った重複行の削除

重複行の削除もしくはユニークなデータのリスト作成も実務で Excel を使うユーザーにとっては往々にして直面する課題である。

いくつかある重複行の削除

現在、重複行の削除で Excel 2007 以降に追加された データ タブ - データ ツールにある「重複行の削除」がもっとも紹介されている機能だろう。


表の重複している項目を削除する(Microsoft atLife)
http://www.microsoft.com/ja-jp/atlife/tips/archive/office/tips/002.aspx


たしかにこの機能により重複行を削除し、ユニークデータのリストの作成が可能なのだが、元データが更新されれば、同じ作業をし直さなければならず、この機能を活用するシーンは私自身はあまりない。正直、単純で汎用性が乏しく実務では応用した活用が難しいのだ。


一方、ピボットテーブルを使うことで元のデータが更新されても重複行を削除した表/リスト作成が可能だ。この方法であれば、元データが更新されてもピボットテーブルの「更新」をすることで対応できる。



ただし、注意したいのは、ピボットテーブル レポートのピボットテーブルは構造化参照可能なテーブルではない。ユニークデータリストを作って終わり、ではなく、そこから何らかの集計・計算・データ利用において、構造化参照によるテーブルの利用ができないため、他への再利用が難しい。テーブルではないことから、データの増減が発生したときの構造化参照テーブルのメリットも使えない。



上記の例ではデータカウントを取ることが目的ではない。逆にピボットテーブルなのでカウントの取得は簡単だ。しかし、このブログでも再三紹介しているように、現在そして今後 Excel はテーブル機能をベースにして拡張、新機能が追加されている。なるべくテーブルを使った課題解決方法を手にしておきたいところだ。

参考までに、もちろん、VBA を使った重複行削除のテクニックもある。

重複行を削除する(OfficeTANAKA)
http://officetanaka.net/excel/vba/tips/tips14.htm

VBA を使えば、重複行削除をしたユニークデータのリストを作成し、それをテーブルに変換することができる。

ただし今では VBA プログラミングをせずに「機能」だけで上記を実現できる。 それが Power Query だ。

Power Query を使った重複行の削除

Power Query については以前にも一部の機能を紹介しているが、そこでも述べたように Power Query はサーバーやクラウドからデータを Excel に取り込むことだけを目的としたアドインではない。Excel のテーブルもデータ ソースとして指定が可能だ。

そして、Power Query のクエリ エディターの「列の削減」で「重複部分の削除」の機能があるのだ。
これを使うことで、「重複行の削除」と同様のことができる。


もちろん、Power Query で取り込んだデータは Excel のテーブルとなる。構造化参照可能なユニークデータの「テーブル」となる。これでピボットテーブルの重複行削除でできなかったことが可能になる。

Power Query が Excel をデータ ソースに変える

しかし、本当に重要なのは、重複行の削除ができることではない。

データを Excel のテーブルとして持ち、Power Query を使うことで、Excel をまるで「データベース」のように扱うことができる、ということが重要なのだ。これが Power Query をすべての Excel ユーザーに勧めたい理由である。 重複行の削除はほんの一例でしかない。

蓄積されたデータの中から必要なデータを抜き出し、それを加工したい、分析したい、集計したい、というニーズは Excel ユーザーにとっては「通常」のことだと思う。

そしてその作業を「繰り返して」はいないだろうか。更新されたデータ(ワークシート、テーブルといったデータの固まり)を対象に、同じ条件で抜き出す、加工する、レポートを作る、といったことだ。

手作業でデータを抜き出すのであればオートフィルターを使っているだろう。そこから絞り込んだデータを他のワークシートやブックにコピーしていないだろうか。

実践ワークシート協会の VBA セミナー スタンダードを受けた受講者であれば、それら一連の作業を VBA で行うことができるだろう。

Power Query を使うことで、Excel のテーブルをデータ ソースとして指定し、抽出するための複数条件をクエリ エディターを使って設定し、結果を Excel のテーブルとして出力する、それらすべての設定を「クエリ」として保存し、再利用が可能なのだ。

そして、Power Query は条件を設定し抽出するだけではない。カスタム列の追加も可能なのだ。ピボット テーブルの集計フィールド、Power Pivot の集計列と同じだ。データ型の変換までできる。

以下のアニメーション GIF では、Data2 列の数値を文字列変換し、ゼロパディングで 1 を 001 にして Data 列の文字列と結合させ、文字列の Data3 を数値に変換している。列の順番も変更可能だ。このようなデータの操作・加工も Power Query で可能で、ある意味、元のテーブルからまったく別のテーブルを作っているようなものだ。


Power Query のクエリ エディタの式で使える関数はワークシート関数でもなく、Power Pivot の DAX 関数でもない。しかし、マイクロソフトが公開している記事を参考にしながら Excel のワークシート関数の知識で試してみればその使い方はわかると思う。重要なのは全く別のものでなく、かぶっていることが多い、だから、Excel ユーザーであれば「わかる」だろう、想像してみよう、ということだ。

上記のアニメーション GIF でも、関数の Number.ToText の引数として、"000" を入れたのはワークシート関数の TEXT 関数の知識からだ。それで期待通りの動きになるのはさすがマイクロソフトと言わざるを得ないだろう。

少しでもこの情報が参考になれば幸いである。

2014/11/04

[Excel] テーブルのすすめ 構造化参照

Excel 2007 以降で最も重要な機能は「テーブル機能」です。

参照先のデータとしてテーブルを使うとデータの増減に対応できます。この増減に対応するための記述方法が「構造化参照」であり、これまでの A1:C4 や $A$1 などの参照方法と違います。

構造化参照の利用は難しくない

ただ、さすが Excel です。普通の使い方をしていても、あまり意識せずに構造化参照を使うことができます。


[手数料金額]列の1行目に「 = 」入力のあとにカーソルを動かし、同じ列の [売上金額] と [手数料] を選ぶと、構造化参照された [@売上金額]、[@手数料(%)] が入力されます。 @の意味は「この行の」という意味です。そして2行目以下の[手数料金額]に同じ数式がすべてに挿入されます。

テーブルの外のセルから参照すると「テーブル名」が自動挿入されることもわかるでしょう。
そして、列全体を選べば 「 DeptSales[手数料金額] 」 や 「 DeptSales[売上金額] 」、「 DeptSales[営業担当者] 」を参照します。列名をいれると、その列にあるすべてのデータ行を選択します。(これを完全修飾といいます)

この構造化参照式を理解すると、カーソルで範囲を選らばずに列全体を参照する式をいれて、合計やカウントを出すことができます。もちろん、数式オートコンプリートが入力を支援してくれます。

なお、数式オートコンプリートのドロップダウン リストからの選択は下矢印、上矢印のキーを使って移動し、[TAB] キーで確定します。


集計行をテーブルの一番下に追記することをすでに紹介しましたが、その集計行の値を構造化参照で参照することも可能です。これはオートフィルターの結果を取得するのに有効です。(以下のように同じワークシート内で参照することは少なく、出力用・報告用の別ワークシートから参照することが多いでしょう。)


これらの構造化参照式は以下のマイクロソフトのページにくわしく解説されています。
翻訳が中途半端なので読みづらいですが、だいたいの概要はわかると思います。

Excel テーブル数式で構造化参照を使う
http://office.microsoft.com/ja-jp/excel-help/HA102749547.aspx

ただ、構造化参照式を直接入力しなくても、テーブルのセル範囲を選択したとき、それが構造化参照できるようであれば自動的に構造化参照式が入力されるので、あまり難しく考える必要はありません。そのような式が数式に入力された時に驚かないことのほうが重要です。

構造化参照を使いたい関数

すでに VLOOKUP 関数で構造化参照の使い方を紹介しましたが、他にも構造化参照の恩恵を受ける関数があります。「範囲」や「列番号」を使う関数は構造化参照の利用を検討してみるとよいでしょう。

MATCH 関数 http://office.microsoft.com/ja-jp/excel-help/HA102752945.aspx

検査範囲で構造化参照を使います。ただし、列名を検査して列番号を取得したい場合は、COLUMN 関数と構造化参照を組み合わせたほうがシンプルで見やすいでしょう。
テーブルでの使用用途は検索したい文字列/数値を列全体に対して行い、行数を取得するパターンです。ただし、VLOOKUP 関数同様、検査対象列に一意のデータ(ユニークなデータ)が入力されていれば簡単ですが、同じデータが存在する場合は格段に利用(数式)が難しくなります。本当に関数でやらなければいけないのか、テーブルのオートフィルターを使って目視での絞込みによる利用ができないかを検討してください。また、VBA はこのようなケースが得意です。

INDEX 関数 http://office.microsoft.com/ja-jp/excel-help/HA102752976.aspx

MATCH 関数で行番号が分かれば、次に使うのは INDEX 関数です。
列番号は上述のように COLUMN 関数を使えば、行と列で指定したセルの内容を取得できます。
また、対象となる列が決まっている場合は以下のように記述できます。

DeptSales テーブルの営業担当者列の3番目(3行目)を取得
(この "3" をMATCH関数で取得するパターンが多い)

=INDEX(DeptSales[営業担当者], 3)

SUMIF および SUMIFS 関数

SUMIF 関数 http://office.microsoft.com/ja-jp/excel-help/HP010062465.aspx
SUMIFS 関数 http://office.microsoft.com/ja-jp/excel-help/HA102753226.aspx

地域が南西部(A1)の売上金額の合計を求めているのが以下です。



その他の使い方

行数をもとめる =ROWS(テーブル)

 見出し(列名)と集計行が除外され、データ部分の行数を返します。SUBTOTAL 関数の COUNTA で列を指定した場合は、空のセル(行)はカウントされません。反面、ROWS 関数を使うと空の行もカウントされます。

列数をもとめる =COLUMNS(テーブル)

列番号をもとめる =COLUMN(テーブル[列名])

構造化参照とオートフィル

構造化参照を使った数式をオートフィルでコピーできます。
相対参照としての動きが基本です。
以下では第1四半期の合計をサマリーの表に SUM 関数を使って計算し、オートフィルで、第2、第3、第4四半期の合計をオートフィルで数式のコピーをしています。


色別の合計を出すために SUMIF 関数を使います。この時は注意が必要です。
適切でない構造化参照が以下です。


オートフィルによって、SUMIF の検索範囲を指定した dataTbl[色] が移動するためです。
この場合、dataTbl[色] を絶対参照のような指定をしなければなりません。
その指定方法が dataTbl[[色]:[色]] です。こうすることでオートフィルを使っても検索範囲が移動することはありません。


なお、テーブルに限った話ではありませんが、SUMIF 関数の検索条件の指定で、カーソルを動かして「B4」を指定し、F4 キーを押すことで相対参照, 絶対参照の切り替えができます。

テーブル関連の投稿
[テーブルとVLOOKUP] https://road2cloudoffice.blogspot.jp/2014/10/vlookup.html
[テーブルと入力規則] https://road2cloudoffice.blogspot.jp/2014/10/blog-post.html
[テーブルと集計行] https://road2cloudoffice.blogspot.jp/2014/10/blog-post_31.html
[テーブルと構造化参照] https://road2cloudoffice.blogspot.jp/2014/11/blog-post.html
[テーブルとピボット] https://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html
[テーブルとVBA] https://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html

2014/10/24

[Excel] テーブルのすすめ VLOOKUP関数

Office 2007 以降で最も重要な機能追加は「テーブル機能」です。
今後 Office 365 にシフトすればするほどその重要性は増しますが、そもそも「テーブル機能」がどれほど強力に Excel を使った業務を支援するか、という点を今回は VLOOKUP関数から紹介したいと思います。

VLOOKUP関数
VLOOKUP(検索値,範囲,列番号,検索の型)

この構文から、[範囲] と [列番号] をどう扱うかは Excel ユーザーにとっては定番ネタですね。

たとえば、Microsoft のサイトでは Excel 2003 向けの記事として以下のようなものがあります。

VLOOKUP, MATCH および INDEX を使用した動的検索

参照するリストの行が増えたら範囲を変更しなくてはならない、参照するリストの途中に列を追加したら列番号を変更しなければならない、というものです。これをワークシート関数を使って自動的に行うのが上記でいう「動的検索」です。

Excel 2007 以降は、参照先リストをテーブルに変換することで、範囲は「テーブル名」となり、行が追加されても追随します。列番号をとるのに列名の文字列を MATCH 関数を使い [#見出し] の構造化参照からとる方法を紹介している記事もいくつかありますが、テーブルの「構造化参照」の特徴を使うのであれば、COLUMN関数で構造化参照の列名を指定するのが「テーブル機能」らしい使い方です。(一番下の(追記)も参照してください)

VLOOKUP(検査値, テーブル名, COLUMN(列名), 検索の型)


上記で「構造化参照」と言っていますが、関数を「関数の挿入ダイアログ」を使って入力していたらその便利さを見ることはありません。関数の挿入ダイアログは今となっては使ってはいけないと言えます。なぜなら構造化参照を使えないからです。

テーブルはブックの中でオブジェクトとして扱われ、そのテーブルの中にある列もまたオブジェクトとして扱われます。残念ながら日本語の Excel の場合は作成したテーブルに「テーブル1」といった日本語名が付いてしまうので、関数入力時に構造化参照の恩恵を受けられづらいのですが、table1 など英語表記にすると入力の手順が相当変わります。以下、その手順を追ってみましょう。

1) 表を選択して [挿入] タブの [テーブル] をクリックし、テーブルの作成ダイアログで [先頭行をテーブルの見出しとして使用する] にチェックがあるのを確認して [OK] を押します。

2) 作成したテーブルの名前を table1 に変更します

3) 社員番号から名前を VLOOKUP 関数で取得します。その際の操作は以下です。



最終的な数式は以下となりました。

=VLOOKUP(E2,table1,COLUMN(table1[名前]),FALSE)

範囲指定の際に "ta" と打っただけで ta から始まる関数とテーブル名がリストされます。COLUMN関数の引数でも "ta" と打って table1 を選び、その直後に "[" を入れると table1 の列名がリストされるので、そこから [名前] を選び、"]" で閉じます。

これが構造化参照であり、テーブルを使うべき理由のひとつです。

Excel 2003 までの鉄板ネタ(INDEX/MACTHを使ったテクニック)は、Excel 2007 以降はテーブルによって克服され、使い勝手のよい、見やすい数式になっているのです。

なお、テーブル名で日本語が使えないわけではありません。IME 入力による日本語入力のため数式オートコンプリートがすぐに反映しないだけです。「顧客テーブル」というテーブル名を付けた場合は、範囲名で「顧客テーブル」と入れればテーブル名として認識されます。

(追記) COLUMN(テーブル名[列名]) が有効なのは、テーブルの領域が A1 から始まっている場合です。テーブルのようなデータの持ち方の場合は A1 からデータが入力されますが、もし、A列をあけて、1行名をあけるようなデータの持ち方をしている場合や1つのワークシートの複数のテーブルを作った場合は期待した結果にならないことに注意してください。その場合は MATCH 関数を使って [#見出し] の配列から列番号をとることになるが、「テーブル」というデータを扱うのであれば、1シート1テーブル、A1 から始める、としたほうがトラブルは少ないでしょう。

テーブル関連の投稿
[テーブルと入力規則] https://road2cloudoffice.blogspot.jp/2014/10/blog-post.html
[テーブルと集計行] https://road2cloudoffice.blogspot.jp/2014/10/blog-post_31.html
[テーブルと構造化参照] https://road2cloudoffice.blogspot.jp/2014/11/blog-post.html
[テーブルとピボット] https://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html
[テーブルとVBA] https://road2cloudoffice.blogspot.jp/2014/11/blog-post_7.html

[PR] VBAセミナー ベーシック、スタンダードを受講後は、これさえあれば何もいらない
 
Powered by Blogger.

自己紹介

自分の写真
1989年新卒で日本IBMに入社しダウンサイジング担当としてホストコンピュータと繋げるオフコン、UNIX、PCサーバーのプロジェクトを担当。1997年 MSKK(現日本マイクロソフト)入社、NT4出荷に伴い企業向けサポート部門のビジネスマネージャーとして Excel 使いとなり、2002年 にMSMVPなどをサポートするユーザーコミュ二ティ部門を設立、部門をリード。2006年にMSKK退職後、企業向けのITトレーニング会社・団体に携わり、2014年頃よりPowerBI勉強会主催メンバーの一人として参画、そのコミュニティ活動で MSMVP for Data Platform PowerBI 2017受賞。https://mvp.microsoft.com/ja-jp/PublicProfile/5002635 同年にMVP Awardを返上し、アマゾン ウェブ サービス ジャパンに入社、コミュニティプログラム担当として現在に至る。