回答編集履歴
3
追記その2
answer
CHANGED
@@ -100,4 +100,107 @@
|
|
100
100
|
|
101
101
|
Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)
|
102
102
|
|
103
|
-
**【注】ただし C# のオブジェクトとして取得した結果の型は schema.ini で指定した通りになります。上のコード例では DataTable に CSV データを取得していますが、DataTable の型は DataGridView の左から順に int, string, decimal, bool になります。そこはこのコードのメリットと言えるのではないでしょうか。**
|
103
|
+
**【注】ただし C# のオブジェクトとして取得した結果の型は schema.ini で指定した通りになります。上のコード例では DataTable に CSV データを取得していますが、DataTable の型は DataGridView の左から順に int, string, decimal, bool になります。そこはこのコードのメリットと言えるのではないでしょうか。**
|
104
|
+
|
105
|
+
**【追記2】**
|
106
|
+
|
107
|
+
下の 2019/06/27 12:03 の私のコメントで
|
108
|
+
|
109
|
+
> hihijiji さんの案 CsvHelper を NuGet でインストールして使うのが正解のようです。CSV ファイルの特定の列だけ取得できますし、指定した型に変換できないと例外をスローしてくれます。後で例を回答欄に追記しておきます。
|
110
|
+
|
111
|
+
と書きましたが、上の【追記】と同じ CSV ファイルの同じ列を CsvHelper で取得し、同じ Form の同じ DataGridView に表示した例を以下に書いておきます。
|
112
|
+
|
113
|
+
ただし、質問者さんの扱う CSV ファイルにはヘッダがないそうですが、下の例ではヘッダありにしています。ヘッダなしでも対応できるかどうかまでは調べてません。
|
114
|
+
|
115
|
+
コードは以下の通りです。上のコードに Product, ProductMapper クラスを追加し、Form12_Load ハンドラでは先の ADO.NET のコードをコメントアウトして CsvHelper のコードを追記しただけです。
|
116
|
+
|
117
|
+
```
|
118
|
+
using System;
|
119
|
+
using System.Collections.Generic;
|
120
|
+
using System.ComponentModel;
|
121
|
+
using System.Data;
|
122
|
+
using System.Drawing;
|
123
|
+
using System.Linq;
|
124
|
+
using System.Text;
|
125
|
+
using System.Threading.Tasks;
|
126
|
+
using System.Windows.Forms;
|
127
|
+
using System.Data.OleDb;
|
128
|
+
using CsvHelper;
|
129
|
+
using CsvHelper.Configuration;
|
130
|
+
using System.IO;
|
131
|
+
|
132
|
+
namespace WindowsFormsApplication1
|
133
|
+
{
|
134
|
+
public partial class Form12 : Form
|
135
|
+
{
|
136
|
+
private DataGridView dataGridView1;
|
137
|
+
private BindingSource bindingSource1;
|
138
|
+
private string path = @"C:\Users\surfe...\WindowsFormsApplication1\";
|
139
|
+
private string filename = "Products.csv";
|
140
|
+
|
141
|
+
public Form12()
|
142
|
+
{
|
143
|
+
InitializeComponent();
|
144
|
+
|
145
|
+
this.dataGridView1 = new DataGridView();
|
146
|
+
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
|
147
|
+
this.bindingSource1 = new BindingSource();
|
148
|
+
this.dataGridView1.DataSource = this.bindingSource1;
|
149
|
+
this.Controls.Add(this.dataGridView1);
|
150
|
+
}
|
151
|
+
|
152
|
+
private void Form12_Load(object sender, EventArgs e)
|
153
|
+
{
|
154
|
+
// 接続文字列。HDR=Yes で一行目をヘッダーとして扱う
|
155
|
+
//string conString =
|
156
|
+
// "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
|
157
|
+
// this.path +
|
158
|
+
// ";Extended Properties=\"text;HDR=Yes;FMT=Delimited\"";
|
159
|
+
|
160
|
+
//OleDbConnection con = new OleDbConnection(conString);
|
161
|
+
//string commText = "SELECT [ProductID],[ProductName],[UnitPrice],[Discontinued] FROM [" + this.filename + "]";
|
162
|
+
//OleDbDataAdapter da = new OleDbDataAdapter(commText, con);
|
163
|
+
|
164
|
+
//DataTable dt = new DataTable();
|
165
|
+
//da.Fill(dt);
|
166
|
+
|
167
|
+
//this.bindingSource1.DataSource = dt;
|
168
|
+
|
169
|
+
using (var csv = new CsvReader(new StreamReader(this.path + this.filename)))
|
170
|
+
{
|
171
|
+
var config = csv.Configuration;
|
172
|
+
config.HasHeaderRecord = true; // ヘッダーが存在する場合 true
|
173
|
+
config.RegisterClassMap<ProductMapper>();
|
174
|
+
var list = csv.GetRecords<Product>();
|
175
|
+
this.bindingSource1.DataSource = list;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
public class Product
|
181
|
+
{
|
182
|
+
public int ProductID { get; set; }
|
183
|
+
public string ProductName { set; get; }
|
184
|
+
public decimal UnitPrice { set; get; }
|
185
|
+
public bool Discontinued { set; get; }
|
186
|
+
}
|
187
|
+
|
188
|
+
public class ProductMapper : ClassMap<Product>
|
189
|
+
{
|
190
|
+
private ProductMapper()
|
191
|
+
{
|
192
|
+
Map(c => c.ProductID).Index(0);
|
193
|
+
Map(c => c.ProductName).Index(1);
|
194
|
+
Map(c => c.UnitPrice).Index(5);
|
195
|
+
Map(c => c.Discontinued).Index(9);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
```
|
201
|
+
|
202
|
+
結果は上の画像と同じです。
|
203
|
+
|
204
|
+
クラス Product で指定した型に変換できないと例外がスローされます。例えば int 型でなければならない ProductID を CSV ファイルで "xxxxx" にすると以下の例外がスローされます。
|
205
|
+
|
206
|
+

