学習めも。

Python、Anaconda学習中🔰 ブログ引っ越ししました😄よろしくお願いします!https://noeiganolife.com/

記録用🔰

プログラミング以外の記事はこちら

Selenium IDEでブラウザ操作を記録!

参考文献

無料のChrome拡張機能でマクロの記録と同じようなことができる!

ブラウザ操作を記録して、Pythonのコードに書き起こす事ができる。
※プログラミングの参考として有効!

Selenium IDEインストール

Chrome ウェブストアからインストール

ブラウザ操作を記録

①まずは起動する(下図のように拡張機能をクリックして起動) ②「Record a new test in a new project」をクリック ③プロジェクト名をつけてOKをクリックすると、「起点にするWebページURL」を入力する画面が表示されるので、URLを入れて、Start Recordingをクリックして記録を開始する ④記録中であることが表す表示が右下に出るので、この状態で記録したい操作をする ⑤操作を終えたら、別ウィンドウで開いているSeleniumIDEの画面の録画中止ボタンをクリックして録画終了。すると、テスト名を入力する画面が表示されるので、適当な名前を入れてOKをクリック ⑥入力した操作がテストとして登録された。この状態で再生ボタンを押すと、記録した操作を再生でき、また、保存ボタンで記録した操作を保存できる Pythonにコードを書き出す Exportすると、コードへの書き出しができる

RPAとの違い

この2つは自動化できる対象の範囲が異なる
RPAはカーソルの位置やボタンの画像に対して入力やクリックを記録するため、ブラウザに限らずどのようなソフトの操作でも記録可能。
SeleniumはWebページの中身を解読して、その中の要素に対して入力やクリックを記録。そのためブラウザ上の操作しか記録できないが、Webページなら中身を解読しているので、自在に情報を取り出せる。また、オープンソースである。

ブラウザの拡張機能って無料で色々できたりしてほんと便利!
これは活用していきたい!

ということで、今回はブラウザ操作の記録について書きました

次は・・・

次は実際のWebページから情報を読み取り、Excelに書き込みを行うまでを学びます

yoji.hateblo.jp

投稿がお役に立てたら、★ポチッとお願いします😁

Seleniumのインストール⇨アナコンダ導入!

参考文献

self-development.info (ドライバーの配置) 上記のサイトを使い、Selenium、ドライバーをインストールして、起動確認したら、エラー!

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
 
CHROMEDRIVER = "driver/chromedriver"
 
# ドライバー指定でChromeブラウザを開く
browser = webdriver.Chrome(CHROMEDRIVER)
 
# Googleアクセス
browser.get('https://www.google.com/')
 
# 検索ボックスを特定
elem = browser.find_element(By.NAME, 'q')
# 「Selenium」と入力して、「Enter」を押す
elem.send_keys('Selenium' + Keys.RETURN)
 
# ブラウザを閉じる
#browser.quit()

以下のサイトを参考に、トラブルシューティングを試みる

https://teshi-learn.com/2021-08/mac%E3%81%ABchormedriver%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%EF%BC%88chromedriver%E3%81%AF%E3%80%81%E9%96%8B%E7%99%BA%E5%85%83%E3%81%8C%E6%9C%AA%E7%A2%BA%E8%AA%8D%E3%81%AE/

▼結果 ナヌ!?ドライバーが間違っているって?そんなはずは・・・
正確にはドライバーのバージョンが間違い得ていたみたい
ちゃんとChromeのバージョンを調べてからインストールしたつもりが😅😅
とりあえず、指示通りにドライバーを入れ直す

また、Macがドライバーを開けないようなので、環境設定でセキュリティ許可をしてから、再度プログラム実行

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
 
CHROMEDRIVER = "driver/chromedriver 2"
 
# ドライバー指定でChromeブラウザを開く
browser = webdriver.Chrome(CHROMEDRIVER)
 
# Googleアクセス
browser.get('https://www.google.com/')
 
