回答編集履歴

3

追記その2

2019/06/27 03:22

投稿

退会済みユーザー
test CHANGED
@@ -203,3 +203,209 @@
203
203
 
204
204
 
205
205
  **【注】ただし C# のオブジェクトとして取得した結果の型は schema.ini で指定した通りになります。上のコード例では DataTable に CSV データを取得していますが、DataTable の型は DataGridView の左から順に int, string, decimal, bool になります。そこはこのコードのメリットと言えるのではないでしょうか。**
206
+
207
+
208
+
209
+ **【追記2】**
210
+
211
+
212
+
213
+ 下の 2019/06/27 12:03 の私のコメントで
214
+
215
+
216
+
217
+ > hihijiji さんの案 CsvHelper を NuGet でインストールして使うのが正解のようです。CSV ファイルの特定の列だけ取得できますし、指定した型に変換できないと例外をスローしてくれます。後で例を回答欄に追記しておきます。
218
+
219
+
220
+
221
+ と書きましたが、上の【追記】と同じ CSV ファイルの同じ列を CsvHelper で取得し、同じ Form の同じ DataGridView に表示した例を以下に書いておきます。
222
+
223
+
224
+
225
+ ただし、質問者さんの扱う CSV ファイルにはヘッダがないそうですが、下の例ではヘッダありにしています。ヘッダなしでも対応できるかどうかまでは調べてません。
226
+
227
+
228
+
229
+ コードは以下の通りです。上のコードに Product, ProductMapper クラスを追加し、Form12_Load ハンドラでは先の ADO.NET のコードをコメントアウトして CsvHelper のコードを追記しただけです。
230
+
231
+
232
+
233
+ ```
234
+
235
+ using System;
236
+
237
+ using System.Collections.Generic;
238
+
239
+ using System.ComponentModel;
240
+
241
+ using System.Data;
242
+
243
+ using System.Drawing;
244
+
245
+ using System.Linq;
246
+
247
+ using System.Text;
248
+
249
+ using System.Threading.Tasks;
250
+
251
+ using System.Windows.Forms;
252
+
253
+ using System.Data.OleDb;
254
+
255
+ using CsvHelper;
256
+
257
+ using CsvHelper.Configuration;
258
+
259
+ using System.IO;
260
+
261
+
262
+
263
+ namespace WindowsFormsApplication1
264
+
265
+ {
266
+
267
+ public partial class Form12 : Form
268
+
269
+ {
270
+
271
+ private DataGridView dataGridView1;
272
+
273
+ private BindingSource bindingSource1;
274
+
275
+ private string path = @"C:\Users\surfe...\WindowsFormsApplication1\";
276
+
277
+ private string filename = "Products.csv";
278
+
279
+
280
+
281
+ public Form12()
282
+
283
+ {
284
+
285
+ InitializeComponent();
286
+
287
+
288
+
289
+ this.dataGridView1 = new DataGridView();
290
+
291
+ this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
292
+
293
+ this.bindingSource1 = new BindingSource();
294
+
295
+ this.dataGridView1.DataSource = this.bindingSource1;
296
+
297
+ this.Controls.Add(this.dataGridView1);
298
+
299
+ }
300
+
301
+
302
+
303
+ private void Form12_Load(object sender, EventArgs e)
304
+
305
+ {
306
+
307
+ // 接続文字列。HDR=Yes で一行目をヘッダーとして扱う
308
+
309
+ //string conString =
310
+
311
+ // "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
312
+
313
+ // this.path +
314
+
315
+ // ";Extended Properties=\"text;HDR=Yes;FMT=Delimited\"";
316
+
317
+
318
+
319
+ //OleDbConnection con = new OleDbConnection(conString);
320
+
321
+ //string commText = "SELECT [ProductID],[ProductName],[UnitPrice],[Discontinued] FROM [" + this.filename + "]";
322
+
323
+ //OleDbDataAdapter da = new OleDbDataAdapter(commText, con);
324
+
325
+
326
+
327
+ //DataTable dt = new DataTable();
328
+
329
+ //da.Fill(dt);
330
+
331
+
332
+
333
+ //this.bindingSource1.DataSource = dt;
334
+
335
+
336
+
337
+ using (var csv = new CsvReader(new StreamReader(this.path + this.filename)))
338
+
339
+ {
340
+
341
+ var config = csv.Configuration;
342
+
343
+ config.HasHeaderRecord = true; // ヘッダーが存在する場合 true
344
+
345
+ config.RegisterClassMap<ProductMapper>();
346
+
347
+ var list = csv.GetRecords<Product>();
348
+
349
+ this.bindingSource1.DataSource = list;
350
+
351
+ }
352
+
353
+ }
354
+
355
+ }
356
+
357
+
358
+
359
+ public class Product
360
+
361
+ {
362
+
363
+ public int ProductID { get; set; }
364
+
365
+ public string ProductName { set; get; }
366
+
367
+ public decimal UnitPrice { set; get; }
368
+
369
+ public bool Discontinued { set; get; }
370
+
371
+ }
372
+
373
+
374
+
375
+ public class ProductMapper : ClassMap<Product>
376
+
377
+ {
378
+
379
+ private ProductMapper()
380
+
381
+ {
382
+
383
+ Map(c => c.ProductID).Index(0);
384
+
385
+ Map(c => c.ProductName).Index(1);
386
+
387
+ Map(c => c.UnitPrice).Index(5);
388
+
389
+ Map(c => c.Discontinued).Index(9);
390
+
391
+ }
392
+
393
+ }
394
+
395
+ }
396
+
397
+
398
+
399
+ ```
400
+
401
+
402
+
403
+ 結果は上の画像と同じです。
404
+
405
+
406
+
407
+ クラス Product で指定した型に変換できないと例外がスローされます。例えば int 型でなければならない ProductID を CSV ファイルで "xxxxx" にすると以下の例外がスローされます。
408
+
409
+
410
+
411
+ ![イメージ説明](e5ecb4f556158230c6704cbd1d28e285.jpeg)

