三流君ASPで遊ぶ、失敗する

[三流君] Top ken3.orgへ
[ASP解説] ASPの解説TOP
[ASP記事 バックナンバー] 番号順のバックナンバー
[SOHO/在宅プログラマー/派遣] 派遣のお話ほか
[...サイトマップ(総合案内へ)]




分類別ガイド
ADOで[ADO Mdb接続] ,[ADO Excel接続] ,[ADO CSV接続]

[ASP Form データのやりとりPOSTとGET]
[ASPでTextFile操作]
[ASPでVBScriptを使う]
[その他サンプル]

バックナンバー No.60 〜 No.64


No.60 2003/06/03
しつこい加筆解説、学習方法、拾ったサンプルソースをものにする方法
[ページTOPへ戻る]

<しつこい加筆解説、学習方法、拾ったサンプルソースをものにする方法>

こんにちは、三流プログラマーのKen3です。 前回のNo.59に文章を付け足しただけですが 学習方法、拾ったサンプルソースをものにする方法 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ として、再度追加発行します。 発行前にもっと内容、見たほうがよかったですね。 くだらない解説付のほうがいいのか? それとも マジメな解説がいいのか? 迷うところだけど。 基準として、 同じネタでも毒吐いてるのは、 http://www.ken3.org/guchi/ のプログラマー愚痴系で、 http://www.ken3.org/asp/ のASP系は、マジメに解説しようと思っているのですが、 同じ作者なので、時々、まざってしまうけど、ご勘弁を。 拾い読みして、何かの参考となれば幸いです。

/* * 1.今回のキッカケ */

ASPでExcelの処理、ADO使ってごまかしたけど、 他に方法無いか?模索中・・・・ そしたら、マイクロソフトのHPから、おっ?と思うサンプルを拾う。 拾ったサンプルを自分のものにした、そんなストーリーを書きます。 元ネタは、ASPですが、他の言語でもやりかたは一緒だと思うので、 何かのきっかけとなれば、、、、 いつもの三流プログラマーの語りから、何かをつかんでくれれば幸いです。

/* * 2.拾ったサンプル */

ASP Excel でいろいろと検索、巡回してました。 いろいろと出てきますねぇ、要望が多いのかなぁ。 私のつぶされそうなカスページにもポツポツ検索で来るし、 おっ、マイクロソフトのサンプルページかぁ、 よし、見てみるか。 ※てな感じで、みなさんも必要なサンプルを探していると思います。 http://msdn.microsoft.com/library/en-us/dnwebteam/html/webteam07032000.asp ちっ、ここも英語かよ、日本語のサンプルは無いの? それとも日本語化される前に、ASP.NETになっちゃったの? サンプル、見つかっても英語の時、ガックリ来ますよね。 なんて前置きは置いといて、 いつもの台詞で、英語読めないけどプログラムソースはなぜか読める そんな三流プログラマーが下記のソースを拾ってきた。 ※ページの下のほうに転がってました あきらめないで、読めないのに軽く流し読みすると、 たまに自分の目にソースファイルが飛び込んでくる。 英語読めないけど(コメントやメッセージの意味は不明) でも、VBAやASPの言語仕様は万国共通なので、 ソースファイルはなぜか不思議とある程度は読むことが出来ると思う。 <%@ language=vbscript %> <% response.buffer = true response.ContentType = "application/vnd.ms-excel" response.AddHeader "content-disposition", "inline; filename=dynamic.xls" response.write "<table width=200>" response.write "<tr>" for i = 1 to 4 response.write "<td width=40>" response.write i + i response.write "</td>" next response.write "<td width=40><b>=sum(A1:D1)</b></td>" response.write "</tr>" response.write "</table>" response.flush response.end %> response.writeで出力しているみたいだなぁ、 で、中身をざっと見てみると、 response.ContentType = "application/vnd.ms-excel" response.AddHeader "content-disposition", "inline; filename=dynamic.xls" とExcel処理の匂いがプンプン。 ※夏の女性の匂いに引き付けられないで、  サンプルの匂いに魅かれてちゃダメだよ。 ここで、私がもしかしたら使えるのかも?と思ったのが、 response.write "<td width=40><b>=sum(A1:D1)</b></td>" と、セルの集計関数の=Sumを使っている場所。 データだけならCSV経由でサーバーから落として、 あと好きなように加工してね、、とやるんだけど、 もし=Sumなどワークシート関数使えるなら、 結果をASPからExcelで返す時、いろいろと使えるのでは? で、上記ソースをまるごとコピーして、実行してみました。 http://www.ken3.org/cgi-bin/test/test059-1.asp で実行できます。 すると、いつものxlsファイルを開く、保存の警告メッセージ。 ってことは、Excelのファイルとして認識? ※↑メッセージ画面 開くを選択して、開いてみると、=SUMの計算式が埋まっていた。 ※↑開いたイメージ。

/* * 3.拾ったサンプルを解析して自分のものにする */

