三流君ASPで遊ぶ、失敗する No.90 〜 No.94 バックナンバー
<ADO CSVで先頭行にフィールド名が無い時>
こんにちは、三流プログラマーのKen3です。
今回は、
ADOのCSV接続で、先頭行に項目名(フィールド名)が無い時の接続、
そんなお話です。
http://www.ken3.org/cgi-bin/group/asp_ado_csv.asp
に、
関連項目ASPでADO CSV接続の他のサンプルもあるので、合わせて見てください。
/*
* 1.今回のキッカケ
*/
質問フォームより、下記の質問をもらいました。
-----
ASPからADO接続出来るなんて知りませんでした。
今回、CSVファイル内を検索してヒットした行をHTML表示する用件があったので、凄く
参考になりました。
1点質問があります。
今回のCSVファイルには1行目にヘッダ情報があるので、条件を指定できましたが、当方
のCSVファイルはヘッダ情報の無いデータのみになってますので、全件検索しか出来ま
せんでした。
ヘッダ情報が無いCSVファイルに対して条件追加をした場合の項目名(列名)記述方法を
ご存知であればご教示願います。
-----
ご教示かぁ・・・この言葉は嫌いなんだよねぇ〜
と
いつもの関係ないことから入って、
自分でもわからなかったので探ってみました。
/*
* 2.1行目にヘッダ情報が無いCSVファイル(先頭行にフィールド名無し)
*/
1行目にヘッダ情報が無いCSVファイルかぁ。
テストデータで下記のデータを作成しました。
test090.csv
9-99999999999,CSVのヘッダーを無くして見た,Ken3,100,2004/1/06
4-8399-0986-5,CPUの創りかた,毎コミ,2800,2003/9/30
4-8399-0997-0,速効!図解 ホームページ・ビルダー7,毎コミ,1280,2003/3/13
・
・
・
4-8222-0785-4,信頼されるSEの条件,日経BP出版センター,1700,2003/3/13
4-89311-450-6,よくわかる Microsoft Word2002ドリル,FOM出版,1000,2002/4/10
4-407-05082-9,30時間でマスター Word&Excel2002,実教出版,857,2002/3/28
普通に接続すると、勝手に
9-99999999999やCSVのヘッダーを無くして見たをフィールド名にしてくれる(笑)
これだとイヤなので(イヤじゃなくて使えないので)
Googleで、
Microsoft Text Driver csv ADO
をキーワードにしてwebを検索する。
いろいろとでてくるのですが、
http://dbforums.com/arch/212/2003/7/855889
を見ると、
"Driver={{Microsoft Text Driver (*.txt; *.csv)}}; MaxBufferSize=2048;
DBQ=C:\\Temp; DriverId=27; Format=TABDELIMITED"
or
"Driver={{Microsoft Text Driver (*.txt; *.csv)}}; MaxBufferSize=2048;
DBQ=C:\\Temp; DriverId=27; Format=Delimited(:)"
なんて書いてある。
これ予想だけど、Format=Delimited(:)で区切り記号も指定できそう。
ほかにパラメータないのかなぁ?
http://dbforums.com/arch/43/2003/1/582349
には、
mConn.Open "DRIVER={Microsoft Text Driver (*.txt; *.csv)}; DBQ=" &
mFilePath & ";Extended
Properties='text;HDR=NO';Extensions=asc,csv,tab,txt;Persist Security
Info=False"
HDR=NO
^^^^^^
おっ、これってヘッダーぽくない?
英語読めないので、続きの探索を打ち切る。
※ヘッダーをHDR=NOにして、自分でフィールド名を指定したいけど、
そこまで探せなかった(打ち切るなんて書いてるけど、探せなかっただけ(笑))
よし、英語読めないなら、中国語でしょう?(オイオイ)
http://www.csdn.net/Develop/article/16%5C16955.shtm
oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\;" & _
"Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
でも、可能みたいですね。
これを参考にして、下記の接続文字列を作成してみた。
'接続情報の作成 ドライバーの指定と、DBQには、パスのみを指定する
Con = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath(".") & ";" & _
"Extended Properties=""text;HDR=No;FMT=Delimited;"";"
'↑MapPathに(".")を渡し、カレントディレクトリを渡す
最大のポイントは、
^^^^^^^^^^^^^^^^^^
"Extended Properties=""text;HDR=No;FMT=Delimited;"";"
のパラメータを接続情報に含めたことです。(HDR=Noとしてます)
あとは、全てを読むテストのSQL文
'SQLのテーブル名には、ファイル名test090.csvを指定します。
strSQL = "select * from test090.csv"
を作成して、
'接続文字列、SQLを渡して、レコードセットを開く
rs.Open strSQL, Con, 0 '0=adOpenForwardOnly
と、レコードセットを作り、
見出しとデータを下記のような感じで、画面に出してみました。
'見出しを(フィールド名を)そのまま書き込む
Response.Write "<TR>"
For Each fld_A In rs.Fields 'フィールドのアイテムに対してループ
Response.Write "<TH>" & fld_A.Name & "</TH>" '←.Nameでフィールド名
Next
Response.Write "</TR>"
'お約束のEOFまでループは(データが無くなるまでループ)、
Do While rs.EOF = False 'レコードセットの.EOFがFalseの間
Response.Write "<TR>" '内容を表示する
For Each fld_A In rs.Fields 'フィールドのアイテムに対してループ
Response.Write "<TD>" & fld_A.Value & "</TD>" '←.Valueでフィールドの値
Next
Response.Write "</TR>"
rs.MoveNext '次のレコードに移動する
Loop
実際のテストは、
http://www.ken3.org/cgi-bin/test/test090-1.asp
で、実行できます。(ソースの全ても見れます。)
実行すると、先頭行をデータとして扱い、
F1,F2と自動でフィールド名を付けてくれてます。
/*
* 3.自動で付けられる予定のF1,F2のフィールド名を条件に出来るか?
*/
おっと、質問は、条件を指定して、検索したかっただよね。
接続文字列は、下記のように作って、
'接続情報の作成 ドライバーの指定と、DBQには、パスのみを指定する
Con = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath(".") & ";" & _
"Extended Properties=""text;HDR=No;FMT=Delimited;"";"
'↑MapPathに(".")を渡し、カレントディレクトリを渡す
SQL文でF1やF2を使用してみます。
データの並びは、
4-8222-0785-4,信頼されるSEの条件,日経BP出版センター,1700,2003/3/13
F1 F2 F3 F4 F5
なので、
F3の出版社=日経BP出版センターのデータを探す
'SQLのテーブル名には、ファイル名test090.csvを指定します。
strSQL = "select * from test090.csv"
strSQL = strSQL & " Where F3 = '日経BP出版センター'"
'↑F3の出版社の項目を条件にしてデータをWhereで絞り込む
と、F3フィールドに対して、条件を付けてみました。
http://www.ken3.org/cgi-bin/test/test090-2.asp
で、テスト実行できます(全てのソースもここで見れます)
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
先頭行に項目名が無い、そんなCSVファイルに対して、
ADOを使用して、接続してみました。
いろいろと問題点や疑問点を残しつつ、脱線・寄り道の多いメルマガですが、
今後とも、よろしくお願いします。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<ADO CSVでReadOnly=0と.AddNewを使いデータ追加>
こんにちは、三流プログラマーのKen3です。
今回は、
ADOのCSV接続で、
ReadOnly=0と.AddNewを使いデータを追加してみた
そんなお話です。
http://www.ken3.org/cgi-bin/group/asp_ado_csv.asp
に、
関連項目ASPでADO CSV接続の他のサンプルもあるので、合わせて見てください。
/*
* 1.今回のキッカケ
*/
特に無いんだけど、
CSVの更新と削除は、
Microsoft OLE DB Provider for ODBC Drivers エラー '80004005'
[Microsoft][ODBC Text Driver] この ISAM では、
リンク テーブル内のデータを削除することはできません。
と、怒られてました。
では、追加(ファイルの後ろにAppendの追記)はできるかなぁ〜
と
あまり使わないかも的な処理を書いてみました。
※普通に追加なら、FileSystemObjectで追加していけば通常はOKなのですが、
強引にネタとしてしまいました。
/*
* 2.開き方のポイント ReadOnly=0なんてパラメータあったよ
*/
さてと、データを追加するのかぁ。
追加だから、
'接続文字列、SQLを渡して、レコードセットを開く
rs.Open strSQL, Con, adOpenStatic, adLockOptimistic
で、開こうとすると
ADODB.Recordset エラー '800a0bb9'
引数が間違った型、または許容範囲外であるか、競合しています。
/cgi-bin/test/test091-1.asp, 行 44
あららダメかぁ・・・
Const adOpenStatic = 3 '---- CursorTypeEnum Values ----
で、開けないんですね・・・
そんなこんなで、失敗が続き、調べてみると、
http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B316475
↑xlsの例みたいですが、
cn.Open "Driver={Microsoft Excel Driver (*.xls)};DBQ=C:\MyDoc.xls;ReadOnly=0;"
とあって、
おっ?
ReadOnly=0なんてパラメータあったよ
^^^^^^^^^^
こんどは、ReadOnly=0で調べると、
ReadOnly=0 (更新可能)
ReadOnly=1 (更新不可、リードオンリー)
となっている。(ReadOnly=True/Falseとは書けないのかなぁ?)
接続文字列を下記のように作成しました。
'※接続情報の作成 ドライバーの指定と、DBQには、パスのみを指定する
Con = "Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=" _
& Server.MapPath(".") & ";" _
& "ReadOnly=0;"
で、開く時は、レコードセットを作成して、
'ADO DB Recordset オブジェクトを作成する、英文そのままじゃん
Set rs=Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseServer 'カーソルはサーバーの指定
'SQLのテーブル名には、ファイル名を指定します(test091.csvを指定)
strSQL = "select * from test091.csv"
'接続文字列、SQLを渡して、レコードセットを開く
rs.Open strSQL, Con, adOpenDynamic, adLockOptimistic
と、SQLを渡して作成してみました。
※rs.CursorLocation = adUseServer 'カーソルはサーバーの指定
は、無くてもOKでした(あとで気が付きました)
/*
* 3..AddNewでデータを追加してみた
*/
接続が出来たら(レコードセットが作成できたら)
今度はレコードを追加してみたかったので、
.AddNewでデータを追加してみます。
ファイル名はtest091.csvで、データは,カンマで区切られてます。
FID,書き込み時刻,IP情報,Reffer
の4つの項目をCSVで管理してみます。
このASP(test091-1.asp)が実行されたら、
test091.csvと接続後、
最終行にカーソルを移動(.Movelast)してFID+1の次の番号を計算。
.Addnew後、
IPアドレスの頭10桁とReferrer(どこからきたか)をフィールドにセットして、
.Updateで更新してみます。
実際のテストは、
http://www.ken3.org/cgi-bin/test/test091-1.asp
で、実行できます。(ソースの全ても見れます。)
まずは、
接続・レコードセットの作成です
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'※接続情報の作成 ドライバーの指定と、DBQには、パスのみを指定する
Con = "Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=" _
& Server.MapPath(".") & ";" _
& "ReadOnly=0;"
'SQLのテーブル名には、ファイル名を指定します(test091.csvを指定)
strSQL = "select * from test091.csv"
'ADO DB Recordset オブジェクトを作成する、英文そのままじゃん
Set rs=Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseServer 'カーソルはサーバーの指定
'接続文字列、SQLを渡して、レコードセットを開く
rs.Open strSQL, Con, adOpenDynamic, adLockOptimistic
ここまでで、なんとかCSVと接続しました。
ポイントは、接続文字列のReadOnly=0です。
最後の番号を取得したいので、
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'最終のデータを取得する
rs.MoveLast 'レコードを最終行へ移動
NEXT_NO = Cint(rs.Fields("FID").Value) + 1 '次の番号を+1して計算する
.MoveLastで最終行に移動後、.Fields("FID").Valueの値に+1して、
次の連番を作成しました。
データを.AddNewで追加する
^^^^^^^^^^^^^^^^
rs.AddNew
rs.Fields("書き込み時刻").Value = Now()
rs.Fields("FID").Value = NEXT_NO '次の番号をセットする
'↓番号でフィールドにアクセスも出来るよ
rs.Fields(2).Value = Left(Request.ServerVariables("REMOTE_ADDR"), 10)
rs.Fields(3).Value = Request.ServerVariables("HTTP_REFERER")
Response.Write ".Updateで更新(レコード確定)<br>"
rs.Update
rs.Close 'クローズして確定する
ここも、ポイントは特に無いのですが、
rs.Fields("書き込み時刻")やrs.Fields("FID")
と、フィールド名で指定する方法と
rs.Fields(2)やrs.Fields(3)のように、フィールドの番号で指定する方法、
どちらも使えます。
データをセットしたら、
.Update で データを確定してます
(忘れても、.Closeやカーソル移動で自動確定されるけど)
http://www.ken3.org/cgi-bin/test/test091-1.asp
で、テスト可能なので、遊んでみてください(ソースの全ても見れます。)
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
ADOを使用して、CSVと接続、データを追加してみました。
※ADOで接続が面倒、これなら、FileSystemObjectで追加したほうが楽。
と、判断材料に使ってもらえればうれしいです。
いろいろと問題点や疑問点を残しつつ、脱線・寄り道の多いメルマガですが、
今後とも、よろしくお願いします。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<FORM SELECTタグのOPTION値を受け取って処理を行う>
こんにちは、三流プログラマーのKen3です。
今回は、
処理を分解して考えましょう、事例を探したり、単体テストしましょう
SELECTタグのOPTION値を受け取って処理を行う
そんなお話です。
/*
* 1.今回のキッカケ
*/
掲示板に下記の書き込みをいただきました。
------------
>内容としまして、プルダウンメニューとチェックボックスのある
>フォームでのデータ表示(テーブル)検索についてなのですが
>
>例えばデータはtest.mdbでmachineテーブル
>フィールドはそれぞれ
>ID:オートナンバー
>M_name:A,B,C,D,E,F
>M_number:1,2,3,4
>M_coments:コメント
>です。
>
>メインのフォームに
>プルダウンメニュー(M_nameのA,B,C,D,E,F)と
>チェックボックス4つ(M_numberの1,2,3,4)があります。
>※M_nameのアルファベットとM_numberの数字はそれぞれtest.mdb上
>に複数(重複)存在します。
>
>そこで検索例としまして
>「A」が"1"でそれぞれフォームで選択&チェックし、”表示”
>ボタンでフォーム下にテーブルとしてデータを表示したいと
>思い投稿させて頂きました。
>ちなみにチェックボックスは必須ではありません。
>チェックが無いときは、プルダウンメニューで選択したフィールド
>(A,B,C,D,E,F)の全フィールドを表示させるみたいに・・・と
>言う感じです。
---------------
前回の質問の処理も中途半端の尻切れトンボだったのに、
この回答者(Ken3)はダメだ頼りにならないと思われてもしかたない状態で、
再度チャンスが来たので、汚名挽回したいですね。
※なんて思いつつ、今回の回答もキレが無いんだけど
/*
* 2.処理を分解して考える
*/
社内ツールや自分が使うツールだと、
設計書を書かないで、要求だけ聞いて(目的だけ自分で考えて)
作り始めると思います。
が、最低限、入力と出力のイメージを書いておきます。
>メインのフォームに
>プルダウンメニュー(M_nameのA,B,C,D,E,F)と
>チェックボックス4つ(M_numberの1,2,3,4)があります。
FORMで入力された
SELECTタグの値 と CHECKBOXタグの値
を
受け取るのかぁ。
そして、SQL文を作成して、データの表示ですね。
SQL文の作成では、
チェック無しの時は、全てのデータを表示(全てにチェックと同様に扱う)
が注意ポイントかなぁ。
プログラムは流用だぁ〜
と
言えるくらい自分の記憶やライブラリ、社内資産がまとまっていれば楽なんだけど、
分解した処理で、自分がやったことが無い、そんな箇所をチェックしたり、
似ている処理を探したり、社内事例を検索する(webで事例を集めたりする)
※裁判で弁護士が過去の判例を検索して、被告の状況と比べる感じと似てるかなぁ。
/*
* 3.FORM SELECT タグのデータを受け取る
*/
自分のライブラリを見ると、チェックボックスの事例は、
No.45 HTML FORM INPUT TYPE="CHECKBOX" チェックボックスの入力
http://www.ken3.org/backno/backno_asp10.html#45
で簡単な解説、
http://www.ken3.org/cgi-bin/test/test045-1.asp
で、実際にCHECKBOXを使用したテストを行ってます。
あれれ、SELECTのタグのサンプル無いよ(笑)
ありそうで無かったんだなぁ。
だからSELECTタグってなんだよ。
^^^^^^^^^^^^^^^^
あっ、HTMLのFORMでプルダウンの選択を書く時のタグです。
<br>
あなたの好きなパリーグの球団は?
<SELECT name="pl">
<option value="lions">西武</option>
<option value="buffaloes">近鉄</option>
<option value="hawks">ダイエー</option>
<option value="marines">ロッテ</option>
<option value="fighters">日本ハム</option>
<option value="bluewave">オリックス</option>
</SELECT><br>
こんな感じで、SELECTとOPTIONのタグで構成されてます。
option value=""だとどうなるのか少し興味があったので、
あなたの好きなセリーグの球団は?
<SELECT name="cl">
<option value="">特に無しorわからない</option>
<option value="1">阪神</option>
<option value="2">中日</option>
<option value="3">ヤクルト</option>
<option value="4">巨人</option>
<option value="5">広島</option>
<option value="6">横浜</option>
</SELECT><br>
で、""特に無しを設定してみました。
FORMの入力と受け取ったデータを表示するサンプルを
http://www.ken3.org/cgi-bin/test/test092-1.asp
で、書いてみます。(ソースの全ても見れます。)
実際にテストしてみてください。
/*
* 4.値を受け取りSQLを発行する
*/
入力関係のテストが終了したので、
今度は、受け取った値を使用して、DBからデータを表示してみます。
<FORM ACTION="test092-2.asp" METHOD="POST">
<font color="blue">SELECT OPTION の 入力(選択) TEST</font><br>
<SELECT name="KUBUN">
<option value="">全てのデータ</option>
<option value="ASP">ASPのデータ</option>
<option value="VBA">VBAのコメント</option>
<option value="GUCHI">愚痴系</option>
<option value="24H">24Hコンビニ</option>
</SELECT>
<INPUT TYPE="submit" VALUE="検索する">
</FORM>
で、SELECT name="KUBUN"とデータを送り、
'KUBUNが送られてきたかチェックする
strKUBUN = Request.Form("KUBUN")
If Len(strKUBUN) <> 0 Then 'KUBUNが在りの時(0文字以上の時)
'KUBUNを条件にWHERE句を作る
strWHERE = "Where F_KUBUN = '" & strKUBUN & "' "
Else
'条件無しの時は、空白にしておく
srrWHERE = " "
End If
手抜きで、””の場合と送られてこなかった場合を判断するために、
Len関数で文字数が0以外かをチェックして、
WHERE句を作ってみました。
あとは、普通に、
'SQL文を作成する
strSQL = "Select * From KANSOU " '感想(KANSOU)テーブルから全項目(*)
strSQL = strSQL & strWHERE
strSQL = strSQL & "ORDER BY WriteTime DESC" '並べ替えは時間の降順
で、SQL文を組み立ててみました。
http://www.ken3.org/cgi-bin/test/test092-2.asp
でテストできます。(ソースの全ても見れます。)
/*
* 5.終わりの挨拶 </HTML>
*/
今回は、
SELECTタグで入力(選択)したデータを受け取るサンプルでした。
次回は、チェックボックスと組み合わせて使ってみたいと思います。
いろいろと問題点や疑問点を残しつつ、脱線・寄り道の多いメルマガですが、
今後とも、よろしくお願いします。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<FORM CHECKBOXから受け取った値を使用してWHERE句の作成>
こんにちは、三流プログラマーのKen3です。
今回は、
FORM CHECKBOXから受け取ったデータ
を使用して、WHERE句を作成してみます。
※いろいろなパターンが考えられるのでお好きなやつで。
(みなさんの丸秘テクニックがあったら、教えてください)
/*
* 1.今回のキッカケ
*/
入力フォームのチェックボックスでチェックされた値の使用方法を見直したいなぁ〜
と
思い、今回の発行となりました。
SQLのWHERE句を数パターン作ったので、参考になれば幸いです。
/*
* 2.名前(name="xxx")が一緒のパターンと違うパターン
*/
自分のライブラリを見ると、チェックボックスの事例は、
No.45 HTML FORM INPUT TYPE="CHECKBOX" チェックボックスの入力
http://www.ken3.org/backno/backno_asp10.html#45
で簡単な解説をしてますが、
TYPE="CHECKBOX"で
name="xxxx"が違うパターン
<INPUT TYPE="CHECKBOX" NAME="c1">HTMLから詳しく丁寧に<BR>
<INPUT TYPE="CHECKBOX" NAME="c2" VALUE="VBScript">VBScriptをもっと詳しく<BR>
<INPUT TYPE="CHECKBOX" NAME="c3" VALUE="GAME">ゲーム作ろうよ<BR>
name="xxxx"が同じパターン
<INPUT TYPE="CHECKBOX" NAME="kibou" VALUE="HTML">HTMLから詳しく丁寧に<BR>
<INPUT TYPE="CHECKBOX" NAME="kibou" VALUE="VBScript">VBScriptをもっと詳しく<BR>
<INPUT TYPE="CHECKBOX" NAME="kibou" VALUE="GAME">ゲーム作ろうよ<BR>
実際に、
http://www.ken3.org/cgi-bin/test/test045-1.asp
で、テストすると、
c1,c2,c3と違う場合はそれぞれ、
c1 on (Value=設定無し)
c2 VBScript (Value="VBScript"と値を指定)
など、
チェックした値をRequest.Form("c1")など項目別に取得することができます。
NAME="kibou"と各チェックボックスの名前が同じ場合は、
Request.Form("kibou")の共通の項目名で取得すると、
Valueで指定した値がVBScript, GAMEとカンマで区切られて取得できます。
/*
* 3.TYPE="CHECKBOX"でname="xxxx"が違うパターン
*/
値の受け渡しがなんとなくわかったので、
TYPE="CHECKBOX"でname="xxxx"が違うパターン で Where句を作成してみます。
入力は、
□VBA,□ASP,□24H,□GUCHI
と区分をチェックさせチェックありのデータをWhere句でor指定して取り出します。
<INPUT TYPE="CHECKBOX" NAME="ASP">ASP<br>
<INPUT TYPE="CHECKBOX" NAME="VBA">VBA<br>
<INPUT TYPE="CHECKBOX" NAME="24H">コンビニ系<br>
<INPUT TYPE="CHECKBOX" NAME="GUCHI">愚痴系<br>
と、NAME=の部分を4つ作成して、フォームを作りました。
ア.Ifの連続でWHERE句を作成してみた
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
オマエ何年プログラマーやってんの?
と
読者の心の声が聞こえる書き方で、WHERE句を作成すると、
'WHERE句を作成する
strWHERE = "" '条件を初期化する
'4つの区分をそれぞれ判断する
If Request.Form("VBA") = "on" Then 'VBAの判断
If strWHERE = "" Then
strWHERE = " Where KUBUN='VBA' "
Else
strWHERE = strWHERE & " Or KUBUN='VBA'"
End If
End If
If Request.Form("ASP") = "on" Then 'ASPの判断
If strWHERE = "" Then
strWHERE = " Where KUBUN='ASP' "
Else
strWHERE = strWHERE & " Or KUBUN='ASP'"
End If
End If
If Request.Form("24H") = "on" Then '24Hの判断
If strWHERE = "" Then
strWHERE = " Where KUBUN='24H' "
Else
strWHERE = strWHERE & " Or KUBUN='24H'"
End If
End If
If Request.Form("GUCHI") = "on" Then 'GUCHIの判断
If strWHERE = "" Then
strWHERE = " Where KUBUN='GUCHI' "
Else
strWHERE = strWHERE & " Or KUBUN='GUCHI'"
End If
End If
'SQL文を作成する (作成したWHERE句を組み合わせる)
strSQL = "Select * From KANSOU " '感想(KANSOU)テーブルから全項目(*)
strSQL = strSQL & strWHERE
strSQL = strSQL & "ORDER BY WriteTime DESC" '並べ替えは時間の降順
こんな感じかな。
テストは、
http://www.ken3.org/cgi-bin/test/test093-1.asp
で、実行できます。(カスイ 工夫無しのソースの全てもここで見れます。)
ポイントは、If文でRequest.Form("xxxx")それぞれの区分がonかチッェクして、
さらに前の条件が無ければWHERE あれば or にしただけです。
なんの工夫も無い、よく見かけるプログラムですよね。
イ.同じ処理なんだからループで回そうよ
さてと、みっともないプログラムを見せてしまいましたね。
お口直しのデザートじゃないのですが、
ArrayとUboundで項目名を管理して、同様のWhere句を作成してみました。
'WHERE句を作成する
strKUBUN = Array("VBA", "ASP", "24H", "GUCHI") '区分を配列にする
strWHERE = "" '条件を初期化する
'区分の数だけループさせる
For n = 0 To Ubound(strKUBUN)
If Request.Form(strKUBUN(n)) = "on" Then '区分n番目の項目がonか?
If strWHERE = "" Then '初めの項目か?チェックする
strWHERE = " Where F_KUBUN='" & strKUBUN(n) & "' "
Else '2番目以降はorでつなぐ
strWHERE = strWHERE & " Or F_KUBUN='" & strKUBUN(n) & "' "
End If
End If
Next
'SQL文を作成する (作成したWHERE句を組み合わせる)
strSQL = "Select * From KANSOU " '感想(KANSOU)テーブルから全項目(*)
strSQL = strSQL & strWHERE
strSQL = strSQL & " ORDER BY WriteTime DESC" '並べ替えは時間の降順
テストは、
http://www.ken3.org/cgi-bin/test/test093-2.asp
で、実行できます。(少し工夫したソースの全てもここで見れます。)
ポイントは、Array("VBA", "ASP", "24H", "GUCHI") で項目名の配列作成
For n = 0 To Ubound(strKUBUN)で0番目からループを作成して、
あとは、Request.Form(strKUBUN(n))やstrKUBUN(n)と使用しただけです。
少しはまとまったし、項目増やすだけで変更対応も容易になりました。
まぁ、なんだかんだ言っても、
If Request.Form("ASP") = "on"
If Request.Form(strKUBUN(n)) = "on"
など、項目単位にチェックして、Where句を作る方法でした。
/*
* 4.TYPE="CHECKBOX"でname="xxxx"を同じにしてVALUE=を区分とする
*/
個別にチェックする方法はどうでしたか?
次は、name="KUBUN"と同一にしてValueの値を使ってみます。
入力は、
□VBA,□ASP,□24H,□GUCHI
と区分をチェックさせまでは一緒ですが(見た目は一緒)
NAME="KUBUN"にしてVALUE="XXXX"を下記のように指定してみます。
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="ASP">ASP<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="VBA">VBA<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="24H">コンビニ系<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="GUCHI">愚痴系<br>
と、VALUE=の部分を4つ作成して、フォームを作りました。
ウ.Replaceで途中のカンマを置き換え WHERE IN句を使用する
Request.Form("KUBUN")とすると、
選択された項目がVBA, 24Hとカンマとスペースで区切られて渡ります。
これを利用して、
VBA, 24H
を
WHERE F_KUBUN IN ('VBA','24H')
と、IN句で条件を作ってみます。
'WHERE句を作成する
strKUBUN = Request.Form("KUBUN") 'フォームから区分を受け取る
If strKUBUN = "" Then '区分が選択されていなかったら
strWHERE = "" 'データ無しの時は条件をカラにする
Else ',を変換してWHERE句を作成する
' ASP, 24Hの文字を", "(カンマとスペース1つ)を','に変換する
strWORK = Replace(strKUBUN, ", ", "','") '置き換える
strWHERE = " Where F_KUBUN IN ('" & strWORK & "') "
End If
http://www.ken3.org/cgi-bin/test/test093-3.asp
でテストできます。(ソースの全ても見れます。)
ポイントは特に無く、
", "(カンマとスペース1つ)を','にReplace関数を使って変換してみました。
エ.Request.Form(xxx).Countで複数チェック
いろいろと探っていた副産物なのですが、
If Request.Form("KUBUN").Count > 0 Then '項目数をチェック
と、.Countで同じNAMEで送られて来たデータの個数を取得できます。
それと同時に、
項目名Name="KUBUN"と同一のデータが送られてきたときに、
Request.Form("KUBUN")(1) や Request.Form("KUBUN")(2)
とすると、個別に値を取得することが出来ます。
※(1)からデータが始まります。
※※(0)にはVBA, 24Hとカンマ区切りの値が格納されています。
これを利用して、
'WHERE句を作成する
If Request.Form("KUBUN").Count > 0 Then '項目数をチェック
'複数の時、1番目(最初の条件をまず代入)
strWHERE = " Where F_KUBUN = '" & Request.Form("KUBUN")(1) & "' "
'次の条件((2)から)をループで追加する
For n = 2 To Request.Form("KUBUN").Count
'Orで条件をつなげる
strWHERE = strWHERE & " Or F_KUBUN = '" & Request.Form("KUBUN")(n) & "' "
Next
Else
strWHERE = "" 'データ無しの時は条件をカラにする
End If
http://www.ken3.org/cgi-bin/test/test093-4.asp
でテストできます。(ソースの全ても見れます。)
ポイントは、Request.Form("KUBUN").Countで1以上の時はデータありと判断。
まず、一番目を代入して、
" Where F_KUBUN = '" & Request.Form("KUBUN")(1) & "' "
頭のWhereを付けて作成。
あとは、ループで2番目から数分ORを頭につけて作成してみました。
※Orで条件をつなげたけど、Where INで書くなら、下記のようにしてください
strWHERE = " Where F_KUBUN IN ('" & Request.Form("KUBUN")(1) & "'"
'次の条件((2)から)をループで追加する
For n = 2 To Request.Form("KUBUN").Count
'Orで条件をつなげる
strWHERE = strWHERE & ",'" & Request.Form("KUBUN")(n) & "'"
Next
strWHERE = strWHERE & ")" '最後忘れずに)で閉じてね。
/*
* 5.終わりの挨拶 </HTML>
*/
今回は、
CHECKBOXの値を使って、複数の条件を受け取り、
WHERE句を作成する方法を数パターン書いてみました。
自分にあった方法を使ってみてください。
次回は、
やっと質問の処理、プルダウンとチェックボックスの組み合わせをやってみます。
いろいろと問題点や疑問点を残しつつ、脱線・寄り道の多いメルマガですが、
今後とも、よろしくお願いします。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<2進数文字列と16進文字列の変換処理に挑戦>
こんにちは、三流プログラマーのKen3です。
今回は、
2進数文字列と16進文字列の変換処理に挑戦してみます。
/*
* 1.今回のキッカケ
*/
文字コードなどの変換で、16進数から2進文字列を作りたかったので、
自作してみました。
意外とハマりました。
16進数 F2 を 11110010 など、2進数の文字列に直したい。
逆に
10100011 を A3 にしたい、
と
質問をもらった。
/*
* 2.16進数文字列を2進数文字列に直す
*/
いろいろとやり方があるのですが、8421で計算してみました。
0 --> 0000
1 --> 0001
2 --> 0010
3 --> 0011
・
・
9 --> 1001
A --> 1010
B --> 1011
など、変換表を作成しておいて、置きかえる方法もあるし、
2で割っていったり計算で求めたりとイロイロとありますが、
三流君らしい、下記のサンプルを作ってみました。
処理のポイントは、
F3などの16進文字列から1文字取出します。
Fを取出します。でもこれは文字なので数値に変換したいです。
そこで a = CInt("&H" & "F") と、文字列から数値変換の標準関数Cintを使い、
変換します。
ここから、さらに一工夫して、ビットが8 4 2 1 となっているので、
まずF(15) で、8が立っているか調べるために and 演算しました。
If (nCHK And n8421) = 0 で判断してます。
次は4を調べるので/2で割って、4回、まわしてます(小細工)
これで、ビットを調べて0と1の文字列を作成してます。
http://www.ken3.org/cgi-bin/test/test094-1.asp?DATA=F2
でテスト実行できます。
ソースは下記で、回しながら処理を行ってます。
<%
'HEX16進文字列を受け取り2進数文字列を返す
Function HEX16toSTR2(strHEX)
Dim n 'ループカウンタ
Dim i 'ループのカウンタ
Dim n8421 '8 4 2 1の数値計算用
Dim str2STR
Dim nCHK
str2STR = "" '結果のエリアを初期化する
'文字数分ループする
For n = 1 To Len(strHEX)
nCHK = CInt("&h" & Mid(strHEX, n, 1)) 'n文字目を数値変換
n8421 = 8 '初期値に8を代入する(上からチェックしたいので)
For i = 1 To 4 '4回まわるよ
If (nCHK And n8421) = 0 Then 'Andでビットをチェックする
str2STR = str2STR & "0" 'ビットは立ってないよ
Else
str2STR = str2STR & "1" 'ビットは立ってるよ
End If
'次のビットをチェックしたいので2で割る
n8421 = n8421 / 2
Next
Next
'リターン値をセットして終了
HEX16toSTR2 = str2STR
End Function
%>
※G5など、16進数に無い表記だとエラーが発生してしまうが、
それなりに動作してます。エラーチェック入れねば・・・
/*
* 3. 2進数文字列を16進数文字列に直す
*/
今度は、逆で、1010をAに変換する番です。
1010 これは、8+2です。
えっなんで? 8 4 2 1 と 4つをポイントにビットが立っていたら計算してます。
そんな感じのサンプルが下記のサンプルです。
ポイントは、
0と1を判断して、8 4 2 1の順で数値を+して行き、
4つ単位でHEX関数で、16進に変換してます
<%
'2進文字列を受け取り16進文字列を返す
Function STR2toHEX16(str2)
Dim strHEX
Dim n 'ループカウンタ
Dim i 'ループのカウンタ
Dim n8421 '8 4 2 1の数値計算用
Dim nBYTE
strHEX = "" '結果のエリアを初期化する
'文字数分ループする
For n = 1 To Len(str2) Step 4 '4文字(1バイト)単位にループを作る
n8421 = 8 '初期値に8を代入する(上から計算したいので)
nBYTE = 0 '1バイト計算用変数を初期化
For i = 0 To 3 '4回まわるよ(4ビット分)
'ビットが立っているかチェックする
If Mid(str2, n + i, 1) = "1" Then
nBYTE = nBYTE + n8421 'ビットに対応した数値を+する
End If
'次のビットを計算したいので2で割る
n8421 = n8421 / 2
Next
'計算して、1倍との数値が完成したので16進文字にしてセットする
strHEX = strHEX & Hex(nBYTE)
Next
'リターン値をセットして関数を抜ける
STR2toHEX16 = strHEX
End Function
%>
上から順番にビットをチェックしていき、8421の順で繰り返してます。
/*
* 4.データが4ビット単位じゃないとバグるよ
*/
なんとか、出来たと思いつつ、バグを発見。
4つ単位でデータが作られればいいけど、
頭の0を省略します。
0111と書いてほしいんだけど、
111なんてデータがくると、
私の処理だと違う数値に変換してしまいます。
後ろからみる
や
桁数のチェック
なんてエラー処理、確認処理が必要です。
ア.初めに桁をチェックする
問題なのが、
111と3桁の2進数文字列が来ると、8+4+2をやってしまいます。
0111と送られてくれば、4+2+1で7と計算されるのに。
とするなら、強引に、3桁111を4桁0111にしてしまうそんな処置を足してみました。
'頭4文字単位かチェックする
n = Len(str2) Mod 4 '足りない文字数を計算する
If n <> 0 Then
str2 = String(4 - n, "0") & str2 '頭に文字0を追加する
End If
2進数文字列を受け取りHEX16進文字列を返す(頭0を+する)
http://www.ken3.org/cgi-bin/test/test094-2.asp?DATA=111
で、テストできます。(無事7と表示されるか、、、)
イ.後ろから計算してみる。
問題なのは、111を頭から4桁と決め付けて8+4+2を+してるからだろ
だったら、後ろから、1+2+4+8+16+32+64...で計算しろよ、
と、考え方を変えたのが下記の変換プログラムです。
2進数文字列を受け取りHEX16進文字列を返す(頭0を+する)
http://www.ken3.org/cgi-bin/test/test094-3.asp?DATA=111010
で、テストできます。(6桁の11 1010を変換すると3Aとなるはず?)
<%
'2進文字列を受け取り16進文字列を返す(後ろからチェック)
Function STR2toHEX16_B(str2)
Dim strHEX
Dim n 'ループカウンタ
Dim i 'ループのカウンタ
Dim n8421 '8 4 2 1の数値計算用
Dim nBYTE
strHEX = "" '結果のエリアを初期化する
n8421 = 1 '初期値に1を代入する(下から計算したいので)
nBYTE = 0 '計算用変数を初期化
'文字数分ループする
For n = Len(str2) To 1 Step -1 '後ろからループを作る
'ビットが立っているかチェックする
If Mid(str2, n + i, 1) = "1" Then
nBYTE = nBYTE + n8421 'ビットに対応した数値を+する
End If
'次のビットを計算したいので*2で計算 1.2.4.8.16.32...としたい
n8421 = n8421 * 2
Next
'計算して、数値が完成したので16進文字にしてセットする
strHEX = Hex(nBYTE)
'リターン値をセットして関数を抜ける
STR2toHEX16_B = strHEX
End Function
%>
処理のポイントは、
文字列を後ろから見るために、逆順のループを作ってみました。
For n = Len(str2) To 1 Step -1 '後ろからループを作る
で、次のポイントが、
'次のビットを計算したいので*2で計算
n8421 = n8421 * 2
2進数は*2で次の位が求められるので、単純にカケテ次の位を計算してます。
If Mid(str2, n + i, 1) = "1" Then
nBYTE = nBYTE + n8421 'ビットに対応した数値を+する
End If
あとは、ビットが立っていたら+しているだけです。
最後はHEX関数で、変換しただけです。
こんな感じで、プログラムを一から見直して、作成してみました。
/*
* 5.終わりの挨拶 </HTML>
*/
今回は、
2進数文字列と16進数文字列の変換処理を少しやってみました。
もっと効率の良いやり方があると思いますが、
1つの参考例になれば幸いです。
いろいろと問題点や疑問点を残しつつ、脱線・寄り道の多いメルマガですが、
今後とも、よろしくお願いします。
何かの参考となれば幸いです。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
三流君のHP主な飛び先
分類別ガイド
[アクセスランキング ]
[サイトマップ ]
[リンク先・相互リンク先など ]
Ken3の日記(weblog) --
[広告・副収入系 ]
[プログラマー業務の愚痴 ]
[VBA系の話題 ]
[ASP系の話題 ]
[コンビニ系ネタ ]
[その他 ]
種類別のサービス紹介ページ
[イーバンク銀行(eBANK)の口座開設 ]
[ジャパンネットバンク(JNB)の口座開設 ]
[ネットで小遣い稼ぎ(笑) ]
[在宅プログラマー/SOHO ]
[プログラマー転職/派遣/就職 ]
[バナー広告アフィリエイトで稼ぐ実態 ]
種類別の商品 通信販売ページ
[自作PCパーツ ]
[ゲームソフトの通信販売 ]
[CD/DVD/ビデオ ]
[花・フラワー ]
[ダイエット・健康食品・サプリメントの通信販売 ]
[美容・化粧品の通信販売 ]
[ブランド・ジュエリー・香水の通信販売 ]
[グルメ・おいしい食品の通信販売 ]
[日本酒・焼酎の通信販売 ]
[ワインの通信販売 ]
[チーズの通信販売 ]
[デザート・お菓子の通信販売 ]
[ペット関係 ]
ネットワーク関係
ネットワーク技術が基礎から身につく 日経NETWORK
最適ソリューションを実現するための実務専門誌「日経システム構築」
Web制作・Webクリエイター - All About [Webプロデュース]
サンプル・ライブラリ・素材 - All About [JavaScript]
All About [ビジネスへのネット活用]
All About [ソフトウエアエンジニア]