QuotedPrintable

文字列をQuoted-Pintableにエンコード・デコードします。

Quoted-Printableとは、電子メールの送受信の際に用いられるデータの変換方式のひとつで、本文に用いられる8ビット文字を7ビットのデータであるASCIIコードに変換する方式のことです。

構文
  1. UString = QuotedPrintable.encode( str )
  2. UString = QuotedPrintable.decode( str )
引数
str
エンコード・デコードしたい文字列
戻り値
エンコード・デコードした文字列

プログラム

UWSC
//////////////////////////////////////////////////
// 【引数】
//   str : エンコード・デコードしたい文字列 
// 【戻値】
//   エンコード・デコードした文字列 
//////////////////////////////////////////////////
MODULE QuotedPrintable
FUNCTION encode(str)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
DIM Matches = reExecute(JISToSJIS(decToHex(ExcelFunction.CODE("<#DBL>" + s + "<#DBL>"))), "([0-9A-F]{2})([0-9A-F]{2})")
FOR m = 0 TO Matches.Count - 1
res = res + "=" + Matches.Item(m).SubMatches(0) + "=" + Matches.Item(m).SubMatches(1)
NEXT
NEXT
RESULT = res
FEND
FUNCTION decode(str)
DIM res = ""
DIM Matches = reExecute(str, "=([0-9A-F]{2})+")
DIM n = 0
WHILE n <= Matches.Count - 1
SELECT TRUE
CASE hexToDec(Matches.Item(n).SubMatches(0)) >= $81
res = res + ExcelFunction.CHAR(hexToDec(SJISToJIS(Matches.Item(n).SubMatches(0) + Matches.Item(n+1).SubMatches(0))))
n = n + 2
DEFAULT
res = res + ExcelFunction.CHAR(hexToDec(Matches.Item(n).SubMatches(0)))
n = n + 1
SELEND
WEND
RESULT = res
FEND
ENDMODULE
//////////////////////////////////////////////////
// 【引数】
//   bin : 2進数 
//   signFlg : 符号付きならばTrue 
// 【戻値】
//   10進数に変換した値 
//////////////////////////////////////////////////
FUNCTION binToDec(bin, signFlg = TRUE)
DIM dec = 0
DIM decimalFlg = IIF(POS(".", bin), TRUE, FALSE)
IFB COPY(bin, 1, 1) = "1" AND signFlg THEN
// 負数
// ビット反転用の値
// 最上位ビット
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
// 最下位ビット
DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
// 整数部
DIM dec2 = POWER(2, msb) - 1
// 小数部
FOR i = -1 TO lsb STEP -1
dec2 = dec2 + POWER(2, i)
NEXT
DIM a = binToDec(bin, FALSE)
DIM b = dec2
dec = -1 * (bitXor(a, b) + POWER(2, lsb))
ELSE
// 正数(先頭ビットが0、もしくは、signFlgがFalse)
IFB decimalFlg THEN
// 小数部分
DIM integer = COPY(bin, 1, POS(".", bin) - 1)
DIM decimal = COPY(bin, POS(".", bin) + 1)
FOR i = 1 TO LENGTH(decimal)
dec = dec + COPY(decimal, i, 1) * POWER(2, -1 * i)
NEXT
ELSE
integer = bin
ENDIF
// 整数部分
FOR i = 1 TO LENGTH(integer)
dec = dec + COPY(integer, i, 1) * POWER(2, LENGTH(integer) - i)
NEXT
ENDIF
RESULT = dec
FEND
//////////////////////////////////////////////////
// 【引数】
//   arg1 : 数値1(10進数) 
//   arg2 : 数値2(10進数) 
// 【戻値】
//   2つの数値のビット毎の排他的論理和 
//////////////////////////////////////////////////
FUNCTION bitXor(arg1, arg2)
DIM args[1] = arg1, arg2
DIM bins[1]
DIM decimals[1]
DIM integers[1]
DIM keta[1]
IFB ABS(arg1) <> arg1 OR ABS(arg2) <> arg2 THEN
RESULT = ERR_VALUE
EXIT
ENDIF
FOR i = 0 TO 1
bins[i] = decToBin(args[i])
decimals[i] = 0
IFB POS(".", bins[i]) <> 0 THEN
integers[i] = COPY(bins[i], 1, POS(".", bins[i]) - 1)
decimals[i] = COPY(bins[i], POS(".", bins[i]) + 1)
ELSE
integers[i] = bins[i]
ENDIF
NEXT
keta[0] = IIF(LENGTH(integers[0]) > LENGTH(integers[1]), LENGTH(integers[0]), LENGTH(integers[1]))
integers[0] = strPad(integers[0], keta[0], "0", LEFT)
integers[1] = strPad(integers[1], keta[0], "0", LEFT)
keta[1] = IIF(LENGTH(decimals[0]) > LENGTH(decimals[1]), LENGTH(decimals[0]), LENGTH(decimals[1]))
decimals[0] = strPad(decimals[0], keta[1], "0", RIGHT)
decimals[1] = strPad(decimals[1], keta[1], "0", RIGHT)
DIM bin = ""
FOR i = 1 TO keta[0]
bin = bin + (VAL(COPY(integers[0], i, 1)) XOR VAL(COPY(integers[1], i, 1)))
NEXT
bin = bin + "."
FOR i = 1 TO keta[1]
bin = bin + (VAL(COPY(decimals[0], i, 1)) XOR VAL(COPY(decimals[1], i, 1)))
NEXT
RESULT = binToDec(bin)
FEND
//////////////////////////////////////////////////
// 【引数】
//   dec : 10進数 
//   signFlg : 符号付きならばTrue 
//   digits : 桁数 
//   recursive 
// 【戻値】
//   2進数に変換した値 
//////////////////////////////////////////////////
FUNCTION decToBin(dec, signFlg = FALSE, digits = FALSE, recursive = 1)
DIM bin = ""
DIM decimalFlg = IIF(POS(".", dec) <> 0, TRUE, FALSE)
DIM negativeFlg = IIF(dec < 0, TRUE, FALSE)
dec = ABS(dec)
DIM integer = IIF(decimalFlg, COPY(dec, 1, POS(".", dec) - 1), dec)
DIM offset = POWER(10, LENGTH(dec) - POS(".", dec))
DIM decimal = IIF(decimalFlg, COPY(dec, POS(".", dec) + 1) / offset, 0)
REPEAT
bin = (integer MOD 2) + bin
integer = INT(integer / 2)
UNTIL integer = 0
IFB decimalFlg THEN
bin = bin + "."
DIM loop = 0
REPEAT
loop = loop + 1
decimal = decimal * 2
bin = bin + IIF(decimal >= 1, "1", "0")
IF decimal > 1 THEN decimal = decimal - 1
UNTIL decimal = 1 OR loop >= 16
WHILE loop MOD 4 <> 0
loop = loop + 1
bin = bin + "0"
WEND
ENDIF
WHILE LENGTH(REPLACE(bin, ".", "")) MOD 8 <> 0
bin = "0" + bin
WEND
IFB negativeFlg THEN
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
DIM lsb = IIF(decimalFlg , POS(".", bin) - LENGTH(bin), 0)
DIM a = binToDec(bin)
DIM b = POWER(2, msb) - 1
FOR i = -1 TO lsb STEP -1
b = b + POWER(2, i)
NEXT
dec = bitXor(a, b) + POWER(2, lsb)
bin = decToBin(dec, signFlg, digits, recursive + 1)
ENDIF
IFB recursive = 1 THEN
DIM bit = COPY(bin, 1, 1)
DIM len = LENGTH(REPLACE(bin, ".", ""))
IF negativeFlg AND (bit = "0" OR len MOD 2 <> 0) THEN bin = strRepeat("1", IIF(len MOD 2 <> 0, 4, 8)) + bin
IF !negativeFlg AND (bit = "1" OR len MOD 2 <> 0) THEN bin = strRepeat("0", IIF(len MOD 2 <> 0, 4, 8)) + bin
ENDIF
RESULT = bin
FEND
//////////////////////////////////////////////////
// 【引数】
//   dec : 10進数 
//   signFlg : 符号付きならばTrue 
//   recursive : 再帰処理の深さ 
// 【戻値】
//   16進数に変換した値 
//////////////////////////////////////////////////
FUNCTION decToHex(dec, signFlg = FALSE, recursive = 1)
DIM hex = ""
DIM array[] = "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
DIM decimalFlg = IIF(POS(".", dec) <> 0, TRUE, FALSE)
DIM negativeFlg = IIF(dec < 0, TRUE, FALSE)
dec = ABS(dec)
DIM integer = IIF(decimalFlg, COPY(dec, 1, POS(".", dec) - 1), dec)
DIM offset = POWER(10, LENGTH(dec) - POS(".", dec))
DIM decimal = IIF(decimalFlg, COPY(dec, POS(".", dec) + 1) / offset, 0)
REPEAT
hex = array[integer MOD 16] + hex
integer = INT(integer / 16)
UNTIL integer = 0
IFB decimalFlg THEN
hex = hex + "."
DIM loop = 0
REPEAT
loop = loop + 1
decimal = decimal * 16
hex = hex + array[decimal]
offset = POWER(10, LENGTH(decimal) - POS(".", decimal))
decimal = (decimal * offset - INT(decimal) * offset) / offset
UNTIL decimal = 0 OR loop >= 4
ENDIF
IFB negativeFlg THEN
DIM bin = hexToBin(hex)
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
DIM a = hexToDec(hex)
DIM b = POWER(2, msb) - 1
FOR i = -1 TO lsb STEP -1
b = b + POWER(2, i)
NEXT
dec = bitXor(a, b) + POWER(2, lsb)
hex = decToHex(dec, signFlg, recursive + 1)
ENDIF
IFB recursive = 1 THEN
DIM bit = COPY(hexToBin(COPY(hex, 1, 1)), 1, 1)
DIM len = LENGTH(REPLACE(hex, ".", ""))
IF negativeFlg AND (bit = "0" OR len MOD 2 <> 0) THEN hex = strRepeat("F", IIF(len MOD 2 <> 0, 1, 2)) + hex
IF !negativeFlg AND (bit = "1" OR len MOD 2 <> 0) THEN hex = strRepeat("0", IIF(len MOD 2 <> 0, 1, 2)) + hex
ENDIF
RESULT = hex
FEND
//////////////////////////////////////////////////
// 【引数】
//   
// 【戻値】
//   
//////////////////////////////////////////////////
MODULE ExcelFunction
CONST Excel = CREATEOLEOBJ("Excel.Application")
FUNCTION ASC(str)
RESULT = Excel.Evaluate("ASC(" + str + ")")
FEND
FUNCTION BAHTTEXT(num)
RESULT = Excel.Evaluate("BAHTTEXT(" + num + ")")
FEND
FUNCTION CHAR(num)
RESULT = Excel.Evaluate("CHAR(" + num + ")")
FEND
FUNCTION CLEAN(str)
RESULT = Excel.Evaluate("CLEAN(" + str + ")")
FEND
FUNCTION CODE(str)
RESULT = Excel.Evaluate("CODE(" + str + ")")
FEND
FUNCTION DATEVALUE(str)
RESULT = Excel.Evaluate("DATEVALUE(<#DBL>" + str + "<#DBL>)")
FEND
FUNCTION YEN(num, digit = "")
RESULT = Excel.Evaluate("YEN(" + num + ", " + digit + ")")
FEND
FUNCTION EXACT(str1, str2)
RESULT = Excel.Evaluate("EXACT(" + str1 + ", " + str2 + ")")
FEND
FUNCTION FIND(str)
RESULT = Excel.Evaluate("FIND(" + str + ")")
FEND
FUNCTION FINDB(str)
RESULT = Excel.Evaluate("FINDB(" + str + ")")
FEND
FUNCTION FIXED(str, digit = "", separator = "")
RESULT = Excel.Evaluate("FIXED(" + str + ", " + digit + ", " + separator + ")")
FEND
FUNCTION LEFT(str, num = "")
RESULT = Excel.Evaluate("LEFT(<#DBL>" + str + "<#DBL>, " + num + ")")
FEND
FUNCTION LEFTB(str, byte = "")
RESULT = Excel.Evaluate("LEFTB(" + str + ", " + byte + ")")
FEND
FUNCTION LEN(str)
RESULT = Excel.Evaluate("LEN(<#DBL>" + str + ")")
FEND
FUNCTION LENB(str)
RESULT = Excel.Evaluate("LENB(" + str + ")")
FEND
FUNCTION LOWER(str)
RESULT = Excel.Evaluate("LOWER(" + str + ")")
FEND
FUNCTION MID(str, start, num)
RESULT = Excel.Evaluate("MID(" + str + ", " + start + ", " + num + ")")
FEND
FUNCTION MIDB(str, start, num)
RESULT = Excel.Evaluate("MIDB(" + str + ", " + start + ", " + num + ")")
FEND
FUNCTION PROPER(str)
RESULT = Excel.Evaluate("PROPER(" + str + ")")
FEND
FUNCTION REPLACE(str, start, length, replace)
RESULT = Excel.Evaluate("REPLACE(" + str + ", " + start + ", " + length + ", " + replace + ")")
FEND
FUNCTION REPLACEB(str, start, byte, replace)
RESULT = Excel.Evaluate("REPLACEB(" + str + ", " + start + ", " + byte + ", " + replace + ")")
FEND
FUNCTION REPT(str, num)
RESULT = Excel.Evaluate("REPT(" + str + ", " + num + ")")
FEND
FUNCTION RIGHT(str, num = "")
RESULT = Excel.Evaluate("RIGHT(<#DBL>" + str + "<#DBL>, " + num + ")")
FEND
FUNCTION RIGHTB(str, byte = "")
RESULT = Excel.Evaluate("RIGHTB(" + str + ", " + byte + ")")
FEND
FUNCTION SEARCH(str, target, start = "")
RESULT = Excel.Evaluate("SEARCH(" + str + ", " + target + ", " + start + ")")
FEND
FUNCTION SEARCHB(str, target, start = "")
RESULT = Excel.Evaluate("SEARCHB(" + str + ", " + target + ", " + start + ")")
FEND
FUNCTION SUBSTITUTE(str1, str2, str3, target = "")
RESULT = Excel.Evaluate("SUBSTITUTE(" + str1 + ", " + str2 + ", " + str3 + ", " + target + ")")
FEND
FUNCTION T(num)
RESULT = Excel.Evaluate("T(" + num + ")")
FEND
FUNCTION TEXT(num, format)
RESULT = Excel.Evaluate("TEXT(" + num + ", <#DBL>" + format + "<#DBL>)")
FEND
FUNCTION TRIM(str)
RESULT = Excel.Evaluate("TRIM(" + str + ")")
FEND
FUNCTION UPPER(str)
RESULT = Excel.Evaluate("UPPER(" + str + ")")
FEND
FUNCTION VALUE(str)
RESULT = Excel.Evaluate("VALUE(" + str + ")")
FEND
ENDMODULE
//////////////////////////////////////////////////
// 【引数】
//   hex : 16進数 
// 【戻値】
//   2進数に変換した値 
//////////////////////////////////////////////////
FUNCTION hexToBin(hex)
HASHTBL hb
hb["0"] = "0000";	hb["1"] = "0001";	hb["2"] = "0010";	hb["3"] = "0011";
hb["4"] = "0100";	hb["5"] = "0101";	hb["6"] = "0110";	hb["7"] = "0111";
hb["8"] = "1000";	hb["9"] = "1001";	hb["A"] = "1010";	hb["B"] = "1011";
hb["C"] = "1100";	hb["D"] = "1101";	hb["E"] = "1110";	hb["F"] = "1111";
DIM bin = ""
IFB POS(".", hex) <> 0 THEN
FOR i = 1 TO LENGTH(hex)
DIM str = COPY(hex, i, 1)
IF str = "." THEN bin = bin + "."
bin = bin + hb[str]
NEXT
ELSE
FOR i = 1 TO LENGTH(hex)
bin = bin + hb[COPY(hex, i, 1)]
NEXT
ENDIF
RESULT = bin
FEND
//////////////////////////////////////////////////
// 【引数】
//   hex : 16進数 
//   signFlg : 符号付きならばTrue 
// 【戻値】
//   10進数に変換した値 
//////////////////////////////////////////////////
FUNCTION hexToDec(hex, signFlg = TRUE)
hex = STRCONV(hex, SC_UPPERCASE)
DIM dec = 0
DIM decimalFlg = IIF(POS(".", hex) <> 0, TRUE, FALSE)
hex = IIF(LENGTH(REPLACE(hex,".", "" )) MOD 2 <> 0, "0", "") + hex
DIM negativeFlg = IIF(COPY(hexToBin(hex), 1, 1) = "1", TRUE, FALSE)
DIM sign = 1
IF negativeFlg AND signFlg THEN sign = -1
IFB negativeFlg AND signFlg THEN
DIM bin = hexToBin(hex)
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
DIM a = hexToDec(hex, FALSE)
DIM b = POWER(2, msb) - 1
FOR i = -1 TO lsb STEP -1
b = b + POWER(2, i)
NEXT
DIM dec2 = bitXor(a, b) + POWER(2, lsb)
hex = decToHex(dec2)
ENDIF
integer = IIF(decimalFlg, COPY(hex, 1, POS(".", hex) - 1), hex)
decimal = IIF(decimalFlg, COPY(hex, POS(".", hex) + 1), "0")
FOR i = 1 TO LENGTH(integer)
s = COPY(hex, i, 1)
num = IIF(CHKNUM(s), s, ASC(s) - (ASC("A") - 10))
dec = dec + num * POWER(16, LENGTH(integer) - i)
NEXT
FOR i = 1 TO LENGTH(decimal)
s = COPY(decimal, i, 1)
num = IIF(CHKNUM(s), s, ASC(s) - (ASC("A") - 10))
dec = dec + num * POWER(16, -1 * i)
NEXT
RESULT = sign * dec
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
//////////////////////////////////////////////////
// 【引数】
//   JIS : 16進数 
// 【戻値】
//   シフトJIS(16進数) 
//////////////////////////////////////////////////
FUNCTION JISToSJIS(JIS)
DIM arr[1]
DIM res[1]
arr[0] = hexToDec(COPY(JIS, 1, 2))
arr[1] = hexToDec(COPY(JIS, 3, 2))
// 上位8bit
arr[0] = arr[0] - $21
// 上位7bit
res[0] = binToDec(COPY(decToBin(arr[0]), 1, LENGTH(decToBin(arr[0])) - 1))
res[0] = decToHex(res[0] + IIF(res[0] <= $1E, $81, $C1))
// 下位8bit
SELECT COPY(hexToBin(arr[0]), LENGTH(hexToBin(arr[0])))
CASE "0"
res[1] = arr[1] + $1F
IFB res[1] >= $7F THEN
res[1] = decToHex(res[1] + 1)
ELSE
res[1] = decToHex(res[1])
ENDIF
CASE "1"
res[1] = decToHex(arr[1] + $7E)
SELEND
RESULT = JOIN(res, "")
FEND
//////////////////////////////////////////////////
// 【引数】
//   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
//////////////////////////////////////////////////
// 【引数】
//   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
//////////////////////////////////////////////////
// 【引数】
//   SJIS : シフトJIS(16進数) 
// 【戻値】
//   JIS(16進数) 
//////////////////////////////////////////////////
FUNCTION SJISToJIS(SJIS)
DIM arr[1]
DIM res[1]
arr[0] = hexToDec(COPY(SJIS, 1, 2))
arr[1] = hexToDec(COPY(SJIS, 3, 2))
IFB arr[0] <= $9F THEN
arr[0] = arr[0] - $71
ELSE
arr[0] = arr[0] - $B1
ENDIF
arr[0] = arr[0] * 2 + 1
IF arr[1] >= $7F THEN arr[1] = arr[1] - 1
IFB arr[1] >= $9E THEN
arr[1] = arr[1] - $7D
arr[0] = arr[0] + 1
ELSE
arr[1] = arr[1] - $1F
ENDIF
res[0] = COPY("0" + decToHex(arr[0]), LENGTH("0" + decToHex(arr[0])) - 1)
res[1] = COPY("0" + decToHex(arr[1]), LENGTH("0" + decToHex(arr[1])) - 1)
RESULT = JOIN(res, "")
FEND
//////////////////////////////////////////////////
// 【引数】
//   input : 入力文字列 
//   length : 埋めたあとの長さ 
//   str : 埋める文字 
//   type : 埋める方向 
// 【戻値】
//   指定文字で埋めた文字列 
//////////////////////////////////////////////////
FUNCTION strPad(input, length, str = " ", type = RIGHT)
DIM s = ""
SELECT type
CASE LEFT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = COPY(s, 1, length - LENGTH(input)) + input
CASE RIGHT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = input + COPY(s, 1, length - LENGTH(input))
SELEND
RESULT = input
FEND
//////////////////////////////////////////////////
// 【引数】
//   inputs : 繰り返す文字列 
//   multiplier : inputsを繰り返す回数 
// 【戻値】
//   inputsをmultiplier回を繰り返した文字列を返します 
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
DIM res = ""
FOR n = 1 TO multiplier
res = res + inputs
NEXT
RESULT = res
FEND

関連記事

Base64 (自作関数)
Base64 のエンコード・デコードを行います。
Cipher (自作関数)
文字列の暗号化・復号を行います。
WordFunction (自作関数)
Morse (自作関数)
モールス信号