さてと、そんな方法でExcelファイルを返すことが出来たので、 拾ったサンプルを自分のものにするために、 わからないことを探りますか。 ここが学生さんのレポートを丸写しで終わっていた課題と違うところかな ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 自分のものにしないとメルマガ読んでるだけじゃ意味無しですよ。 response.buffer = true を調べると、 response.buffer = true の時は、出力をバッファして、 response.flush 途中でバッファを出力 response.end  ASPの処理を中止し、現在までの結果を返すのかぁ。 なるほどね。 関連項目として、今回出てこなかったけど、 response.clear ってのがあって、バッファに格納された出力をクリアすることが出来ます。 このクリアを使って、エラーが発生したら、途中までの出力を消して、 エラーのメッセージ画面を表示することも出来そうです。 ※また注意事項として、  response.buffer = trueは、<Html>などの出力の前に行うことです。  まぁ、出力のバッファだから、一番最初にやれってことね。 こんな、流れで、自分の知らない命令をヘルプで調べたり、 初めの調査はASP Excelだったのに、 芋ずる式にresponse.bufferを調べるようになり、自分のものになっていく。 また、自分で調べると関連項目、ここではサンプルに載っていなかった response.clear って出力をクリアする処理をついでに覚えて、 途中までの出力をクリア(キャンセル)して、新たなエラーなどを出力できる。 そんな処理方法まで、学習してしまった。 次は、 response.ContentType = "application/vnd.ms-excel" これは、今から送るデータのタイプは、 "application/vnd.ms-excel" ですよ、とブラウザに教えるために書きます。 response.ContentType = "imge/gif" など、指定します。 文字データだけじゃなくて、ASPでいろいろと出来るんだね、、と感じた。 ここは、これで止めてしまったが、 自分の学習リストをメモ帳などのテキストで残しておき、 ヒマなとき、response.ContentType = "imge/gif"を調べる、、、 なんてやっておくと、幅広く知識を吸収できます。 response.AddHeader "content-disposition", "inline; filename=dynamic.xls" これは、詳しく載っていなかったけど、 動作や.AddHeaderから判断すると、ヘッダ情報にファイル名を載せている感じです。 response.write "<table width=200>" response.write "<tr>" ↑この、Excelファイルなのに、普通のテーブルってのが不思議だけど、  ※不思議に感じたら、調べろよ、なぜか?理由があるダロ。   疑問のまま素通りすると、私みたいな三流プログラマーなんですね。   こんな疑問も、テキストファイルのリストに書いておくといいですよ。   (貯まっていくと、イヤになったり、どれからやるか迷うので、    ほどほどにね。。。) for i = 1 to 4 response.write "<td width=40>" response.write i + i response.write "</td>" next TDだから、横に数値を書き込んで、 ※自分で知識があるから、さらっと読めるけど(読めたけど)  ASPやHTMLやったこと無い人は、<TD>って何?  から解析に入らないといけないので、  ソースを拾って読むには、ある程度の知識が必要とフト思いました。 response.write "<td width=40><b>=sum(A1:D1)</b></td>" ここが一番感動した、 =Sum とワークシート関数を入れている部分です。 普通にテーブルイメージなんですね。 ※解析してて嬉しくなる、、そんな感覚があると思います。  下ばかり見て歩いてないで、周りをよく見て歩いていたら、  風がふいて・・・いいもの目撃・発見、、なんてことは無いかな(謎)  変な想像したアナタ、あたりだよたぶんその想像が(笑) response.write "</tr>" 行の終了、 response.write "</table>" テーブルの終了 response.flush バッファを出力 response.end ASP終了 って流れでした。 こんな感じで、拾ってきたソースサンプルを 自分の知識にすることができました。 なんて流れるように書いてるけど、 これは私の数少ない成功例 ^^^^^^^^^^^^^^^^^^^^^^^^ 実際は、解析途中で断念したり、 棚上げ後回しの拾ってきたソース君達も多いです。 全て、こんな方法で知識を吸収はできないのですが、 方法の1つとして、感覚だけでもつかんでもらえて、 成長のキッカケとなればうれしいです。

/* * 4.終わりの挨拶(次回はアルのか?(爆)) */

内容は同じだったのですが、 学習をテーマに加筆してみました。 たまにこんな感じで、加筆発行するかもしれませんが、 よろしくお願いします。 ※あっ、うざいって人は、  http://www.mag2.com/m/0000099248.htm  でメルマガの方を解除して、 http://www.ken3.org/asp/ のHPをたまに覗きに来て下さい。  内容は同じなので。 何か読者の心に残れば、うれしいです。 *私の独り言をうまく消化してくださいね。 いつも失敗?のKen3でした。 ~~~~~~~(↑オイオイ)

No.61 2003/06/04
SJIS--JISのコード変換
[ページTOPへ戻る]

<SJIS--JISのコード変換>

こんにちは、三流プログラマーのKen3です。 今回は、 シフトJISからJISコードへ、コード変換を行ってみます。 拾い読みして、何かの参考となれば幸いです。

/* * 1.今回のキッカケ */