# 検索ボックスを特定
elem = browser.find_element(By.NAME, 'q')
# 「Selenium」と入力して、「Enter」を押す
elem.send_keys('Selenium' + Keys.RETURN)
 
# ブラウザを閉じる
#browser.quit()

できたーーー!😂😂
バージョン間違えるという、初歩的なミスでした😅

Webページを表示する

▼ブラウザの基本操作

コード 機能
driver.get(WebページのURL) Webページを開く
driver.beck() 履歴を1つ戻る
driver.forward() 履歴を1つ進む
driver.refresh() ページを更新する
driver.quit() ブラウザを閉じる

▼現在のページ情報の取得

コード 機能
driver.current_url URLを取得
driver.title タイトルを取得

(練習)
Google, yahoo, pythonの3つのWebページを順に開いて移動して、それから履歴を1つずつ遡って、最後にGoogleに戻るプログラムを作成する
※それぞれのページ遷移に遷移したら、現在のページのタイトルとURLをprint()で表示。それぞれのページ遷移の間には、time.sleep(2)により2秒間待機する (web_browser_navigate.py)

from selenium import webdriver
import time
# chromedriver.exeがある場所
driver_path = "driver/chromedriver"
# WebDriverの作成
driver = webdriver.Chrome(executable_path=driver_path)

# www.google.co.jpを開く
driver.get("https://www.google.co.jp")
print(driver.title, driver.current_url)
time.sleep(2)

# www.yahoo.co.jpを開く
driver.get("https://www.yahoo.co.jp")
print(driver.title, driver.current_url)
time.sleep(2)

# www.python.orgを開く
driver.get("https://www.python.org")
print(driver.title, driver.current_url)
time.sleep(2)

# www.yahoo.co.jpに戻る
driver.back()
print(driver.title, driver.current_url)
time.sleep(2)

# www.google.co.jpに戻る
driver.back()
print(driver.title, driver.current_url)
time.sleep(2)

# webdriverの終了(ブラウザを閉じる)
driver.quit()

▼結果
できたー😆😆
ブラウザが切り替わってく様子見ると感動する!動画が載せられたら!ww
以下は出力

テキスト入力、キー入力、クリックを操作する

▼テキスト入力

#テキスト入力
要素.send_keys("テキスト")

#テキストクリア
要素.clear()

▼Enterキーを操作する

from selenium.webdriver.common.keys import Keys

# Enterキーの入力
要素.send_keys(Keys.ENTER)

・テキストの入力後にEnterキーをを入力したい場合は、selenium.webdriver.common.keysからKeysをインポートしておき、Keys .ENTERをsend_keeys()でキー送信する
※他にもKeys .SHIFT、Keys .DELETE、Keys .CONTROLなどの特殊キーを送信できる
▼キーの組み合わせを入力

#テキスト入力+Enterキー
要素.send_keys("テキスト" + Keys.ENTER)

#Shiftキーを押しながらテキスト入力(大文字入力)
要素.send_keys(Keys.SHIFT + "python")

▼ボタンやリンクをクリックする

#クリック
要素.click()

練習

(やりたい事) これらをの機能を組み合わせて実際にプログラミング!
Googleの検索ページで、「札幌の降水確率のグラフ」を表示するまでの動作をする
Googleの検索ボックスに「札幌天気」と入力して検索を行う
②表示された検索結果ページの天気予報のグラフにある「降水確率」ボタンをクリックして、グラフの表示を切り替える

(ポイント)
・Webページから要素を特定するには、driver.find_element()で表示中のWebページから検索する
※検索BOXの要素もこれで取得
・条件に合う要素がすぐに見つからなかった場合の待ち時間を10秒に設定。インターネット上には要素を後から読み込むWebページもあるので、見つからなかった場合の待ち時間を設定
driver.implicitly_wait(10)

(web_browser_search.py)

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

# chromedriverがある場所
driver_path = "driver/chromedriver"

# webdriverの作成
driver = webdriver.Chrome(executable_path=driver_path)

# 要素が見つからない場合は10秒待つように設定
driver.implicitly_wait(10)