2

追記

2019/06/27 03:22

投稿

退会済みユーザー
test CHANGED
@@ -199,3 +199,7 @@
199
199
 
200
200
 
201
201
  Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)
202
+
203
+
204
+
205
+ **【注】ただし C# のオブジェクトとして取得した結果の型は schema.ini で指定した通りになります。上のコード例では DataTable に CSV データを取得していますが、DataTable の型は DataGridView の左から順に int, string, decimal, bool になります。そこはこのコードのメリットと言えるのではないでしょうか。**

1

追記

2019/06/26 06:36

投稿

退会済みユーザー
test CHANGED
@@ -7,3 +7,195 @@
7
7
 
8
8
 
9
9
  であれば、JET または ACE プロバイダ + ADO.NET を使って、型は schema.ini というファイルを作って指定するという方向で考えるというのはいかがですか?
10
+
11
+
12
+
13
+ **【追記】**
14
+
15
+
16
+
17
+ 検証してみましたが、JET または ACE プロバイダ + ADO.NET で特定の列を取得するのは SELECT クエリで取得したい列を指定すれば可能でしたが、schema.ini ファイルに指定される型と CSV データが違ってもエラーは出ませんでした。
18
+
19
+
20
+
21
+ なので、質問者さんの目的、
22
+
23
+
24
+
25
+ > エラーメッセージが出るようにしたいです。
26
+
27
+
28
+
29
+ には上記の案ではダメでした。すみません。
30
+
31
+
32
+
33
+
34
+
35
+ 以下、お役には立たないと思いますが、ご参考までにどのように検証したかを書いておきます。
36
+
37
+
38
+
39
+ まず、CSV ファイルですが、Microsoft のサンプルデータベース Northwind の Products テーブルから SSMS を使ってエクスポートしたものを使います。
40
+
41
+
42
+
43
+ ![イメージ説明](4071879e0de9cdb9621ee5062dda0941.jpeg)
44
+
45
+
46
+
47
+ Schema.ini は以下の通り。
48
+
49
+
50
+
51
+ ```
52
+
53
+ [Products.csv]
54
+
55
+ ColNameHeader=True
56
+
57
+ Format=CSVDelimited
58
+
59
+ CharacterSet=65001
60
+
61
+ Col1=ProductID Long
62
+
63
+ Col2=ProductName Text
64
+
65
+ Col3=SupplierID Long
66
+
67
+ Col4=CategoryID Long
68
+
69
+ Col5=QuantityPerUnit Text
70
+
71
+ Col6=UnitPrice Currency
72
+
73
+ Col7=UnitsInStock Short
74
+
75
+ Col8=UnitsOnOrder Short
76
+
77
+ Col9=ReorderLevel Short
78
+
79
+ Col10=Discontinued Bit
80
+
81
+ ```
82
+
83
+ Windows Forms アプリのコードは以下の通り。
84
+
85
+
86
+
87
+ ```
88
+
89
+ using System;
90
+
91
+ using System.Collections.Generic;
92
+
93
+ using System.ComponentModel;
94
+
95
+ using System.Data;
96
+
97
+ using System.Drawing;
98
+
99
+ using System.Linq;
100
+
101
+ using System.Text;
102
+
103
+ using System.Threading.Tasks;
104
+
105
+ using System.Windows.Forms;
106
+
107
+ using System.Data.OleDb;
108
+
109
+
110
+
111
+ namespace WindowsFormsApplication1
112
+
113
+ {
114
+
115
+ public partial class Form12 : Form
116
+
117
+ {
118
+
119
+ private DataGridView dataGridView1;
120
+
121
+ private BindingSource bindingSource1;
122
+
123
+ private string path = @"C:\Users...\WindowsFormsApplication1\";
124
+
125
+ private string filename = "Products.csv";
126
+
127
+
128
+
129
+ public Form12()
130
+
131
+ {
132
+
133
+ InitializeComponent();
134
+
135
+
136
+
137
+ this.dataGridView1 = new DataGridView();
138
+
139
+ this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
140
+
141
+ this.bindingSource1 = new BindingSource();
142
+
143
+ this.dataGridView1.DataSource = this.bindingSource1;
144
+
145
+ this.Controls.Add(this.dataGridView1);
146
+
147
+ }
148
+
149
+
150
+
151
+ private void Form12_Load(object sender, EventArgs e)
152
+
153
+ {
154
+
155
+ // 接続文字列。HDR=Yes で一行目をヘッダーとして扱う
156
+
157
+ string conString =
158
+
159
+ "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
160
+
161
+ this.path +
162
+
163
+ ";Extended Properties=\"text;HDR=Yes;FMT=Delimited\"";
164
+
165
+
166
+
167
+ OleDbConnection con = new OleDbConnection(conString);
168
+
169
+ string commText = "SELECT [ProductID],[ProductName],[UnitPrice],[Discontinued] FROM [" + this.filename + "]";
170
+
171
+ OleDbDataAdapter da = new OleDbDataAdapter(commText, con);
172
+
173
+
174
+
175
+ DataTable dt = new DataTable();
176
+
177
+ da.Fill(dt);
178
+
179
+
180
+
181
+ this.bindingSource1.DataSource = dt;
182
+
183
+ }
184
+
185
+ }
186
+
187
+ }
188
+
189
+ ```
190
+
191
+
192
+
193
+ 結果は以下のようになります。
194
+
195
+
196
+
197
+ ![イメージ説明](3b00e846e3c535fc8c4b9affab98994b.jpeg)
198
+
199
+
200
+
201
+ Schema.ini の型指定を例えば Text を Long にするなど変換できない様に変えれば何らかのエラーが出ると思っていたのですが、出ませんでした。(ただし、DataGridView への表示結果は期待したものにはなりませんが)