VBA系のメルマガ( http://www.ken3.org/vba/ ) で、 シフトJISからJISコードへ、コード変換を行ってみたので、 ASP(VBScript)でもやってみます。

/* * 2.VBAの自作関数を移植する。 */

VBA系のメルマガ No.79 SJIS--JISコードの文字列を作成したい で、下記の変換関数を作成しました。 ※式、コードの意味などは、 http://www.ken3.org/backno/backno_vba16.html#79 を見てください。 'シフトJISコードの文字列を受け取り、JISコードを返す
Function SJIStoJIS(strSJISCODE As String) As String

    Dim hi As Long
    Dim lo As Long

    'シフトJISコードの上位バイトを hi、下位バイトを lo とします。
    hi = Val("&h" & Mid(strSJISCODE, 1, 2))
    lo = Val("&h" & Mid(strSJISCODE, 3, 2))

    'hi が 0x9f 以下の場合、 hi から 0x71 減じます。
    'そうでない場合、 hi から 0xB1 減じます。
    hi = hi - IIf(hi <= &H9F, &H71, &HB1)
    
    'hi に 2 を乗じて、さらに 1 を加えます。
    hi = hi * 2 + 1
    
    'lo が 0x7F より大きい場合、 lo から 1 減じます。
    If lo > &H7F Then lo = lo - 1
    
    'lo が 0x9E 以上の場合、lo から 0x7D 減じて、hi に 1 加えます。
    If lo >= &H9E Then
        lo = lo - &H7D
        hi = hi + 1
    Else 'そうでない場合、 lo から 0x1F 減じます。
        lo = lo - &H1F
    End If

    '結果を返します
    SJIStoJIS = Right("0" & Hex(hi), 2) & Right("0" & Hex(lo), 2)

End Function
まぁ、VBScriptでも、普通に動くだろ、 変数やりターン値の AS XXXXX の型指定が出来ないから、それは取って 組み込み実行すると。 Microsoft VBScript 実行時エラー エラー '800a000d' 型が一致しません。: 'Val' /cgi-bin/test/test061-1.asp, 行 61 オイオイ、Val関数って使えないのかよ。 ※いつも思うけど、  型が一致しないとメッセージでるから、送り側の変数が悪いのか?  と見当違いのデバックしてたよ。  型が一致しません。じゃなくて、関数が見つかりませんのほうがいいのにね。 'シフトJISコードの上位バイトを hi、下位バイトを lo とします。 hi = Clng("&h" & Mid(strSJISCODE, 1, 2)) lo = Clng("&h" & Mid(strSJISCODE, 3, 2)) と Clng関数を使用に変更しました。 えっ、まだダメなの? Microsoft VBScript 実行時エラー エラー '800a000d' 型が一致しません。: 'IIf' /cgi-bin/test/test061-1.asp, 行 66 あらら、IIfもVBScriptは無いんだぁ。 一行で書いてる処理をバラすか。 If hi <= &H9F Then hi = hi - &H71 'hi が 0x9f 以下の場合、 hi から 0x71 減じます。 Else hi = hi - &HB1 'そうでない場合、 hi から 0xB1 減じます。 End If と 普通に書きました(笑)

/* * 3.テストモジュールを組み込む */

http://www.ken3.org/cgi-bin/test/test061-1.asp?DATA=Ken3%82%CD%8EO%97%AC でテストすると、 受け取ったデータは[Ken3は三流]です バイト数は、10Byteです 1文字目は[K] をAscで変換すると75 さらにHexで16進数にすると4B 2文字目は[e] をAscで変換すると101 さらにHexで16進数にすると65 3文字目は[n] をAscで変換すると110 さらにHexで16進数にすると6E 4文字目は[3] をAscで変換すると51 さらにHexで16進数にすると33 5文字目は[は]をAscで変換すると-32051さらにHexで16進(SJIS)は82CD JISコードは244F 6文字目は[三]をAscで変換すると-29105さらにHexで16進(SJIS)は8E4F JISコードは3B30 7文字目は[流]をAscで変換すると-26708さらにHexで16進(SJIS)は97AC JISコードは4E2E 使用したテストモジュールは、 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <%@LANGUAGE=VBScript%> <html> <head> <title>SJISからJISコードに変換、文字コード関係で遊ぶ</title> </head> <body> <h2>SJISからJISコードに変換、文字コード関係で遊ぶ</h2> <br> 自作したSJIS--JIS変換ルーチンを呼んでます。<br> ※詳細は、ソースと詳細解説のページを見てください。<br> <hr> <% CHK_DATA = Request.QueryString("DATA") 'パラメータの代入 '長さをチェックする If Len(CHK_DATA) <> 0 Then '文字が入っていたら Response.Write "受け取ったデータは[" Response.Write Server.HTMLEncode(CHK_DATA) & "]です<br>" '関数を呼んで、バイト数を表示する Response.Write "バイト数は、" & Byte_Count(CHK_DATA) & "Byteです<br>" '文字数分ループして、コードを表示 For n = 1 To Len(CHK_DATA) Response.Write n & "文字目は" strWORK = Mid(CHK_DATA, n, 1) 'n番目の文字を取り出す Response.Write "[" & Server.HTMLEncode(strWORK) & "] " Response.Write "をAscで変換すると" & Asc(strWORK) strCODE = Hex(Asc(strWORK)) If Len(strCODE) <= 2 Then '半角か? Response.Write " さらにHexで16進数にすると" & strCODE Else Response.Write " さらにHexで16進(SJIS)は" & strCODE Response.Write " JISコードは" & SJIStoJIS(strCODE) End If Response.Write "<BR>" & vbCRLF Next End If %> <HR> <FORM ACTION="test061-1.asp" METHOD="GET"> 調査したい文字列を入力してください。<br> <INPUT TYPE="text" SIZE="30" NAME="DATA" VALUE="<%=CHK_DATA%>"> <INPUT TYPE="submit" VALUE="コード調査開始"><br> ↑いろいろと遊んでみてください↑ </FORM> <br> </body> </html> <% 'SJISコードの文字列を受け取り、JISコードの文字列を返す
Function SJIStoJIS(strSJISCODE)

    Dim hi 
    Dim lo 

    'シフトJISコードの上位バイトを hi、下位バイトを lo とします。
    hi = Clng("&h" & Mid(strSJISCODE, 1, 2))
    lo = Clng("&h" & Mid(strSJISCODE, 3, 2))

    If hi <= &H9F Then 
      hi = hi - &H71 'hi が 0x9f 以下の場合、 hi から 0x71 減じます。
    Else
      hi = hi - &HB1 'そうでない場合、 hi から 0xB1 減じます。
    End If

    'hi に 2 を乗じて、さらに 1 を加えます。
    hi = hi * 2 + 1

    'lo が 0x7F より大きい場合、 lo から 1 減じます。
    If lo > &H7F Then lo = lo - 1

    'lo が 0x9E 以上の場合、lo から 0x7D 減じて、hi に 1 加えます。
    If lo >= &H9E Then
        lo = lo - &H7D
        hi = hi + 1
    Else 'そうでない場合、 lo から 0x1F 減じます。
        lo = lo - &H1F
    End If

    '結果を返します
    SJIStoJIS = Right("0" & Hex(hi), 2) & Right("0" & Hex(lo), 2)

End Function
'文字列を受け取り、バイト数を返す
Function Byte_Count(strMOJI)
  bcnt = 0
  '文字数分ループして、コードを表示
  For n = 1 To Len(strMOJI)
    nCODE = Asc(Mid(strMOJI, n, 1))  'n番目の文字コードを求める
    If (nCODE And &HFF00) = 0 Then  'コードは1バイトか? *asp055
      bcnt = bcnt + 1
    Else
      bcnt = bcnt + 2
    End If
  Next
  'リターン値をセットする
  Byte_Count = bcnt
End Function
%>
http://www.ken3.org/cgi-bin/test/test061-1.asp でいろいろな文字を入れて、遊んでみてください。

/* * 4.終わりの挨拶 </HTML> */

今回は、 ・VBAで作成したJISコードの変換モジュールを移植してみました。 ・Val関数は使えない ・IIf関数は使えない って話でした 何かの参考となれば幸いです。 素朴な疑問やリクエスト、クレームなどがあったら、 掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi に気軽に書き込んでください。 ASP、VBScript勉強中の三流プログラマーのKen3でした。 ---------------------------------- 関連項目(ただのバックナンバー紹介) ---------------------------------- VBA系のメルマガ No.79 SJIS--JISコードの文字列を作成したい http://www.ken3.org/backno/backno_vba16.html#79 変換の式、調査方法などを見てください。

No.62 2003/06/05
日付関係の復習、YYYYMMDDを返すFunction関数を作成する
[ページTOPへ戻る]

<日付関係の復習、YYYYMMDDを返すFunction関数を作成する>

こんにちは、三流プログラマーのKen3です。 今回は、 日付、時刻関係の関数の復習 と VBScriptにVBAでよく愛用していたFormat関数が使えないので、 自作でYYYYMMDDを返すFunction関数を作成してみます。

/* * 1.今回のキッカケ */

HPで訪問者のログを収集してます。 http://www.ken3.org/cgi-bin/cnt/log100.asp リンク元、GoogleやYahooからの探し物のお客さんが意外と多いです。 で、最近、よく見かけるのが、 http://www.google.co.jp/search?hl=ja&ie=UTF-8&q=ASP+Format&lr=lang_ja と ASP Formatとキーワードにして私のページにたどり着く人です。 ADO から MDB へのSQL文でFormat関数使用 http://www.ken3.org/cgi-bin/test/test040-1.asp が、検索に引っかかってしまいます。 ADOのSQL文で使用可能な例題、 Select Format(WriteTime, 'YYYYMMDD') AS YYYYMMDD, Count(*) AS CNT From log GROUP BY Format(WriteTime, 'YYYYMMDD') が拾われてしまうみたいです。 ※Format関数、ASP(VBScript)には無いです、 そして、訪問者は、 ちぇ、期待してきたけど時間つぶしてしまった。。。 ~~~~~~~~~~ と去って行くのであった。(マル) 少しでもお客さんを取り込むには、品揃えを充実させよう。 ってことで、復習を兼ねてYYYYMMDDを返す自作関数を作ってみます。 ※Format関数って、12.5とか数値も扱ってたし、yyyy-mm-dd形式も?  って心の中で叫ばないでね・・・

/* * 2.事前調査、各部分を取り出す関数を調べる */

ASP,VBScriptでFormat関数使えないんだよなぁ。。。 日付関係の関数を駆使して、文字列を作成するか。 えっと、現在時刻はNow関数でわかるから、 あとはこれを変換しながら、調べた関数をチェックしますか。 年 Year() 月 Month()  日 Day() 曜日 Weekday() 1:日曜〜7:土曜の数値を返す WeekDayName(数値)で曜日文字 時 Hour() 分 Minute() 秒 Second() と、いろいろな変換関数存在するので、 関数に日付の値を渡すと変換できそうです。 http://www.ken3.org/cgi-bin/test/test062-1.asp で、下記のテストプログラムを実行可能です。 <%@LANGUAGE=VBScript%> <html> <head> <title>VBScript/Year/Month/Day/WeekDay/Hour/Minute/Secound 関数使用例</title> </head> <body> <h2>VBScript関数<br>Year/Month/Day/WeekDay/Hour/Minute/Secound 関数使用例</h2> <!-- Ken3 --><!-- #include file="info.inc" --> <br> 現在時刻を返すNow関数と組み合わせて下記の関数を使用してみました。<br> <hr> 年 Year(変数や値)=<%=Year(Now)%><br> 月 Month(変数や値)=<%=Month(Now)%><br> 日 Day(変数や値)=<%=Day(Now)%><br> 曜日 Weekday(変数や値)=<%=Weekday(Now)%>(←1:日曜〜7:土曜の数値)<br> 曜日の名前 WeekdayName(1〜7)=<%=WeekdayName(Weekday(Now))%><br> ※通常日付を渡すんだけど、↑WeekdayNameだけ数値に対応した曜日文字を返す<br> <hr> 時 Hour(変数や値)=<%=Hour(Now)%><br> 分 Minute(変数や値)=<%=Minute(Now)%><br> 秒 Second(変数や値)=<%=Second(Now)%><br> <hr> <br> </body> </html>

/* * 3.2003/6/5を20030605と一桁の月日は頭0を付ける */

あとは組み合わせて、一桁の時、頭0付けかぁ。 Right("0" & 変数, 2) と小細工で、0と+してから、右端から2文字取るかな。 T = Now() strMM = Right("0" & Month(T)), 2) strDD = Right("0" & Day(T)), 2) YYYYMMDD = Year(T) & strMM & strDD うわ、なんかダサ(笑) ここまで来たら、関数名もFormatYYMMDD(引数)でイイヤ 値を返すんだからFunctionの関数にしてと、 下記のようにしてみました。 http://www.ken3.org/cgi-bin/test/test062-1.asp で、下記のテストプログラムを実行可能です。 <%@LANGUAGE=VBScript%> <html> <head> <title>YYYYMMDDの文字列を返す関数を作ってみた</title> </head> <body> <h2>YYYYMMDDの文字列を返す関数を作ってみた</h2> <!-- Ken3 --><!-- #include file="info.inc" --> <br> 日付を渡すと、YYYYMMDDの形式で文字列を返す関数<br> その名もFormatYYYYMMDD(笑)<br> <hr> FormatYYYYMMDD(Now)は<%=FormatYYYYMMDD(Now)%>と変換される。<br> ログファイル名を作るときは、<br> strLOGNAME = FormatYYYYMMDD(Now()) & ".log" なんて使う<br> <% strLOGNAME = FormatYYYYMMDD(Now()) & ".log" %> <%=strLOGNAME%><br> <hr> なんかなぁ、、、もっと勉強して、使える関数作らないとなぁ。<br> <hr> <br> <!-- Ken3 --><% Call OUT_SRC("") 'ソースの表示関数を呼ぶ %> <!-- Ken3 --><!-- #include file="inc_mokuji.inc" --> </body> </html> <!-- Ken3 --><!-- #include file="out_src.inc" --> <% '受け取った日付データを変換してYYYYMMDDの文字列で返す
Function FormatYYYYMMDD(cnvMOTO)

  '念のため日付型に変換可能かチェックする
  If IsDate(cnvMOTO) = False Then
    FormatYYYYMMDD = "" '変換エラーの時は空文字を返すようにする
  Else
    strMM = Right("0" & Month(cnvMOTO), 2)  '月の変換
    strDD = Right("0" & Day(cnvMOTO), 2)    '日の変換
    'リターン値で結果を返す
    FormatYYYYMMDD = Year(cnvMOTO) & strMM & strDD
  End If

