LoginSignup
3
3

More than 1 year has passed since last update.

Access VBA CSVのインポートとエクスポートをSchema.iniとクエリで行う Import and Export Text DB file with Query

Last updated at Posted at 2019-10-26

特徴と注意

参照設定が必要

ActiveX Data Object Library6.1をセットする

拡張子とファイルの位置

出力するtxtファイル、csvファイル、インポートする出力ファイル、accdbファイルは同じフォルダに置き、生成する
出力は別フォルダでもよい。しかし別の場所に保存するとそこにschema.iniができるため、非効率でミスとの原因になる。
このため、すべて同じフォルダが良い。

今回使うファイル

インポートするテキストファイル名(コンマ区切り,UTF-8)

CSVimportExport.txt

エクスポートするテキストファイル名(コンマ区切り,UTF-8)

test.txt

schema.ini

インポート、エクスポートするファイルのデータ形式、フィールド名(の有無)、日付、通貨の書式を決める
schema.ini
CSVimportExport.txtとtest.txtのあるフォルダに置くこと
またこのクエリでテキストファイルに出力する最大の特徴はSchema.iniが自動的に作成される点
Export Csv File with using Query have a very useful. Because first time exporting with Query Make Or Add Table or Query infomation to Schema.ini.(not perfect)

accessのファイル

test.accdb

存在するフォルダ

すべてのファイルはc:\hogeにある(この前提はクエリのSQLで使用する)

mdbでもaccdbでもどちらでもよい

とりあえずこれらはmdb時代に書かれたものが多いが、今回はaccdbで実験した。

現在の主流な方法ではない

通常のサイトは99%Docmd.TranspherTextしかない
しかし
ImportExportText マクロ アクション
もあり、ここでもSchema.iniが有効になる。

前提

accdbファイル

c:\dbfolder
test.accdbがある

インポートするテキストファイル

csv,txtどちらでもよい
UTF-8
1行目のJames Smithの後ろに機種依存文字、碇の絵文字が入っている
日付は時刻情報がない。mm/dd/yyyy型になっている

test.txt
ID,F01Name,F02Birthday,F03Currency,F04Long
"1","James Smith⚓","01/01/2019","$100025.55",2255000
2,"Amy Rock",02/01/2019,"$1024.55",2244000
3,"Steave Springsteen",02/01/2018,"$24.55",2244000

VBAのコード Import Export

Sub ExportQueryToCsv()
'VBA for Micorsoft Access 2007 Later
'SQL文でCSVを書き出す。この時、ID=1だけ出力する
'もしなかった場合は列のフィールド名だけ返す。
'この時Schema.iniに出力するファイルが書いていなければ追記する。Schema.ini自体がなければSchema.iniを作成して追記する。
'ただし機種依存文字がフィールド名にあると文字化けする。
'Docmdと異なる最大の特徴が、副次的にSchema.iniが追記型で作成される点
'絞り込んで1レコードだけ出力し、わざとSchema.iniを作らせる
'このためSelectが2回重なっている
'今回はaccdbであるが、mdbでも可能
'Const dbfolder = "H:\dbfolder\
'同名のテーブルが出力されている場合、同名のテーブルのフィールドが変わっていても、Sheama.iniは書き換えられない。
'コメントは行頭に半角セミコロン
'MaxRowsが出てこない
'通貨単位は円で固定(日本の場合)ドルから読み込ませても円。小数点2桁は保持しているが、出力すると四捨五入されて円単位になる。
'日付はmm/dd/yyyyで読み込ませると時間がついてそのままだと yyyy/mm/dd hh:mm:ssで出力される。時間を使っていない場合は日付も指定する。
'Schema.iniはこのVBAで出力しても通貨単位は変わらないため、通貨単位を設定するとドル記号が付される。こうするとドルとして正常に表示される。
'Yes /No 型はbit LookUpWizardでチェックボックスにしても反映されない。
'Col7=ff LongChar Attribute  'Attribute Hyperlink 'Hyperlink型はメモ型にAttributeが追加されたもの
'Col9=dd BigInteger '大きい数値は大きい数値
'Col10=ddr Decimal Precision 18 Scale 4 '
'Col12=fiole OLE 'OLEはOLEになる
'Col13=figu Char Width 255 ’短い数値のレプリケーションID型はテキストになる
'Dbname:hoge.accdb
'Csv:test.csv
Dim CN As New ADODB.Connection
Dim myDB As String, myTbl As String, myTxtFile As String
Dim myFolder As String, tmpSTR As String
Dim TableName As String
TableName = "T_CsvImport"
'書き出し元のaccdbファイル
myDB = CurrentDb.Name
'書き出すデータ
myTbl = "(select * from TableName);"
'テキストファイル名
myTxtFile = "test.txt"
'書き出し先のフォルダ名
myFolder = CurrentProject.Path

