Copilot の利用状況レポートで、使われていないライセンスを見つけて付け替える|最後に使った日の数え方と毎月の確認の手順
Copilot のライセンスは使われているのか、使っていない人の席を回してよいのか。Microsoft 365 管理センターの使用状況レポートを書き出し、アプリ別の列から最後に使った日を出して、部署とライセンスの名簿を足し、付け替えの候補と待つ人を分ける進め方を、毎月の確認の手順と集計のスクリプトつきで説明します。
目次 クリックで開く
更新の見積もりを前に、配った Copilot のライセンスが本当に使われているのかを聞かれた。使っていない人の席は、使いたがっている人に回してよいのか。使用状況レポートを開くと似た名前の日付の列が並び、どれが答えか分からない。
答えは、日付の列のうちいちばん新しい日を一人ずつ出し、付けてからの日数と合わせて区分することです。Copilot の利用を毎月見る立場で、そのまま使える確認の表とスクリプトも付けました。
以下の図と表は、Microsoft Learn の列と定義に沿って当社が作った架空の会社のデータで、人数や割合は確かめ方を説明するための値です。当社は Microsoft 365 の導入と運用を手伝っています。
従業員約900人の会社で、Copilot ライセンスを持つ120人を、最後に使った日から書き出した日(10月20日)まで何日たったかで分けました。28日以内に使った100人は「使っている」、29〜60日前の5人は「声をかける」、それより前か日付が無い12人は「付け替えの候補」です。日付が無い11人のうち3人は、付けてから60日たっていないので「待つ」にしました。
この図は、書き出しを1回と名簿を2つ用意すれば作れます。ただし、数える列と期間を取り違えると、同じ日の書き出しから77人とも108人とも数えられてしまいます。
見るのは、使用状況レポートのユーザー別の表
名前を先にそろえます。Learn ではアプリを「Microsoft Copilot」に改め、ライセンスもこの名前で書くページが多くなっていますが、価格ページの製品名は「Microsoft 365 Copilot」のままです。レポートは、Learn では「Microsoft Copilot 使用状況レポート」、管理センターの画面では [Microsoft 365 Copilot] > [Copilot] の [使用量] タブに「Microsoft 365 Copilot の使用状況」という見出しで出ます。以下、ライセンスを Copilot ライセンス、このレポートを使用状況レポートと呼びます。
Copilot の利用を見るレポートはいくつかあり、ライセンスの付け替えに関係するのは次の4つです。一人ずつの行があり、アプリごとに最後に使った日が入っているのは、使用状況レポートのユーザー別の表です。
| レポート | 開く場所 | 載っている人 | 期間 | 一人ずつの表 | 使い道 |
|---|---|---|---|---|---|
| 使用状況レポート(Microsoft Copilot 使用状況レポート) | 管理センターの [レポート] > [使用状況](ページ名は「利用状況」)> [Microsoft 365 Copilot] > [Copilot] の [使用量] タブ | 過去180日に一度でも Copilot ライセンスを持った人 | 上部で選ぶ(Learn の記事では7・28・90・180日)。この記事では28日(無ければ30日) | あり([エクスポート] で CSV) | 付け替えの候補を出す |
| Copilot Chat のレポート(Microsoft Copilot Chat 使用状況レポート) | 同じ [Microsoft 365 Copilot] の下の [Copilot Chat] | Copilot ライセンスを持たずに Copilot Chat を使った人だけ | 上部で選ぶ(Learn の記事では7・28・90・180日)。この記事では28日(無ければ30日) | あり(CSV) | 付け替え先の候補を探す |
| Cowork の使用状況(Copilot Cowork usage) | 管理センターの [Copilot] > [Cowork] の Usage タブ | 2026年4月1日以降に Cowork を使った人 | 日付の範囲を選ぶ(既定は直近28日) | あり(CSV) | Cowork を使っている人を、付け替えの候補から外す前に確かめる |
| Viva の Copilot ダッシュボード | Viva インサイトの web アプリの [Copilot ダッシュボード] | Copilot ライセンスを持つ人(ライセンスの無い人の Copilot Chat の利用も) | 直近28日(最大6日遅れ) | 名前つきの一人ずつの表は無い(部署などの集計。最小グループ サイズより少ない集まりは出ない) | 部署ごとの使われ方を部門長と見る。Copilot ライセンスが1〜49で Viva インサイトのライセンスが50未満だと、週・月の推移やベンチマークなどは含まれない |
期間・対象は2026年10月24日時点の Microsoft Learn の記述。管理センターの画面で確かめたのは、利用状況のページ、Copilot と Copilot Chat のレポートの見出しとタブ、名前を隠す設定、[課金情報] > [ライセンス] とユーザーの [ライセンスとアプリ] までで、その名前は画面の表示どおりです。Cowork の Usage タブ、Entra の [ユーザーをダウンロード]、Viva の [Copilot ダッシュボード]、組織メッセージのページ、ユーザー別の表の [列の選択]・[エクスポート] は画面では見ておらず、Learn の表記で書いています。
Microsoft Purview の監査ログにも Copilot とのやり取りは残りますが、Microsoft は、監査ログを使用状況の集計の土台にすることは意図していないとし、監査ログから数えたプロンプト数や利用者数は使用状況レポートと一致しないことがある、とも書いています。部署ごとの割合だけなら Viva の Copilot ダッシュボードで足りますが、誰の席を回すかを決めるには一人ずつの行が要ります。
写真は Copilot ライセンスを付けた翌日の画面で、カードはすべて0でした。同じ日の試用環境では、このレポートに「組織には割り当てられた Copilot ライセンスがありません」とも出ていました。使用状況レポートは、Learn の全般の説明でも、通常24〜72時間以内に使えるようになり、数日かかることもあるとされています。なお、このタブを Learn は [使用状況]、画面は [使用量] と表示しています。
書き出す前に決めること:名前を出すか、何日で見るか
使用状況レポートは、既定でユーザー名や表示名を隠して表示します。全体管理者は、組織のプライバシー方針で許される場合に、管理センターの [設定] > [組織の設定] の [サービス] タブで [レポート] を開き、「すべてのレポートでユーザー、グループ、サイト名を隠蔽する」のチェック(既定でオン)を外して保存すれば、名前を表示できます。Microsoft Graph の adminReportSettings でも変えられます。
変更は数分で反映され、Microsoft Graph や Power BI の使用状況レポート、Teams 管理センターの使用状況レポートにも効きます(パネルの説明にも同じことが書かれています)。名前を表示したことは Microsoft Purview の監査ログに記録されます。
組織のすべてのレポートに効く設定なので、外す前に、名前つきの一覧を誰が見て、何に使うかを決めておきます。同じ Copilot のレポートの [準備] タブ(準備状況レポート)の「Copilot の候補」の列について、Microsoft は「このデータは、従業員のパフォーマンスを評価するために使用するためのものではありません」と書いています。使用状況の一覧も、付け替えと声かけのためだけに使い、人事の評価には使わないと先に決めておけば、部門長にも本人にも説明しやすくなります。
期間は、レポートの上部で選びます。管理センターの利用状況のページの説明は7・30・90・180日で、Learn の使用状況レポートの全般のページも「一般に」7・30・90・180日とし、個別のレポートの記事を見るよう求めています。その Copilot の使用状況レポートの記事は7・28・90・180日です。付け替えの判断には28日(無ければ30日)を使い、毎月同じ日に書き出します。ある日の利用は、通常その日の終わり(UTC)から48時間以内にレポートに入ります。ユーザー別の表は [列の選択] で表示する列を選べるので、Last activity date の列をすべて表示した状態で [エクスポート] から CSV に書き出します。
書き出しのほかに名簿が2つ要ります。1つは部署の名簿です。使用状況レポートには部署の列が無いので、Microsoft Entra 管理センターの [Microsoft Entra ID] > [ユーザー] > [すべてのユーザー] > [ユーザーをダウンロード] で CSV を書き出し(手順)、department(部署)の列を使います。Viva の Copilot ダッシュボードの部署の絞り込みも、既定ではこの欄を使うので、空欄の人が多ければ先に埋めておきます。
もう1つはライセンスの名簿で、Copilot ライセンスを付けた人と、付けた日・外した日の一覧です。使用状況レポートには付けた日が無く、表には外した人も残るので、自社の割り当ての記録から作り、人数は管理センターの [課金情報] > [ライセンス] の数と照らします。
書き出しの段階で起きやすい取り違えが2つあります。1つは、Copilot Chat のレポートで、ライセンスを持つ人の Chat の利用を見ようとすることです。このレポートは Copilot ライセンスを持たない人だけが対象なので、240行あってもライセンスを持つ人は出てきません。ライセンスを持つ人の Chat の利用は、使用状況レポートの Copilot Chat (work)(職場)と Copilot Chat (web) の列で見ます。図では120人中76人が、28日以内にどちらかを使っていました。
もう1つは、名前を隠したまま書き出して部署の名簿と突き合わせることです。ユーザー名の列が隠れた値になるので、129行のうち1人も一致しません。設定を外して書き出し直すと、今ライセンスがある120人が全員一致します。
最後に使った日は、日付の列のいちばん新しい日で数える
ユーザー別の表には、数の列と日付の列があります。Prompts submitted (any app)(送信したプロンプトの数)と Active Days(アクティブな日数)は、選んだ期間の中の数です。日付の列は、全体の Last activity date (UTC) と、Teams・Word・Excel などアプリ別の Last activity date で、期間を7日にしても180日にしても同じ日が出ます。
数の列で「使っているか」を決めると、ずれが出ます。Active Days は Copilot Chat にプロンプトを送った日数なので、Teams の会議の要約や Word の機能だけを使う人は、使っていても0日になりえます。また、90日の期間で書き出すと、2か月前に使ったきりの人もプロンプトが1件以上になります。
日付の列も、全体の列だけに頼らないほうが安全です。Learn は全体の列を、定義の欄では Copilot Chat にメッセージを送った最新の日と書き、機能の表では Word・Excel・PowerPoint などの機能の利用もこの日付に示されると書いていて、同じページの中で書き方が分かれています。アプリ別の列は、そのアプリで意図的な操作をした最新の日です(Copilot のアイコンを開いただけでは数えず、プロンプトを送るなどの操作で数えます)。そこで、全体の列とアプリ別の列のうち、いちばん新しい日を「最後に使った日」にします。どちらの書き方が実際の挙動でも、取りこぼしが出ません。
今ライセンスがある120人について、同じ10月20日にそれぞれの期間で書き出した表から数えると、90日の表でプロンプトが1件以上の人は108人、28日の表で Active Days が1日以上の人は77人、最後に使った日が28日以内の人は100人でした。Active Days が0日なのに、アプリ別の列では28日以内に使っていた人が23人います。
分母にも気をつけます。ユーザー別の表は、過去180日のどこかで Copilot ライセンスを持ったすべての人の一覧で、あとで外した人や、一度も使っていない人も載ります。図の129行のうち9行は外した人でした。ライセンスの名簿と突き合わせて今の120人に絞ってから割ります(100÷129=77.5% ではなく、100÷120=83.3%)。
日付が無い人を、そのまま「一度も使っていない」と決めつけないでください。使用状況レポートの FAQ には、ライセンスを付けて24時間以内に使い、その後使っていない人は、まれに最後に使った日が空になる、と書かれています。アプリ別の列についても、Word・Excel・PowerPoint・OneNote・Outlook の日付は、データの送信が遅れて空欄や実際より新しい日になることがある、とあります。日付が無い人は、外す前に本人に確かめます。
日数は書き出した日から数えます。表の日付は UTC で、データは通常2日ほど遅れて入るので、28日や60日の境目の前後にいる人は、翌月の確認でもう一度見ます。
区分の境目(28日・60日)は、この記事の例です。自社で決めるときは、保存しておいた過去の書き出しを並べ、最後に使った日から30日・60日・90日といった区切りごとに、翌月の確認で使っていた人を数えます。戻る人がほとんどいなくなる区切りを、付け替えの候補の境目にします。付けて間もない人を待つ日数も、付けた日から何日目の確認で初めて最後に使った日が出たかを数えて決めます。
部署を足して、薄いアプリの列を見る
ライセンスの名簿で絞った表に、部署の名簿を User name と userPrincipalName で突き合わせて部署を足します。部署ごとに、使っている人の割合と、アプリ別の列が28日以内の人の割合を並べたのが次の図です。
読む順は2つです。まず、使っている人の割合が全体(83.3%)より低い部署を探します。図では▼を付けた行です。次に、その行で色の薄いアプリの列を見ます。薄い列は、その部署でまだ Copilot を使っていない場面なので、声をかけるときに使い方を案内する場面の候補になります。
ライセンスを持つ人が5人未満の部署は「その他」にまとめ、まとめても5人に届かないときは割合を出していません。人数の少ない部署の割合は、誰が使っていないかがほぼ分かってしまうからです。Viva の Copilot ダッシュボードも、組織が決めた最小グループ サイズより少ない集まりの数字は表示しません。
付け替えの判断の表
区分ごとに、次にすることと、その結果どうするかを決めておきます。人数は10月20日の値です。
| 区分 | 条件 | 人数 | 次にすること | その結果 |
|---|---|---|---|---|
| 使っている | 最後に使った日が28日以内 | 100人 | そのまま | 翌月も同じように確かめる |
| 待つ(付けて間もない) | 付けて60日未満で、28日以内に使っていない | 3人 | 使い始めの案内を送る | 付けて60日を過ぎたあとの確認で、ほかの区分に振り分ける |
| 声をかける | 最後に使った日が29〜60日前 | 5人 | 本人に使い方を案内する | 翌月の確認で使っていれば「使っている」に戻る。61日を過ぎれば「付け替えの候補」に移る |
| 付け替えの候補 | 最後に使った日が61日以上前か日付が無い(付けて60日以上) | 12人 | 本人と上長に使う予定を確かめる。Cowork を使えるようにしている組織では、Cowork の使用状況も見る | 予定が無ければ外す。予定があると答えた人は残し、翌月も使っていなければ外す |
| 表に無い(確かめる) | ライセンスの名簿にいて、使用状況レポートの表にいない | 0人 | 付けた日と、アカウントが残っているかを確かめる | 付けた直後なら「待つ」と同じ扱い。それ以外は名簿を直す |
| 付け替え先の候補 | Copilot Chat のレポートで、28日のうち10日以上 Chat を使った、ライセンスの無い人 | 17人 | 部署の希望と合わせて、付ける順番を決める | 付けた日から60日は「待つ」として扱う |
28日・60日は、自社の過去の書き出しで数え直して決めます。10日は、空く席の数に合わせて上げ下げします。
Cowork を使うにも Copilot ライセンスが要ります。Cowork の利用が使用状況レポートの日付の列に入るかは、使用状況レポートのページには書かれていないので、Cowork を使えるようにしている組織では、外す前に Cowork の使用状況で、その人が Cowork を使っていないかを見ます。
本人と上長への確認は、返事の期限を次の月の確認より前に置きます。期限までに返事が無ければ外す、と最初の連絡に書いておくと、外した席を次の確認の前に付け替え先へ回せます。
ライセンスを外すのも付けるのも、管理センターの [課金情報] > [ライセンス] で製品を選び、[ライセンスの割り当て] か、人の行を選んで出る [ライセンスの割り当て解除] で行えます。1人ずつなら、[ユーザー] > [アクティブなユーザー] で人を選び、[ライセンスとアプリ] でも変えられます(手順。ライセンス管理者かユーザー管理者以上のロールが要ります)。
同じライセンスでも、画面によって製品名の書き方が違うことがあります。試用環境では、ライセンスの画面で「Microsoft 365 Business Premium with Copilot」、ユーザーの [ライセンスとアプリ] で「Microsoft 365 Business Premium と Microsoft 365 Copilot Business」と出ていました。名簿と照らすときは、製品名ではなく人で突き合わせます。
声のかけ方には、使用状況レポートに組み込まれた組織メッセージも使えます。Copilot ライセンスを持ち30日間使っていない Windows 11 の利用者に、Windows の通知でメッセージを送るカードなどがあり、送る相手を Microsoft 365 グループで絞れます。メッセージを見た数やクリックの数は、管理センターの [レポート] の組織メッセージのページで確かめられます。
付け替え先の候補は、Copilot Chat のレポートから探します。スクリプトに Copilot Chat のレポートの CSV も渡すと、28日のうち10日以上 Chat を使ったライセンスの無い人を、部署を付けた一覧(chat_candidates_日付.csv)に書き出します。10日は、空く席の数に合わせて上げ下げします。
このレポートには、以前ライセンスを外したあとに Chat を使った人も載るので、一覧の licensed_before の列で見分けます。[準備] タブの準備状況レポートにも、ライセンスの無い人のうち Microsoft 365 アプリをよく使う上位25%を示す Suggested candidate for Copilot(Copilot の候補)の列がある、と Learn には書かれています。ただ、当社の試用環境で見た表と [列の選択] には、この列は出ていませんでした(Username など7列)。
付け替えの候補12人の席を回すと、Microsoft 365 Copilot(大企業向け)の年払いの価格で、12人×4,497円=月53,964円分のライセンスが、使う人のところに移ります(ユーザーあたり月額相当・税抜、2026年10月24日に価格ページで確認。300ユーザーまでの Microsoft 365 Copilot Business は価格が違います)。新しく買い足す前に、まずこの席から回します。
声をかけた効き目は、本人たちの翌月で見る
声をかけた効き目は、声をかけた本人たちが翌月の確認で「使っている」に戻ったかで見ます。比べる相手は、声をかけなかった月の同じ区分の戻り方です。図の例では、声をかけなかった4か月で、前回「声をかける」だった人は延べ16人、そのうち翌月に使っていたのは5人(31%)でした。
1か月だけでは決めません。この例の戻り方(31%)なら、5人ほどだと、効き目が無くても、たまたま2〜3人が戻ることがあります。図の例でも、何もしなかった8月20日に7人中4人が戻っています。声をかけた人の戻りを何か月分か足し、延べの人数が何もしなかった月の延べ(この例では16人)と同じくらいになったところで、合計の戻り方を比べます。
比べた結果は3通りです。何もしなかった月の戻り方をはっきり上回れば、声かけが効いたとみなして続けます。この例の戻り方(16人中5人)のまま声かけが効いていないとすると、延べ16人のうち9人以上が戻る確率は3.3%で、5%を下回るいちばん少ない人数なので、9人以上なら偶然では起きにくいと考えます(8人以上なら9.2%)。これは、一人ひとりが5/16の確率で戻るかどうかが互いに独立だと仮定した二項分布の値で、9人から16人までについて「16人から k 人を選ぶ組み合わせの数 ×(5/16)の k 乗 ×(11/16)の(16−k)乗」を足したものです。自社では、自社の何もしなかった月の戻り方と延べの人数で数え直します。
同じくらいなら、効き目はまだ分からないので、もう何か月か足して比べ直します。下回るか、ほとんど戻らない月が続くなら、相手・案内の中身・時期のどれかを変えます。どの月の確認も、声をかけてから28日の期間がまるごと入ったあとに行います。
付け替えの候補で「使う予定がある」と答えて残した人も、同じように見ます。比べる相手は、何もしなかった月の付け替えの候補の戻り方で、この例では延べ40人中3人でした。どちらの数も、スクリプトが前回の結果と比べて画面に出します。
比べる相手は、自社の書き出しで作ります。過去の書き出しを残しているなら、古い月から順に、同じフォルダで、その月の書き出しと書き出した日を渡してスクリプトを実行すると、月ごとの戻り方が出ます(スクリプトは直前の結果としか比べないので、順番に回します)。その前の月に声をかけていた月は、何もしなかった月には数えません。名前を隠す設定のまま保存した書き出しは、名簿と一致しないので使えません。
残していないなら、今月から書き出しを保存し始め、声をかける相手を部署ごとに順に広げて、まだ声をかけていない部署の戻り方と比べます。部署ごとの戻り方は、前回と今回の license_review_日付.csv の kind と dept の列で、前回「声をかける」だった人を部署ごとに数えれば出せます。ただし、部署によって使っている人の割合が違うので、まだ声をかけていない部署の戻り方が、声をかけた部署と同じ条件だとは限りません。比べるなら、使っている人の割合が近い部署どうしにします。
会社全体の割合(付けて60日以上の人のうち使っている人)は、何もしなかった月でも83.3〜89.1%の間を動き、付け替えで外した人と付けた人の分だけ分母の顔ぶれが入れ替わるので、声かけの効き目の判定には使いません。また、使っている人の割合は、Copilot で仕事の時間が減ったかどうかとは別の数字です。研修のあとに業務の所要時間で確かめる方法は、Copilot 研修を買う前に、社内で決めることに書きました。
毎月の確認の手順
ここまでを毎月の作業にすると、次のようになります。日付は毎月20日の例です。
| いつ | 誰が | どのレポート・名簿 | 期間 | 何を見るか | どう判断するか |
|---|---|---|---|---|---|
| 毎月20日 | 情報システムの担当(レポート閲覧者など、使用状況レポートを見られる管理者ロール) | 使用状況レポートのユーザー別の表と、Copilot Chat のレポートを [エクスポート] | 28日(無ければ30日) | 書き出した日をファイル名に入れて保存する | — |
| 同じ日 | 情報システムの担当 | Entra の [ユーザーをダウンロード]、ライセンスの名簿 | — | 部署の空欄、名簿の人数と [課金情報] > [ライセンス] の数が合うか | 合わなければ名簿を直してから集計する |
| 同じ日 | 情報システムの担当 | 集計のスクリプト(先月と同じフォルダで実行) | 28日(無ければ30日) | 区分ごとの人数、「表に無い」人、部署×アプリの表、前回「声をかける」だった人の戻り方 | 「表に無い」人を確かめる。戻り方を記録し、何か月分か足して何もしなかった月と比べる |
| 翌営業日まで | Copilot の推進担当 | 区分「声をかける」「待つ」の一覧 | — | 誰に何を案内するか | 組織メッセージか個別の連絡で案内する |
| その月のうち | 推進担当と部門長 | 区分「付け替えの候補」、Cowork の使用状況、付け替え先の候補の一覧 | 28日(無ければ30日) | 本人に使う予定があるか、Cowork を使っていないか、付け替え先は誰か | 期限までに予定が無ければ外して、付け替え先に付ける |
| 3か月ごと | 推進担当 | Viva の Copilot ダッシュボード | 直近28日 | 部署ごとの使われ方の推移 | 部門長との打ち合わせで、声のかけ方を見直す |
Learn のロールの一覧で「ユーザーの詳細なし」と書かれたロール(使用状況サマリー レポート閲覧者など)では、ユーザー別の詳細は見られません。
集計のスクリプト(Python)
図の数は、次のスクリプトで出しました。Python 3 の標準の機能だけで動き、追加のインストールは要りません。引数は、使用状況レポートの CSV、部署の名簿、ライセンスの名簿、書き出した日、(あれば)Copilot Chat のレポートの CSV です。実行すると、一人ずつの区分を書いた license_review_日付.csv ができ、画面に区分ごとの人数、最後に使った日の分布、付けて60日以上の人のうち使っている人の割合、部署×アプリの表が出ます。
毎月同じフォルダで実行すると、前回の license_review と比べて、前回「声をかける」「付け替えの候補」だった人のうち今回使っている人の数も出ます。
列名は、Microsoft Learn のユーザー別の表の英語表記に合わせています(2026年10月24日時点)。書き出したファイルの見出しが違うときは、先頭の USER や APPS を直してください。ユーザー別の表はデータが入るまで画面に出ないため、列名はまだ管理センターの画面では確かめておらず、Learn の表記です(同じ画面の [準備] タブの表は Username などの英語の列名でした)。日付は 2026-10-18、2026/10/18(日本語の Excel で保存した形)、10/18/2026(時刻つきも可)を、文字コードは UTF-8 と Shift_JIS を読みます。
ライセンスの名簿は userPrincipalName・assigned_date・removed_date の3列で作ります。外した人は removed_date に日付を入れて残しておくと、過去の月の書き出しも同じスクリプトで集計できます。付けた日が空欄の人は「待つ」にせず、画面に人数を出します。
# Copilot 使用状況レポートのユーザー別の表から、最後に使った日と付け替えの区分を出す
# 使い方: python copilot_license_review.py 使用状況.csv 部署の名簿.csv ライセンスの名簿.csv 書き出した日 [Copilot Chat.csv]
# 例: python copilot_license_review.py usage.csv users.csv licenses.csv 2026-10-20 chat.csv
# 毎月同じフォルダで実行すると、前回の license_review_<日付>.csv と比べて、声をかけた人が戻ったかも出す
import csv, glob, re, sys, datetime as dt
from collections import Counter, defaultdict
# 書き出したファイルの見出しが違うときは、ここを直す
USER, NAME_DEPT, LIC_USER, LIC_FROM, LIC_TO = 'User name', 'department', 'userPrincipalName', 'assigned_date', 'removed_date'
CHAT_USER, CHAT_DAYS_COL, CHAT_PROMPTS = 'Username', 'Active days', 'Prompts submitted'
APPS = {'Teams': 'Last activity date of Teams Copilot (UTC)', 'Outlook': 'Last activity date of Outlook Copilot (UTC)',
'Word': 'Last activity date of Word Copilot (UTC)', 'Excel': 'Last activity date of Excel Copilot (UTC)',
'PowerPoint': 'Last activity date of PowerPoint Copilot (UTC)', 'Chat (work)': 'Last activity date of Copilot Chat (work) (UTC)'}
USED, CALL, WAIT, MIN_GROUP, CHAT_DAYS = 28, 60, 60, 5, 10 # 使っている/声をかける の日数、付けてから待つ日数、部署をまとめる人数、付け替え先の目安
def read(path):
for enc in ('utf-8-sig', 'cp932'):
try:
with open(path, encoding=enc, newline='') as f:
return list(csv.DictReader(f))
except UnicodeDecodeError:
pass
raise SystemExit(f'文字コードを読めません: {path}')
def day(s):
"""2026-10-18、2026/10/18、10/18/2026、10/18/2026 0:00、2026-10-18T00:00:00Z を読む。空欄は None"""
s = (s or '').strip().split(' ')[0].split('T')[0]
if not s:
return None
a, b, c = (int(x) for x in re.split(r'[-/]', s))
return dt.date(a, b, c) if a > 31 else dt.date(c, a, b)
usage, users, lic = read(sys.argv[1]), read(sys.argv[2]), read(sys.argv[3])
base = dt.date.fromisoformat(sys.argv[4])
dept = {u[LIC_USER].lower(): u[NAME_DEPT] or '(部署なし)' for u in users}
now, ever = {}, set() # 書き出した日にライセンスが付いていた人と付けた日(空欄は None)
for r in lic:
u, a, z = r[LIC_USER].lower(), day(r[LIC_FROM]), day(r[LIC_TO])
ever.add(u)
if (a is None or a <= base) and not (z and z <= base):
now[u] = a
held_by = Counter(dept.get(u, '(部署なし)') for u in now)
group = lambda d: d if held_by[d] >= MIN_GROUP else 'その他(5人未満の部署)' # 少人数の部署は個人が分かるのでまとめる
table = {r[USER].lower(): r for r in usage}
strange = sum(1 for u in table if u not in dept and u not in ever) # 名前が隠れていると、ほぼ全部の行がここに入る
rows = []
for upn, assigned in now.items():
r = table.get(upn)
held = (base - assigned).days if assigned else None
if r is None: # 名簿にいて表にいない(付けた直後、反映の遅れ、アカウントの削除など)
rows.append({'user': upn, 'dept': group(dept.get(upn, '(部署なし)')), 'assigned': assigned or '', 'last_used': '', 'days': '',
'kind': '表に無い(確かめる)', 'apps_28d': ''})
continue
dates = [day(v) for k, v in r.items() if k.startswith('Last activity date') and day(v)]
last = max(dates) if dates else None # 全体の列とアプリ別の列のうち、いちばん新しい日
gone = (base - last).days if last else None
if gone is not None and gone <= USED:
kind = '使っている'
elif held is not None and held < WAIT:
kind = '待つ(付けて間もない)'
elif gone is not None and gone <= CALL:
kind = '声をかける'
else:
kind = '付け替えの候補' # 日付が無い人を含む。空欄でも使っていないとは限らないので、外す前に本人に確かめる
apps = [a for a, c in APPS.items() if day(r.get(c)) and (base - day(r[c])).days <= USED]
rows.append({'user': r[USER], 'dept': group(dept.get(upn, '(部署なし)')), 'assigned': assigned or '', 'last_used': last or '',
'days': '' if gone is None else gone, 'kind': kind, 'apps_28d': '/'.join(apps)})
out = f'license_review_{base}.csv'
with open(out, 'w', encoding='utf-8-sig', newline='') as f:
w = csv.DictWriter(f, fieldnames=['user', 'dept', 'assigned', 'last_used', 'days', 'kind', 'apps_28d'])
w.writeheader(); w.writerows(rows)
k = Counter(r['kind'] for r in rows)
print(f'表の行 {len(usage)} / 書き出した日にライセンスがある人 {len(now)} / 表と一致した人 {len(now) - k["表に無い(確かめる)"]} / '
f'どちらの名簿にも無い行 {strange} / 付けた日が空欄 {sum(1 for a in now.values() if a is None)}')
print('区分:', dict(k))
bins = Counter('表に無い' if r['kind'].startswith('表に無い') else '日付が無い' if r['days'] == '' else '0-7日' if r['days'] <= 7 else
'8-28日' if r['days'] <= 28 else '29-60日' if r['days'] <= 60 else '61-90日' if r['days'] <= 90 else '91日以上' for r in rows)
print('最後に使った日から:', dict(bins))
judged = [r for r in rows if r['kind'] != '表に無い(確かめる)' and (r['assigned'] == '' or (base - r['assigned']).days >= WAIT)]
if judged:
print(f'付けて{WAIT}日以上の人のうち使っている人: {sum(r["kind"] == "使っている" for r in judged)}/{len(judged)} '
f'= {sum(r["kind"] == "使っている" for r in judged) / len(judged):.1%}')
by = defaultdict(list)
for r in rows:
if not r['kind'].startswith('表に無い'):
by[r['dept']].append(r)
print('部署 | 人数 | 使っている | ' + ' | '.join(APPS))
for d, rs in sorted(by.items(), key=lambda x: -len(x[1])):
pct = lambda n: f'{n / len(rs):.0%}' if len(rs) >= MIN_GROUP else '—' # まとめても5人に届かなければ割合を出さない
print(d, len(rs), pct(sum(r['kind'] == '使っている' for r in rs)), *[pct(sum(a in r['apps_28d'].split('/') for r in rs)) for a in APPS], sep=' | ')
prev = sorted(p for p in glob.glob('license_review_*.csv') if p < out) # 前回の確認と比べる(同じフォルダに残しておく)
if prev:
before = {r['user'].lower(): r['kind'] for r in read(prev[-1])}
cur = {r['user'].lower(): r['kind'] for r in rows}
for was in ('声をかける', '付け替えの候補'):
ids = [u for u, kd in before.items() if kd == was and u in cur]
print(f'前回({prev[-1][15:25]})「{was}」で今もライセンスがある {len(ids)}人のうち、今回「使っている」: {sum(cur[u] == "使っている" for u in ids)}人')
if len(sys.argv) > 5: # Copilot Chat のレポート(ライセンスを持たない人だけ)から付け替え先の候補
chat = [r for r in read(sys.argv[5]) if int(r[CHAT_DAYS_COL] or 0) >= CHAT_DAYS]
with open(f'chat_candidates_{base}.csv', 'w', encoding='utf-8-sig', newline='') as f:
w = csv.writer(f)
w.writerow(['user', 'dept', 'active_days', 'prompts', 'licensed_before'])
for r in sorted(chat, key=lambda r: -int(r[CHAT_DAYS_COL])):
u = r[CHAT_USER].lower()
w.writerow([r[CHAT_USER], dept.get(u, '(部署なし)'), r[CHAT_DAYS_COL], r[CHAT_PROMPTS], 'yes' if u in ever else ''])
print(f'付け替え先の候補(期間内に {CHAT_DAYS} 日以上 Chat を使った、ライセンスの無い人): {len(chat)}人 → chat_candidates_{base}.csv')
Excel で同じことをするなら、書き出した表に列を1つ足して Last activity date の列すべての MAX で最後に使った日を出し、XLOOKUP で部署の名簿とライセンスの名簿から部署と付けた日を引きます。日付が文字列として読み込まれたときは、日付に直してから計算します。
図の会社は、従業員900人・9部署で、4月1日に112人へ Copilot ライセンスを付け、途中で9人を外し、17人を足した、という想定で作りました。5月から10月まで毎月20日に書き出したことにした半年分の表を、このスクリプトで順に集計しています。日本語の Excel で保存した日付、時刻つきの日付、付けた日の空欄、名簿にいて表にいない人を入れた表でも、同じスクリプトが止まらずに動くことを確かめました。
今月の一覧を、来月の比べる相手として残す
今月声をかけた人が来月戻ったかは、今月の一覧が手元に無いと数えられません。名前を隠す設定を外すかどうかと、名前つきの一覧を誰が見るかを決めたら、今月の使用状況レポートを28日(無ければ30日)の期間で書き出し、ファイル名に書き出した日を入れて保存してください。スクリプトは毎月同じフォルダで実行します。付け替えの候補は今月の書き出しからすぐ出せます。声をかけるのを一部の部署から始めておけば、来月の確認で、声をかけた部署とまだの部署の戻り方を並べられます。
ライセンスを配る相手の決め方や、この確認を社内の手順に組み込むところで迷ったら、当社のMicrosoft 365・Google Workspace 活用支援のページから相談できます。
AI活用支援
Claude・ChatGPT・Gemini・Copilotのどれをどの業務に使うかの見極めから、社内のAIチャット環境、権限と情報の扱いの設計、MCPやAPIでの既存システム連携、研修・伴走までを支援します。
