アプリ版:「スタンプのみでお礼する」機能のリリースについて

テキストファイルをAccess2003を使用しVBAでインポートする為に、schema.iniを作成しましたがエラーが発生してしまいます。

テキストファイルとschema.iniを同じフォルダ内に置いて解決すると思っておりましたが、何か他に指定する事などあったのでしょうか?

ファイルは省略してますが次のようになります。

▼テキストファイル
A100000B5400ファンデーション
A200000K3800化粧水

▼schema.ini
[商品マスタ.txt]
ColNameHeader=False
MaxScanRows=0
CharacterSet=932
Format=TabDelimited
Col1=商品番号 Text
Col2=販売価格 Currency
Col3=商品名 Text

▼VBA該当箇所
DoCmd.TransferText acImportDelim, , "商品マスタ", "C:\商品マスタ.txt", True

上記設定でインポートを試みたところ、実行時エラー '2391':が発生しうまく処理できませんでした。

因みに、インポートウィザードを使用した場合と、第二引数にインポート定義を指定した場合は問題なくインポートできます。

色々検索はしたものの解決策が見つからない為質問しました。
ご存知の方がいらっしゃいましたらご教示いただければ幸いです。

A 回答 (6件)

今回の課題は、テキストファイルの短縮だったのですが、


直接の回答が出来なかったですが、回答をよく理解下さったようで
答えに力が入り、自分も色々勉強させていただきました。
    • good
    • 0
この回答へのお礼

本来ならば質問の趣旨「schema.ini使用方法について」に沿って答えを書いて下さった30246kikuさんをベストアンサーに選ぶべきなのでしょうが、この一連の質問に3ヶ月もお付き合い頂いたchayamatiさんを今回はベストアンサーに選ばせていただきたいと思います。

30246kikuさん、chayamatiさん、本当にありがとうございました。

お二方をはじめ、他の回答者の方からも色々と手ほどきを頂けたお陰で、今回の疑問も解決できましたし、少しですがAccessを理解する事ができました!

余談ですが現在は、更なる理解を深める為、自社で管理している紙ベースの商品情報をAccessで管理できるよう試行錯誤しております。

お礼日時:2014/10/28 18:56

