カテゴリー名: [ADOによるデータベースの新規作成]
データベース操作のうち、新規作成とデータの書き込みを取り上げます。
AccessよりExcelの方がなじみのある人が多いと思うので、まずはExcelファイルから取り上げます。
Excelを動かすことなく VBScriptで操作します。
データベースの解説は、「読む」から入るのが王道でしょうが、読むためのデータベースがないことには始まらないので「書く」からいきます。
test.xls というファイルを作成します。
テーブル名は Sheet1 です。
「氏名」と「身長」の二つのフィールドからなるレコードを3人分登録します。
解説すべきことがいろいろありますが、まずは VBScript を掲げます。解説は、その後に記します。
これを実行すると test.xls が作成されます。既に test.xls が存在する場合は、それを削除した上で新たに作成します。
1Option Explicit 2Dim DbName, TableName, TypeStr 3Dim FSO, DbPath, ShellObj, DriverStr 4Dim CN, ConnStr, RS, sql 5 6DbName = "test.xls" 7TableName = "Sheet1" 8TypeStr = "氏名 varchar,身長 float" 9 10Set FSO = CreateObject("Scripting.FileSystemObject") 11DbPath = FSO.GetAbsolutePathName(DbName) 12If (FSO.FileExists(DbPath) = True) Then FSO.DeleteFile(DbPath) 13Set FSO = Nothing 14 15Set ShellObj = CreateObject("Wscript.Shell") 16If ShellObj.Environment("Process").Item( _ 17 "PROCESSOR_ARCHITECTURE") = "x86" Then ' 32bit版の場合 18 DriverStr = "Provider=Microsoft.Jet.OLEDB.4.0;" 19Else ' 64bit版の場合 20 DriverStr = "Provider=Microsoft.ACE.OLEDB.12.0;" 21End If 22Set ShellObj = Nothing 23ConnStr = DriverStr & "Data Source=" & DbPath & ";" & _ 24 "Extended Properties=""Excel 8.0;HDR=Yes;""" 25 26Set CN = CreateObject("ADODB.Connection") 27CN.Open ConnStr 28sql = "create table " & TableName & " (" & TypeStr & ");" 29CN.Execute(sql) ' テーブル(つまりワークシート)作成 30 31Set RS = CreateObject("ADODB.Recordset") 32sql = "select * from " & TableName & ";" 33RS.Open sql,CN,0,2,1 34RS.AddNew 35 RS.Fields("氏名").Value = "鈴木xls" 36 RS.Fields("身長").Value = 172.3 37RS.Update 38RS.AddNew 39 RS.Fields(0).Value = "高橋xls" 40 RS.Fields(1).Value = 168.5 41RS.Update 42RS.AddNew Array("氏名", "身長"), Array("田中xls", 183.6) 43RS.Update 44RS.Close 45CN.Close 46Set RS = Nothing 47Set CN = Nothing
データベースを最初に設定する場合、データベースの名前、テーブルの名前、フィールドの名前とタイプが必要です。
フィールドのタイプというのは、文字列なのか数値なのかといったデータ型のことです。
先のVBScriptでは次の3行がそれらを定めています。
DbName = "test.xls"
TableName = "Sheet1"
TypeStr = "氏名 varchar,身長 float"
「氏名」が文字列型、「身長」は数値型(浮動小数点数)です。
Accessになじみのある人には、文字列型を表す varchar に桁数指定がないところに違和感を覚えるかもしれません。
ここは varchar(20)
などのように書いてもいいのですが、Excelファイルでは、その桁数指定が無視されます。なので、varcharとだけしました。
Excelファイルは、本来、データベース用として設計されていないので、Accessファイルと比べた場合、いくつか機能的に不十分なところがあります。
マイクロソフトは、データベースにアクセスするためのエンジンを切り替えました。Office2003ころまでは JET.4.0、Office2007以降では ACE.12.0 です。
32bitのWindowsでOffice2007以降が導入されていれば、おそらく JET, ACEの両法が使えると思います。Office2003までだと JETしか使えないケースがあるかもしれませんが。
64bitのWindowsの場合は、JETが使えず、ACEだけ利用できるというケースが多いのではないでしょうか。
正確には「Windowsが32bitか64bitか」ということではなく、VBScriptが実行されるときに暗黙のうちに呼び出されている WScript.exe または CScript.exe が32bit版か64bit版かの違いが影響します。64bit版だと、JETを使えずACEを利用せざるを得ないということです。
というような事情があるので、今回のVBScriptでは 32bitか 64bitかを確認するようにしています。
Set ShellObj = CreateObject("Wscript.Shell")
とした上で、
ShellObj.Environment("Process").Item("PROCESSOR_ARCHITECTURE")
の値を見ます。
この値が “x86” であれば32bit版、それ以外なら64bit版であると推測されます。たとえば “AMD64” だと64bit版です。
32bit版ならJETエンジンを使い、64bit版だとACEエンジンを使うようにします。次に述べる「接続文字列」でその辺の設定をします。
データベース test.xls のフルパスが C:\work\test.xls の場合でいうと、データベースに接続するための接続文字列が下のようになります。
長いので2行にして掲げますが、ほんとは1行です。
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\work\test.xls;
Extended Properties="Excel 8.0;HDR=Yes;"
上は JET.4.0 を指定しているので 32bit用です。
64bit用は下のようになります。
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\work\test.xls;
Extended Properties="Excel 8.0;HDR=Yes;"
HDR=Yes
というのは、ヘッダーの扱いを指定するものです。
Yesだと、ワークシートの1行目をフィールド名とみなすことになります。
Noにすれば、1行目をフィールド名ではなくデータとみなします。
Excelファイルをデータベースとして扱う場合は、HDRをYesにしておくのが無難です。
特に、ワークブックを新規に作成するときは、HDRをNoにしても意味ないのでYesにします。
既存のワークブックを読み取ってデータベース操作するときは、HDRをNoにした方がいいケースもあると思いますが……
VBScriptの中で、ADOの接続用オブジェクトを変数CNに代入しています。
このCNがデータベース操作の中核を担います。
「接続文字列」が変数ConnStrに代入されている場合、CNの生成とオープンは次のようにして行います。
Set CN = CreateObject("ADODB.Connection")
CN.Open ConnStr
SQL(構造化問合せ言語)の命令文が変数sqlに代入されている場合、
CN.Execute(sql)
とすればSQL命令が実行されます。
データベースのテーブル(Sheet1)を生成するための命令文は下のとおりです。
create table Sheet1 (氏名 varchar,身長 float);
上を文字列として変数sqlに代入しておいて、CN.Execute(sql)
とすればテーブルが生成されます。
ここで疑問を感じる人がいるかもしれません。
「テーブルを生成する前に、test.xlsというデータベース本体を生成する必要があるのではないか?」
この疑問は当然で、実際、Accessデータベースの場合は、テーブルを生成する前にデータベース本体を生成しなければなりません。
ところが、Excelの場合はテーブル生成時にデータベース本体が暗黙のうちに生成されます。
既に test.xls というデータベース本体が存在していれば、新たに生成されたりはしませんが、test.xlsがまだない場合、新規に生成されます。
テーブルを生成した後は、いよいよデータの書き込みです。
ですが、書き込みの前にレコードを扱うための下準備を行う必要があります。
レコードの処理は、レコードセットオブジェクトを設けて、それにより行います。
まず Set RS = CreateObject("ADODB.Recordset")
としてレコードセットオブジェクトを生成します。
次にレコードをオープンしますが、パラメータをいくつか指定します。
まず、下のSQL命令文を予め変数sqlに代入しておきます。テーブルから全てのフィールドを抽出するSQL命令文です。
select * from Sheet1;
その上で、次のようにするとレコードセットを書き込み用にオープンできます。
RS.Open sql,CN,0,2,1
改めて生成とオープンを連続して書くと下のとおり。
Set RS = CreateObject("ADODB.Recordset")
sql = "select * from Sheet1;"
RS.Open sql,CN,0,2,1
既に存在しているデータベースから一定の条件に合致するデータだけ取り出したいようなときは、sqlをもっと複雑なものにした上でレコードセットをオープンします。
第3、第4、第5パラメータの 0,2,1 については次の項で説明します。
RS.Open sql,CN,0,2,1
の 0 ですが、
これは、注目レコードの移動方式(カーソルタイプ)です。
前から後ろに向かって順番どおりに移すタイプか、
後ろから前に戻るなど自由に移せるタイプかなどを指定するものです。
次の値を指定できます。
数値 | 定数名 | 説明 |
---|---|---|
0 | adOpenForwardOnly | レコードセットの先頭から後方へ移動。高速に動作(既定値) |
1 | adOpenKeyset | 自由に移動。参照専用 |
2 | adOpenDynamic | 自由に移動。他のユーザの更新を参照可能 |
3 | adOpenStatic | 自由に移動。他のユーザの更新を参照不可能 |
RS.Open sql,CN,0,2,1
の 2 は、ロックタイプです。
レコードを読取り専用/更新可能のどちらでオープンするか、
更新可能のときは他の利用者の更新との兼ね合いをどうするかなどを指定します。
次の値を指定できます。
数値 | 定数名 | 説明 |
---|---|---|
1 | adLockReadOnly | 読み取り専用(既定値) |
2 | adLockPessimistic | 排他ロックを行う |
3 | adLockOptimistic | 共有ロックを行う |
4 | adLockBatchOptimistic | 複数のレコードを一括更新処理 |
ロックの詳しいことは分かりませんが、データベースを他の人と共有するとか、複数のソフトから同時期にアクセスするというのでなければ、「排他」でも「共有」でも、どちらでもいいと思います。
RS.Open sql,CN,0,2,1
の 1 はオプションです。第1パラメータの種類を明示するためのものです。
サンプルではSQL命令文を変数sqlに代入して、それを第1パラメータとして指定しています。このような場合は、オプションを 1(定数名 adCmdText)にします。
SQL命令文ではなくテーブル名を指定した場合は、オプションとして 512(adCmdTableDirect)または2(adCmdTable)を指定します。
オプションは、省略されることも多いようです。省略すると自動判別されますが、指定した方が若干でもスピードアップにつながるようです。
オプションの詳細については、マイクロソフト社の Recordset オブジェクトの基本を参考にして下さい。
このサイトには、カーソルタイプやロックタイプの説明もあります。
データの書き込みはレコードごとに行います。一人分を書き込んだら、次に二人目を書き込みます。
まず、RS.AddNew
として新しいレコードを書き込める状態にします。
次はフィールドごとの書き込みです。下のようにします。
RS.Fields("氏名").Value = "鈴木"
RS.Fields("身長").Value = 172.3
これで「氏名」と「身長」のデータをセットしたことになります。
といっても、実際にデータベースに書き込みできた訳ではありません。メモリー上に一時記録されただけということのようです。
ちゃんと書き込みするためには RS.Update
を記述します。
二人目のデータも同じように、RS.AddNew
と RS.Update
で囲む形で行います。
さっきはフィールドの指定を “氏名” とか “身長” という文字列で行いましたが、インデックス番号で指定することもできます。
その場合は、1からではなく0から始まります。下のような記述です。
RS.AddNew
RS.Fields(0).Value = "高橋"
RS.Fields(1).Value = 168.5
RS.Update
AddNewにパラメータを渡してデータを書き込むこともできます。
第1パラメータはフィールド名が格納された配列、第2パラメータが各データが格納された配列です。
次のように記述します。
RS.AddNew Array("氏名", "身長"), Array("田中", 183.6)
RS.Update
以上が主な書き込みの方法です。
データベースへのアクセスが一通り終了したら、レコードセット(RS)、ADOの接続用オブジェクト(CN)の両法ともクローズします。
RS.Close
CN.Close
これでデータベースの処理が終了です。
Excel2007以降の test.xlsx は、ADOのJET.4.0エンジンで扱うことはできません。ACE.12.0エンジンで行います。
32bit版, 64bit版のどちらであっても、ACE.12.0エンジンを用います。ACEが使えない環境では、残念ながらxlsxファイルを扱うことができません。
xlsファイルとの違いは、この点だけです。
したがって、接続文字列(ConnectionString)が違うだけということになります。
xlsx用の接続文字列は下のとおり。2行になっていますが、ほんとは1行です。
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\work\test.xlsx;
Extended Properties="Excel 12.0 XML;HDR=Yes;"
あと、32bit版か64bit版かの識別をしても仕方ないのでやりません。
1Option Explicit 2Dim DbName, TableName, TypeStr 3Dim FSO, DbPath 4Dim CN, ConnStr, RS, sql 5 6DbName = "test.xlsx" 7TableName = "Sheet1" 8TypeStr = "氏名 varchar,身長 float" 9 10Set FSO = CreateObject("Scripting.FileSystemObject") 11DbPath = FSO.GetAbsolutePathName(DbName) 12If (FSO.FileExists(DbPath) = True) Then FSO.DeleteFile(DbPath) 13Set FSO = Nothing 14 15ConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;" & _ 16 "Data Source=" & DbPath & ";" & _ 17 "Extended Properties=""Excel 12.0 XML;HDR=Yes;""" 18Set CN = CreateObject("ADODB.Connection") 19CN.Open ConnStr 20sql = "create table " & TableName & " (" & TypeStr & ");" 21CN.Execute(sql) 22 23Set RS = CreateObject("ADODB.Recordset") 24sql = "select * from " & TableName & ";" 25RS.Open sql,CN,0,2,1 26RS.AddNew 27 RS.Fields("氏名").Value = "鈴木xlsx" 28 RS.Fields("身長").Value = 172.3 29RS.Update 30RS.AddNew 31 RS.Fields(0).Value = "高橋xlsx" 32 RS.Fields(1).Value = 168.5 33RS.Update 34RS.AddNew Array("氏名", "身長"), Array("田中xlsx", 183.6) 35RS.Update 36RS.Close 37CN.Close 38Set RS = Nothing 39Set CN = Nothing
以上でこのページは終了です。
データベースの本丸である Accessファイルについては次項で取り上げます。
なお、データの書き込みをSQL命令文の insert into
で行うこともできます(zip圧縮ファイルに含まれている create_xls02.vbs, create_xlsx02.vbsを参照)。
SQL命令文のinsertについては Accessファイルのところで触れます。
〜 以上 〜