2021年1月29日金曜日

受信メール検索 - GAS

■スレッド検索


・件名から検索

var thd = GmailApp.search('subject:"検索文字"');
 検索条件は文字列で指定
subject:""で指定した文字を含む件名のスレッドを配列で取得

・複数の検索条件を指定

//and
var thd = GmailApp.search('subject:("検索文字1" "検索文字2")');

//or
var thd = GmailApp.search('subject:{"検索文字1" "検索文字2"}');
 複数条件を指定するときは半角スペースを空けて
( )で括ればand条件、{ }で括ればor条件となる

//送信者を指定
var thd = GmailApp.search('from:"メールアドレス"');

//日付を指定
var thd = GmailApp.search('after:2021/01/01');

//複合条件(and)
var thd = GmailApp.search('(subject:"検索文字" from:"メールアドレス" after:2021/01/01)');
 件名以外での検索も可能
 and、orの指定は上と同じ

 主な検索条件
 subject:件名
 from:送信者
 before:日付(指定日以前)
 after:日付(指定日以降)
 label:ラベル
 is:「unread」で未読、「read」で既読
 has:「attachment」添付ファイルあり

・取得する件数を指定

var thd = GmailApp.search('subject:"検索文字"', 0, 10);
 検索条件で取得できたスレッドのうち、何番目から何件取得するかを指定
.search()の第二引数は取得開始index、第三引数は取得件数
 取得開始indexは最新のスレッドから0始まり
 ※上のコードは最新(index 0)から10件を取得する

■メッセージ取得


・スレッドからメッセージを取得

var thd = GmailApp.search('subject:"検索文字"');

for(let i=0; i<thd.length; i++){
	var msgs = thd[i].getMessages();
}
 取得した各スレッドからメッセージの配列を取得
 最初に受信したメールはmsgs[0]
 以降そのメールに返信がある場合はmsgs[1]、msgs[2]、・・・と取得できる

■メールの内容取得


・メッセージからメール内容を取得

var thd = GmailApp.search('subject:"検索文字"');

for(let i=0; i<thd.length; i++){
	var msgs = thd[i].getMessages();

	//件名
	var strSub = msgs[0].getSubject();
	//本文
	var strBody = msgs[0].getBody();
}
 最初の受信メールの件名と本文を取得

var thd = GmailApp.search('subject:"検索文字"');

for(let i=0; i<thd.length; i++){
	var msgs = thd[i].getMessages();

	for(let j=0; j<msgs.length; j++){
		//件名
		var strSub = msgs[j].getSubject();
		//本文
		var strBody = msgs[j].getBody();
	}
}
 返信メールも含めて取得する場合はループを使用

 主な関数
 .getSubject():件名
 .getBody():本文
 .getDate():受信日
 .getFrom():送信者
 .getCc():CC
 .getBcc():BCC

2021年1月25日月曜日

メール送信 - GAS

■メール送信


・宛先、タイトル、本文

var strTo = '送信先メールアドレス';
var strTitle = 'メールタイトル';
var strBody = 'メール本文';

GmailApp.sendEmail(strTo, strTitle, strBody);

・複数の宛先

var lsTo = ['送信先メールアドレス1', '送信先メールアドレス2', ・・・];
var strTitle = 'メールタイトル';
var strBody = 'メール本文';

GmailApp.sendEmail(lsTo, strTitle, strBody);

var strTo = '送信先メールアドレス1,送信先メールアドレス2,・・・';
var strTitle = 'メールタイトル';
var strBody = 'メール本文';

GmailApp.sendEmail(strTo, strTitle, strBody);
配列カンマ区切りの文字列で指定

・その他オプション

var strTo = '送信先メールアドレス';
var strTitle = 'メールタイトル';
var strBody = 'メール本文';

var options = {name:'送信者名',	cc:'メールアドレス,・・・', bcc:'メールアドレス,・・・'};

