🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

8491閲覧

取り込んだcsvのデータをソートしたいです。

xss

総合スコア36

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2019/09/11 12:27

編集2019/09/11 16:03

前提・実現したいこと

VBAで取り込んだcsvファイルのデータをソートしたいのですがうまくいきません。
3列目の数字をキーにして昇順ソートを行ってからデータを扱いたいです。

よろしければソートの手法やソートが実現できるコードを教えて頂けませんでしょうか。
お手数お掛けいたしますがご教授をよろしくお願いします。

csvファイルはテキストファイルで作成し拡張子をcsvにしております。
■使用するCSVのデータ
"富田","男","104","神奈川"
"村田","男","106","沖縄"
"山田","女","103","福岡"
"前田","男","101","北海道"
"栗田","男","103","東京"
"藤田","男","102","大阪"
"三田","女","106","愛媛"
"園田","女","105","愛媛"

該当のソースコード

Public Const COLNUM = 3 Public Function CntConfirmation(ByVal pfilePath As String)As Boolean CntConfirmation = False Dim agoRecord As String Dim newRecord As String Dim cntStorage As String 'CSV行格納配列 Dim fileDataTable() As String Dim FSO As Object Dim dataFile As Object Set FSO = CreateObject("Scripting.FileSystemObject") Set dataFile = FSO.OpenTextFile(pfilePath) 'ここが焦点になります。 '******************************** 'ここの処理でソートを試みてみました。 dataFile.sort Key := Range("C1"), _ Order := xlAscending '******************************** Do while readCSV(dataFile,fileDataTable) newRecord = fileDataTable(COLNUM - 1) If agoRecord = newRecord Then cntStorage = cntStorage + 1 End If agoRecord = newRecord loop CntConfirmation = True End Function

補足情報(FW/ツールのバージョンなど)

Excel2016

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2019/09/11 13:26

FileSystemObjectにソート機能はないと思いますが(私が知らないだけかもしれませんが)、 FileSystemObjectでソートを行うことができるという情報は、どこから入手したのでしょうか。 そのURL等を提示していただければ幸いです。 私が思うに、適当なワークシートにファイルの内容を展開し、ワークシート上でソートするのが、一番簡単かと思うのですが、いかがでしょうか。
xss

2019/09/11 13:33

tatsu99さん回答ありがとうございます。 FileSystemObjectでソートを行おうとしていなくオブジェクト型に格納した後で処理を通してソートできないか探っている所です。 エクセルで開いてフィルタでソートをするのが手っ取り早いのは事実でございますがなんとかコード上で昇順ソートを実現したく困っております。。
meg_

2019/09/11 22:18

OpenTextFileの戻り値は「TextStream オブジェクト」ですね。仮にこれを並べ替えられたとしても、意味ないかと思います。 エクセルの機能を使いたくないなら、ご自身でソート機能を実装すれば良いです。
tatsu99

2019/09/12 00:11

>FileSystemObjectでソートを行おうとしていなくオブジェクト型に格納した後で処理を通してソートできないか探っている所です。 meg_さんも書かれていますが、OpenTextFileの戻り値は「TextStream オブジェクト」です。 TextStream オブジェクトはSortメソッドを持っていません。 vbaで最も使用されるソートは、Rangeオブジェクトのソートです。Rangeオブジェクトはセルの集合です。したがって、「適当なワークシートにファイルの内容を展開し、ワークシート上でソートする」ことになります。この場合、人間の手作業は発生しません。全て、マクロで行います。 それで良ければ、提示可能です(案1)。ただし、この場合、ワークシートを1枚使用するので、そのワークシートを予め、確保しておく必要があります。そんな、みっともないことはしたくないということであれば、実行時にワークシートを追加し、完了後にワークシートを削除することになります。 Rangeオブジェクトのソートは使いたくないということであれば、SortedListの使用が考えられますが、ソートの条件は1つのキーという制約があります。また、キーの重複を許さないので、特別な手当てが必要になります。それで良ければ、提示可能です。(案2) 又、ソートのキーですが3桁固定なのでしょうか。もし、そうでないなら、文字列としてソートするのか数字としてソートするのか、どちらでしょうか。 数字のソート昇順の場合、以下のようになります。 "50" "223" "1234" 文字のソート昇順の場合、以下のようになります。 "1234" "223" "50"
tatsu99

2019/09/12 01:46

結局最終的には、何がほしいのでしょうか。 fileDataTable()にソートされた結果がほしいのでしょうか。 readCSVのソースが提示されていないので、よくわかりませんが、 fileDataTableの要素は、1レコードですか、それとも、3列目のキーのみでしょうか。 キーの重複件数をカウントしているようにも見えますが、キーの重複件数がほしいためにだけソートしているのであれば、ソートせずに、キーの重複件数のみを取得する方法もあります。(dictionaryを使います)
xss

