これは私がVB4CGIからASPに書き換えるのに気がついたことをまとめたものです。
間違ったことが書いてあるかもしれません。参考程度に読んでください。
原作者 古口正巳 [koguchi@sf.airnet.ne.jp] 1998.7.30更新
全般
Groval.asaやASPのメインルーチンの変数はグローバル(広域)変数です。
関数またはサブルーチンで使用されている変数名は使用しないでください。特にvb4cgi.incに使用されてい変数。
(動作異常を起こして原因が特定できないときがあります。最悪の場合IISが落ちます。)
べつなルーチンを読み込むときは
サブルーチン集ではすべて使われないと思われる特殊な変数名を使うか一回サブルーチンに落とす。
例:
<%
cgimain
%>
getcgivalueで返される値が文字列ではなく数値に変換されているときがある。フォームデーターの書き方による。
変数の型変換が不明瞭であるので,必ず目的の型かVartypeなどで確認してから使用すること。
特に数値どおしでも比較がうまくいかないときがある。整数・浮動小数点など精度も合わせる必要あり。
同じ数値であっても型が違うと比較したときFalseになることがある。
何も入力されていない変数やFormデーターの型変換が失敗するときがある。
vb4cgi.incの関数を用いてHtml文を書くときは
Sendheader "Title" '←必ず文字列を指定すること。エラーになります。
Send "Output"
....
Sendfooter
と書くだけで良いので便利だと思います。
1.File System
最初にOPENステートメントに相当する次のような文を書きます(fs,aは任意のオブジェクト名)
Set fs = CreateObject("Scripting.FileSystemObject")
sFilename = Server.MapPath("testfile.txt")
次のうちどれかを記入する。(行単位書き込み,読み込み。ファイルがないときは作成)
READ->
Set a = fs.OpenTextFile(sFilename, 1, false)
ReadAfile = a.ReadLine
改行コードも読みこみ時はa.ReadAll
WRITE->
Set a = fs.OpenTextFile(sFilename, 2, True)
a.WriteLine(str)
改行コードを書き込まないならa.Write
APPEND->
Set a = fs.OpenTextFile(sFilename, 8, True)
a.WriteLine(str)
最後にCLOSEに相当する
CLOSE -> a.Close
さらに Set fs = Nothing も書けばファイルシステムオブジェクトもなくなります。
2.異なっている関数
FORMAT -> FormatDateTime等
引数が1のとき先頭にスペースが入るときがある
文字演算子を駆使して同様な関数を作るしかない
NEXTの後のループ変数は取り除く
For I=1 to 10:Next i -> Next
LIKE演算子がない(vb4cgi.incの定義関数を使用)
strlike(str1,str2)<>""----> *#と書くと正常に動作しないことが判明。
END -> Response.End
型宣言はすべて取り除かないとエラーになる。自作定義関数なども
as string -> NULL
dim(1 to 8)が使えない
MID$などの$関数は使えない
SELECT CASE CASEで 1 to 10は使えない
formatDateTime(mydate, 0)でmydateが2000年になると長い日付形式で表示されてしまう。
2000年に対応させる場合formatDateTime(mydate, 2)を使わなければならない。
Formatdatetime(mydate, 1)の先頭に半角スペースが挿入されることがある。
Trim(Formatdatetime(mydate, 1))と書かないと正確に動作しない。
関数で未定義変数を出力しようとするとエラーも発生せずに止まってしまうことがある
コメントアウト(')してあってもデバッガーからエラーが出力されることがある
3.VB4CGIの定義関数をASPに書き換える覚書
もしも私の変換プログラムをVB4CGI.INCを使わない形に直すときはこれに従って下さい。
ちゃとVbCrLfを書いておいた方が後でデバッグが簡単になります。
ただVbLfは半角スペースに変換されることがありますので,VbCrだけで良いかもしれません。
VbCrLがもしも定義されていなければ & CHR(13) & CHR(10)を用います。
vbみたく総ての定数が最初から実装されていないので注意しましょう。
Send -> Response.Write + Vbcrlf
GetCgiValue 文字を期待していると数値が帰ってくることがあり。適宜型変換関数を用いる(CStr, CInt..)
getcgivalue= Request.Form(str) 'POST
if getcgivalue="" then getcgivalue= Request.QueryString(str) 'GET
SendHeader ->
Response.Write "
" & sTitle & "" + VbCrLf
Response.Write "" + VbCrLf'日本語の設定 Shift-JIS
Response.Write "" + VbCrLf
Response.Write "" + VbCrLf'に何か加える時は直して下さい。ここでは背景色を設定してます。背景が必要でないときはのみにしてください。
'#RRGGBBで色を設定します。RR,GG,BBはそれぞれ赤・緑・青で16進数で00-FFまでに設定します。
SendFooter -> Response.Write "" + VbCrLf
主な環境変数などの変更
だめな例:App.Path -> Request.ServerVariables("APPL_PHYSICAL_PATH")
app.pathに比較すると最後の\が多い。サブディレクトリだと正しく動作しない
Server.MapPath("./")が正しい
Send "Content-type: image/gif" & vbCrLf -> Response.ContentType = "image/gif"
SendB -> Response.BinaryWrite digit<=バイナリ配列
主なメディアタイプ
application/msword MSWORD
application/octet-stream binary(.LZH)
application/pdf PDF
application/zip ZIP
audio/basic au
audio/x-pn-realaudio Real Audio
audio/x-wav WAVE
image/gif GIF
image/jpeg JPEG
image/x-xbitmap Bitmap
text/html HTML
text/plain 単純テキスト
text/richtext RichText
video/mpeg MPEG
video/quicktime QuickTime
video/x-msvideo AVI
REMOTE_HOST -> Request.ServerVariables("REMOTE_HOST")
REMOTE_ADDR -> Request.ServerVariables("REMOTE_ADDR")
CGI_UserAgent -> Request.ServerVariables("HTTP_USER_AGENT")
CGI_ScriptName -> Request.ServerVariables("PATH_INFO")
CGI_ScriptName -> Request.ServerVariables("SCRIPT_NAME")
CGI_PathTranslated -> Server.MapPath("/")
4.DAO->ADO(DAO 3.5, ACCESS95)
Find系やSeek系の命令はないmove系のみ→書き換え必要
editがない→そのまま代入update
ワイルドカードはACCESSやDAOと書式が違います'*' -> '%', '?" -> '_'
[a - f] or [abcdef] a-fにある任意の 1 文字 [^a - f]はa-fにないの意味
rs.MoveFirstなどでレコードが1個もないとエラーになる→命令実行前にチェックすること。
record!fieldはエラーになるrecord("field")と書く
Dim db As Database 'DAO
Set db = OpenDatabase(App.Path & "\" & "log.mdb")
は
'Dim cn As ADODB.Connection 'ADO Connection いろいろな書き方ができるのでごちゃごちゃになってしまいました
'Set cn = New ADODB.Connection
Set cn = Server.CreateObject("ADODB.Connection") <-ASP
または
Dim cn As New ADODB.Connection
'cn.ConnectionTimeout = 100
cn.Open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & App.Path & "\" & "log.mdb"
(SQL Serverなら{SQL Server})
'Dim rs As Recordset 'DAO
'Set rs = db.OpenRecordset("log")
Set rs = Server.CreateObject("ADODB.Recordset") <-ASP
は
'Dim rs As ADODB.Recordset 'ADO Recordset
'Set rs = New ADODB.Recordset
または
Dim rs As New ADODB.Recordset
'rs.CursorType = adOpenKeyset
'rs.LockType = adLockOptimistic
'rs.Open "log", cn, , , adCmdTable
まとめて書けば(logテーブルを開く)
rs.Open "log", cn, adOpenKeyset, adLockOptimistic, adCmdTable
読みこみ専用SQLで開く(雑草テーブルから学名がaで始まるすべてのレコード)
rs.Open "SELECT * From 雑草 WHERE 学名 LIKE 'a%'", cn, adOpenForwardOnly, adLockReadOnly, adCmdText
adovbs.incをインクルードしないときは\program files\common files\system\ado\などにある
'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0 (Default)前方参照のみ可能な静的カーソル
Const adOpenKeyset = 1 追加データ参照できず。削除データーにはアクセスできない。
Const adOpenDynamic = 2 すべて可能な動的カーソル。
Const adOpenStatic = 3 コピーによる静的カーソル。前方・後方に移動可能。
'---- LockTypeEnum Values ----
Const adLockReadOnly = 1 (Defalut)読みこみ専用
Const adLockPessimistic = 2 編集開始時にレコードをロックする。
Const adLockOptimistic = 3 Update時にレコードをロックする。
Const adLockBatchOptimistic = 4 共有的バッチ更新
'---- CommandTypeEnum Values ----
Const adCmdUnknown = &H0008 不明。重い
Const adCmdText = &H0001 SQL文などのテキスト
Const adCmdTable = &H0002 テーブル名
Const adCmdStoredProc = &H0004 stored procedure
レコードの追加
rs.AddNew '新レコードの準備
rs!Time = Now
If CGI_RemoteAddr = "" Then 'Null値があるときはエラーになるので注意
rs!CGI_RemoteAddr = Null
Else
rs!CGI_RemoteAddr = CGI_RemoteAddr
End If
If CGI_RemoteHost = "" Then
rs!CGI_RemoteHost = Null
Else
rs!CGI_RemoteHost = CGI_RemoteHost
End If
If CGI_UserAgent = "" Then
rs!CGI_UserAgent = Null
Else
rs!CGI_UserAgent = CGI_UserAgent
End If
rs.Update 'レコード更新
SQLなら
'Queryでレコード更新 'Null値があるとエラー
cn.Execute "INSERT INTO log ( [TIME], CGI_RemoteAddr, CGI_RemoteHost, CGI_UserAgent ) VALUES ('" & Now & "','" & CGI_RemoteAddr & "','" & CGI_RemoteHost & "','" & CGI_UserAgent & "');"
TIME, DATEはシステム予約されているので[TIME], [DATE]とかく
文字列は' 'でくくること
ちゃんと書くなら
sql = "INSERT INTO log ( "
values = " VALUES ( "
sql = sql & "[TIME]"
values = values & "'" & Now & "'"
If CGI_RemoteAddr <> "" Then 'Null値を除く
sql = sql & ", CGI_RemoteAddr"
values = values & ", '" & CGI_RemoteAddr & "'"
End If
If CGI_RemoteHost <> "" Then
sql = sql & ", CGI_RemoteHost"
values = values & ", '" & CGI_RemoteHost & "'"
End If
If CGI_UserAgent <> "" Then
sql = sql & ", CGI_UserAgent"
values = values & ", '" & CGI_UserAgent & "'"
End If
sql = sql & " )"
values = values & " )"
パラメーターを使うなら
'Queryでレコード更新
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cn
'ADDOB.Connectionを使用しないならコメントをはずす
'cmd.ActiveConnection = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & CGI_AppPath & "\" & "log.mdb"
cmd.CommandText = "INSERT INTO log ( [TIME], CGI_RemoteAddr, CGI_RemoteHost, CGI_UserAgent ) VALUES ( ?, ?, ?, ?)"
Set prm = cmd.CreateParameter( , 135, , , now) 'adDBTimeStamp
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter( , 200, , Len(CGI_RemoteAddr), CGI_RemoteAddr) 'adVarChar
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter( , 200, , Len(CGI_RemoteHost), CGI_RemoteHost)
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter( , 200, , Len(CGI_UserAgent), CGI_UserAgent)
cmd.Parameters.Append prm
cmd.Execute RecordsAffected, , 1 'adCmdText NULL値があるとエラー
'recordsaffected 影響を受けたレコード数
'コマンドオブジェクトを使うなら
Set cmd = Server.CreateObject("ADODB.Command")
Set cmd.ActiveConnection = cn
'新規挿入
cmd.CommandText = "INSERT INTO calendar ([date], caldata) VALUES( '" & s & "', '" & ds & "')"
'削除
cmd.CommandText = "DELETE * FROM calendar WHERE [date] = '" & s & "'"
'更新
cmd.CommandText = "UPDATE calendar SET caldata = '" & ds & "' WHERE [date] = '" & s & "'"
クエリーの実行
cmd.Execute RecordsAffected, , 1 'adCmdText
注意:SQLサーバーを用いるときには次の点に注意すること。
ADO(SQL)はそのままではうまく動作しなかったので次の変更を加えた。
UPSIZING WIZARDを使用しアクセスのデーターベースをSQLデーターベースに変換した。
DAOとSQLの仕様の違いの修正が必要
tempDBの拡張→2MB->20MB, エリーの[]除去,大文字小文字の区別の修正→すべて小文字に,DELETE * FROM →* FROMを取り除く
'---- DataTypeEnum Values ----
Const adEmpty = 0 指定した値なし
Const adTinyInt = 16 1バイトの符号付き整数
Const adSmallInt = 2 2バイトの符号付き整数
Const adInteger = 3 4バイトの符号付き整数
Const adBigInt = 20 8バイトの符号付き整数
Const adUnsignedTinyInt = 17 1バイトの符号なし整数
Const adUnsignedSmallInt = 18 2バイトの符号なし整数
Const adUnsignedInt = 19 4バイトの符号なし整数
Const adUnsignedBigInt = 21 8バイトの符号なし整数
Const adSingle = 4 単精度浮動小数点数
Const adDouble = 5 倍精度浮動小数点数
Const adCurrency = 6 通貨値(8バイト符号付き整数1万桁)
Const adDecimal = 14 固定の精度および桁数を持つ正確な整数
Const adNumeric = 131 固定の精度および桁数を持つ正確な整数
Const adBoolean = 11 ブール値
Const adError = 10 32ビットのエラーコード
Const adUserDefined = 132 ユーザー定義型
Const adVariant = 12 OLEオートメーションバリアント
Const adIDispatch = 9 OLEオブジェクトのIDispatchインターフェースを指すポインタ
Const adIUnknown = 13 OLEオブジェクトのIUnknownインターフェースを指すポインタ
Const adGUID = 72 グローバル一意識別子(GUID)
Const adDate = 7 日付値
Const adDBDate = 133 日付値(yyyymmdd)
Const adDBTime = 134 時刻値(hhmmss)
Const adDBTimeStamp = 135 日付時刻スタンプ(yyyymmddhhmmss+10億分の1桁までの少数)
Const adBSTR = 8 Null終端文字列(Unicode)
Const adChar = 129 文字列値
Const adVarChar = 200 文字列値(Parameterオブジェクト)
Const adLongVarChar = 201 長文字列値(Parameterオブジェクト)
Const adWChar = 130 Null終端文字列(Unicode)
Const adVarWChar = 202 Null終端文字列(Unicode)(Parameterオブジェクト)
Const adLongVarWChar = 203 Null終端文字列(Parameterオブジェクト)
Const adBinary = 128 バイナリ値
Const adVarBinary = 204 バイナリ値(Parameterオブジェクト)
Const adLongVarBinary = 205 ロングバイナリ値(Parameterオブジェクト)
ここに書いた内容はあくまでも条件を限定して調べた結果であります。
多くが個人的な感想であり事実と異なることがあります。
(koguchi@sf.airnet.ne.jp http://wwww.sf.airnet.ne.jp/koguchi/)