# www.google.co.jpを開く
driver.get("https://www.google.co.jp")

# 検索ボックスに「札幌天気」を入力して、Enterキーを押す
driver.find_element(By.NAME, "q").send_keys("札幌天気" + Keys.ENTER)

# [降水確率]のボタンをクリック
driver.find_element(By.ID, "wob_rain").click()

# 5秒待つ
time.sleep(5)

# ブラウザを閉じる
driver.quit()

▼結果
あれ?できない。。。
▼エラーメッセージ(by. jupyter)
Seleniumインストールしたのにおかしいなあ・・・と思ったら、仮想環境が違いました💦
pip3 listで見たら、普通にSeleniumがありませんでした!そりゃできないわな・・・と
ググったら、Jupyterで簡単にカーネル変更できるらしいんだけど、使いたい仮想環境が書かれてないなあ・・・ とりあえず、仮想環境を変更しました
使い始めたアナコンダナビゲーター使用🎶
GUIで使いやすい!
※切り替える前にコマンドCtrl+Cで一回Jupyterを閉じてから切り替えます 仮想環境にインストールされているツールたちを調査(Jupyter使用)
コマンド入れる時は、最初にビックリマーク入れます☝️ あれ?ここにもない・・・なぜ!? 原因はよくわかりませんが、インストールし直しましたww
▼結果 できました🎶 サイトの様式が出版された時と変わってたみたいで、最後までは切り替わらなかったけど、ちゃんと走った!!😆
仮想環境要注意だな

でも、仮想環境の切り替えとか、Jupyterでの仮想環境の環境の調べ方とかを学べたので、収穫あり!

ちなみに、Windowsではエクスプローラーでファイルのクリックをすればすぐに走らせられるらしいんだけど、Macでファイルをクリックしても、フィイルの中身が表示されるだけでしたw

投稿がお役に立てたら、★ポチッとお願いします😁

VSCodeがおかしい!😭😭なので再インストールして、環境構築し直します!

前々からおかしくなっていて、VSCode上でターミナルが使えなかったり、jupyterが使えなくなったり・・・😭😭

初心者なため、色々無理な使い方をしたり、仮想環境を使うためにいじくりまわしたせいかもしれない・・・

ということで、気を取り直して、インストールし直すことにしました!!

時間はかかるかもしれないけれど、大掃除的な気持ちでやります!

拡張機能の入れ直しについても書きます〜

まずは完全にアンインストール(拡張機能や設定上のアレコレをリセット!)

daeudaeu.com ターミナルアプリから下記の3つのコマンドを実行することでアンインストールすることができます。

rm -rf /Applications/Visual\ Studio\ Code.app/
rm -rf ~/Library/Application\ Support/Code
rm -rf ~/.vscode/

大事に育ててきたアレやこれやがこんな簡単に消えますww

次はインストール

初期設定

こちらを参考にしました! biz.hpg.co.jp

なんとか落ち着きました!参考になるサイトがあるから、あっという間に終わった。

使うフォントはまだ迷い中・・・
今まで使っていたやつがいいかな?w

メールを自動送信する(失敗!)

フォルダ構成

(やりたい事) 複数のメールをまとめて送信する

f:id:Moriane:20220414064522p:plain ・メール本文にしようする文章はテキストファイルに保存
・顧客の名前やメールアドレスはExcelファイルから参照
・添付ファイルはフォルダに保存しておく
・該当する顧客にメール送信するプログラムを作成する!!

メール送信工程

①メール送付リストを作成 フォルダーから請求書のPDFファイルを1つ取得する
(PDFファイルごとに繰り返す) 顧客IDをPDFファイル名から把握する
該当する顧客データをファイル「顧客マスタ」から検索
メール送付リストに「顧客データ」と「PDFファイル」を登録
②メールを一斉送信 SMTPサーバーに接続
(メール送付リストの顧客ごとに繰り返す) メッセージを準備
件名、メールアドレスを設定
メール本文を追加
添付ファイルにPDFファイルを追加
メッセージを送信
SMTPサーバーと接続を閉じる

