Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(Windows 10 Pro : Excel 2016)
2つのテキストデータを挿入したい
投稿日時: 18/10/11 06:09:32
投稿者: nktdai1755

readtxt1だけのマクロを実行するとA列に"C:\tmp\data1.txt"が挿入されます。しかし、 readtxt2のマクロを
追記すると、ファイルは既に開かれています。とエラー。どうすれば、2つのデータをA列とB列に挿入する事ができるのでしょうか。
 
Sub readtxt1()
    Dim buf As String
    Dim n As Long
    Open "C:\tmp\data1.txt" For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            n = n + 1
            Cells(n, 1) = buf
        Loop
    Close #1
End Sub
 
Sub readtxt2()
    Dim buf As String
    Dim n As Long
    Open "C:\tmp\data2.txt" For Input As #2
        Do Until EOF(1)
            Line Input #2, buf
            n = n + 1
            Cells(n, 2) = buf
        Loop
    Close #2
End Sub
-------------------------------
C:\tmp\data1.txt
aaa
bbb
ccc
 
C:\tmp\data2.txt
ddd
eee
fff
-----------------------------------

回答
投稿日時: 18/10/11 07:36:35
投稿者: simple

Do Until EOF(1) の 1 はファイル番号です。

回答
投稿日時: 18/10/11 10:21:05
投稿者: なと

補足ですが、ファイル番号は定数で指定すると衝突させるミスが起こりやすく、今回のEOFの1のように修正で見落としやすいので、FreeFileで最初に空き番号を取得して、基本的には変数で指定するようにすると安全です。
 
例えば以下のコードのような感じで使います。
http://www.moug.net/tech/exvba/0060027.html

回答
投稿日時: 18/10/11 14:45:04
投稿者: WinArrow
投稿者のウェブサイトに移動

エラーメッセージの内容から考えると
readtxtの中の
> Do Until EOF(1)
で、別のエラーが出て処理をキャンセルし
eadtxt2を再実行したときのエラーではないかと思います。
 
通常、ファイル番号は、Closeすれば解放されます。
 
Openで#2が使われたが、処理を途中でキャンセルすると
#2が解放されづずに使用状態として認識されています。
ですから、再度#2を使ってOpenすると、
>ファイルは既に開かれています
というエラーが発生します。
 
残ったままの#2を開放するには、
Openステートメントの前に
Close #2
を実行すれば、よいです。
 
処理の途中で、ファイル番号を解放しなかった場合でも
ファイル番号を変数で使用した場合でも同じです。
が、ファイル番号として認識された番号が分からないので、解放できませんよね?
その場合は、
 
FileNO = FreeFile
をステップ実行で実行してみれば、取得した1つ前の番号が解放されていない番号です。
 
 
 

投稿日時: 18/10/13 02:00:58
投稿者: nktdai1755

コメントありがとうございます。
 
ファイル名を取得して、ファイルを開けるにはどうすればよいでしょうか。

Open "C:\tmp\data1.txt" For Input As #1
Open "C:\tmp\data2.txt" For Input As #2
Open "C:\tmp\data3.txt" For Input As #3
Open "C:\tmp\data4.txt" For Input As #4
 
dir関数を使えば宜しいのでしょうか。使い方がわかりません。
tmp配下には10個のファイルがあります。
 

回答
投稿日時: 18/10/13 07:01:20
投稿者: simple

皆さんからの指摘に対するなんらかの
コメントを追加いただくと、ご自分の確認にもなると思います。
 
それで、大事なことを忘れていましたが、
ファイルの数だけファイル番号を使わないといけないわけではありません。
 
ファイルを開いて、処理をして、閉じて、を繰り返すだけなら、
同じファイル番号を使って問題ありません。
つまり、複数のファイルを同時に開いたままにする必要がなければ、1つで十分です。
 
次に、フォルダ内のファイルを網羅的に取得したいということなら、
Dir関数が適当です。
これについては、こちらmougのサイトにある「即効テクニック」シリーズの中に
参考となる記事があります。
 
「フォルダ内のファイル一覧を取得する」
http://www.moug.net/tech/exvba/0060001.html
です。これを参考にトライしてみてください。
Dir("C:\tmp\*.txt")のような形式で指定します。

投稿日時: 18/10/16 13:38:22
投稿者: nktdai1755

ご回答ありがとうございます。
dir関数にて、取得したファイル一覧から、
どのような、ファイルオープンすればよろしいのでしょうか?

回答
投稿日時: 18/10/16 20:38:07
投稿者: simple

こんばんは。
即効テクニックの記事から、こんなものが書けますよね。

Sub Sample1()
    Dim i As Long, buf As String
    Const Path As String = "C:\temp\"
    buf = Dir(Path & "*.*")
    Do While buf <> ""
        i = i + 1
        'buf に "data1.txt"などが取得できるので、
        'ここで、@"C:\temp\data1.txt"というパス名を作成し(文字列の連結)、
        '      Aそのファイルを開く(A以下は既に完成しているのでは?)
        '        B読み込んだ文字列を指定した列(例えば i 列)に書き込む
        '        Cファイルを閉じる
        buf = Dir()
    Loop
    MsgBox "終了しました"
End Sub

このコメント部分を作ればいいんじゃないでしょうか。
すでに出来上がっているものを少し修正して組み合わせればよいのではないでしょうか。

