質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

5回答

4488閲覧

C#でExcelで作成されたCSVファイルを読みこみ、配列に格納したいです。

keion327

総合スコア12

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2018/11/07 00:53

編集2018/11/08 02:59

C#を始めて1か月も経たない初心者です。初質問で緊張しています。

C#でExcelで作成された"Item.csv"というファイルを読み込み、配列に格納するプログラムをご教授頂きたいです。

また、Excelで作成されたCSVファイルを読み込む場合、行全体だけでなく、行列を指定することは可能なのでしょうか?

例えば一番下の行の"A75004M05"を指定し、この文字であれば次のダイアログ画面へ行く。
それ以外なら進めないといった処理を行います。

その際に一番下の行の"A75004M05"を抽出したいです。

初心者プログラマーのため、質問が理解できなかったり、足りない場合は申し訳ないです。

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

C#

1 public void ReadCSV1(string [] args) 2 { 3 var parser = new TextFieldParser(@"Item*.csv", Encoding.GetEncoding("Shift_JIS")); 4 using (parser) 5 { 6 parser.TextFieldType = FieldType.Delimited; 7 parser.SetDelimiters(","); 8 9 parser.HasFieldsEnclosedInQuotes = true; 10 11 parser.TrimWhiteSpace = false; 12 while (!parser.EndOfData) 13 { 14 string[] row = parser.ReadFields(); 15 foreach (string field in row) 16 { 17 Console.Write(field + "\t"); 18 } 19 Console.WriteLine(); 20 } 21 } 22 Console.ReadKey(); 23 24 } 25

試したこと

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

keion327

2018/11/07 00:55

画像を載せたはずなのですが、掲載されていませんでした。編集します。
keion327

2018/11/07 01:08

追加させて頂きました。
Zuishin

2018/11/07 01:12

CSV の実態はテキストファイルです。Excel の実行画像ではなく、CSV をテキストエディタで開いてその内容を質問に追記した方が適切な回答が得られやすいと思います。その際コードブロックを使ってください。
Zuishin

2018/11/07 01:17

YAmaGNZ さんへのコメントで思ったのですが、多分これは CSV ではなく INI ですね?
keion327

2018/11/07 02:02

本当にありがとうございます。Zuishin様含めみなさん迅速な回答で初めての質問で不安だったのですが非常に助かっております。
keion327

2018/11/07 02:03

質問を編集しましたので、お時間がありましたらよろしくお願い致します。
papinianus

2018/11/07 02:04

