Items.Restrictリストリクト メソッド

本ページには広告が含まれています。

Items コレクションにフィルタをかけ、一致するアイテムのコレクションを返します。

条件式はJetクエリまたはDASLクエリで記述します。

コレクションにフィルタをかけるメソッドとしてItems.Restrict メソッドもありますが、違いは検索速度くらいで検索対象のアイテムが少ないときに使います。検索対象のアイテムが多いときはItems.Restrict メソッドを使うと良いです。

構文
  1. Items = Items.Restrict( Filter )
引数
Filter 省略可
適用するフィルター文字列式
戻り値
Items コレクションにフィルターを適用し、フィルターに一致するアイテムを含む新しいItems コレクションを返します。

Items オブジェクトを返すメソッド・プロパティ

Items.Restrict メソッド
Items コレクションにフィルタを適用し、フィルタに一致する元のすべてのアイテムを含む新しいItems コレクションを返します。

フィルタ

Jetクエリ

Outlook 2003以前のバージョンで使用されていたフィルタ式の記述方法で、AccessのJetデータベースエンジンと同じ構文を使用しています。

Jetクエリで使えるカラム([ ]で囲まれた名前)はMailItem オブジェクトのプロパティと同じと考えて大丈夫だと思います。

フィルタ説明
[BCC]ブラインド・カーボン・コピー(Blind Carbon Copy)
[CC]カーボン・コピー(Carbon Copy)
[Importance]重要度。0:低、1:標準、2:高。
[LastModificationTime]最終更新日時。日時の形式を参照。
[ReceivedTime]受信日時。日時の形式を参照。
[SenderEmailAddress]送信元アドレス
[SenderName]送信者名
[SentOn]送信日時
[Size]メールのサイズ、バイト(Byte)単位。
[Subject]件名
[To]宛先
[UnRead]メールの未既読を指定。TRUEなら未読、FALSEなら既読。
重要度(Importance)

重要度で絞り込みます。

UWSC
Items = Items.Restrict("[Importance] = 0")        // 低
Items = Items.Restrict("[Importance] = 1")        // 標準
Items = Items.Restrict("[Importance] = 2")        // 高
Items = Items.Restrict("[Importance] <= 1")    // 低~標準
受信日時(ReceivedTime)

受信日時で絞り込みます。以下は受信日が2023/05/01のメール。[ReceivedTime]は日時情報も含んでいて日時と日付の比較ではマッチしないので、以下のように範囲で指定します。

UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01' AND [ReceivedTime] < '2023/05/02'")
UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 0:00' AND [ReceivedTime] < '2023/05/02 0:00'")

受信日時で絞り込みます。以下は受信日時が2023/05/08 09:00:002023/05/08 09:59:59のメール。

UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/08 09:00 PM' AND [ReceivedTime] < '2023/05/08 10:00 PM'")

受信日時は分単位でしか指定できないため、秒単位で絞ることはできず範囲で絞るしかありません。以下は2023/05/08 21:15:002023/05/08 21:15:59に受信したメール。

UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/08 09:15 PM' AND [ReceivedTime] < '2023/05/08 09:16 PM'")
送信者アドレス(SenderEmailAddress)

送信者アドレスで絞り込みます。以下は送信者アドレスがinfo@example.comのメール。

UWSC
Items = Items.Restrict("[SenderEmailAddress] = 'info@example.com'")
送信者名(SenderName)

送信者名が空欄ではないメール。

UWSC
Items = Items.Restrict("[SenderName] <> ''")
件名(Subject)

件名キーワードに一致するメール。

UWSC
Items = Items.Restrict("[Subject] = 'キーワード'")
サイズ(Size)

サイズで絞り込みます。以下はサイズが5000バイト以上のメール

UWSC
Items = Items.Restrict("[Size] >= 5000")

サイズが10005000バイトのメール。

UWSC
Items = Items.Restrict("[Size] >= 1000 AND [Size] <= 5000")
宛先(To)

宛先info@example.comのメール。

UWSC
Items = Items.Restrict("[To] = 'info@example.com'")
未既読(UnRead)

未読のメール。

UWSC
Items = Items.Restrict("[UnRead] = TRUE")

既読のメール。

UWSC
Items = Items.Restrict("[UnRead] = FALSE")
複数条件

複数の条件を指定する場合は条件を論理演算子(ANDOR)で繋げます。

UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/09' AND [ReceivedTime] < '2023/05/10'")

DASLクエリ

Outlook 2007以降のバージョンで導入されたフィルタ式の記述方法で、SQLに似た構文を使用しています。

UWSC
@SQL = 名前空間:プロパティ名 = 値
@SQL = 名前空間#フィールド名 = 値
@SQL = 名前空間#フィールド名 = 値1;値2;値3;
@SQL = 名前空間:プロパティ LIKE '%文字列%'
@SQL = 名前空間:プロパティ LIKE '%文字列'
@SQL = 名前空間:プロパティ名 IS NULL
urn:schemas:httpmail: Namespace | Microsoft Learn
名前空間
urn:schemas:httpmail
プロパティ名 説明
attachmentfilename
bccBCC
calendar
contacts
content-disposition-type
content-media-type
date
datereceived受信日時
deleteditems
displaybcc
displaycc
displayto
drafts
expiry-date
flagcompleted
from
fromemail送信元アドレス
fromname
hasattachment添付ファイル
True:あり、False:なし
htmldescription
importance重要度
0:低、1:標準、2:高
inbox
journal
messageflag
msgfolderroot
normalizedsubject
notes
outbox
priority
read未既読。0:未読、1:既読
reply-by
reply-to
savedestination
saveinsent
sendmsg
sender
senderemail
sendername
sentitems
subject件名
submitted
tasks
textdescription本文
thread-topic
to
unreadcount
urn:schemas-microsoft-com:office:office Keywords 分類項目
重要度(Importance)

重要度標準のメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:importance=1")
受信日時(datereceived)

受信日2023/05/01のメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:datereceived >= '2023/05/01'")

受信日が今日のメール。

UWSC
Items = Items.Restrict("@SQL=%today(urn:schemas:httpmail:datereceived)%")

受信日が昨日のメール。

UWSC
Items = Items.Restrict("@SQL=%yesterday(urn:schemas:httpmail:datereceived)%")

受信日が今週のメール。

UWSC
Items = Items.Restrict("@SQL= %thisweek(urn:schemas:httpmail:datereceived)%")

受信日が先週のメール。

UWSC
Items = Items.Restrict("@SQL= %lastweek(urn:schemas:httpmail:datereceived)%")

受信日が今月のメール。

UWSC
Items = Items.Restrict("@SQL=%thismonth(urn:schemas:httpmail:datereceived)%")

受信日が先月のメール。

UWSC
Items = Items.Restrict("@SQL=%lastmonth(urn:schemas:httpmail:datereceived)%")

SQLで複数の条件を指定する場合は、Restrictメソッドを繰り返し実行します。以下は受信日時が今日で件名重要を含むメール。

UWSC
Items = Items.Restrict("@SQL=%today(urn:schemas:httpmail:datereceived)%")
Items = Items.Restrict("@SQL=urn:schemas:httpmail:subject LIKE '%重要%'")
件名(Subject)

件名重要で始まるメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:subject LIKE '重要%'")

件名重要を含むメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:subject LIKE '%重要%'")

件名RE:で始まるメール。大文字小文字の区別はなし。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:subject like 'RE:%'")

件名FW:で始まるメール。大文字小文字の区別はなし。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:subject like 'FW:%'")
カテゴリ(Categories)

カテゴリがついていないメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:categories like ''")
添付ファイル

添付ファイルがあるメール。

UWSC
Items = Items.Restrict("@SQL= urn:schemas:httpmail:hasattachment=True")

添付ファイルがないメール。

UWSC
Items = Items.Restrict("@SQL= urn:schemas:httpmail:hasattachment=False")
送信元アドレス(fromemail)

送信元アドレス@docomo.ne.jpを含むメール。後方一致ができないので部分一致で行っています。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:fromemail LIKE '%@docomo.ne.jp%'")
複数条件

受信日時2023/05/01のメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:datereceived>='2023/05/01' AND urn:schemas:httpmail:datereceived<'2023/05/02'")

受信日時2023/01/01以降で添付ファイルがあるメール。

UWSC
Items = Items.Restrict("@SQL=urn:schemas:httpmail:datereceived>='2023/01/01' AND urn:schemas:httpmail:hasattachment=True")

日時の形式

以下の形式の組み合わせで記述することができます。時刻区分(午前/午後)を指定しなかった場合、時刻は24時間表記となります。

  • <日付>
  • <日付> <時刻>
  • <日付> <時刻><時刻区分>
  • <日付> <時刻> <時刻区分>
  • <日付> <時刻区分><時刻>
  • <日付> <時刻区分> <時刻>
  • <時刻区分><時刻> <日付>
  • <時刻区分> <時刻> <日付>
UWSC
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01'")
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 12:00'")
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 05:00AM'")
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 05:00 AM'")
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 AM05:00'")
Items = Items.Restrict("[ReceivedTime] >= '2023/05/01 AM 05:00'")
Items = Items.Restrict("[ReceivedTime] >= 'AM05:00 2023/05/01'")
Items = Items.Restrict("[ReceivedTime] >= 'AM 05:00 2023/05/01'")

日付の形式

  • YYYY/MM/DD
  • MM/DD/YYYY
  • YYYY/M/D
  • M/D/YYYY
  • YYYY年MM月DD日
  • MM月DD日YYYY年

時刻の形式

  • HH:MM
  • H:M

時刻区分

  • 午前/午後
  • AM/PM
  • A/P

AM0:00AM12:00は24時間表記の0:00PM0:00PM12:00は24時間表記の12:00を指します。

時刻を24時間表記で記述した場合、時刻区分は記述しても無視されます。

以下はどちらも2023/05/10 13:00を指します。

UWSC
2023/05/10 13:00 AM 
2023/05/10 13:00 PM

LIKE句

列(カラム)に対して文字列検索を行うことができます。

クエリ説明
LIKE '<文字列>'完全一致
LIKE '<文字列>%'前方一致
LIKE '%<文字列>%'文字列を含む

比較演算子・論理演算子

演算子意味
a = baとbが等しい
a < baがb未満より小さい
a <= baがb以下
a > baがbより大きい
a >= baがb以上
a <> baとbが等しくない
a AND baかつb
a OR baまたはb
IS NULL否定

フィルタにかけたメールの件数を求めるにはItems.Restrict メソッドを使います。以下は未読メールの件数を取得します。

UWSC
DIM Items = Folder.Items.Restrict("[UnRead] = TRUE")
PRINT Items.Count

ここにはない演算子を使って条件を指定する場合は、MailItemでループするときにIF文を使います。

以下は受信日時が2022/01/012022/01/31の範囲で、件名に重要を含むメールを抽出する例。

UWSC
Items = Items.Restrict("[ReceivedTime] >= '2022/01/01' AND [ReceivedTime] <= '2022/01/31'")

FOR MailItem IN Items
	IFB POS("重要", MailItem.Subject) <> 0 THEN
		
	ENDIF
NEXT

プログラム実行例

指定期間に受信したメールを取得(Outlook)

UWSC
CONST olFolderInbox = 6

DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.GetDefaultFolder(olFolderInbox)
DIM Items = Folder.Items

DIM start = "2022/01/01"
DIM end = "2022/01/31"

Items = Items.Restrict("[ReceivedTime] >= '" + start + "' AND [ReceivedTime] < '" + end + "'")

FOR MailItem IN Items
	WITH MailItem
		PRINT "受信日時:<#TAB>" + .ReceivedTime
		PRINT "件名:<#TAB><#TAB>" + .Subject
		PRINT "----------"
	ENDWITH
NEXT
使用関数

指定期間のメール情報を取得(Outlook)

UWSC
CONST olFolderInbox = 6
CONST xlTop = -4160
CONST xlLeft = -4131

DIM Excel = ExcelBoot()

DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.GetDefaultFolder(olFolderInbox)
DIM Items = Folder.Items

DIM start = "2021/01/01"
DIM end = "2021/01/02"