'同名のCsvファイルがあると作成に失敗するので削除する。
'また、この性質からSQLによりテキストファイルに追記することは不可能と考えられる。
With CreateObject("Scripting.Filesystemobject")
If .FolderExists(myFolder) = False Then Exit Sub
If .FileExists(myFolder & "\" & myTxtFile) = True Then .DeleteFile myFolder & "\" & myTxtFile
'If .FileExists(myFolder & "\" & "Schema.ini") = True Then .DeleteFile myFolder & "\" & "Schema.ini"
End With

'書き出し先を指定する文字列を作成
tmpSTR = "[TEXT;DATABASE=" & myFolder & "].[" & myTxtFile & "]"

'データベースに接続し、SQL文を実行 (テキストファイル書き出し)
Set CN = CurrentProject.Connection
With CN
.Execute "SELECT * INTO " & tmpSTR & " FROM " & "(SELECT * FROM " & TableName & " WHERE ID = 1);" 'ID=1は例。フィールドIDで1を取り出している);の並び、'1'はデータ型が違うとしてエラーになる。
End With

CN.Close: Set CN = Nothing

End Sub
Sub CSVからテーブルを作る()
'通貨単位は円で固定(日本の場合)
'VBA for Micorsoft Acc
Dim cDB As DAO.Database: Set cDB = Application.CurrentDb
Dim cCdb As Database: Set cCdb = CodeDb
Dim CN As New ADODB.Connection
Dim myDB As String, myTbl As String, myTxtFile As String
Dim myFolder As String, tmpSTR As String
Dim TableName As String
Dim tdf As TableDef
'読み込むテキストファイル名
myDB = "TestCsvTable.txt" ' UTF-8でもよい、ヘッダーがあってもよい、IDは数値でオートナンバーにならない、ドルでも円に強制換算される。日付は入る
'書き出す(作成する)テーブル
myTbl = "T_CsvImport"

'書き出し先のフォルダ名(テキストファイルとDBは同じフォルダにある)
myFolder = CurrentProject.Path

'同名のテーブルがあると失敗するため削除する
For Each tdf In cDB.TableDefs
If tdf.Name = myTbl Then
DoCmd.SetWarnings False
DoCmd.DeleteObject acTable, myTbl
DoCmd.SetWarnings True
Exit For
End If
Next

'書き出し先を指定する文字列を作成
tmpSTR = "[TEXT;DATABASE=" & myFolder & "].[" & myDB & "]"

'データベースに接続し、SQL文を実行 (テキストファイル書き出し)
Set CN = CurrentProject.Connection
With CN
.Execute "SELECT * INTO " & myTbl & " FROM " & tmpSTR & ";"   'ID=1は例。フィールドIDで1を取り出している);の並び、'1'はデータ型が違うとしてエラーになる。
End With

CN.Close: Set CN = Nothing
Application.RefreshDatabaseWindow
End Sub

ImportするときのアクションクエリのSQL

クエリの場合、ダブルクリックして実行するとメッセージが2回表示される。
この時既存のT_CsvImportテーブルは削除され、新しく作成される。
ID列を設定していると、オートナンバー型ではなく長整数型になっている。

SELECT * INTO T_CsvImport FROM [TEXT;DATABASE=C:\hoge].[TestCsvTable.txt];

Exportするときのアクションクエリ

ただし、Exportするほうはファイル名に注意。拡張子の前はピリオドではない。
また保存してGridViewからスィッチするとAliasが付く。

SELECT * INTO [TEXT;Database=C:\hoge\].[test#txt]
FROM (SELECT * FROM T_CsvImport WHERE ID = 1);

しかしQA_Exportなどとして保存して開くと、書き換わる

SELECT * INTO [test#txt]
FROM (SELECT * FROM T_CsvImport WHERE ID = 1)  AS [%$##@_Alias];

この書き方がサブクエリだが、上記のサブクエリの書き方はVBAでは有効であったが、もともとは角かっこで包むものらしい。
http://blog.jojo.jp/?eid=831205
このサイトの書き方のALIASに[%$##@_Alias]を生かして

SELECT * INTO [Text;database=C:\hoge\].[test#txt]
FROM [SELECT * FROM T_CsvImport WHERE ID = 1].  AS [%$##@_Alias];

と書いてもよい。
ただしやはりクエリではフォルダ名がなくなってしまい、角かっこも書き換わる。

SELECT * INTO [test#txt]
FROM (SELECT * FROM T_CsvImport WHERE ID = 1)  AS [%$##@_Alias];

出力ファイルをデータベースと同じフォルダに置くと表記も簡便になる。
またAliasが追加される現象は2003年には知られており、
mdb(access)におけるFrom句でのサブクエリ実装方法
http://blog.jojo.jp/?eid=831205
CreateViewにすると付加される。
https://www.pcreview.co.uk/threads/why-does-access-create-alias-_alias.1072230/

Because you have a Sub-Query which is the SELECT statement
inside the first SELECT.

When you switch between the SQLView and GridView, Access
re-arranges the SQL String as it interprets. If you don't
want this to happen, work wxclusively with SQLView.

鍵を握るのはSchema.ini

Schema.iniは基本的にはANSIファイルが良いが、今回はなぜかUTF-8で大丈夫だった。

Schema.ini

  1. ドル記号にしても円になり、csv/txtに出力するときには表示桁数で出力される。小数点は四捨五入される。これは設定で小数点以下2桁を表示してもそうなる。Schema.iniの細かい書式設定はエクスポートを想定しているようだ。
  2. 米ドルだと金額が変わってしまうため、これを防ぐためには出力するときに以下のようにドルと小数点を指定するとよい。
  3. 千円単位のコンマは実際にインポートファイルの中で使用され、ダブルクォーテーションで包まれている"$10,000.22"のようなデータがある場合はCurrencyThousandSymbol=,有効。表示にコンマがきちんと表示される。しかし、CSV形式でエクスポートするときは有効ではない。また使用していないのにCurrencyThousandSymbol=,を使うとエラーになる。通貨の区切りとデータの区切りが同じになるためである。だからと言ってコンマ区切りの場合でCurrencyThousandSymbol='のような指定をしてもコントロールパネルで有効ではないため無視される。
  4. 機種依存文字をフィールド名に使っていると読み込まれない。エラーになる。またアクセスのフィールド名は最初は数字は不可で15文字、重複は許されない。
  5. 機種依存文字をデータに使っている場合はUTF-8に対応する65001をインポート、エクスポート時に指定しダブルクォーテーションで包む。
  6. 一度出力されると、Schema.iniのデータは変更されなくなる。このため、テーブルの構成を変えたら、該当部分を手動で変える必要がある。
  7. 日付は読み込むとき型を指定すると、出力したとき時間まで追加する。このためエクスポート時には日付の形をきちんと指定する。
  8. ハイパーリンクは数字で指定される。手動で設定する場合と微妙に表現が違う。GUIDは数字ではなくテキスト扱いになるなど、方が違うものもある。
  9. その他細かい注意点はコードやSchema.iniのコメント行に記載している。
  10. これまではschema.iniはメモ帳(notepad.exe)を起動し、入力をしてAnsi形式でschema.iniで保存し、拡張子を.iniに変えていた。修正するときは右クリックで編集か、プログラムで開くでメモ帳を選択していた(ただし次からこのファイルはこのアプリケーションで開くにはチェックを入れない)。しかしこの方法では多数のフィールドのあるテーブルはミスが発生した。
  11. 同様にDocmdのインポート方法でも多数のフィールドの定義がGUIで行う(さらに詳細の出し方が難しい)、フィールドの幅が広狭あって指定しづらいうえに、勝手に「コード」という名称があるとインデックス扱いするのためそれをやめさせるなど、非常に煩雑だった
  12. この方法ではクエリを使ってインポート、エクスポートを繰り返し、schema.iniを改善することによって、csvのインポート、エクスポートを正確に行うことができる。
  13. 一度schema.iniに定義されると、Accessは次からそれを参照して修正せず、エラーを出したりする。しかし10の方法で手動で開き、該当ファイル分を全削除するか、修正することで対応できる。メモ帳は開きっぱなしでも独占しないため、Accessのcsvの入出力結果で簡単に修正できる。
  14. また一度読み込んだものを同じパターンで出力する場合は、出力したschema.iniの結果を入力ファイルのものとしてコピペするとよいので(ただしMaxscanrowsなどを設定する必要がある)、インデックスがオートナンバーにならないことを除けばかなり楽である。
  15. さらに下記の方法で出力ファイル側のレコード数を絞り込めば、全部出力することがないため、ディスク容量を2倍使用するということがない。
  16. AccessはAMPM形式の表示は読み込むことができない。Excelは可能。ただし、2019/01/01 00:00:00 AMのように分との間に半角スペースが必要
  17. https://www.tek-tips.com/viewthread.cfm?qid=457050 によるとDateTimeFormat=yyyy-mm-ddとしてもCol3="Date Hired" DateTime(mmddyyyy)のように列ごとの指定は可能だとしている(未検証)

絞り込むSQLクエリ

出力するときID=1のみ

"SELECT * INTO " & tmpSTR & " FROM " & "(SELECT * FROM " & TableName & " WHERE ID = 1);"
ここでFrom のあとにもう一度***(Select * From Tablename Where ID =1)P***とカッコ書きで追加されている。
ここは単純にテーブル/クエリでもよい。
"Select * Into test.txt FROM Tablename:"`
でも有効であるが、テーブルのデータが多いと時間がかかる。またデータ自体はいらないときはわざと存在しないIDを指定する。
するとフィールド名とSchemaを入手できる。
しかし、出力結果を何度か見てSchema.iniやデータ形式、内容に問題がないことを確認してから小さく絞り込んだほうが良い。

Insert Intoの中身の関係

インポート

Select Into 新しいテーブル form ファイル名

エクスポート

Select Into ファイル名 form テーブル、クエリ名、あるいは選択クエリ

SQLの実行で、ファイル名とパスの表記とActiveconnectionで包まれていること

これはADODB.Connectionからの流れが非常に重要。ちょっと前の発掘した記事の書き方で書くと、

Dim CN As ADODB.Connection : Set Cn = New ADODB.Connection '上はズルしているけど、本当はこう記載する。
Set CN = CurrentProject.Connection 'ActiveConnectionではない
With CN
.Execute "SELECT * FROM [Text;DATABASE=C:\FolderName;HDR=NO;].[Temp.CSV];" 'テーブル作成、削除などのアクションクエリはExecute
Emd With

ここの[Text;DATABASE=C:\FolderName;HDR=NO;].[Temp.CSV]はあたかもディレクトリが一つのデータベースであるかのように表記されているのがユニークだと思う。

schema.ini

schema.iniはこの方法でかなり効率的に取得できるが、それでもMaxScanRowsなどの指定は出力されない。
ドルはあまり使わないと思うが、Importで再利用するときはMaxScanrows、文字コードなどいくつかの設定は自分で設定しなければならない。
しかし列名や設定を全部書くのは大変なので、この方法でSchemaを取得できるのはかなり効率が良い。

schema.ini
[test.txt]
ColNameHeader=True
CharacterSet=65001
;コメントは命令の後ろにセミコロンをつけて続けることはできない。スペースを入れてもダメ
;VBAと異なり、可読性のために、=の前後に空白を入れない。入れると別の意味になるためエラーを引き起こす
;タブ区切りはTABLmitedになる
;文字コードは https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
Format=CSVDelimited
;ドルの時していると有効
CurrencySymbol=$ 
CurrencyDigits=2
CurrencyNegFormat=1
;日付はyyyy/mm/dd型しか使用しない場合宣言すると時間の00:00:00が付かない。
DateTimeFormat=yyyy/mm/dd
CurrencyPosFormat=1
;これは指定するとコンマ区切り(CSVLimited)はエラーになる しかし'や`も効かない。
;CurrencyThousandSymbol=,
;これは指定するとコンマ区切り(CSVLimited)はエラーになる
;CurrencyDecimalSymbol=.
;これは指定するとコンマ区切りはエラーになる;
;DecimalSymbol=,
TextDelimeter="
Col1=ID Integer
Col2=F01Name Char Width 255
Col3=F02Birthday Date
Col4=F03Currency Currency
Col5=F04Long Integer
[TestCsvTable.txt]
ColNameHeader=True
CharacterSet=65001
Format=CSVDelimited
DateTimeFormat=mm/dd/yyyy
NumberLeadingZeros=True
MaxScanRows=25
;ドルの場合指定しても円になるが、小数点以下は保持される
CurrencySymbol=$
CurrencyDigits=2
;これは指定するとインポート時にコンマ区切りはエラーになるが、コンマ区切りの大きい数があり、ダブルクォーテーションで区切られている場合はエラーにならない。しかし安定しないので指定しないほうが良い。またテキストファイルもコンマ区切りで数字を表記しないほうが良い。
;CurrencyThousandSymbol=,
Format=CSVDelimited
TextDelimeter="
Col1=ID Integer
Col2=F01Name Char Width 255
Col3=F02Birthday Date
Col4=F03Currency Currency
Col5=F04Long Integer

インポート、エクスポートがAccessのうちに保持されない

この方法はDoCmd.TranspherSpreadSheetやDocmd.Outputtxtよりあまりマニュアルがない。
しかし、

やっぱり現在のAccessの公式解説は間違っている

2つの文字セットから選択できます。ANSI、OEM です。 CharacterSet Schema.ini の設定は、Windows レジストリ、ファイルごとの設定をオーバーライドします。 次の例では、ANSI に設定する文字を設定する Schema.ini エントリを示します。
Charset=ANSI
CharSet=OEM

としか書いていないが、実際はUTF-8の65001日本語の932も有効だ。上記のクエリで出力するとSchema.iniに何も書いていなければ932で出力するからだ。

http://makoto-watanabe.main.jp/access/dahowchangingtext.htm#start
こちらがわかりやすい。

2021/07/31
そして、検索にかからないAccess用のSchema.ini の解説は
ドキュメント Office クライアントの開発 Access Access デスクトップ データベース リファレンス Microsoft Access SQL リファレンス 外部データ ソース用の Windows レジストリ設定 テキスト データ ソース ドライバーの初期化
テキストデータソースドライバーの初期化
が本当であるが、タイトルは全くわからない上に、最初はレジストリのことが機作してあり、普通はこのあとSchema.ini の説明があるとは思わないだろう。

CurrencyPosformat

これは番号で指定する。日本円はややこしいので指定しないほうがよいが、他国の通貨では必要になるだろう。この記述は

$1は0
1$は1
のように対応しているため、
CurrencyPosformat=0
col=の前に記載する。
CurrencyPosformat=$1
とは書かない。

CurrencyNegFormat

マイナスの場合の取り扱い。
これも番号で指定する。
マイナス1000ドルは-$1,000と表示したいと思う
その時は1を入れる。
何も指定しないと出力時はエクセルと同様カッコ書きになる。
またインポートするテキストでマイナスになる場合ドル記号を用いるには$-2000.22のように通貨記号の後ろに書くとうまくいく。

マイナスの例のテーブル

これを試すためには以下のテキストをTestCsvTable.txtで保存し、schema.iniを作成してインポートしてみるとよい。
出力ファイル名はtest.txtとする。
このcsvのインポート、エクスポートは

TestCsvTable.txt
ID,F01Name,F02Birthday,F03Currency,F04Long
"1","James Smith⚓","01/01/2019","$-100025.55",2255000
2,"Amy Rock",02/01/2019,"$1024.55",2244000
3,"Steave Springsteen",02/01/2018,"$24.55",2244000
マイナスの例のためのschema.ini
schema.ini
[test.txt]
ColNameHeader=True
CharacterSet=65001
;コメントは命令の後ろにセミコロンをつけて続けることはできない。スペースを入れてもダメ
;VBAと異なり、可読性のために、=の前後に空白を入れない。入れると別の意味になるためエラーを引き起こす
;タブ区切りはTABLmitedになる
Format=CSVDelimited
;ドルの時していると有効
CurrencySymbol=$ 
CurrencyDigits=2
CurrencyNegFormat=1
;日付はyyyy/mm/dd型しか使用しない場合宣言すると時間の00:00:00が付かない。
DateTimeFormat=yyyy/mm/dd
CurrencyPosFormat=1
;これは指定するとコンマ区切り(CSVLimited)はエラーになる しかし'や`も効かない。
;CurrencyThousandSymbol=,
;これは指定するとコンマ区切り(CSVLimited)はエラーになる
;CurrencyDecimalSymbol=.
;これは指定するとコンマ区切りはエラーになる;
;DecimalSymbol=,
TextDelimeter="
Col1=ID Integer
Col2=F01Name Char Width 255
Col3=F02Birthday Date
Col4=F03Currency Currency
Col5=F04Long Integer
[TestCsvTable.txt]
ColNameHeader=True
CharacterSet=65001
Format=CSVDelimited
DateTimeFormat=mm/dd/yyyy
NumberLeadingZeros=True
MaxScanRows=25
;ドルの場合指定しても円になるが、小数点以下は保持される
CurrencySymbol=$
CurrencyDigits=2
;これは指定するとコンマ区切りはエラーになるが、コンマ区切りの大きい数があり、ダブルクォーテーションで区切られている場合はエラーにならない。
CurrencyPosformat=0
;CurrencyThousandSymbol=,
Format=CSVDelimited
TextDelimeter="
Col1=ID Integer
Col2=F01Name Char Width 255
Col3=F02Birthday Date
Col4=F03Currency Currency
Col5=F04Long Integer

CurrencyThousandSymbolを指定するとコンマ区切りの場合はエラーになるが例外がある

コンマ区切りの大きい数があり、ダブルクォーテーションで区切られている場合はエラーにならない。しかし、安定しないのでテキストファイルでは通貨もコンマ区切りせず、これを回避したほうが良い

余談

今回の
[発掘:Access]外部テキストファイルとの接続方法
がなければわからないものだった

参考

文字コード

概略日本語版
https://www.ipentec.com/document/windows-codepage-list
公式
https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
ただし上記ページにはMSの横暴が書かれていない
Shift_JIS と Windows-31J (MS932) の違いを整理してみよう
https://weblabo.oscasierra.net/shift_jis-windows31j/
Shift-JisとCP932の違い
https://qiita.com/kasei-san/items/cfb993786153231e5413
知るのと使っているのはまた別。

Schema.iniのOEMUNICODEはたぶんUTF-16

https://sites.google.com/site/autohotkeyjp/reference/misc/CodePage
メモ帳のUNICODEはUTF-16なので、このSchema.iniもUtf-16をユニコードとして設定していると思われる。

フィールド名の予約語

Access 2002 およびそれ以降のバージョンの Access の予約語の一覧
https://support.microsoft.com/ja-jp/help/286335/list-of-reserved-words-in-access-2002-and-in-later-versions-of-access
NO,NAMEなどはうっかりすると踏んでしまう。
Access の予約語と記号
https://support.office.com/ja-jp/article/access-%E3%81%AE%E4%BA%88%E7%B4%84%E8%AA%9E%E3%81%A8%E8%A8%98%E5%8F%B7-ae9d9ada-3255-4b12-91a9-f855bdd9c5a2

Access データベースでの作業時に使用すべきでない特殊文字
https://support.microsoft.com/ja-jp/help/826763/error-message-when-you-use-special-characters-in-access-databases

もっとわかりやすいのはこちら
アクセス2007フィールド名・テーブル名など命名方法は大事かな?
https://kaiton.hatenadiary.jp/entry/20070302/1172795401
要注意なのは丸付き数字が考えられる。また旅館・ホテルの中黒など。
カタカナは全角。

もし予約語が使われていた場合のクエリの表記方法
https://kazenetu.exblog.jp/9579962/

フィールド名の予約語はそのままインポート/エクスポートするファイル名にも適用される

Access データベースでの作業時に使用すべきでない特殊文字
https://support.microsoft.com/ja-jp/help/826763/error-message-when-you-use-special-characters-in-access-databases

Access にインポートしたテキスト ファイルにタブ文字や他の特殊文字が含まれていると、これらの特殊文字が変換され、ボックスとして表示されます

ADODBでUTF-8のCSVを取り込む

http://my-business-adversaria.blogspot.com/2012/08/adodbutf-8csv.html
このように2012年の時点でUTF-8は65001であることが知られている。
また、UTF-8がADODBであることも重要。

見出し行のないテキストファイルを読み込む

https://antonsan.net/vt/excel-db/heading-4/page-046
ここに記載されたコードを現代版に書き換えたものがExportQueryToCsvである。
しかしこの記事も2018年。まだJET4.0は有効なのだろうか。
しかし64bitの場合通じない恐れがあるので、Ace12.0を使っている。もちろんAce15.0やAce16.0も有効だ。

schema.iniファイルを利用してテーブルの定義情報通りに読み込む

(TAB区切りのテキストファイルを読み込む)
https://antonsan.net/vt/excel-db/heading-4/page-045
Schema.iniはTAB区切りのテキストファイル(TSVという場合もある)をExcelに読み込ませるときも有効とされる。
Text File Format (Text File Driver)
https://docs.microsoft.com/en-us/sql/odbc/microsoft/text-file-format-text-file-driver?view=sql-server-ver15
あるフィールドにデータがないことを示す場合は固定長の場合、スペースが必要。通常の可変長の場合は区切り文字を詰めるとよい。
Note
For delimited files, a NULL is represented by no data between two delimiters.
Note
For fixed-width files, a NULL is represented by spaces.

これはできない

※もしかしたらですが、SQLが使える、ということはテキストファイルの内容もSQL+ODBC経由でレコードの追加・編集などもできるかもしれません。Excelファイルが対象の場合ではSQLでは削除だけができませんが、テキストファイルならSQLで削除もできるのかも???でも、未確認なのでご自分でも調べてみてください。

これは無理。Schemaを使う場合、CSVファイルで、絞り込みやインポート、エクスポート、選択はできるが、削除はできない。また追記もできない。既存のファイルがあるとエラーになる。こうならないのはローカルテーブルに追記する場合だけのようだ。
ただし、以下のようにレコードセットを2つ作る方法なら追記できる。
この時aRSはFowardonlyが早い、テキストファイルに接続するars2はadOpenStaticにする。aRs2をadOpenDynasetにするとエラーになる。
またテキストファイルの表記はピリオドをナンバー記号にする(シャープに似たやつですがナンバー記号です)。それとコンマ区切りは単にCSVDelimitedではなく、Delimitedになる。さらにフォルダー名は最後に\をつけること。
あとこの方法、たぶんすごく遅い。
最終投稿日は2019/10/18でAccess2000の話題を扱うようなサイトは信用ができない。

Dim CN As New ADODB.Connection
Dim CN2 As New ADODB.Connection
Dim aRS As New ADODB.Recordset
Dim aRs2 As New ADODB.Recordset
Dim i As Long
CN2.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.Path & "\;Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
CN2.Open
Set aRS = New ADODB.Recordset
aRS.Open "Select * from T_CsvImport Where ID = 1;", CN, adOpenForwardOnly
Set aRs2 = New ADODB.Recordset
aRs2.Open "Select * From test#txt", CN2, adOpenStatic, adLockOptimistic
Do Until aRS.EOF = True
aRs2.AddNew
For i = 0 To aRS.Fields.Count - 1
aRs2.Fields(i).Value = aRS.Fields(i).Value
Next
aRs2.Update
aRS.MoveNext
Loop
aRS.Close
aRs2.Close

このように追記される

"ID","F01Name","F02Birthday","F03Currency","F04Long"
1,"James Smith⚓",2019/01/01,-$100025.55,2255000
1,"James Smith⚓",2019/01/01,-$100025.55,2255000
1,"James Smith⚓",2019/01/01,-$100025.55,2255000

拡張子がTsv形式のタブ区切りテキストファイルでも、レジストリに登録する必要はない

ファイル(テキスト, Excel, Access)への接続文字列の生成 [VBScript/VBA]
http://blog.livedoor.jp/tea_cocoa_cake/archives/15943900.html

.tsvファイル (TAB区切りテキスト)を開こうとすると「データベースまたはオブジェクトは読み取り専用なので、更新できません。」エラーが発生する可能性あり。レジストリを変更する必要があるかも?

これもSchema.iniが有効。レジストリを変更する必要はない。
https://www.connectionstrings.com/textfile/
ConnectionStringsは接続文字辞典のようなサイトで、こうしたテキストファイルの接続も記載されているが、Jet4.0のままである。
やはりエラーになる
このため、Microsoft.Jet.OLEDB.4.0はMicrosoft.ACE.OLEDB.12.0に読み替えて使うこと(重要)

和暦バグの回避

Accessは和暦だと読み込まないというバグがある。
これを回避するためにExcelを利用する方法。
https://qiita.com/Q11Q/items/dd793d751fc4d67d0c61
最終的にPowerShellまで行き着いた
https://qiita.com/Q11Q/items/695c987d52c09b663ffc

選択クエリ(2021/07/30追記)

SELECT  * FROM [Text;DATABASE=C:\FolderName;HDR=YES;].[jexSchemaTab.csv];

実はこのように選択クエリも記述できる。ただし、True/False型はチェックボックスにはならず、値(0,-1)で表示される。
これを使ってDAO.Recordseを作ることもできる。

拡張子がtabのテキストファイル(2021/07/30追記)

テキストデータソースドライバーの初期化
を見ると、レジストリにテキストのデータベースファイルとして解釈する拡張子にtabがある。
上記のヘルプを見ると、

テキスト ベースのデータを探す場合に参照されるファイルの拡張子です。既定値は、txt、csv、tab、および asc です。値の型は REG_SZ 型です。

原因は不明だが、以下のようにダブルクォーテーションで囲まれているcsvファイルをメモ帳でタブ区切りに変換し、この記事の方法でSchema.ini を作り、変換するとエラーが発生した。

"head","field01","Field2"
"a","b","c"

メモ帳でタブ文字を検索 置換する - Windows Tips
という方法で","を"t"に置換し、tab区切りにした。(Tabは見えないのでtと表記)もちろんSchema.iniもTab区切り)もので、エラーが起きたことはなかったが、先日、MEMO型のフィールドで読み込みエラーが起きた。コンマが入っているとエラーを起こしたのかもしれない。
これが拡張子をtabにしてSchema.iniに書き込むと、インポートエラーが消えた。

Access でファイルのインポートまたはエクスポートを実行すると、読み取り専用のエラーが発生する場合がある

Access 2010

現象

Microsoft Access 2010、Microsoft Access 2000 または Microsoft Access 97 でファイルのインポート、またはファイルのエクスポートを実行した際に、以下のエラー メッセージが表示され、ファイルのインポート、またはエクスポートに失敗する場合があります。

データベースまたはオブジェクトは読み取り専用であるため、更新できません。
このエラーは、Access に Jet データベースエンジンのセキュリティ上の問題に対応したサービス パックが適用された環境で、拡張子が無い、または、以下の拡張子以外のファイルをインポート、またはエクスポートしようとした際に発生します。


  • txt
  • csv
  • tab
  • asc
  • htm
  • html

原因

Jet データベースエンジンは Text IISAM を使用することでテキスト ファイルを編集することが可能なため、システム テキストファイルの誤った編集によるセキュリティ上のリスクが発生する可能性がありました。この問題に対応するため、Microsoft ACE データベース エンジン、Microsoft Jet データベース エンジン 4.0 および Microsoft Jet データベースエンジン 3.5 では、Service Pack 3.0 以降、レジストリに指定された拡張子以外のファイルをインポート、またはエクスポートすることができなくなったためにこの現象が発生します。

状況

この動作は仕様です。

仕様と言いながらJet4.0では修正されている。
しかしこの拡張子tabというのはAccess97からテキスト形式のデータベースとして認識されるようになっていたことがわかる。

Accessの機能からインポート、エクスポートするとき(2021/07/30追記)

Access VBAでExcel・CSVデータをインポートする
この記事はAccessの外部データインポート機能から、インポート定義、Docmd.Tranpfertxt、と流れるように説明してあり、よくまとまっているが、SQLはちょっとしか触れられていない。しかし以下の本家の解説
Access>インポートとエクスポート
では、通常のインポートやエクスポートはここに掲載されているもの。本記事で書かれているような項目は一切記載されていない。しかし、いくつかAccessやExcelのテキストファイルに関する内部構造が伺える。また、リンクテーブルとインポート、エクスポートが同じ項目にある。確かに、選択クエリでCSVを使うと、リンクテーブルのようになっており、おそらく、リンクテーブルは、選択クエリをテーブルにしたものだといえる。
また、クエリデザインを使ったクエリ(本当はSQL)のことは
Access>クエリ
に記述されている。
しかし、ここではSQLの概要程度がわかるだけである。詳細は、
Microsoft Access SQL リファレンス
にあるのだが、ここでもIn句を参照しろといいながら、In句はリンクもない。
それではこの記事のIn句のような使い方はどこにあるのかというと
Docs>Office VBA リファレンス> Access>概念>構造化照会言語 (Access SQL) >>IN
実はここにText;Databaseの書き方のヒントは記載されている。

テキスト (.txt または .csv) ファイルのインポートまたはエクスポート
Excelはこの記事ではコンマ区切りがcsv、それ以外、例えばタブ区切り(文字コード9))はtxt形式という扱いになっているという。Accessとは異なっていることがわかる。

拡張子tabは謎のまま残された(2021/07/30追記)

なお、上記の拡張子のうち、
https://www.tohoho-web.com/ex/draft/extension.htm
から

asc形式テキストファイルで、ASCIIコード形式であることを明示した拡張子
ということはわかった。

またODBCでは記述する。しかし、Azureでは、
インジェスト用に Azure Data Explorer でサポートされているデータ形式
Azureではtsvファイル形式がリストに上がっているが,asc形式、tab形式はない。
拡張子tabはいずれ使われなくなるのだろう。しかし、なぜこのような拡張子があるのか、本当にTab区切りと割り切っていいのか、不明である。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3