End Function
%>
頻繁に、変換処理しないと、あまり関数化の意味無いかなぁ。

/* * 4.終わりの挨拶 </HTML> */

ほんとは、偽のSQL文とか使って、 ADOでFormat関数を使えないかなぁと探ったけど、断念しました。 で、 なんか今回は、単なる日付関数紹介でした。 何かの参考となれば幸いです。 素朴な疑問やリクエスト、クレームなどがあったら、 掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi に気軽に書き込んでください。 ASP、VBScript勉強中の三流プログラマーのKen3でした。

No.63 2003/06/08
Application.Lock .Unlockを使ってみた
[ページTOPへ戻る]

<Application.Lock .Unlockを使ってみた>

こんにちは、三流プログラマーのKen3です。 今回は、 同時アクセス、排他制御もどきで、 Application.Lock .Unlockを使ってみた そんなお話です。

/* * 1.今回のキッカケ */

HPで訪問者のログを収集してます。 DBに追加されていくので、削除しないとデータが増えてしまいます。 ※当たり前でしょ(笑) 自社のサーバーなら、日替わり処理で、 タスクのスケジュールで、 SQL Delete文を発行すれば、済んでしまうんだけど、 レンタルサーバーだと、そんな処理タイミングを作ることが出来ません。 面倒だけど、削除のSQL文が入ったASPファイルを自分で実行してました。 なんとか、自動化できないかなぁ、、、と考えてて、 その日初めて起動した時に、8日前のデータを消すことにチャレンジしてみました。 ※今のところ、うまくいってます。