Items = Items.Restrict("[ReceivedTime] >= '" + start + "' AND [ReceivedTime] < '" + end + "'")

DIM array[][1] = "受信日時", "ReceivedTime", + _
					"送信者メールアドレス", "SenderEmailAddress", + _
					"送信者", "SenderName", + _
					"CC", "CC", + _
					"BCC", "BCC", + _
					"件名", "Subject", + _
					"本文", "Body", + _
					"HTML本文", "HTMLBody"

Excel.Application.ScreenUpdating = FALSE

FOR i = 0 TO UBound(array)
	Excel.Cells(1, i + 1).Value = array[i][0]
NEXT

DIM row = 2

FOR MailItem IN Items
	FUKIDASI(row + "/" + Items.Count)
	WITH MailItem
		FOR i = 0 TO UBound(array)
			Excel.Cells(row, i + 1).Value = EVAL("." + array[i][1])
		NEXT
	ENDWITH
	row = row + 1
NEXT

WITH Excel.Range("A1").CurrentRegion
	.ColumnWidth = 20
	.RowHeight = 30
	.VerticalAlignment = xlTop
	.HorizontalAlignment = xlLeft
ENDWITH

Excel.Application.ScreenUpdating = TRUE

//////////////////////////////////////////////////
// 【引数】
//   path : 開くファイルのパス名 
// 【戻り値】
//   <a href="https://uwsc.jp/com/excel/" >Excel オブジェクト</a> 
//////////////////////////////////////////////////
FUNCTION ExcelBoot(path = "")
	DIM Excel = CREATEOLEOBJ("Excel.Application")
	Excel.Visible = TRUE
	IFB path = "" THEN
		Excel.Workbooks.Add
	ELSE
		DIM FSO = CREATEOLEOBJ("Scripting.FileSystemObject")
		IFB FSO.GetParentFolderName(path) = "" THEN
			path = GET_CUR_DIR + "\" + path
		ENDIF
		Excel.Workbooks.Open(path)
	ENDIF
	RESULT = Excel
FEND

//////////////////////////////////////////////////
// 【引数】
//   inputs : 繰り返す文字列 
//   multiplier : inputsを繰り返す回数 
// 【戻り値】
//   inputsをmultiplier回を繰り返した文字列を返します 
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
	DIM res = ""
	FOR n = 1 TO multiplier
		res = res + inputs
	NEXT
	RESULT = res
FEND

//////////////////////////////////////////////////
// 【引数】
//   arrayname : 上限値を求める配列の名前 
//   dimension : 返す次元を示す整数 
// 【戻り値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(arrayname[], dimension = 1)
	RESULT = EVAL("RESIZE(arrayname" + strRepeat("[0]", dimension - 1) + ")")
FEND
使用関数

指定期間に受信したメールからURLを抽出(Outlook)

UWSC
HASHTBL url = HASH_SORT

CONST olFolderInbox = 6

DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.GetDefaultFolder(olFolderInbox)
DIM Items = Folder.Items

DIM start = "2021/01/01"
DIM end = "2021/01/07"

Items = Items.Restrict("[ReceivedTime] >= '" + start + "' AND [ReceivedTime] <= '" + end + "'")

DIM row = 1

FOR MailItem IN Items
	FUKIDASI(row + "/" + Items.Count)
	DIM Matches = reExecute(MailItem.Body, "https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?")
	FOR Match IN Matches
		url[Match.Value] = url[Match.Value] + 1
	NEXT
	row = row + 1
NEXT

FOR i = 0 TO LENGTH(url) - 1
	FUKIDASI(i + "/" + (LENGTH(url) - 1))
	PRINT url[i, HASH_KEY]
NEXT

//////////////////////////////////////////////////
// 【引数】
//   str : 正規表現による検索の対象となる文字列 
//   Pattern : 正規表現で使用するパターンを設定 
//   IgnoreCase : 大文字・小文字を区別しない場合はTrue、区別する場合はFalse 
//   Global : 文字列全体を検索する場合はTrue、しない場合はFalse 
// 【戻り値】
//   正規表現で検索した結果をMatchesコレクションとして返します。 
//////////////////////////////////////////////////
FUNCTION reExecute(str, Pattern, IgnoreCase = TRUE, Global = TRUE)
	DIM re = CREATEOLEOBJ("VBScript.RegExp")
	re.Pattern = Pattern
	re.IgnoreCase = IgnoreCase
	re.Global = Global
	RESULT = re.Execute(str)
FEND
使用関数
解説

指定期間に受信したメールの添付ファイルをすべて保存(Outlook)

UWSC
CONST olFolderInbox = 6

DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.GetDefaultFolder(olFolderInbox)
DIM Items = Folder.Items

DIM start = "2021/01/01"
DIM end = "2021/01/31"

Items = Items.Restrict("[ReceivedTime] >= '" + start + "' AND [ReceivedTime] <= '" + end + "'")

DIM folderspec = "D:\Desktop\Outlook\"
CreateFolders(folderspec)

DIM row = 1

FOR MailItem IN Items
	FUKIDASI(row + "/" + Items.Count)
	FOR i = 1 TO MailItem.Attachments.Count
		DIM Attachment = MailItem.Attachments.Item(i)
		DIM path = folderspec + Attachment
		path = uniqueFilename(path)
		Attachment.SaveAsFile(path)
		PRINT path
	NEXT
	row = row + 1
NEXT

//////////////////////////////////////////////////
// 【引数】
//   folderspec : 作成するフォルダのパス 
// 【戻り値】
//   
//////////////////////////////////////////////////
PROCEDURE CreateFolders(folderspec)
	WITH CREATEOLEOBJ("Scripting.FileSystemObject")
		folderspec = .GetAbsolutePathName(folderspec)
		IF !.DriveExists(.GetDriveName(folderspec)) THEN EXIT
		DIM parentPath = .GetParentFolderName(folderspec)
		IF !.FolderExists(parentPath) THEN CreateFolders(parentPath)
		IF !.FolderExists(folderspec) THEN .CreateFolder(folderspec)
	ENDWITH
FEND

//////////////////////////////////////////////////
// 【引数】
//   path : ファイルのパス 
// 【戻り値】
//   重複しないファイル名 
//////////////////////////////////////////////////
FUNCTION uniqueFilename(path)
	DIM FSO = CREATEOLEOBJ("Scripting.FileSystemObject")
	IFB FSO.FileExists(path) THEN
		DIM fol = FSO.GetParentFolderName(path)
		DIM filename = FSO.GetBaseName(path)
		DIM extension = FSO.GetExtensionName(path)
		DIM i = 2
		WHILE FSO.FileExists(FSO.BuildPath(fol, filename + " (" + i + ")." + extension))
			i = i + 1
		WEND
		RESULT = FSO.BuildPath(fol, filename + " (" + i + ")." + extension)
	ELSE
		RESULT = path
	ENDIF
FEND
使用関数
解説

指定期間のメールを日毎に集計(Outlook)

UWSC
CONST olFolderIndex = 6

DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.GetDefaultFolder(olFolderIndex)
DIM Items = Folder.Items

Items = Items.Restrict("[ReceivedTime] >= '2020/12/01' AND [ReceivedTime] < '2020/12/31'")

HASHTBL dates = HASH_SORT

FOR MailItem IN Items
	DIM datetime = MailItem.ReceivedTime
	GETTIME(0, datetime)
	DIM date = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2
	dates[date] = dates[date] + 1 
NEXT

FOR i = 0 TO LENGTH(dates) - 1
	PRINT dates[i, HASH_KEY] + "<#TAB>" + dates[i, HASH_VAL]
NEXT
結果
プレーンテキスト
2020/12/05	78
2020/12/06	60
2020/12/07	72
2020/12/08	82
2020/12/09	75
2020/12/10	91
2020/12/11	82
2020/12/12	77
2020/12/13	63
2020/12/14	71
2020/12/15	104
2020/12/16	84
2020/12/17	80
2020/12/18	93
2020/12/19	78
2020/12/20	66
2020/12/21	67
2020/12/22	75
2020/12/23	82
2020/12/24	73
2020/12/25	87
2020/12/26	73
2020/12/27	56
2020/12/28	65
2020/12/29	69
2020/12/30	44
2020/12/31	1
使用関数

過去7日間に受信した迷惑メールの受信日時とメールアドレスを取得

UWSC
DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folders = NameSpace.Folders("Yahoo!_新").Folders("迷惑メール")
DIM startDate = dateAdd("d", -7, today())
DIM endDate = dateAdd("d", -1, today())
DIM Items = Folders.Items.Restrict("[ReceivedTime] >= '" + startDate + "' AND [ReceivedTime] < '" + endDate + "'")
DIM count = Items.Count

Items.Sort("受信日時")

FOR Index = 1 TO count
	WITH Items.Item(Index)
		PRINT .ReceivedTime + "<#TAB>" + .SenderEmailAddress
	ENDWITH
NEXT