GmailApp.sendEmail(strTo, strTitle, strBody, options);
 4つ目の引数に辞書型で、必要なものだけ指定

 attachments:添付ファイル
 bcc:BCCメールアドレス
 cc:CCメールアドレス
 from:送信元アドレス
 htmlBody:メール本文の代わりにhtmlを使用
 inlineImages:画像(htmlBody使用前提)
 name:送信者名
 noReply:メールアドレスを返信不可のものにする(G Suiteのみ有効)
 replyTo:返信先アドレス

2021年1月23日土曜日

while - GAS

■繰り返し


・条件がtrueの間繰り返す

var a = 0;

while(a<5){
	Logger.log(a);
	a++;
}

//ログ
// 0.0
// 1.0
// 2.0
// 3.0
// 4.0

・途中で繰り返しを抜ける

var a = 0;

while(true){
	Logger.log(a);
	a++;
    
	if(a==5){
		break;
	}
}

//ログ
// 0.0
// 1.0
// 2.0
// 3.0
// 4.0
 条件をtrueとすると無限ループになる

・途中で次へ飛ぶ

var a = 0;

while(true){
	if(a==2){
		a++;
		continue;
	}
	Logger.log(a);
	a++;
    
	if(a==5){
		break;
	}
}

//ログ
// 0.0
// 1.0
// 3.0
// 4.0

for - GAS

■繰り返し


・基本

for(let i=0; i<5; i++){
	Logger.log(i);
}

//ログ
// 0.0
// 1.0
// 2.0
// 3.0
// 4.0
for(初期化; 条件; 増加)のように指定
 条件がtrueの間繰り返す

・配列の値を取り出す

var ls = [0,1,2,3,4];

for(let i of ls){
	Logger.log(i);
}

//ログ
// 0
// 1
// 2
// 3
// 4

・途中で繰り返しを抜ける

for(let i=0; i<5; i++){
	if(i==3){
    	break;
    }
	Logger.log(i);
}

//ログ
// 0.0
// 1.0
// 2.0

・途中で次の値へ飛ぶ

for(let i=0; i<5; i++){
	if(i==3){
    	continue;
    }
	Logger.log(i);
}

//ログ
// 0.0
// 1.0
// 2.0
// 4.0

switch - GAS

■条件分岐


・複数の条件を指定

var a = 3;

switch(a){
  case 2:
    Logger.log('this is 1st case');
    break;
  case 3:
    Logger.log('this is 2nd case');
    break;
  case 4:
    Logger.log('this is 3rd case');
    break;
  default:
    Logger.log('this is other');
    break;
}

//ログ
// this is 2nd case
switch()に指定した値とcaseの値を比較
 2つの値が等しいときcase内のコードが実行される

var a = 3;

switch(a){
  case 2:
    Logger.log('this is 1st case');
  case 3:
    Logger.log('this is 2nd case');
  case 4:
    Logger.log('this is 3rd case');
  default:
    Logger.log('this is other');
}

//ログ
// this is 2nd case
// this is 3rd case
// this is other
 ※breakがないと該当したcase以下全てが実行されてしまう

・caseを演算子で指定

var a = 3;

switch(true){
  case a>5:
    Logger.log('this is 1st case');
    break;
  case a>3:
    Logger.log('this is 2nd case');
    break;
  case a>1:
    Logger.log('this is 3rd case');
    break;
  default:
    Logger.log('this is other');
    break;
}

//ログ
// this is 3rd case
switch()trueを指定して
caseに演算子を記載する

if - GAS

■条件分岐


・条件がTrueの場合のみ実行

var a = 3;

if(a>5){
	Logger.log('this is 1st if');
}

a = 6;

if(a>5){
	Logger.log('this is 2nd if');
}

//ログ
// this is 2nd if

・条件で分岐

var a = 3;

if(a>5){
	Logger.log('this is True');
}else{
	Logger.log('this is False');
}