メールを送信するには「メール送付リスト」に登録した顧客を1つずつ取り出して、顧客ごとにメッセージデータを作成する
メッセージデータには、まず件名とメールアドレスを設定し、本文を追加して。請求書のPDFファイルを添付ファイルとして加えて送信する

メール送付リストの作成

次のように[顧客データ、請求書PDFファイルのパス]を要素に持つリストにする
このようにリストを作成すれば、顧客データの中のメールアドレスに、PDFファイルを添付して、メール送信すれば良いので、一斉に送信する処理を作りやすくなる

mailing_list = [
  [[顧客ID, 顧客名,部署名,担当者名,メールアドレス,・・・],
  請求書PDFファイルパス],
  [[顧客ID, 顧客名,部署名,担当者名,メールアドレス,・・・],
  請求書PDFファイルパス],
  ・・・
]

・最初に必要なモジュールを全てインポートしておく

openpyxl Excelファイルの読み込み
Path フォルダ内のファイル検索
smtplib SMTPサーバーと更新する
MIMEMultipart メッセージを作成する
MIMEText 本文を作成する
MIMEApplication 添付ファイルを作成する
sys プログラムを中止する
import sys
import openpyxl
from pathlib import Path
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# 顧客マスタの読み込み
wb_master = openpyxl.load_workbook("顧客マスタ.xlsx")
ws_master = wb_master["Sheet1"]

customer_list = []
for row in ws_master.iter_rows(min_row=2):
    if row[0].value is None:
        break
    value_list = []
    for c in row:
        value_list.append(c.value)
    customer_list.append(value_list)

# 請求書PDFのフォルダー
pdf_dir = "請求書PDF_202007"

# メーリングリスト
mailing_list = []

# フォルダーから請求書のPDFファイルを1つずつ取得する
for invoice in Path(pdf_dir).glob("*.pdf"):
    # 「顧客ID」 は、 PDFファイルの拡張子を除いた部分
    customer_id = invoice.stem
    # 該当する顧客データを「顧客マスタ」から検索
    for customer in customer_list:
        if customer_id == customer[0]:
            # メーリングリストに「顧客データ」と
            # 「PDFファイル」のパスを追加
            mailing_list.append([customer, invoice])
            # 顧客ID、顧客名、メールアドレス、
            # PDFファイルのパスを表示
            print(customer[0], customer[1], customer[4], invoice)

結果

(検索)
⇨PDFファイルが対象なので、glob()の括弧の中には「*.pdf」を指定して、拡張子でファイルを検索

(取得)
⇨取得したPDFを送信する顧客はファイル名が顧客IDとなっている。拡張子を除いた顧客IDの部分はstemで取得できる

(送信リストに追加)
検索した顧客データは送付する請求書のPDFファイルのパスと一緒にメール送信リストに追加。これから送付する顧客とPDFファイルが確認できるようprint()で表示 f:id:Moriane:20220414073651p:plain

メールを一斉に送信

間違えて送信しないようにテストをする
プログラムにテストモードを追加する
変数test_modeがTrieの場合は自分のアドレス宛てに送信するようにする
※テストモードではtest、本番モードではrealと入力してもらうようにするが、本番モードのreal以外が入力された場合はテストモードにする

また、テストモードの切り替えはinput()を用いて、画面から行うようにする
次に送信を開始する前に、どちらのモードが設定されているかを明示して送信しても大丈夫かを確認する
input()を用いて、続行して送信する場合はyes、中止する場合はnoを入力してもらい、入力した値がyes以外の場合は、sys.exit()でプログラムを中止する
プログラムを続行する場合は、メッセージの送信に備えて、メール本文をmail_body.txtから読み込んでおく

# モード選択
print()  # 1行空ける
mode = input("モード選択(テスト=test、本番=real):")
# 本番以外はテスト
if mode != "real":
    test_mode = True
else:
    test_mode = False

