Quantcast
Channel: いつも隣にITのお仕事
Viewing all 2074 articles
Browse latest View live

【エクセルVBAでIE操作】WEBページのテーブル要素からセルのデータを取り出す方法

$
0
0
cell

photo credit: andrey.pehota via photopin (license)

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

初心者向けエクセルVBAでIEを操作するシリーズをお送りしています。

前回の記事はこちら。

【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法
初心者向けエクセルVBAでIEを操作するシリーズ7回目。今回はHTMLにおけるテーブルの構成の仕方に触れつつ、そのテーブル内のデータを取得するというWEBスクレイピングらしいテクニックを解説します。

IEでWEB上の表を取得し、その各行のテキストを取得する方法をお伝えしました。

さて、行を表すtr要素の配下には、さらにセルを表すtd要素というものがあります。

今回は、それを一つ一つ取り出していきたいと思います。

ということで、WEBページのテーブル要素からセルのデータを取り出す方法です。

では、行ってみましょう!

前回のおさらい

前回からテーマにしているのは、こちらのYahooファイナンスの時価総額ランキングのページです。

時価総額上位:株式ランキング – Yahoo!ファイナンス

前回は、HTMLで表の構造がどのようになっているのか、Google Chromeのデベロッパーツールで確認をしつつ、以下のようなプロシージャを作成しました。

Sub MySub()
    
    Dim objIE As InternetExplorer
    Set objIE = New InternetExplorer
    
    objIE.Visible = True
    objIE.Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
    
    Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
        DoEvents
    Loop
    
    Dim htmlDoc As HTMLDocument
    Set htmlDoc = objIE.Document
    
    Dim tr As HTMLTableRow
    For Each tr In htmlDoc.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        Debug.Print tr.innerText
    Next tr
    
End Sub

ページ内に、テーブルの本体セクションを表すtbody要素が1つしかありませんので、それをまず取得、その後それに含まれる行を表すtr要素をコレクションとして取得しました。

さて、今回はそのtr要素の配下にさらにtd要素がありますので、その取得をしていきたいと思います。

テーブルの各セルのテキストを取り出す

tr要素からtd要素のコレクションを取得する

前回のプロシージャの17~19行目で、tr要素についてのループになっていますが、このtr一つ一つについてtd要素を取得して、それについてループをするというネスト構造にしていけば良さそうです。

tr要素を表すHTMLTableRowオブジェクトに対しても、他のHTML要素と同じくgetElementsByTagNameメソッドを使うことができます。

HTMLTableRowオブジェクト.getElementsByTagName(タグ名)

これで、td要素HTMLTableCellオブジェクトのコレクションとして取得できるわけです。

td要素のコレクションをループしてテキストを取り出す

そのコレクションに対してループをしてあげれば、個々のセルのデータを取り出すことができます。

Dim td As HTMLTableCell
For Each td In tr.getElementsByTagName("td")
    'td要素に対する処理
Next td

今回も、innerTextプロパティでテキストを取り出してみましょう。

HTMLTableCellオブジェクト.innerText

テーブルのtd要素のテキストを取り出すプロシージャ

では、以上を踏まえてプロシージャを作り直します。

こちらです。

Sub MySub()
    
    Dim objIE As InternetExplorer
    Set objIE = New InternetExplorer
    
    objIE.Visible = True
    objIE.Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
    
    Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
        DoEvents
    Loop
    
    Dim htmlDoc As HTMLDocument
    Set htmlDoc = objIE.Document
    
    Dim tr As HTMLTableRow
    For Each tr In htmlDoc.getElementsByTagName("tbody")(0).getElementsByTagName("tr")
        
        Dim td As HTMLTableCell
        For Each td In tr.getElementsByTagName("td")
            Debug.Print td.innerText,
        Next td
        
        Debug.Print
    Next tr
    
End Sub

実行をすると、以下のような出力を得られます。

テーブルのtd要素のテキストを出力

まとめ

以上、エクセルVBAでWEBページのテーブル要素からセルのデータを取り出す方法をお伝えしました。

入れ子状態にはなっていますが

  1. getElementsByTagNameメソッドでコレクションを取得
  2. For Each文でコレクションをループ
  3. 各要素に対して処理

という基本動作の組み合わせになっていることがわかりますよね。

テーブルはこのような階層構造を取得するには良い題材ですよね。

次回以降、さらに凝った取得の仕方についてお伝えできればと思います。

【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
初心者向けエクセルVBAでIEを操作するシリーズです。今回はIEを操作してWEBページ内の検索窓に任意のキーワードを入力して送信する方法をお伝えします。GoogleChromeの検証機能も活用しますよ!

どうぞお楽しみに!

連載目次:エクセルVBAでIEを操作してWEBスクレイピング

IEを操作してWEBページのデータを取得して、エクセルのデータとして取り込む、つまりWEBスクレイピングをエクセルVBAで実現します。各種WEBページを課題として様々なデータの取得の仕方を解説していきたいと思います。

  1. 【エクセルVBAでIE操作】10分で終わるセッティングとWEBページの閲覧確認
  2. 【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
  3. 【エクセルVBAでIE操作】ブラウザの読み込み待ちをしないとダメなのです
  4. 【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する
  5. 【エクセルVBAでIE操作】ディスクリプションなどの要素をname属性でGetする
  6. 【エクセルVBAでIE操作】hタグなどの要素をタグ名でGetする
  7. 【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法
  8. 【エクセルVBAでIE操作】WEBページのテーブル要素からセルのデータを取り出す方法
  9. 【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
  10. 【エクセルVBAでIE操作】ページをクロールしてブログの記事一覧を取得する方法
  11. 【エクセルVBAでIE操作】ブログの記事一覧ページから公開日とカテゴリを取得する
  12. 【エクセルVBAでIE操作】ページャーを最後のページまでどんどんリンクする
  13. 【エクセルVBAでIE操作】ユーザー名とパスワードを入力してログインをする
  14. 【エクセルVBAでIE操作】name属性を利用して画像ボタンをクリックする
  15. 【エクセルVBAでIE操作】alt属性・src属性を利用して画像ボタンをクリックする

【QUERY関数】group by句とsum関数で列の値の合計値を求める

$
0
0

QUERY関数10アイキャッチ

みなさんこんにちは!
もり(@moripro3)です。

GoogleスプレッドシートQUERY関数の使い方をシリーズでお届けしています!

前回の記事では、group by句とcount関数を使用して、列の要素数をカウントする方法を紹介しました。

スプレッドシートのCOUNTIF関数で集計するよりも、QUERY関数で集計したほうが「項目名を設定する必要がなく、項目の集計漏れが発生しない」というメリットがあります。

【QUERY関数】group by句とcount関数で列のデータ数をカウントする
GoogleスプレッドシートのQUERY関数を紹介するシリーズ。第九回目は、group by句を使用して値を集計する方法の紹介です。group by句は集計関数と併せて使用します。count関数データの個数を数えます。

引き続き、値の集計をするgroup by句を紹介します。

「group by句は集計関数と一緒に使用する」というルールを前回お伝えしましたね。今回は、集計関数のsum関数を使用して、値の合計値を求める方法を紹介します。

スプレッドシートのSUMIF(S)関数もありますが、count関数と同じように、QUERY関数を使用したほうが集計漏れが発生しないのでオススメですよ。

それではみていきましょう!

前回のおさらい:group by句と集計関数とは

QUERY関数は、クエリで抽出した結果を、グループ化して集計することが可能です。そのためには、下記の2つを理解しておく必要があります。

  • データをグループ化するための「group by句」
  • データを処理するための「集計関数」

group by句とは、複数行にわたる値を集計するための句です。

group by 列

group by句で指定するすべての列は、select句で集計関数によって集計されている必要があります。