//ログ
// this is False

・複数条件で分岐

var a = 3;

if(a>5){
	Logger.log('this is 1st True');
}else if(a>2){
	Logger.log('this is 2nd True');
}else{
	Logger.log('this is False');
}

//ログ
// this is 2nd True

2021年1月18日月曜日

メッセージボックス - GAS

■メッセージボックス


・ポップアップボックス

Browser.msgBox(値);

Browser.msgBox(タイトル, 値);
 OKボタンのみ
 戻り値は文字列で「ok」

・ボタンを増やす

Browser.msgBox(タイトル, 値, Browser.Buttons.OK_CANCEL);

Browser.msgBox(タイトル, 値, Browser.Buttons.YES_NO);

Browser.msgBox(タイトル, 値, Browser.Buttons.YES_NO_CANCEL);
 戻り値はそれぞれ
 「ok」「cancel」
 「yes」「no」
 「yes」「no」「cancel」
 ※タイトルは省略可

・インプットボックス

Browser.inputBox(タイトル, 値, Browser.Buttons.OK_CANCEL);
 入力欄のあるボックス
 戻り値は
 OKボタン押下 ⇒ 入力欄の値
 CANCELボタン押下 ⇒ 「cancel」

ログ出力 - GAS

■ログ出力


・実行ログに値を記載

Logger.log(値);

2021年1月13日水曜日

値取得、記入 - GAS

■スプレッドシート接続


var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();

■値取得


・1つのセルの値を取得

var val = sheet.getRange(行番号, 列番号).getValue();
.getRange()に行、列番号を指定してセルを取得
 さらに.getValue()で値を取得

・範囲を指定して取得

var data = sheet.getRange(行番号, 列番号, 行数, 列数).getValues();

var val = data[行番号-1][列番号-1];
.getRange()にさらに行数、列数で範囲を指定
.getValues()で値を二次元配列で取得
[ ][ ]でインデックスを指定して値を取り出す
 ※配列なのでインデックスは0始まり
var data = sheet.getRange(行番号, 列番号, 行数, 列数).getValues();

var val;
for(let i=0; i<data.length; i++){
	for(var j=0; j<data[i].length; j++){
    	val = data[i][j];
    }
}
 for文で全ての値を取り出す

・シート内の全ての値を取得

var data = sheet.getDataRange().getValues();

var val = data[行番号-1][列番号-1];
.getDataRange()とすると値が入っている範囲全てを取得する
.getValues()からは上記と同様

■値記入


・1つのセルに値を記入

sheet.getRange(行番号, 列番号).setValue(値);
.getRange()に行、列番号を指定してセルを取得
.setValue()で値を指定して記入

・範囲を指定して記入

sheet.getRange(行番号, 列番号, 行数, 列数).setValues([ [値,値,・・・], [値,値,・・・], ・・・ ]);

sheet.getRange(行番号, 列番号, 行数, 列数).setValue(値);
.getRange()にさらに行数、列数で範囲を指定
.setValues()に二次元配列を指定する
.setValue()を使うと範囲全てに同じ値が記入される

2021年1月12日火曜日

スプレッドシート接続 - GAS

■スプレッドシートを開く


・スクリプトが紐づいている場合

var ss = SpreadsheetApp.getActiveSpreadsheet();

・スクリプトが紐づいていない場合

var ss = SpreadsheetApp.openByUrl('スプレッドシートのURL');

var ss = SpreadsheetApp.openById('スプレッドシートのID');
 ※紐づいている状態でも可

■シートを取得


・アクティブなシートを取得

var sheet = ss.getActiveSheet();

・シート名を指定

var sheet = ss.getSheetByName('シート名');

・シート一覧を取得

var sheet = ss.getSheets()[シート番号];
 「.getSheets()」でシートの一覧を取得してから
[ ]内にシートのインデックスを指定(左から0スタート)

変数定義 - GAS

■変数、定数


