Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


13600 / 13646 ツリー ←次へ | 前へ→

【4603】".txt"ファイルの必要な列だけを読み込みExcelに貼り付けられませんか... めぎゅ 03/3/28(金) 11:10 質問
【4617】Re:".txt"ファイルの必要な列だけを読... Jaka 03/3/28(金) 16:12 回答
【4622】Re:".txt"ファイルの必要な列だけを読... めぎゅ 03/3/28(金) 18:34 質問
【4624】Re:".txt"ファイルの必要な列だけを読... Hirofumi 03/3/29(土) 10:13 回答
【4636】さらに・・・もう一つ めぎゅ 03/3/31(月) 13:30 質問
【4643】Re:さらに・・・もう一つ Hirofumi 03/3/31(月) 19:24 回答
【4664】ありがとうございます。さらにもう一点・・・ めぎゅ 03/4/1(火) 16:31 質問
【4667】Re:ありがとうございます。さらにもう一点・・・ Hirofumi 03/4/1(火) 20:27 回答
【4631】Re:".txt"ファイルの必要な列だけを... ポンタ 03/3/30(日) 18:16 回答
【4632】Re:".txt"ファイルの必要な列だけを読... Jaka 03/3/31(月) 10:28 回答
【4639】Re:".txt"ファイルの必要な列だけを読... めぎゅ 03/3/31(月) 14:05 質問
【4640】ごめんなさい。 Jaka 03/3/31(月) 16:27 回答
【4641】ちょっとびっくり。 Jaka 03/3/31(月) 16:35 発言
【4682】ありがとうございました! めぎゅ 03/4/2(水) 17:40 お礼

【4603】".txt"ファイルの必要な列だけを読...
質問  めぎゅ E-MAIL  - 03/3/28(金) 11:10 -

引用なし
パスワード
   こんにちは。
現在、Excelからテキストファイルを開いて処理をしています。
データ量が多いため(テキストで3M)開く時間も長いです!
むしろエクスプローラーからExcelに手動でドラッグしたほうが早いのです。

".txt"内の必要な列を読み込み、Excelのブックに列ごと出力することはできませんでしょうか?
または、データ量の多いテキストファイルをExcelにて開く処理を早くすることは可能でしょうか?

【4617】Re:".txt"ファイルの必要な列だけを...
回答  Jaka  - 03/3/28(金) 16:12 -

引用なし
パスワード
   こんにちは。
1例です。
データ行数が何万行もあると、配列使っているほうが余計に遅くなると思います。
(書き込みに時間がかかりフリーズしたみたいにOr本当にフリーズしちゃいます。)
最近のPC性能ぐらいであれば、1つづつ書き込んで行ってもさほど時間は掛からないと思います。

実際、手動と比べて速いのかどうか解りませんが....。

配列使用
Sub hui()
  Dim Tbl() As Variant
  FileOpen = Application.GetOpenFilename("Excelファイル (*.txt), *.txt")
  If FileOpen <> False Then
    Open FileOpen For Input As #1
  Else
    End
  End If
  Do Until EOF(1)
    Line Input #1, Rdata
    DataCnt = DataCnt + 1
  Loop
  Close #1
  列数 = 15   '←ここのフィールド数を変えてください。
         'マクロでカンマ数を数えても良いんだけど、
         '実際のデータを見ていないので...。
  ReDim Preserve Tbl(1 To DataCnt, 1 To 1)
  Open FileOpen For Input As #1
  Do Until EOF(1)
    For I = 1 To 列数
      Input #1, Rdata
      If I = 6 Then   '6列目
       CNT = CNT + 1
       Tbl(CNT, 1) = Rdata
      End If
    Next
  Loop
  Close #1
  Range("A1:A" & DataCnt).Value = Tbl
  Erase Tbl
End Sub

ノーマル
Sub hui2()
  Dim Tbl() As Variant
  FileOpen = Application.GetOpenFilename("Excelファイル (*.csv;*.txt), *.csv;*.txt")
  If FileOpen <> False Then
    Open FileOpen For Input As #1
  Else
    End
  End If
  Do Until EOF(1)
    Line Input #1, Rdata
    DataCnt = DataCnt + 1
  Loop
  Close #1
  列数 = 15   '←ここのフィールド数を変えてください。
         'マクロでカンマ数を数えても良いんだけど、
         '実際のデータを見ていないので...。
  ReDim Preserve Tbl(1 To DataCnt, 1 To 1)
  Open FileOpen For Input As #1
  Do Until EOF(1)
    For I = 1 To 列数
      Input #1, Rdata
      If I = 6 Then   '6列目
       CNT = CNT + 1
       Range("A" & CNT).Value = Rdata
      End If
    Next
  Loop
  Close #1