/* * 2.手で走らせてた削除のSQL文 */

下記のような感じで、SQL文を作り、 strSQL = "Delete From log " '現在時刻、日付型は#で囲む strSQL = strSQL & "Where WriteTime < #" & DateAdd("d", -7, Date) & "#" 削除のSQLを db.Execute(strSQL) で発行してました。
Sub DeleteMDB()

  'ADO DB Connection オブジェクトを作成する、英文そのままじゃん
  Set db=Server.CreateObject("ADODB.Connection")

  '.Provider?プロバイダー?通信会社?じゃなくって
  'データアクセスにはJet.OLEDB.4.0を使うことを設定
  db.Provider = "Microsoft.Jet.OLEDB.4.0"

  '次に、接続DBの位置を渡すので、Server.MapPathで変換して渡す
  db.ConnectionString = Server.MapPath("../test/cnt.mdb")

  'やっとデータベースを開ける
  db.open

  'SQL文を作る
  strSQL = "Delete From log "      '現在時刻、日付型は#で囲む
  strSQL = strSQL & "Where WriteTime < #" & DateAdd("d", -7, Date) & "#"
  'SQL文を発行
  db.Execute(strSQL)

  'データベースも閉じようよ
  db.Close

  'お行儀よくオブジェクトも開放しましょう(通常は自動的に解放されるけど)
  Set db = Nothing