・変数定義

var a;
var b = 'test';

let c;
varのスコープは関数内
letのスコープはブロック(if、forなどの{})内

・定数定義

const d = 'test const';
 スコープはブロック内
 再代入は不可

2021年1月7日木曜日

SQLite - SQL

■テーブル作成、確認、削除


・テーブル名とカラム名を指定して作成

create table
	table_name(column_name1, column_name2)

・カラムに型を指定

create table
	table_name(column_name1 integer, column_name2 text)
 カラム名の後に型を指定する
text:文字列
numeric:数値
integer:整数
real:浮動小数点
none:指定なし

・主キーを設定

create table
	table_name(column_name1 primary key, column_name2)
 カラム名の後に「primary key」を付けると主キーカラムになる
 設定されたカラムは重複不可
create table
	table_name(column_name1 integer primary key, column_name2)
 integer型に設定した場合は自動採番となる
 ※autoincrement指定と同意

・テーブル一覧取得

select
	*
from
	sqlite_master
where
	type='table'

・テーブル削除

drop table
	table_name


■テーブル操作


・テーブルにレコードを追加

insert into
	table_name ('column_name1', 'column_name2')
	values ('value1', 'value2')
 テーブル名とカラム名、対応する値を指定する


■テーブル参照


・テーブルを指定して値を取得

select
	column_name1,
  	column_name2
from
	teble_name
select にカラム名、from にテーブル名を指定

select
	*
from
	teble_name
* で全てのカラムを取得

・値でフィルター

select
	*
from
	teble_name
where
	column_name1 = 'aaa' and
	column_name2 >= 100
where にカラム名と条件式を指定する
 複数条件を指定する場合は and で区切る

sqlite3 - python

■インポート

import sqlite3

■データベース操作


・データベース作成、接続

conn = sqlite3.connect('データベースパス')

conn.close()
.connect()にパスを指定(拡張子は「.db」)
 すでにデータベースが存在する場合は接続される
 最後に.close()で閉じる

・データベースの操作

conn = sqlite3.connect('データベースパス')

cur = conn.cursor()
cur.execute('SQL文')

conn.commit()

conn.close()
.cursor()でカーソルを作成しSQLを実行
conn.commit()で上で実行した操作を確定

2021年1月5日火曜日

while - python

■繰り返し


・条件がTrueの間繰り返す

a = 0

while a<5:
	print(a)
	a += 1

#出力
# 0
# 1
# 2
# 3
# 4

・途中で繰り返しを抜ける

a = 0

while True:
	print(a)
	a += 1
    
	if a==5:
		break

#出力
# 0
# 1
# 2
# 3
# 4
 条件をTrueとすると無限ループになる

・途中で次へ飛ぶ

a = 0

while True:
	if a==2:
		a += 1
		continue

	print(a)
	a += 1
    
	if a==5:
		break

#出力
# 0
# 1
# 3
# 4
 変数のインクリメントを忘れると無限ループになる

■繰り返し後の動作


・全ての繰り返しが終了した場合に実行

a = 0

while a<5:
	print(a)
	a += 1
else:
	print('this is else')

#出力
# 0
# 1
# 2
# 3
# 4
# this is else

a = 0

while a<5:
	print(a)
	a += 1
    
	if a==3:
		break
else:
	print('this is else')

#出力
# 0
# 1
# 2
 breakで繰り返しを抜けた場合、else内は実行されない

for - python

■繰り返し


・指定の回数繰り返す

for i in range(5):
	print(i)

#出力
# 0
# 1
# 2
# 3
# 4
range関数を使い回数を指定する

・リストなどの値を取り出す

for i in ['a','b','c','d','e']:
	print(i)

#出力
# a
# b
# c
# d
# e
 動作はrange関数と同様

・途中で繰り返しを抜ける

for i in range(5):
	if i==3:
		break
        
	print(i)

#出力
# 0
# 1
# 2

