4.08.2012

How to define constants using variables in VBScript

VBScript: 変数や演算子を使って定数を定義する方法

VBScript では読み取り専用の変数を作るために Const ステートメントが用意されている。
しかし、そこで指定できるのはリテラル定数のみであり、このようなステートメントは許可されていない。

Const kConstant0 = 1 + 2
Const kConstant1 = "Hello, " & "World"

これは大変不便である。そこで、このような定数を定義するためのラッパーを作成した。

・ConstWrapper.vbs

Function Constant(ByVal name, ByVal value)
  Dim literal

  Select Case VarType(value)
  Case vbEmpty: literal = "Empty"
  Case vbNull : literal = "Null"
  Case vbInteger, vbLong, vbSingle, vbDouble, vbCurrency, vbBoolean, _
      vbDecimal, vbByte
    literal = value
  Case vbString
    If InStr(value, vbCr) Or InStr(value, vbLf) Then
      Err.Raise 1, "Constant", _
          "ValueError: value contains a newline"
    End If
    literal = """" & Replace(value, """", """""") & """"
  Case vbDate
    literal = "#" & _
        Join(Array(Year(value), Month(value), Day(value)), "-") & " " & _
        Join(Array(Hour(value), Minute(value), Second(value)), ":") & "#"
  Case Else
    Err.Raise 2, "Constant", _
        "ValueError: type '" & TypeName(value) & "' cannot be a constant"
  End Select

  Execute "Const " & name & "=" & literal
End Function

・使用例

Constant "kConstant0", 1 + 2
Constant "kConstant1", "Hello, " & "World"

・テストコード

If WScript.FullName <> WScript.Path & "\cscript.exe" Then
  Dim args, i, shell
  args = """" & WScript.ScriptFullName & """"
  For Each i In WScript.Arguments: args = args & " """ & i & """": Next
  Set shell = CreateObject("WScript.Shell")
  shell.Run WScript.Path & "\cscript.exe //NOLOGO " & args, 1, False
  WScript.Quit
End If

Dim gCount: gCount = 0

Check "0"
Check "1"
Check "0000000000000000001"
Check "32767"        ' 2^15-1
Check "32768"        ' 2^15
Check "2147483647"   ' 2^31-1
Check "2147483648"   ' 2^31
Check "-0"
Check "-1"
Check "-32767"       ' -(2^15-1)
Check "-32768"       ' -(2^15)
Check "-2147483647"  ' -(2^31-1)
Check "-2147483648"  ' -(2^31)

Check "&O000000"       ' 0
Check "&O00000000000"  ' 0
Check "&O00000000001"  ' 1
Check "&O77777"        ' 2^15-1
Check "&O17777777777"  ' 2^31-1
Check "&O177777"       ' -1
Check "&O37777777777"  ' -1
Check "&O100001"       ' -(2^15-1)
Check "&O100000"       ' -(2^15)
Check "&O20000000001"  ' -(2^31-1)
Check "&O20000000000"  ' -(2^31)

Check "&H0000"      ' 0
Check "&H00000000"  ' 0
Check "&H00000001"  ' 1
Check "&H7fff"      ' 2^15-1
Check "&H10000"     ' 2^15
Check "&H7fffffff"  ' 2^31-1
Check "&Hffff"      ' -1
Check "&Hffffffff"  ' -1
Check "&H8001"      ' -(2^15-1)
Check "&H8000"      ' -(2^15)
Check "&H80000001"  ' -(2^31-1)
Check "&H80000000"  ' -(2^31)

Check "0."
Check "3.14159265358979"
Check "1e2"
Check "1.2e-3"

Check """"""
Check """"""""""
Check """Hello, World"""

Check "#1-2#"
Check "#01-02#"
Check "#1/2#"
Check "#1 2#"
Check "#Jan-2#"
Check "#2-Jan#"
Check "#1-2-3#"
Check "#2003-1-2#"
Check "#2-3-Jan#"
Check "#2003-2-Jan#"
Check "#4:5#"
Check "#04:05#"
Check "#4:5:6#"
Check "#04:05:06#"
Check "#1-2-3 4:5:6#"
Check "#4:5:6 1-2-3#"
Check "#2003-01-02 04:05:06#"

Check "True"
Check "False"

Check "Empty"
Check "Null"

Check "CSng(1.2)"
Check "CCur(1.2)"
Check "CByte(255)"

' Error cases
ON ERROR RESUME NEXT
Check "vbCrLf"
WScript.Echo "[Error:" & Err.Number & "]", Err.Source, Err.Description
Check "WScript.Arguments"
WScript.Echo "[Error:" & Err.Number & "]", Err.Source, Err.Description
Check "Array()"
WScript.Echo "[Error:" & Err.Number & "]", Err.Source, Err.Description
ON ERROR GOTO 0

MsgBox "Click OK to exit."