csvでないならexcelで開いても無益です。テキストエディタで開いて、それをコードとして「```」で囲んではりつけていただくことはできませんか?
keion327

2018/11/07 02:07

毎度毎度迅速なご対応本当に感謝しております!拡張子が一応.csvなのですがそれでもだめでしょうか?
keion327

2018/11/07 02:11

覚えることが多すぎて頭がパニック起きてます
papinianus

2018/11/07 02:12

「だめ」をどう理解するかにもよりますが、内容がcsvの仕様にあっていないものを、excelやtextfieldparserで読んでも嬉しいことがありません。特にexcelは区切り文字などが画面上見えなくなるので、回答に繋げることが難しくなります。右クリックしたメニューでプログラムから開く、でメモ帳を選択するか、メモ帳にドラッグドロップすることは不可能ですか?
papinianus

2018/11/07 02:14

まず覚えるべきは、これはCSVではない、ということと、excelで開いてちゃんと四角形にデータが見えないやつは、エディタ(vscode、なければメモ帳でも)で開いてみる。の2つです。
tamoto

2018/11/07 02:16

セルに分割配置されてるのでもっと大きい単位でカンマ区切りの可能性もあります……? どちらにせよ「テキスト」としてのデータ内容とフォーマットが確認できないことには回答のしようがないタイプの問題ですね。
keion327

2018/11/07 02:28

メモ帳に変えたらカンマがたくさん出てきました。この中のInit,1の1を指定して、この処理が終わったら次はWAIT_Tの100を読むといったようなことをしたいです。
Zuishin

2018/11/07 02:58

CSV ではあるんですね。このデータを処理することは可能です。しかしどうしてみなさん渋い顔なのかと言うと、「このデータを処理できるプログラム」を作ったからと言って「このデータが更新されても処理できるプログラム」にはならない可能性があるからです。データがどのように変化するのか(新しい項目が増えることがあるのか、グループ名は固定なのかなど)の詳細がわからなければ、変化に対応することはできません。今まではどうやって処理していて、それをどうして何も知らされていない人が担当するようになったのでしょう? 今までのやり方ではいけませんか?
Zuishin

2018/11/07 03:00

と書いている間に内容がガラッと変わりましたが、ここまで変わるなら処理は不可能というほかありません。
papinianus

2018/11/07 03:10

いやまじで不可能でしょ。最初にZuishinさんが仰ってたことを2回目の繰り返しになりますが、書きますけど、それをコードブロックに貼れないのですか?最初のexcelの図とテキストでは[テスト項目]がなくずれてますし、今度は仕様が全然違う。shutdownやsnlenやinitやwaitはどうしたのですか
papinianus

2018/11/07 03:11

私の回答に寄せられたコメントからすると質問者様にこのファイルを渡しているオヤブンがcsvでないものをexcelに読ませた結果としてcsvになっているのだろうと思います。こんなiniっぽいcsv作る処理をかくなんてまともじゃないと思うので。
papinianus

2018/11/07 03:20

当初質問に貼ってたのは、秀丸で開いている、Scan.iniじゃないですよね…みんなiniだって言ってたよね…
Zuishin

2018/11/07 03:20

もしかしてコピペ知りませんか? メモ帳でテキストファイル(この場合 CSV)を開いたら、Ctrl+A ですべて選択し、Ctrl+C でクリップボードにコピーします。そして質問を編集し、Ctrl+V で貼り付け、貼り付けたデータをマウスでドラッグして選択し、<code> というボタンを画面から探して押してください。
guest

回答5

0

多分、読み込んだ結果の1項目(例えばrow[1])が"S/N_LEN=11"となっているかと思います。
その位置が固定なのであれば、指定行、指定列の値を"="でsplitするなどで対応できるのではないでしょうか?

String.Splitに関してはこちらを参考にしてみてください。

上記でsplitのほうを紹介しましたが、"="でも分割していいよという話であれば下記のようにデリミタを設定すれば、"S/N_LEN=11"というデータがあった場合、"S/N_LEN"と"11"に分かれるかと

C#

1parser.SetDelimiters(new string[]{ "," , "=" });

他の方も言っておられますが、iniファイルとして扱ったほうがよろしいかと思われる内容のファイルだと思います。

追記

なんとなく考え方の勘違いをされている気がします。
「最後の行の2列目を指定して、CSVファイルを読み込む」
のではなく、
「CSVファイルを全部(処理によっては行ごと)読み込んでから、指定行、指定列のデータを配列等から取り出す」
です。
提示されているソースにて、CSVファイルを1行づつ読み込めますので、1行読み込んだところでrow[1]=="A75004M05"とでも判断すればよろしいかと思います。

投稿2018/11/07 01:08

編集2018/11/07 03:24
YAmaGNZ

総合スコア10242

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

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

keion327

2018/11/07 01:11

ありがとうございます。 例えば"ShutDown=OFF"の"OFF"を指定する場合はどのように編集したら良いでしょうか。
keion327

2018/11/07 02:04

ありがとうございます。質問内容と画像をもう少し分かりやすいのに入れ替えました。
YAmaGNZ

2018/11/07 02:18

例えで出しておられる「15行目のE列」などはどのファイルを読み込んだとしても固定なのでしょうか? それによって、プログラムで読み込んだ行をカウントして15行目ならという判断を行えばいいのか、別の判断をすればいいのか変わってきます。 まずはプログラムにて全部読み込んだ結果から、ここからどうしたいかを考えたほうがよろしいかと思います。
keion327

2018/11/07 02:30

固定ではありません。画像を入れ替えましたが、Init,1の1を読込み、それを使用した処理を終えたら次はWAIT_Tの100を読むといった処理をしていきます。説明下手すぎて申し訳ありません。
YAmaGNZ

2018/11/07 02:39

このファイルの仕様を明確にしないとご希望の処理は行えないと思います。 例えば、「Init,1の1を読み込み」とのことですが、これはどこを判断すればよいのか明確にする必要があります。 必ず11行目から始まるのか、[TestItem]と書かれた行の2行後からなのか 列に関しても、必ず5列目なのかどうかなど 少なくとも、全て日本語で明確に説明できる必要があります。そうでないとプログラムを作成できません。 ですので、作業としてはまず、ファイルの仕様を(上司等をまきこんで)明確にすることから始めてください。
keion327

2018/11/07 05:51

色々とありがとうございました。 なんとか今頑張っております。 ちなみに上記の画像の.csvで以下の処理を行った場合、row[]が格納されたTestDlg.mSettingData4[]はそれぞれ何が入っているのでしょうか?(エラー出すぎてデバッグできません) public void ReadCSV1(string[] args) { StringBuilder sb = new StringBuilder(1024); var parser = new TextFieldParser(@"Stand_Item.csv", Encoding.GetEncoding("Shift_JIS")); using (parser) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); parser.HasFieldsEnclosedInQuotes = true; parser.TrimWhiteSpace = false; while (!parser.EndOfData) { string[] row = parser.ReadFields(); TestDlg.mSettingData4[0] = row[0]; TestDlg.mSettingData4[1] = row[1]; TestDlg.mSettingData4[2] = row[2]; TestDlg.mSettingData4[3] = row[3]; for (int n = 0; n < row.Length; n++) Console.Write(" "); Console.WriteLine(" "); } } Console.ReadKey(); }
YAmaGNZ

2018/11/07 06:15

焦らずにゆっくり進めてください。 コンパイルエラーが出るのであれば、まずはそれを修正することが先かと思います。 提示ソースの場合、TestDlg.mSettingData4へ代入する部分をコメントアウトしてもrowの配列の中身は確認できるかと思います。 提示されたCSVですと、row[0]には日時、row[1]には"A75004M05"などの文字列、それ以降はさまざまな数字が格納されるかと思います。
keion327

2018/11/07 06:28

本当にありがとうございます。 row[0]やrow[1]はこの状態だと最後の行のみしか格納されていないのでしょうか? 本当は最初から最後の行まで格納したいです。 難しいですね。。。
YAmaGNZ

2018/11/07 06:34

「C# CSV 読み込み 配列」などで検索して、他の人のコードを参考にしてみてください。 現状のソースですと、1行読んでrowに格納を繰り返すので、最終的に最後の行の値のみが残るのですが、rowの定義がループ内なので、ループを抜けるとスコープから外れてrow自体がなくなります。
guest

0

ここを参考にしたのでしょうか。
年齢が25歳の行のときだけOKとするようにかいてみました。

csharp

1using System; 2using System.Linq; 3using System.Text; 4using Microsoft.VisualBasic.FileIO; 5 6namespace CsvParser 7{ 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 var parser = new TextFieldParser(@"C:\work\test.csv", Encoding.GetEncoding("Shift_JIS")) 13 { TextFieldType = FieldType.Delimited, HasFieldsEnclosedInQuotes = true, TrimWhiteSpace = false, Delimiters = new[] { "," } }; 14 using (parser) 15 { 16 var header = parser.ReadFields().Select((field, index)=>new { field, index}).ToDictionary(a => a.field, a => a.index); 17 // ファイルの終端までループ 18 while (!parser.EndOfData) 19 { 20 // フィールドを読込 21 string[] row = parser.ReadFields(); 22 if(row[header["年齢"]] == "25") { Console.Write("OK"); } 23 Console.WriteLine("←"); 24 } 25 } 26 Console.ReadKey(); 27 } 28 } 29}

--- iniについて
ライブラリつかってパースはもしかしたら今はつらいのかもしれないので、ご提示の要件からするともう単純にテキスト比較すればいいんじゃないと思い、こういうコードを書いてみました。

csharp

1using System; 2using System.Text; 3using System.IO; 4 5namespace CsvParser 6{ 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 var txt = File.ReadAllText(@"C:\work\test.ini", Encoding.GetEncoding("shift_jis")); 12 if(txt.Contains("S/N_LEN=11")) { return; } 13 if(txt.Contains("ShutDown=OFF")) { return; } 14//ここから処理を継続すれば、↑のパターンを除外できます 15 } 16 } 17}

投稿2018/11/07 00:58

編集2018/11/07 01:28
papinianus

総合スコア12705

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

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

keion327

2018/11/07 01:07

CSVファイルを読込み、中の"S/N_LEN=11"の11を読込み、もし11なら進み、11以外なら進めないというソースを作成したかったです。
papinianus

2018/11/07 01:20

書き直しはしたものの、Zuishinさんも書いておられますが、これはそもそもCSVではないですね https://note.dokeep.jp/post/csharp-inifile-read/ こういう記事を参考にiniとしてパースしたほうがいいのではないかと思います
keion327

2018/11/07 02:05

ありがとうございます。このCSVファイルを使用してやってくれと言われました。質問内容と画像を入れ変えました。よろしくお願い致します。
papinianus

2018/11/07 02:15

その指示者さんが、これをcsvだと思って、"Item.csv"に変換して渡してくるのだとしたら、ヤバいです。他に頼れる先輩はいませんか?
keion327

2018/11/07 02:33

みなさんC++しかやっていないみたいでC#は分からないらしいです。。。メモ帳に差し替えてみました。例えばINIT,1の1を指定し、それを使用した処理を終えたら次はWAIT_T,100の100を読むといったように順番にそれらを使用して処理していくみたいです。
papinianus

2018/11/07 03:13

C++は関係ないです。これを新人?である質問者様にcsvで頼むと言っている職場は危険です
keion327

2018/11/07 05:58

色々とありがとうございました。 なんとか今頑張っております。 ちなみに上記の画像の.csvで以下の処理を行った場合、row[]が格納されたTestDlg.mSettingData4[]はそれぞれ何が入っているのでしょうか?(エラー出すぎてデバッグできません) public void ReadCSV1(string[] args) { StringBuilder sb = new StringBuilder(1024); var parser = new TextFieldParser(@"Stand_Item.csv", Encoding.GetEncoding("Shift_JIS")); using (parser) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); parser.HasFieldsEnclosedInQuotes = true; parser.TrimWhiteSpace = false; while (!parser.EndOfData) { string[] row = parser.ReadFields(); TestDlg.mSettingData4[0] = row[0]; TestDlg.mSettingData4[1] = row[1]; TestDlg.mSettingData4[2] = row[2]; TestDlg.mSettingData4[3] = row[3]; for (int n = 0; n < row.Length; n++) Console.Write(" "); Console.WriteLine(" "); } } Console.ReadKey(); }
papinianus

2018/11/07 06:07

エラーが出すぎるとは?visual studioですよね?実行時エラーがそんなに出ますか? エラーが出ているのであれば、何とも言えません。 エラーがなければ、Console.ReadKey()の時点で、TextDlg.mSettingData4は、{"2013なんとかかんとか", "A75004M05", "1", "95"}になると推測します。 無関係なsbとかがありますが、そういう分からないのを手当たり次第入れるのはやめましょう。無関係なヤツの無関係なエラーになんて対処できないでしょう。
guest

0

自己解決

みなさん本当にありがとうございました。

この案件未熟ながら頑張ります。

機会がありましたらまたよろしくお願い致します。

投稿2018/11/08 00:44

keion327

総合スコア12

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

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

0

質問欄が長すぎるのでこちらに。

例えば一番下の行の"A75004M05"を指定し、この文字であれば次のダイアログ画面へ行く。

それ以外なら進めないといった処理を行います。
その際に一番下の行の"A75004M05"を抽出したいです。

作りたいものは何ですか?
ダイアログとは何ですか?
ダイアログはnewできますか?
ダイアログにデータを渡すことで要件を満たしますか?
進めないというのはどういう画面処理ですか?
指定するのは誰で、抽出するのは誰ですか?
指定する行為が画面での操作なのであれば、あらかじめ"A75004M05"は決まっているのではないですか?都度抽出するのですか?
一番下の行の左から2列目を抽出すればよいのですか? ←ここに対応したコードを書いてます。

回答欄なんで回答をはっときます
CSVであっても、ヘッダ行がないので、もう2番目、ということ以外の手掛かりはない。

csharp

1// 一番下 2var A75004M05 = File.ReadLines(@"C:\work\Item.csv", Encoding.GetEncoding("shift_jis")).Last().Split(',').ElementAt(1);

csharp

1//Aなんちゃらが事前にわかっている場合の該当する一行のデータを取得する 2var A75004M05Line = File.ReadLines(@"C:\work\Item.csv", Encoding.GetEncoding("shift_jis")).SkipWhile(line => !line.Contains("A75004M05")).ElementAt(0);

投稿2018/11/07 03:18

編集2018/11/07 03:25
papinianus

総合スコア12705

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

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

keion327

2018/11/07 05:59

色々とありがとうございました。 なんとか今頑張っております。 ちなみに上記の画像の.csvで以下の処理を行った場合、row[]が格納されたTestDlg.mSettingData4[]はそれぞれ何が入っているのでしょうか?(エラー出すぎてデバッグできません) public void ReadCSV1(string[] args) { StringBuilder sb = new StringBuilder(1024); var parser = new TextFieldParser(@"Stand_Item.csv", Encoding.GetEncoding("Shift_JIS")); using (parser) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); parser.HasFieldsEnclosedInQuotes = true; parser.TrimWhiteSpace = false; while (!parser.EndOfData) { string[] row = parser.ReadFields(); TestDlg.mSettingData4[0] = row[0]; TestDlg.mSettingData4[1] = row[1]; TestDlg.mSettingData4[2] = row[2]; TestDlg.mSettingData4[3] = row[3]; for (int n = 0; n < row.Length; n++) Console.Write(" "); Console.WriteLine(" "); } } Console.ReadKey(); }
guest

0

データ起こししました

,,,,,,,,,,, S/N_LEN=11,,,,,,,,,,, DATABase=OFF,,,,,,,,,,, '''''''''''''''' ImageFolder=\192.168.200.11\file_share\Scanner_Test,,,,,,,,,,, ScanWaitTime=2.0,,,,,,,,,,, ShutDown=Off,,,,,,,,,,, Operator=Off,,,,,,,,,,, ,,,,,,,,,,, [TextItem],,,,,,,,,,, 番号,測定項目名,コメント,測定コマンド,,,,,,,,,,, ,,,INIT,1,,,,,,, ,,,WAIT_T,100,,,,,,, ,,,DISP,,,,,,,, ,,,MEAS,BLUR,2,48,1,,,,

csharp

1using System; 2using System.Linq; 3using System.Collections.Generic; 4using System.Text; 5using System.IO; 6 7namespace CsvParser 8{ 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 var txt = File.ReadLines(@"C:\work\Item.csv", Encoding.GetEncoding("shift_jis")).ToArray(); 14 if (IsShutDownOff(txt)) { Console.WriteLine("中断(シャットダウンオフ)"); Console.ReadKey(); return; } 15 if (IsSerialNumberLength11(txt)) { Console.WriteLine("中断(S/N_LEN=11)"); Console.ReadKey(); return; } 16 var initVal = findNextOfKey(txt, "INIT"); 17 var waitVal = findNextOfKey(txt, "WAIT_T"); 18 Console.WriteLine($"INIT = {initVal} , WAIT_T = {waitVal}"); 19 } 20 static bool IsShutDownOff(IEnumerable<string> lines) => lines.Any(line => line.Contains("Shutdown=OFF")); 21 static bool IsSerialNumberLength11(IEnumerable<string> lines) => lines.Any(line => line.Contains("S/N_LEN=11")); 22 static string firstLineWhichHas(IEnumerable<string> lines, string key) => lines.FirstOrDefault(line => line.Contains(key)); 23 static string getNextOf(string line, string key) => line?.Split(',').SkipWhile(col => col.Trim().ToLower() != key.ToLower()).ElementAt(1).Trim() ?? string.Empty; 24 static string findNextOfKey(IEnumerable<string> lines, string key) => getNextOf(firstLineWhichHas(lines, key), key); 25 } 26}

投稿2018/11/07 02:44

編集2018/11/07 03:08
papinianus

総合スコア12705

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

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

papinianus

2018/11/07 03:13

起こしたデータも書いたコードも無になった。
keion327

2018/11/07 05:59

めちゃくちゃなことして申し訳ありません。 ちなみに上記の画像の.csvで以下の処理を行った場合、row[]が格納されたTestDlg.mSettingData4[]はそれぞれ何が入っているのでしょうか?(エラー出すぎてデバッグできません) public void ReadCSV1(string[] args) { StringBuilder sb = new StringBuilder(1024); var parser = new TextFieldParser(@"Stand_Item.csv", Encoding.GetEncoding("Shift_JIS")); using (parser) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(","); parser.HasFieldsEnclosedInQuotes = true; parser.TrimWhiteSpace = false; while (!parser.EndOfData) { string[] row = parser.ReadFields(); TestDlg.mSettingData4[0] = row[0]; TestDlg.mSettingData4[1] = row[1]; TestDlg.mSettingData4[2] = row[2]; TestDlg.mSettingData4[3] = row[3]; for (int n = 0; n < row.Length; n++) Console.Write(" "); Console.WriteLine(" "); } } Console.ReadKey(); }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問