# 送信確認
if test_mode:
    result = input("テストモードで自分宛てに送信します(続行=yes、中止=no):")
else:
    result = input("本番モードで送信します(続行=yes、中止=no):")

# 続行以外は中止
if result != "yes":
    print("プログラムを中止します")
    sys.exit()

# メール本文をファイルから読み込んでおく
text = open("mail_body.txt", encoding="utf-8")
body_temp = text.read()
text.close()

▼結果
プログラムを実行すると次のように画面モードを選択できる。
ここでは、送信するかどうかの確認でNoを入力して、プログラムを中止している ・SMTPサーバに接続したら、メール送信リストの顧客への送信を始める。メール送付リストの1件文のデータは[顧客データ, 請求書PDFファイルのパス]のようなリストになっている。
⇨そこでメール送信リストをリープして一つの要素を変数dataに代入してインデックスを用いてdata[0]で顧客データ、data[1]で請求書PDFファイルのパスを取得する
⇨この顧客データから顧客メールアドレスを取得して、件名や自分のアドレスと一緒にメッセージ設定する。
さらに、会社名や担当者名も取得して、メール本文にformat()で埋め込む。
・添付ファイルのデータは請求書PDFファイルのパスにあるPDFファイルからバイナリで読み取る
※ここでヘッダーにふあするファイル名には、パスに.nameをつけて「フォルダーを除いたファイル名」を指定する
・メール本文と添付ファイルの追加が終わったら、メッセージをsend_message()で送信する。
・送信中は進捗がわかるように、print()で送信している顧客IDと会社名を表示
・リストの全ての顧客に送信を完了したら、最後にSMTPサーバーとの接続を閉じる ▼全てのコード(mail_invice_sender.py)

import sys
import openpyxl
from pathlib import Path
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# 顧客マスタの読み込み
wb_master = openpyxl.load_workbook("顧客マスタ.xlsx")
ws_master = wb_master["Sheet1"]

customer_list = []
for row in ws_master.iter_rows(min_row=2):
    if row[0].value is None:
        break
    value_list = []
    for c in row:
        value_list.append(c.value)
    customer_list.append(value_list)

# 請求書PDFのフォルダー
pdf_dir = "請求書PDF_202007"

# メーリングリスト
mailing_list = []

# フォルダーから請求書のPDFファイルを1つずつ取得する
for invoice in Path(pdf_dir).glob("*.pdf"):
    # 「顧客ID」 は、 PDFファイルの拡張子を除いた部分
    customer_id = invoice.stem
    # 該当する顧客データを「顧客マスタ」から検索
    for customer in customer_list:
        if customer_id == customer[0]:
            # メーリングリストに「顧客データ」と
            # 「PDFファイル」のパスを追加
            mailing_list.append([customer, invoice])
            # 顧客ID、顧客名、メールアドレス、
            # PDFファイルのパスを表示
            print(customer[0], customer[1], customer[4], invoice)

# モード選択
print()  # 1行空ける
mode = input("モード選択(テスト=test、本番=real):")
# 本番以外はテスト
if mode != "real":
    test_mode = True
else:
    test_mode = False

# 送信確認
if test_mode:
    result = input("テストモードで自分宛てに送信します(続行=yes、中止=no):")
else:
    result = input("本番モードで送信します(続行=yes、中止=no):")

# 続行以外は中止
if result != "yes":
    print("プログラムを中止します")
    sys.exit()

# メール本文をファイルから読み込んでおく
text = open("mail_body.txt", encoding="utf-8")
body_temp = text.read()
text.close()

my_address = "自分のメールアドレス"

# SMTPサーバー(今回はGmailで送信)
smtp_server = "smtp.gmail.com"
port_number = 587

# ログイン情報(今回はGmailのアカウントを入力する)
account = "自分のメールのアカウント"
password = "自分のメールのパスワード"

# SMTPサーバーに接続
server = smtplib.SMTP(smtp_server, port_number)
server.starttls()
server.login(account, password)