投稿日時: 18/10/17 00:24:42
投稿者: nktdai1755

コメントありがとうございます。
「フォルダ内のファイル一覧を取得する」
http://www.moug.net/tech/exvba/0060001.html
を確認しました。
 
Sub Sample1()
 Dim i As Long
 Dim buf As String
 Const Path As String = "C:\temp\"
  buf = Dir(Path & "*.*")
Do While buf <> ""
  i = i + 1
  Cells(i, 1) = buf
  buf = Dir()
Loop
msgbox "全部で" & i & "個ファイルがありました"
End Sub
---------------------
上記をコードを入力すると、A列に "C:\temp\"配下のテキストファイルが記載されました。
data1.txt
data2.txt
data3.txt
A〜Cは作成可能ですが、どうやって@を作成するのでしょうか?
        'buf に "data1.txt"などが取得できるので、
        'ここで、@"C:\temp\data1.txt"というパス名を作成し(文字列の連結)、
        '    Aそのファイルを開く(A以下は既に完成しているのでは?)
        ' B読み込んだ文字列を指定した列(例えば i 列)に書き込む
        ' Cファイルを閉じる
        buf = Dir()

回答
投稿日時: 18/10/17 07:39:15
投稿者: simple

Open "C:\tmp\data1.txt" For Input As #1
を実行するためには、"C:\tmp\data1.txt"という文字列をOpenに与えればよいわけですが、
・"C:\tmp\" という文字列と、
・Dir関数で取得した"data1.txt"(これはbuf変数そのものです)という文字列を
& で連結すればよいと思います。
そのように書きましたが。

投稿日時: 18/10/19 01:37:32
投稿者: nktdai1755

>Open "C:\tmp\data1.txt" For Input As #1
>を実行するためには、"C:\tmp\data1.txt"という文字列をOpenに与えればよいわけですが、
>・"C:\tmp\" という文字列と、
>・Dir関数で取得した"data1.txt"(これはbuf変数そのものです)という文字列を
>& で連結すればよいと思います。
>そのように書きましたが。
Const Path As String = "C:\temp\"
Open Path & buf For Input As #1
ということでしょうか。
 
もう少し詳しく教えて頂けないでしょうか。

回答
投稿日時: 18/10/19 07:05:12
投稿者: simple

それでよいと思いますよ。
 
フォルダ名 と ファイル名 を連結させて フルパスにしているということです。
これ以上の説明は私には無理です。というかそういうことはご自分でなさることです。
それぞれの言葉の意味は、ExcelVBAの基礎的な本や、ネットで検索してみてください。

回答
投稿日時: 18/10/19 07:25:25
投稿者: simple

ひょっとすると、18/10/16 20:38:07 で書いたコードの意味が伝わっていないのかな。
それは、ファイル名を繰り返し取得するコードをもとに、
全体の流れを示したものです。
 
そのコメントにした部分に、
@"C:\temp\data1.txt"というパス名を作成し(文字列の連結)、
Aそのファイルを開く(A以下は既に完成しているのでは?)
B読み込んだ文字列を指定した列(例えば i 列)に書き込む
Cファイルを閉じる
というコードを埋め込んでひとつのコード(プログラム)にしたらよいのではないか、
と申し上げています。
 
@とAの部分は、あなたが18/10/19 01:37:32に作られた。
 
>A〜Cは作成可能ですが、どうやって@を作成するのでしょうか?
ということですから、あとはそれをつなげるだけではないですか?
もし、トライしてみて不明であれば、その旨コメントを返してください。
私は日中はアクセスできませんが、皆さんからコメントがいただけるはずです。

回答
投稿日時: 18/10/21 23:17:10
投稿者: simple

今までのものを基本的には貼り付けるだけだと思います。
 
ただし、複数のファイルがあるので、それぞれ別の列に書込むところが
新しいと言えば新しいですが、
Cells(n, 1).ValueをCells(n, i).Valueに変更するだけなので、
それほど難しい話ではないですよね。
 
どこに詰まっているのか私にはわかりませんでした。
何の返事もないですし。
一方で、余り長いことこの状態にあるのも適当ではないので、
コードを示します。参考にしてください。
 

Sub test()
    Const Path As String = "C:\temp\"
    Dim i As Long
    Dim n  As Long
    Dim buf As String
    Dim s As String

    buf = Dir(Path & "*.*")
    Do While buf <> ""
        i = i + 1
        Cells(1, i).Value = buf
        
        'ファイルを開いて列に読み込む
        n = 1
        Open Path & buf For Input As #1
        Do Until EOF(1)
            Line Input #1, s
            n = n + 1
            Cells(n, i).Value = s
        Loop
        Close #1

        buf = Dir()
    Loop
    ' MsgBox "全部で" & i & "個ファイルがありました"
End Sub

 
(注1)
ファイルを一行ごとに読み込む際の変数は元はbufで、
すでに使っている変数です。
bufそのままでも同じ結果が得られますが、
意味が違うものには別の変数を使ったほうが良いと思い、
bufを s に変更しています。
(注2)
ファイル名を一行目に書き込んでみました。
 
もともとの2つのプロシージャの意味がきちんと理解されていれば、
それを組み合わせることは難しくないのではないかと想像しておりました。
答えを待つよりも、自分でトライされることをお奨めします。

トピックに返信