プロが教えるわが家の防犯対策術!

お世話様です。

フォルダ:D:\test に下記CSVファイルが存在している時、同じ会社名同士で売上比較をした際に A.csv > B.csv なら "●", A.csv < B.csv なら "○",
A.csv = B.csv なら "-" とした2次元配列(項目名:比較)になるようにするにはどの様にすれば宜しいでしょうか?
バージョンは 2019 です。

A.csv

会社名,売上
A社,100
B社,95
C社,110
D社,85

----------
B.csv

会社名,売上
A社,105
B社,90
C社,100
D社,85

----------
配列に

会社名,比較
A社,○
B社,●
C社,○
D社,-


です。(配列のカンマは区切りの目安として入れてます。)

それぞれのCSVファイル内では会社名の重複はありませんが、双方のファイル間で組み合わない(片方にしか存在していない)ケースもあります。
可能ならその会社名を抽出する方法もお願いしたい所ではありますが、アドバイス頂ければ調べてみたいと思います。

質問者からの補足コメント

  • うーん・・・

    翌々考えると会社名と比較は対になるので、これは1次元配列でした。(ボケました)

    ならばDictionaryクラスのValuesとかみたいに扱って取り出せるのかな?と挑戦してみます。
    お礼の場所が別になってしまい申し訳ありません。

    No.6の回答に寄せられた補足コメントです。 補足日時:2021/12/29 12:53

A 回答 (6件)

下記、コンソールアプリケーションで作成しました。


回答に貼り付ける関係上、あえてModule1.vb内にすべて記述したものになります。
様々な考えによって実装は異なるでしょうが、参考にしてください。

プロジェクトを右クリック→NuGetパッケージの管理 から、CsvHelperをインストールしてください。
CSV読み込みに、余計な思考を費やす必要ありません。

Imports System.Globalization
Imports System.IO
Imports System.Text
Imports CsvHelper.Configuration
Imports CsvHelper.Configuration.Attributes

Module Module1
Sub Main()
' CSVの読み込み設定
Dim config As New CsvConfiguration(CultureInfo.CurrentCulture)
config.Delimiter = ","
config.HasHeaderRecord = True
config.ShouldQuote = Function(x) False

' 比較元を読み込み
Dim sourceSalesList As List(Of Sales)
Using reader As New StreamReader("D:\test\A.csv", Encoding.GetEncoding("SHIFT-JIS")),
csvReader As New CsvHelper.CsvReader(reader, config)
sourceSalesList = csvReader.GetRecords(Of Sales)().ToList()
End Using

' 比較先を読み込み
Dim destSalesList As List(Of Sales)
Using reader As New StreamReader("D:\test\B.csv", Encoding.GetEncoding("SHIFT-JIS")),
csvReader As New CsvHelper.CsvReader(reader, config)
destSalesList = csvReader.GetRecords(Of Sales)().ToList()
End Using

Dim salesCompareList As New List(Of SalesCompare)()

' どちらにも同じ会社名があるものを追加
Dim joinSalesList = sourceSalesList _
.Join(destSalesList,
Function(x) x.CompanyName,
Function(y) y.CompanyName,
Function(Source, Dest) New With {Source, Dest})
For Each joinSales In joinSalesList
salesCompareList.Add(New SalesCompare(joinSales.Source, joinSales.Dest))
Next

' A.csvにしかない会社名のものを追加
Dim exceptSalesList As IEnumerable(Of Sales)
exceptSalesList = sourceSalesList.Except(destSalesList, New SalesComparer())
For Each exceptSales In exceptSalesList
salesCompareList.Add(New SalesCompare(exceptSales))
Next

' B.csvにしかない会社名のものを追加
exceptSalesList = destSalesList.Except(sourceSalesList, New SalesComparer()).ToList()
For Each exceptSales In exceptSalesList
salesCompareList.Add(New SalesCompare(exceptSales))
Next

' 試しに出力
For Each salesCompare As SalesCompare In salesCompareList
Console.WriteLine($"{salesCompare.CompanyName}:{salesCompare.Result}")
Next
Console.ReadLine()
End Sub
End Module

' セールス実績のクラス
Class Sales
<Index(0)>
Public Property CompanyName As String

<Index(1)>
Public Property Amount As Integer
End Class

Class SalesComparer
Implements IEqualityComparer(Of Sales)

Public Shadows Function Equals(x As Sales, y As Sales) As Boolean Implements IEqualityComparer(Of Sales).Equals
Return x.CompanyName = y.CompanyName
End Function

Public Shadows Function GetHashCode(obj As Sales) As Integer Implements IEqualityComparer(Of Sales).GetHashCode
Return obj.CompanyName.GetHashCode()
End Function
End Class

' セールス実績の比較結果クラス
Class SalesCompare
Public ReadOnly Property Source As Sales
Public ReadOnly Property Dest As Sales

Public Sub New(source As Sales, Optional dest As Sales = Nothing)
Me.Source = source
Me.Dest = dest
End Sub

Public ReadOnly Property CompanyName As String
Get
Return Source.CompanyName
End Get
End Property

Public ReadOnly Property Result As String
Get
If Dest Is Nothing Then
Return "片方にしかない"
End If
If Source.Amount > Dest.Amount Then
Return "●"
End If
If Source.Amount < Dest.Amount Then
Return "○"
End If

Return "-"
End Get
End Property
End Class


実行結果
A社:○
B社:●
C社:●
D社:-
E社:片方にしかない
F社:片方にしかない
この回答への補足あり
    • good
    • 1