End Sub
この削除の関数を、 その日、はじめて来た訪問者に実行させたくて、 共通のApplication変数に削除実施日を保存しておき、 現在時刻と削除実施日が違った場合のみ削除処理が走るように、 細工してみたいと思います。

/* * 3.ロック処理で細工する */

作成した、削除のSQLを初回だけ呼ぶルーチンです。 <% '日付の管理 Application.Lock 'ロックの設定 Application("LOCK_FLG") = "ON" '日替わりチェック WTEMP = Application("SDATE") DEL_FLG = "OFF" If WTEMP <> Date Then Application("SDATE") = Date '日付の代入 DEL_FLG = "ON" End If Application.UnLock 'ロックの解除 '日替わり削除処理を呼ぶか判断 If DEL_FLG = "ON" Then Call DeleteMDB() End If %> 同時にアクセスされて、変数を壊されるのがイヤだったので、 Application.Lock と Applicationオブジェクトへのアクセスをロックします。 Application("LOCK_FLG") = "ON" なんて意味深なことやっているけど、これは、気にしないでください。 ※変数名に意味は無く、代入処理に意味があります。 フラグは使ってないんですね(笑) AさんとBさんがほぼ同時にアクセスしてきました。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Aさん      Bさん Application.Lock 'ロックの設定 Application.Lock 'ロックの設定 Application("LOCK_FLG") = "ON" Application("LOCK_FLG") = "ON" '日替わりチェック '日替わりチェック WTEMP = Application("SDATE") WTEMP = Application("SDATE") DEL_FLG = "OFF" DEL_FLG = "OFF" If WTEMP <> Date Then If WTEMP <> Date Then Application("SDATE") = Date Application("SDATE") = Date DEL_FLG = "ON" DEL_FLG = "ON" End If End If Application.UnLock 'ロックの解除 Application.UnLock 'ロックの解除 すると、Aさんのほうが少し早かったので、 先にApplication.Lockをかけました。 Bさんは、少し遅れてApplication.Lock の要求を出しました。 Aさんの Application("LOCK_FLG") = "ON" は、普通にアプリケーション変数LOCK_FLGにONって文字列をセットします。 Bさんも、セットしようとアプリケーション変数LOCK_FLGにアクセスするも、 Aさんのかけた.Lockのおかげで、ここで解除となるまでまたされます。 Aさんの処理が進むと、 Application.UnLock 'ロックの解除 とロックが解除されます。 で、やっとBさんの処理、 Application("LOCK_FLG") = "ON" が開始されます。 こんな流れを作りたかったので、 Application.Lock Application.UnLock と Application("変数名") = "" で 小細工してみました。

/* * 4.終わりの挨拶 </HTML> */

同時アクセス数が少なかったり、 止めて処理しているのが日付の比較だけなので(軽い処理なので) ロックしている時間が短く、今のところ影響なく動作しています。 今回の処理は、別に2回、3回削除のSQL文走っても実害は無かったのですが、 ユニークな連番を振る処理などで、 排他的な処理をする時 And 軽めの処理限定で、 Application.Lock Application.UnLock を使うのも1つの手だなぁと思います。 何かの参考となれば幸いです。 素朴な疑問やリクエスト、クレームなどがあったら、 掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi に気軽に書き込んでください。 ASP、VBScript勉強中の三流プログラマーのKen3でした。

No.64 2003/06/13
Session("変数名")で接続単位に変数を管理する
[ページTOPへ戻る]

<Session("変数名")で接続単位に変数を管理する>

こんにちは、三流プログラマーのKen3です。 今回は、 Session("変数名")を使ってみた そんなお話です。

/* * 1.今回のキッカケ */

ASP間で値を保持、そんなことをやってみたくて、 アプリケーション全体(アクセスユーザー全体)で参照可能な変数の管理は、 No.42 Application("XXXX") Application変数のテスト http://www.ken3.org/backno/backno_asp09.html#42 で、軽く解説しました。 まぁ、アプリ全体(アクセスユーザー全体)でも、いいのですが、 アクセスしたユーザー単位で値を管理したい、 そんな時に使用するのが、 セッション変数 Session("項目名")です。

/* * 2.Session("変数名")で簡単に使用可能 */