End Sub

【4622】Re:".txt"ファイルの必要な列だけを...
質問  めぎゅ E-MAIL  - 03/3/28(金) 18:34 -

引用なし
パスワード
   早速のお返事ありがとうございます(^^)

私の知識不足なんですが・・・、Jakaさんから頂いた処理をお聞きしたいのですが、
Rdataに必要である列の値が入力され、配列に格納されると認識していいのでしょうか?
実際、必要な列数を入力したところ、必要なデータがRdataに格納されませんでした。
例ですが、タブ区切りのテキストにて、1READに80項目データがあったとして、
必要な項目(列)15,16,42と不規則な部分の項目(列)が必要であるとしたら

列数 = 80

    For I = 1 To 列数
      Input #1, Rdata
      If I = 15 or 16 or 42 Then   '15,16,42列目
       CNT = CNT + 1
       Tbl(CNT, 1) = Rdata
       Tbl2(CNT, 1) = Rdata
       Tbl3(CNT, 1) = Rdata

      End If
    Next

と感じでいいんでしょうか?
どうもRdataに入る値が違うような・・・
すいません!知識不足で!もしかしたらタブ区切りとかですとダメだったりしますか???
お願いします!

>配列使用
>Sub hui()
>  Dim Tbl() As Variant
>  FileOpen = Application.GetOpenFilename("Excelファイル (*.txt), *.txt")
>  If FileOpen <> False Then
>    Open FileOpen For Input As #1
>  Else
>    End
>  End If
>  Do Until EOF(1)
>    Line Input #1, Rdata
>    DataCnt = DataCnt + 1
>  Loop
>  Close #1
>  列数 = 15   '←ここのフィールド数を変えてください。
>         'マクロでカンマ数を数えても良いんだけど、
>         '実際のデータを見ていないので...。
>  ReDim Preserve Tbl(1 To DataCnt, 1 To 1)
>  Open FileOpen For Input As #1
>  Do Until EOF(1)
>    For I = 1 To 列数
>      Input #1, Rdata
>      If I = 6 Then   '6列目
>       CNT = CNT + 1
>       Tbl(CNT, 1) = Rdata
>      End If
>    Next
>  Loop
>  Close #1
>  Range("A1:A" & DataCnt).Value = Tbl
>  Erase Tbl
>End Sub

【4624】Re:".txt"ファイルの必要な列だけを...
回答  Hirofumi E-MAIL  - 03/3/29(土) 10:13 -

引用なし
パスワード
   横から失礼します
列を抜き出して書き込むならこんなやり方も有るよ
Split関数を仕様しているので、Excel2000以降じゃないと使え無いけど
ただし、Excel97でもSplit関数の代替を作れば遅く成るけど可能
Split関数の代替は必要なら考えて見ます
>不規則な部分の項目(列)
と有りますが、これも条件が解れば組み込み可能かもしれません

Public Sub TextRead()

  Dim i As Long
  Dim vntFileName As Variant
  Dim dfn As Integer
  Dim strBuff As String
  Dim vntColm As Variant
  Dim vntData As Variant
  Dim vntWrite As Variant
  Dim lngWriteRow As Long
  Const cstrFilter As String _
      = "テキスト (*.txt),*.txt,CSV (*.csv),*.csv,全て (*.*),*.*"
  Const cstrTitle As String = "読み込みファイルの選択"
  
  '読み込む列の指定
  vntColm = Array(15, 16, 42)
  vntColm = Array(2, 4, 6)
  '書き込み用配列の確保
  ReDim vntWrite(UBound(vntColm))
  
  '読み込むファイル名を指定
  vntFileName _
    = Application.GetOpenFilename(cstrFilter, 1, cstrTitle)
  If vntFileName = False Then
    Exit Sub
  End If
  'ファイルをInputモードで開く
  dfn = FreeFile
  Open CStr(vntFileName) For Input As dfn
  
  '書き込み行の初期値を設定
  lngWriteRow = 1
  'ファイルの終わりまで繰り返し
  Do Until EOF(dfn)
    '1行(1レコード)読み込み
    Line Input #dfn, strBuff
    '区切文字(Tab)で文字列を区切配列に格納(列数と添え字が等しい)
    vntData = Split(strBuff, vbTab, , vbBinaryCompare)
    '読み込み列を書き込み用配列に代入
    For i = 0 To UBound(vntColm)
      vntWrite(i) = vntData(vntColm(i))
    Next i
    '書き込み位置にデータを書き込み
    With Cells(lngWriteRow, 1)
      Range(.Offset(, 0), .Offset(, _
              UBound(vntColm))).Value = vntWrite
    End With
    '書き込み行を更新
    lngWriteRow = lngWriteRow + 1
  Loop
  
  'ファイルを閉じる
  Close #dfn
  