2019/09/12 04:59

ご返事ありがとうございます。dataFile(CSVのデータ)に対して 3列目をキーにして昇順ソートをしたいです。 CSVは毎回レコード数が違います。 10万レコードだったり1万レコードだったりします。 3列目は値は桁数が同じ数字になります。 分かりやすく3桁にしております。 そして重複した値があります。 fileDataTableは1レコードの3列目の値(数字)を差していてそれを交互に比較していき差異があった場合にカウントをするコードを作成したく迷っておりました。 私がほしいものは Set dataFile = FSO.OpenTextFile(pfilePath) のdataFileを3列目を基準に昇順ソートを行いたいです。
meg_

2019/09/12 10:59

.NETのArrayListのSortメソッドでもソート出来そうです。
guest

回答3

0

既存のオブジェクトを使うのであれば、ADODB(Microsoft ActiveX Data Objects X.X Library)を使うのも手ではあるでしょう。

例1:ADODB.Connectionを使う方法

既存のCSVファイルをデータベースとして見立てて、読み込む方法です。
実行環境によって調整が必要ですが、動くのであれば色々操作が楽な方法です。

結果はADODB.Recordsetというオブジェクトとなりますが、このオブジェクトから色々な形式に変換できます(下記コードでは確認用に文字列化しています)。

vba

1Sub teratail211399_CSVSort_ADODBConnection(pfilePath As String) 2 '元の質問 3 'https://teratail.com/questions/211399 4 '参考サイト 5 'https://z1000s.hatenablog.com/entry/2019/06/10/225834 6 7 Dim FSO As Object 'As Scripting.FileSystemObject 8 Set FSO = CreateObject("Scripting.FileSystemObject") 9 10 'ここの書き方はOfficeのバージョン・bit数・Accessインストールの有無などによって変わる。 11 '参考 12 'Driver={Microsoft Text Driver (*.txt; *.csv)}; 13 'Driver={Microsoft Access Text Driver (*.txt, *.csv)}; 14 Const ConnectionStringBase = _ 15 "Provider=Microsoft.ACE.OLEDB.12.0;" & _ 16 "Data Source='{SourceFolder}';" & _ 17 "Extended Properties=""Text;HDR=No;""" 18 19 Dim conString As String 20 conString = Replace( _ 21 ConnectionStringBase, _ 22 "{SourceFolder}", _ 23 FSO.GetParentFolderName(pfilePath) _ 24 ) 25 26 Dim con As Object 'As ADODB.Connection 27 Set con = CreateObject("ADODB.Connection") 28 29 con.Open conString 30 31 'FileNameから(FROM [{FileName}]) 32 '全列取得(SELECT *) 33 'F3の列を昇順(ASC)ソート(ORDER BY F3 ASC) 34 Const SQLBase = "SELECT * FROM [{FileName}] ORDER BY F3 ASC" 35 36 Dim cmdSql As String 37 cmdSql = Replace( _ 38 SQLBase, _ 39 "{FileName}", _ 40 FSO.GetFileName(pfilePath) _ 41 ) 42 43 Dim rs As Object 'As ADODB.Recordset 44 Set rs = con.Execute(cmdSql) 45 46 '確認用(ORDER BYで指定していない列はCSVファイル通りの順番ではない) 47 rs.MoveFirst 48 Debug.Print rs.GetString 49 Stop 50 51End Sub

text

1前田 男 101 北海道 2藤田 男 102 大阪 3栗田 男 103 東京 4山田 女 103 福岡 5富田 男 104 神奈川 6園田 女 105 愛媛 7三田 女 106 愛媛 8村田 男 106 沖縄

例2:ADODB.Recordsetを単独で使う方法

例1で使っているADODB.Recordsetは単独でもソート機能を持っているため、そちらを使う手もあります。

CSVの読み込みと解釈は自前で実装する必要があります(下記コードは簡易コードです)。

vba

