[[20171014171937]] 『CSVから特定の列を抜き出す・・・2』(ちはる) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『CSVから特定の列を抜き出す・・・2』(ちはる)

度々申し訳ありません。
[[20171014125556]]で質問させていただいた者です。
回答を下さった方のアドバイスや自分でも調べてみて、コードを書いてみたのですが、目的の物が出来あがらず、厚かましくも、もう一度質問をさせていただきます。

まず、目的なのですが、

同じ階層に、約100程のフォルダの中にそれぞれ5つ前後のCSVが格納されています。
そのCSVファイルの中から、特定の列のデータだけを管理用エクセルへ書き出す作業をします。
CSVデータの形式は全て共通、100列(固定)100〜200行(これは各々まちまち)程で、抜き出したい列は5つです。(2、5,8,9,17行目。ただし今後変更や、増えるかもしれません)
管理票エクセルシートに転記する際、データを昇順したり、特定のものだけを抜き出し、チェックしながら管理票エクセルに貼り付けて行くといった作業が必要になる為、CSVファイルのままではなく、エクセルに変換したいのです。

また、元のCSVファイルは、別の作業で統合や加工を行う必要がある為、変更を加えずそのままにしておきたいのです。

やりたい手順としては、

?@任意のCSVファイルを選択する(実行ボタンを押したらファイルパスを入力する画面が出て、入力をしてエンターを押したら以下?A〜?Cのアクションが起こるようにしたい)

?AそのCSVファイルから特定の列だけ抜き出す(2、5,8,9,17)など

?B特定の列のみなったCSVファイルをエクセルに変換し、元となったCSVファイルと同じフォルダに格納する(元となったCSVファイルは何も変更をせずそのまま閉じる)

?C出来れば元となったCSVファイルを閉じたあと、特定列だけ抜き出しエクセルに変換されたファイルが自動で開くようにしたい

調べてみて、一番目的に近かったのが以下の物なのですが・・・

Sub sample()
Dim file As String
Dim c As Integer
file = Application.GetOpenFilename("CSVファイル,*.csv?")
If file = "False" Then Exit Sub
Workbooks.Open file
c = InputBox("何列")
Workbooks.Open file
Columns(c).Delete
ActiveWorkbook.Close True
End Sub

これですと、まず

?@削除したい列が1つしか選べない
?ACSVからエクセルに変換という目的が出来ない
?B元のCSVを加工するコードになってしまう

ので、目的に適いません。
元になるCSVを予めコピーしておき、コピーで作業を行うという手もあるのですが、作業量が多い為現実的ではありませんし、別の作業で元のCSVを選択する際、間違ってしまう可能性もあるので、エクセル形式で吐き出させたいのです。

図々しい質問、お願いであり、誠に恥ずかしい限りなのですが、どのようにすれば上記目的な叶うのか、ご教示いだけないでしょうか。
どうぞよろしくお願いいたします。

< 使用 Excel:Excel2013、使用 OS:Windows10 >


質問者です。コメントを書くルールを熟読しておらず、一部文字化けしてしまったようです。

?@
?A
?B

はそれぞれ、



と、丸つきで記述したものです。
お目汚しで申し訳ありませんでした。
(ちはる) 2017/10/14(土) 17:44


また、削除したい列を選ばせるのでなく、ファイルを指定すれば目的の列の物だけをエクセルファイルとして出てくるようにしたいのです。
(当分は必要になる列は変わらないですし、変わったあとはその部分だけ書き換えるので)

どうぞよろしくお願いいたします。
(ちはる) 2017/10/14(土) 17:49


 csvファイルの1行目は列項目(フィールド名)になっていますか?
 出来れば、一行目から数行抜粋して提示してもらえますか?

(seiya) 2017/10/14(土) 18:38


コメントをありがとうございます!
はい、フィールド名になっています。

カナ 局名 県 住所 通称 番地 連番 規模 通名 待ち 人数
ティーケ  TK  千葉  香住  かすみ 1-2   024  JJ  TD  87   90
オオム   OM  大阪  赤穂  アコ  8-9   345  NS  IK  09   78

というようなCSVファイルです。

コメントして下さり、ありがとうございます。
もしよろしけばお教えください。

(ちはる) 2017/10/14(土) 18:56


 区切り文字はカンマでは無いようですが、なんですか?
(seiya) 2017/10/14(土) 19:04

すみません、カンマで区切ってあるデータです。
わかりにくくてすみません。
(ちはる) 2017/10/14(土) 19:09

 エクセルから貼り付けたのですね、わかりました。

 ユーザーフォームを使用して、フィールド選択をします。