//////////////////////////////////////////////////
// 【引数】
//   interval : 加算する時間間隔を表す文字列式(yyyy:年、m:月、d:日、ww:週、h:時、n:分、s:秒) 
//   num : dateに加算する値。未来は正、過去は負で指定 
//   date : 時間間隔を加算する日付 
// 【戻り値】
//   日時(date)に、指定した単位(interval)の時間(num)を加算して返します 
//////////////////////////////////////////////////
FUNCTION dateAdd(interval, num, date)
	DIM year, month, day, d
	GETTIME(0, date)
	DIM time = G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2
	SELECT interval
		CASE "yyyy"
			d = (G_TIME_YY + num) + "/" + G_TIME_MM2 + "/" + G_TIME_DD2
			IF time <> "00:00:00" THEN d = d + " " + time
		CASE "m"
			IFB num > 0 THEN
				year = G_TIME_YY + INT((G_TIME_MM + num) / 12)
				month = REPLACE(FORMAT(((G_TIME_MM + num) MOD 12), 2), " ", "0")
			ELSE
				year = G_TIME_YY + CEIL((G_TIME_MM + num) / 12 - 1)
				month = REPLACE(FORMAT(G_TIME_MM - (ABS(num) MOD 12), 2), " ", "0")
			ENDIF
			IF month = "00" THEN month = 12
			day = G_TIME_DD2
			d = "" + year + month + day
			IFB !isDate(d) THEN
				d = year + "/" + month + "/" + "01"
				d = getEndOfMonth(d)
			ELSE
				d = year + "/" + month + "/" + day
			ENDIF
			IF time <> "00:00:00" THEN d = d + " " + time
		CASE "d"
			t = GETTIME(num, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "ww"
			t = GETTIME(num * 7, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "h"
			t = GETTIME(num / 24, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "n"
			t = GETTIME(num / 1440, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "s"
			t = GETTIME(num / 86400, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
	SELEND
	RESULT = d
FEND

//////////////////////////////////////////////////
// 【引数】
//   date : 日付(”YYYYMMDD” or “YYYY/MM/DD” or “YYYY-MM-DD” or “YYYYMMDDHHNNSS” or “YYYY/MM/DD HH:NN:SS”) 
//   m : 第一引数の指定日からプラスマイナスm月とする 
// 【戻り値】
//   dateからm月後の月末の日付 
//////////////////////////////////////////////////
FUNCTION getEndOfMonth(date, m = 0)
	date = dateAdd("m", m + 1, date)
	GETTIME(0, date)
	GETTIME(-G_TIME_DD, date)
	RESULT = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2
FEND

//////////////////////////////////////////////////
// 【引数】
//   expr : 評価する式 
//   truepart : 評価した式がTrueのときに返す値 
//   falsepart : 評価した式がFalseのときに返す値 
// 【戻り値】
//   truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき 
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
	IFB EVAL(expr) THEN
		RESULT = truepart
	ELSE
		RESULT = falsepart
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   date : 存在するかを調べる日付文字列。YYYYMMDD or YYYY/MM/DD or YYYY-MM-DDのいずれかの形式。 
// 【戻り値】
//   TRUE : 日付として認識できる、FALSE : 日付として認識できない 
//////////////////////////////////////////////////
FUNCTION isDate(date)
	TRY
		GETTIME(0, date)
		RESULT = TRUE
	EXCEPT
		RESULT = FALSE
	ENDTRY
FEND

//////////////////////////////////////////////////
// 【引数】
//   
// 【戻り値】
//   
//////////////////////////////////////////////////
使用関数
解説

未読メールの本文からURLを抽出

UWSC
DIM Outlook = CREATEOLEOBJ("Outlook.Application")
DIM NameSpace = Outlook.GetNameSpace("MAPI")
DIM Folder = NameSpace.Folders("Android_新").Folders("受信トレイ")
DIM Items = Folder.Items.Restrict("[UnRead] = TRUE")

Items.Sort("受信日時", TRUE)

// クリックするURLを格納した配列(部分一致)
DIM urls[] = "://example.com"

DIM driver = CREATEOLEOBJ("Selenium.WebDriver")
WebDriverDownload.Chrome()

// ログイン情報を保存
CONST PROFILE_PATH = "C:\Users\" + BETWEENSTR(DOSCMD("SET"), "USERNAME=", "<#CR>") + "\AppData\Local\Google\Chrome\User Data\Default"
driver.AddArgument("user-data-dir=" + PROFILE_PATH)
driver.Start("chrome")

DIM count = Items.Count

FOR Index = count TO 1 STEP -1
	WITH Items.Item(Index)
		FUKIDASI(Index + "<#TAB>" + .SenderEmailAddress + "<#TAB>" + .ReceivedTime)
		DIM Matches = reExecute(.Body, "https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?")
		// メール本文のURLをループ
		FOR Match IN Matches
			// クリックするURLをチェック
			FOR i = 0 TO UBound(urls)
				IF POS(urls[i], Match.Value) = 0 THEN CONTINUE
				driver.Get(Match.Value)		// リンクを開く
			NEXT
		NEXT
		SLEEP(1.000)
	ENDWITH
NEXT

//////////////////////////////////////////////////
// 【引数】
//   num : 単位換算する数値 
//   before : 変換前の単位 
//   after : 変換後の単位 
// 【戻り値】
//   指定した単位に変換した数値 
//////////////////////////////////////////////////
FUNCTION convert(num, before, after)
	HASHTBL unit
	
	// 重量
	unit["g,sg"] = "num * 6.85217658567918 * POWER(10, -5)"
	unit["g,lbm"] = "num * 2.20462262184878 * POWER(10, -3)"
	unit["g,u"] = "num * 6.02217 * POWER(10, +23)"
	unit["g,ozm"] = "num * 3.52739619495804 * POWER(10, -2)"
	unit["sg,g"] = "num * 1.45939029372064 * POWER(10, +4)"
	unit["sg,lbm"] = "num * 3.21740485564304 * POWER(10, +1)"
	unit["sg,u"] = "num * 8.78869644513561 * POWER(10, +27)"
	unit["sg,ozm"] = "num * 5.14784776902887 * POWER(10, +2)"
	unit["lbm,g"] = "num * 4.5359237 * POWER(10, +2)"
	unit["lbm,sg"] = "num * 3.10809501715673 * POWER(10, -2)"
	unit["lbm,u"] = "num * 2.7316103628429 * POWER(10, +26)"
	unit["lbm,ozm"] = "num * 1.6 * POWER(10, +1)"
	unit["u,g"] = "num * 1.66053100460465 * POWER(10, -24)"
	unit["u,sg"] = "num * 1.13782516695463 * POWER(10, -28)"
	unit["u,lbm"] = "num * 3.66084421703269 * POWER(10, -27)"
	unit["u,ozm"] = "num * 5.8573507472523 * POWER(10, -26)"
	unit["ozm,g"] = "num * 2.8349523125 * POWER(10, +1)"
	unit["ozm,sg"] = "num * 1.94255938572295 * POWER(10, -3)"
	unit["ozm,lbm"] = "num * 6.25 * POWER(10, -2)"
	unit["ozm,u"] = "num * 1.70725647677681 * POWER(10, +25)"
	
	// 距離
	unit["m,mi"] = "num * 6.21371192237334 * POWER(10, -4)"
	unit["m,Nmi"] = "num * 5.39956803455724 * POWER(10, -4)"
	unit["m,in"] = "num * 3.93700787401575 * POWER(10, +1)"
	unit["m,ft"] = "num * 3.28083989501312 * POWER(10, +0)"
	unit["m,yd"] = "num * 1.09361329833771 * POWER(10, +0)"
	unit["m,ang"] = "num * 1 * POWER(10, +10)"
	unit["m,pica"] = "num * 2.36220472440945 * POWER(10, +2)"
	unit["mi,m"] = "num * 1.609344 * POWER(10, +3)"
	unit["mi,Nmi"] = "num * 8.68976241900648 * POWER(10, -1)"
	unit["mi,in"] = "num * 6.336 * POWER(10, +4)"
	unit["mi,ft"] = "num * 5.28 * POWER(10, +3)"
	unit["mi,yd"] = "num * 1.76 * POWER(10, +3)"
	unit["mi,ang"] = "num * 1.609344 * POWER(10, +13)"
	unit["mi,pica"] = "num * 3.8016 * POWER(10, +5)"
	unit["Nmi,m"] = "num * 1.852 * POWER(10, +3)"
	unit["Nmi,mi"] = "num * 1.15077944802354 * POWER(10, +0)"
	unit["Nmi,in"] = "num * 7.29133858267717 * POWER(10, +4)"
	unit["Nmi,ft"] = "num * 6.0761154855643 * POWER(10, +3)"
	unit["Nmi,yd"] = "num * 2.02537182852143 * POWER(10, +3)"
	unit["Nmi,ang"] = "num * 1.852 * POWER(10, +13)"
	unit["Nmi,pica"] = "num * 4.3748031496063 * POWER(10, +5)"
	unit["in,m"] = "num * 2.54 * POWER(10, -2)"
	unit["in,mi"] = "num * 1.57828282828283 * POWER(10, -5)"
	unit["in,Nmi"] = "num * 1.37149028077754 * POWER(10, -5)"
	unit["in,ft"] = "num * 8.33333333333333 * POWER(10, -2)"
	unit["in,yd"] = "num * 2.77777777777778 * POWER(10, -2)"
	unit["in,ang"] = "num * 2.54 * POWER(10, +8)"
	unit["in,pica"] = "num * 6 * POWER(10, +0)"
	unit["ft,m"] = "num * 3.048 * POWER(10, -1)"
	unit["ft,mi"] = "num * 1.89393939393939 * POWER(10, -4)"
	unit["ft,Nmi"] = "num * 1.64578833693305 * POWER(10, -4)"
	unit["ft,in"] = "num * 1.2 * POWER(10, +1)"
	unit["ft,yd"] = "num * 3.33333333333333 * POWER(10, -1)"
	unit["ft,ang"] = "num * 3.048 * POWER(10, +9)"
	unit["ft,pica"] = "num * 7.2 * POWER(10, +1)"
	unit["yd,m"] = "num * 9.144 * POWER(10, -1)"
	unit["yd,mi"] = "num * 5.68181818181818 * POWER(10, -4)"
	unit["yd,Nmi"] = "num * 4.93736501079914 * POWER(10, -4)"
	unit["yd,in"] = "num * 3.6 * POWER(10, +1)"
	unit["yd,ft"] = "num * 3 * POWER(10, +0)"
	unit["yd,ang"] = "num * 9.144 * POWER(10, +9)"
	unit["yd,pica"] = "num * 2.16 * POWER(10, +2)"
	unit["ang,m"] = "num * 1 * POWER(10, -10)"
	unit["ang,mi"] = "num * 6.21371192237334 * POWER(10, -14)"
	unit["ang,Nmi"] = "num * 5.39956803455724 * POWER(10, -14)"
	unit["ang,in"] = "num * 3.93700787401575 * POWER(10, -9)"
	unit["ang,ft"] = "num * 3.28083989501312 * POWER(10, -10)"
	unit["ang,yd"] = "num * 1.09361329833771 * POWER(10, -10)"
	unit["ang,pica"] = "num * 2.36220472440945 * POWER(10, -8)"
	unit["pica,m"] = "num * 4.23333333333333 * POWER(10, -3)"
	unit["pica,mi"] = "num * 2.63047138047138 * POWER(10, -6)"
	unit["pica,Nmi"] = "num * 2.28581713462923 * POWER(10, -6)"
	unit["pica,in"] = "num * 1.66666666666667 * POWER(10, -1)"
	unit["pica,ft"] = "num * 1.38888888888889 * POWER(10, -2)"
	unit["pica,yd"] = "num * 4.62962962962963 * POWER(10, -3)"
	unit["pica,ang"] = "num * 4.23333333333333 * POWER(10, +7)"

	// 時間
	unit["yr,day"] = "num * 3.6525 * POWER(10, +2)"
	unit["yr,hr"] = "num * 8.766 * POWER(10, +3)"
	unit["yr,mn"] = "num * 5.2596 * POWER(10, +5)"
	unit["yr,sec"] = "num * 3.15576 * POWER(10, +7)"
	unit["day,yr"] = "num * 2.7378507871321 * POWER(10, -3)"
	unit["day,hr"] = "num * 2.4 * POWER(10, +1)"
	unit["day,mn"] = "num * 1.44 * POWER(10, +3)"
	unit["day,sec"] = "num * 8.64 * POWER(10, +4)"
	unit["hr,yr"] = "num * 1.14077116130504 * POWER(10, -4)"
	unit["hr,day"] = "num * 4.16666666666667 * POWER(10, -2)"
	unit["hr,mn"] = "num * 6 * POWER(10, +1)"
	unit["hr,sec"] = "num * 3.6 * POWER(10, +3)"
	unit["mn,yr"] = "num * 1.90128526884174 * POWER(10, -6)"
	unit["mn,day"] = "num * 6.94444444444444 * POWER(10, -4)"
	unit["mn,hr"] = "num * 1.66666666666667 * POWER(10, -2)"
	unit["mn,sec"] = "num * 6 * POWER(10, +1)"
	unit["sec,yr"] = "num * 3.16880878140289 * POWER(10, -8)"
	unit["sec,day"] = "num * 1.15740740740741 * POWER(10, -5)"
	unit["sec,hr"] = "num * 2.77777777777778 * POWER(10, -4)"
	unit["sec,mn"] = "num * 1.66666666666667 * POWER(10, -2)"
	
	// 圧力
	unit["Pa,atm"] = "num * 9.86923266716013 * POWER(10, -6)"
	unit["Pa,mmHg"] = "num * 7.5006168270417 * POWER(10, -3)"
	unit["atm,Pa"] = "num * 1.01325 * POWER(10, +5)"
	unit["atm,mmHg"] = "num * 7.6 * POWER(10, +2)"
	unit["mmHg,Pa"] = "num * 1.33322368421053 * POWER(10, +2)"
	unit["mmHg,atm"] = "num * 1.31578947368421 * POWER(10, -3)"
	
	// 物理的な力
	unit["N,dyn"] = "num * 1 * POWER(10, +5)"
	unit["N,lbf"] = "num * 2.2480894309971 * POWER(10, -1)"
	unit["dyn,N"] = "num * 1 * POWER(10, -5)"
	unit["dyn,lbf"] = "num * 2.2480894309971 * POWER(10, -6)"
	unit["lbf,N"] = "num * 4.4482216152605 * POWER(10, +0)"
	unit["lbf,dyn"] = "num * 4.4482216152605 * POWER(10, +5)"
	
	// エネルギー
	unit["J,e"] = "num * 1 * POWER(10, +7)"
	unit["J,cal"] = "num * 2.38845896627496 * POWER(10, -1)"
	unit["J,eV"] = "num * 6.241457 * POWER(10, +18)"
	unit["J,HPh"] = "num * 3.72506135998619 * POWER(10, -7)"
	unit["J,Wh"] = "num * 2.77777777777778 * POWER(10, -4)"
	unit["J,flb"] = "num * 7.37562149277265 * POWER(10, -1)"
	unit["J,BTU"] = "num * 9.47817120313317 * POWER(10, -4)"
	unit["J,c"] = "num * 2.39005736137667 * POWER(10, -1)"
	unit["e,J"] = "num * 1 * POWER(10, -7)"
	unit["e,cal"] = "num * 2.38845896627496 * POWER(10, -8)"
	unit["e,eV"] = "num * 6.241457 * POWER(10, +11)"
	unit["e,HPh"] = "num * 3.72506135998619 * POWER(10, -14)"
	unit["e,Wh"] = "num * 2.77777777777778 * POWER(10, -11)"
	unit["e,flb"] = "num * 7.37562149277265 * POWER(10, -8)"
	unit["e,BTU"] = "num * 9.47817120313317 * POWER(10, -11)"
	unit["e,c"] = "num * 2.39005736137667 * POWER(10, -8)"
	unit["cal,J"] = "num * 4.1868 * POWER(10, +0)"
	unit["cal,e"] = "num * 4.1868 * POWER(10, +7)"
	unit["cal,eV"] = "num * 2.61317321676 * POWER(10, +19)"
	unit["cal,HPh"] = "num * 1.55960869019902 * POWER(10, -6)"
	unit["cal,Wh"] = "num * 1.163 * POWER(10, -3)"
	unit["cal,flb"] = "num * 3.08802520659405 * POWER(10, +0)"
	unit["cal,BTU"] = "num * 3.9683207193278 * POWER(10, -3)"
	unit["cal,c"] = "num * 1.00066921606119 * POWER(10, +0)"
	unit["eV,J"] = "num * 1.60219000146921 * POWER(10, -19)"
	unit["eV,e"] = "num * 1.60219000146921 * POWER(10, -12)"
	unit["eV,cal"] = "num * 3.82676507468522 * POWER(10, -20)"
	unit["eV,HPh"] = "num * 5.96825606582916 * POWER(10, -26)"
	unit["eV,Wh"] = "num * 4.45052778185891 * POWER(10, -23)"
	unit["eV,flb"] = "num * 1.18171470103417 * POWER(10, -19)"
	unit["eV,BTU"] = "num * 1.51858311338733 * POWER(10, -22)"
	unit["eV,c"] = "num * 3.82932600733558 * POWER(10, -20)"
	unit["HPh,J"] = "num * 2.68451953769617 * POWER(10, +6)"
	unit["HPh,e"] = "num * 2.68451953769617 * POWER(10, +13)"
	unit["HPh,cal"] = "num * 6.41186475995073 * POWER(10, +5)"
	unit["HPh,eV"] = "num * 1.67553132601905 * POWER(10, +25)"
	unit["HPh,Wh"] = "num * 7.4569987158227 * POWER(10, +2)"
	unit["HPh,flb"] = "num * 1.98 * POWER(10, +6)"
	unit["HPh,BTU"] = "num * 2.54443357764402 * POWER(10, +3)"
	unit["HPh,c"] = "num * 6.41615568283024 * POWER(10, +5)"
	unit["Wh,J"] = "num * 3.6 * POWER(10, +3)"
	unit["Wh,e"] = "num * 3.6 * POWER(10, +10)"
	unit["Wh,cal"] = "num * 8.59845227858985 * POWER(10, +2)"
	unit["Wh,eV"] = "num * 2.24692452 * POWER(10, +22)"
	unit["Wh,HPh"] = "num * 1.34102208959503 * POWER(10, -3)"
	unit["Wh,flb"] = "num * 2.65522373739816 * POWER(10, +3)"
	unit["Wh,BTU"] = "num * 3.41214163312794 * POWER(10, +0)"
	unit["Wh,c"] = "num * 8.60420650095602 * POWER(10, +2)"
	unit["flb,J"] = "num * 1.3558179483314 * POWER(10, +0)"
	unit["flb,e"] = "num * 1.3558179483314 * POWER(10, +7)"
	unit["flb,cal"] = "num * 3.23831553532865 * POWER(10, -1)"
	unit["flb,eV"] = "num * 8.46227942433866 * POWER(10, +18)"
	unit["flb,HPh"] = "num * 5.05050505050505 * POWER(10, -7)"
	unit["flb,Wh"] = "num * 3.76616096758722 * POWER(10, -4)"
	unit["flb,BTU"] = "num * 1.28506746345658 * POWER(10, -3)"
	unit["flb,c"] = "num * 3.24048266809608 * POWER(10, -1)"
	unit["BTU,J"] = "num * 1.05505585262 * POWER(10, +3)"
	unit["BTU,e"] = "num * 1.05505585262 * POWER(10, +10)"
	unit["BTU,cal"] = "num * 2.51995761111111 * POWER(10, +2)"
	unit["BTU,eV"] = "num * 6.58508573672607 * POWER(10, +21)"
	unit["BTU,HPh"] = "num * 3.93014778922204 * POWER(10, -4)"
	unit["BTU,Wh"] = "num * 2.93071070172222 * POWER(10, -1)"
	unit["BTU,flb"] = "num * 7.78169262265965 * POWER(10, +2)"
	unit["BTU,c"] = "num * 2.52164400721797 * POWER(10, +2)"
	unit["c,J"] = "num * 4.184 * POWER(10, +0)"
	unit["c,e"] = "num * 4.184 * POWER(10, +7)"
	unit["c,cal"] = "num * 9.99331231489443 * POWER(10, -1)"
	unit["c,eV"] = "num * 2.6114256088 * POWER(10, +19)"
	unit["c,HPh"] = "num * 1.55856567301822 * POWER(10, -6)"
	unit["c,Wh"] = "num * 1.16222222222222 * POWER(10, -3)"
	unit["c,flb"] = "num * 3.08596003257608 * POWER(10, +0)"
	unit["c,BTU"] = "num * 3.96566683139092 * POWER(10, -3)"
	
	// 仕事率
	unit["HP,W"] = "num * 7.4569987158227 * POWER(10, +2)"
	unit["W,HP"] = "num * 1.34102208959503 * POWER(10, -3)"
	
	// 磁力
	unit["T,ga"] = "num * 1 * POWER(10, +4)"
	unit["ga,T"] = "num * 1 * POWER(10, -4)"
	
	// 温度
	unit["C,F"] = "num * (9/5) + 32"
	unit["C,K"] = "num + 273.15"
	unit["F,C"] = "(num - 32) * (9/5)"
	unit["F,K"] = "(num - 32) * (5/9) + 273.15"
	unit["K,C"] = "num - 23373.15"
	unit["K,F"] = "(num - 273.15) * (9/5) + 32"
	
	// 体積(容積)
	unit["tsp,tbs"] = "num * 3.33333333333333 * POWER(10, -1)"
	unit["tsp,oz"] = "num * 1.66666666666667 * POWER(10, -1)"
	unit["tsp,cup"] = "num * 2.08333333333333 * POWER(10, -2)"
	unit["tsp,us_pt"] = "num * 1.04166666666667 * POWER(10, -2)"
	unit["tsp,uk_pt"] = "num * 8.67368942321863 * POWER(10, -3)"
	unit["tsp,qt"] = "num * 5.20833333333333 * POWER(10, -3)"
	unit["tsp,gal"] = "num * 1.30208333333333 * POWER(10, -3)"
	unit["tbs,tsp"] = "num * 3 * POWER(10, +0)"
	unit["tbs,oz"] = "num * 5 * POWER(10, -1)"
	unit["tbs,cup"] = "num * 6.25 * POWER(10, -2)"
	unit["tbs,us_pt"] = "num * 3.125 * POWER(10, -2)"
	unit["tbs,uk_pt"] = "num * 2.60210682696559 * POWER(10, -2)"
	unit["tbs,qt"] = "num * 1.5625 * POWER(10, -2)"
	unit["tbs,gal"] = "num * 3.90625 * POWER(10, -3)"
	unit["oz,tsp"] = "num * 6 * POWER(10, +0)"
	unit["oz,tbs"] = "num * 2 * POWER(10, +0)"
	unit["oz,cup"] = "num * 1.25 * POWER(10, -1)"
	unit["oz,us_pt"] = "num * 6.25 * POWER(10, -2)"
	unit["oz,uk_pt"] = "num * 5.20421365393118 * POWER(10, -2)"
	unit["oz,qt"] = "num * 3.125 * POWER(10, -2)"
	unit["oz,gal"] = "num * 7.8125 * POWER(10, -3)"
	unit["cup,tsp"] = "num * 4.8 * POWER(10, +1)"
	unit["cup,tbs"] = "num * 1.6 * POWER(10, +1)"
	unit["cup,oz"] = "num * 8 * POWER(10, +0)"
	unit["cup,us_pt"] = "num * 5 * POWER(10, -1)"
	unit["cup,uk_pt"] = "num * 4.16337092314494 * POWER(10, -1)"
	unit["cup,qt"] = "num * 2.5 * POWER(10, -1)"
	unit["cup,gal"] = "num * 6.25 * POWER(10, -2)"
	unit["us_pt,tsp"] = "num * 9.6 * POWER(10, +1)"
	unit["us_pt,tbs"] = "num * 3.2 * POWER(10, +1)"
	unit["us_pt,oz"] = "num * 1.6 * POWER(10, +1)"
	unit["us_pt,cup"] = "num * 2 * POWER(10, +0)"
	unit["us_pt,uk_pt"] = "num * 8.32674184628989 * POWER(10, -1)"
	unit["us_pt,qt"] = "num * 5 * POWER(10, -1)"
	unit["us_pt,gal"] = "num * 1.25 * POWER(10, -1)"
	unit["uk_pt,tsp"] = "num * 1.15291192848466 * POWER(10, +2)"
	unit["uk_pt,tbs"] = "num * 3.84303976161554 * POWER(10, +1)"
	unit["uk_pt,oz"] = "num * 1.92151988080777 * POWER(10, +1)"
	unit["uk_pt,cup"] = "num * 2.40189985100971 * POWER(10, +0)"
	unit["uk_pt,us_pt"] = "num * 1.20094992550486 * POWER(10, +0)"
	unit["uk_pt,qt"] = "num * 6.00474962752428 * POWER(10, -1)"
	unit["uk_pt,gal"] = "num * 1.50118740688107 * POWER(10, -1)"
	unit["qt,tsp"] = "num * 1.92 * POWER(10, +2)"
	unit["qt,tbs"] = "num * 6.4 * POWER(10, +1)"
	unit["qt,oz"] = "num * 3.2 * POWER(10, +1)"
	unit["qt,cup"] = "num * 4 * POWER(10, +0)"
	unit["qt,us_pt"] = "num * 2 * POWER(10, +0)"
	unit["qt,uk_pt"] = "num * 1.66534836925798 * POWER(10, +0)"
	unit["qt,gal"] = "num * 2.5 * POWER(10, -1)"
	unit["gal,tsp"] = "num * 7.68 * POWER(10, +2)"
	unit["gal,tbs"] = "num * 2.56 * POWER(10, +2)"
	unit["gal,oz"] = "num * 1.28 * POWER(10, +2)"
	unit["gal,cup"] = "num * 1.6 * POWER(10, +1)"
	unit["gal,us_pt"] = "num * 8 * POWER(10, +0)"
	unit["gal,uk_pt"] = "num * 6.66139347703191 * POWER(10, +0)"
	unit["gal,qt"] = "num * 4 * POWER(10, +0)"

	RESULT = EVAL(unit[before + "," + after])
FEND

//////////////////////////////////////////////////
// 【引数】
//   interval : 加算する時間間隔を表す文字列式(yyyy:年、m:月、d:日、ww:週、h:時、n:分、s:秒) 
//   num : dateに加算する値。未来は正、過去は負で指定 
//   date : 時間間隔を加算する日付 
// 【戻り値】
//   日時(date)に、指定した単位(interval)の時間(num)を加算して返します 
//////////////////////////////////////////////////
FUNCTION dateAdd(interval, num, date)
	DIM year, month, day, d
	GETTIME(0, date)
	DIM time = G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2
	SELECT interval
		CASE "yyyy"
			d = (G_TIME_YY + num) + "/" + G_TIME_MM2 + "/" + G_TIME_DD2
			IF time <> "00:00:00" THEN d = d + " " + time
		CASE "m"
			IFB num > 0 THEN
				year = G_TIME_YY + INT((G_TIME_MM + num) / 12)
				month = REPLACE(FORMAT(((G_TIME_MM + num) MOD 12), 2), " ", "0")
			ELSE
				year = G_TIME_YY + CEIL((G_TIME_MM + num) / 12 - 1)
				month = REPLACE(FORMAT(G_TIME_MM - (ABS(num) MOD 12), 2), " ", "0")
			ENDIF
			IF month = "00" THEN month = 12
			day = G_TIME_DD2
			d = "" + year + month + day
			IFB !isDate(d) THEN
				d = year + "/" + month + "/" + "01"
				d = getEndOfMonth(d)
			ELSE
				d = year + "/" + month + "/" + day
			ENDIF
			IF time <> "00:00:00" THEN d = d + " " + time
		CASE "d"
			t = GETTIME(num, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "ww"
			t = GETTIME(num * 7, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "h"
			t = GETTIME(num / 24, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "n"
			t = GETTIME(num / 1440, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
		CASE "s"
			t = GETTIME(num / 86400, date)
			d = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2 + IIF(t MOD 86400, " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2, "")
	SELEND
	RESULT = d
FEND

//////////////////////////////////////////////////
// 【引数】
//   interval : 時間単位(yyyy︰年、q:四半期、m︰月、d︰日、w:週日、ww:週、h:時、n:分、s:秒) 
//   date1 : 日時1 
//   date2 : 日時2 
// 【戻り値】
//   date2からdate1を引いた時間間隔を求めます。 
//////////////////////////////////////////////////
FUNCTION dateDiff(interval, date1, date2)
	DIM y1, y2, m1, m2, d1, d2, d
	SELECT interval
		CASE "yyyy"
			GETTIME(0, date1)
			y1 = G_TIME_YY
			GETTIME(0, date2)
			y2 = G_TIME_YY
			d = y2 - y1
		CASE "q"
			GETTIME(0, date1)
			y1 = G_TIME_YY
			m1 = G_TIME_MM
			GETTIME(0, date2)
			y2 = G_TIME_YY
			m2 = G_TIME_MM
			d = y2 * 4 + CEIL(m2/3) - (y1 * 4 + CEIL(m1/3))
		CASE "m"
			GETTIME(0, date1)
			y1 = G_TIME_YY
			m1 = G_TIME_MM
			GETTIME(0, date2)
			y2 = G_TIME_YY
			m2 = G_TIME_MM
			d = (y2 - y1) * 12 + m2 - m1
		CASE "d"
			d1 = GETTIME(0, date1)
			d2 = GETTIME(0, date2)
			d = (d2 - d1) / 86400
		CASE "w"
			d = INT(dateDiff("d", date1, date2) / 7)
		CASE "ww"
			date1 = dateAdd("d", -1 * getWeekday(date1), date1)
			d = INT(dateDiff("d", date1, date2) / 7)
		CASE "h"
			d = dateDiff("d", date1, date2) * 24
		CASE "n"
			d = dateDiff("d", date1, date2) * 1440
		CASE "s"
			d = dateDiff("d", date1, date2) * 86400
	SELEND
	RESULT = d
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 数値 
// 【戻り値】
//   
//////////////////////////////////////////////////
FUNCTION decimalDigits(num)
	DIM str = fixed(num)
	RESULT = IIF(POS(".", str), LENGTH(BETWEENSTR(str, ".")), 0)
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 数値 
//   digits : 小数点以下の桁数 
// 【戻り値】
//   
//////////////////////////////////////////////////
FUNCTION fixed(num, digits = EMPTY)
	num = VAL(num)		// 指数表記を整える
	IFB POS("E-", num) THEN
		DIM mantissa = BETWEENSTR(num,, "E")
		DIM exponent = BETWEENSTR(num, "E")		
		RESULT = "0." + strRepeat("0", VAL(ABS(exponent) - 1)) + REPLACE(mantissa, ".", "")
	ELSEIF POS("E", num) THEN
		RESULT = ROUND(num, -1 *digits)
		mantissa = BETWEENSTR(num,, "E")
		exponent = BETWEENSTR(num, "E")
		RESULT = REPLACE(mantissa, ".", "") + strRepeat("0", VAL(exponent) - decimalDigits(mantissa))
	ELSEIF LENGTH(BETWEENSTR(num, ".")) < digits THEN
		DIM keta = digits - LENGTH(BETWEENSTR(num, "."))
		RESULT = num + IIF(POS(".", num) OR keta = 0, "", ".") + strRepeat("0", keta)
	ELSE
		IF digits = EMPTY THEN digits = LENGTH(BETWEENSTR(num, "."))
		RESULT = "" + roundOff(num, digits)
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   array : 最大公約数を求める数値を格納した配列 
// 【戻り値】
//   最大公約数 
//////////////////////////////////////////////////
FUNCTION GCD(array[])
	DIM c = LENGTH(array)
	DIM rem = array[c-1] MOD array[c-2]
	IFB rem = 0 THEN
		IFB LENGTH(array) = 2 THEN
			RESULT = array[c-2]
			EXIT
		ENDIF
		RESIZE(array, c-2)
		RESULT = GCD(array)
		EXIT
	ENDIF
	array[c-1] = array[c-2]
	array[c-2] = rem
	RESULT = GCD(array)
FEND

//////////////////////////////////////////////////
// 【引数】
//   date : 日付(”YYYYMMDD” or “YYYY/MM/DD” or “YYYY-MM-DD” or “YYYYMMDDHHNNSS” or “YYYY/MM/DD HH:NN:SS”) 
//   m : 第一引数の指定日からプラスマイナスm月とする 
// 【戻り値】
//   dateからm月後の月末の日付 
//////////////////////////////////////////////////
FUNCTION getEndOfMonth(date, m = 0)
	date = dateAdd("m", m + 1, date)
	GETTIME(0, date)
	GETTIME(-G_TIME_DD, date)
	RESULT = G_TIME_YY4 + "/" + G_TIME_MM2 + "/" + G_TIME_DD2
FEND

//////////////////////////////////////////////////
// 【引数】
//   date : 日付文字列(”YYYYMMDD” or “YYYY/MM/DD” or “YYYY-MM-DD” or “YYYYMMDDHHNNSS” or “YYYY/MM/DD HH:NN:SS”)もしくはシリアル値 
//   type : 取得する曜日番号の種類を示す0〜3または11〜17の値。1と17は日曜日を1、2と11は月曜日を1とカウントします。11以降はExcel2010で追加された値で、互換性を保つために重複した値があります。 
// 【戻り値】
//   typeで指定した種類によって以下の値を返します。 : (0 : 0(日曜)〜6(土曜)、1 : 1(日曜)~7(土曜)、2 : 1(月曜)~7(日曜)、3 : 0(月曜)〜6(日曜)、11 : 1(月曜)~7(日曜)、12 : 1(火曜)~7(月曜)、13 : 1(水曜)~7(火曜)、14 : 1(木曜)~7(水曜)、15 : 1(金曜)~7(木曜)、16 : 1(土曜)~7(金曜)、17 : 1(日曜)~7(土曜)) 
//////////////////////////////////////////////////
FUNCTION getWeekday(date, type = 1)
	IF VARTYPE(date) <> 258 THEN date = text(date, "yyyy/mm/dd")
	GETTIME(0, date)
	DIM w = G_TIME_WW
	SELECT TRUE
		CASE type = 0
			RESULT = w
		CASE type = 1
			RESULT = w + 1
		CASE type = 2
			RESULT = IIF(w=0, 7, w)
		CASE type = 3
			RESULT = (w+6) MOD 7
		CASE type >= 11
			RESULT = ((getWeekday(date, 2) + 17 - type) MOD 7) + 1
	SELEND
FEND

//////////////////////////////////////////////////
// 【引数】
//   serial : シリアル値もしくは時刻文字列 
// 【戻り値】
//   時刻から時間を表す0〜23の範囲の値 
//////////////////////////////////////////////////
FUNCTION Hour(serial)
	IF VARTYPE(serial) = 258 THEN serial = timeValue(serial)
	RESULT = INT(serial * 24) MOD 24
FEND

//////////////////////////////////////////////////
// 【引数】
//   expr : 評価する式 
//   truepart : 評価した式がTrueのときに返す値 
//   falsepart : 評価した式がFalseのときに返す値 
// 【戻り値】
//   truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき 
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
	IFB EVAL(expr) THEN
		RESULT = truepart
	ELSE
		RESULT = falsepart
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   date : 存在するかを調べる日付文字列。YYYYMMDD or YYYY/MM/DD or YYYY-MM-DDのいずれかの形式。 
// 【戻り値】
//   TRUE : 日付として認識できる、FALSE : 日付として認識できない 
//////////////////////////////////////////////////
FUNCTION isDate(date)
	TRY
		GETTIME(0, date)
		RESULT = TRUE
	EXCEPT
		RESULT = FALSE
	ENDTRY
FEND

//////////////////////////////////////////////////
// 【引数】
//   text : JSONとして解析する文字列 
//   value : JSON文字列に変換する値 
//   reviver : 使用不可 
//   replacer : 使用不可 
//   space : 出力するJSON文字列に空白を挿入するための文字列もしくは数値 
// 【戻り値】
//    : Parse : JSON文字列をオブジェクトに変換、 
//   Stringify : オブジェクトをJSON文字列に変換、 : 
//////////////////////////////////////////////////
MODULE JSON
	DIM SC, CodeObject
	PROCEDURE JSON
		SC = CREATEOLEOBJ("ScriptControl")
		WITH SC
			.Language = "JScript"
			.ExecuteStatement(json2)
			.ExecuteStatement("Array.prototype.Item = function(i, value){if(value === undefined) return this[i]; this[i] = value;}")
			CodeObject = .CodeObject
		ENDWITH
	FEND
	FUNCTION Parse(text, reviver = NULL)
		RESULT = CodeObject.JSON.parse(text, reviver)
	FEND
	FUNCTION Stringify(value, replacer = NULL, space = "")
		RESULT = CodeObject.JSON.stringify(value, replacer, space)
		IF space <> "" THEN RESULT = REPLACE(RESULT, CHR(10), "<#CR>")
	FEND
ENDMODULE

TEXTBLOCK json2
//  json2.js
//  2023-05-10
//  Public Domain.
//  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

//  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
//  NOT CONTROL.

//  This file creates a global JSON object containing two methods: stringify
//  and parse. This file provides the ES5 JSON capability to ES3 systems.
//  If a project might run on IE8 or earlier, then this file should be included.
//  This file does nothing on ES5 systems.

//      JSON.stringify(value, replacer, space)
//          value       any JavaScript value, usually an object or array.
//          replacer    an optional parameter that determines how object
//                      values are stringified for objects. It can be a
//                      function or an array of strings.
//          space       an optional parameter that specifies the indentation
//                      of nested structures. If it is omitted, the text will
//                      be packed without extra whitespace. If it is a number,
//                      it will specify the number of spaces to indent at each
//                      level. If it is a string (such as "\t" or " "),
//                      it contains the characters used to indent at each level.
//          This method produces a JSON text from a JavaScript value.
//          When an object value is found, if the object contains a toJSON
//          method, its toJSON method will be called and the result will be
//          stringified. A toJSON method does not serialize: it returns the
//          value represented by the name/value pair that should be serialized,
//          or undefined if nothing should be serialized. The toJSON method
//          will be passed the key associated with the value, and this will be
//          bound to the value.

//          For example, this would serialize Dates as ISO strings.

//              Date.prototype.toJSON = function (key) {
//                  function f(n) {
//                      // Format integers to have at least two digits.
//                      return (n < 10)
//                          ? "0" + n
//                          : n;
//                  }
//                  return this.getUTCFullYear()   + "-" +
//                       f(this.getUTCMonth() + 1) + "-" +
//                       f(this.getUTCDate())      + "T" +
//                       f(this.getUTCHours())     + ":" +
//                       f(this.getUTCMinutes())   + ":" +
//                       f(this.getUTCSeconds())   + "Z";
//              };

//          You can provide an optional replacer method. It will be passed the
//          key and value of each member, with this bound to the containing
//          object. The value that is returned from your method will be
//          serialized. If your method returns undefined, then the member will
//          be excluded from the serialization.

//          If the replacer parameter is an array of strings, then it will be
//          used to select the members to be serialized. It filters the results
//          such that only members with keys listed in the replacer array are
//          stringified.

//          Values that do not have JSON representations, such as undefined or
//          functions, will not be serialized. Such values in objects will be
//          dropped; in arrays they will be replaced with null. You can use
//          a replacer function to replace those with JSON values.

//          JSON.stringify(undefined) returns undefined.

//          The optional space parameter produces a stringification of the
//          value that is filled with line breaks and indentation to make it
//          easier to read.

//          If the space parameter is a non-empty string, then that string will
//          be used for indentation. If the space parameter is a number, then
//          the indentation will be that many spaces.

//          Example:

//          text = JSON.stringify(["e", {pluribus: "unum"}]);
//          // text is '["e",{"pluribus":"unum"}]'

//          text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
//          // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

//          text = JSON.stringify([new Date()], function (key, value) {
//              return this[key] instanceof Date
//                  ? "Date(" + this[key] + ")"
//                  : value;
//          });
//          // text is '["Date(---current time---)"]'

//      JSON.parse(text, reviver)
//          This method parses a JSON text to produce an object or array.
//          It can throw a SyntaxError exception.

//          The optional reviver parameter is a function that can filter and
//          transform the results. It receives each of the keys and values,
//          and its return value is used instead of the original value.
//          If it returns what it received, then the structure is not modified.
//          If it returns undefined then the member is deleted.

//          Example:

//          // Parse the text. Values that look like ISO date strings will
//          // be converted to Date objects.

//          myData = JSON.parse(text, function (key, value) {
//              var a;
//              if (typeof value === "string") {
//                  a =
//   /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
//                  if (a) {
//                      return new Date(Date.UTC(
//                         +a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]
//                      ));
//                  }
//                  return value;
//              }
//          });

//          myData = JSON.parse(
//              "[\"Date(09/09/2001)\"]",
//              function (key, value) {
//                  var d;
//                  if (
//                      typeof value === "string"
//                      && value.slice(0, 5) === "Date("
//                      && value.slice(-1) === ")"
//                  ) {
//                      d = new Date(value.slice(5, -1));
//                      if (d) {
//                          return d;
//                      }
//                  }
//                  return value;
//              }
//          );

//  This is a reference implementation. You are free to copy, modify, or
//  redistribute.

/*jslint
    eval, for, this
*/

/*property
    JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== "object") {
    JSON = {};
}

(function () {
    "use strict";

    var rx_one = /^[\],:{}\s]*$/;
    var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
    var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
    var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
    var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

    function f(n) {
        // Format integers to have at least two digits.
        return (n < 10)
            ? "0" + n
            : n;
    }

    function this_value() {
        return this.valueOf();
    }

    if (typeof Date.prototype.toJSON !== "function") {

        Date.prototype.toJSON = function () {

            return isFinite(this.valueOf())
                ? (
                    this.getUTCFullYear()
                    + "-"
                    + f(this.getUTCMonth() + 1)
                    + "-"
                    + f(this.getUTCDate())
                    + "T"
                    + f(this.getUTCHours())
                    + ":"
                    + f(this.getUTCMinutes())
                    + ":"
                    + f(this.getUTCSeconds())
                    + "Z"
                )
                : null;
        };

        Boolean.prototype.toJSON = this_value;
        Number.prototype.toJSON = this_value;
        String.prototype.toJSON = this_value;
    }

    var gap;
    var indent;
    var meta;
    var rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        rx_escapable.lastIndex = 0;
        return rx_escapable.test(string)
            ? "\"" + string.replace(rx_escapable, function (a) {
                var c = meta[a];
                return typeof c === "string"
                    ? c
                    : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
            }) + "\""
            : "\"" + string + "\"";
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i;          // The loop counter.
        var k;          // The member key.
        var v;          // The member value.
        var length;
        var mind = gap;
        var partial;
        var value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (
            value
            && typeof value === "object"
            && typeof value.toJSON === "function"
        ) {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === "function") {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case "string":
            return quote(value);

        case "number":

// JSON numbers must be finite. Encode non-finite numbers as null.

            return (isFinite(value))
                ? String(value)
                : "null";

        case "boolean":
        case "null":

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is "object", we might be dealing with an object or an array or
// null.

        case "object":

// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.

            if (!value) {
                return "null";
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === "[object Array]") {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || "null";
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0
                    ? "[]"
                    : gap
                        ? (
                            "[\n"
                            + gap
                            + partial.join(",\n" + gap)
                            + "\n"
                            + mind
                            + "]"
                        )
                        : "[" + partial.join(",") + "]";
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === "object") {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === "string") {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (
                                (gap)
                                    ? ": "
                                    : ":"
                            ) + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (
                                (gap)
                                    ? ": "
                                    : ":"
                            ) + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0
                ? "{}"
                : gap
                    ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
                    : "{" + partial.join(",") + "}";
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== "function") {
        meta = {    // table of character substitutions
            "\b": "\\b",
            "\t": "\\t",
            "\n": "\\n",
            "\f": "\\f",
            "\r": "\\r",
            "\"": "\\\"",
            "\\": "\\\\"
        };
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = "";
            indent = "";

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === "number") {
                for (i = 0; i < space; i += 1) {
                    indent += " ";
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === "string") {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== "function" && (
                typeof replacer !== "object"
                || typeof replacer.length !== "number"
            )) {
                throw new Error("JSON.stringify");
            }

// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.

            return str("", {"": value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== "function") {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k;
                var v;
                var value = holder[key];
                if (value && typeof value === "object") {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            rx_dangerous.lastIndex = 0;
            if (rx_dangerous.test(text)) {
                text = text.replace(rx_dangerous, function (a) {
                    return (
                        "\\u"
                        + ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
                    );
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with "()" and "new"
// because they can cause invocation, and "=" because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
// replace all simple value tokens with "]" characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or "]" or
// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

            if (
                rx_one.test(
                    text
                        .replace(rx_two, "@")
                        .replace(rx_three, "]")
                        .replace(rx_four, "")
                )
            ) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval("(" + text + ")");

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return (typeof reviver === "function")
                    ? walk({"": j}, "")
                    : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError("JSON.parse");
        };
    }
}());
ENDTEXTBLOCK

//////////////////////////////////////////////////
// 【引数】
//   str : 正規表現による検索の対象となる文字列 
//   Pattern : 正規表現で使用するパターンを設定 
//   IgnoreCase : 大文字・小文字を区別しない場合はTrue、区別する場合はFalse 
//   Global : 文字列全体を検索する場合はTrue、しない場合はFalse 
// 【戻り値】
//   正規表現で検索した結果をMatchesコレクションとして返します。 
//////////////////////////////////////////////////
FUNCTION reExecute(str, Pattern, IgnoreCase = TRUE, Global = TRUE)
	DIM re = CREATEOLEOBJ("VBScript.RegExp")
	re.Pattern = Pattern
	re.IgnoreCase = IgnoreCase
	re.Global = Global
	RESULT = re.Execute(str)
FEND

//////////////////////////////////////////////////
// 【引数】
//   str : 正規表現による検索の対象となる文字列 
//   Pattern : 正規表現で使用するパターンを設定 
//   IgnoreCase : 大文字・小文字を区別しない場合はTrue、区別する場合はFalse 
//   Global : 文字列全体を検索する場合はTrue、しない場合はFalse 
// 【戻り値】
//   正規表現にマッチするかどうかを示すブール値 
//////////////////////////////////////////////////
FUNCTION reTest(str, Pattern, IgnoreCase = TRUE, Global = TRUE)
	DIM re = CREATEOLEOBJ("VBScript.RegExp")
	re.Pattern = Pattern
	re.IgnoreCase = IgnoreCase
	re.Global = Global
	RESULT = re.Test(str)
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 数値 
//   digit : 四捨五入する位置(マイナスで整数方向) 
// 【戻り値】
//   四捨五入した値 
//////////////////////////////////////////////////
FUNCTION roundOff(num, digit = 0)
	DIM sign = sign(num)
	num = ABS(num)
	DIM offset = POWER(10, digit)
	DIM n = num * offset - INT(num * offset)
	RESULT = sign * IIF(n >= 0.5, CEIL(num * offset) / offset, INT(num * offset) / offset)
FEND

//////////////////////////////////////////////////
// 【引数】
//   serial : 時間を表すシリアル値を指定 
// 【戻り値】
//   
//////////////////////////////////////////////////
FUNCTION Second(serial)
	RESULT = REPLACE(FORMAT(INT(serial * 86400) MOD 60, 2), " ", "0")
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 符号を求める数値 
// 【戻り値】
//   1 : 正の数、0 : ゼロ、-1 : 負の数、ERR_VALUE : それ以外 
//////////////////////////////////////////////////
FUNCTION sign(num)
	SELECT TRUE
		CASE !CHKNUM(num)
			RESULT = ERR_VALUE
		CASE num > 0
			RESULT = 1
		CASE num = 0
			RESULT = 0
		CASE num < 0
			RESULT = -1
	SELEND
FEND

//////////////////////////////////////////////////
// 【引数】
//   inputs : 繰り返す文字列 
//   multiplier : inputsを繰り返す回数 
// 【戻り値】
//   inputsをmultiplier回を繰り返した文字列を返します 
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
	DIM res = ""
	FOR n = 1 TO multiplier
		res = res + inputs
	NEXT
	RESULT = res
FEND

//////////////////////////////////////////////////
// 【引数】
//   serial : シリアル値 
//   format : フォーマット 
// 【戻り値】
//   数値を表示書式に基づいて変換した文字列 
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// 【引数】
//   serial : シリアル値 
//   format : フォーマット 
// 【戻り値】
//   
//////////////////////////////////////////////////
FUNCTION text(serial, format, hour12 = FALSE)
	HASHTBL startDate
	startDate["明治"] = "1868/01/25"
	startDate["大正"] = "1912/07/30"
	startDate["昭和"] = "1926/12/25"
	startDate["平成"] = "1989/01/08"
	startDate["令和"] = "2019/05/01"
	
	DIM baseDate = "1899/12/30"
	serial = VAL(serial)
	SELECT TRUE
		CASE reTest(format, "\[h+\]")
			Matches = reExecute(format, "\[(h+)\]")
			DIM hour = iif(hour12, Hour(serial) MOD 12, Hour(serial))
			RESULT = text(hour, strRepeat("0", LENGTH(Matches.Item(0).SubMatches(0))))
		CASE reTest(format, "^h+$")
			Matches = reExecute(format, "^(h+)$")
			hour = iif(hour12, Hour(serial) MOD 12, Hour(serial))
			RESULT = text(hour MOD 24, strRepeat("0", LENGTH(Matches.Item(0).SubMatches(0))))
		CASE reTest(format, "\[m+\]")
			Matches = reExecute(format, "\[(m+)\]")
			RESULT = text(serial * 1440, strRepeat("0", LENGTH(Matches.Item(0).SubMatches(0))))
		CASE format = "m"
			GETTIME(serial, baseDate)
			RESULT = text(G_TIME_MM, "0")
		CASE format = "mm"
			GETTIME(serial, baseDate)
			RESULT = G_TIME_MM2
		CASE format = "n"
			GETTIME(serial, baseDate)
			RESULT = G_TIME_NN
		CASE format = "nn"
			GETTIME(serial, baseDate)
			RESULT = G_TIME_NN2
		CASE format = "s"
			GETTIME(serial, baseDate)
			RESULT = text(G_TIME_SS, "0")
		CASE format = "ss"
			GETTIME(serial, baseDate)
			RESULT = G_TIME_SS2
		CASE format = "yyyy"
			GETTIME(serial, baseDate)
			RESULT = G_TIME_YY4
		CASE format = "yy"
			GETTIME(serial, baseDate)
			RESULT = COPY(G_TIME_YY4, 3, 2)
		CASE format = "e"
			SELECT TRUE
				CASE dateDiff("d", startDate["令和"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(serial, "yyyy") - 2018
				CASE dateDiff("d", startDate["平成"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(serial, "yyyy") - 1988
				CASE dateDiff("d", startDate["昭和"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(serial, "yyyy") - 1925
				CASE dateDiff("d", startDate["大正"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(serial, "yyyy") - 1911
				CASE dateDiff("d", startDate["明治"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(serial, "yyyy") - 1867
			SELEND
		CASE format = "ee"
			SELECT TRUE
				CASE dateDiff("d", startDate["令和"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(text(serial, "yyyy") - 2018, "00")
				CASE dateDiff("d", startDate["平成"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(text(serial, "yyyy") - 1988, "00")
				CASE dateDiff("d", startDate["昭和"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(text(serial, "yyyy") - 1925, "00")
				CASE dateDiff("d", startDate["大正"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(text(serial, "yyyy") - 1911, "00")
				CASE dateDiff("d", startDate["明治"], text(serial, "yyyy/mm/dd")) >= 0
					RESULT = text(text(serial, "yyyy") - 1867, "00")
			SELEND
		CASE format = "g"
			SELECT TRUE
				CASE dateDiff("d", startDate["令和"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "R"
				CASE dateDiff("d", startDate["平成"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "H"
				CASE dateDiff("d", startDate["昭和"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "S"
				CASE dateDiff("d", startDate["大正"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "T"
				CASE dateDiff("d", startDate["明治"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "M"
			SELEND
		CASE format = "gg"
			RESULT = COPY(text(serial, "ggg"), 1, 1)
		CASE format = "ggg"
			SELECT TRUE
				CASE dateDiff("d", startDate["令和"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "令和"
				CASE dateDiff("d", startDate["平成"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "平成"
				CASE dateDiff("d", startDate["昭和"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "昭和"
				CASE dateDiff("d", startDate["大正"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "大正"
				CASE dateDiff("d", startDate["明治"], text(serial, "yyyy/mm/dd")) >= 0;		RESULT = "明治"
			SELEND
		CASE format = "mmmmm"
			RESULT = COPY(text(serial, "mmmm"), 1, 1)
		CASE format = "mmmm"
			DIM month[] = "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
			RESULT = month[text(serial, "m") - 1]
		CASE format = "mmm"
			RESULT = COPY(text(serial, "mmmm"), 1, 3)
		CASE format = "dd"
			GETTIME(serial, baseDate)
			RESULT = text(G_TIME_DD2, "00")
		CASE format = "d"
			GETTIME(serial, baseDate)
			RESULT = text(G_TIME_DD, "0")
		CASE reTest(format, "^[ad]{3,4}$")
			Matches = reExecute(format, "([ad]{3,4})")
			GETTIME(serial, baseDate)
			DIM aaa[] = "日", "月", "火", "水", "木", "金", "土"
			DIM aaaa[] = "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"
			DIM ddd[] = "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
			DIM dddd[] = "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday";
			RESULT = EVAL(Matches.Item(0).SubMatches(0) + "[" + getWeekday(G_TIME_WW, 1) + "]")
		CASE reTest(format, "(0+\.?0+)?%")
			Matches = reExecute(format, "(0+\.?0+)?%")
			RESULT = text(serial * 100, Matches.Item(0).SubMatches(0)) + "%"
		CASE reTest(format, "^\[DBNum\d{1,4}\](.*?)$")
			Matches = reExecute(format, "^\[DBNum(\d{1,4})\](.*?)$")
			DIM value = VAL(Matches.Item(0).SubMatches(0))
			DIM sss = text(serial, Matches.Item(0).SubMatches(1))
			Matches = reExecute(sss, "(\D+)?(\d+)(\D+)?")
			DIM res = ""
			FOR m = 0 TO Matches.Count - 1
				serial = Matches.Item(m).SubMatches(1)
				SELECT value
					CASE 1, 2
						DIM n[][9] = "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九", + _
										"", "壱", "弐", "参", "四", "伍", "六", "七", "八", "九"
						DIM a[][3] = "", "十", "百", "千", + _
										"", "拾", "百", "阡"
						DIM b[][3] = "", "万", "億", "兆", + _
										"", "萬", "億", "兆"
						DIM r = ""
						DIM j = 0
						type = value - 1
						REPEAT
							DIM str = ""
							DIM n4 = serial MOD 10000
							FOR i = LENGTH(n4) TO 1 STEP -1
								s = COPY(n4, i, 1)
								IFB s = 1 AND a[type][LENGTH(n4)-i] <> "" THEN
									str = IIF(s, a[type][LENGTH(n4)-i], "") + str
								ELSE	
									str = n[type][s] + IIF(s, a[type][LENGTH(n4)-i], "") + str
								ENDIF
							NEXT
							IF str <> "" THEN r = str + b[type][j] + r
							j = j + 1
							serial = INT(serial / 10000)
						UNTIL serial = 0
						res = res + Matches.Item(m).SubMatches(0) + r + Matches.Item(m).SubMatches(2)
					CASE 3
						res = res + Matches.Item(m).SubMatches(0) + STRCONV(serial, SC_FULLWIDTH) + Matches.Item(m).SubMatches(2)
					CASE 4
						res = res + Matches.Item(m).SubMatches(0) + STRCONV(serial, SC_HALFWIDTH) + Matches.Item(m).SubMatches(2)
				SELEND
			NEXT
			RESULT = res
		CASE reTest(format, "^(.*?)(AM\/PM|am\/pm|A\/P|a\/p)(.*?)$")
			Matches = reExecute(format, "^(.*?)(AM\/PM|am\/pm|A\/P|a\/p)(.*?)$")
			DIM array = SPLIT(Matches.Item(0).SubMatches(1), "/")
			ampm = array[IIF(serial - INT(serial) >= 0.5, 1, 0)]
			hour12 = TRUE
			res = ""
			WITH Matches.Item(0)
				res = text(serial, .SubMatches(0), hour12) + ampm + text(serial, .SubMatches(2), hour12)
			ENDWITH
			RESULT = res
		CASE reTest(format, "([^ymdagehns]{0,})?(([ymdagehns])\3{0,})([^ymdagehns]+)?")
			Matches = reExecute(format, "([^ymdagehns]{0,})?(([ymdagehns])\3{0,})([^ymdagehns]+)?")
			FOR n = 0 TO Matches.Count - 1
				IF n = 0 THEN res = Matches.Item(n).SubMatches(0)
			NEXT
			FOR n = 0 TO Matches.Count - 1
				WITH Matches.Item(n)
					res = res + text(serial, .SubMatches(1), hour12) + .SubMatches(3)
				ENDWITH
			NEXT
			RESULT = res
		CASE format = "0/0"
			DIM separator = POS(".", serial)
			DIM g = 0
			IFB separator <> 0 THEN
				DIM keta = LENGTH(serial)
				DIM shift = POWER(10, keta - separator)
				IFB shift >= POWER(10, 15) THEN
					DIM position = 0
					FOR i = 0 TO 14
						IFB serial * POWER(10, i) - serial >= 1 THEN
							position = i
							BREAK
						ENDIF
					NEXT
					tmp = serial * POWER(10, position)
					FOR i = 1 TO 15
						r = (tmp * POWER(10, i)) / serial - (tmp / serial)
						a1 = tmp * POWER(10, i) - tmp
						IF a1 = INT(a1) THEN BREAK 
					NEXT
					DIM frac[] = a1, r
					g = GCD(frac)
					RESULT = (a1/g) + "/" + (r/g)
				ELSE
					DIM molecule = serial * shift	// 分子
					DIM denominator = shift		// 分母
					DIM nums[] = molecule, denominator
					g = GCD(nums)
					molecule = molecule / g
					denominator = denominator / g
					RESULT = molecule + "/" + denominator
				ENDIF
			ELSE
				RESULT = serial + "/1"
			ENDIF
		CASE reTest(format, "(0+)\.?(0+)?") AND UBound(SPLIT(format, ".")) <= 1 
			Matches = reExecute(format, "(0+)\.?(0+)?")
			len1 = LENGTH(Matches.Item(0).SubMatches(0))
			len2 = LENGTH(Matches.Item(0).SubMatches(1))
			DIM arr[] = LENGTH(INT(serial)), len1
			IFB POS(".", format) THEN
				RESULT = REPLACE(FORMAT(serial, CALCARRAY(arr, CALC_MAX) + len2 + 1, len2), " ", "0")
			ELSE
				RESULT = REPLACE(FORMAT(serial, CALCARRAY(arr, CALC_MAX)), " ", "0")
			ENDIF
	SELEND
FEND

//////////////////////////////////////////////////
// 【引数】
//   str : 時刻文字列。hh:nn:ss AM/PM、hh:nn AM/PM、hh AM/PM、hh:nn:ss、hh:nn、hh時nn分ss秒、hh時nn分のいずれかの形式を指定。 
// 【戻り値】
//   シリアル値 (例)0…00:00:00、0.5…12:00:00、0.999988425925926…23:59:59 
//////////////////////////////////////////////////
FUNCTION timeValue(str)
	DIM serial = 0
	DIM Matches
	DIM pattern = "(\d+)"
	DIM hh = "(0?[0-9]|1[0-2])"
	DIM ampm = "([AP]M|[ap]m)"
	SELECT TRUE
		CASE reTest(str, "\b" + hh + ":" + pattern + ":" + pattern + " " + ampm + "\b")
			Matches = reExecute(str, "\b" + hh + ":" + pattern + ":" + pattern + " " + ampm + "\b")
			WITH Matches.Item(0)
				serial = timeValue(.SubMatches(0) + " " + .SubMatches(3)) + VAL(.SubMatches(1)) / 1440 + VAL(.SubMatches(2)) / 86400
			ENDWITH
		CASE reTest(str, "\b" + hh + ":" + pattern + " " + ampm + "\b")
			Matches = reExecute(str, "\b" + hh + ":" + pattern + " " + ampm + "\b")
			WITH Matches.Item(0)
				serial = timeValue(.SubMatches(0) + " " + .SubMatches(2)) + VAL(.SubMatches(1)) / 1440
			ENDWITH
		CASE reTest(str, "\b" + hh + " " + ampm + "\b")
			Matches = reExecute(str, "\b" + hh + " " + ampm + "\b")
			WITH Matches.Item(0)
				serial = VAL(.SubMatches(0) MOD 12) + IIF(reTest(.SubMatches(1), "AM|am"), 0, 12)
				serial = serial / 24
			ENDWITH
		CASE reTest(str, "\b" + pattern + ":" + pattern + ":" + pattern + "\b")
			Matches = reExecute(str, "\b" + pattern + ":" + pattern + ":" + pattern + "\b")
			WITH Matches.Item(0)
				serial = VAL(.SubMatches(0)) / 24 + VAL(.SubMatches(1)) / 1440 + VAL(.SubMatches(2)) / 86400
			ENDWITH
		CASE reTest(str, "\b" + pattern + ":" + pattern + "\b")
			Matches = reExecute(str, "\b" + pattern + ":" + pattern + "\b")
			WITH Matches.Item(0)
				serial = VAL(.SubMatches(0)) / 24 + VAL(.SubMatches(1)) / 1440
			ENDWITH
		CASE reTest(str, "\b" + pattern + "時" + pattern + "分" + pattern + "秒")
			Matches = reExecute(str, "\b" + pattern + "時" + pattern + "分" + pattern + "秒")
			WITH Matches.Item(0)
				serial = VAL(.SubMatches(0)) / 24 + VAL(.SubMatches(1)) / 1440 + VAL(.SubMatches(2)) / 86400
			ENDWITH
		CASE reTest(str, "\b" + pattern + "時" + pattern + "分")
			Matches = reExecute(str, "\b" + pattern + "時" + pattern + "分")
			WITH Matches.Item(0)
				serial = VAL(.SubMatches(0)) / 24 + VAL(.SubMatches(1)) / 1440
			ENDWITH
		DEFAULT
			serial = ERR_VALUE
	SELEND
	RESULT = serial - INT(serial)
FEND

//////////////////////////////////////////////////
// 【引数】
//   arrayname : 上限値を求める配列の名前 
//   dimension : 返す次元を示す整数 
// 【戻り値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(arrayname[], dimension = 1)
	RESULT = EVAL("RESIZE(arrayname" + strRepeat("[0]", dimension - 1) + ")")
FEND

//////////////////////////////////////////////////
// 【引数】
//   path 
//   destination 
// 【戻り値】
//   
//////////////////////////////////////////////////
PROCEDURE UnZip(path, destination = "")
	DIM FSO = CREATEOLEOBJ("Scripting.FileSystemObject")
	DIM folderspec = FSO.GetParentFolderName(path)
	DIM filename = FSO.GetFileName(path)
	IF destination = "" THEN destination = folderspec
	POWERSHELL("Set-Location " + folderspec + "; Expand-Archive " + filename + " -DestinationPath " + destination + " -Force")
FEND

//////////////////////////////////////////////////
// 【引数】
//   version1 : 1つ目のバージョン 
//   version2 : 2つ目のバージョン 
//   operator : <、<=、>、>=、=、<>のいずれかの演算子 
// 【戻り値】
//   1つ目のバージョンが2つ目のバージョンより小さい場合-1、同じ場合0、2つ目のバージョンが小さい場合1を返します。演算子を指定したときは、演算子の関係を満たす場合True、満たさない場合はFalseを返します。 
//////////////////////////////////////////////////
FUNCTION versionCompare(version1, version2, operator = EMPTY)
	DIM array1 = SPLIT(version1, ".")
	DIM array2 = SPLIT(version2, ".")
	IFB LENGTH(array1) <> LENGTH(array2) THEN
		RESULT = ERR_VALUE
		EXIT
	ENDIF
	IFB operator = EMPTY THEN
		FOR i = 0 TO UBound(array1)
			IFB array1[i] < array2[i] THEN
				RESULT = -1
				EXIT
			ELSEIF array1[i] > array2[i] THEN
				RESULT = 1
				EXIT
			ENDIF
		NEXT
		RESULT = 0
	ELSE
		FOR i = 0 TO UBound(array1)
			IFB array1[i] <> array2[i] THEN
				RESULT = EVAL("array1[i] " + operator + " array2[i]")
				EXIT
			ENDIF
		NEXT
		IFB POS("=", operator) THEN
			RESULT = TRUE
		ELSE
			RESULT = FALSE
		ENDIF
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   bit64 : Chromeブラウザが64bitの場合はTrue、32bitの場合はFalseを指定。省略した場合、インストール先のフォルダパスから判断。 
//   force : 現在インストールされているドライバーとバージョンが一致しても強制的にインストール処理を行う場合、Trueを指定 
// 【戻り値】
//   
//////////////////////////////////////////////////
MODULE WebDriverDownload
	DIM WshShell = CREATEOLEOBJ("WScript.Shell")
	DIM folderspec = WshShell.ExpandEnvironmentStrings("%LOCALAPPDATA%\SeleniumBasic\")
	PROCEDURE Chrome(bit64, force = FALSE)
		DIM browserVersion = ChromeBrowserVersion()
		IF browserVersion = READINI("Chrome", "version", folderspec + "WebDriverVersion.ini") AND !force THEN EXIT
		DIM bit = IIF(bit64, "64", "32")
		WRITEINI("Chrome", "bit", bit, folderspec + "WebDriverVersion.ini")
		DIM driverVersion = ChromeDriverVersion(browserVersion)
		DIM driverURL = ChromeDriverURL(driverVersion, bit)
		WRITEINI("Chrome", "DriverURL", driverURL, folderspec + "WebDriverVersion.ini")
		InstallChromeDriver(driverURL, bit)
		WRITEINI("Chrome", "version", browserVersion, folderspec + "WebDriverVersion.ini")
	FEND
	FUNCTION ChromeBrowserVersion()
		TRY
			DIM path = WshShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe\Path")
		EXCEPT
			PRINT "Google Chromeがインストールされていません"
			EXIT
		ENDTRY
		RESULT = TRIM(DOSCMD("DIR /B /O-N <#DBL>" + path + "<#DBL> | FINDSTR <#DBL>^[0-9].*¥>"))
	FEND
	FUNCTION ChromeDriverVersion(version)
		DIM major = SPLIT(version, ".")[0]
		IFB major >= 115 THEN
			DIM url = "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_" + major
		ELSE
			url = "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_" + major
		ENDIF
		WITH CREATEOLEOBJ("Msxml2.XMLHTTP")
			.Open("GET", url, FALSE)
			.Send()
			RESULT = .ResponseText
		ENDWITH
	FEND
	FUNCTION ChromeDriverURL(browserVersion, bit)
		DIM driverVersion = ChromeDriverVersion(browserVersion)
		DIM major = SPLIT(browserVersion, ".")[0]
		IFB versionCompare(driverVersion, "121.0.6167.184", ">=") THEN
			RESULT = "https://storage.googleapis.com/chrome-for-testing-public/" + driverVersion + "/win" + bit + "/chromedriver-win" + bit + ".zip"
		ELSEIF major >= 115 THEN
			RESULT = "https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/" + driverVersion + "/win" + bit + "/chromedriver-win" + bit + ".zip"
		ELSE
			RESULT = "https://chromedriver.storage.googleapis.com/" + driverVersion + "/chromedriver_win32.zip"
		ENDIF
	FEND
	PROCEDURE InstallChromeDriver(driverURL, bit)
		DIM filename = "chromedriver.zip"
		IF Download(driverURL, folderspec, filename) THEN UnZip(folderspec + filename)
		path = folderspec + "chromedriver-win" + bit + "\chromedriver.exe"
		WITH CREATEOLEOBJ("Scripting.FileSystemObject")
			.CopyFile(path, folderspec, TRUE)
			.DeleteFolder(.GetParentFolderName(path))
		ENDWITH
	FEND
	PROCEDURE Firefox(force = FALSE)
		DIM driverVersion = FireFoxDriverVersion()
		IF driverVersion = READINI("Firefox", "DriverVersion", folderspec + "WebDriverVersion.ini") AND !force THEN EXIT
		DIM driverURL = FirefoxDriverURL(driverVersion)
		WRITEINI("Firefox", "DriverURL", driverURL, folderspec + "WebDriverVersion.ini")
		InstallFirefoxDriver(driverURL)
		WRITEINI("Firefox", "DriverVersion", driverVersion, folderspec + "WebDriverVersion.ini")
	FEND
	FUNCTION FireFoxDriverVersion()
		DIM versionURL = "https://api.github.com/repos/mozilla/geckodriver/tags"
		WITH CREATEOLEOBJ("Msxml2.XMLHTTP")
			.Open("GET", versionURL, FALSE)
			.Send()
			DIM json = .ResponseText
		ENDWITH
		DIM obj = JSON.Parse(json)
		RESULT = obj.Item(0).name
	FEND
	FUNCTION FirefoxDriverURL(driverVersion)
		TRY
			path = WshShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe\")
			DIM bit = IIF(POS("Program Files (x86)", path), 32, 64)
		EXCEPT
			PRINT "Firefoxがインストールされていません"
			EXIT
		ENDTRY
		RESULT = "https://github.com/mozilla/geckodriver/releases/download/" + driverVersion + "/geckodriver-" + driverVersion + "-win" + bit + ".zip"
	FEND
	PROCEDURE InstallFirefoxDriver(driverURL)
		DIM filename = "geckodriver.zip"
		IF Download(driverURL, folderspec , filename, TRUE) THEN UnZip(folderspec + filename)
	FEND
	PROCEDURE MsEdge(force = FALSE)
		DIM browserVersion = MsEdgeBrowserVersion()
		IF browserVersion = READINI("MsEdge", "version", folderspec + "WebDriverVersion.ini") AND !force THEN EXIT
		DIM driverVersion = MsEdgeDriverVersion(browserVersion)
		DIM driverURL = MsEdgeDriverURL(driverVersion)
		WRITEINI("MsEdge", "DriverURL", driverURL, folderspec + "WebDriverVersion.ini")
		InstallMsEdgeDriver(driverVersion, driverURL)
		WRITEINI("MsEdge", "version", browserVersion, folderspec + "WebDriverVersion.ini")
	FEND
	FUNCTION MsEdgeBrowserVersion()
		TRY
			path = WshShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\msedge.exe\")
		EXCEPT
			PRINT "Microsoft Edgeがインストールされていません"
			EXIT
		ENDTRY
		RESULT = TRIM(POWERSHELL("(get-item (<#DBL>" + path + "<#DBL>)).VersionInfo.FileVersion"))
	FEND
	FUNCTION MsEdgeDriverVersion(browserVersion)
		DIM major = TOKEN(".", browserVersion)
		DIM Request = Request("https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver/LATEST_RELEASE_" + major + "_WINDOWS")
		RESULT = TRIM(Request.responseText)
	FEND
	FUNCTION MsEdgeDriverURL(driverVersion)
		RESULT = "https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver/" + driverVersion + "/edgedriver_win" + IIF(KINDOFOS(TRUE), "64", "32") + ".zip"
	FEND
	PROCEDURE InstallMsEdgeDriver(driverVersion, driverURL)
		DIM filename = "msedgedriver." + driverVersion + ".zip"
		IF Download(driverURL, folderspec, filename) THEN UnZip(folderspec + filename)
	FEND
ENDMODULE

//////////////////////////////////////////////////
// ダウンロード
// url:URL、dir:ディレクトリ名、filename:ファイル名、isServerXMLHTTP:
//////////////////////////////////////////////////
FUNCTION Download(url, dir, filename, isServerXMLHTTP = FALSE)
	CONST adSaveCreateOverWrite = 2
	WITH CREATEOLEOBJ("ADODB.Stream")
		.Open()
		.Type = 1
		IF isServerXMLHTTP THEN
			obj = CREATEOLEOBJ("Msxml2.ServerXMLHTTP")
		ELSE
			obj = CREATEOLEOBJ("Msxml2.XMLHTTP")
		ENDIF
		obj.Open("GET", url, FALSE)
		obj.Send()
		.Write(obj.responseBody)
		.SaveToFile(dir + filename, adSaveCreateOverWrite)
		.Close()
	ENDWITH
	RESULT = FOPEN(dir + filename, F_EXISTS)
FEND

//////////////////////////////////////////////////
// 要求
// url:URL、isServerXMLHTTP:
//////////////////////////////////////////////////
FUNCTION Request(url, isServerXMLHTTP = FALSE)
	IFB isServerXMLHTTP THEN
		RESULT = CREATEOLEOBJ("Msxml2.ServerXMLHTTP")
	ELSE
		RESULT = CREATEOLEOBJ("Msxml2.XMLHTTP")
	ENDIF
	WITH RESULT
		.Open("GET", url, FALSE)
		.Send()
	ENDWITH
FEND
使用関数

参考文献

  1. Items.Restrict メソッド (Outlook) | Microsoft Learn
  2. https://platform.kobot.jp/support/solutions/articles/47001150388-outlook%E3%83%A1%E3%83%BC%E3%83%AB%E5%8F%96%E5%BE%97%E6%99%82%E3%81%AE%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6
  3. https://vicugna-pacos.github.io/vba/outlook/search-and-filter/
  4. Get Outlook Mail activity Filter with From AND Subject - Help - UiPath Community Forum
  5. Compoze Software API Documentation: Class HttpMailProperty

関連記事

MailItem オブジェクト
メールメッセージを表します。
MailItem.Attachments プロパティ (Outlook)
メールに添付されているすべての添付ファイルを表すOutlook.Restrictを返します。
MailItem.BodyFormat プロパティ (Outlook)
メール本文の形式を表すOlBodyFormatクラスの定数を取得または設定します。
MailItem.To プロパティ (Outlook)
Outlook アイテムの宛先の受信者の表示名一覧を表す、セミコロン(;)で区切られた文字列型(String) の一覧を設定します。
MailItem.HTMLBody プロパティ (Outlook)
メールのHTML形式の本文を表す文字列型の値を取得または設定します。
MailItem.Parent プロパティ (Outlook)
指定したオブジェクトの親オブジェクトを返します。
MailItem.ReceivedTime プロパティ (Outlook)
アイテムを受信した日付と時刻を示す日付型(Date)の値を取得します。
CDO.From プロパティ
メッセージの差出人(From)を指定します。
AppointmentItem オブジェクト
新しい予定を表すAppointmentItemオブジェクトを作成します。
Folder オブジェクト