この回答へのお礼

再度の回答、何より物凄いコードを書いて頂けて呆然としてます。
実行結果はご提示されている物と同じである確認が出来ました。
NuGetパッケージ系は生涯無縁とも思っていましたので、今後どのような物があるのか調べる楽しみが出てきました。

サンプル出力はプロパティを用いている感じですが、これを配列のインデックス番号に置き換えるとしたら

>' セールス実績のクラス

以下を見直す事になるのでしょうか?
それとも内容的に大掛かりな変更になりますか?
或いは出力方法をちょっと弄ればと言う感じでしょうか?
少し脳活してみたいので具体的でなくても構いません。
ポイントのみ教えていただけたら幸いです。

お礼日時:2021/12/29 11:47

こんにちは


VS(C#)を昔、少し触りましたが、教えられるレベルではありませんので
VB.NETでも、ここあたりが参考になるのではないかと思います。
https://dobon.net/vb/dotnet/file/readcsvfile.html
    • good
    • 0
この回答へのお礼

助かりました

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

昔VBを触って即挫折した頃に見かけたサイトですね。
当時はフォーム上のButtonやTextBoxとかの処理でも頭抱えてました。
暫く離れていましたが再度紹介していただいたサイトで、やり直してみたいと思えて来ました。

お礼日時:2021/12/28 18:43

> 記載されている項目名からしてVisualBasicがメインでVBAも可って思ってました。


> なのでバージョンはVisual Studioのものです。
> 一応2017も入ってはいますが今回についてやり方に違いはあるのでしょうか?

Visual Basic(VB.NET)とVisual Basic for Application(VBA)は別物です。
前者はWindowsアプリケーションなどを独自に作成するものであり、
後者はExcel、Word、PowerPointなどのファイルにプログラムが埋め込まれ、そのファイルをExcelなどのアプリケーションで開いている時に動作させるものです。

独自アプリケーションでCSVファイルを操作したいのか、ExcelやWordを起動している状態でCSVファイルを操作したいのか、で全く異なります。

よって、Googleなどで検索した時、VB、VBAというキーワードで全く別の情報がでてきます。

それをご理解していただいた上で、VB.NETですか?VBAですか?
という質問になります。
    • good
    • 1
この回答へのお礼

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

#1さんの時にお礼ではなく補足欄を用いれば良かったのかも知れませんね。

>一応今やっているのは、
>・Windowsフォームアプリケーション(.NET Framework)

とは書かせていただきましたが、書く場所をミスってしまい申し訳ありませんでした。

ExcelVBAであれば2つのファイルの値をコピペしてセルに貼り付け、区切り文字で列に分け、ワークシート関数かWorksheetFunctionでなら出来るかも知れません。
それでも手動コピペとシートを頼った方法になってしまいます。
手動部分はマクロの自動記録を参考に行けるかもですが、私はてっきりVisualStudioででもそんな機能があるのかと気になった次第です。

お礼日時:2021/12/28 11:22

>VBAについてしか見つからず


VBAでいいのです VBA=マクロ です

マクロ記述をしてもいいのですが、あなたの質問の仕方では、あなたの技量がわからないし、あまり関係ない記述に凝っている(例「CSVから読み込む」)ところからすると、やりたいことは もっと奥がありそう なので「マクロ記録でやってみては」としました。
多くの人が「マクロ記録」を使って勉強したと思いますよ。

ところでNo2の回答で気づきましたが Excelでよかったのでしょうか?
    • good
    • 0
この回答へのお礼

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

一応カテ的にVB.NETの質問も可能と判断し(質問文では漏れてしまい申し訳ありません)質問をさせて頂きました。

最初の回答のお礼でお伝えしているプロジェクトの条件

・Windowsフォームアプリケーション(.NET Framework)

を上げさせて頂きましたが、Excelかどうかについてはまだ情報不足でしたでしょうか。

それよりこのカテってVB系なのかVBAのみなのかがわかりにくいのですね。
C#についてはキチンと記載があるのですけど。

お礼日時:2021/12/28 16:37

カテゴリはVBAですが、VBAでやりたいのですか?


.NET Frameworkでやりたいのですか?
2019というバージョンはOfficeではなく、Visual Studioでしたか?
    • good
    • 0
この回答へのお礼

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

>カテゴリはVBAですが、VBAでやりたいのですか?

そうなのですか?
記載されている項目名からしてVisualBasicがメインでVBAも可って思ってました。
なのでバージョンはVisual Studioのものです。
一応2017も入ってはいますが今回についてやり方に違いはあるのでしょうか?

>.NET Frameworkでやりたいのですか?

はい。
VBをやるには入門編の様な気がしましたので。(もしかして違いますか?)

お礼日時:2021/12/28 10:01

マクロ記録を使って、あなたの言う手順を実際にやってみて、記録されたマクロを手直しすればいいでしょう。



マクロを教えてもいいけど、あなた自身がこの操作をわかってないみたいなので、あえてこう言っておきます。
    • good
    • 0
この回答へのお礼

早々に回答ありがとうございました。

マクロの記録と言うのがあるのですね。
一応今やっているのは、
・Windowsフォームアプリケーション(.NET Framework)
なのですがどの辺を弄ると使えますか?
それとも隠しコマンド的な物でしょうか?

検索してもVBAについてしか見つからず。
もしご存じならリンクを頂けると幸いです。

お礼日時:2021/12/28 08:45

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