# メーリングリストの顧客に1つずつメール送信
for data in mailing_list:
    customer = data[0]
    pdf_file = data[1]

    # メッセージの準備
    msg = MIMEMultipart()
    # 件名、メールアドレスの設定
    msg["Subject"] = "ご請求書送付のご案内[株式会社エクセルパイソン]"
    msg["From"] = my_address
    if test_mode:
        msg["To"] = my_address
    else:
        msg["To"] = customer[4]

    # メール本文の追加
    body_text = body_temp.format(
        company=customer[1],
        department=customer[2],
        person=customer[3]
    )
    body = MIMEText(body_text)
    msg.attach(body)
    # 添付ファイルの追加
    pdf = open(pdf_file, mode="rb")
    pdf_data = pdf.read()
    pdf.close()
    attach_file = MIMEApplication(pdf_data)
    attach_file.add_header("Content-Disposition", "attachment", filename=pdf_file.name)
    msg.attach(attach_file)

    # メール送信
    print("メール送信:", customer[0], customer[1])
    server.send_message(msg)

# SMTPサーバーとの接続を閉じる
server.quit()

▼結果(失敗!)
なぜ!ここまできて😭
Emailポリシーに引っかかったらしいです💦

解決できなかったので、ここまでにしましょうw f:id:Moriane:20220415073107p:plain

Pythonで自動送信するときに気をつけること

メール送信を自動化するときには「送信ミス」と「迷惑メールに間違われること」に特に気をつけないといけない。
まずはテストモードを実装して、自分のアドレス宛てにテストで送信して、本文と添付ファイルの内容を確認できるようにする
また、本当に一斉送信を開始しても大丈夫か、一時停止して確認するステップも実装する
さらに、送信中は進捗がわかるように、送信している相手をprint()で随時表示し、送信中にミスに気がついた場合は、キー「Ctrl+C」を押すことで強制終了できる。

メールで送るメッセージを作成する

メッセージ作成に必要なモジュールのインポート

以下のモジュールをインポート!
これらのモジュールは標準ライブラリにあるので、インストールの必要はない

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

メッセージの作成

# メッセージの作成方法
msg = MIMEMultipart()
# 件名、メールアドレス
msg["Subject"] = "件名"
msg["From"] = "自分のメールアドレス(送信元)"
msg["To"] = "相手のメールアドレス(送信先)"

# メール本文
body = MIMEText(本文のテキスト)
msg.attach(body)

# 添付ファイル
attach_file = MIMEApprication(PDFファイルから読み込んだデータ)
attach_file.add_header("Content-Disposition","attachment",filename="PDFファイル名")
msg.attach(attach_file)

このように作成したメッセージ(変数msg)をserver.send_message(msg)により送信する
※やり方はこちら yoji.hateblo.jp

送信の控えをとっておく方法

Outlookなどのメールソフトから送信すると「送信済み」フォルダーに追加されるが、Pythonプログラムから創始した場合は控えが残らないため、BCCを送信することで送信の控えにすることができる。
社内共有のアドレスなどに送信すると、お互いにチェックもできるので便利

msg["Bcc"] = "控え用のメールアドレス"

メール本文をファイルから読み込む

メール本文はテキスト保存しておき、そこから読み込んでメールメッセージに追加する
なお、メモ帳やテキストエディタで作成し、文字コードUTF-8で保存したものを使用する。
Windowsは初期設定の文字コードUTF-8に設定されているので、いつも通りテキストを書いて保存するだけでよい
Macの場合は、テキストエディットで「フォーマット」ー「標準テキストにする」を選択するとテキストファイルを作成できる。保存するときは、文字コードを意味する「エンコーディング」をUnicodeUTF-8)にすること

メール本文

(メール本文:mail_body.txt)

{company} {department}
{person} 様

いつも大変お世話になっております。
株式会社エクセルパイソンの田中です。

7月分のご請求書をPDFファイルにて、
本メールに添付させていただきました。
何卒ご査収のほどお願い申し上げます。

