はじめに
自己の立場を軽く。
新卒から2年目までWEB系のバック、フロントエンドをRubyで経験。
4年異業種を経験し、再度IT職のSESへ転職しました。
そこでVue、REACTなどモダンな言語を数カ月経験した後に、
現在のASPclassicにアサインという流れになります。
この記事の対象者
•モダンな言語から、レガシー言語へ向き合う方
•基幹業務などの開発案件にアサインされた方
•エンジニア経験の浅い方(己)
•過去の自分に向けて
背景
更新、削除処理で以下の流れを回してます。
表示処理ではなく、ユーザーのアクション処理になります。
1. SQLで取得した各列の値を
2. カンマ区切りの文字列に連結し
3. hidden inputに格納
4. フォーム送信
5. サーバー側でSplitして配列化
6. 同じインデックスを1レコードとして扱う
問題
今回は、工程5で空文字としての配列が入ってほしかったです。
しかし、UboundとSplitの組み合わせでエラーとなりました。
- HTML側のhidden input例
ここではvalue属性は空文字 "" に設定されている
サンプルコード
<input type="hidden" id="hidKey" name="hidKey" value="">
- Classic ASP側での受け取り
' フォームから受け取ったカンマ区切りデータを配列化
arrKey = Split(Request.Form("hidKey"), ",")
arrName = Split(Request.Form("hidName"), ",")
arrCategory = Split(Request.Form("hidCategory"), ",")
arrCount = Split(Request.Form("hidCount"), ",")
' 基準となる配列の要素数でループ
For i = 0 To UBound(arrKey)
' 1レコード分のデータを組み立て
ReDim record(3)
record(0) = arrKey(i)
record(1) = arrName(i) ' ここでエラー
record(2) = arrCategory(i)
record(3) = arrCount(i)
' 件数チェックなどの事前処理
sqlInfo = BuildCheckSQL(record)
Set rs = ExecuteQuery(sqlInfo("SQL"), sqlInfo("Params"))
If Not rs.EOF Then
existingCount = rs(0).Value
End If
rs.Close
' 条件に応じて削除処理
If existingCount > 0 Then
ExecuteDelete(record)
End If
Next
配列が同じ要素数になることが前提のため、
1つでもから配列になると下記でエラーが出てしまいます。
For i = 0 To UBound(arrKey)
通常は、Request.Form("hidCname") が空文字 "" の場合
Split("") → Array("") → UBound=0
arr(0) は空文字 "" を参照してほしいです。
しかし、今回UBound(Sname) = -1 になりました。
0番目を参照すると「Subscript out of range」でエラーになる内容です。
なぜUBound=-1になるのか?
「Empty」と「空文字」の違い
- Empty
- 変数が初期化されていない状態
- 値が設定されていない
- Variant型
- Split(Empty, ",") → 空配列(要素0)になる場合がある
→UBound=-1
- 空文字 ""
- 値はあるが文字列長が0
- Split("", ",") → Array("") → 要素数1 → UBound=0
⇛「空文字が1要素入った配列」になる
※ UBound = -1 になるのは、
Splitの対象が空文字ではなく「Empty」の場合である
なぜhidden inputがEmptyになるか?
- inputがdisabledになっている
- ブラウザやJavaScriptでvalueを削除して送信
- フォーム自体にそのhiddenが送信されなかった
→この場合、Request.Formで受け取る値が Empty になりうる
改善策
- Emptyを空文字に変換してからSplit
val = Request.Form("hidName")
If IsEmpty(val) Then
val = ""
End If
arrName = Split(val, ",")
End If
- 参照前に必ずチェック
If IsArray(arrName) And UBound(arrName) >= 0 Then
record(1) = arrName(i)
Else
record(1) = ""
End If
まとめ
今回は、alue='' に見える hidden input を、ASP側で Empty として受け取ったためUBoud=-1 になりました
- Classic ASPでhidden inputの値がEmptyの場合、Splitで空配列となりUBound=-1になります
- 空文字 "" と Empty は異なります
- UBound参照前には必ず IsEmpty / UBoundチェックを行うのが吉?
- Empty → "" に置き換えてからSplitという対処を行いました