集計関数とは、指定の列の値に対して処理を実行する関数です。count, sum, avg, max, minの5種類があります。

    集計関数(列)

     

    今回は、合計値を求めるsum関数を紹介します。備品購入リストのサンプルを用いて、単価の合計値を求めていきます。

    query9-1

    列の値の合計値を求めるsum関数

    sum関数は、指定列の値の合計を求める関数です。

    sum(列)

    まずは最も簡単な使い方です。D列「単価」の合計値を求めます。

    =query(A:E,"select sum(D)",1)

    query10-1

    合計値50,300を求めることができました。

    項目ごとの合計値を求める

    続いて、E列「購入者」ごとの合計金額を算出してみます。select句でE列を指定し、かつ、group by句でE列をグループ化します。

    =query(A:E,"select E,sum(D) group by E",1)

    query10-2

    E列購入者ごとの合計金額を算出できました。

    QUERY関数の第1引数に列全体を指定してるため、空白行も集計されています。前回同様に「データが存在する行のみを集計対象とする」ことで解決します。

    where 列 is not null

    where句を使用して、E列がnull(空白)でない行、つまり、なんらかのデータが存在する行のみを集計対象にすればOKですね。

    =query(A:E,"select E,sum(D) where E is not null group by E",1)

    query10-3

    label句で項目名を設定する

    集計関数を使用すると、集計結果の項目名が「関数名+列名」となります。

    たとえば、D列「単価」の合計値をsum関数で求める場合、「sum 単価」と自動で設定されます。この項目名を変更する方法を紹介します。

    query10-4

     

    label句を使用すると、抽出結果の列に任意の名前をつけることができます。

    label 列 ラベル名

    ポイントは2つです。

    • ラベル名はシングルクォートで囲んで文字列とする
    • 「D列の合計値」にラベルを付けるので、label D ではなく、label sum(D) と記述する

    D列の合計値に「合計額」というラベルを付ける書き方がこちらです。

    =query(A:E,"select sum(D) label sum(D) '合計額'",1)

    query10-5

     

    それでは、このlabel句を使用して、購入者ごとの合計金額を求めたクエリにラベルを付けてみます。

    label句は、QUERY関数の第2引数の最後に記述します。

    =query(A:E,"select E,sum(D) where E is not null group by E label sum(D) '合計額'",1)

    query10-6

    「sum 単価」の表記(H1セル)が、label句で指定した「合計額」に変わりましたね。

    まとめ

    今回の記事では、group by句とsum関数を使用して、列をグループ化して値の合計値を求める方法を紹介しました。

    記述が長くなると難しく感じますが、select, where, group by, label それぞれの句の役割をきちんと理解し、順番につなげていけば大丈夫です。

    この記事では、下記の1~4の順番でクエリを組み立てています。もう一度復習もかねてご確認ください。

    select E,sum(D) where E is not null group by E label sum(D) '合計額'

    1. select句で集計する列を指定する
    2. where句で空白行を除外する
    3. group by句で列をグループ化する
    4. label句で項目名を変更する

      次回も引き続きgroup by句でデータの集計をする方法を紹介します。どうぞお楽しみに!

      連載目次:GoogleスプレッドシートQUERY関数をマスターしよう

      スプレッドシートのQUERY関数を使って、データ抽出・集計を効率化する方法を紹介しています。

      1. スプレッドシートのQUERY関数を使う最初の一歩!クエリを理解する
      2. QUERY関数の基本!別シートのデータからselect句で列を取得する方法
      3. 【QUERY関数】where句と比較演算子を使って単一条件に一致した行を抽出する
      4. 【QUERY関数】where句とlike演算子を使用して指定の文字を含む行を抽出する
      5. 【QUERY関数】where句で日付データを条件にして行を抽出する
      6. 【QUERY関数】where句で時刻データを条件にして行を抽出する
      7. 【QUERY関数】where句でand,orを使用して複数条件を指定する
      8. 【QUERY関数】order by句で抽出結果を昇順・降順ソートする
      9. 【QUERY関数】group by句とcount関数で列のデータ数をカウントする

      【保存版】実務でOutlook VBAを使いこなすための初心者向け完全マニュアル

      $
      0
      0

      outlook,vba,manual

      皆様こんにちは、ノグチです。

      メーラーの定番、MicrosoftのOutlook。

      規定のメーラーに指定している会社も多いのではないでしょうか。

      メールはとっても便利で、気軽に様々な情報をやり取りできてしまうのですが、反面受信ボックスの中に欲しい情報が埋もれてしまって、取り出すのに一苦労…なんてことも起きがちです。

      Outlook VBAは、そんな困りごとの解決手段として使えるかもしれません。

      このページは、Outlookを使う上での困りごとの解決や、Outlookをより便利に使うといった、Outlook VBAを実務で使うあれこれをまとめたページです。

      下記のVBAリファレンスも併せてご覧くださいね。

      【保存版】VBAリファレンス~キーワード別インデックス
      VBAのリファレンスページで、Excel・Word・PowerPointなど共通でご利用いただけます。 ステートメント・関数・オブジェクト・メソッド・プロパティなどについてキーワード別にリストアップしています。

      連載目次:はじめてのOutlook VBA

      Outlook VBAで、予定やタスクの登録方法など、Outlookを操作する方法をご紹介しています。メーラーやスケジューラとして便利なOutlookですが、VBAで更に便利なツールにしてしまいましょう!

      1. 【はじめてのOutlook VBA】Outlookの予定を登録する方法
      2. 【Outlook VBA】エクセルワークシートの内容で予定登録する方法
      3. 【Outlook VBA】今開いているOutlookウインドウを操作しよう!Inspectorオブジェクトの取得
      4. 【Outlook VBA】CurrentItemプロパティで今開いているメールのMailItemオブジェクトを取得する方法

      連載目次:Outlook VBAでメールを操作してみよう

      メーラーとして名高く、そして便利なOutlook。

      Outlookのメールだって、VBAで操作することができますよ。本シリーズでは、Outlookのメールを、VBAで操作する方法をご紹介していきます。

      1. 【Outlook VBA】メールの送信時イベントで確認ダイアログを表示する方法
      2. 【Outlook VBA】UnReadItemCountプロパティで受信フォルダの未読メール件数を取得する方法
      3. 【Outlook VBA】メール本文から欲しい情報だけを取り出す方法

      連載目次:Outlook VBA 予定を登録してみよう

      Outlook VBAで、予定の管理も便利にしてしまいましょう。

      VBAでの予定の登録だけでなく、登録済みの予定への操作方法もご紹介しています。

      1. 【はじめてのOutlook VBA】Outlookの予定を登録する方法
      2. 【Outlook VBA】エクセルワークシートの内容で予定登録する方法
      3. 【Outlook VBA】登録済みの予定を日付で検索して取得する方法
      4. 【Outlook VBA】イベントApplication_Startupで起動時に今日の予定を表示する方法

      連載目次:Outlook VBAでタスクを登録してみよう

      Outlook VBAで基本的なタスクを登録する方法と、応用編としてエクセルワークシートに書き出した複数のタスクを、一括で登録する方法をご紹介していきます。

      1. Outlook VBAでタスクを登録する最も簡単なプログラム
      2. 【Outlook VBA】エクセルワークシートのタスク一覧をOutlookのタスクに登録する方法

      連載目次:Outlook VBAでメールの添付ファイルを操作しよう

      Outlook VBAでメールの添付ファイルを指定フォルダにワンクリックで保存する方法をご紹介しています。1件ずつメールを開いて、添付ファイルをクリックして、保存先のフォルダを選んで...なんて地味に面倒な作業とはオサラバです。

      1. 【Outlook VBA】今開いているOutlookウインドウを操作しよう!Inspectorオブジェクトの取得
      2. 【Outlook VBA】CurrentItemプロパティで今開いているメールのMailItemオブジェクトを取得する方法
      3. 【Outlook VBA】今開いているメールのAttachmentsコレクションを取得する方法
      4. 【Outlook VBA】メールの添付ファイルをワンクリックで指定フォルダに保存する方法
      5. 【Outlook VBA】受信フォルダにあるメールの添付ファイルを指定フォルダに取り出す方法

      コミュニティ内で初心者向けプログラミング講座を開催してどうだったか

      $
      0
      0

      みなさん、こんにちは!
      タカハシ(@ntakahashi0505)です。

      「ノンプログラマーのためのスキルアップ研究会」は、ノンプログラマーがプログラミングをはじめとするITスキルを学び合うコミュニティです。

      2019年2月から、コミュニティ内でプログラミング初心者講座を行うという、新たな取り組みを行っていたんですね。

      コミュニティ連携型!初心者向けプログラミング講座開講のお知らせ
      コミュニティ「ノンプログラマーのためのスキルアップ研究会」と連携した、VBAおよびGoogle Apps Script初心者講座(全6回)を開催させていただくことになりましたのでお知らせします。

      Google Apps ScriptとVBAの2つのコースで、それぞれ毎週、計6回ずつ。

      先日のノンプロ研定例会は、初心者講座の卒業発表会という企画で、計15名の受講者の皆さんにLT形式で発表をしていただきました。

      いや~、盛り上がりましたね~。

      ということで、今回はその発表会を受けてのレポートをお送りします。

      ちなみに当日の様子は以下、Togetterのツイートまとめもご覧くださいませ。

      ノンプロ研定例会Vol.17「初心者講座第一期生卒業LT大会」
      今回は、2019年2月から4月まで、約2ヶ月にわたり開催された「ノンプロ研初心者講座第一期」の卒業発表会です!初心者講座VBAコース・GASコースに参加された皆さん(できる限り全員)に5~10分程..

      では、行ってみましょう!

      講師という立場で学びだったこと・嬉しかったこと

      私は講師という立場で両方のコースに携わっていたので、みなさんがどう捉えていたのか…大変興味があったのですが、いくつかすごくためになる&嬉しいコメントをいただきましたので、そのあたりを重点にお伝えしていきます。

      解説・写経・宿題のバランス

      解説・写経・宿題のバランス…これが良かったとおっしゃっていただけるの、本当に嬉しいです。

      企業向け研修をたくさんこなしてきた経験が生きているのですが、どうしても一方的な喋りの時間が長いと飽きたり、眠くなったり、集中が切れたりしちゃうので、なるべく頻繁に写経の演習を入れるようにしています。

      また、写経ならばその解答時間に個人差出ないのですが、ロジックを考える問題は、個人差がメチャメチャ生まれてしまう…

      そのために、ロジックを考える問題は、全て宿題に回すという作戦をとっています。

      本来は、これで実務でツールを作るトライができるくらいになるのに8週なのですが、ノンプロ研の場合は、事前演習+Slackでのサポートで、それをなんとか圧縮して6週。

      おかげで、金銭的コストも下げられる…!

      こんな計算でおりましたから…全員にマッチというのは難しいのでしょうけど、皆さんの発表を聴く限り、ほとんどの方が何らかのツールには取り組まれていたので、概ねうまくいったのかなと思います。

      教えるほうも・教わるほうも仲間

      ほんと、ティーチング・アシスタントさんへの感謝を伝えていらっしゃる方が本当に多かったです。

      当日の準備のお手伝いや受講者のサポートをはじめ、Slackでの質疑応答・フォロー・解説・解答案の作成・飲み会の参加…本当にたくさんのご協力をいただきました。

      ノンプログラマーって社内にはなかなか仲間がいないので、仲間に飢えてるんですよね。たぶん。

      自分もそうだったからわかります。

      もちろん、受講者の皆さんも、先輩方がいるのは心強いしモチベーションになると思うのですが、教えるほうも仲間が増えるのが嬉しいんですね。

      この化学反応は、コミュニティ内で研修を行うならではですね。

      すごくいいことだなと思いました。

      教えることは2度学ぶこと

      コミュニティでは口酸っぱく「教えることは2度学ぶこと」とお伝えしまくっているのですが、受講者の皆さんもそれをすでに実践されていて、まあそれは本当に効果的だなと思います。

      この初心者講座の内容を受けて、所属する会社内で勉強会を開いていらっしゃる方も何人もいらっしゃいました。

      また、今度開催されるノンプロ研初心者講座の第二期でティーチング・アシスタントに立候補いただいた方も何人かいらっしゃいます。

      そうやって、教える立場になれる方が増えると、どんどん指数関数的にプログラミングスキルを身につける方が増えていく…

      その先がなんて楽しみなんでしょう!!

      課題と思ったこと

      マンパワー的にキツイ

      第2期もありがたいことにGASコースが開催決定、VBAコースもあと2名で開催決定するところまできています(2019年4月19日執筆時点)。

      また、VBAもGASも中級編や、さらにハンズオン的にピンポイントで個別のパートをお送りするというご要望もたくさんいただいています。

      あと、Pythonの初心者講座も…やりたいですね。

      ただ、今回GASコースとVBAコースを並行してやってみて、私一人が講師だとマンパワー的に正直キツイというのがありました。

      当日はこなせたとしても、SlackでのサポートもかなりTAさんに助けていただいちゃいましたし、動画撮影やリモートのセッティングや、編集・アップロードなどの事務作業も発生します。

      なので、この問題を解消するために、ノンプロ研内で講師と動画系のお手伝いができる方を増やす必要があります。

      そこさえできれば、講座の種類や回数を増やしていけるな~…とワクワクな世界がやってきます。

      Slackをもっと盛り上げたい

      受講者の皆さんには、もっと気軽にSlackに質問を上げて欲しいな~と思いました。

      おそらくTAさんの解説が、すごく参考になっていたとは思うのです。

      ですが、ハマったポイントとか、勘違いしていたこととか、そういうのは「できない人」しか持ちえない価値あるコンテンツなんですよね。

      それがまた、他のメンバーにも有益なんです。

      なので、講座全体の価値をもっと上げるポイントとしては、力を入れたいところだな~と。

      何か施策を考えたいですね~

      首都圏以外のエリアから気持ちよく参加いただきたい

      首都圏以外のエリアにお住まいの方にどうやってクオリティを下げずに参加いただけるか…これは、けっこうな悩みでした。

      今回、GASコースに関しては大阪チームも5名参加がありまして、きのぴぃさんや大阪の皆さんの神対応のおかげで、急遽大阪サテライト会場を設けることができました。

      ただ、リモート配信でハングアウトが満席になったりとか、Zoomに切り替えて設定ミスってたとか、そういうトラブルがちょいちょいありました。

      あと、今回の発表会ですが、皆さん都合が合わなかったのもあり、おひとりだけリモートで発表いただいていたのですが、それでもハウリングしまくりでセッティングが決まらず…なかなかもたついてしまいました。

      モウ、セッティング、ムズイ

      まず、従来のセッティングは安定して行うこと(ここはだいぶノウハウついたので大丈夫と思う)、あと理想は現地で講義自体ができることなので、それも含めて欲深く展開していきたいと思います。

      まとめ

      そんな感じで、2ヶ月間行ってきた初心者講座第一期、そして卒業発表LT大会

      少し課題はあるにしても、皆さんのおかげで良い学びの機会になったかと思います。

      5月からGASコースの第二期がはじまりますし、そしてVBAコースの第二期やPythonその他についてどんどん機会を設けていきます。

      コミュニティ連携型!初心者向けプログラミング講座開講のお知らせ
      コミュニティ「ノンプログラマーのためのスキルアップ研究会」と連携した、VBAおよびGoogle Apps Script初心者講座(全6回)を開催させていただくことになりましたのでお知らせします。

      2019/5/16の定例会では、「『教えて二度学ぶ!』 ノンプロ研講座開催のA to Z」と題しまして、メンバーの皆さんが講師として(またはTAやサポート)参加できるように道筋を作れればと思っています。

      ご興味がある方はぜひご参加を!

      また、合わせて今後のノンプロ研講座の展開を楽しみにしていてくださいね~

      「ノンプログラマーのためのスキルアップ研究会」について

      コミュニティ「ノンプログラマーのためのスキルアップ研究会」では、毎月の定例会や勉強会、Slackでのやり取りを通して、皆さんのプログラミング学習の質やモチベーションを高めるための活動をしています。 過去の活動については、以下のページをご覧ください。
      コミュニティ「ノンプログラマーのためのスキルアップ研究会」の活動レポートまとめ
      コミュニティ「ノンプログラマーのためのスキルアップ研究会」(略して「ノンプロ研」)。このページはその活動レポートまとめページです。コミュニティ活動の一気読みをされたい方、ぜひご活用くださいませ。
      ぜひ、皆様のご参加をお待ちしております!
      コミュニティ「ノンプログラマーのためのスキルアップ研究会」についてのお知らせ #ノンプロ研
      ノンプログラマーがVBA・GAS・Pythonなどのプログラミングを学ぶコミュニティ「ノンプログラマーのためのスキルアップ研究会」が絶賛活動中です!本ページはコミュニティの情報発信をしていく特集ページです。

      エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法

      $
      0
      0
      table

      photo credit: Cristian Ştefănescu He was a friend of mine via photopin (license)

      みなさん、こんにちは!
      タカハシ(@ntakahashi0505)です。

      エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。

      前回の記事はこちら。

      エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
      エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。今回は、エクセルVBAでIEを操作するクラスに、リンクテキストでa要素を探して取得するメソッドを追加していきます。

      リンクテキストでa要素を探してリンクする方法でした。

      今回のテーマはテーブルデータの取得です。

      普通に処理書くとわりと面倒なので、クラスのメンバーとして定義しておけば簡単にできそうですよね…!

      ということで、エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法です。

      では、行ってみましょう!

      前回のおさらい

      では、前回のおさらいからです。

      まずIEを操作するクラスIEObjectです。

      Public IE As InternetExplorer
      Public Document As HTMLDocument
      
      Private Sub Class_Initialize()
          Set IE = New InternetExplorer
          IE.Visible = True
      End Sub
      
      Private Sub Class_Terminate()
          IE.Quit
      End Sub
      
      Public Sub Navigate(ByVal url As String)
          IE.Navigate url
          Wait
          Set Document = IE.Document
      End Sub
      
      Public Sub Wait()
          Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
              DoEvents
          Loop   
      End Sub
      
      Public Function GetElementByLinkText(ByVal text As String) As HTMLAnchorElement
          
          Set GetElementByLinkText = Nothing
          
          Dim anchor As HTMLAnchorElement
          For Each anchor In Document.Links
              If anchor.innerText = text Then
                  Set GetElementByLinkText = anchor
                  Exit Function
              End If
          Next anchor
          
      End Function

      前回は、GetElementByLinkTextメソッドを作りました(今回の内容で関わるメンバーだけ掲載しています)。

      検証するための標準モジュールのプロシージャがこちらでした。

      Sub MySub()
          
          Dim ieObj As IEObject: Set ieObj = New IEObject
          ieObj.Navigate "https://tonari-it.com"
          
          Dim text As String: text = "詳細・お申込はこちら"
          
          Dim anchor As HTMLAnchorElement
          Set anchor = ieObj.GetElementByLinkText(text)
          
          If Not anchor Is Nothing Then
              ieObj.Navigate anchor.href
          Else
              Debug.Print text; "をテキストとするa要素はありませんでした"
          End If
          
          Stop
          
      End Sub

      Webページのテーブルデータを取得する

      今回はガラっとネタが変わりまして、Webページのテーブルデータを取得する便利メソッドを作っていきます。

      こちらのYahooファイナンスの時価総額ランキングのページから、時価総額順位のテーブルデータを取得していこうというものです。

      時価総額上位:株式ランキング – Yahoo!ファイナンス

      ページを開いたイメージはこちらです。

      Yahooファイナンスの時価総額上位ランキングのテーブル

      幸い、このページにはテーブル要素はひとつしかありませんので、その取得は容易です。

      あとは、その内部のtr要素、そしてさらにその配下のth要素、td要素をループで取り出せればOKということですね。

      テーブルデータを取得して出力するメソッド

      まずは、table要素を渡すと、その内部のデータをイミディエイトウィンドウに出力するPrintTableDataメソッドを作ってみました。

      こちらです。

      Public Sub PrintTableData(ByVal table As HTMLTable)
                  
          Dim tr As HTMLTableRow
          For Each tr In table.getElementsByTagName("tr")
                  
              Dim th As HTMLTableCell
              For Each th In tr.getElementsByTagName("th")
                  Debug.Print th.innerText,
              Next th
              
              Dim td As HTMLTableCell
              For Each td In tr.getElementsByTagName("td")
                  Debug.Print td.innerText,
              Next td
              
              Debug.Print
          Next tr
          
      End Sub

      複雑そうに見えますが、テーブルの構造がわかっていれば以外と簡単です。

      まず、table要素をHTMLTableオブジェクトとしてパラメータtableで受けます。

      その配下には行を表すtr要素がありますから、その全てについてループを回します。それが4~17行目からのループです。

      さらに、行の中には見出しセルを表すth要素、もしくはtd要素がありますから、それぞれ存在するすべてについてループを回して、その内容をinnerTextプロパティで取得してデバッグ出力しています。

      テーブルデータ取得メソッドの動作確認

      では、このPrintTableDataメソッドを動作確認してみましょう。

      以下のプロシージャを標準モジュールに記述して実行してみます。

      Sub MySub()
          
          Dim ieObj As IEObject: Set ieObj = New IEObject
          
          With ieObj
              .Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
              .PrintTableData .Document.getElementsByTagName("table")(0)
          End With
              
      End Sub

      かなりシンプルに書けますよね。

      実質、URLのアクセスをするNavigateメソッドと、テーブルを指定して出力するPrintTableDataメソッドの2行だけです。

      実行をすると、イミディエイトウィンドウに、以下のようにテーブル内のデータが出力されます。

      Webページのテーブルデータの出力結果

      まとめ

      以上、エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法をお伝えしました。

      テーブルの構造がきれいに揃っていないとちょっとうまくいかない場合もあるので注意です。

      さて、次回はせっかくデータを取得したので、シートに出力をするように変更していきたいと思います。

      どうぞお楽しみに!

      連載目次:エクセルVBAでIEを操作するクラスを作る

      エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。
      1. エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
      2. エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
      3. エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
      4. エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
      5. エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法

      【Outlook VBA】Application_NewMailExイベントでメール受信時にメッセージを表示する方法

      $
      0
      0

      outlook,vba,Application_NewMailEx

      みなさまこんにちは、ノグチです。

      Outlookでは、メールを受信した時にと音やデスクトップ通知で教えてくれますよね。

      でも音や通知だと見落としたり、別に報せなくてもいいメールも知らせてくれたりして、だんだんちゃんと見なくなっていったりして…

      携帯電話の着信音みたいに、特定の条件にマッチしたメールを受信した時だけ、違う方法で教えてくれたりしないかなあ…

      そんなお悩みを持つあなた、Outlook VBAならできるかもしれません!

      今回は、Application_NewMailExイベントで、Outlookでメールを受信したらメッセージを表示する方法をご紹介します!

      Application_NewMailExイベント

      Outlookでメールを受信した時に操作したい場合、Application_NewMailExイベントを使います。

      このイベントは、Outlookがメールを受信するたびに実行されるイベントなので、メール受信時に何か処理をさせたいならば、このApplication_NewMailExイベントのイベントプロシージャ内に処理を差し込んでいきます。

      引数EntryIDCollection

      Application_NewMailExイベントには、引数EntryIDCollectionがあります。

      メールや予定、カレンダーなど、Outlookのアイテムには、アイテムフォルダに保存されたタイミングで、必ず一意になるEntryIDというIDが付与されます。

      Application_NewMailExイベントの引数は、このEntryIDをString型で渡してくれるのです。

      GetItemFromIDメソッドでMailItemオブジェクトを取得

      Outlookのアイテムに一意のIDが付与されること、Application_NewMailExイベントの引数でそのIDが渡されることは、上でご説明した通りです。

      では今度は、引数で渡されたIDから受信したメールの情報を取得していきます。

      使用するのは、NameSpaceオブジェクトのGetItemFromIDメソッド。

      このメソッドは、NameSpace内で、引数に指定したEntryIDにマッチするアイテムを探して、取得したアイテムのオブジェクト型(メールならMailItemオブジェクト)で返してくれるメソッドです。

      記述方法はこちら。

      NameSpaceオブジェクト.GetItemFromID(EntryID)

      Application_NewMailExイベント内で使用するなら、記述方法のEntryIDの部分はイベントプロシージャの引数、”EntryIDCollection”がそのまま入ります。

      このように。

      NameSpaceオブジェクト.GetItemFromID(EntryIDCollection)

      NameSpaceオブジェクトについては下記記事でご紹介していますので、こちらも併せてご覧ください。

      【エクセルVBA】GetNamespaceメソッドでOutlookのデータフォルダにアクセスする方法
      GetNameSpaceメソッドでOutlookのデータフォルダにアクセスする方法をご紹介しています。このメソッドでOutlookのNameSpaceオブジェクトを取得すれば、メール、連絡先、予定表などのデータフォルダにアクセスして、更にその中のデータを読込んだり、エクセルシートに書き出したりすることができますよ。

      条件にマッチしたメールを受信したらメッセージを表示する

      ここまでご紹介したイベントとメソッドを使って、特定の条件を持ったメールを受信したらメッセージを表示するコードを書いてみましょう。

      こんな感じになります。

      Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
      Dim myItem As Outlook.Items
      Dim objId As Object
      
      Set myNamespace = GetNamespace("MAPI")
      Set objId = myNamespace.GetItemFromID(EntryIDCollection)
      
      If InStr(objId.Subject, "日報") Then
          MsgBox "日報が届きました!"
      End If
      End Sub

      メールの件名に「日報」という文字が入っていたら、「日報が届きました!」というメッセージを表示するというコードです。

      メールの情報は、GetItemFromIDメソッドで取得したMailItemオブジェクトのSubjectプロパティで取得しています。

      では、こちらのメールを送信して、イベントが実行されるか試してみます。

      outlook,vba,送信メール

      上のメールを受信すると…

      この通り、指定したメッセージが表示されますね。

      outlook,受信メール,メッセージ

      If文でMailItemオブジェクトのプロパティで取得できる値が条件とマッチするか?をチェックすればよいだけなので、条件にはSubjectプロパティ以外も使うことができますよ。

      MailItemプロパティについては、下記記事でご紹介していますのでこちらをご覧ください。

      【Outlook VBA】CurrentItemプロパティで今開いているメールのMailItemオブジェクトを取得する方法
      Outlook VBAで、今開いているメールの添付ファイルをワンクリックで任意のフォルダに保存する方法を5ステップにわけて、連載記事でご紹介しています。今回は、InspectorオブジェクトのCurrentItemプロパティによるMailItemオブジェクトの取得についての説明です。

      条件は吟味して!

      さて、ここまでApplication_NewMailExイベントについてご紹介してきましたが、注意点があります。

      それは、イベントで処理したいメールの条件はじっくり吟味しましょう!ということです。

      このイベント、メールが届くたびに実行されます。

      つまり、条件を広めにとってしまって、例えば上のようにメッセージを表示する処理をしていたとすると、メールが届く度にメッセージが表示されることに…

      メッセージの「OK」ボタンを押さない限り、メッセージが表示されている間はOutlookの操作ができなくなりますから、これが頻繁に起こるとなるとはっきり言ってめちゃくちゃ鬱陶しいです。

      折角の便利なイベントなので、欲張って鬱陶しくなるより、吟味した条件でスマートに使用していきたいですね。

      最後に

      今回は、Application_NewMailExイベントで、Outlookでメールを受信したらメッセージを表示する方法をご紹介しました。

      毎日大量のメールが来ていると、欲しいメールがその中に埋もれがちになりますよね。

      今回ご紹介した方法で、本当に欲しいメールの見落としを防いでみませんか?

      それでは、最後までお読みいただきありがとうございました!

      連載目次:Outlook VBAでメールを操作してみよう

      メーラーとして名高く、そして便利なOutlook。

      Outlookのメールだって、VBAで操作することができますよ。本シリーズでは、Outlookのメールを、VBAで操作する方法をご紹介していきます。

      1. 【Outlook VBA】メールの送信時イベントで確認ダイアログを表示する方法
      2. 【Outlook VBA】UnReadItemCountプロパティで受信フォルダの未読メール件数を取得する方法
      3. 【Outlook VBA】メール本文から欲しい情報だけを取り出す方法
      4. 【Outlook VBA】Application_NewMailExイベントでメール受信時にメッセージを表示する方法

      エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する

      $
      0
      0

      みなさん、こんにちは!
      タカハシ(@ntakahashi0505)です。

      エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方のシリーズです。

      前回の記事はこちら。

      エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法
      エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。今回は、エクセルVBAでIEを操作するクラスにテーブルのデータを取得してデバッグ出力するメソッドを追加していきます。

      Webページのテーブルデータを取得するメソッドを作成しました。

      それで、テーブルデータを取得しても、イミディエイトウィンドウに出力するだけではちょっと微妙ですよね…

      せっかくエクセルVBAなので、ワークシートに書き出すというのが基本っすもんね。

      ということで、今回はエクセルVBAによるIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを作成していきます。

      では、行ってみましょう!

      前回のおさらい

      まず、前回のおさらいからです。

      IEを操作するクラスIEObjectはこちらです。

      Public IE As InternetExplorer
      Public Document As HTMLDocument
      
      Private Sub Class_Initialize()
          Set IE = New InternetExplorer
          IE.Visible = True
      End Sub
      
      Private Sub Class_Terminate()
          IE.Quit
      End Sub
      
      Public Sub Navigate(ByVal url As String)
          IE.Navigate url
          Wait
          Set Document = IE.Document
      End Sub
      
      Public Sub Wait()
          Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
              DoEvents
          Loop   
      End Sub
      
      Public Sub PrintTableData(ByVal table As HTMLTable)
                  
          Dim tr As HTMLTableRow
          For Each tr In table.getElementsByTagName("tr")
                  
              Dim th As HTMLTableCell
              For Each th In tr.getElementsByTagName("th")
                  Debug.Print th.innerText,
              Next th
              
              Dim td As HTMLTableCell
              For Each td In tr.getElementsByTagName("td")
                  Debug.Print td.innerText,
              Next td
              
              Debug.Print
          Next tr
          
      End Sub

      前回は、Webページのtable要素を表すHTMLTableを渡すことで、そのデータをイミディエイトウィンドウに出力するPrintTableDataメソッドを作りました(今回の内容で関わるメンバーだけ掲載しています)。

      確認用の標準モジュールのSubプロシージャがこちらです。

      Sub MySub()
          
          Dim ieObj As IEObject: Set ieObj = New IEObject
          
          With ieObj
              .Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
              .PrintTableData .Document.getElementsByTagName("table")(0)
          End With
              
      End Sub

      これで、IEで表示したページの最初のtable要素のデータを取得することができます。

      Webテーブルのデータをシートに書き出すメソッド

      今回は、取得したテーブルデータをシート上に出力するように変更していきたいと思います。

      作ったメソッドがこちらのWriteTableDataメソッドです。

      Public Sub WriteTableData(ByVal table As HTMLTable, ByVal cell As Range)
                  
          Dim i As Long: i = 0
          Dim tr As HTMLTableRow
          For Each tr In table.getElementsByTagName("tr")
                  
              Dim j As Long: j = 0
              Dim th As HTMLTableCell
              For Each th In tr.getElementsByTagName("th")
                  cell.Offset(i, j).Value = th.innerText
                  j = j + 1
              Next th
              
              Dim td As HTMLTableCell
              For Each td In tr.getElementsByTagName("td")
                  cell.Offset(i, j).Value = td.innerText
                  j = j + 1
              Next td
                          
              i = i + 1
          Next tr
          
      End Sub

      対象となるtable要素であるHTMLTableオブジェクトに加えて、データを書き出す基点となるRangeオブジェクトをパラメータcellで受けるようにしました。

      その位置から、行方向にi、列方向にjというカウント変数を用います。

      • tr要素内のth要素・td要素をすべて取り出したらiをプラス1
      • th要素またはtd要素の内容をセルに書き込んだらjをプラス1

      そのi,jを使って、Offsetプロパティで書き出し先のセルを移動させていくという作戦です。

      WriteTableDataメソッドの動作確認

      では、以下のようなSubプロシージャを作成して、WriteTableDataメソッドの動作の確認をしてみましょう。

      Sub MySub()
          
          Dim ieObj As IEObject: Set ieObj = New IEObject
          
          With ieObj
              .Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
              .WriteTableData .Document.getElementsByTagName("table")(0), Sheet1.Range("A1")
          End With
              
      End Sub

      これまたシンプルですね。

      書き出し先はオブジェクト名Sheet1のA1セルとします。

      実行すると、IEが動作して以下のようにシートにテーブルデータが書き出されます。

      シートに書き出したWebページのテーブルデータ

      51位以降を取得したい場合は

      1. ページをめくってtable要素を取得
      2. 書き出したシートの最終行を求める
      3. 最終行の次の行以降にテーブルデータを書き込む

      という流れで作れば良さそうですね。

      あと、一部見出しにセルの結合があったり、フッターにも見出し行があったりするので、その辺が気になれば、標準モジュールの処理で追加する必要がありますね。

      必要に応じてチャレンジしてみてください。

      まとめ

      以上、エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する方法をお伝えしました。

      縦横がきれいにそろっているtable要素であればだいたいうまく取得して書き出せると思いますので、便利かな~と思います。

      次は、検索窓にテキストを入力するメソッドを作っていきます。

      どうぞお楽しみに!

      連載目次:エクセルVBAでIEを操作するクラスを作る

      エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。
      1. エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
      2. エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
      3. エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
      4. エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
      5. エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
      6. エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法

      【QUERY関数】group by句とavg関数で列の値の平均値を求める

      $
      0
      0

      QUERY関数11アイキャッチ

      みなさんこんにちは!
      もり(@moripro3)です。

      GoogleスプレッドシートQUERY関数の使い方をシリーズでお届けしています!

      前回の記事では、group by句とsum関数を使用して、列の値の合計値を算出する方法を紹介しました。

      【QUERY関数】group by句とsum関数で列の値の合計値を求める
      GoogleスプレッドシートのQUERY関数を紹介するシリーズ。第十回目は、group by句とsum関数で項目毎の値の合計値を求める方法です。label句を使用して集計結果の列名を変更することもできます。

      さて、合計値ときたら…次に求めたいのは「平均値」ですよね!

      今回の記事では、この2点を紹介します。

      • 平均値を求めるavg関数の使い方
      • セルの書式設定をするformat句で小数点の端数処理をする方法

      それでは備品購入リストのサンプルを用いて、見ていきましょう!

      query11-1

      列の値の合計値を求めるavg関数

      avg関数は、指定列の値の平均値を求める関数です。

      avg(列)

      まずは最も簡単な使い方です。D列「単価」の平均値を求めます。

      =query(A:E,"select avg(D)",1)

      query11-2

      G2セルにD列の平均値が算出されました。

      ご覧のとおり、小数点以下まで計算・表示されています。次の項で、format句を使用して整数部のみの表示にする方法を紹介します。

      query11-3

      format句でセルの書式設定をする

      format句とは、セル(列)に書式設定をするための句です。

      format 列 表示形式

      この記事ではformat句を使用した「数字」の書式設定を紹介しますが、format句では日付の書式設定もできるので、興味のある方はこちらの公式ドキュメント(英語版)も併せてご覧ください。

      小数点以下を四捨五入して整数表示にする

      数字3桁ごとにカンマで区切り、小数点以下を四捨五入して整数部のみを表示させる記述です。表示形式はシングルクォートで囲みます。

      =query(A:E,"select avg(D) format avg(D) '#,##0'",1)

      query11-4

      このformat句では、スプレッドシート上の表示が変わるだけで、avg関数の算出結果は変わりません。

      query11-5

       

      表示形式が ‘#,##0’ だと、下4桁しか表示されないように見えてしまいますが、5桁以上の数字でも大丈夫です。

      「QUERY関数で小数点を丸めて整数表示にする時は、format句で ‘#,##0’ と記述する」と覚えておきましょう!

      query11-9

      小数点以下の指定の桁数まで表示させる

      format句では、ピリオドのあとにゼロを並べることで、小数点以下の桁数を指定できます。小数点2桁まで表示(小数点第3位を四捨五入)させる書き方がこちらです。

      =query(A:E,"select avg(D) format avg(D) '#,##0.00'",1)

      query11-6

      なお、この場合も、スプレッドシート上の表示桁数が変わるのみで、avg関数の算出値自体が変わるわけではありません。

      項目ごとの平均値を求める

      続いて、group by句を使用して、B列「区分」ごとの平均値を算出してみます。group by句の使い方は、これまで紹介してきたcount関数・sum関数と同じです。

      select句でB列を指定し、かつ、group by句でB列をグループ化します。group by句は、format句よりも前に書きます。

      =query(A:E,"select B,avg(D) group by B format avg(D) '#,##0'",1)

      query11-7

      B列「区分」ごとの平均値を算出できました。

      QUERY関数の第1引数に列全体を指定しているため、空白行も集計されています。

      where 列 is not null

      これも前回記事と同様に、where句を使用して、null(空白)でない行(なんらかのデータが存在する行)のみを集計対象にすればOKです。

      =query(A:E,"select B,avg(D) where B is not null group by B format avg(D) '#,##0'",1)

      query11-8

      まとめ

      今回の記事では、group by句とavg関数で項目毎の平均値を求める方法・format句を使用してセルの書式設定をする方法を紹介しました。

      format句はクエリの最後に記述するのがポイントです。select, where, group by, format それぞれの句の役割と、記述する順番をもう一度おさらいしておきましょう。

      select B,avg(D) where B is not null group by B format avg(D) '#,##0'

      1. select句とavg関数で集計する列を指定する
      2. where句で空白行を除外する
      3. group by句で列をグループ化する
      4. format句で列の書式設定をする

       

        group by句で使用できる集計関数はまだまだあります。次回は、列の最大値・最小値を求めるmax関数とmin関数を紹介します。

        どうぞお楽しみに!

        連載目次:GoogleスプレッドシートQUERY関数をマスターしよう

        スプレッドシートのQUERY関数を使って、データ抽出・集計を効率化する方法を紹介しています。

        1. スプレッドシートのQUERY関数を使う最初の一歩!クエリを理解する
        2. QUERY関数の基本!別シートのデータからselect句で列を取得する方法
        3. 【QUERY関数】where句と比較演算子を使って単一条件に一致した行を抽出する
        4. 【QUERY関数】where句とlike演算子を使用して指定の文字を含む行を抽出する
        5. 【QUERY関数】where句で日付データを条件にして行を抽出する
        6. 【QUERY関数】where句で時刻データを条件にして行を抽出する
        7. 【QUERY関数】where句でand,orを使用して複数条件を指定する
        8. 【QUERY関数】order by句で抽出結果を昇順・降順ソートする
        9. 【QUERY関数】group by句とcount関数で列のデータ数をカウントする
        10. 【QUERY関数】group by句とsum関数で列の値の合計値を求める

        エクセルVBAでIEを操作するクラスに検索入力&ボタンクリックのメソッドを追加する方法

        $
        0
        0

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。

        前回の記事はこちら。

        エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する
        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方のシリーズです。今回はエクセルVBAによるIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを作成していきます。

        エクセルVBAのIEクラスにWebページのテーブルデータをシートに書き出すメソッドを追加しました。

        さて、今回は少し方向性を変えまして、検索窓へのテキスト入力とボタンクリックをしてみたいと思います。

        ということで、エクセルVBAでIEを操作するクラスに検索窓の入力&ボタンクリックのメソッドを追加する方法です。

        では、行ってみましょう!

        前回のおさらい

        では、まずはおさらいから。

        IEを操作するクラスIEObjectはこちらです。

        Public IE As InternetExplorer
        Public Document As HTMLDocument
        
        Private Sub Class_Initialize()
            Set IE = New InternetExplorer
            IE.Visible = True
        End Sub
        
        Private Sub Class_Terminate()
            IE.Quit
        End Sub
        
        Public Sub Navigate(ByVal url As String)
            IE.Navigate url
            Wait
            Set Document = IE.Document
        End Sub
        
        Public Sub Wait()
            Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop   
        End Sub
        
        Public Sub WriteTableData(ByVal table As HTMLTable, ByVal cell As Range)
                    
            Dim i As Long: i = 0
            Dim tr As HTMLTableRow
            For Each tr In table.getElementsByTagName("tr")
                    
                Dim j As Long: j = 0
                Dim th As HTMLTableCell
                For Each th In tr.getElementsByTagName("th")
                    cell.Offset(i, j).Value = th.innerText
                    j = j + 1
                Next th
                
                Dim td As HTMLTableCell
                For Each td In tr.getElementsByTagName("td")
                    cell.Offset(i, j).Value = td.innerText
                    j = j + 1
                Next td
                            
                i = i + 1
            Next tr
            
        End Sub

        前回作成したのは、WriteTableDataメソッドで、table要素を表すHTMLTableオブジェクトと、書き出しの基点となるRangeオブジェクトを渡すと、テーブルデータをセルに書き出すというものでした(今回の内容で関わるメンバーだけ掲載しています)。

        確認用の標準モジュールのSubプロシージャがこちらです。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            
            With ieObj
                .Navigate "https://info.finance.yahoo.co.jp/ranking/?kd=4"
                .WriteTableData .Document.getElementsByTagName("table")(0), Sheet1.Range("A1")
            End With
                
        End Sub

        Yahoo!で検索をする機能をクラスに追加する

        今回は、「Yahoo!JAPAN」の検索窓から任意の文字列で検索をするという処理を作成していきます。

        Yahoo! JAPAN
        日本最大級のポータルサイト。検索、オークション、ニュース、天気、スポーツ、メール、ショッピングなど多数のサービスを展開。あなたの生活をより豊かにする「課題解決エンジン」を目指していきます。

        Yahoo!JAPANの検索窓と検索ボタン

        検索窓は「srchtxt」というidを持つtextタイプのinput要素、検索ボタンは「srchbtn」というidを持つsubmitタイプのinput要素です。

        なので

        • idで要素を取得して値を入力するメソッド
        • idで要素を取得してクリックするメソッド

        この2つを作って組み合わせていけば良さそうです。

        詳しくは以下記事もご参考くださいませ。

        【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
        初心者向けエクセルVBAでIEを操作するシリーズです。今回はIEを操作してWEBページ内の検索窓に任意のキーワードを入力して送信する方法をお伝えします。GoogleChromeの検証機能も活用しますよ!

        指定のidの要素の値を入力するメソッド

        では、まず指定のidの要素にテキストを入力するメソッドからです。

        引数としては、要素を特定するためのidと、入力する値をいずれも文字列型で渡します。

        Sub InputTextById(ByVal id As String, ByVal keyword As String)
            
            Document.getElementById(id).Value = keyword
            
        End Sub

        けっこうシンプルですね。

        指定のidの要素をクリックするメソッド

        次に、指定のidの要素をクリックするメソッドです。

        こちらはクリックするだけなので、引数はidだけですね。

        Sub ClickButtonById(ByVal id As String)
            
            Document.getElementById(id).Click
            Wait
            Set Document = IE.Document
            
        End Sub

        クリックすると画面遷移しますので、既にあるWaitメソッドを拝借して読み込み待ちをしています。

        また、Documentのセットもします。

        Yahoo!検索を行うメソッドの動作確認

        では、Yahoo!で検索を行うメソッドの実行確認していきましょう。

        以下のSubプロシージャを実行します。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            
            With ieObj
                .Navigate "https://www.yahoo.co.jp/"
                .InputTextById "srchtxt", InputBox("キーワードを入力してください")
                .ClickButtonById "srchbtn"
            End With
            
            Stop
            
        End Sub

        実行すると、まず入力ダイアログが表示されます。

        Yahoo!検索するキーワードを入力するダイアログ

        キーワードを入力して「OK」をクリックすると、IEでキーワードの入力とボタンクリックが動作して、以下の検索結果ページが表示されました。

        IEを操作してYahoo!検索結果ページを表示

        まとめ

        以上、エクセルVBAでIEを操作するクラスにYahoo!検索を行う入力&クリックのメソッドを追加する方法をお伝えしました。

        なんとなく、入力とクリックを同じメソッドに機能持たせたくなってしまう気もしますが、そこはぐっとこらえて別々にします。

        というのも、メソッドは汎用性があるほうが良いので、他のケースでも使えるようにしといたほうがいいんですね。

        次回は、検索結果ページから記事タイトルとURLを取得するメソッドを考えます。

        どうぞお楽しみに!

        連載目次:エクセルVBAでIEを操作するクラスを作る

        エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。
        1. エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
        2. エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
        3. エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
        4. エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
        5. エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
        6. エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法
        7. エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する

        エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法

        $
        0
        0
        login

        photo credit: Got Credit Login via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。

        前回の記事はこちら。

        エクセルVBAでIEを操作するクラスに検索入力&ボタンクリックのメソッドを追加する方法
        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。今回は、エクセルVBAでIEを操作するクラスに検索窓の入力&ボタンクリックのメソッドを追加する方法をお伝えします。

        検索入力&ボタンクリックのメソッドを追加しました。

        さて、今回はその応用になりますが、ログイン処理をするクラスをつくります。

        ログインが必要なサイトのスクレイピングをするならば、メソッド化しておくと便利ですものね。

        ということで、エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法です。

        では、行ってみましょう!

        前回のおさらい

        まずは、前回のおさらいからです。

        IEを操作するクラスIEObjectは以下の通りです。

        Public IE As InternetExplorer
        Public Document As HTMLDocument
        
        Private Sub Class_Initialize()
            Set IE = New InternetExplorer
            IE.Visible = True
        End Sub
        
        Private Sub Class_Terminate()
            IE.Quit
        End Sub
        
        Public Sub Navigate(ByVal url As String)
            IE.Navigate url
            Wait
            Set Document = IE.Document
        End Sub
        
        Public Sub Wait()
            Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop   
        End Sub
        
        Sub InputTextById(ByVal id As String, ByVal keyword As String)
            
            Document.getElementById(id).Value = keyword
            
        End Sub
        
        Sub ClickButtonById(ByVal id As String)
            
            Document.getElementById(id).Click
            Wait
            Set Document = IE.Document
            
        End Sub

        前回作成したのは、以下2つのメソッドでした。

        • InputTextByIdメソッド:input要素をidで取得してその値を入力する
        • ClickButtonByIdメソッド:input要素をidで取得してクリックする

        ちなみに、上記IEObjectクラスのコードは、今回の内容で必要なメンバーだけ掲載しています。

        それで、検証用の標準モジュールのプロシージャがこちらですね。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            
            With ieObj
                .Navigate "https://www.yahoo.co.jp/"
                .InputTextById "srchtxt", InputBox("キーワードを入力してください")
                .ClickButtonById "srchbtn"
            End With
            
            Stop
            
        End Sub

        さて、今回はログイン処理をしたいわけですが、入力欄に入力して、ボタンをクリックする…という動作でいうと、前回の内容が大いに参考になりますね。

        WordPressの管理画面にログインする

        今回は、例としてWordPressの管理画面にログインしてみたいと思います。

        ログインしていない状態で、管理画面のURL「https://example.com/wp-admin/」にアクセスすると以下の画面になります。

        WordPressのログイン画面

        ここで、ユーザー名とパスワードを入力し、ログインボタンをクリックすればログインできます。

        それぞれの要素は、以下に示すとおりid属性で取得可能です。

        • ユーザー名の入力フォーム:id=”user_login”のinput要素
        • パスワードの入力フォーム:id=”user_pass”のinput要素
        • ログインボタン:id=”wp-submit”のinput要素

        ただ、一度ログインをすると、一定のセッションの間はログイン済みと判定されますので、ログイン処理は不要です。

        ログイン処理を行うメソッド

        では、以上を踏まえて、クラスIEObjectにログイン処理を行うLogInメソッドを追加しました。

        コードはコチラです。

        Sub LogIn()
            
            Const LOGIN_URL As String = "https://example.com/wp-admin/" 'ログインURL
            
            With Me
                .Navigate LOGIN_URL
                    
                With .Document
                    .getElementById("user_login").Value = "XXXXXX" 'ユーザー名を指定
                    .getElementById("user_pass").Value = "XXXXXXXX" 'パスワードを指定
                    .getElementById("wp-submit").Click
                End With
            End With
            
        End Sub

        ログインページへのリンクは、既に作成したNavigateメソッドの力を借ります。

        検証用のプロシージャはこちらです。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            ieObj.LogIn
            
            Stop
            
        End Sub

        いや~スッキリしますね~。

        実行すると、未ログインの状態のときは、うまくログインできます。

        しかし、一度ログインした後に、再度実行すると、以下のように実行時エラーとなってしまいます。

        実行時エラー

        前述の通り、WordPressの管理画面は一度ログインすると、しばらくのセッションの間はログイン済みになりますので、ログイン画面に飛ばされずに済みます。

        ですから、id=”user_login”のinput要素が見つからずにエラーとなってしまうのです。

        つまり、ログイン済みかそうでないかの判定が必要になるのです。

        WordPressに限らず多くのサイトでは同様の仕組みが敷かれていますよね。

        ログイン状態かどうかを判定する

        ログイン状態かどうかを判定するには、どうしたらよいでしょうか。

        ログイン状態であれば、Navigateメソッドでページ遷移したURLをそのまま開けます。

        ただし、未ログイン状態であれば、いったんログイン画面のURLにリダイレクトされる、つまり、その際にIEで開いていれうドキュメントは、別のURLのものになっているわけですよね。

        ですから、読み込みが完了したときの、IEのドキュメントのURLが、Constステートメントで定義したURLと等しいかどうかを判定すれば良いわけです。

        ログイン状態の判定を踏まえたログインメソッド

        ログイン状態の判定を踏まえて、前述のLogInメソッドを修正しました。

        こちらです。

        Sub LogIn()
            
            Const LOGIN_URL As String = "https://example.com/wp-admin/" 'ログインURL
            
            With Me
                .Navigate LOGIN_URL
                    
                If .Document.url <> LOGIN_URL Then
                    With .Document
                        .getElementById("user_login").Value = "XXXXXX" 'ユーザー名を指定
                        .getElementById("user_pass").Value = "XXXXXXXX" 'パスワードを指定
                        .getElementById("wp-submit").Click
                    End With
                End If
            End With
            
        End Sub

        実行すると、ログイン時も未ログイン時もうまく動作してくれることを確認できるはずです。

        まとめ

        以上、エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法をお伝えしました。

        今回のLogInメソッドは、対象となるサイトが異なれば、都度それに合わせてカスタマイズが必要ですね。

        ただ、一度作っておくと標準モジュールが非常にスッキリすると思います。

        次回は、読み込み待ち処理で、引数で渡した任意の秒数を待つように変更してみたいと思います。

        エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する
        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。今回は、エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する方法を紹介します。

        どうぞお楽しみに!

        連載目次:エクセルVBAでIEを操作するクラスを作る

        エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。
        1. エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
        2. エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
        3. エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
        4. エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
        5. エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
        6. エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法
        7. エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する
        8. エクセルVBAでIEを操作するクラスに検索入力&ボタンクリックのメソッドを追加する方法
        9. エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法
        10. エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する

        エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する

        $
        0
        0
        wait

        photo credit: eeems via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。

        前回の記事はこちら。

        エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法
        エクセルVBAでIEスクレイピングをするときに便利なクラスの作り方をお伝えしております。今回は、エクセルVBAでIEを操作するクラスに、ログイン処理をするメソッドを追加する方法をお伝えします。

        ログインが必要なサイトをスクレイピングする際の、ログイン処理をメソッド化する方法をお伝えしました。

        さて、しばらくお世話になってきた、読み込み待ち用のWaitメソッドですが、意図的に待ち時間を増やしたいときありますよね。

        今回は、その点をパワーアップしていきますよ。

        エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する方法です。

        では、行ってみましょう!

        前回のおさらい

        では、前回のおさらいからです。

        IEを操作するクラスIEObjectのコードはこちらです。

        Public IE As InternetExplorer
        Public Document As HTMLDocument
        
        Private Sub Class_Initialize()
            Set IE = New InternetExplorer
            IE.Visible = True
        End Sub
        
        Private Sub Class_Terminate()
            IE.Quit
        End Sub
        
        Public Sub Navigate(ByVal url As String)
            IE.Navigate url
            Wait
            Set Document = IE.Document
        End Sub
        
        Public Sub Wait()
            Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop   
        End Sub
        
        Sub LogIn()
            
            Const LOGIN_URL As String = "https://example.com/wp-admin/" 'ログインURL
            
            With Me
                .Navigate LOGIN_URL
                    
                With .Document
                    .getElementById("user_login").Value = "XXXXXX" 'ユーザー名を指定
                    .getElementById("user_pass").Value = "XXXXXXXX" 'パスワードを指定
                    .getElementById("wp-submit").Click
                End With
            End With
            
        End Sub

        前回はLogInメソッドを作りました。

        そのおかげで、ログインしているかどうかといった判定もするにも関わらず標準モジュールがとてもスッキリします。

        そんな、検証用の標準モジュールのプロシージャはこちらでした。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            ieObj.LogIn
            
            Stop
            
        End Sub

        Waitメソッドに指定の秒数の待ち時間を入れたい

        さて、先ほど紹介したコードにIEObjectクラスのWaitメソッドというものがあります。

        これは、IEが読み込み待ち完了まで待つためのメソッドです。

        URLを踏んでサーバーから新たなWebページを読み込むときなどは、このメソッドによる読み込み待ちで十分なのです。

        ただ、ブラウザ上でJavaScriptが動作するようなときには、それが最後まで実行されない間に、マクロが次の処理を実行しに行ってしまうようなケースがあります。

        そのようなときに、意図的に何秒かの待ちをプラスして入れたいというときがあるんです。

        指定秒数だけマクロの動作を停止する

        指定の日時までマクロの実行を停止する

        この目的を達成するときに活躍するのが、ApplicationメソッドのWaitメソッドです。

        これは、指定の日時までマクロの実行を停止するというものです。

        Application.Wait 日時

        今から指定の秒数後を求める

        Waitメソッドで指定する日時を「今から指定の秒数後」にしたいわけですね。

        例えば、こうします。

        Application.Wait Now + TimeSerial(0, 0, sec)

        現在日時を取得するNow関数に加えて、時、分、秒から時刻を生成するTimeSerial関数を使います。

        Now
        TimeSerial(時, 分, 秒)

        TimeSerial関数の「秒」を秒数secを加算した時間まで停止するとするのです。

        待ち時間を加えたWaitメソッド

        では、IEObjectクラスのWaitメソッドを修正していきましょう。

        Public Sub Wait(ByVal sec As Long)
            Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop
            
            Application.Wait Now + TimeSerial(0, 0, sec)
        End Sub

        これで、WaitメソッドではIEの読み込み待ちをした上で、引数で受け取った秒数sec分だけ意図的に停止します。

        では、以下の検証用のプロシージャを実行して確認してみましょう。

        Sub MySub()
            
            Dim ieObj As IEObject: Set ieObj = New IEObject
            With ieObj
                .Navigate "https://tonari-it.com"
                .Wait 5
            End With
                
        End Sub

        しかし、実行すると以下のようにコンパイルエラーになってしまいます。

        コンパイルエラー:引数は省略できません

        IEObjectクラスのNavigateメソッドでも、Waitメソッドを使っていたんでした…。

        そして、そこで引数を与えていなかったのでエラーになっちゃいました。

        引数を省略可能にする

        ここで、引数を0などとしても良いのですが、せっかくなのでもう少し使い勝手をよくしましょう。

        Waitメソッドの引数を省略可能にするのです。

        Subプロシージャを宣言する、Subステートメントで以下のように指定をすることで、引数の省略と省略時のデフォルト値の指定が可能です。

        Sub プロシージャ名(Optional パラメータ As 型 = デフォルト値)
         ’処理
        End Sub

        ということで、Waitメソッドを以下のように変更します。

        Public Sub Wait(Optional ByVal sec As Long = 0)
            Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE
                DoEvents
            Loop
            
            Application.Wait Now + TimeSerial(0, 0, sec)
        End Sub

        これで先ほどの検証用プロシージャを実行します。

        本ブログのトップページが読み込まれた後、しばらくする(5秒後)とIEが閉じるのが確認できるはずです。

        まとめ

        以上、エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する方法をお伝えしました。

        読み込み待ちをするWaitメソッドは、本記事のように省略可能な待ち秒数を受け取れるようにしておくと、汎用的に便利に使えますね。

        また、IEクラスのグッドな追加機能があれば紹介していきますね。

        どうぞお楽しみに!

        連載目次:エクセルVBAでIEを操作するクラスを作る

        エクセルVBAでInternetExplorerを操作してWebスクレイピング、まだまだ現役で必要となる現場もあるでしょう。このシリーズでは、IEを使ったスクレイピングをするときに便利なクラスの作り方をお伝えします。
        1. エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
        2. エクセルVBAでIEを操作するクラスでWebページを開くメソッドを追加する
        3. エクセルVBAでIEを操作するクラスに読み込み待ちとドキュメント取得の機能を追加する方法
        4. エクセルVBAでIEを操作するクラスにname属性で取得した要素から内容を取り出すプロパティを作成
        5. エクセルVBAでIEを操作するクラスにリンクテキストでa要素を探してリンクする方法
        6. エクセルVBAでIEを操作するクラスにテーブルのデータを取得するメソッドを追加する方法
        7. エクセルVBAでIEを操作するクラスにWebページのテーブルデータをシートに書き出すメソッドを追加する
        8. エクセルVBAでIEを操作するクラスに検索入力&ボタンクリックのメソッドを追加する方法
        9. エクセルVBAでIEを操作するクラスにログイン処理をするメソッドを追加する方法
        10. エクセルVBAによるIEを操作するクラスに指定秒数の待ち時間を入れるメソッドを追加する

        メールを2ステップでクリップできる!「Evernote for Gmail」のインストールとその使い方

        $
        0
        0

        evernote-for-gmail

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        ちょっと久々ですが、Evernoteネタです。

        このたびGmailアドオン「Evernote for Gmail」がリリースされました!

        Gmailのメッセージを爆速でEvernoteにクリップできるという…素晴らしい!!

        この記事では、「Evernote for Gmail」のインストールと使い方について、そしてそのメリットについて紹介します。

        では、行ってみましょう!

        「Evernote for Gmail」とは

        Evernoteは、直接ノートを作るのはもちろん、画像やファイル、Webページなどをガンガンクリップして「外部クラウドノート」として非常に活躍してくれています。

        ただ、「メール」のクリップに関してはちょっと不満だったんですね。

        できないこともなかったのですが、クリップ用の専用のメールアドレスに転送をするという、ちょっとマニアックな方法でした。

        転送という手順を踏むのも若干手間ですし、Gmailにはスレッドが増えちゃうし、細かいところでいうと、Evernoteにクリップしたノートのタイトルが「Fwd: ~」ではじまるタイトルになっちゃうし…

        そんな悩みを全て一挙に解決してくれるのが、Gmailアドオン「Evernote for Gmail」

        1. アドオンのアイコンクリックから呼び出し
        2. (必要に応じてメモや設定して)「保存」

        この2ステップだけでクリップ完了

        Gmailにスレッドも増えないし、タイトルもメッセージのタイトルがそのまま入ります。

        「Evernote for Gmail」をインストールする方法

        では、早速Gmailアドオン「Evernote for Gmail」をインストールしていきましょう。

        「Evernote for Gmail」アドオンをインストール

        まず、以下「Evernote for Gmail」アドオンの公式ページのURLにアクセスします。

        ページが開いたら「アドオンを入手」をクリックします。

        「Evernote for Gmail」ページで「アドオンを入手」

        すると「G Suite Marketplace」というページの「Evernote for Gmail」ページに遷移します。

        このタイミングでGoogleアカウントにログインする必要があり、そのアカウントのGmailアドオンとしてインストールされますからね。

        ログインしていれば「インストール」をクリックできると思います。

        Evernote for Gmailアドオンをインストール

        ちなみに、G Suiteアカウントの場合はコチラ。「ドメインインストール」と「個別インストール」を選択できました。

        G Suiteアカウントの場合のEvernote for Gmailアドオンインストール
        G Suiteのアカウントでも基本的な流れは一緒ですので、以降は無料Googleアカウントをベースにインストールの方法をお伝えしていきますね。

        アカウントの認証

        続いて、Evernote for GmailがGmailアカウントにアクセスしてよいかの認証を進めていきます。

        インストールをクリックすると、「インストールの準備」というダイアログが表示されますので「続行」をクリックします。

        インストールの準備を続行する

        次に、「Googleにログイン」のウィンドウが開きますので、アドオンをインストールするアカウントを選択します。

        アドオンをインストールするアカウントを選択

        「Evernote for Gmail」が、選択したGoogleアカウントにアクセスしてよいかどうかの許可を求められますので、各スコープを確認して「許可」をクリック。

        Googleアカウントへのアクセスを許可する

        これで、「Evernote for Gmail」アドオンのインストールは完了です。「完了」をクリックします。

        Evernote for Gmailのインストール完了

        GmailからEvernoteにクリップする

        Evernoteアカウントにログインして承認する

        続いてブラウザでGmailを開いてみると、サイドパネルに「Evernote」のマークが…!

        早速クリックしてみましょ!

        Evernote for Gmailのアイコンをクリック

        初回はサイドバー「Evernote」に「START NOW」ボタンが表示されますので、クリックします。

        ここから、今度は「Evernote for Gmail」がEvernoteにアクセスするための承認を進めていきます。

        START NOWをクリック

        (ちなみに、私はChatworkデスクトップアプリを使っているのですが、このクリックした後の画面が出ないようですので、この手順はブラウザ版Gmailで進めてくださいね。)

        すると別ウィンドウで「Evernote」のログインを求められます。

        メールアドレスとパスワードを入力して「ログイン」です。

        EvernoteのアカウントにGoogleアカウントを使っている場合は「Googleで続行」でもOKと思います。

        Evernoteにログイン

        今度は、今ログインしたEvernoteアカウントに対して、「Evernote for Gmail」がアクセスしてよいかの承認を求められますので、内容を確認して「承認する」をクリックします。

        Evernoteアカウントへのアクセスを承認する

        これで、Evernoteアカウント側の承認も完了です。

        メッセージをEvernoteにクリップする

        では、Gmailでメッセージをクリップしてみましょう。

        任意のメッセージで、サイドパネルの象さんアイコンをクリックします。

        認証が完了していますので、今度は「保存場所」「タグ」「コメントの追加」について編集ができます。

        必要な設定と入力を終えて、「保存」でEvernoteにメッセージをクリップできます。

        GmailからEvernoteへメッセージをクリップする

        上記の画像では保存場所を変更していますが、編集せずに「既定のノートブック」でもOKです。ていうか、私はそうしています。

        また、タグも使っていませんので、コメントも不要であれば、そのまま「保存」クリックするだけです。

        Evernoteにメッセージをクリップした

        Evernoteを確認すると、以下のようにちゃんと先ほどのメッセージがノートとしてクリップされています。

        GmailからクリップされたEvernoteのノート

        メッセージの件名がノートタイトルになっています。もちろん「Fwd:」はつかない…個人的にはこれがけっこうありがたい。

        あと、コメントはノートの上部に水平線の前に入りますね。

        iPhoneアプリ版Gmailからクリップする

        PCはこれで快適になりましたが、スマホのGmailアプリもよく使いますよね…!

        スマホからは今まで通り転送かな~…と思いきや、Gmailアプリでメッセージを開いた画面の一番下部、「利用可能なアドオン」に象さんマークが…!

        さっそくタップして使ってみます。

        iPhone版GmailからEvernote for Gmailを呼び出す

        クリップの仕方はPC版とほぼ一緒。

        「保存場所」「タグ」の編集とコメントの入力を(必要であれば)行って、「保存」をタップです。

        iPhone版Gmailからメッセージを保存

        これだけ!

        「メールが正常に保存されました」と表示されます。

        iPhone版GmailでEvernoteへのクリップが完了

        Evernoteを開いてみるとバッチリ保存されています!

        iPhone版Gmailアプリからクリップされたノート

        スマホからでも簡単クリップですね…!

        まとめ

        以上、Gmailアドオン「Evernote for Gmail」のインストールとその使い方についてお伝えしました。

        • Gmailから2ステップで簡単クリップ
        • 転送によるスレッドが増えない
        • 件名がノートタイトルに

        などなど、今までちょっと困っていたメールのクリップのかゆいところを全部解消してくれた感じですね。ものすごいありがたい…!

        GmailをはじめG Suiteにはこのような便利なアドオンが出てくる可能性があるので、しっかりウォッチしておかないとですね。

        また、便利なアドオンがあれば紹介していきたいと思います。

        どうぞお楽しみに!

        エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る

        $
        0
        0
        timer

        photo credit: Curtis Gregory Perry Push To Set via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAで便利なクラスを作るのにハマっておりまして、ここしばらくIEを操作するクラスを作っていたんですね。

        以下の記事から10記事くらいに渡ってお伝えしています。

        エクセルVBAでIEを操作するもっとも簡単なクラスを作成する方法
        エクセルVBAでInternetExplorerを操作してWebスクレイピング…けっこういつも同じ処理を作ります。そんなときには、クラスで部品化が有効です。まずは、IEを操作するもっとも簡単なクラスを作成します。

        今回は、ちょっと別の機能として、実行時間を測定するタイマーをクラスで作ってみようと思います。

        実行時間を測定するの…よくやりますもんね。

        ということで、今回はエクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしていきます。

        では、行ってみましょう!

        課題とするプログラム

        課題とするプログラム、高速化するためのアプローチは以下の記事でも紹介しているものです。

        遅い…重い…そんなエクセルVBAプログラムの処理速度を劇的に改善する方法
        エクセルVBAの実行速度が遅い・重いって時ありませんか?そんな時にエクセルVBAのプログラムの処理速度を速くするテクニックを紹介します。プログラムの実行時間を測定する方法も合わせてお伝えします。

        これを、クラス化して使い回しをしやすくしよう!というものです。

        そのコードを以下に再掲しますね。

        Sub MySub()
                              
            Dim start As Date: start = Time
            
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
            
            With Application
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
            
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                
            With Application
                .Calculation = xlCalculationAutomatic
                .EnableEvents = True
                .ScreenUpdating = True
            End With
                
            Dim finish As Date: finish = Time
            MsgBox "実行時間は " & Format(finish - start, "nn分ss秒") & " でした", vbInformation + vbOKOnly
            
        End Sub

        クラスTimerObjectの作成とパブリック変数

        では、ちょぴっとずつ作っていきましょう。

        まず、クラスモジュールを追加して、その名称をTimerObjectとしましょう。

        それで、実行時間を測定するためにスタートとフィニッシュの日時が必要なので、それらをDate型のパブリック変数として宣言してあげます。

        Public Start As Date
        Public Finish As Date

        まずは持つべきデータから定義してあげると、クラスは作りやすいですよね。

        いい感じです。

        すると、標準モジュールはこうなりますかね。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            timerObj.Start = Time
            
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
            
            With Application
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
            
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                
            With Application
                .Calculation = xlCalculationAutomatic
                .EnableEvents = True
                .ScreenUpdating = True
            End With
                    
            timerObj.Finish = Time
            MsgBox "実行時間は " & Format(timerObj.Finish - timerObj.Start, "nn分ss秒") & " でした", vbInformation + vbOKOnly
            
        End Sub

        むしろ若干コードが増えちゃいましたね。

        クラスなのでインスタンス化が必要ですので、3行目はそのインスタンス化と、オブジェクト変数へのセットを行っています。

        コンストラクタでスタート時間をセットする

        クラスを使用するメリットの一つは、コンストラクタですね。

        インスタンス化と同時にデータを投入するなどの処理を行えます。

        今回は、スタート時間を取得する処理を、以下のようなコンストラクタに入れてあげます。

        Private Sub Class_Initialize()
            Start = Time
        End Sub

        これで、前述の標準モジュールの4行目はそっくりカットできますね。

        実行時間をダイアログで表示するメソッド

        続いて、フィニッシュ時間を取得して、実行時間をダイアログで表示する処理をReportTimerメソッドとして作成しました。

        Public Sub ReportTimer()
            Finish = Time
            MsgBox "実行時間は " & Format(Finish - Start, "nn分ss秒") & " でした", vbInformation + vbOKOnly
        End Sub

        これで、標準モジュールの31行目と32行目は

        timerObj.ReportTimer

        という1行にまとめることができます。

        動作確認とまとめのコード

        まとめのコードはこちらです。

        まずは、TimerObjectクラスのコードです。

        Public Start As Date
        Public Finish As Date
        
        Private Sub Class_Initialize()
            Start = Time
        End Sub
        
        Public Sub ReportTimer()
            Finish = Time
            MsgBox "実行時間は " & Format(Finish - Start, "nn分ss秒") & " でした", vbInformation + vbOKOnly
        End Sub

        標準モジュールはこちらです。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
            
            With Application
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
            
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                
            With Application
                .Calculation = xlCalculationAutomatic
                .EnableEvents = True
                .ScreenUpdating = True
            End With
                    
            timerObj.ReportTimer
            
        End Sub

        まあ、少し…はスッキリしましたかね。

        実行すると、以下のように実行時間が表示されます。

        マクロの実行時間をダイアログで表示する

        まとめ

        以上、エクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしました。

        標準モジュールのコード量を大きく減らすことにはなっていないのですが、タイマーに関する変数と処理をTimerObjectクラスに渡すことができたので、気持ち的にはかなりスッキリしたのではないでしょうか。

        あと、マクロによってはタイマーをいくつもセットしたいときがあるかも知れませんが、クラスにしておけばインスタンスをその分生成すればいいですもんね。

        さて、次回ですがせっかくなので高速化する処理もクラス化していきたいと思います。

        どうぞお楽しみに!

        【Outlook VBA】NewMailExイベントで受信したメールの内容をエクセルシートに書き出す方法

        $
        0
        0

        outlook,vba,newmailex,エクセル書き出し

        皆様こんにちは、ノグチです。

        前回の記事では、OutlookのNewMailExイベントを使って、受信したメールが条件にマッチするものだったらメッセージを表示する方法をご紹介しました。

        今回は、同じくこのNewMailExイベントで、受信したメールが条件にマッチするものだったら、メールの内容をエクセルシートに書き出す方法をご紹介していきます。

        前回のおさらい

        まずはOutlookのNewMailExイベントのおさらいをしましょう。

        前回のコードはこちらでした。

        Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
        Dim myItem As Outlook.Items
        Dim objId As Object
        
        Set myNamespace = GetNamespace("MAPI")
        Set objId = myNamespace.GetItemFromID(EntryIDCollection)
        
        If InStr(objId.Subject, "日報") Then
            MsgBox "日報が届きました!"
        End If
        
        End Sub

        メールのタイトルに『日報』という文字が含まれていたら、メールを受信したタイミングでメッセージを表示するというものでした。

        イベント時に指定の処理をさせたい場合は、イベントプロシージャ内に処理を記述するのでしたね。

        今回は、このメッセージ表示部分の処理を、メールの情報をエクセルシートに書き出す、という動作に置き換えていきますよ。

        対象のメールフォーマットとエクセルシート

        今回は、こちらのメールを対象にしてみましょう。

        outlook,newmailex,メールフォーマット

        このメールの件名から年月日を、本文から作業時間と作業内容を取得して、こちらのエクセルシートに書き出していきます。

        対象メールを受信したら内容をエクセルに書き出すコード

        Outlookからエクセルを操作するための準備

        Outlookからエクセルを操作するためにはまず、

        • 参照設定
        • コード内でエクセルのApplicationオブジェクト取得

        が必要です。

        これについては下記記事で紹介していますので、ご覧ください。

        【エクセルVBA】エクセルVBAでOutlookを操作しよう!参照設定とOutlookアプリケーションオブジェクトの取得
        エクセルVBAでOutlookのメール送信やタスク作成操作をする前準備として、VBEの参照設定や、Outlookアプリケーションオブジェクトの取得方法をご紹介しています。 VBAとOutlookを組み合わせて使うことで、既に便利に使えているメーラーを更に便利にできるかもしれませんよ。

        参照設定はしていなくてもOutlookからエクセルを操作することはできます。

        しかしコードが長くなってしまうのと、参照設定をしたほうがコードの記述が楽、ということもあって、設定しておくのがオススメです。

        では、エクセルのApplicationオブジェクトを取得し、書き出したいエクセルのファイルパスを指定しましょう。

        上のコードに上記を書き足すと、こんな感じになります。

        Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
        Dim objId As Object
        
        Set myNamespace = GetNamespace("MAPI")
        Set objId = myNamespace.GetItemFromID(EntryIDCollection)
        
        If InStr(objId.Subject, "日報") Then
            Dim strFile As String
            Dim objExcel As Excel.Application 
        
            strFile = "C:\Users\Desktop\日報リスト.xlsx"
        
            Set objExcel = New Excel.Application    ’エクセルのApplicationオブジェクトを取得
            Set wb = objExcel.Workbooks.Open(strFile)
            Set ws = wb.Worksheets("Sheet1")
        
        End If
        End Sub

        NewMailExイベントは、対象にしたいメール以外を受信した時にも実行されます。

        対象外のメールを受信した場合にはExcelオブジェクトを読込ませる必要は無いので、Excel関連の宣言やオブジェクト取得のコードはIF文の中に入れてしまっています。

        受信したメールから情報を取得してエクセルシートに書き出す

        メールの件名は、MailItemオブジェクトのSubjectプロパティで、メールの本文はBodyプロパティで取得することができます。

        受信したメールのMailItemオブジェクトを取得する方法は、前回の記事でご紹介しました。

        メール本文から欲しい情報を取り出す方法は、こちらの記事でご紹介しています。

        【Outlook VBA】メール本文から欲しい情報だけを取り出す方法
        MailItemオブジェクトのBodyプロパティとMid関数を使って、Outlookのメール本文から欲しい情報だけを取り出す方法をご紹介しています。メールで勤務時間を管理しているあなた!この方法なら、日々のチェックが楽になるかも?

        これらを上のコードに加えると、こんな感じになります。

        Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
        Dim myNameSpace As NameSpace
        Dim objId As Object
        
        Set myNameSpace = GetNamespace("MAPI")
        Set objId = myNameSpace.GetItemFromID(EntryIDCollection)
        
        If InStr(objId.Subject, "日報") Then
            Dim strFile As String
            Dim objExcel As Excel.Application
                
            strFile = "C:\Users\ryoku\Desktop\日報リスト.xlsx"
        
            Set objExcel = New Excel.Application
            Set wb = objExcel.Workbooks.Open(strFile)
            Set ws = wb.Worksheets("Sheet1")
        
            With objId
        
                Dim lngLen As Long
                Dim lngLen2 As Long
                Dim lngLen3 As Long
                Dim lngLen4 As Long
                
                '作業日
                i = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1
                ws.Cells(i, 1).Value = Mid(objId.Subject, Len("【日報】") + 1, Len(objId.Subject) - Len("【日報】"))
                
                '作業時間
                lngLen = InStr(objId.Body, "【作業時間】") + Len("【作業時間】")
                lngLen2 = InStr(objId.Body, vbCrLf)
                
                ws.Cells(i, 2).Value = Mid(objId.Body, lngLen, lngLen2 - lngLen)
                
                '作業内容
                lngLen3 = InStr(objId.Body, "【作業内容】") + Len("【作業内容】")
                
                ws.Cells(i, 3).Value = Right(objId.Body, Len(objId.Body) - lngLen3)
            End With
        
        wb.save
        wb.Close
        objExcel.Quit
        
        End If
        End Sub

        対象メールを受信したら、メールの件名と本文から欲しい情報を取得し、「日報リスト.xlsx」というファイルを開いて、最下行に取得したメールの内容を書き出していく、というコードです。

        そして、対象としたいメールを受信すると…

        この通り、エクセルにメールの情報が転記されていますね。

        QuitメソッドでApplication終了を忘れずに!

        上のコードの下から3行目、QuitメソッドでエクセルのApplicationオブジェクトを終了させていますね。

        Closeメソッドでブックを閉じているから、エクセルは終了できているのでは?と思ってしまいますが、QuitメソッドでApplicationオブジェクトを終了させないと、メモリ上にエクセルが残り続けてしまいます

        そうすると、このエクセルが編集中のままになってしまい、次に上のコードでエクセルに書き込むことができなくなってしまうのです。

        取得したApplicationオブジェクトは、コード内で不要になったら必ずQuitする癖をつけたいですね。

        イベントを使わない方法も考えてみる

        ここまで、メールを受信したら、都度エクセルに書き出す方法をご紹介しました。

        しかし対象になるメールが多い場合は、このNewMainEXイベントを使わない方法も検討した方がいいかもしれません

        例えば、就業時間になると部下から一斉に日報メールが届く…というような場合です。

        上の方法では、メールを受信する度にエクセルを開いたり閉じたりすることになるので、Outlookの処理速度を遅く感じる、などの影響が出てしまう可能性があります。

        エクセルに書き出したいメールが同じタイミングで大量に来ることがわかっているのであれば、Outlookの自動仕分機能を使って一旦サブフォルダに集めてから、指定したサブフォルダ内のメールをエクセルに一気に書き出す、という方法の方がスマートかもしれません。

        最後に

        今回は、NewMailExイベントを使って、メールを受信する都度メールの内容を指定のエクセルシートに書き出す方法をご紹介しました。

        メールの内容を控えておかないといけなかったり、月末などのタイミングで日々送られるメールの内容と突合しないといけない、といった場合には、このようにメールを受信したタイミングでエクセルに書き出してしまえばよいですね。

        それでは、最後までお読みいただき有難うございました!

        連載目次:Outlook VBAでメールを操作してみよう

        メーラーとして名高く、そして便利なOutlook。

        Outlookのメールだって、VBAで操作することができますよ。本シリーズでは、Outlookのメールを、VBAで操作する方法をご紹介していきます。

        1. 【Outlook VBA】メールの送信時イベントで確認ダイアログを表示する方法
        2. 【Outlook VBA】UnReadItemCountプロパティで受信フォルダの未読メール件数を取得する方法
        3. 【Outlook VBA】メール本文から欲しい情報だけを取り出す方法
        4. 【Outlook VBA】Application_NewMailExイベントでメール受信時にメッセージを表示する方法

        【QUERY関数】group by句とmax・min関数で列の最大値・最小値を求める

        $
        0
        0

        QUERY関数12アイキャッチ

        みなさんこんにちは!
        もり(@moripro3)です。

        GoogleスプレッドシートQUERY関数の使い方をシリーズでお届けしています!

        前回の記事では、group by句とavg関数を使用して、列の値の平均値を算出する方法を紹介しました。

        【QUERY関数】group by句とavg関数で列の値の平均値を求める
        GoogleスプレッドシートのQUERY関数を紹介するシリーズ。第十一回目は、group by句とavg関数で項目毎の値の平均値を求める方法です。format句で書式設定をして小数点以下の桁数を処理する方法も紹介しています。

        QUERY関数の第2引数[クエリ]には5種類の集計関数が使用でき、シリーズ直近3回の記事でcount関数, sum関数, avg関数を紹介しました。

        この記事では残りの2つ、max関数min関数を紹介します。

        関数名 説明
        count() 列の要素数を返す
        sum() 列の値の合計値を返す
        avg() 列の値の平均値を返す
        max() 列の最大値を返す
        min() 列の最小値を返す

        それでは備品購入リストのサンプルを用いて、見ていきましょう!

        query12-1

        列の最大値を求めるmax関数

        max関数は、指定列の最大値を求める関数です。

        max(列)

        まずは最も簡単な使い方です。D列「単価」の最大値を求めます。

        =query(A:E,"select max(D)",1)

        query12-8

        「単価」の列で最も大きい値20000を取得できました。

        列の最小値を求めるmin関数

        min関数は、指定列の最小値を求める関数です。

        min(列)

        D列「単価」の最小値を求めます。200が取得できます。

        =query(A:E,"select min(D)",1)

        query12-2

        最大値・最小値を合わせて求める

        max関数とmin関数をカンマ区切りで指定すると、1行でまとめて2つの値を取得できます。

        =query(A:E,"select min(D),max(D)",1)

        query12-3

        すべてのデータ型に使用できる

        max関数とmin関数は、数値以外にも、日付・文字列などすべてのデータ型に使用できます。

        • 日付 → 日付の小さい(早い)順に比較
        • 文字列 → アルファベット順に比較(大文字と小文字は区別される)

        日付データであるA列「購入日」を指定すると、下記の通り日付を取得できます。

        • min関数(最小値) = 最も早い 4月27日
        • max関数(最大値) = 最も遅い 5月6日

        =query(A:E,"select min(A),max(A)",1)

        query12-4

        where句で抽出条件を指定する

        QUERY関数の5種類の集計関数は、where句と併せて使うことができます。

        たとえば、リストの中から「5月1日以降に購入した備品」の最小単価と最大単価を求めてみます。select句のあとに、where句で日付条件を指定します。

        =query(A:E,"select min(D),max(D) where A >= date '2019-05-01'",1)

        query12-5

        5月1日以降に購入した備品の「最小単価 200」と「最大単価 5000」を取得できました。

        where句での日付の指定方法は少し特殊なので、こちらの記事で紹介しています。

        【QUERY関数】where句で日付データを条件にして行を抽出する
        GoogleスプレッドシートのQUERY関数を紹介するシリーズ。第五回目は、where句の条件に日付を指定する方法です。今日期限のタスク一覧・今月期限のタスク一覧の抽出方法を紹介しています。

        他にも、where句を使用して「OA機器の最小単価と最大単価を求める」なんてこともできますね。色々組み合わせて使ってみてください。

        項目ごとの最大値と最小値を求める

        group by句を使用して、購入者ごとの最大値・最小値を求めることも可能です。group by句の使用方法は、他の集計関数(count, sum, avg)と同じです。

        select句とgroup by句で同じ列を指定します。ここではE列の購入者です。

        =query(A:E,"select E,min(D),max(D) group by E",1)

        query12-6

        E列「購入者」ごとの最小単価と最大単価を取得できました。

        QUERY関数の第1引数に列全体を指定しているため、空白行も集計されているので、空白行は除外しましょう。

        where 列 is not null

        where句を使用して、null(空白)でない行(なんらかのデータが存在する行)のみを集計対象にすればOKです。

        =query(A:E,"select E,min(D),max(D) where D is not null group by E",1)

        query12-7

        まとめ

        今回の記事では、max関数, min関数, group by句を紹介しました。

        • max関数で列の最大値を取得する
        • min関数で列の最小値を取得する
        • group by句で項目ごとの最大値と最小値を取得する

        max関数 と min関数 は、数値だけでなく、日付・文字列データも比較できる点がポイントです。

        さて次回は、group by句を徹底解説します。これまで、「区分ごとの集計」「購入者ごとの集計」など、1つの列のみの集計方法を紹介してきましたが、group by句は、複数列の集計もできるんですよ!

        どうぞお楽しみに!

        連載目次:GoogleスプレッドシートQUERY関数をマスターしよう

        スプレッドシートのQUERY関数を使って、データ抽出・集計を効率化する方法を紹介しています。

        1. スプレッドシートのQUERY関数を使う最初の一歩!クエリを理解する
        2. QUERY関数の基本!別シートのデータからselect句で列を取得する方法
        3. 【QUERY関数】where句と比較演算子を使って単一条件に一致した行を抽出する
        4. 【QUERY関数】where句とlike演算子を使用して指定の文字を含む行を抽出する
        5. 【QUERY関数】where句で日付データを条件にして行を抽出する
        6. 【QUERY関数】where句で時刻データを条件にして行を抽出する
        7. 【QUERY関数】where句でand,orを使用して複数条件を指定する
        8. 【QUERY関数】order by句で抽出結果を昇順・降順ソートする
        9. 【QUERY関数】group by句とcount関数で列のデータ数をカウントする
        10. 【QUERY関数】group by句とsum関数で列の値の合計値を求める
        11. 【QUERY関数】group by句とavg関数で列の値の平均値を求める

        【Outlook VBA】今開いているメールからワンクリックで予定登録画面を開く方法

        $
        0
        0

        メールから予定登録,eyecatch

        皆様こんにちは、ノグチです。

        メールでやり取りをしていて、メールの内容を予定に登録したいこと、ありますよね。

        ランチのお誘いだったり、ミーティングの日程だったり、書類の提出期限だったり。

        メール画面からワンクリックで予定登録の画面を開けたら便利なのになあ…

        ついでに、メールの内容を予定に貼り付けておいてくれたら助かるのに…

        それ、VBAを使えばできちゃいますよ。

        ということで今回は、ワンクリックで今開いているメールの内容を転記した予定登録画面を開く方法をご紹介します。

        メールの内容を予定登録画面に転記する

        では早速、以下の3ステップでメールの内容を予定登録画面に転記するコードを書いていきましょう。

        1. 今開いているメールのMailItemオブジェクトを取得する
        2. AppointItemオブジェクトを取得する
        3. AppointItemオブジェクトのプロパティにメールの値をセット

        どれも今までの記事でご紹介した方法でできちゃいますよ。

        1.今開いていメールのMailItemオブジェクトを取得する

        まずは、今開いているメールのMailItemオブジェクトを取得しましょう。

        今開いているメールのMailItemオブジェクトは、ApplicationオブジェクトのActiveInspectorメソッドでInspectorオブジェクトを取得して、更にInspectorオブジェクトのCurrentItemプロパティで取得できるのでしたね。

        【Outlook VBA】今開いているOutlookウインドウを操作しよう!Inspectorオブジェクトの取得
        Outlook vbaで、メールの添付ファイルをワンクリックで指定フォルダに保存する方法を複数回記事にわたってご紹介していきます。今回は、ActiveInspectionメソッドで、今開いているOutlookウインドウのInspectorオブジェクトを取得する方法をご紹介しています。

        ここまでをコードにしてみると、こんな感じになります。

        Dim objItem As Object
        Dim objIns As Inspector
        
        Set objIns = Application.ActiveInspector
        Set objItem = objIns.CurrentItem   '今開いているメールオブジェクトを取得

        2.予定のAppointItemオブジェクトを取得する

        今開いているメールのMailItemオブジェクトが取得できたら、お次は予定のアイテムオブジェクトを取得しましょう。

        予定は、AppointItemオブジェクトで操作するということは、以前こちらの記事でご紹介しました。

        【はじめてのOutlook VBA】Outlookの予定を登録する方法
        Outlook VBAでコーディングするためのVBEの準備と、VBAで予定を登録する方法をご紹介しています。1件の予定登録の手間は大したことがなくても、複数登録する必要が出てくると面倒臭い...本稿では複数の予定をOutlookにまとめて登録するための第一歩として、単体の予定をVBAで登録する方法をご紹介します。

        このAppointItemオブジェクトを取得するために、ApplicationオブジェクトのCreateItemメソッドを使い、引数にAppointItemオブジェクトの定数olAppointmentItemをセットします。

        こんな風に。

        Dim objApItem As Outlook.AppointmentItem
        
        Set objApItem = Application.CreateItem(olAppointmentItem)
        これで、AppointItemオブジェクトが取得できました。

        3.メールの内容をAppointItemオブジェクトのプロパティにセット

        AppointItemオブジェクトが取得できたら、次はメールから取得した情報を、予定の内容にセットしていきます。

        今回は予定の件名と本文に、今開いているメールの件名と本文をそれぞれセットすることにしましょう。

        AppointItemオブジェクトのSubjectプロパティとBodyプロパティに、MailItemオブジェクトのSubjectプロパティとBodyプロパティで取得した値をセットします。

        MailItemオブジェクトのプロパティについては下記記事をご覧くださいね。

        【エクセルVBA】Outlookでメールを作成・送信する方法
        エクセルシートに記入された件名や本文を、エクセルVBAによってOutlookのメールの件名と本文にセットしてメール送信する方法をご紹介しています。VBAでメールの送信ができれば、宛先に応じてメールの本文を変えつつ一斉に送信することもできますよ。

        そして、それぞれプロパティをセットした状態で予定登録画面を開きたいので、プロパティセットの後にDisplayメソッドを加えておきます。

        こんな感じ。

        With objApItem
            .Subject = objItem.Subject
            .Body = objItem.Body
            .Display
        End With
        これで、予定登録画面を開きつつ、メールの情報を予定にセットできました。

        今開いているメールの内容を予定の画面に転記するコード

        上のコードをまとめると、こんなコードになります。
        Sub Add_AppointItem()
        
        Dim objItem As Object
        Dim objIns As Inspector
        Dim objApItem As Outlook.AppointmentItem
        
        Set objIns = Application.ActiveInspector
        Set objItem = objIns.CurrentItem   '今開いているメールオブジェクトを取得
        Set objApItem = Application.CreateItem(olAppointmentItem)
        
        With objApItem
            .Subject = objItem.Subject
            .Body = objItem.Body
            .Display
        End With
        
        End Sub

        今開いているメールの件名と本文を予定の件名と本文にセットして、Displayメソッドで予定登録画面を表示する、というコードです。

        ではメールをメールを開きつつ、実行してみましょう。

        こちらのメールを開いて…

        メール,予定登録

        マクロを実行してみると…

        予定

        この通り、開いているメールの内容が、予定登録画面に転記されていますね。

        あとは予定の内容を編集して、保存ボタンを押せば、予定登録完了です。

        登録画面を表示しないで予定を登録しておきたい場合は、上のコードのDisplayメソッドの部分を、Saveメソッドに書き換えればOK。

        VBAのプロシージャをメニューに追加する

        メールの内容を予定登録画面に転記する方法をご紹介しましたが、マクロの起動方法も大切ですよね。

        折角予定登録はマクロがやってくれたとしても、マクロの起動を「メニューから開発タブを開いて、マクロからプロシージャを選んで…」と複数ステップを踏んでいては、手間が減っているようには思えません。

        折角なので、プロシージャをメニューにセットして、ワンクリックで起動できるようにしてしまいましょう。

        まず、メールのメニューバーからファイル>オプションを開きます。

        (Outlookのオプションではなく、メール画面からのオプションなので注意です。)

        オプション画面の『リボンのユーザー設定』を選択して、右側の下部にある「新しいタブ」ボタンで新しいタブを追加しておきます。

        次に左側のリストから「マクロ」を選択します。

        すると、今あるプロシージャ名がリストで表示されますので、メニューバーに表示しておきたいプロシージャを選択して、画面中央にある「追加」ボタンで、先ほど追加した新しいタブに加えておきます。

        メール,オプション

        後はOKを押してオブション画面を閉じれば…

        メール,メニュー,プロシージャセット

        このように、メールのメニューにプロシージャがセットできました。

        あとは、開いたメール画面でこのプロシージャをクリックすれば、マクロが実行されます。

        もちろん、この記事以外でご紹介しているコードも、この方法でメニューにセットしておくことができますよ。

        但し、イベントプロシージャはメニューにセットすることができません。

        イベントプロシージャは対象となるイベントが起こったときに自動的に実行されますので、そもそもセットしておく必要もありませんからね。

        最後に

        今回は、ワンクリックで今開いているメールの内容を転記した予定登録画面を開く方法をご紹介しました。

        記事の中ではメールから予定に転記したのは件名と本文だけでしたが、本文から日付や場所を取り出すことができれば、更に予定登録が楽になりますね。

        それでは、最後までお読みいただきありがとうございました!

        連載目次:Outlook VBAでメールを操作してみよう

        メーラーとして名高く、そして便利なOutlook。

        Outlookのメールだって、VBAで操作することができますよ。本シリーズでは、Outlookのメールを、VBAで操作する方法をご紹介していきます。

        1. 【Outlook VBA】メールの送信時イベントで確認ダイアログを表示する方法
        2. 【Outlook VBA】UnReadItemCountプロパティで受信フォルダの未読メール件数を取得する方法
        3. 【Outlook VBA】メール本文から欲しい情報だけを取り出す方法
        4. 【Outlook VBA】Application_NewMailExイベントでメール受信時にメッセージを表示する方法

        エクセルVBAの実行速度を高速化するための処理をクラス化する方法

        $
        0
        0
        booster

        photo credit: LimpingFrog Productions Expanding our Personal Space via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        前回は以下の記事で実行時間を測定するためのクラスを作成しました。

        エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        エクセルVBAでは使い回しをするような機能をクラス化しておくと便利ですよね。今回は、使用頻度が高い機能ということで、エクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしていきます。

        使い回しもできますし、便利ですよね。

        そういえば、前回お題となっていたプロシージャの中に「高速化」をするためのルーチンがありましたよね。

        これも、「使い回し」できちゃったほうが便利なのでは…?

        ということで、今回はエクセルVBAの実行速度を高速化するための処理をクラス化する方法をお伝えしますよ。

        では、行ってみましょう!

        課題とするプログラム

        では、課題とするプログラムから確認していきましょう。

        前回、標準モジュールに作成したプロシージャで、こちらになります。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
            
            With Application
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
            
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                
            With Application
                .Calculation = xlCalculationAutomatic
                .EnableEvents = True
                .ScreenUpdating = True
            End With
                    
            timerObj.ReportTimer
            
        End Sub

        TimerObjというのが、実行時間を測定する用のクラスですね。

        インスタンスを生成した時点から測定を開始して、ReportTimerを実行した時点までの実行時間をMsgBox関数で表示してくれます。

        今回は、上記の以下の部分をクラス化していきます。

        1. 8~12行目の高速化に関するApplicationクラスの各プロパティの設定をする処理
        2. 24~28行目の高速化に関するApplicationクラスの各プロパティの設定を戻す処理

        各プロパティの機能については以下の記事をご参考くださいね。

        遅い…重い…そんなエクセルVBAプログラムの処理速度を劇的に改善する方法
        エクセルVBAの実行速度が遅い・重いって時ありませんか?そんな時にエクセルVBAのプログラムの処理速度を速くするテクニックを紹介します。プログラムの実行時間を測定する方法も合わせてお伝えします。

        ちなみに、白状しておきますと、今回の内容はthomさんの以下の記事をたいへん参考にさせていただいております。

        クラスをはじめ、VBAについてとても深くてためになる記事を、たくさん提供いただいていますので、この記事以外にもぜひご覧いただければと思います。

        クラスPerformanceBoosterの作成とパブリック変数

        では、作っていきます。

        まずクラスモジュールを挿入して、名称をPerformanceBoosterとします。

        持つべきデータを定義しておきたいですが、今回は実行前のCalculationプロパティの値を保存しておくための、initCalculationValue_というプライベート変数だけ用意しておきましょう。

        Private initCalculationValue_ As XlCalculation

        Calculationプロパティの値は、列挙型XlCalculationのメンバーになりますので、それを型に設定してあげてます。

        その他のプロパティも初期値を保存しておかなくて良いのか?って話なのですが、他のプロパティはFalseのまま使用することはあんまりないかな~ということで割愛してます。

        コンストラクタで各プロパティを設定する

        クラスPerformanceBoosterですが、使用するにはインスタンスを生成する必要があります。

        コンストラクタを使えば、生成したと同時に、Calculationプロパティの初期値を保存すること、また各プロパティを高速モードに設定することができますね。

        以下のように作成してあげます。

        Private Sub Class_Initialize()
        
            With Application
                initCalculationValue_ = .Calculation
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
        
        End Sub

        いい感じです。

        デストラクタでプロパティを元に戻す

        前回作成したタイマークラスの場合は、欲しいタイミングでレポートしたかったので、それ用のメソッドを作りました。

        ただ、今回の場合は、設定を戻すのはいつでも良いので、プロシージャの実行終了時、クラスPerformanceBoosterが破棄されるときに実行してあげれば良いかも…

        そうです、デストラクタですね。

        Private Sub Class_Terminate()
        
            With Application
                .Calculation = initCalculationValue_
                .EnableEvents = True
                .ScreenUpdating = True
            End With
        
        End Sub

        設定を戻すだけなので、中身は簡単です。

        動作確認とまとめのコード

        まとめのコードは掲載しておきますね。

        まずは、クラスPerformanceBoosterのコードです。

        Private initCalculationValue_ As XlCalculation
        
        Private Sub Class_Initialize()
        
            With Application
                initCalculationValue_ = .Calculation
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
        
        End Sub
        
        Private Sub Class_Terminate()
        
            With Application
                .Calculation = initCalculationValue_
                .EnableEvents = True
                .ScreenUpdating = True
            End With
        
        End Sub

        続いて、お待ちかねの標準モジュール。

        以下の通り、タイマーと高速化の部分は、2つのインスタンスの生成と、タイマーのReportTimerメソッドのたったの3行にまとめることができています。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            Dim booster As PerformanceBooster: Set booster = New PerformanceBooster
               
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
                    
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                            
            timerObj.ReportTimer
            
        End Sub

        超すっきりですね。

        実行すると、以前と同様5秒という記録を叩きました。問題なさそうですね。

        エクセルVBAで実行時間を高速化した結果

        まとめ

        以上、エクセルVBAの実行速度を高速化するための処理をクラス化する方法をお伝えしました。

        クラスモジュール化しておけば、使い回しが便利ですもんね。

        ぜひご活用くださいませ。

        また、便利なクラスがあれば紹介したいと思います。

        どうぞお楽しみに!

        連載目次:エクセルVBAのタイマー&高速化クラスとアドインを作る

        エクセルVBAで実行時間を測定するタイマークラス、また処理速度を高速化するブースタークラスを作成し、それを使い回ししやすいようにアドイン化する方法をお伝えします。
        1. エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        2. エクセルVBAの実行速度を高速化するための処理をクラス化する方法

        【QUERY関数】group by句で複数の列をグループ化して集計する

        $
        0
        0

        QUERY関数13アイキャッチ

        こんにちは!もり(@moripro3)です。

        GoogleスプレッドシートQUERY関数の使い方をシリーズでお届けしています!

        前回の記事では、group by句とmax,min関数を使用して、列の最大値と最小値を算出する方法を紹介しました。

        【QUERY関数】group by句とmax・min関数で列の最大値・最小値を求める
        GoogleスプレッドシートのQUERY関数を紹介するシリーズ。第十二回目は、group by句とmax関数, min関数で列の最大値・最小値を求める方法です。数値データだけでなく、日付・文字列データの比較も可能です。

        直近数回の記事で、列の値をグループ化して集計するためのgroup by句を使ってきました。

        • (例)列xをグループ化し、項目ごとの「合計値」を求める

        これまでの記事で紹介してきたのは、1つの列のみをグループ化する使い方でしたが、実務で大量のデータを扱う場合、複数の列をキーにして集計することがありますよね。

        そこで今回は、group by句で複数の列をグループ化して集計する方法を紹介します。

        それではみていきましょう!

        (前回までのおさらい)列をグループ化するgroup by句

        group by句とは、複数行にわたる値を集計するための句です。

        group by句で指定する列は、このようにselect句で指定されているか、

        select 列 group by 列

        もしくは、select句で、集計関数によって集計されている必要があります。

        select 集計関数(列) group by 列

        前回までのおさらいもかねて、40人の生徒表をサンプルに使用して、列の項目ごとの人数を集計してみます。
        query13-1

        1つの列でグループ化する

        group by句を使用して、列ごとの人数をカウントしてみましょう。

        • 性別ごとの人数
        • 血液型ごとの人数

        まずは性別ごとの人数を求めてみます。B列「性別」でグループ化して人数をカウントする記述です。

        =query(A:C,"select B,count(B) where B is not null group by B",1)

        query13-2-2

         

        つぎに、血液型ごとの人数を求めます。C列「血液型」でグループ化して人数をカウントする記述です。

        =query(A:C,"select C,count(C) where C is not null group by C",1)

        query13-3

         

        このように、1つの列のみをグループ化する記述の場合、「性別」または「血液型」のいずれかしか求めることができません。

        group by句で2つの列を指定することで、「性別・血液型別の人数」を集計することが可能です。次の項で、グループ化の考え方とクエリの記述方法を紹介します。

        group by句で複数列をグループ化する

        group by句は、複数の列をグループ化して集計することが可能です。select句とgroup by句それぞれに、カンマ区切りで列を列挙します。

        select 列1,列2,列3 … group by 列1,列2,列3 …

        さきほどの40人の生徒表を使用して「性別・血液型別」の人数を集計してみます。まずは、40人の生徒を図でイメージしましょう。性別は、男性=青・女性=ピンクで、血液型は記載のとおりです。

        query13-4

        グループ化の順序は自由に指定することが可能です。この40人を、2通りの方法で集計してみます。

        • パターン1.性別 → 血液型
        • パターン2.血液型 → 性別

        パターン1.性別→血液型でグループ化

        まずは、「性別 → 血液型」ごとに人数を集計するパターンです。select句で1~3の順番で指定、group by句で1,2の順番で指定します。

        1. B列(性別)
        2. C列(血液型)
        3. C列(血液型)をcount関数で集計

        ※select句で指定する列の順番(B,C)と、group by句で指定する列の順番(B,C)は一致させます。

        =query(A:C,"select B,C,count(C) where C is not null group by B,C",1)

        query13-5

        【考え方】
        下記の2ステップで、40人の生徒を分割しています。

        1. 「性別」でグループ化する(男, 女)
        2. 1のグループを、さらに「血液型」でグループ化する(AB, A, B, O)

        query13-11

        パターン2.血液型→性別でグループ化

        つぎに、「血液型 → 性別」ごとに人数を集計するパターンです。select句で1~3の順番で指定、group by句で1,2の順番で指定します。

        1. C列(血液型)
        2. B列(性別)
        3. B列(性別)をcount関数で集計

        ※select句で指定する列の順番(C,B)と、group by句で指定する列の順番(C,B)は一致させます。

        =query(A:C,"select C,B,count(B) where B is not null group by C,B",1)

        query13-7

        【考え方】
        下記の2ステップで、40人の生徒を分割しています。

        1. 「血液型」でグループ化する(AB, A, B, O)
        2. 1のグループを、さらに「性別」でグループ化する(男・女)

        query13-12

        グループ化する順序の指定

        2つの集計パターンを紹介しました。

        • 性別 → 血液型
        • 血液型 → 性別

        グループ化の順序が異なっても、集計結果は同じになります。それでは、どのようにグループ化の順序を指定すればよいか迷いますね。

        オススメは、大カテゴリ → 小カテゴリと、項目数の少ない列を優先してグループ化する方法です。

        • 「性別」は2種類(男, 女) ← 大カテゴリ
        • 「血液型」は4種類(AB, A, B, O) ← 小カテゴリ

        40人の生徒表の場合、性別の方が種類が少ないので、性別 → 血液型の順序が良いでしょう。

        ただ、必ずしもという訳ではないので、業務要件や、集計目的に応じて、列の優先順位を考えてみてください。

        まとめ

        今回の記事では、group by句で複数の列をグループ化して集計する方法を紹介しました。

        スプレッドシートのQUERY関数は、SQLをベースにした難易度の高い関数です。その分、ひとつの関数で、行の抽出・ソート・セルの書式設定・グループ集計などが一気にできる強みがあります。

        QUERY関数で自由自在にデータ集計ができるようになれば、事務職としての戦闘力はトップレベル、一目置かれること間違いなし!

        シリーズ全体を通して、「クエリとは何か?」から、一つずつ積み上げてきました。
        QUERY関数を一から勉強したい!QUERY関数を使うメリットは?そもそも「クエリ」って何?など、基礎から学びたい方は、ぜひシリーズ初回の記事からご覧ください。

        または、下記の連載目次から、必要な記事のみを復習してみてくださいね!

        連載目次:GoogleスプレッドシートQUERY関数をマスターしよう

        スプレッドシートのQUERY関数を使って、データ抽出・集計を効率化する方法を紹介しています。

        1. スプレッドシートのQUERY関数を使う最初の一歩!クエリを理解する
        2. QUERY関数の基本!別シートのデータからselect句で列を取得する方法
        3. 【QUERY関数】where句と比較演算子を使って単一条件に一致した行を抽出する
        4. 【QUERY関数】where句とlike演算子を使用して指定の文字を含む行を抽出する
        5. 【QUERY関数】where句で日付データを条件にして行を抽出する
        6. 【QUERY関数】where句で時刻データを条件にして行を抽出する
        7. 【QUERY関数】where句でand,orを使用して複数条件を指定する
        8. 【QUERY関数】order by句で抽出結果を昇順・降順ソートする
        9. 【QUERY関数】group by句とcount関数で列のデータ数をカウントする
        10. 【QUERY関数】group by句とsum関数で列の値の合計値を求める
        11. 【QUERY関数】group by句とavg関数で列の値の平均値を求める
        12. 【QUERY関数】group by句とmax・min関数で列の最大値・最小値を求める
        13. 【QUERY関数】group by句で複数の列をグループ化して集計する

        便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法

        $
        0
        0
        add

        photo credit: mikecogh Blank Equation via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAで実行時間を測定するクラスや、処理を高速化するクラスを作成しております。

        エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        エクセルVBAでは使い回しをするような機能をクラス化しておくと便利ですよね。今回は、使用頻度が高い機能ということで、エクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしていきます。
        エクセルVBAの実行速度を高速化するための処理をクラス化する方法
        作成したプロシージャの中に「高速化」をするためのルーチンを入れることがよくありますが、「使い回し」できちゃったほうが便利ですよね。今回は、エクセルVBAの実行速度を高速化するための処理をクラス化する方法です。

        それで、これらのクラスはあちこちで使い回ししたいですよね…

        都度、クラスモジュールをコピーしたりしてもいいのですが、「アドイン」という機能を使うと、参照設定のみで使えるようになります。

        ということで、今回は便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法です。

        では、行ってみましょう!

        前回のおさらい

        では、前回までのおさらいからです。

        まずは、標準モジュールから…こちらです。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            Dim booster As PerformanceBooster: Set booster = New PerformanceBooster
               
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
                    
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                            
            timerObj.ReportTimer
            
        End Sub

        処理自体にはあまり意味がないのですが、実行時間がかさみそうな処理です。

        TimerObjectクラスはインスタンスの生成時から、ReportTimerメソッドまでの実行時間を測定して、メッセージ表示するものです。

        エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        エクセルVBAでは使い回しをするような機能をクラス化しておくと便利ですよね。今回は、使用頻度が高い機能ということで、エクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしていきます。

        PerformanceBoosterクラスは、Applicationクラスのいくつかのプロパティを変更して、高速化するものです。

        インスタンス生成時にプロパティをセットして、インスタンスの破棄時にプロパティを元に戻します。

        エクセルVBAの実行速度を高速化するための処理をクラス化する方法
        作成したプロシージャの中に「高速化」をするためのルーチンを入れることがよくありますが、「使い回し」できちゃったほうが便利ですよね。今回は、エクセルVBAの実行速度を高速化するための処理をクラス化する方法です。

        今回は、この二つのクラスをアドインとして利用できるようにしていきます。

        アドインとは

        アドインというのは、拡張子xlam形式のブックのことで、非表示でブックを開くことができるものです。

        よく、VBEの「ツール」メニュー「参照設定」からライブラリを追加しますよね。

        実は他のxlsm形式のブックのマクロも、そこから参照設定して使用することができるわけですが、xlsm形式だと、もう一丁Excelブックが立ち上がっちゃってちょっと邪魔なんですね。

        そこで非表示のアドインです。

        アドインは非表示なので、邪魔にならないように参照設定できます。

        ですが、アドインもExcelブックの一種なので、通常のマクロと同じように開発できる…つまり、自作ライブラリを作る感じですね。

        それで、今回はアドインに自作クラスを記述したマクロを用意しておいて、それを参照設定して、他のブックからクラスを使えるようにしちゃおうということです。

        マクロブックをアドインブックとして保存

        では、進めていきましょう。

        まず、これまで作ってきたクラスモジュールと標準モジュールを含むブックをアドインとして保存します。

        エクセルの「ファイル」メニューの「名前をつけて保存」から、「Excelアドイン(*.xlam)」を選択して保存します。

        Excelマクロブックをアドインとして保存

        それで、保存する形式を「Excelアドイン(*.xlam)」にすると、自動的に保存するフォルダが

        C:\Users\ユーザー名\AppData\Roaming\Microsoft\AddIns

        というようなフォルダになります。

        このフォルダはアドインを保存する専用のフォルダで、ユーザーアドインフォルダといいます。

        Excelのユーザーアドインフォルダ

        これでアドインとしての保存はOK。

        アドインの設定とマクロの編集

        プロジェクト名の変更

        こうして保存したアドインですが、いくつか設定やマクロの編集が必要です。

        まず、プロジェクト名を変更します。

        というのも、参照元のプロジェクトと、参照先のこのアドインのプロジェクトで同じ名前だとうまくいかないのです。

        なので、こちらのアドインのほうのプロジェクト名を変更します。

        まず、VBEの「ツール」メニューから「VBAProjectのプロパティ」を選択します。

        VBAProjectのプロパティを開く

        「プロジェクトプロパティ」というダイアログが開きますので、「プロジェクト名」を入力して、「OK」をクリックします。

        プロジェクト名を変更

        プロジェクトエクスプローラーを確認すると、プロジェクト名が変更されていることを確認できます。

        プロジェクトエクスプローラーでプロジェクト名を確認

        クラスモジュールをPublicNotCreatableにする

        続いて、クラスモジュールにもちょっと設定が必要です。

        プロジェクトエクスプローラーでクラスモジュールを選択しているときの、プロパティウィンドウを見てください。

        クラスモジュールには「Instancing」という唯一のプロパティがあるのですが、その設定が「1 – Private」となっているはずです。

        なんとなく意味がわかると思いますが、「インスタンスはプライベートでしか使えない」という設定になっているんですね。

        なので、これを「2- PublicNotCreatable」とします。

        クラスモジュールのプロパティを「2- PublicNotCreatable」に変更

        つまり、これで他のプロジェクトからも「インスタンスがパブリックでも使える」状態になったわけです。

        これを、TimerObjectクラスと、PerformanceBoosterクラスと両方で設定しておきます。

        インスタンス生成用のFunctionプロシージャを作る

        …ただし、Instancingプロパティの値「NotCreatable」とありますね。

        つまり、他のプロジェクトからはインスタンスを作成できないっつーわけですね。

        なので、アドインの標準モジュールに、インスタンスを生成して返すFunctionプロシージャを作っておいてあげます。

        それらのFunctionプロシージャをパブリックにしておけば、それは他のプロジェクトから呼び出せます。

        そして、そのFunctionプロシージャはアドインの中、つまり同じプロジェクト内にありますから、インスタンスは生成できるよということです。

        Public Function CreateTimer()
        
            Dim t As TimerObject: Set t = New TimerObject
            Set CreateTimer = t
        
        End Function
        
        Public Function CreateBooster()
        
            Dim b As PerformanceBooster: Set b = New PerformanceBooster
            Set CreateBooster = b
        
        End Function

        これで保存すれば、アドイン側の準備はOKです。

        ちょっと長くなりそうなので、続きは次回!

        まとめ

        以上、便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法をお伝えしました。

        あとは、このアドインを参照設定して、他のプロジェクトから使用できるようにすればよいですね。

        それについては、次回お伝えしていきます。

        どうぞお楽しみに!

        エクセルVBAで自作アドインの便利クラスを活用する方法

        $
        0
        0
        reference

        photo credit: Melinda * Young The Old Books via photopin (license)

        みなさん、こんにちは!
        タカハシ(@ntakahashi0505)です。

        エクセルVBAで実行時間を測定するクラス、処理の高速化をするクラスを作っておりました。

        前回は、以下の記事でそれらのクラスをアドイン化して便利に使いまわそう!という内容でお送りしました。

        便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法
        便利なクラスはあちこちで使い回ししたいですよね。「アドイン」という機能を使うと、参照設定のみで使えるようになります。今回は便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法をお伝えします。

        アドインファイルを作るところまでお伝えしたのですが、まだそれを活用する方法をお伝えできていなかったので、本記事はその続編となります。

        ということで、エクセルVBAで自作アドインの便利クラスを活用する方法です。

        では、行ってみましょう!

        前回のおさらい

        まずは、お題となる標準モジュールのプロシージャからご覧ください。

        こちらです。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = New TimerObject
            Dim booster As PerformanceBooster: Set booster = New PerformanceBooster
               
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
                    
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                            
            timerObj.ReportTimer
            
        End Sub

        処理自体はあまり意味がありませんが、2つの便利なクラスの使用例となっています。

        まず、実行速度を測定するTimerObjectクラス。

        Public Start As Date
        Public Finish As Date
        
        Private Sub Class_Initialize()
            Start = Time
        End Sub
        
        Public Sub ReportTimer()
            Finish = Time
            MsgBox "実行時間は " & Format(Finish - Start, "nn分ss秒") & " でした", vbInformation + vbOKOnly
        End Sub

        エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        エクセルVBAでは使い回しをするような機能をクラス化しておくと便利ですよね。今回は、使用頻度が高い機能ということで、エクセルVBAで実行時間を測定するのに便利なタイマークラスの作り方をお伝えしていきます。

        そして、処理の高速化を行うPerformanceBoosterクラスです。

        Private initCalculationValue_ As XlCalculation
        
        Private Sub Class_Initialize()
        
            With Application
                initCalculationValue_ = .Calculation
                .Calculation = xlCalculationManual
                .EnableEvents = False
                .ScreenUpdating = False
            End With
        
        End Sub
        
        Private Sub Class_Terminate()
        
            With Application
                .Calculation = initCalculationValue_
                .EnableEvents = True
                .ScreenUpdating = True
            End With
        
        End Sub

        エクセルVBAの実行速度を高速化するための処理をクラス化する方法
        作成したプロシージャの中に「高速化」をするためのルーチンを入れることがよくありますが、「使い回し」できちゃったほうが便利ですよね。今回は、エクセルVBAの実行速度を高速化するための処理をクラス化する方法です。

        この2つのクラス…あちこちで使い回しそうなので、アドイン化して使い回しをしやすくしよう!というのが前回からの内容です。

        アドインブックの作成や設定などは、前回の以下記事をご覧くださいね。

        便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法
        便利なクラスはあちこちで使い回ししたいですよね。「アドイン」という機能を使うと、参照設定のみで使えるようになります。今回は便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法をお伝えします。

        そして、そのアドインブックにインスタンス生成用のパブリックなFunctionプロシージャを作成する必要がありまして、それはコチラです。

        Public Function CreateTimer()
        
            Dim t As TimerObject: Set t = New TimerObject
            Set CreateTimer = t
        
        End Function
        
        Public Function CreateBooster()
        
            Dim b As PerformanceBooster: Set b = New PerformanceBooster
            Set CreateBooster = b
        
        End Function

        …と、ここまでがおさらいです(長)。

        今回はこの作成したアドインを活用していく方法を見ていきましょう。

        アドインを他のプロジェクトから活用する

        では、元のブック「実行速度.xlsm」からアドインを活用できるようにしていきましょう。

        クラスモジュールを開放する

        まず、「実行速度.xlsm」には、まだ以下のクラスモジュールが存在しています。

        • TimerObject
        • PerformanceBooster

        これら、2つのクラスモジュールは、アドインブックに移設しました。

        後ほど参照設定して使えるようになりますので、このブックには存在している必要がありません。

        プロジェクトエクスプローラー上で右クリックして「解放」してあげましょう。

        クラスモジュールを開放する

        アドインを参照設定する

        続いて、アドインブックを参照設定していきます。

        参照設定の手順は、実はライブラリの参照設定と同じです。

        まず、VBEの「ツール」メニューの「参照設定」を選択します。

        VBEから参照設定を開く

        続いて、以下のように進めますよ。

        1. 参照設定ダイアログで「参照」ボタンをクリック
        2. ファイルの参照ダイアログでユーザーアドインフォルダを選択
        3. ファイル形式を「Microsoft Excel Files」を選択
        4. 作成したアドインブックを選択
        5. 「開く」ボタンをクリック

        アドインブックの参照設定
        おさらいですが、ユーザーアドインフォルダは以下のようなパスでしたね。

        C:\Users\ユーザー名\AppData\Roaming\Microsoft\AddIns

        すると、以下のように参照設定ダイアログには「Performance」にチェックが入りますね。

        また、プロジェクトエクスプローラーでも「Performance(実行速度.xlam)」の存在が確認(非表示ではありながらもアドインブックが開いている)でき、かつVBAProjectからの参照先として設定されていることがわかります。

        アドインブックの参照設定を確認する

        アドインのクラスを活用する

        では、コードをアドインを活用するものに変更していきましょう。

        他のプロジェクトのクラスは「PublicNotCreatable」ですから、Newキーワードでインスタンスを生成できませんでした。

        なので、インスタンス生成用のFunctionプロシージャCreateTimerおよびCreateBoosterを使ってあげるんでしたね。

        それらに修正したコードがこちらです。

        Sub MySub()
                              
            Dim timerObj As TimerObject: Set timerObj = CreateTimer
            Dim booster As PerformanceBooster: Set booster = CreateBooster
               
            Sheet1.Cells.Clear
            Sheet2.Cells.Clear
                    
            With Sheet1
                Dim i As Long
                For i = 1 To 300
                    .Cells(i, 1).Value = i
                    .Cells(i, 2).FormulaLocal = "=SUM(A1:A" & i & ")"
                    .Rows(i).Copy
                    Sheet2.Cells(i, 1).PasteSpecial
                Next i
            End With
                            
            timerObj.ReportTimer
            
        End Sub

        3,4行目をちょっと変更するだけでいけますね。

        では、実行して動作確認をしてみましょう。

        アドインのクラスを用いる動作確認

        無事に動作し、変わらず5秒という記録を叩き出しましたね。

        まとめ

        以上、エクセルVBAで自作アドインの便利クラスを活用する方法をお伝えしました。

        ちょっと手順はいりますが、いつも使うクラスがあれば今回紹介した2つのクラスに限らずアドインブックに入れておくと良さそうですね。

        どうぞご活用ください!

        連載目次:エクセルVBAのタイマー&高速化クラスとアドインを作る

        エクセルVBAで実行時間を測定するタイマークラス、また処理速度を高速化するブースタークラスを作成し、それを使い回ししやすいようにアドイン化する方法をお伝えします。
        1. エクセルVBAで実行時間を手軽に測定するTimerObjectクラスを作る
        2. エクセルVBAの実行速度を高速化するための処理をクラス化する方法
        3. 便利なクラスを使い回す!エクセルVBAで自作クラスをアドイン化する方法
        Viewing all 2074 articles
        Browse latest View live


        <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>