>DoCmd.RunSQL ("Insert Into 商品マスタ(商品番号,商品名,メーカーコード, "



これは命令文の1部分です
DoCmd.RunSQL ("Insert Into 商品マスタ(商品番号,商品名,メーカコード, " _
& "ブランドコード,重要成分コード,大分類コード,販売価格,廃番フラグ,更新日) " _
& " Select 商品番号,商品名,メーカコード,ブランドコード,重要成分コード, " _
& "大分類コード,販売価格,廃番フラグ,更新日 From 商品M中継 ;")
上記4行が一つになって1つの命令文になりますが、これを分割して文字列結合します。
分割した文字列の末尾に _(アンダーバー)を付けて続きがあることを明記します。
文字列の文頭に 文字列結合記号の&を付けます。

>調べてもRTN()が何を意味しているのか分からなかった為、手詰まりとなりました…
>予想では、そのVBAのすぐ上にある「Private Sub 商品マスタインポート_Click()~End Sub」までの式を利用してという意味なのでしょうか。
概念的にはメインプログラムとサブプログラム(サブルーチン)があると考えて下さい
RTNは【 routine 】の子音を抜き出したもので
自分だけかもしれませんがメインプログラム名と同じ名前は使えないのでRTNを付加しています。
メインプログラムの命令文が多くなりすぎると、見直し「デバッグ」が大変なので
一部分を抜き出してサブプログラムにしたり、他のプログラムで同じ処理があるときは
サブルーチンは共有目的で作成することもあります。

プログラムの1塊は
Private Sub 商品マスタインポート_Click()
DoCmd.SetWarnings False
If MsgBox("商品マスタ再インポート", vbYesNoCancel) = 6 Then
商品マスタインポートRTN
Else
MsgBox ("取り消し")
End If
End Sub
のように Private Sub プログラム名 _ イベント名()で始まり End Subで完成しますね

Private Sub 商品マスタインポートRTN()
DoCmd.SetWarnings False
DoCmd.RunSQL ("delete from 商品M中継;")
DoCmd.RunSQL ("delete from 商品マスタ;")
DoCmd.TransferText acImportDelim, , "商品M中継", "D:\okwave\テキスト\商品マスタ.txt", True
DoCmd.SetWarnings True
DoCmd.RunSQL ("INSERT INTO 商品マスタ SELECT 商品M中継.* FROM 商品M中継 ; ")
MsgBox ("商品マスタ 再インポート完了")
DoCmd.SetWarnings False
End Sub
こちらは Private Sub プログラム名 () とイベント名が欠落しています。
他のプログラムから呼び出してもらいます。
Private Sub 商品マスタインポート_Click()の中の 商品マスタインポートRTN が呼び出す処理です。

今回はif文の一部にするのが嫌で、サブルーチン方式にしました。


突然ですが、変数の暗黙の宣言が規定値になっています。
「メーカコード」と「メーカーコード」で苦労されましたね
暗黙の宣言を禁止する設定があります。
【VBE】コーディング画面のメニューバーから
【ツール】⇒【オプション】⇒【変数の宣言を強制するにチェック】⇒【OK】

------------------------------------------------------
先が見えたようなので、こちらからの積極的なアドバイスはここまでにします。
    • good
    • 0
この回答へのお礼

お返事が遅くなり大変申し訳ございません。

完成後に他の仕様がどのようになったかを含めお返事差し上げようと思ったのですが、後出しで「この情報も必要だよ~」「こんなファイルがあるよ~」なんて事が起こり、日々検索と試作の繰り返しで中々ご連絡差し上げられませんでした…

> 分割した文字列の末尾に _(アンダーバー)を付けて続きがあることを明記します。
> 文字列の文頭に 文字列結合記号の&を付けます。
処理が次の行にまたがっている事を表す為の表記だったのですね!

文字数を減らす為にダラダラ長く書くべきか、見易さ・処理の単位を優先して複数行に分けて書くべきか悩む場合も出てくるのでしょうか。
業務で使用したい為、今回新たに作ったプログラムは動くなら良しとしているのですが、少し落ち着いたら細かい見直しが必要そうです。

> RTNは【 routine 】の子音を抜き出したもので
RTNとは元からAccessに存在するメソッド(?)などの事だと思い込んで調べていました。
なるほど見つからない訳ですね^^;

> サブルーチンは共有目的で作成することもあります。
そのような使い方も出来るのですね。
今回記述していただいたVBAはメインプログラムとサブプログラムで構成されていたのですね。

> Private Sub 商品マスタインポートRTN()
上記2つの事から、Private Sub 商品マスタインポート_Click()の中の、商品マスタインポートRTNを名乗っている処理が呼び出されているという事なのですね!

> 暗黙の宣言を禁止する設定があります。
VBAを使う前に必要な設定が実はあったのですね。
確かにどんなソフトも勝手をよくする為に、設定を見直す事があります!
「メーカコード」と「メーカーコード」このようなタイプミスにエラーを返してくれる設定でもあったのですね。

この設定に限らずですが、ここで質問せず独学で進めていたら、しばらく気づかなかった事が山程あったでしょう。

ありがとうございます。

今回の問題のファイルの他に2つのプログラム(?)を作成し、やっと実用に入れそうです。

1つは、Excelファイルとデータベースを照らし合わせ、一致した情報をリストアップし、それをCSV書き出しするものです。
こちらは完成し、ダブルクリック起動で処理を完結する内容をマクロを組み合わせて作りました。

もう1つは、独立させて使うか、今回のデータベースに組み合わせて使うか検討段階で、
ある情報をSwitch関数を使い抽出条件によって複数の指定番号に振り分ける内容のクエリを作りました。

なるべく単純な操作で済む様フォームを作成し、いくつかのコマンドボタンにイベントを設定しているのですが、複数店舗があり少しずつ仕様が違う為、どこまで自動化するか、どこで分岐させるか判断に悩むところです。

今度こそ完成は目前です。
色々とご教示いただきまして誠にありがとうございます。

寒暖の差があって体調を崩しやすい季節ですが、風邪など気をつけてくださいね。

お礼日時:2014/10/21 15:10

御無沙汰しました。



もっと早く気付けばよかったのですが
受け取ったテキストファイルのデータを疑うことはしませんでした。
提供先でのテキストファイル生成の行程でミスの可能性があるのでは
この工程の中に人手の作業が入っていれば…

そこで、受取ったテキストファイルは取り敢えずACCESSのテーブルに全て
インポートして、これを正規のテーブルに移行したいと思います。
元のテーブル名の末尾に【PRE】を付加した次のテーブルを作成して下さい。
元のテーブルをコピペして作成しますので、フィールド名とデータ型が
同じものが出来ます。
・出来たテーブルから主キーを外します。
・フィールドプロパティーのインデックス設定されているものはインデックスなし
・ルックアップは以前外すようにと言いましたが誤りでした。変更しなくてよいです。
・もし【商品マスタ中継】のように中継テーブルがあれば【商品マスタPRE】と改名
・これらのテーブルにリレーションシップはなしです。
-----------------------------------
新規に用意するテーブル
【商品マスタPRE】、【カテゴリPRE】、【カテゴリ関連PRE】、【メーカーPRE】、
【ブランドPRE】、【成分PRE】、【成分関連PRE】、【説明PRE】、【HOGEPRE】
---------------------------------

尚、
・商品マスタテーブルには【匿名10】~【匿名37】の28フィールドを追加しています。
・カテゴリー関連テーブルに大分類コード、中分類コード、小分類コードの
 3つのフィールドを追加しました。
「Access schema.ini使用方」の回答画像4

この回答への補足

こんばんは。
ご無沙汰しております。
突然ですが、やりたい事がほぼできました!

質問当初はAccessでさえ理解できていない為VBAの使用を避けておりましたが結果、皆様に書いて頂いたコードを自分でも調べて触るうちに、少し意味が分かるようになった為、改変してSQLを作ってみたらいいところまでできました!

「Accessで縦に情報が展開されてるテーブルの処理」の質問で30246kikuさんがズバリなVBAを書いてくださった後すぐにでも試してみたら、もっと早く解決していたのかもしれないのですが…

コードはこのようになりました。
フィールドの結合をするためのクエリが3つ。
それを含むクエリのフィールドと複数のテーブルからフィールドを選択クエリで取り出し、装飾したものになります。

まだ完全に理解していないのと、どうやってもエラーになってしまったりする為に複数のクエリとなっております。

※Samp1は30246kikuさんが書いてくださったBVAでCSVに出力したものをAccessへインポートしたものです。

1.項目と項目説明の結合(Qsamp1)
SELECT Samp1.商品コード, ("<p class=""a"">"+[項目1]+"</p>") & ("<p class=""b"">"+[説明1]+"</p>") AS 適用1,… ("<p class=""a"">"+[項目122]+"</p>") & ("<p class=""b"">"+[説明122]+"</p>") AS 適用122
FROM Samp1;

2.項目の内容を全て結合(Q補足)
SELECT Qsamp1.商品コード, [適用1] & [適用2] … & [適用95] AS 補足
FROM Qsamp1;

3.商品マスタテーブルのフィールドの結合(Q説明)
SELECT 商品マスタ.商品コード, ("<p class=""a"">"+"内容量"+"</p>") & ("<p class=""b"">"+[商品マスタ.内容量]+"</p>") & ("<p class=""a"">"+"商品サイズ"+"</p>") & ("<p class=""b"">"+[商品マスタ.サイズ]+"</p>") & ("<p class=""a"">"+[商品マスタ.メーカー]+"</p>") & ("<p class=""b"">"+[メーカー.メーカー名]+"</p>") & ("<p class=""a"">"+"ブランド名"+"</p>") & ("<p class=""b"">"+[ブランド.ブランド名]+"</p>") AS 説明
FROM ブランド RIGHT JOIN (メーカー RIGHT JOIN 商品マスタ ON メーカー.メーカーコード = 商品マスタ.メーカーコード) ON ブランド.ブランドコード = 商品マスタ.ブランドコード;

4.(上記1~3を合わせたクエリ)
SELECT 商品マスタ.商品コード, [Q説明].説明 & ("<p class=""a"">"+[成分.成分名]+"とは"+"</p>") & ("<p class=""b"">"+[成分.成分説明]+"</p>") & [Q補足].補足 AS 商品説明文, 商品マスタ.販売価格, 商品マスタ.廃盤
FROM (((ブランド RIGHT JOIN (メーカー RIGHT JOIN 商品マスタ ON メーカー.メーカーコード=商品マスタ.メーカーコード) ON ブランド.ブランドコード=商品マスタ.ブランドコード) LEFT JOIN 成分 ON 商品マスタ.成分コード=成分.成分コード) LEFT JOIN [Q補足] ON 商品マスタ.商品コード=[Q補足].商品コード) LEFT JOIN [Q説明] ON 商品マスタ.商品コード=[Q説明].商品コード;

4.のクエリを、マクロを使って使用範囲のみ抽出しCSVに出力して、完成です。

マクロは、抽出範囲のテキストファイルをインポートし、4.のクエリを開くものです。
抽出条件に以下の式を入れる事によって抽出したい範囲だけのCSVを出力できるようになりました。
In (SELECT * FROM code)

…ただし、2.で本来ならば[適用122]まで続くはずでしたが[適用95]までとなっております。
それ以上ですとエラーとなってしまう為です。
これを[適用122]までにできれば、本当の本当に完成となります。


今まで長い間お付き合いいただき本当にありがとうございました。

それでもまだ使い勝手が良くない為、常に改変していくつもりですので質問ペースを落としつつ、今後もchayamatiさんの回答を楽しみにしております^^

補足日時:2014/10/10 20:46
    • good
    • 0

> 1.3. ⇒【その他の項目を初期状態にする】


その他の…とは、商品番号の他の全ての項目の事でしょうか?
初期状態にするとは、データ型の事でしょうか?
よく分からなかった為、商品番号を主キーにした以外はそのままの状態にしました。
------------------------------------------------------
主キーにすると重複が許されません、そのためこれを回避するために外します。
インポートできたテキストファイルは変更する必要は無いのですが、
インポートできていないテーブルについては、それぞれ主キーの無い
複製(例えば 商品M中継)を作ってこれにインポートしてはどうかと…
  初期状態:すみません 表現が悪かったです。
  テーブル設計の時フィールドのプロパティは数値、テキストだけにして
  その他のプロパティは規定値のまま

> 1.4.テーブルルックアップを外す
すみません、ルックアップしている項目がどのテーブルにも存在していませんでした。
いつぞやルックアップの設定方法を教えて頂いた事は覚えているのですが…
覚えていらっしゃったら、どの項目が何をルックアップしていたのか教えて頂けますでしょうか?

こんな状態ですが、VBAを差し替え後、商品マスタをインポートしてみたところ「パラメータの入力」と小窓が出現しメーカーコードを求めてきました。
-----------------------------------------------------------------
このメーカコードはルックアップ設定しています。テキストボックスに変更して下さい。

その他 商品マスタの ブランドコード、重要成分コード、大分類コード 等もルックアップの対象です。

また1:∞のリレーションの∞側の項目は1側のテーブルをルックアップの対象です。
【説明】【HOGE】の商品番号も例外ではありません。

この回答への補足

おはようございます。

お返事が遅くなりまして申し訳ございません。

エラーの原因を調べ、修正しました。
変更内容は以下です。

メーカコード → メーカーコード
廃番フラグ → 廃盤フラグ

商品マスタテーブルを初期状態に戻し、ルックアップを外した状態で、再度インポートしてみたところ
「コンパイルエラー 構文エラー」となり、以下が黄色く反転されました。

Private Sub 商品マスタインポートRTN()

そして以下は青く反転されました。

DoCmd.RunSQL ("Insert Into 商品マスタ(商品番号,商品名,メーカーコード, "

調べてもRTN()が何を意味しているのか分からなかった為、手詰まりとなりました…

予想では、そのVBAのすぐ上にある「Private Sub 商品マスタインポート_Click()~End Sub」までの式を利用してという意味なのでしょうか。

う~ん、そうだったとしても、エラーになった理由が分からないです…

補足日時:2014/10/06 12:05
    • good
    • 0

#1です



現在 Yahooメールの障害のため、補足等あった通知を受け取る事が出来ていないのですが・・・


> テーブルに追加する時には、
>
> INSERT INTO 追加先テーブル名
> FROM [商品.txt] In 'フォルダパス'[Text;FMT=Delimited];

この記述は嘘ですね。その前の記述につられました

INSERT INTO 追加先テーブル名
SELECT * FROM [商品.txt] In 'フォルダパス'[Text;FMT=Delimited];

でしょうか・・・

> ダブルクォーテーション以降がインポートされなかった為

Schema.ini 内の指定に、テキストを " で区切るか・・・という指定があったと思うので
色々いじってみてください。

TextDelimeter=none とか TextDelimeter=" とか?


でも、リンクテーブルが出来たのであれば、もし、遅くて使えないとかになったら
リンクテーブルから、正式なテーブルへ INSERT INTO しても良いかも

後は、mdb 1つで何でもやろうとはしないで、
この mdb は txt を取り込んで正式テーブルに展開するだけ・・・ という作り方でも良いのかも??
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

> この記述は嘘ですね。その前の記述につられました
恐れ多いのですが、自分なりに追加クエリのSQLを探し手を加えたのですが、SELECTの後に何を入れてもエラーだった為諦めました。
が…式(?)を見て納得です。
FROMで引用元のファイルを指定し、「*」でその全てのフィールドという事なのですね!
ありがとうございます。


> TextDelimeter=none とか TextDelimeter=" とか?
あまりにも検索に引っかからない為(私の検索の仕方が悪いのかも)、理由は置いといて提示頂いた「none」と「"」で試したところ「none」でうまく動作しました。
1日中探しまわって、このページの最後の行でやっと謎が解けました。
http://makoto-watanabe.main.jp/access/dahowchang …


> この mdb は txt を取り込んで正式テーブルに展開するだけ・・・ という作り方でも良いのかも??
なるほど~!
複数のmdbで管理するなんて考えもつきませんでした。
例えば上の例で言うと、正式テーブルに展開したものを、別のmdbからクエリで操作する事によって、データが軽くなる、或いはデータが扱いやすい場合があるという事でしょうか?

お礼日時:2014/10/04 19:08

前のご質問は完結したと思って良いのでしょうか。


リンクテーブルにした際の結果報告を待っていたのですが・・・

というのは置いといて、

良く知りませんが、schema.ini 内の
・記述の仕方
・DoCmd.TransferText の指定方法
は、あっているのでしょうか?

・schema.ini 内のテキスト型の記述は、 Char Width 255 とかの様な気がするし
・DoCmd.TransferText では、ヘッダ(見出し)あり指定の様だけど、
 schema.ini ではヘッダはない・・・となっているようだし・・・
 どちらが優先されるんでしょう

さて、私は我流なので、ここからは嘘が多くなるかも・・・
schema.ini を使う時には、DoCmd.TransferText は使いません。
(使い方があるのかもしれませんが、私は???)

テーブル「★★」にインポートするとした場合、基本となる「★★」を作っておきます。
1度、インポートしてみるでも良いですし、
読み込むフィールド順で手作業で作っても良いです。

そのテーブルに対して以下クエリを実行すると、基本となる schema.ini が出来上がります。

SELECT * INTO [ファイル名] IN 'フォルダパス'[Text;FMT=Delimited;HDR=Yes]
FROM ★★;

ファイル名:仮のテキストファイル名
フォルダパス:そのテキストファイルが出来上がるフォルダのパス

ファイル名を「a.txt」、フォルダが「D:\Hoge」なら

SELECT * INTO [a.txt] IN 'D:\Hoge'[Text;FMT=Delimited;HDR=Yes]
FROM ★★;

これで、「D:\Hoge\a.txt」ファイルにテーブル内容が吐き出されます。
(既にそのファイルが存在した時にはエラーになりますけど・・・)
この時、D:\Hoge\schema.ini 内は

[a.txt]
ColNameHeader=True
CharacterSet=932
Format=CSVDelimited
Col1=an Integer
Col2=区分 Char Width 5
Col3=コード LongChar Attribute 32

の様な感じで・・・
それを本物のファイル用に修正していきます。

[商品.txt]
ColNameHeader=False
CharacterSet=932
Format=TabDelimited
Col1=an Long
Col2=区分 Char Width 5
Col3=コード Memo

ヘッダ(見出し)はありませんよ
タブ区切りですよ・・・
とかに変更して・・・・

取り込む時のクエリ記述では、
テーブルを作る時には

SELECT * INTO 作成テーブル名
FROM [商品.txt] In 'フォルダパス'[Text;FMT=Delimited];

テーブルに追加する時には、

INSERT INTO 追加先テーブル名
FROM [商品.txt] In 'フォルダパス'[Text;FMT=Delimited];

とか・・・(未検証)


※ 余談

テキストファイルをリンクテーブルとして設定すると、定義情報
(インポート/エクスポートでも同じなのかは?)が、システムファイルに作成されるようです。

SELECT * FROM MSysIMEXSpecs;

とか

SELECT * FROM MSysIMEXColumns;

で確認できると思います。あわせて、
リンクテーブルの TableDef 内、Connect の文字列を合わせたもので、
schema.ini を作成できるかと・・・
(逆・・・かも、schema.ini の内容を上記3つに分けて持たせたのかも・・・)
(それがあったから、DoCmd.TransferText が出来上がったのかも?)

※ テキストファイル内の区切り文字は、安易に変更すべきではないと思っています。
区切り文字に何を使うかは意図があったはずで、それを確認するのが最初かと・・・
個人的にはそう思います。

なお、テキストファイルをリンクテーブルにした際、
そのフィールドに定義した型と異なるデータ部分は
・テーブル内容を表示した時には #Num! の様な表示に・・・
(数値部分に数字以外の文字があったとか)
・Recordset としてアクセスした時には Null
で、判別できたような・・・

この回答への補足

回答ありがとうございます。

> リンクテーブルにした際の結果報告を待っていたのですが・・・
申し訳ございません。
休みを挟んですっかり忘れていたようです…

今更ですがリンクテーブルを試したところ、データに不備なくリンクが作成できました。
リンクにすると遅くなるとあったので心配していたのですが、一番大きなデータでもストレスなく開ける程度でした。

テキストデータが更新されることも考えられるので、リンクテーブルいいかもしれません!


> schema.ini を使う時には、DoCmd.TransferText は使いません。
直前の作業でDoCmd.TransferTextを使用していた為、使うものかと思い込んでおりました。
自分でもどんな命令なのか調べた程度ですが、なにより人様に書いて頂いたVBAなので指定方法に間違いはないと思います。

基本となる schema.iniをご教示して頂いたクエリで作成し、出来上がったschema.iniと先に自分で作成してみたschema.iniを比較してみたら記述の仕方が間違っていたようです。

出来たschema.iniを本物のファイル用に修正しご教示して頂いたクエリ2つ共試してみたところ、
テーブルに追加するクエリでは「INSERT INTO ステートメントの構文エラーです」となりました。
テーブルを作るクエリではほぼ成功しました。
ほぼというのは、あるフィールドの内容にダブルクォーテーションが含まれる為、ダブルクォーテーション以降がインポートされなかった為です。

何の設定が悪さしているのか調べてみます。


いつも余談などで為になるお話しなどしていただいて ありがとうございます。

知らない単語が登場するたびに検索、検証しているので返事が遅くなり、お詫び申し上げます。
ヒントを充分すぎる位与えて下さるのでどんどん楽しくなってきました♪

補足日時:2014/10/03 19:10
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A