|
2
追記
answer
CHANGED
@@ -98,4 +98,6 @@
|
|
98
98
|
|
99
99
|

|
100
100
|
|
101
|
-
Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)
|
101
|
+
Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)
|
102
|
+
|
103
|
+
**【注】ただし C# のオブジェクトとして取得した結果の型は schema.ini で指定した通りになります。上のコード例では DataTable に CSV データを取得していますが、DataTable の型は DataGridView の左から順に int, string, decimal, bool になります。そこはこのコードのメリットと言えるのではないでしょうか。**
|
1
追記
answer
CHANGED
@@ -2,4 +2,100 @@
|
|
2
2
|
|
3
3
|
135 列ある CSV ファイルの中から特定の 5 列のデータのみ取得したい。その際、各列の型を判定してそれを C# のオブジェクトに反映したいということですか?
|
4
4
|
|
5
|
-
であれば、JET または ACE プロバイダ + ADO.NET を使って、型は schema.ini というファイルを作って指定するという方向で考えるというのはいかがですか?
|
5
|
+
であれば、JET または ACE プロバイダ + ADO.NET を使って、型は schema.ini というファイルを作って指定するという方向で考えるというのはいかがですか?
|
6
|
+
|
7
|
+
**【追記】**
|
8
|
+
|
9
|
+
検証してみましたが、JET または ACE プロバイダ + ADO.NET で特定の列を取得するのは SELECT クエリで取得したい列を指定すれば可能でしたが、schema.ini ファイルに指定される型と CSV データが違ってもエラーは出ませんでした。
|
10
|
+
|
11
|
+
なので、質問者さんの目的、
|
12
|
+
|
13
|
+
> エラーメッセージが出るようにしたいです。
|
14
|
+
|
15
|
+
には上記の案ではダメでした。すみません。
|
16
|
+
|
17
|
+
|
18
|
+
以下、お役には立たないと思いますが、ご参考までにどのように検証したかを書いておきます。
|
19
|
+
|
20
|
+
まず、CSV ファイルですが、Microsoft のサンプルデータベース Northwind の Products テーブルから SSMS を使ってエクスポートしたものを使います。
|
21
|
+
|
22
|
+