・途中で次の値へ飛ぶ

for i in range(5):
	if i==3:
		continue
        
	print(i)

#出力
# 0
# 1
# 2
# 4

■繰り返し後の動作


・全ての繰り返しが終了した場合に実行

for i in range(5):
	print(i)
else:
	print('this is else')

#出力
# 0
# 1
# 2
# 3
# 4
# this is else
for i in range(5):
	if i==3:
		break
        
	print(i)
else:
	print('this is else')

#出力
# 0
# 1
# 2
 途中で繰り返しを抜けた場合、else内は実行されない

2021年1月4日月曜日

json - python

■インポート

import json

■文字列と辞書型の変換


・文字列を辞書型に変換

str = '{ "a":"あ", "b":"い", "c":"う" }'
print(str)
print(type(str))

dic = json.loads(str)
print(dic)
print(type(dic))

#出力
# { "a":"あ", "b":"い", "c":"う" }
# <class 'str'>
# {'a': 'あ', 'b': 'い', 'c': 'う'}
# <class 'dict'>

・辞書型を文字列に変換

dic = {'a': 'あ', 'b': 'い', 'c': 'う'}
print(dic)
print(type(dic))

str = json.dumps(dic)
print(str)
print(type(str))

#出力
# {'a': 'あ', 'b': 'い', 'c': 'う'}
# <class 'dict''>
# {"a": "\u3042", "b": "\u3044", "c": "\u3046"}
# <class 'str'>
 非ASCII文字(2バイト文字)はunicodeになる
str = json.dumps(dic, ensure_ascii=False)
print(str)
print(type(str))

#出力
# {"a": "あ", "b": "い", "c": "う"}
# <class 'str'>
 「ensure_ascii=False」と指定するとそのまま
 ※keyが文字列ではない場合、変換後は強制的に文字列になる

if - python

■条件分岐


・条件がTrueの場合のみ実行

a = 3

if a>5:
	print('this is 1st if')
    
a = 6

if a>5:
	print('this is 2nd if')
    
#出力
# this is 2nd if

・条件で分岐

a = 3

if a>5:
	print('this is True')
else:
	print('this is False')

#出力
# this is False

・複数条件で分岐

a = 3

if a>5:
	print('this is 1st True')
elif a>2:
	print('this is 2nd True')
else:
	print('this is False')

#出力
# this is 2nd True
 「elif 条件:」を追加して条件を増やしていく

range - python

■整数列の作成


・指定の数の整数を作成

range(5)

#0~4
0始まりで指定の数だけ作成
for i in range(5):
	print(i)

#出力
# 0
# 1
# 2
# 3
# 4

a = range(5)
print(a[3])

#出力
# 3
 リストのように[ ]で要素を取り出せる
 ※型はリストではない

・範囲を指定して作成

range(4,10)

#4~9

range(-3,2)

#-3~1
 第一引数以上、第二引数未満の整数列を作成

・増加幅を指定

for i in range(0,10,3):
	print(i)

#出力
# 0
# 3
# 6
# 9
 第三引数に幅を指定できる
for i in range(10,0,-3):
	print(i)

#出力
# 10
# 7
# 4
# 1
 マイナスも指定可能
 その場合は第一引数を第二引数より大きくする

datetime - python

■インポート

import datetime

■日付操作


・現在の日付を取得

datetime.datetime.now()

#2021-01-04 19:34:19.929699

・日付型を文字列に変換

dateNow = datetime.datetime.now()

datetime.datetime.strftime(dateNow, '%Y/%m/%d %H:%M:%S')

#2021/01/04 19:34:19
 第一引数は日付、第二引数に文字列の形を指定
 書式
 年:%Y - 2021、%y - 21
 月:%m - 01、%B - January、%b - Jan
 日:%d - 04、%A - Monday、%a - Mon
 時:%H - 19、%I - 07、%P - PM
 分:%M - 34
 秒:%S - 19