ご不明な点等がございましたら、
お問い合わせいただけたら幸いです。

今後とも宜しくお願い申し上げます。

*********************
株式会社エクセルパイソン
営業本部 田中一郎

TEL. 00-0000-0000
FAX. 00-0000-0000
*********************

メール本文のうち、波括弧で囲んだ部分を会社名などに置き換えるには、format()を利用する
まずopen()で開き、read()でファイルの中の全文を読み込む
読み込んだな用をbody_tempで代入したら、ファイルをclose()で閉じる
(read_mail_body.py)

# メール本文をファイルから読み込む
f = open("mail_body.txt", encoding="utf-8")
body_temp = f.read()
f.close()

# メール本文の波かっこの部分を置き換える
body_text = body_temp.format(
    company="株式会社鈴木商店",
    department="調達部第1課",
    person="平松真一"
)

print(body_text)

▼結果 f:id:Moriane:20220413073601p:plain

メール本文をメッセージデータに追加する

body = MIMEText(body_text)
msg.attach(body)

※メール本文はMIMEText() のかっこの中に入れて、メール本文用のデータにしてbodyに代入する。
※それをメッセージデータのmsgにattach()で追加

メールにPDFファイルを添付

メールに添付するには、binaryという形式(コンピュータが直接処理できる形式のデータ)でファイルを読み取り、そのデータをメッセージに追加。
※コンピュータが扱うデータのうち人間が読んで理解できるものをテキスト形式、それ以外をバイナリ形式と呼ぶ。PDF以外にも画像や音声などはバイナリ形式で書き込まれる

binaryファイルを読み込むには、open()の括弧の中で「mode="rb"」を指定(rbはread binary)。
read()でファイルの中の全データを読み込み、pdf_dataに代入してファイルをcloseで閉じる。
▼PDFファイルのデータ読み込み方法

pdf = open(PDFファイルのパス, mode="rb")
pdf_data = pdf.read()
pdf.close()

・ファイルから読み込んだデータは、MIMEAppliation()の括弧の中に入れて、添付ファイルを作成。
⇨そこに受診した側が添付ファイルであることがわかるように、add_header()でヘッダーという情報を加える
・ヘッダーContent -Dispositionの値を添付ファイルを表すattachmentにして、さらにfilename = "PDFファイル名"により受信側で保存するといのデフォルトのファイル名を指定
・メッセージ添付するには、メール本文と同様にattach()を用いる

#データから添付ファイルを作成
attach_file = MIMEApplication(pdf_data)
#ヘッダーの追加
attach_file.add_header("Content-Disposition", "attachment", filename="PDFファイル名")
#添付ファイルの添付
msg.attach(attach_file)

「自分宛て」にテスト送信

ここまでの内容を組み合わせて、送信するプログラムファイルと同じフォルダに添付ファイルを入れて最後に「SMTPサーバに接続」してメッセージ送信する。

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

# 自分のメールアドレス
my_address = "自分のメールアドレス"

# SMTPサーバー(今回はGmailで送信)
smtp_server = "smtp.gmail.com"
port_number = 587

# ログイン情報(今回はGmailのアカウントを入力する)
account = "自分のメールのアカウント"
password = "自分のメールのパスワード"

# メッセージの準備
msg = MIMEMultipart()

# 件名、メールアドレスの設定
msg["Subject"] = "ご請求書送付のご案内[株式会社エクセルパイソン]"
msg["From"] = my_address
msg["To"] = my_address

# メール本文の追加
text = open("mail_body.txt", encoding="utf-8")
body_temp = text.read()
text.close()
body_text = body_temp.format(
    company="株式会社鈴木商店",
    department="調達部第1課",
    person="平松真一"
)
body = MIMEText(body_text)
msg.attach(body)

# 添付ファイルの追加
pdf = open("C0001.pdf", mode="rb")
pdf_data = pdf.read()
pdf.close()
attach_file = MIMEApplication(pdf_data)
attach_file.add_header("Content-Disposition","attachment",filename="C0001.pdf")
msg.attach(attach_file)