|
23
|
+
|
24
|
+
Schema.ini は以下の通り。
|
25
|
+
|
26
|
+
```
|
27
|
+
[Products.csv]
|
28
|
+
ColNameHeader=True
|
29
|
+
Format=CSVDelimited
|
30
|
+
CharacterSet=65001
|
31
|
+
Col1=ProductID Long
|
32
|
+
Col2=ProductName Text
|
33
|
+
Col3=SupplierID Long
|
34
|
+
Col4=CategoryID Long
|
35
|
+
Col5=QuantityPerUnit Text
|
36
|
+
Col6=UnitPrice Currency
|
37
|
+
Col7=UnitsInStock Short
|
38
|
+
Col8=UnitsOnOrder Short
|
39
|
+
Col9=ReorderLevel Short
|
40
|
+
Col10=Discontinued Bit
|
41
|
+
```
|
42
|
+
Windows Forms アプリのコードは以下の通り。
|
43
|
+
|
44
|
+
```
|
45
|
+
using System;
|
46
|
+
using System.Collections.Generic;
|
47
|
+
using System.ComponentModel;
|
48
|
+
using System.Data;
|
49
|
+
using System.Drawing;
|
50
|
+
using System.Linq;
|
51
|
+
using System.Text;
|
52
|
+
using System.Threading.Tasks;
|
53
|
+
using System.Windows.Forms;
|
54
|
+
using System.Data.OleDb;
|
55
|
+
|
56
|
+
namespace WindowsFormsApplication1
|
57
|
+
{
|
58
|
+
public partial class Form12 : Form
|
59
|
+
{
|
60
|
+
private DataGridView dataGridView1;
|
61
|
+
private BindingSource bindingSource1;
|
62
|
+
private string path = @"C:\Users...\WindowsFormsApplication1\";
|
63
|
+
private string filename = "Products.csv";
|
64
|
+
|
65
|
+
public Form12()
|
66
|
+
{
|
67
|
+
InitializeComponent();
|
68
|
+
|
69
|
+
this.dataGridView1 = new DataGridView();
|
70
|
+
this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
|
71
|
+
this.bindingSource1 = new BindingSource();
|
72
|
+
this.dataGridView1.DataSource = this.bindingSource1;
|
73
|
+
this.Controls.Add(this.dataGridView1);
|
74
|
+
}
|
75
|
+
|
76
|
+
private void Form12_Load(object sender, EventArgs e)
|
77
|
+
{
|
78
|
+
// 接続文字列。HDR=Yes で一行目をヘッダーとして扱う
|
79
|
+
string conString =
|
80
|
+
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
|
81
|
+
this.path +
|
82
|
+
";Extended Properties=\"text;HDR=Yes;FMT=Delimited\"";
|
83
|
+
|
84
|
+
OleDbConnection con = new OleDbConnection(conString);
|
85
|
+
string commText = "SELECT [ProductID],[ProductName],[UnitPrice],[Discontinued] FROM [" + this.filename + "]";
|
86
|
+
OleDbDataAdapter da = new OleDbDataAdapter(commText, con);
|
87
|
+
|
88
|
+
DataTable dt = new DataTable();
|
89
|
+
da.Fill(dt);
|
90
|
+
|
91
|
+
this.bindingSource1.DataSource = dt;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
```
|
96
|
+
|
97
|
+
結果は以下のようになります。
|
98
|
+
|
99
|
+

|
100
|
+
|
101
|
+
Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)
|