End Sub

【4631】Re:".txt"ファイルの必要な列だけを...
回答  ポンタ  - 03/3/30(日) 18:16 -

引用なし
パスワード
   横から失礼します。

TextStreamObjectと正規表現を使っています。
標準モジュールに貼り付けてお試しください。

Sub test()
  Dim FileName As String
  Dim objText As Object
  Dim objRe As Object
  Dim objMatches As Object
  FileName = Application.GetOpenFilename("Excelファイル (*.txt), *.txt")
  If FileName = "False" Then Exit Sub
  Application.ScreenUpdating = False
  Set objText = CreateObject("Scripting.FileSystemObject").OpenTextFile(FileName, 1)
  Set objRe = CreateObject("VBScript.Regexp")
  objRe.Pattern = "[^\t]+\t"
  objRe.Global = True
  Do
    Set objMatches = objRe.Execute(objText.ReadLine)
    Range(Cells(objText.Line - 1, 1), Cells(objText.Line - 1, 3)) = _
      Array(objMatches.Item(15).Value, _
        objMatches.Item(16).Value, _
        objMatches.Item(42).Value)
  Loop Until objText.AtEndOfStream
  Application.ScreenUpdating = True
End Sub

【4632】Re:".txt"ファイルの必要な列だけを...
回答  Jaka  - 03/3/31(月) 10:28 -

引用なし
パスワード
   おはようございます。
配列を3つ作って、3列とりたいと言う事でしたら、こんな感じ...。
ただ、1つの配列の大きさがどれだけの物かわからないけど、大きそうな物を3つも作って大丈夫なのかまでは解りません。
それと、書き終わった後、全部の配列の後始末は忘れない様にした方が良いです。
残しておくと、後々で処理が遅くなるみたいです。

For I = 1 To 列数
  Input #1, Rdata
  If I = 15 Then
    CNT15 = CNT15 + 1
    Tbl(CNT15, 1) = Rdata
  ElseIf I = 16 Then
    CNT16 = CNT16 + 1
    Tbl2(CNT16, 1) = Rdata
  ElseIf I = 42 Then
    CNT42 = CNT42 + 1
    Tbl3(CNT42, 1) = Rdata
  End If
Next


それと、ノーマルの方余計な物が残ったままでした。

Sub hui2()
  Dim 列数 As Integer, I As Long, CNT15 As Long, CNT16 As Long, CNT42 As Long
  FileOpen = Application.GetOpenFilename("Excelファイル (*.csv;*.txt), *.csv;*.txt")
  If FileOpen = False Then
    End
  End If
  列数 = 80   '←ここのフィールド数を変えてください。
  Open FileOpen For Input As #1
  Do Until EOF(1)
    For I = 1 To 列数
      Input #1, Rdata
      If I = 1 Then
       CNT15 = CNT15 + 1
       Range("A" & CNT15).Value = Rdata = Rdata
      ElseIf I = 16 Then
       CNT16 = CNT16 + 1
       Range("B" & CNT16).Value = Rdata = Rdata
      ElseIf I = 42 Then
       CNT42 = CNT42 + 1
       Range("C" & CNT42).Value = Rdata = Rdata
      End If
    Next
  Loop
  Close #1
End Sub

【4636】さらに・・・もう一つ
質問  めぎゅ E-MAIL  - 03/3/31(月) 13:30 -

引用なし
パスワード
   ありがとうございます!

無事、欲しい列が取得できました!
所要時間は19秒ほどでした。かなりの高速化です。
ところで、配列に格納した後、貼り付け先の設定ですが、
ブックとシートも選択したいのですが・・・どこで設定するのでしょうか??
↓ここの貼り付け先は、マクロを動かした自分のブックになってしまうので
 決められたファイルに設定したいのですが・・・
 教えてください!