# SMTPサーバーに接続
server = smtplib.SMTP(smtp_server, port_number)
server.starttls()
server.login(account, password)

# メール送信
server.send_message(msg)

# SMTPサーバーとの接続を閉じる
server.quit()

実行すると自分宛てにメールが届いているのが確認できる
SMTPサーバーに接続してログインするまでに、数秒かかることがある
▼届いた!(やったね😂) f:id:Moriane:20220413081412p:plain

次は

次はメールの自動送信について学びます!

参考文献

スケジュール表の描画(ステップ1)月・日・曜日と罫線を描画

これを作ります

f:id:Moriane:20220412083507p:plain

コード

Public Sub スケジュール表描画()
  Workbooks.Add   ' 新規ブック追加
  Range("A1").Value = "2022/8/26"  '表示形式を設定
  Range("A1").NumberFormatLocal = "m/d(aaa)" '表示形式を「月/日(曜日)に設定」

  'オートフィルで連続した月日曜日を描画
  Range("A1").AutoFill Destination:=Range("A1:A32"), Type:=xlFillSeries

  Range("A1:B32").Borders.Weight = xlThin  '格子状の細線を引く
  Range("A1:B32").BorderAround Weight:=xlThick   '格子状の細線を引く
  Range("B1").ColumnWidth = 40  '列幅の設定

End Sub

ところで、VBAVSCodeと連携しようとして失敗したけど、VSCodeにて、拡張子に「.vba」をつけてファイルを保存したら、VBAの補完が使えるようになった💛
これからはこれを活用します!!💡 f:id:Moriane:20220412083837p:plain

固定した期間にて、月・日・曜日を1つの列に描画

▼セルの表示形式を設定

オブジェクト.NumberFormatLocal = "表示形式"


▼Auto Fillメソッドを用いて、次の書式で記述

オブジェクト.AutoFill Destination:=セル範囲, Type:=fireworksフィルの内容

▼A1セルの値を使い、A1〜A32セルの範囲にオートフィルで連続データを入力する

オブジェクト.AutoFill Destination:=セル範囲, Type:=フィル内容

フィル内容の定数

定数 フィルの内容
xlFillDefault オートフィル
xlFillCopy セルのコピー
xlFillSeries 連続データ
xlFillValues 書式なしコピー
xlFillFoemats 書式のみコピー

格子状の罫線を引く

オブジェクト.Borders(罫線の位置)

※罫線の位置を省略するとセル範囲に格子状に罫線が引かれる
罫線の指定、プロパティの種類についてはこちら

指定したセル範囲の周囲のみに罫線を引くBorderAroudメソッドも便利!

Range("A1:B32").BorderAround LineStyle:=線の種類, Weight:=線の太さ, Color:=色  

以上を使って、冒頭の内容を作ります!

Public Sub スケジュール表描画()
  Workbooks.Add   ' 新規ブック追加
  Range("A1").Value = "2022/8/26"  '表示形式を設定
  Range("A1").NumberFormatLocal = "m/d(aaa)" '表示形式を「月/日(曜日)に設定」

  'オートフィルで連続した月日曜日を描画
  Range("A1").AutoFill Destination:=Range("A1:A32"), Type:=xlFillSeries

  Range("A1:B32").Borders.Weight = xlThin  '格子状の細線を引く
  Range("A1:B32").BorderAround Weight:=xlThick   '格子状の細線を引く
  Range("B1").ColumnWidth = 40  '列幅の設定

End Sub

次は月と日と曜日を別々に分けて描画するよ!

あれ?インデントが使えない?

仕事で支給されているWindow PCでは当たり前に使っていたTabキーでインデントするやつ、いつも当たり前に使っていたから気がつかなかったんだけど、
私用のMacでやってみたら使えなかった?

あれ?今まで使ってなかったっけ?😅

参考記事

qiita.com

インデントの上げ下げ

 ⌘ + ] インデントを上げる  ⌘ + [ インデントを下げる