三流君ASPで遊ぶ、失敗する
バックナンバー No.55 〜 No.59
<And演算子を使う>
こんにちは、三流プログラマーのKen3です。
今回は、
読者から軽くメールもらったので、
ネタにしてみます。
拾い読みして、何かの参考となれば幸いです。
/*
* 1.今回のキッカケ
*/
In message "re:[ASPで遊ぶ No.052] - キャラクタコード....",
> 二年目プログラマーの西 ***です。
>> nCODE = Asc(Mid(strMOJI, n, 1)) 'n番目の文字コードを求める
>> If nCODE >= 0 And nCODE <= 255 Then 'コードが1バイト文字内か?
>
> 三流だとAnd演算子も知らない?ありえねぇ〜
---
なんて、いつものクレーム?メールをいただきました。
本名でクレーム書いて来るって、潔いよね。
(実は本名じゃなかったりして、、、
西多摩雄とかニシタマオだったら相手にしないんだけど)
そんな関係ない話は置いといて、
/*
* 2.問題のコードとAnd演算子の使い方
*/
'文字列を受け取り、バイト数を返す
Function Byte_Count(strMOJI)
bcnt = 0
'文字数分ループして、コードを表示
For n = 1 To Len(strMOJI)
nCODE = Asc(Mid(strMOJI, n, 1)) 'n番目の文字コードを求める
If nCODE >= 0 And nCODE <= 255 Then 'コードが1バイト文字内か?
bcnt = bcnt + 1
Else
bcnt = bcnt + 2
End If
Next
'リターン値をセットする
Byte_Count = bcnt
End Function |
指摘場所は、バイト数を計算している関数内の
nCODE = Asc(Mid(strMOJI, n, 1)) 'n番目の文字コードを求める
If nCODE >= 0 And nCODE <= 255 Then 'コードが1バイト文字内か?
bcnt = bcnt + 1
Else
bcnt = bcnt + 2
End If
の場所ですね。
まぁ、
If nCODE >= 0 And nCODE <= 255 Then 'コードが1バイト文字内か?
でも、動いているのですが、たぶん美的意識、美観的に良くない、
nCODE And &HFF00 とAnd演算子を使用してマスクしろって感じなんだろうなぁ。
えっ、Andって演算子だったの?
そうですよ?知らなかった?
nCODE >= 0 And nCODE <= 255
をわかり易くするために、まず()を付けます、
(nCODE >= 0) And (nCODE <= 255)
(True) And (True) みたいに、演算してるんですね(論理演算だけど)
And &hFF00とすることで、
上のビットを残し、下のビットを消すなんてことが出来るんですね。
If nCODE >= 0 And nCODE <= 255 Then 'コードが1バイト文字内か?
を
If (nCODE And &HFF00) = 0 Then 'コードは1バイトか? *asp055
みたいに書くことができます。
0以上で255(含む)より下か?とIf文を作成して、
1バイトか?判断するのもありだし、
FF00でAndして、判断するのもひとつの手なんですよ。
今回は、好みの問題ってことであまり実害は無いけど、
And演算子、頭のスミに入れて置いてください。
http://www.ken3.org/cgi-bin/test/test055-1.asp?DATA=Ken3%82%CD%8EO%97%AC
で、And &HFF00バージョンの確認ができます。
※同じく動作することを確認してみてください。
/*
* 3.終わりの挨拶 </HTML>
*/
今回は、
And演算子の簡単な説明でした。
最近、ビット演算、、する機会、、、無いなぁとフト思いました。
素朴な疑問やリクエスト、今回みたいなクレームなどがあったら、
メール : qaqaqa@ken3.org
掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi
に気軽に書き込んでください。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<Excel(*.xls)とADOで接続、.Addnewしてみた>
こんにちは、三流プログラマーのKen3です。
今回は、
Excel(*.xls)とADOで接続後、
レコードセット.Addnewでレコード追加、
rs.Fields("名前").Value = 値
rs.Fields(フィールド番号).Value = 値
とデータをセットして、
.Updateで更新
と
普通に操作してみます。
拾い読みして、何かの参考となれば幸いです。
/*
* 1.今回のキッカケ
*/
No.53 ADOでExcelファイル(*.xls)とやっと接続できた(ほっ)
http://www.ken3.org/backno/backno_asp11.html#53
で、
サーバーに置いた、*.xlsファイルに接続できたので、
読み込みが出来たら、書き込みでしょ、、
って流れで、
.AddNewでデータを追加してみたいと思います。
/*
* 2.普通にAddNewで出来ないの?
*/
さてと、下記のような感じで、Excelファイルにアクセスできました。
http://www.ken3.org/cgi-bin/test/test053-1.asp
参照。
'ADO DB Recordset オブジェクトを作成する、英文そのままじゃん
Set rs=Server.CreateObject("ADODB.Recordset")
strSQL = "select * from DATA_RANGE"
Con = "Driver={Microsoft Excel Driver (*.xls)};DBQ=" & _
Server.MapPath("test053.xls") & ";"
Response.Write "作った、使った接続文字列は<br>" & Con & "<hr>"
'接続文字列、SQLを渡して、レコードセットを開く
Rs.Open strSQL, Con, 0 '0=adOpenForwardOnly
strOUT = ""
Do While Rs.EOF = False
For Each FieA In Rs.Fields
strOUT = strOUT & FieA.Name & " -- " & FieA.Value & "<BR>"
Next
Rs.MoveNext '次のレコードへ移動
Loop
Rs.Close
Set Rs = Nothing
パターン的には、
'接続文字列、SQLを渡して、レコードセットを開く
Rs.Open strSQL, Con, 0 '0=adOpenForwardOnly
の
0=adOpenForwardOnlyを追加可能なカーソルにすればOKかなぁ。
カーソル関係の定数を見ると
(ローカル内のadovbs.incを参照しました)
'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3
となっているから、adOpenDynamic = 2にして、
'接続文字列、SQLを渡して、レコードセットを開く
Rs.Open strSQL, Con, 2
.AddNew 'レコードセットの追加
としたけど、、、あれ、
ADODB.Recordset エラー '800a0cb3'
オブジェクトまたはプロバイダは要求された操作を実行できません。
/cgi-bin/test/test056-1.asp, 行 31
あっ、ロックのタイプ、書いてないや
'---- LockTypeEnum Values ----
Const adLockReadOnly = 1
Const adLockPessimistic = 2
Const adLockOptimistic = 3
Const adLockBatchOptimistic = 4
は、adLockOptimistic = 3を使用すればOKだろうと軽く考えて、
'接続文字列、SQLを渡して、レコードセットを開く
Rs.Open strSQL, Con, 2, 3
Microsoft OLE DB Provider for ODBC Drivers エラー '80004005'
[Microsoft][ODBC Excel Driver] 更新可能なクエリであることが必要です。
/cgi-bin/test/test056-1.asp, 行 36
えっ、なんで、、、更新可能じゃないの???
う〜ん。
/*
* 3.接続できたら、あとは簡単と豪語してたのに(笑)
*/
接続できたら、あとは追加・更新・削除は簡単と豪語してたのに(笑)
やばいなぁ。。。
得意の人様のHPを観察して、パクるか。
AccessからADOでExcelを更新するページ見ても、できてるよなぁ普通に使って。。。
こりゃ、ハマったかな(爆)
で、マイクロソフトのサポートページを見ていて、
英語のページに紛れ込んだ。
http://support.microsoft.com/default.aspx?scid=kb;EN-US;314763
FIX: ADO Inserts Data into Wrong Columns in Excel
The information in this article applies to:
ActiveX Data Objects (ADO) 2.1
ActiveX Data Objects (ADO) 2.5
ActiveX Data Objects (ADO) 2.6
Microsoft OLE DB Provider for Jet 4.0
英語、読めないんだけど(情けないことに中学生以下じゃないたぶん(笑))
おっ、と思うソースが目に飛び込んできた。
Private Sub Command1_Click()
Dim strCn As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim fld As ADODB.Field
'Open connection
strCn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & App.Path & "\Test.xls;" & _
"Extended Properties=Excel 8.0"
Set cn = New ADODB.Connection
cn.Open strCn
'Add new values.
Set rs = New ADODB.Recordset
With rs
.CursorLocation = adUseClient
.Open "Select * from [Sheet1$]", cn, adOpenStatic, adLockOptimistic
.AddNew
.Fields("ColumnA").Value = 3
.Fields("ColumnB").Value = 3
.Fields("ColumnC").Value = ""
.Fields("ColumnD").Value = 3
.Fields("ColumnE").Value = 3
.Fields("ColumnF").Value = "testing"
.Update
.Close
End With
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub |
英語、読めなくても、ソースって意外と読めるもんなんですよね。
※このサンプルソース、英語のコメントが無いのが良かったのかも
これって、見るからに、Excelファイルに追加してる、そんな感じするよね(笑)
自分のソースとの違いを見る。
まず、接続の作り方が、いきなりレコードセットじゃなく、
'Open connection
strCn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & App.Path & "\Test.xls;" & _
"Extended Properties=Excel 8.0"
とADODB.Connectionを開いてから、
Set rs = New ADODB.Recordset
With rs
.CursorLocation = adUseClient
.Open "Select * from [Sheet1$]", cn, adOpenStatic, adLockOptimistic
.AddNew
と、レコードセットを開いて、.Addnewしてる。
.CursorLocation = adUseClient
ってなんだ?
定数のファイル(ローカル内のadovbs.incを参照しました)
を見てみると、
'---- CursorLocationEnum Values ----
Const adUseServer = 2
Const adUseClient = 3
となっていて、
adUseClientの上に、adUseServer?
英語わからない、私でも、これって?サーバーの指定?かもと予想。
これを参考にして、
訪問者の時刻、IPアドレス、端末情報を保存するサンプルを作ってみました。
Excelファイルのフォーマットと名前の定義は、
↑みたいに作成しました。
<%@LANGUAGE=VBScript%>
<html>
<head>
<title>Excel(*.xls)とADOで接続、.Addnewしてみた</title>
</head>
<body>
<h2>Excel(*.xls)とADOで接続、.Addnewしてみた</h2>
<!-- Ken3 --><!-- #include file="info.inc" -->
test056-1.asp<br>
ASPからADOを使用してExcel(*.xls)と接続して、<br>
.AddNewでレコードを追加する。<br>
<hr>
<%
'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3
'---- LockTypeEnum Values ----
Const adLockReadOnly = 1
Const adLockPessimistic = 2
Const adLockOptimistic = 3
Const adLockBatchOptimistic = 4
'---- CursorLocationEnum Values ----
Const adUseServer = 2
Const adUseClient = 3
'ADO DB Connection オブジェクトを作成する、英文そのままじゃん
Set db=Server.CreateObject("ADODB.Connection")
'接続文字列
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath("test056.xls") & ";" & _
"Extended Properties=Excel 8.0"
Response.Write "接続文字列は<br><b>"
Response.Write strCon & "</b><br>です<br>"
'データベース(xls)を開く
db.open strCon
Response.Write "その次はレコードセット<br>"
'ADO DB Recordset オブジェクトを作成する、英文そのままじゃん
Set rs=Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseServer 'カーソルはサーバーの指定
Response.Write "Select * from FIELD_RANGE, db, 〜<br>"
rs.Open "Select * from FIELD_RANGE", db, adOpenStatic, adLockOptimistic
Response.Write "開いたレコードセットに対して.AddNew<br>"
rs.AddNew
Response.Write "フィールドにアクセスする<br>"
'↓フィールド名でアクセス
rs.Fields("F_HIZUKE").Value = Now()
rs.Fields("F_IP").Value = Left(Request.ServerVariables("REMOTE_ADDR"), 9)
'↓番号でアクセスも出来るよ
rs.Fields(2).Value = Request.ServerVariables("HTTP_REFERER")
rs.Fields(3).Value = Request.ServerVariables("HTTP_USER_AGENT")
Response.Write ".Updateで更新(レコード確定)<br>"
rs.Update
Response.Write "rs.Close でレコードセットを閉じる<br>"
rs.Close
Set rs = Nothing 'オブジェクト変数を開放する
Response.Write "db.Close でxlsとの接続を閉じる<br>"
db.Close
Set db = Nothing 'オブジェクト変数も開放する
%>
<hr>
時刻、IPアドレス(頭から9文字)ユーザーのブラウザ情報を書き込みました<br>
[<a Href="test056.xls" TARGET="_blank">書き込んだtest056.xlsを開く</a>]<br>
↑書き込まれたデータの確認<br>
</body>
</html>
テストは、
http://www.ken3.org/cgi-bin/test/test056-1.asp
で、可能です。
アクセスすると、ログ情報をtest056.xlsに書き込みます。
アクセス後、Excelファイルをダウンロードして、
データが追加されていることを確認してみてください。
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
簡単に.Addnewの解説、、と行きたかったけど、
ハマってしまった、、なんて情けないお話でした(三流プログラマーらしいよね)
and
英語読めないのに、ソースは読める不思議な自分に気がついて、変な気分。
※で、調子に乗ってマイクロソフトの英語サイト読んだけど、よくわかんなかった(笑)
私の失敗談が、
ASPからADOを使用して、Excelファイルに書き込む
そんな処理の参考となれば幸いです。
テストは、
http://www.ken3.org/cgi-bin/test/test056-1.asp
で、可能です。
素朴な疑問やリクエスト、今回みたいなクレームなどがあったら、
メール : qaqaqa@ken3.org
掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi
に気軽に書き込んでください。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<Excelグラフ付の雛形シートにASPからADOを使用してデータセット>
こんにちは、三流プログラマーのKen3です。
今回は、
グラフ付のExcelファイルとADOで接続後、
データをセット(更新)
そのExcelファイルをダウンロードさせます。
拾い読みして、何かの参考となれば幸いです。
/*
* 1.今回のキッカケ
*/
No.53 ADOでExcelファイル(*.xls)とやっと接続できた(ほっ)
http://www.ken3.org/backno/backno_asp11.html#53
で、
サーバーに置いた、*.xlsファイルに接続でき、
No.56 Excel(*.xls)とADOで接続、.Addnewしてみた
http://www.ken3.org/backno/backno_asp12.html#56
で、
Excelの表にデータを追加することが出来ました。
そしたら、今度は更新でしょう
ってことで、一週間分のログを日別に集計して、
Excelの表を更新してみます。
.AddNewの時、.Updateも使っているので、
普通の表だと面白みに欠けるので、
グラフ付のExcelファイルに書き込んでみます。
/*
* 2.まずは、雛形ファイルの用意
*/
A列 B列 C D列
日付 訪問者数
2001/1/1 10
2001/1/2 20
2001/1/3 30 横棒グラフを
2001/1/4 40 シートとリンクさせて作成
2001/1/5 50 雛形を作成。
2001/1/6 60
2001/1/7 70
2001/1/8 80
作成イメージは
↑みたいに作成しました。
今回は、名前の定義は作らないで、
DATA!A2:B9 みたいに指定してみたいと思います。
/*
* 3.訪問者をSQL文で集計する
*/
ログファイルから日付別に集計するのは、
http://www.ken3.org/cgi-bin/test/test040-1.asp
でやったSQL文を流用して、
Select Format(WriteTime, 'YYYYMMDD') AS YYYYMMDD, Count(*) AS CNT
From log
GROUP BY Format(WriteTime, 'YYYYMMDD')
を使用して、日付別に集計します。
集計値を配列に入れて、それをエクセルにセットする方法を取ります。
いきなり動作したソース載せちゃうけど、
http://www.ken3.org/cgi-bin/test/test057-1.asp
でテスト可能です。ポイントの解説は下のほう見てください。
<%@LANGUAGE=VBScript%>
<html>
<head>
<title>Excel(*.xls)グラフ付雛形にADOで接続しデータ更新</title>
</head>
<body>
<h2>Excel(*.xls)グラフ付雛形にADOで接続しデータ更新</h2>
<!-- Ken3 --><!-- #include file="info.inc" -->
test057-1.asp<br>
ASPからADOを使用してExcel(*.xls)と接続して、<br>
.Updateでレコードを更新する。<br>
<hr>
<%
'---- CursorTypeEnum Values ----
Const adOpenForwardOnly = 0
Const adOpenKeyset = 1
Const adOpenDynamic = 2
Const adOpenStatic = 3
'---- LockTypeEnum Values ----
Const adLockReadOnly = 1
Const adLockPessimistic = 2
Const adLockOptimistic = 3
Const adLockBatchOptimistic = 4
'---- CursorLocationEnum Values ----
Const adUseServer = 2
Const adUseClient = 3
'配列変数に集計値をまず入れます。
Dim PageCNT(10) '8個でいいんだけど
Dim dHIZUKE(10)
'ADO DB Connection オブジェクトを作成する、英文そのままじゃん
Set db=Server.CreateObject("ADODB.Connection")
'データアクセスにはJet.OLEDB.4.0を使うことを設定
db.Provider = "Microsoft.Jet.OLEDB.4.0"
'接続DBの位置は、Server.MapPathで変換して渡す
db.ConnectionString = Server.MapPath("cnt.mdb")
db.open 'やっとデータベースを開ける
'FORMAT関数を使用して、テーブル名logからデータを集計する
'SQL文を発行する
strSQL = "Select Format(WriteTime, 'YYYY/MM/DD') AS YYYYMMDD, Count(*) AS CNT"
strSQL = strSQL & " From log"
strSQL = strSQL & " Where WriteTime >= #" & DateAdd("d", -7, Date) & "#"
strSQL = strSQL & " GROUP BY Format(WriteTime, 'YYYY/MM/DD')"
'オマケで画面にデータ表示
Response.Write "<hr>発行する(した)SQL文は<br><B><font color='green'>"
Response.Write strSQL & "</font></B><br>です<hr>"
Set rs = db.Execute(strSQL)
'データの表示をテーブルで行う
Response.Write "<TABLE Border='1'>"
'見出しをバカっぽく、そのまま書き込む
Response.Write "<TR>"
Response.Write "<TD>NO.</TD>"
Response.Write "<TD>日付</TD>"
Response.Write "<TD>閲覧ページ数</TD>"
Response.Write "</TR>"
'EOFまでループ
nCNT = 1
Do While rs.EOF = False '.EOFがFalseの間
Response.Write "<TR>" '内容を表示する
Response.Write "<TD>" & nCNT & "</TD>"
Response.Write "<TD>" & rs.Fields("YYYYMMDD") & "</TD>"
Response.Write "<TD ALIGN='RIGHT'>" & rs.Fields("CNT") & "</TD>"
Response.Write "</TR>" & Chr(13) & Chr(10)
'配列変数に日付、カウント値を代入
dHIZUKE(nCNT) = rs.Fields("YYYYMMDD")
PageCNT(nCNT) = rs.Fields("CNT")
'次のレコードにポインタを移動する
rs.MoveNext 'これを忘れると悲惨なことに、、、
'カウンタを増やす
nCNT = nCNT + 1
Loop
Response.Write "</TABLE><HR>" 'テーブルは終わりです
'お行儀よくオブジェクトも開放しましょう
'今回同じ名前を使いまわしてみます、開放すれば大丈夫でしょう
rs.Close '開いていたレコードセットを閉じる
Set rs = Nothing
db.Close 'データベースも閉じようよ
Set db = Nothing
'---------------------
'ここからExcel側の処理
'---------------------
'ADO DB Connection オブジェクトを作成する、英文そのままじゃん
Set db=Server.CreateObject("ADODB.Connection")
'接続文字列作成、test057.xlsを指定する
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath("test057.xls") & ";" & _
"Extended Properties=Excel 8.0"
Response.Write "ExcelとのADO接続文字列は<br><b>"
Response.Write strCon & "</b><br>です<br>"
'データベース(xls)を開く
db.open strCon
Response.Write "その次はレコードセット<br>"
'ADO DB Recordset オブジェクトを作成する、英文そのままじゃん
Set rs=Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = adUseServer 'カーソルはサーバーの指定
Response.Write "Select * from [DATA$A1:B9], db, 〜<br>"
rs.Open "Select * from [DATA$A1:B9]", db, adOpenStatic, adLockOptimistic
Response.Write "開いたレコードセットに対して.MoveFirst<br>"
rs.MoveFirst '先頭へ(A2:B2の行)
Response.Write "ループで配列からフィールド(セル)へセット<br>"
'ループ
For n = 1 To 8 '当日+一週間の7日で8回まわる
rs.Fields(0).Value = dHIZUKE(n)
rs.Fields(1).Value = PageCNT(n)
rs.Update '更新
rs.MoveNext '次のレコードへ(次の行へ)
Next
Response.Write "rs.Close でレコードセットを閉じる<br>"
rs.Close
Set rs = Nothing 'オブジェクト変数を開放する
Response.Write "db.Close でxlsとの接続を閉じる<br>"
db.Close
Set db = Nothing 'オブジェクト変数も開放する
%>
<hr>
集計値をtest057.xlsへ書き込みました<br>
[<a Href="test057.xls" TARGET="_blank">書き込んだtest057.xlsを開く</a>]<br>
↑書き込まれたデータの確認、グラフ付はOKか確認する<br>
</body>
</html>
ポイント解説
~~~~~~~~~~~~
あまりポイントは、無いんだけど、
'接続文字列作成、test057.xlsを指定する
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Server.MapPath("test057.xls") & ";" & _
"Extended Properties=Excel 8.0"
接続までは、スムーズでした。
で
いつものようにハマったのは、データエリアの指定です。
^^^^^^^^^^^^^^^^^^^^^^^^^^^
回答を先に出してしまうけど、
Response.Write "Select * from [DATA$A1:B9], db, 〜<br>"
rs.Open "Select * from [DATA$A1:B9]", db, adOpenStatic, adLockOptimistic
と
from [DATA$A1:B9]で指定すると、
シートの範囲をレコードセットにできます。
※名前の範囲無くても使用できるので、意外と便利ですね
初め書いた書き方は(失敗例その1は)
rs.Open "Select * from DATA!A2:B9", db, adOpenStatic, adLockOptimistic
この書き方だと、
Microsoft JET Database Engine エラー '80040e14'
FROM 句の構文エラーです。
/cgi-bin/test/test057-1.asp, 行 121
ちっ、また調べるのかよ(笑)
http://www.microsoft.com/japan/msdn/columns/office/office10052000.asp
がMSのページです。※よかった日本語だよ。
Excel Link
Excel ワークブックへのリンク
オブジェクト 構文
ワークシート sheetname$
名前付き範囲 rangename
名前付きではない範囲 sheetname$rangeaddress
えっと、この3種類が使えるなら、
DATA$A2:B9でいいのか、この位置に$は違和感あるけど、仕様なんでしょう。
!はエクセルのセル上の慣れてる書き方だったか。
rs.Open "Select * from [DATA$A2:B9]", db, adOpenStatic, adLockOptimistic
で勝負。(失敗例その2)
ADODB.Field エラー '800a0bcd'
~~~~~~~~~~~
BOF と EOF のいずれかが True になっているか、
または現在のレコードが削除されています。
要求された操作には、現在のレコードが必要です。
オイオイ、
あらら、まだダメなの、、、
ADODB.Field エラー?
~~~~~~~~~~~
あっ、フィールドかぁ、
A2:B9これってデータエリアで、見出しの行含んでないや。
これで、フィールド名が取れないのかな、もしかして。
rs.Open "Select * from [DATA$A1:B9]", db, adOpenStatic, adLockOptimistic
と見出しの行を含ませたら、やっと動作しました。
※意外と単純なミス?でした。。。
でも、エラーメッセージ、フィールド名が不明とか、
わかりやすく出してほしいよね......
えっ、そんなミスするのは三流君だけ???
あとは、ループで頭から配列変数からフィールドにデータをセット、
その後、.Updateで更新しました。
rs.MoveFirst '先頭へ(A2:B2の行)
Response.Write "ループで配列からフィールド(セル)へセット<br>"
'ループ
For n = 1 To 8 '当日+一週間の7日で8回まわる
rs.Fields(0).Value = dHIZUKE(n)
rs.Fields(1).Value = PageCNT(n)
rs.Update '更新
rs.MoveNext '次のレコードへ(次の行へ)
Next
余計な話なので、聞き流してほしいけど、
ADOって
.Edit メソッドで編集状態に
フィールド代入
フィールド代入
.Update メソッドでレコード確定
の流れじゃないのね。
DAOのクセで.Edit使ってたけど、
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Microsoft VBScript 実行時エラー エラー '800a01b6'
オブジェクトでサポートされていないプロパティまたはメソッドです。: 'Edit'
/cgi-bin/test/test057-1.asp, 行 128
.Editってメソッドは無いです。
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
・Excelの雛形シートにASPからデータをセット
・Select Form [シート$範囲]でExcelの指定範囲をレコードセットに指定
・指定範囲の先頭行にはフィールド名を指定するんだよ
・ADOには、.EDITメソッドは無いんだよ
って話でした
サクサクと、作成が進むと思ったのですが、
簡単な処理でもハマりました。
私の失敗談が、
ASPからADOを使用して、Excelファイルに書き込む
そんな処理の参考となれば幸いです。
今回のグラフ付雛形シートにデータセット、
http://www.ken3.org/cgi-bin/test/test057-1.asp
でテスト可能です。
素朴な疑問やリクエスト、今回みたいなクレームなどがあったら、
掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi
に気軽に書き込んでください。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
<復習、#Include,FileSystemObject,乱数ランダム>
こんにちは、三流プログラマーのKen3です。
今回は、
復習を兼ねて、
#Include File で、ファイルをインクルードする
FileSystemObjectでテクストファイルの読み込み処理、
乱数でランダムな数値を発生
なんて感じのネタをやってみたいと思います。
拾い読みして、何かの参考となれば幸いです。
/*
* 1.今回のキッカケ
*/
テキスト広告のローテーションを作ってみたくて(笑)
いろいろと試行錯誤した結果を兼ねて、ASP系のネタにしてみました。
/*
* 2.#Include File で、ファイルをインクルードする
*/
ASPと言っても、通常は、HTML内に<% 〜 %>でスクリプトを埋め込んでます。
a.asp
<% ASP の処理A %>
<html>
<head> </head>
<body>
ヘッダ部分に目次へのリンクなど
本文
<% ASP の処理B %>
フッダ、広告など
<% ASP の処理C %>
</body>
</html>
<% ASP の処理D サブルーチンなど %>
まぁ、書き方のキレイさ(見易さなど)
位置によっていろいろとあるのですが、
こんな感じです。
大体、HPを作成する時、構成を決めます。
----
上部 HPタイトルと目次、掲示板へのリンク、、
本文があって
下部 リンクを書く人や小金稼ぎのバナー広告
----
まぁ、わかりやすく、こんな構成だとします。
すると、上部のHTMLと下部のHTMLは変わらないんですね。
なので、ひとつの方法は、雛形のHTMLファイルを作っておいて、
それを別名でコピーして修正する、そんな方法です。
※私も使ってます。
この方法でも良いのですが、
2・3ヶ月たってくると、広告を差し替えたいなぁ、
新しいカテゴリできたので、タイトルにリンクを増やしたい・・・
と共通だったはずのヘッダ、フッダを修正する時があります。
そんな時に便利な方法が、
#Includeを使ってASPを作る方法です。
使い方は簡単で、
<!-- #Include File="info.inc" -->
と外部から挿入したいファイルを書くだけです。
具体的な使い方は、
<%@LANGUAGE=VBScript%>
<html>
<head>
<title>ASP #Include File="xxxx.inc" でファイルをインクルード</title>
</head>
<body bgcolor=#ffffff text=#000000>
<!-- #Include File="info.inc" -->
<!-- ↑ヘッダの共通イメージをインクルード -->
<h2>ASP #Include File="xxxx.inc" でファイルをインクルード</h2>
test058-1.asp<br>
#Include File="xxxx.inc"とファイルをインクルードして、<br>
共通のヘッダ、フッダを使う<br>
<hr>
[<a Href="info.inc" TARGET="_blank">info.incを開く</a>]
←使用したヘッダファイル<br>
[<a Href="inc_mokuji.inc" TARGET="_blank">inc_mokuji.incを開く</a>]
←使用したフッダファイル<br>
<!-- #include file="inc_mokuji.inc" -->
<!-- ↑フッダの共通イメージをインクルード -->
</body>
</html>
ポイントは、
~~~~~~~~~~~~
<!-- #Include File="info.inc" -->
↑ヘッダの共通イメージをインクルード
<!-- #include file="inc_mokuji.inc" -->
↑フッダの共通イメージをインクルード
なんだぁ、一行単純に書いてるだけなのね(笑)
この単純に書いた一行の処理にしていると、
ヘッダやフッダのイメージを変えたい時は、
http://www.ken3.org/cgi-bin/test/info.inc
http://www.ken3.org/cgi-bin/test/inc_mokuji.inc
といったファイルの中身を変更するだけで、
実行時に読み込まれるので、表示内容を変更することが出来ます。
http://www.ken3.org/cgi-bin/test/test058-1.asp
でテストできます。イメージを確認してください。
/*
* 3.ランダムにローテーションバナーを表示させたい
*/
さてと、
#Include File を使うと、実行時にファイルを挿入可能なことがわかりました。
一歩進んだ要求だと(そんな要求私だけかもしれないけど)
ランダムでバナー広告を切り替えて表示したい。
なんて、思うかもしれません。
乱数かぁ、、、
Randomize '乱数系を初期化
nNO = Int(Rnd * 10)
で0〜9までの数を発生させられるので、
インクルードするファイルを
http://www.ken3.org/cgi-bin/inc/hed0.inc
http://www.ken3.org/cgi-bin/inc/hed1.inc
http://www.ken3.org/cgi-bin/inc/hed2.inc
・
・
http://www.ken3.org/cgi-bin/inc/hed9.inc
とバーナー広告を10種類用意しておいて、
切り替えてインクルードしてみたいです。
<% '頭で乱数の発生
Randomize '乱数系を初期化
nNO = Int(Rnd * 10) '0〜9までの乱数を発生させる
strFNAME = "/cgi-bin/inc/hed" & nNO & ".inc" 'ファイル名を作る
%>
とファイル名を作ってから、
<!-- #include file="<%=strFNAME%>" -->
で勝負、、あれれ、
Active Server Pages エラー 'ASP 0126'
インクルード ファイルが見つかりません
/cgi-bin/test/test058-2.asp, 行 22
インクルード ファイル '<%=strFNAME%>' が見つかりませんでした。
あっ、バカみたい、””で囲って文字列にしてるよ、
よし、””をはずして、
<!-- #include file=<%=strFNAME%> -->
Active Server Pages エラー 'ASP 0126'
インクルード ファイルが見つかりません
/cgi-bin/test/test058-2.asp, 行 22
インクルード ファイル 'strFNAME' が見つかりませんでした。
できないのかなぁ、
まぁ、インクルードファイルが動的に切り替わる、、
なんて用途ないしね。
自分でファイルを開いて読みますか、
<% '自分でファイルを読む
' FileSystemObjectを生成します
Set objFS = Server.CreateObject("Scripting.FileSystemObject")
' strFNAMEを読取専用モードで開きデータを読む
Set ts = objFS.OpenTextFile(Server.MapPath(strFNAME), 1, True)
Do While ts.AtEndOfStream = False 'ファイルの終端になってない間ループ
strDATA = ts.ReadLine 'ファイルからデータを一行を読む
Response.Write strDATA
Response.Write vbCRLF '改行する
Loop
'使ったファイルは閉じようよ
ts.close
Set objFS = Nothing
%>
と素直に、テキストファイルを開いて1行読み込み、出力しました。
http://www.ken3.org/cgi-bin/test/test058-2.asp
でテストできます。イメージを確認してください。
ポイントは
~~~~~~~~~~
乱数の発生前に、
Randomize '乱数系を初期化
で
乱数系の初期化。
nNO = Int(Rnd * 10)
strFNAME = "/cgi-bin/inc/hed" & nNO & ".inc" 'ファイル名を作る
でファイル名を作ったら、
しかたなく自分でFileSystemObjectを生成して、
.ReadLineで一行読み込む、.AtEndOfStreamでファイルの終端チェック
でした。
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
・インクルードファイルの使い方
・乱数の発生
・テキストファイルをFileSystemObjectで読み込み、インクルードもどき
って話でした
サクサクと、作成が進むと思ったのですが、
簡単な処理でもハマりました。
広告、切り替えても押されないよ(笑)
http://www.ken3.org/cgi-bin/test/test058-1.asp
http://www.ken3.org/cgi-bin/test/test058-2.asp
でテスト可能です。
何かの参考となれば幸いです。
素朴な疑問やリクエスト、クレームなどがあったら、
掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi
に気軽に書き込んでください。
ASP、VBScript勉強中の三流プログラマーのKen3でした。
| No.59 |
2003/06/02 結果をExcelで返すならresponse.ContentType=application/vnd.ms-excel |
[ページTOPへ戻る] |
|
<結果をExcelで返すならresponse.ContentType=application/vnd.ms-excel>
こんにちは、三流プログラマーのKen3です。
今回は、
ASP Excel 系を探っていたら、
また新たに、
response.ContentType
response.buffer = true
response.flush
response.end
なんてサンプル拾ってきたので、
ネタにしてみたいと思います。
拾い読みして、何かの参考となれば幸いです。
/*
* 1.今回のキッカケ
*/
なかなか、ASPでExcelの処理、ADO使ってごまかしたけど、
他に方法無いか?模索中です。
そしたら、マイクロソフトのHPから、おっ?と思うサンプルを拾う。
/*
* 2.拾ったサンプル
*/
http://msdn.microsoft.com/library/en-us/dnwebteam/html/webteam07032000.asp
ちっ、ここも英語かよ、日本語のサンプルは無いの?
それとも日本語化される前に、ASP.NETになっちゃったの?
なんて前置きは置いといて、
いつもの台詞で、英語読めないけどプログラムソースはなぜか読める
そんな三流プログラマーが下記のソースを拾ってきた。
※ページの下のほうに転がってました
<%@ 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.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>などの出力の前に行うことです。
まぁ、出力のバッファだから、一番最初にやれってことね。
次は、
response.ContentType = "application/vnd.ms-excel"
これは、今から送るデータのタイプは、
"application/vnd.ms-excel"
ですよ、とブラウザに教えるために書きます。
response.ContentType = "imge/gif"
など、指定します。
文字データだけじゃなくて、ASPでいろいろと出来るんだね、、と感じた。
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だから、横に数値を書き込んで、
response.write "<td width=40><b>=sum(A1:D1)</b></td>"
ここが一番感動した、
=Sum
とワークシート関数を入れている部分です。
普通にテーブルイメージなんですね。
response.write "</tr>"
行の終了、
response.write "</table>"
テーブルの終了
response.flush
バッファを出力
response.end
ASP終了
って流れでした。
/*
* 4.終わりの挨拶 </HTML>
*/
今回は、
あまり自分のものに出来てないけど、
・出力バッファの制御
・response.ContentType = "application/vnd.ms-excel"でExcelファイルを返す
・普通にテーブルのタグでOK
・response.write "<td width=40><b>=sum(A1:D1)</b></td>"と関数も使用可能
って話でした
何かの参考となれば幸いです。
※ASPでWebのシステムって奥が深そう、、なんて言ってて、
もう時代はASP.NETになってくるのかぁ・・・
素朴な疑問やリクエスト、クレームなどがあったら、
掲示板 : http://www.ken3.org/cgi-bin/bbs/asp/wforum.cgi
に気軽に書き込んでください。
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 [ソフトウエアエンジニア]