1Sub teratail211399_CSVSort_ADODBRecordsetOnly(pfilePath As String) 2 '元の質問 3 'https://teratail.com/questions/211399 4 5 Dim FSO As Object 'As Scripting.FileSystemObject 6 Set FSO = CreateObject("Scripting.FileSystemObject") 7 8 Dim rs As Object 'As ADODB.Recordset 9 Set rs = CreateObject("ADODB.Recordset") 10 11 'CSVの列を定義 12 '文字列でもソートしたいなら、adBSTRではなく、adVarWChar(= 202)と3個目の引数指定が必要 13 Const adBSTR = VBA.VbVarType.vbString '= 8 14 Const adInteger = VBA.VbVarType.vbLong '= 3 15 With rs.Fields 16 .Append "名字", adBSTR 17 .Append "性別", adBSTR 18 .Append "No.", adInteger 19 .Append "県", adBSTR 20 End With 21 rs.Open 22 rs.Sort = "[No.] ASC" 'No.の列を昇順ソートさせる 23 24 Dim ts As Object 'As Scripting.TextStream 25 Set ts = FSO.OpenTextFile(pfilePath) 26 27 Do Until ts.AtEndOfLine 28 Dim csvRecord() As String 29 csvRecord = Split(ts.ReadLine(), ",") 30 rs.AddNew 31 Dim c As Long 32 For c = LBound(csvRecord) To UBound(csvRecord) 33 'VBAの暗黙の型変換も利用 34 'ダブルクォーテーションを削除 35 rs.Fields.Item(c).Value = Replace(csvRecord(c), """", "") 36 Next c 37 Loop 38 ts.Close 39 40 '確認用 41 rs.MoveFirst 42 Debug.Print rs.GetString 43 Stop 44 45End Sub

text

1前田 男 101 北海道 2藤田 男 102 大阪 3山田 女 103 福岡 4栗田 男 103 東京 5富田 男 104 神奈川 6園田 女 105 愛媛 7村田 男 106 沖縄 8三田 女 106 愛媛

投稿2019/09/14 05:25

imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xss

2019/09/20 18:59

imihitoさんご解答ありがとうございます。 ADODBを使用する方法もあるのですね、ものすごく参考になります。 ご回答感謝いたします。
guest

0

ベストアンサー

あなたの提示された関数を修正しました。
「作業」シートを事前に作成してください。
A列がキー、B列が1レコードの内容になります。
個々の項目にはばらしていません。ダブルクオートもとっていません。
A列でソートされた結果が表示されます。

vba

1Public Function CntConfirmation(ByVal pfilePath As String) As Boolean 2 Application.ScreenUpdating = False 3 4 CntConfirmation = False 5 Dim line As String 6 Dim items As Variant 7 Dim ws As Worksheet 8 Dim sr_key As String 9 Dim wrow As Long 10 Dim FSO As Object 11 Dim dataFile As Object 12 Set ws = Worksheets("作業") 13 ws.Cells.ClearContents 14 Set FSO = CreateObject("Scripting.FileSystemObject") 15 Set dataFile = FSO.OpenTextFile(pfilePath) 16 wrow = 0 17 '最後の行迄1行ずつ読み込む 18 Do Until dataFile.AtEndOfStream 19 wrow = wrow + 1 20 line = dataFile.ReadLine 21 items = Split(line, ",") 22 sr_key = CStr(items(2)) 23 ws.Cells(wrow, "A").Value = sr_key 24 ws.Cells(wrow, "B").Value = line 25 Loop 26 'キーでソート 27 ws.Range("A1:B" & wrow).Sort key1:=ws.Range("A1"), Order1:=xlAscending, Header:=xlNo 28 Application.ScreenUpdating = True 29 30 CntConfirmation = True 31End Function

投稿2019/09/12 05:22

tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2019/09/13 10:33

リプライがありませんが、何か不満があるのでしょうか? 個々の項目にばらすとか、ダブルクオートをとるのは、あなたのスキルなら可能かと判断したためです。 また、このケースでは、それらの処理は、求められていないと判断しました。
xss

2019/09/20 18:58

返信遅れて申し訳ございません。 回答ありがとうございます。 読み返して勉強した結果、納得をいたしました。 その中でtatsu99さんのご解答とても参考になりました。 感謝いたします。
guest

0

>よろしければソートの手法やソートが実現できるコードを
>教えて頂けませんでしょうか。
>お手数お掛けいたしますがご教授をよろしくお願いします

CSV ソート

で検索すれば、手法やサンプルコードがいくつか見つかります。
いつ回答があるかわからない掲示板より、
解決が早いと思いますよ。

多分、
1)エクセルでCSVファイルを開く
2)エクセルの並び替え機能で並び替え
とやる手法が、開発コストが少なく、処理速度も速い部類になると思います。

http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_800.html
http://mofuken.blogspot.com/2017/09/vba-csv.html
https://accesskid.wordpress.com/2011/07/01/%E4%B8%A6%E3%81%B9%E6%9B%BF%E3%81%88%E3%81%AE%E5%9F%BA%E6%BA%96%E3%81%A8%E3%81%99%E3%82%8B%E5%88%97%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6csv%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92/
http://sak.cool.coocan.jp/w_sak3/doc/sysbrd/vb_t06.htm

投稿2019/09/11 23:37

mattuwan

総合スコア2163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問