Access Tips by pPoy

   トップへ←Top    QueryへQuery  FormへForm  ReportへReport  Module(Sub)へSub  Module(Function)へFunction  ExcelへExcel  Etc.へEtc.  Word連携へWord

etc. 固定長テキストファイル (全角半角混じり) を正しくテーブルに取り込む方法
《FileSystemObject》 (Access2000〜Access2010)
通常 Access で固定長テキストファイルを取り込む場合は、Access の 「インポート」 機能を使用します。

この機能では、全てが半角の場合は正しくインポートできますが、
特定の全角文字が含まれる場合、桁がずれてしまいます。
  例: ギリシャ文字・囲み英数字(丸付き数字)・ローマ数字・単位記号 etc.

これを防ぐ為には、レジストリを書き換える方法が、マイクロソフトによって説明されています。
『テキストを Access にインポートした際に 区切り位置がずれる場合の対処方法』
結構危険な方法でもあり、しかも全ての PC に対して行う必要があります。

以下は VBA で固定長テキストファイルを正しくインポートする方法です。
FileSystemObject, Windows Script Host 及び lenbt関数 (ユーザ定義関数) を使用します。
ユーザーのデスクトップパスは、WSH を使用して取得します。
※ ADO への参照設定が必要です。

≪準備1≫

デスクトップに、以下のような 固定長テキストファイルを置きます。 ファイル名は、「固定長テキストデータ.txt」 です。
固定長テキストファイル

ファイルは 「SJIS 形式」 で保存されています。
各行の末尾は改行マーク (CRLF) で終わっています。

各データは、
10 Byte
20 Byte
30 Byte
10 Byte
になるように、半角スペースで調整されています。
≪テスト≫

このテキストファイルを、一旦インポートウィザードを使用して取り込んでみます。
インポートウィザードの結果

←左は 取り込んだ結果です。

一見正しく取り込まれているように見えますが よく見ると、
12 行目と 28 行目のデータの一部がずれているのがわかります。

「jpg」 の 「j」 の文字が手前の列の後ろにくっついています。

やはり、標準の機能ではうまくいかないようです。
気を取り直して、VBA で取り込む準備をします。
この頁のTOPへTop
≪準備2≫

VBA でデータを取り込む前に、空のテーブルを作成します。
Et049_3.jpg

← テーブルは、取り込むファイルに合わせて作成する必要があります。
今回の例では、以下のテーブルを作成しました。

テーブル名: tbl_Hana2_IN

フィールド名サイズ
ID数値型長整数型
FileNameテキスト型20
myMemoテキスト型30
etcテキスト型10


※ オートナンバー型は使用できません。エラーとなります。
※ フィールド名はなんでもかまいません。 データの内容にあった名前を付けます。
※ フィールドの型はすべてテキスト型でも OK です。ただし、文字列が入るだけの長さが必要です。
≪準備3≫

テーブル作成後、こちらの 「lenbt関数」 を標準モジュールに貼り付けてください。
全角半角混じりの文字の Byte数を正しく取得する為に必要な関数です。
この頁のTOPへTop
≪準備4≫

最後に、以下のコードを標準モジュールに貼り付けます。
Sub inFixedLengthData()
'固定長テキストファイル(全角半角混じり)を正しくテーブルに取り込む
'全角文字の取込み不具合解消版 2011/04/03 pPoy
    Dim cnn As ADODB.Connection
    Dim rst As ADODB.Recordset
    Dim stSQL As String

    Dim myWSH As Object             'WScript
    Dim myDesktopPath As String
    Dim objFSO As Object            'FileSystemObject
    Dim objFileIn As Object         'File
    
    Dim stFileIn As String          'ファイルのフルパス
    Dim stLine As String            '1行分のテキスト
    Dim myTmp As String             '1フィールド分のテキスト
    
    Dim stfld(3) As String          '★1行分の文字列格納用
    Dim fldSize(3) As Integer       '★フィールド毎のサイズ(byte)
    
    Dim maxLEN As Long              '1行の文字数
    Dim startP As Long              '開始位置
    Dim i As Long, j As Long
    
    Const ForReading = 1
    Const txtFileName = "固定長テキストデータ.txt"  '★
    Const tblName = "tbl_Hana2_IN"                  '★
    
    '取り出すデータの各byte数を配列に格納
    fldSize(0) = 10                 '★ID
    fldSize(1) = 20                 '★FileName
    fldSize(2) = 30                 '★myMemo
    fldSize(3) = 10                 '★etc
    
    'デスクトップパス取得
    Set myWSH = CreateObject("WScript.Shell")
    myDesktopPath = myWSH.SpecialFolders("Desktop")
    Set myWSH = Nothing
    
    'テキストファイルのフルパス
    stFileIn = myDesktopPath & "\" & txtFileName
    
    'ファイルの存在確認
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    If Not objFSO.FileExists(stFileIn) Then
        Set objFSO = Nothing
        Exit Sub
    End If
    
    '既存データ削除
    Set cnn = CurrentProject.Connection
    stSQL = "delete from " & tblName & ";"
    cnn.Execute stSQL
    DoEvents
    
    '空のテーブル open
    Set rst = New ADODB.Recordset
    stSQL = "select * from " & tblName & ";"
    rst.Open stSQL, cnn, adOpenKeyset, adLockOptimistic

    '取込み開始
    Set objFileIn = objFSO.OpenTextFile(stFileIn, ForReading)
    Do Until objFileIn.AtEndOfStream
        '1行読み込み
        stLine = objFileIn.Readline
        maxLEN = Len(stLine)                '1行の文字数
        startP = 1                          '読込開始位置
        '行内ループ
        For i = 0 To UBound(fldSize)
            myTmp = ""
            'フィールド内ループ
            For j = startP To maxLEN
                myTmp = myTmp & Mid(stLine, j, 1)
                If lenbt(myTmp) = fldSize(i) Then
                    stfld(i) = myTmp
                    startP = startP + Len(myTmp)
                    myTmp = ""
                    Exit For
                End If
            Next j
        Next i

        'テーブルに格納
        With rst
            .AddNew
            For i = 0 To UBound(stfld)
                rst(i).Value = stfld(i)
            Next i
            .Update
        End With
    Loop

    MsgBox "処理修了!", vbOKOnly
    rst.Close: Set rst = Nothing: Set cnn = Nothing
    Set objFileIn = Nothing: Set objFSO = Nothing
End Sub
この頁のTOPへTop
≪結果≫

VBA実行結果

← 全てのデータが正しく取り込まれています。
≪補足≫
  1. 取込むデータを変更する場合は、取込み先のテーブル構造の変更と共に、コードの 「★」 マーク部分の変更も必要です。

  2. このコードではテキストデータに項目行が存在しない為、データの最初から最後まで読み込んでいます。
    項目行付きのデータの場合は、項目行をスキップさせる処理が必要です。

  3. 特定の全角文字が含まれるテキストデータをインポートする際桁がずれる不具合は、Access2000 以降の現象です。
    Access2010 になって解消されているかと思っていましたが、ダメでした。 (Windows7+Access2010 でも発生します。)
    ※ この不具合は、Access97 では発生しません。


この頁のTOPへTop
【念の為の注意書きです。】
このページ(下位ページ含む)の全ての物の無断転載を禁止いたします。
又、当ページ(下位ページ含む)に記載されていることは、全て自己の責任において実行してください。

☆ 感想をお知らせください (直接ブラウザから送信致します。メールアカウントは不要です。)
  form mail はこちら


Copyright(C) pPoy 2011