Function Check(ByVal description)
  PackString description, 24
  Execute "PackString VarType(" & description & _
      ") & "": "" & TypeName(" & description & "), 20"
  Execute "Constant ""k" & gCount & """," & description
  Execute "If IsNull(k" & gCount & _
      ") Then PackString ""null"", 24 Else PackString k" & gCount & ", 24"
  Execute "PackString VarType(k" & gCount & _
      ") & "": "" & TypeName(k" & gCount & "), 20"
  WScript.Echo
  gCount = gCount + 1
End Function

Function PackString(ByVal value, ByVal width)
  WScript.StdOut.Write value & String(width - Len(value), " ")
End Function

・出力例

0                       2: Integer          0                       2: Integer
1                       2: Integer          1                       2: Integer
0000000000000000001     2: Integer          1                       2: Integer
32767                   2: Integer          32767                   2: Integer
32768                   3: Long             32768                   3: Long
2147483647              3: Long             2147483647              3: Long
2147483648              5: Double           2147483648              5: Double
-0                      2: Integer          0                       2: Integer
-1                      2: Integer          -1                      2: Integer
-32767                  2: Integer          -32767                  2: Integer
-32768                  3: Long             -32768                  3: Long
-2147483647             3: Long             -2147483647             3: Long
-2147483648             5: Double           -2147483648             5: Double
&O000000                2: Integer          0                       2: Integer
&O00000000000           2: Integer          0                       2: Integer
&O00000000001           2: Integer          1                       2: Integer
&O77777                 2: Integer          32767                   2: Integer
&O17777777777           3: Long             2147483647              3: Long
&O177777                2: Integer          -1                      2: Integer
&O37777777777           2: Integer          -1                      2: Integer
&O100001                2: Integer          -32767                  2: Integer
&O100000                3: Long             -32768                  3: Long
&O20000000001           3: Long             -2147483647             3: Long
&O20000000000           3: Long             -2147483648             5: Double
&H0000                  2: Integer          0                       2: Integer
&H00000000              2: Integer          0                       2: Integer
&H00000001              2: Integer          1                       2: Integer
&H7fff                  2: Integer          32767                   2: Integer
&H10000                 3: Long             65536                   3: Long
&H7fffffff              3: Long             2147483647              3: Long
&Hffff                  2: Integer          -1                      2: Integer
&Hffffffff              2: Integer          -1                      2: Integer
&H8001                  2: Integer          -32767                  2: Integer
&H8000                  3: Long             -32768                  3: Long
&H80000001              3: Long             -2147483647             3: Long
&H80000000              3: Long             -2147483648             5: Double
0.                      5: Double           0                       2: Integer
3.14159265358979        5: Double           3.14159265358979        5: Double
1e2                     5: Double           100                     2: Integer
1.2e-3                  5: Double           0.0012                  5: Double
""                      8: String                                   8: String
""""                    8: String           "                       8: String
"Hello, World"          8: String           Hello, World            8: String
#1-2#                   7: Date             2012/01/02              7: Date
#01-02#                 7: Date             2012/01/02              7: Date
#1/2#                   7: Date             2012/01/02              7: Date
#1 2#                   7: Date             2012/01/02              7: Date
#Jan-2#                 7: Date             2012/01/02              7: Date
#2-Jan#                 7: Date             2012/01/02              7: Date
#1-2-3#                 7: Date             2003/01/02              7: Date
#2003-1-2#              7: Date             2003/01/02              7: Date
#2-3-Jan#               7: Date             2003/01/02              7: Date
#2003-2-Jan#            7: Date             2003/01/02              7: Date
#4:5#                   7: Date             4:05:00                 7: Date
#04:05#                 7: Date             4:05:00                 7: Date
#4:5:6#                 7: Date             4:05:06                 7: Date
#04:05:06#              7: Date             4:05:06                 7: Date
#1-2-3 4:5:6#           7: Date             2003/01/02 4:05:06      7: Date
#4:5:6 1-2-3#           7: Date             2003/01/02 4:05:06      7: Date
#2003-01-02 04:05:06#   7: Date             2003/01/02 4:05:06      7: Date
True                    11: Boolean         True                    11: Boolean
False                   11: Boolean         False                   11: Boolean
Empty                   0: Empty                                    0: Empty
Null                    1: Null             null                    1: Null
CSng(1.2)               4: Single           1.2                     5: Double
CCur(1.2)               6: Currency         1.2                     5: Double
CByte(255)              17: Byte            255                     2: Integer
vbCrLf                  8: String           [Error:1] Constant ValueError: value contains a newline
WScript.Arguments       9: Object           [Error:2] Constant ValueError: type 'Object' cannot be a constant
Array()                 8204: Variant()     [Error:2] Constant ValueError: type 'Variant()' cannot be a constant

Error型、Decimal型、非オートメーションオブジェクトは VBScript では作成が難しかったので省略。
渡された引数を一度 String型 に変換してから Execute 文を実行しているため、型が変わるケースもある。
尚、Execute 文の特性上、改行を含む文字列はどうしても定義することはできない。

0 件のコメント:

コメントを投稿