http://news.mynavi.jp/articles/2009/08/24/vba/
 分らなければ上記リンク等を参考にしてください。

 1) UserForm(UserForm1)を挿入して ListBox(ListBox1) と CommandButton(CommandButton1) を配置する。

 2) UserFormを右クリックして [コードの表示] 出てきた画面の右空白部分に下記コードを貼り付ける。
    もし既に何か書かれてあったら、一旦すべて削除してください。

 Option Explicit
 Private ListTxt As String

 Public Property Get Value() As String
     Value = ListTxt
 End Property 

 Private Sub UserForm_Initialize()
     Me.ListBox1.MultiSelect = 1
 End Sub

 Private Sub CommandButton1_Click()
     Dim i As Long
     ListTxt = ""
     With Me.ListBox1
         For i = 0 To .ListCount - 1
             If .Selected(i) Then ListTxt = ListTxt & "`, `" & .List(i)
         Next
     End With
     If Len(ListTxt) Then ListTxt = Mid$(ListTxt, 3) & "` "
     Me.Hide
 End Sub

 3) 標準モジュールに下記コードを貼り付ける

 Option Explicit

 Sub test()
     Dim fn As String, myDir As String, txt As String
     Dim cn As Object, rs As Object, i As Long
     fn = Application.GetOpenFilename("CSVファイル,*.csv")
     myDir = Left$(fn, InStrRev(fn, "\"))
     fn = Mid$(fn, InStrRev(fn, "\") + 1)
     If fn = "False" Then Exit Sub
     Set cn = CreateObject("ADODB.Connection")
     Set rs = CreateObject("ADODB.Recordset")
     With cn
         .Provider = "Microsoft.ACE.OLEDB.12.0"
         .Properties("Extended Properties") = "Text;HDR=Yes;IMEX=1;FMT=CSVDelimited"
         .Open CreateObject("WScript.Shell").SpecialFolders("desktop")
     End With
     rs.Open "select * from `" & fn & "`", cn, 3
     For i = 0 To rs.Fields.Count - 1
         UserForm1.ListBox1.AddItem rs.Fields(i).Name
     Next
     UserForm1.Show
     rs.Close
     txt = UserForm1.Value
     If Len(txt) Then
         rs.Open "select " & txt & " from `" & fn & "`", cn, 3
         With Sheets.Add
            For i = 0 To rs.Fields.Count - 1
                .Cells(1, i + 1).Value = rs.Fields(i).Name
            Next
            .[a2].CopyFromRecordset rs
            .Name = fn
            .Copy
            With ActiveWorkbook
                .SaveAs myDir & Replace(fn, ".csv", ".xlsx")
                .Close False
            End With
            Application.DisplayAlerts = False
            .Delete
            Application.DisplayAlerts = True
        End With
     End If
     Unload UserForm1
     Set cn = Nothing: Set rs = Nothing
 End Sub

 これでtestを実行してみてください。
(seiya) 2017/10/14(土) 19:16
 修正: 19:36

 コードを若干変更しました。
(seiya) 2017/10/14(土) 19:37

こんなに親切に教えてくださるなんて、本当に本当にありがとうございます!
今から早速やってみます。
seiya様、ご親切に、本当にありがとうございます。
とても助かりましたし、本当に勉強になります。
実行してみてどうだったのか、またコメントしに来ます。
本当にありがとうございました。
(ちはる) 2017/10/14(土) 19:45

実行してみたのですが・・・。
すみません、私のやり方が悪いんだと思うのですが、
どう使うのかわかりませんでした・・・。
折角親切にしてくださったのに、本当にすみません。
ありがとうございました。
(ちはる) 2017/10/14(土) 20:03

 残念だけど一生そうやってるしかないね...
(seiya) 2017/10/14(土) 20:07

本当にそうですね・・・。
折角の親切に、きちんと勉強出来ていなかったので自分でも情けない限りです。
しっかり勉強します。
ごめんなさい。本当にありがとうございました。
ものすごく反省しています。
(ちはる) 2017/10/14(土) 20:16

順を追って、簡単なモノから作って確認していくのがよいと思う。

100列のなかのきまった5列を取り出すなら、
普通に開いて、その5列だけコピーして、元のCSVはそのまま閉じるだけですね。
余り難しく考えずに、できるところから、順を追って作っていけばよいでしょう。
 
一足飛びに完成品を求めるのは、気持ちはわかるが、決してあなたの為にもならない、と思います。

まずは、ひとつのCSVファイルを対象にして、以下のマクロ記録をとってみては?
・ひとつのCSVファイルを開く。
・新しいブックを開く
・5個の列をそれぞれコピーする
・ブックを保存する
・開いたCSVを閉じる

# マクロ記録を取ってください、といわれたら、
# こんなものが採れました、くらいの反応をしてもらえると期待していたが、
# 100列でしたでは、がっくりですよ。マクロ記録したくない、という意思表示ですよね。
# それと、毎回毎回手作業で指定してくれとは言っていない、マクロ記録の一回だけなんですがね。
# 勘違いされているようです。

(γ) 2017/10/14(土) 20:42


Y様、本当に仰る通りです。
こういう物がとれました、としっかりご報告をするべきでした。
無償のご親切に甘えてしまった上にの無礼、本当に申し訳ありません。
それなのに、またご親切なアドバイスをいただき、本当にありがとうございます。

すぐに完成品を求めてしまうのは、確かに私自身の勉強に全くならないと痛感をいたしました。

試しに簡単なマクロからやってみるというのは、早速先程からチャレンジしてみています。
やりたい作業を紙に書き出し、1つ1つ試しながら動かしてみています。

今、seiya様から教えていただいユーザーフォームを使って削除したい指定の列を入れている
マクロを書いてみている所です。

また、Y様から先に教えていただいたマクロ記録から、CSVを取りこんで列を消すマクロのコードを読んで
どういう記述になっているのか、1行づつ理解しています。

お二方からアドバイスしていただいた事、ご親切にしていただいた事はしっかりと活かしていきます。
貴重なお時間を頂いたこと、労力を割いていただい事を忘れません。
本当にありがとうございました。
(ちはる) 2017/10/14(土) 21:05


本当に100列あるなら、一度だけとはいえ95回削除指定を繰り返すのは無駄です。
(追記:まとめて削除指定ができるようですから、大変なことでもないかも)
全体をシートに読み込んで、必要な列だけコピーすればよいと申し上げています。
(γ) 2017/10/14(土) 21:13

 >今、seiya様から教えていただいユーザーフォームを使って削除したい指定の列を入れている 
 >マクロを書いてみている所です。

 ってことは、削除しない列を表示(元来のコード)は出来てるってこと?
 まるっきりの素人がそこまで書けるとは思えんけど。
(seiya) 2017/10/14(土) 21:20

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.