Session("変数名")で、ユーザー単位でセッション変数を設定可能です。 1つの接続で、1つのセッション変数が作成されます。 なんだかよくわからん? えっと、ブラウザを立ち上げて1つのURLを表示したり、 接続をすると固有のセッションIDがふられ、 そのユーザー単位に、 Session("A") = 10 Session("B") = 20 と値の管理ができます。 あっそ? 冷たいなぁ、、、それを利用して、ユーザーの名前を一時的に覚えてみます。 ※ブラウザ側でクッキー使用可能になっている必要があります。 ここも注意かなぁ。

/* * 3.名前を一時的に覚えておく */

セッション単位の変数のテストとして、 ユーザー名を一時的に保持しておくサンプルを作ってみたいと思います。 簡単な流れは、 ユーザー名が送られてきたら(入力されたら)、 Session("USERNAME")に値を保持する Session("USERNAME")が空なら、名前の入力フォームを表示 Request.QueryString("DATA") にデータが入っていたら、 乱数を発生させ、勝敗の判定を行う。 そんな流れのプログラムを作ってみます。 http://www.ken3.org/cgi-bin/test/test064-1.asp でテスト実行できます、遊んでみてください。 <%@LANGUAGE=VBScript%> <html> <head> <title>セッション変数 Session("USERNAME") で名前の管理</title> </head> <body> <h2>セッション変数 Session("USERNAME") で名前の管理</h2> <h3>じゃんけんゲーム</h3><br> <% 'ユーザー名が送られていたら、セッション変数にセットする D = Request.QueryString("UNAME") 'データを代入 If Len(D) <> 0 Then 'データあり Session("USERNAME") = D '名前の代入 End If 'パラメータをチェックする、セッション変数に名前が入っているか? USER_NAME = Session("USERNAME") 'Lenで変数の長さをチェックする If Len(Trim(USER_NAME)) = 0 Then '名前が未入力なら Call INPUT_NAME() '名前入力フォームの表示 Else D = Request.QueryString("DATA") 'データを代入(選択された手) If Len(D) = 1 Then 'データあり Call HANTEI(D) '判断用の関数を呼ぶ End If Call INPUT_FORM() '入力用のフォームを表示する、再度入力させる End If %> <hr> アナタのIP Address=<%=Request.ServerVariables("REMOTE_ADDR")%><br> Session.SessionID=<%=Session.SessionID%><br> サーバー再起動時に同じセッションIDが振られることがあるが、<br> 通常は毎回違う値が表示される<br> ブラウザを閉じてからまた開いたり<br> 隣のインターネット上同じIPの端末から2つ同時に開いたり してテストしてみよう<br><hr> </body> </html> <% '名前入力フォームの表示
Sub INPUT_NAME()
  Response.Write "<HR>"
  Response.Write "<FORM ACTION='test064-1.asp' METHOD='GET'>"
  Response.Write "あなたのお名前は?<br>"
  Response.Write "<INPUT TYPE='text' NAME='UNAME'><br>"
  Response.Write "<INPUT TYPE='submit' VALUE='名前の登録'><br>"
  Response.Write "</FORM>"
End Sub
%>
<% '入力フォームの表示(勝負する手を入力)
Sub INPUT_FORM()
  Response.Write "<HR>"
  Response.Write "<FORM ACTION='test064-1.asp' METHOD='GET'>"
  Response.Write "<b>" & USER_NAME & "</b>さん、あなたの手は?<br>"
  Response.Write "<INPUT TYPE='RADIO' NAME='DATA' VALUE='1'>1.グー<br>"
  Response.Write "<INPUT TYPE='RADIO' NAME='DATA' VALUE='2'>2.チョキ<br>"
  Response.Write "<INPUT TYPE='RADIO' NAME='DATA' VALUE='3'>3.パー<br>"
  Response.Write "<INPUT TYPE='submit' VALUE='勝負する'><br>"
  Response.Write "</FORM>"
End Sub
%>
<% '乱数を発生させて勝負する
Sub HANTEI(strNO)  'ユーザーの手を受取り判断する

    Dim nCON  'コンピュータの手1〜3の数値が入る
    Dim nPC   'ユーザーさんの手
    Dim strTE(3) '(*1)配列変数を宣言

    strTE(1) = "グー"   '(*2)配列にメッセージを代入
    strTE(2) = "チョキ"
    strTE(3) = "パー"

    '入力値の判断、エラーならメッセージを表示させ抜ける
    'If文で1,2,3以外を判断する
    If strNO <> "1" And strNO <> "2" And strNO <> "3" Then
        Response.Write "[" & strNO & "]は不正な入力です"
        Exit Sub  '<--Exit Subを使用してここでプログラムを抜ける
    End If

    'コンピュータの手を決定
    Randomize   ' 乱数発生ルーチンを初期化します。
    nCON = Int((3 * Rnd) + 1)  '1 から 3 までの乱数を発生させます。

    '結果判断と表示
    'ユーザーの手を表示する
    nPC = CInt(strNO) 'CInt関数で数値型に変換する
    Response.Write USER_NAME & "さんの手は、"
    Response.Write strTE(nPC) & "です<br>" '(*3)ここでnPC番目を表示

    '(*4)同様にコンピュータの手を表示する
    Response.Write "コンピュータの手は" & strTE(nCON) & "です<br>"

    '結果の判断
    'まず、引き分けを判断
    If nPC = nCON Then Response.Write "引き分けです<br>"

    '次に自分が勝ちの手を判断 グーvsチョキ,チョキvsパー,パーvsグー
    If nPC = 1 And nCON = 2 Then Response.Write "アナタの勝ちです<br>"
    If nPC = 2 And nCON = 3 Then Response.Write "アナタの勝ちです<br>"
    If nPC = 3 And nCON = 1 Then Response.Write "アナタの勝ちです<br>"

    'コンピュータが勝ちか判断 グーvsパー,チョキvsグー,バーvsチョキ
    If nPC = 1 And nCON = 3 Then Response.Write "私(コンピュータ)の勝ちです<br>"
    If nPC = 2 And nCON = 1 Then Response.Write "私(コンピュータ)の勝ちです<br>"
    If nPC = 3 And nCON = 2 Then Response.Write "私(コンピュータ)の勝ちです<br>"