>    '書き込み位置にデータを書き込み
>    With Cells(lngWriteRow, 1)
>      Range(.Offset(, 0), .Offset(, _
>              UBound(vntColm))).Value = vntWrite
>    End With
>    '書き込み行を更新

【4639】Re:".txt"ファイルの必要な列だけを...
質問  めぎゅ E-MAIL  - 03/3/31(月) 14:05 -

引用なし
パスワード
   こんにちは。
お返事ありがとうございます。

再度お聞きしてしまい申し訳ないのですが、
読み込むテキストデータは、タブ区切りです。
Rdataに入るデータが、タブすべて含めた1Lineのデータが入ってしまうのですが・・・。
例えば、
列数は、全部で4列
1  aaa  bbb  ccc
12  ddd  fff  gggg
13  hhhhh  iiiiii  jjjjj 

といったタブ区切りのデータを読み込みます。
Excelのには、
A列 |B列  |C列
1  |aaa  |ccc
12  |ddd  |gggg
13  |hhhhh |jjjjj

といった形でデータを貼り付けたいのですが・・・。
すいません、どうもうまくいかないのでもう一度ご助言いただけないでしょうか?

列数= 87
>For I = 1 To 列数
>  Input #1, Rdata
>  If I = 0 Then
>    CNT = CNT + 1
>    Tbl(CNT, 1) = Rdata
>  ElseIf I = 2 Then
>    CNT2 = CNT2 + 1
>    Tbl2(CNT2, 2) = Rdata
>  ElseIf I = 3 Then
>    CNT3 = CNT3 + 1
>    Tbl3(CNT3, 3) = Rdata
>  End If
>Next

【4640】ごめんなさい。
回答  Jaka  - 03/3/31(月) 16:27 -

引用なし
パスワード
   >再度お聞きしてしまい申し訳ないのですが、
>読み込むテキストデータは、タブ区切りです。
>Rdataに入るデータが、タブすべて含めた1Lineのデータが入ってしまうのですが・・・。

すみませんでした。
私も前にテストした時に、inputでタブ区切りのテキストがまともに読めませんでしたが、今回テストしてみたら1フィールドずつ読めてしまったのでそのまま載せました。
で、色々テストしてみたらおかしなことが解りました。
エクセルでタブ区切りのテキストを作ったとしてメモ帳などで開いた場合、データが数字だけの場合は、まともな格好でタブが入っているんですが、データに文字が混ざっている場合、そのタブは文字列の中のタブとして扱っちゃうみたいです。
う〜ん、うまく言えませんが...。
こんな感じに、しかも決まりが解らない...。
エクセルから開くとちゃんとタブ区切りで振り分けられるのに....。

1101    060     0600000    ホッカイドウ    サッポロシチュウオウク    イカニケイサイガナイバアイ    北海道    札幌市中央区

データが数字だけの時は、ちゃんと作れて1個づつしっかり読み込めたので、申し訳ありませんでした。
文字が入っているタブ区切りのテキストは、Input読込が出来ないと言う事で....。
申し訳ないことになってしまいました。
Line Inputで、読み込んでタブで振り分けて行く方法のほうが無難みたいです。
ただ、前にVBTabでの判断がうまく行かなかった事もありまして...。

言い訳ばかりで、ごめんなさい。

【4641】ちょっとびっくり。
発言  Jaka  - 03/3/31(月) 16:35 -

引用なし
パスワード
   >1101    060     0600000    ホッカイドウ    サッポロシチュウオウク    イカニケイサイガナイバアイ    北海道    札幌市中央区

上のここではしっかりタブが入っていますが、ワード、メモ帳で開いた時はこんなんでした。(見た目ですが)

1101  060   0600000 ホッカイドウ サッポロシチュウオウク  イカニケイサイガナイバアイ 北海道   札幌市中央区

【4643】Re:さらに・・・もう一つ
回答  Hirofumi E-MAIL  - 03/3/31(月) 19:24 -

引用なし
パスワード
   以下のようにコードを追加して下さい