・文字列を日付型に変換

datetime.datetime.strptime('2021/01/04 19:34:19', '%Y/%m/%d %H:%M:%S')

#2021-01-04 19:34:19
 第一引数は文字列、第二引数に文字列の形に沿った形式を指定

open - python

■テキストファイルの操作


・ファイルを開く

with open('ファイルパス', 'r') as f:
	#全て読み込み
	strData = f.read()
    
	#1行ごとのリストとして読み込み
	listData = f.readlines()
    
	#1行のみ読み込み
	str1st = f.readline()
	str2nd = f.readline()
withを使うとファイルを閉じる操作が不要になる
 open()の第二引数に「'r'」を指定すると読み取り専用で開く
.readline()は実行するごとに1行ずつ読み込む

・ファイルに書き込む

#上書き
with open('ファイルパス', 'w') as f:
	f.write('テキスト')
   
#追記
with open('ファイルパス', 'a') as f:
	f.write('テキスト')
 open()の第二引数に「'w'」を指定すると書き込みモードで開く
 「'a'」を指定すると追記モードで開く
 ファイルパスが存在しない場合は新規作成される

shutil - python

■インポート

import shutil

■ファイル、フォルダ操作


・フォルダの削除

shutil.rmtree('フォルダパス')
 os.rmdir()とは違い、空でないフォルダも削除される

・ファイル、フォルダのコピー

#ファイルコピー
shutil.copy( 'コピー元ファイルパス','コピー先ファイルパス' )

#ファイルコピー(メタデータ含む)
shutil.copy2( 'コピー元ファイルパス','コピー先ファイルパス' )

#フォルダコピー
shutil.copytree( 'コピー元フォルダパス','コピー先フォルダパス' )
 shutil.copy2()はファイル更新日などの情報も引き継ぐ

・ファイル、フォルダの移動

shutil.move( '移動元パス','移動先パス' )

glob - python

■インポート

import glob

■フォルダの中身を取得


・格納されているフォルダ、ファイルのフルパスを取得

#フォルダ直下のみ
glob.glob('フォルダパス/*')

#サブフォルダを含む
glob.glob('フォルダパス/**',recursive=True)
 リストで取得される
 「*」をワイルドカードとして使用
#ファイルのみ
glob.glob('フォルダパス/*.*')

#ファイルの拡張子を指定
glob.glob('フォルダパス/*.txt')

#サブフォルダを含む
glob.glob('フォルダパス/**/*.*',recursive=True)

2021年1月3日日曜日

sys - python

■インポート

import sys

■コマンドライン


・python実行時のコマンドライン引数を取得

sys.argv
 sys.argvはリスト
 スクリプトを実行した場合、sys.argv[0]はスクリプト名になる

os - python

■インポート

import os

■パス関連


・指定したパスのファイル、フォルダが存在するか確認

os.path.exists('パス')
 存在すればTrueを、存在しない場合はFalseを返す

・指定したパスのファイル名とフォルダ名を取得

#ファイル名
os.path.basename('パス')

#フォルダ名
os.path.dirname('パス')
 実際は一番右の「¥」か「/」で分割して前後を取得する

・現在の作業ディレクトリを取得

os.getcwd()

os.path.abspath('')
 os.path.abspath()は指定したパスの正規化された絶対パスを返す
 ほぼ os.getcwd() + '¥' + '指定パス' と同じ

■ファイル、フォルダ操作


・ファイル、フォルダの削除

#ファイル削除
os.remove('ファイルパス')

#フォルダ削除
os.rmdir('フォルダパス')
 フォルダは空のフォルダのみ削除可能
 フォルダ中身も含め削除する場合はshutilモジュールを使用する

・フォルダの作成

os.mkdir('フォルダパス')

・フォルダ名、ファイル名の変更

os.rename( '変更前のパス', '変更後のパス' )
 変更前も後もパスで指定する