End Sub
%>
ポイントは、 ~~~~~~~~~~~~ 'ユーザー名が送られていたら、セッション変数にセットする D = Request.QueryString("UNAME") 'データを代入 If Len(D) <> 0 Then 'データあり Session("USERNAME") = D '名前の代入 End If 'パラメータをチェックする、セッション変数に名前が入っているか? USER_NAME = Session("USERNAME") 'Lenで変数の長さをチェックする If Len(Trim(USER_NAME)) = 0 Then '名前が未入力なら と、 Session("USERNAME")を使用している場所です。 なんて書いたけど、 Session("USERNAME")で変数みたいに、 普通に出し入れできてるだけでした。 ~~~~~~~~~~~~~~~~~~~~~~ アナタのIP Address=<%=Request.ServerVariables("REMOTE_ADDR")%><br> Session.SessionID=<%=Session.SessionID%><br> サーバー再起動時に同じセッションIDが振られることがあるが、<br> 通常は毎回違う値が表示される<br> ブラウザを閉じてからまた開いたり<br> 隣のインターネット上同じIPの端末から2つ同時に開いたり してテストしてみよう<br><hr> なんて、書いてますが、 Session.SessionID が、 ・起動毎に違うID、 ・同じ会社の隣のマシーンからだと違う。 そんな感じのことを確認してみてください。 一時的に値を保持したり、 各接続単位(端末単位、ブラウザ)で、ASP間をまたいだ変数の管理が出来ます。 http://www.ken3.org/cgi-bin/test/test064-1.asp でテスト実行できます、遊んでみてください。

/* * 4.終わりの挨拶 </HTML> */

今回は、 簡単なSession変数のお話でした。 ※活用例がショボかったけど、いろいろと使える手法です。 何かの参考となれば幸いです。 素朴な疑問やリクエスト、クレームなどがあったら、 掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi に気軽に書き込んでください。 ASP、VBScript勉強中の三流プログラマーのKen3でした。



ページフッター リンクや広告、質問送信など

三流解説を読んでいただき、どうもです。ここから下は、三流君宛のメッセージ送信や 三流君のホームページの紹介・案内です
目的の情報が見つかったか?少々心配しつつ、、、※質問や感想は、気軽に送ってくださいね。

まぁ、基本はデータの受け取りかなぁ。
・[Form等を使用したデータのやり取り]・・・ASPと言っても、HTMLの入力フォームからデータを受け取ります。POSTやGETでやりとりを押さえますか。

次は、データの入出力 で ADOを使った(ADOで接続) と SQLの解説を少々
・[ADOでMdbファイルを使う]・・・MDBと接続して、簡単な追加・更新・削除を行った。
・[ADOでExcelと接続してみた]・・・.xlsと接続してSQLを使ってみた。
・[ADOでCSVと接続してみた]・・・.CSV テキストを読み出した。※更新・削除はできません

DBが使えるので、あまり使用しないけど、普通のテキストファイル処理
・[テキストファイル処理]・・・ファイルを開いて、書き込む。1行読み込みなどを軽く

VBScriptでFormat関数が無いなど、微妙にVBAと違うけど
[VBScript関数関係の説明]・・・少し、処理を書いてみた。
[その他処理サンプル]・・・あまり良いサンプル作れなかったけど。。。
何かの参考となれば幸いです。

ニガテな環境設定系など
[Win2003 Server に IIS を Setup]・・・ポイントの無い、ほぼ一本道解説だけど。
[IIS 仮想ディレクトの作成とASP動作TEST]・・・Web拡張でASPを有効にしただけです。

Blog:[三流君の作業日記]/ [サンプルコードのゴミ箱]/ 広告-[通販人気商品の足跡]

質問や要望など メッセージを送る(三流君に連絡する)

質問や要望など連絡方法でお互い確認が取りやすく、便利なのが掲示板なのですが、私の対応のまずさから不定期で荒れてしまい、掲示板は現在封鎖中です。(反省しなきゃ)
感想や質問・要望・苦情など 三流君へメッセージを送る。
時間的余裕のある要望・質問・苦情の場合は、下記のフォームからメッセージを送ることができます。

あなたのお名前(ニックネーム):さん
返信は?: 不用(HP更新を待つ) , E-mail→ アドレス:に返事をもらいたい



(感想や質問・要望 メッセージはHPで記事に載せることがあります。)


急ぎで連絡がほしい、そんな時は:[三流君連絡先アドレス]を見て連絡してください。



[三流君(TOP ken3.org へ戻る)] / [ASPで遊ぶ、失敗する] / [ASP記事 バックナンバー目次]