ただし、Book1.xlsは、既に開かれている物とします

  '書き込み行の初期値を設定
  lngWriteRow = 1
  '以下の行を追加して下さい
  '例えば、Book1.xlsのSheet1に書き込みます
  With Workbooks("Book1.xls").Worksheets("Sheet1")
  'ファイルの終わりまで繰り返し
  Do Until EOF(dfn)
    ・
    ・
    ・
    '書き込み位置にデータを書き込み
    'Cells(lngWriteRow, 1)の前にピリオドを追加
    With .Cells(lngWriteRow, 1)
      Range(.Offset(, 0), .Offset(, _
              UBound(vntColm))).Value = vntWrite
    ・
    ・
    ・
  Loop
  'Loopの後にEnd Withを追加
  End With

もし、Book1.xlsもマクロで開く場合は
With Workbooks("Book1.xls").Worksheets("Sheet1")
より前に

  'Book1.xlsをOpen
  Workbooks.Open (ThisWorkbook.Path & "\" & "Book1.xls")

を要れて下さい

尚、コードの中に
  vntColm = Array(2, 4, 6)
が入っていますが、これは、私のミスで、Test用のコードを消し忘れていました

【4664】ありがとうございます。さらにもう一点・・・
質問  めぎゅ E-MAIL  - 03/4/1(火) 16:31 -

引用なし
パスワード
   無事、作成することができました。
本当にありがとうございます。
処理速度も予想以上に速いものです!

またまた一点、疑問なのです。
1.マクロの所在(実行場所):Book1.xls:Sheet1
2.結果の貼り付け先   :Book2.xlsのSheet1
3.読み込みたいテキストデータ:"test.txt"

この状態で実行すると、結果の貼り付けが、マクロを実行した、Book2.xlsのSheet1に書き込まれてしまいます。

標準モジュールにマクロを記述することにより、問題は解消されましたが、
原因はなにになるのでしょうか?

  Workbooks.Open Filename:="C\Book2.xls"
  
  '↓ここはひつようないかも・・・??
  Workbooks("Book2.xls").Activate
  Worksheets("Sheet1").Activate

  With Workbooks("Book2").Worksheets("Sheet1")
    Do Until EOF(dfn)
      '1行(1レコード)読み込み
      Line Input #dfn, strBuff
      '区切文字(Tab)で文字列を区切配列に格納(列数と添え字が等しい)
      vntData = Split(strBuff, vbTab, , vbBinaryCompare)
      '読み込み列を書き込み用配列に代入
      For i = 0 To UBound(vntColm)
        vntWrite(i) = vntData(vntColm(i))
      Next i
      '書き込み位置にデータを書き込み
      With Cells(lngWriteRow, 1)
        Range(.Offset(, 0), .Offset(, _
                UBound(vntColm))).Value = vntWrite
      End With
      '書き込み行を更新
      lngWriteRow = lngWriteRow + 1
    Loop
  End With

よろしくおねがいします。

【4667】Re:ありがとうございます。さらにもう一点...
回答  Hirofumi E-MAIL  - 03/4/1(火) 20:27 -

引用なし
パスワード
   >標準モジュールにマクロを記述することにより、問題は解消されましたが、
>原因はなにになるのでしょうか?

当然、標準モジュールに記述している物と思っていましたが?
どこに記述していたのでしょうか?

>      '書き込み位置にデータを書き込み
>      With Cells(lngWriteRow, 1)

前にも書いた通り、With Cells(lngWriteRow, 1)の
Cells(lngWriteRow, 1)の前にピリオドが有りません

      With .Cells(lngWriteRow, 1)

に、しないと前のWithに続きません
因って、標準モジュールならActiveになっているシートに書き込まれますし
シートモジュールに書いているなら、書いているシートが対象となると思います

With .Cells(lngWriteRow, 1)の意味は、

With Workbooks("Book2").Worksheets("Sheet1").Cells(lngWriteRow, 1)
と同じ意味になるのですが、ピリオドが無いので、上記の様に成って仕舞います
ですので、

 '↓ここはひつようないかも・・・??
  Workbooks("Book2.xls").Activate
  Worksheets("Sheet1").Activate

を書かなければ成らなくなっていると思います
ピリオドが有れば、多分必要がないと思います

【4682】ありがとうございました!
お礼  めぎゅ E-MAIL  - 03/4/2(水) 17:40 -

引用なし
パスワード
   皆さん、ありがとうございました。
ちゃんと起動しまして、無事作成完了しました(^^)/
本当にありがとうございます!

13600 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free