[VBS 32bit] Access 2016 64Bit Windows 10 で Access97のテーブルにデータを流し込む方法

#これまでのおさらい
##リンク
[Access 2013 Later Make Access 97 mdb Access 2013以降で Access97 のMDBファイルを作る](http://qiita.com/Q11Q/items/e173701e0746779b75ca)
[ACCESS2013以降（64/32bit）でAccess1.0のMDBを作り、Access2003以降のMDBに変換する](http://qiita.com/Q11Q/items/1793f43a1fd4dd3f480f)
[Access 2016 64 bit Windows 10 で Access 97/95 Access2.0 のMDBファイルを作る](http://qiita.com/Q11Q/items/213c6c98e280715e8295)

##これまでわかってきたこと
- Access2016は今でもAccessのすべてのヴァージョンについてテーブルとクエリが実は対応している
- これはVbscript 32Bitで可能となる
- oledb.12.0 はAccess 2010 再頒布可能コンポーネントでAccess 2013 2016でも使用可能となる。
- Access1.0から作成が可能で、最適化をすることでヴァージョンアップが可能。
- このため、Accss97のファイルはAccess2003のMDB形式に変換して確認ができる。
- ***データベースファイルを作成した瞬間なら、テーブル。クエリが作成可能。***

ということがわかってきました。今回は最後の点について確認します。その前に必要なスクリプトを表示します。

#VBScriptの設定
###テキストファイル。
通常のAccess2016では無視しますが、テーブルに取り込むデータをテキストファイル。
は1行目からデータでとします。ファイル名F:\TypeTest.txt

```
tel,3,2017/5/4
bel,4,2018/5/8
Candy Dul,6,2014/5/8
Rank,22,2013/8/6 14:22:25
```
###テキストファイルのポイント

 - コンマ区切りという前提で
 - ダブルクォーテーションで囲まない。
 - 日時はリテラル#2014/12/8#のような形にしない。
 - 1行目を項目にするとテクニックがいるので1行目を項目にしない
###テーブルの仕様
ファイル名F:\testType.txt

|項目名|データタイプ|
|:-:|:-:|
|test | text(255)|
|count| Integer|
|Day| Datetime|

### データベースの名前
 - F:\TESTType97.mdb Access97形式ファイル
 - F\TEST10_2003.mdb 2003形式MDBファイル
 - 言語 日本語
 - Const DB_LANG_JAPANESE = ";LANGID=0x0411;CP=932;COUNTRY=0"

#Script
##DBとテーブル作成
###データベースとテーブルを作成する
```vbnet:c:\hoge\genDb97.vbs
Main
'%SystemRoot%\SysWow64\cscript.exe //Nologo "C:\hoge\genDb97.vbs"
Sub Main()
' 定数/変数宣言部
Const DB_LANG_JAPANESE = ";LANGID=0x0411;CP=932;COUNTRY=0"
Const cnsDbVersion30_AC95_AC97_Jet30_Jet35 = 32
Const DB__DYNASET = 2
Const DB_APPEND_ONLY = 8
Const FILE_NAME = "F:\TESTType97.mdb"
Dim dbe, db, strDbPath
Dim wsh : set wsh=createobject("Wscript.Shell")
' MDB がすでに存在するか調べます。
strDbPath = GetUniqueDbName(FILE_NAME)
If LenB(strDbPath) = 0 Then Exit Sub
' MDB を作成します。
Set dbe = Wscript.CreateObject("DAO.DBEngine.36")
Set db = dbe.CreateDatabase(strDbPath, _ 
DB_LANG_JAPANESE,cnsDbVersion30_AC95_AC97_Jet30_Jet35)
' テーブルを作成します。
db.Execute "CREATE TABLE 売上テーブル " _
& "(販売コード AUTOINCREMENT " _
& "CONSTRAINT PrimaryKey PRIMARY KEY, " _
& "支店 TEXT(255), " _
& "販売日 DATETIME, " _
& "商品 TEXT(255), " _
& "個数 INTEGER, " _
& "売上 CURRENCY);"
db.Execute "CREATE INDEX 販売日 " _
& "ON 売上テーブル (販売日) WITH DISALLOW NULL;"
'TestType Table作成
db.Execute "CREATE TABLE TestType " _
& "(TEST TEXT(255), " _
& "Q INTEGER, " _
& "Day DATETIME);"
' 変数の参照を解放します。
db.Close: Set db = Nothing
Set dbe = Nothing
' ユーザーに結果を通知します。
MsgBox "に '" & FILE_NAME _
& "' を作成しました。", vbInformation
End Sub

Function GetUniqueDbName(filename)
' デスクトップに "test.mdb" というファイルが無いか調べ、
' すでに存在していれば空文字列を、まだ存在していなければ
' フルパスを返します。
Set WshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
strResult = fso.BuildPath( _
WshShell.SpecialFolders(""), _
filename)
If fso.FileExists(strResult) Then
MsgBox "デスクトップに '" & filename _
& "' と同名のファイルが既に存在します。" _
& vbCrLf & vbCrLf & "処理を中止します。", _
vbCritical
Else
GetUniqueDbName = strResult
End If
End Function

Sub GenRecs(rs)
' 過去 30 日分のテスト用レコードを追加します。
' 変数を初期化します。
varSites = Array("", "", "池袋", "上野", "品川")
varProducts = Array("烏龍茶", "ジュース", _
"グレープジュース", "コーヒー", "紅茶")
varPrices = Array(150, 250, 250, 180, 180)
' レコードを追加します。
With rs
For i = Date - 30 To Date
For j = 0 To (Int(6 * Rnd) + 5)
.AddNew
.Fields("支店").Value = varSites(Int(5 * Rnd))
.Fields("販売日").Value = i + Rnd
intProdId = Int(5 * Rnd)
.Fields("商品").Value = varProducts(intProdId)
.Fields("個数").Value = Int(10 * Rnd) + 2
.Fields("売上").Value = .Fields("個数").Value _
* varPrices(intProdId)
.Update
Next
Next
End With
End Sub
```
####補足 テキストデータにタイトルがある場合
```
"TEST","Q","Day"
"tel","3","2017/5/4"
"bel","4","2018/5/8"
"Candy Dul","6","2014/5/8"
"Rank","22","2013/8/6 14:22:25"
```
のような場合について

```vbnet
objFile.SkipLine  '<<<---:::This Line Add
Do Until objFile.AtEndOfStream 
    strEmployee = objFile.ReadLine 
    arrEmployee = Split(replace(strEmployee,"""","",1,-1), ",") '<<<---:::Replace Method Add
    objRecordSet.AddNew 
    WScript.Echo "arrEmployee(0):" & arrEmployee(0)
    WScript.Echo "arrEmployee(1):" & arrEmployee(1)
    WScript.Echo "arrEmployee(2):" & arrEmployee(2)
    objRecordSet("Test") = arrEmployee(0) 
    objRecordSet("Q") = arrEmployee(1) 
    objRecordSet("Day") = arrEmployee(2) 
    objRecordSet.Update 
Loop
```
Skipline命令で1行目をスキップさせます。
データはそのままだとダブルクォーテーションが入ってしまうのでReplaceで取り除きます。
"""",""
のようにダブルクオーテーションが4ついります。

###oledbでtypetestテーブルにデータを入れる。

 -  Microsoft.Jet.OLEDB.4.0
 -  Microsoft.OLEDB.12.0でもよい([Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント](https://www.microsoft.com/ja-jp/download/details.aspx?id=13255)再頒布をダウンロードする)[64/32共存はこの手法を使用](http://bitdatasci.blogspot.jp/2014/08/64windows3264microsoft-access-odbc.html)
 -  [64bit版Windowsでの「Microsoft.Jet.OLEDB.4.0」について](http://qiita.com/yaju/items/86314412741deb806366)では
 
 > VBSなどにプロバイダの記述がある場合は下記のように書き換える。
 >"Provider=Microsoft.Jet.OLEDB.4.0;" → "Provider=Microsoft.ACE.OLEDB.12.0;"

とあるが、このような書き換えは不要。どちらでも動く。つまりOLEDB12.0はインストールする必要があまりない。OLEDBの機能はAccess2013ではOLEDB.15.0　Access2016ではOLEDB16.0が機能する。足りないものはDao36-Jet4.0をVBS 32bit で起動させればよい。

 -  Access2013はOLEDB15.0だが、不安定でOLEDB12.0のインストールは[必須](http://qiita.com/yaju/items/86314412741deb806366)
 -  Access2016 64bitのOLEDB16.0はエラーになるのでJET 4.0の方がよい。
#####つまり再頒布可能コンポーネントがなくてもJet4.0を32BitVBSで使えば問題がない。

```vbnet:VBCSVToaccess.vbs
'%SystemRoot%\SysWow64\cscript.exe //Nologo "C:\hoge\VBCSVToaccess.vbs"
Const adOpenStatic = 3 
Const adLockOptimistic = 3 
Const ForReading = 1
Const FNtype1 ="F:\TESTType97.mdb"
Const FNtype2 ="F:\TEST10_2003.mdb"

Set objConnection = CreateObject("ADODB.Connection") 
Set objRecordSet = CreateObject("ADODB.Recordset") 
 
'objConnection.Open  "Provider = Microsoft.Jet.OLEDB.4.0; " &  "Data Source = c:\scripts\test.mdb"  

objConnection.Open "Provider = Microsoft.Jet.OLEDB.4.0; " & _ 
        "Data Source = F:\TESTType97.mdb"  

objRecordSet.Open "SELECT * FROM TestType", _ 
    objConnection, adOpenStatic, adLockOptimistic 
 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFile = objFSO.OpenTextFile("F:\testType.txt") 
 
Do Until objFile.AtEndOfStream 
    strEmployee = objFile.ReadLine 
    arrEmployee = Split(strEmployee, ",") 
 
    objRecordSet.AddNew 
    WScript.Echo "arrEmployee(0):" & arrEmployee(0)
    WScript.Echo "arrEmployee(1):" & arrEmployee(1)
    WScript.Echo "arrEmployee(2):" & arrEmployee(2)
    objRecordSet("Test") = arrEmployee(0) 
    objRecordSet("Q") = arrEmployee(1) 
    objRecordSet("Day") = arrEmployee(2) 
    objRecordSet.Update 
 
Loop 
 
objRecordSet.Close 
objConnection.Close 

```

###Access97>>Access2003以降MDｂ形式への変換
このJetCompctは32ビットでしかJROが提供されていないため64ビットでは動かない
またJROであるため、Jet4.0をMicrosoft.Ace.Oledb.12.0に書き換えてもスクリプトがエラーで停止する。

```vbnet：JetCompact10.vbs
Option Explicit
'%SystemRoot%\SysWow64\CScript.EXE //Nologo "C:\hoge\JetCompact10.vbs"
Const oldFile = "F:\testType97.mdb"
Const NewFile = "F:\test10_2003.mdb"
Dim JIRO : Set JIRO = CreateObject("JRO.JetEngine")

Dim strOldConnect : strOldConnect = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & oldFile & ";"

Dim strNewConnect : strNewConnect ="Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & NewFile & ";Jet OLEDB:Engine Type =5;"

With CreateObject("Scripting.FileSystemObject")
If .FileExists(oldFIle)=False then Wscript.Quit
If .FileExists(NewFile)=True then Wscript.Quit
End With
JIRO.CompactDatabase strOldConnect, strNewConnect
Set Jiro = Nothing
```
###VBSCript　Dao120-OLEDB12.0 Dao36-Jetのその他の書き方
[Hello!Dao World - CX's Hello, World!](http://cx20.main.jp/blog/hello/category/access/):::[魚拓](http://megalodon.jp/?url=http%3A//cx20.main.jp/blog/hello/category/access/)
VBSによるDao ADODBの接続方法の一覧。ただしDAO関係は32Bit CSCriptを使うこと。

###流し込むときのデータ型に注意
[ACCDB ファイル形式と MDB ファイル形式の相違点](https://support.office.com/ja-jp/article/ACCDB-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%E3%81%A8-MDB-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%E3%81%AE%E7%9B%B8%E9%81%95%E7%82%B9-8cf93630-0b68-4a40-a13c-7528b9f074b6):::[魚拓](http://web.archive.org/web/20161109022728/https://support.office.com/ja-jp/article/ACCDB-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%E3%81%A8-MDB-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%E3%81%AE%E7%9B%B8%E9%81%95%E7%82%B9-8cf93630-0b68-4a40-a13c-7528b9f074b6)

添付ファイル型とメモ型が無理だと思われる。あとANSI(JIS)とユニコードの違い、フォントの違いも影響するだろう
[Q.Windows VistaとXPで「辻」の字形が異なる-JustSystem](http://support.justsystems.com/faq/1032/app/servlet/qadoc?QID=043561)

###MDBファイルのメンテ
[http://itwebkatuyou.com/7900](http://itwebkatuyou.com/7900)
[[ACC2000] ダウンロード センターで入手可能な Jet 最適化ユーティリティ文書番号:273956 - 最終更新日: 2005/11/17 - リビジョン: 1](https://support.microsoft.com/ja-jp/help/273956/acc2000-jet-compact-utility-available-in-download-center)
>Jet 最適化ユーティリティ (JETCOMP.exe) は、Microsoft Jet データベース エンジン 3.x および 4.x で作成したデータベースを最適化するスタンドアロンのユーティリティです。このユーティリティは、Microsoft Jet データベース エンジン 3.x または 4.x と組み合わせて実行することで、破損したデータベースを修復することができます。Microsoft Access 最適化ユーティリティや CompactDatabase メソッドは、Microsoft Jet データベース エンジン 3.x または 4.x と組み合わせて実行することができますが、これらのユーティリティでは修復できないデータベースでも、JETCOMP.exe で修復できることがあります。この理由は、Microsoft Access 最適化ユーティリティや CompactDatabase メソッドでは、データベースを最適化する前に、そのデータベースを開いて閉じることが試行される点にあります。これらのユーティリティでデータベースを再度開くことができない特定の状況では、最適化処理を継続できず、データベースの修復が行われません。***JETCOMP.exe では、最適化の前にデータベースを開いて閉じることが試行されません。このため、Microsoft Access 最適化ユーティリティや CompactDatabase メソッドでは修復不可能なデータベースの修復が行えることがあります。***

>注 : JETCOMP.exe のユーザー インターフェイスは英語版のみが提供され、また、Microsoft Product Support Services によるサポートはありません。ただし、JETCOMP.exe は、Microsoft Jet データベース エンジンが対応している任意の言語のデータベースを最適化することができます。JETCOMP.exe は自由に配布できるユーティリティですが、以下の製品のいずれかをコンピュータにインストールしている必要があります。
>「注 : JETCOMP.exe を実行する前に、データベースにアクセスしているユーザーがいないことを確認する必要があります。
  - Microsoft Office 97
  - Microsoft Office 2000
  - Microsoft Access 97
  - Microsoft Access 2000
  - Microsoft Visual Basic 5.0
  - Microsoft Visual Basic 6.0
  - Microsoft Access 97 のランタイム バージョンを含む Microsoft Office Developer Edition 97 ランタイム アプリケーション
  - Microsoft Access 2000 のランタイム バージョンを含む Microsoft Office Developer 2000 ランタイム アプリケーション
  - Microsoft Jet データベース エンジン 3.5 を含む Microsoft Visual Basic 5.0 ランタイム アプリケーション
  - Microsoft Jet データベース エンジン 3.5 または 4.0 を含む Microsoft Visual Basic 
6.0 ランタイム アプリケーション

※このプログラムはAccess2016 64bit Windows10でも動いた 
なお、Access97形式の場合、Jet3.xの欄を選ぶこと
Jet4.0Xを選ぶとAccess2003形式のMDBに変換されてしまう。
つまりAccess2000とかなくても実はこのツールで変換できてしまう。
今までの苦労は何だったのか。
なお、下の赤い波線を引いた部分がインジケーターになっている。進行状況はそこで把握できる。
![2017-07-01_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/126919/6f361f4b-7c4c-1ebb-c153-63d95adff815.jpeg)