C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: csvファイルの保存


(過去ログ 178 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■102343 / inTopicNo.1)  csvファイルの保存
  
□投稿者/ まさ (1回)-(2023/09/05(Tue) 18:41:17)

分類:[.NET 全般] 

C# Windowsフォーム アプリケーション .NET Framework

C#で 保存先を filePath = @"C:\test\Data保存" + DateTime.Now.ToString("yyyyMMdd") + ".csv";

としてデータを保存しています

ある日付のデータを変更しようとエクセルで開いて保存を CSV(コンマ区切り)で保存したのですが

C#から読み込もうとするとエラーが出て読み込めなくなってしまいます

エクセルで読み込んで編集はできないのでしょうか

ちなみにメモ帳で開いて保存した場合は読み込めました

エクセルで編集する場合はどうすればよろしいでしょうか
お願い致します
引用返信 編集キー/
■102344 / inTopicNo.2)  Re[1]: csvファイルの保存
□投稿者/ 魔界の仮面弁士 (3686回)-(2023/09/05(Tue) 19:00:59)
2023/09/05(Tue) 19:23:18 編集(投稿者)

No102343 (まさ さん) に返信
> csvファイルの保存
CSV 形式は比較的曖昧なフォーマットなので、扱う際には
細かい仕様をきちんと詰めておかないと、互換性問題を引き起こします。


> としてデータを保存しています
C# で保存する際の文字コードは何を指定していますか?
Shift_JIS なのか、UTF-8 (BOM なし)なのか、UTF-8 (BOM あり)なのか、あるいはそれ以外なのか。

改行文字は CR ですか。LF ですか。CRLF ですか。あるいはそれらの混在?

先頭行はヘッダー行ですか? それともすべてデータのみですか?

データの両端がダブルクォーテーションで囲まれているかどうか?

それぞれの行の間に改行がありますか? それとも毎行末尾に改行がありますか?
前者は「1行目{改行}2行目」という形式で
後者は「1行目{改行}2行目{改行}」という形式です。


> ある日付のデータを変更しようとエクセルで開いて保存を CSV(コンマ区切り)で保存したのですが
Excel 側で CSV として保存する際に、ファイルの種類に何を選択していますか?
「CSV (コンマ区切り) (*.csv)」なのか、
「CSV UTF-8 (コンマ区切り) (*.csv)」なのか。

このあたりは、Excel のバージョンによって操作が変わってくることが
ありますので、可能であればお使いの Excel のメジャーバージョンも
確認しておきましょう。
https://atmarkit.itmedia.co.jp/ait/articles/2112/20/news026.html


> C#から読み込もうとするとエラーが出て読み込めなくなってしまいます
どのようなコードを実行したときに、何というエラーが出ているのかを
正確に示してもらわないと、幾らなんでも答えようが無いです。

Excel によって編集された結果は正当だったけれど、
C# 側の実装が不十分で読み取れなくなってしまったのか、
あるいは、Excel 側の編集操作に問題があったのか…。


たとえば、Excel 操作で列数が増減したけれど、
C# 側は列数固定の前提だったので、IndexOutOfRangeException になったとか。


> エクセルで読み込んで編集はできないのでしょうか
Excel 側で、
 「セル内で改行」
 「セル内で , を利用」
 「セル内で " を利用」
のいずれかを行いましたか?

Excel 側では、セル内で , や " や改行を使うと、
データの両端がダブルクォーテーションで囲まれます。
また、Excel で作った CSV では、セル内改行は LF になります。

CSV を読み取る側が、そうした CSV 形式に対応した実装に
なっていない場合は、問題が生じるかもしれません。
その場合、読み取る側のプログラムを見直すのか、
それとも運用回避として Excel 操作を見直すのかはケースバイケース。


> ちなみにメモ帳で開いて保存した場合は読み込めました
メモ帳で[表示]-[ステータスバー]を有効にした時に、
右下に表示される文字コードは何になっていますか?
(Excel で編集する前と後で、文字コードが変化していないか)

"ANSI" と表記されていた場合、日本語環境では Shift_JIS 相当です。
"UTF-8" ならば、BOM なし UTF-8 の Unicode で、
"UTF-8 (BOM 付き)" ならば、BOM あり UTF-8 の Unicode です。

他には、"UTF-16 LE" や "UTF-16 BE" などもありますが、
今回は恐らく UTF-16 系では無いでしょうね。


また、メモ帳で保存する際には、[ファイル]-[名前を付けて保存] を
選択したときに画面下部に表示される「文字コード」の欄にもご注意を。


> エクセルで編集する場合はどうすればよろしいでしょうか
ダブルクリックで編集に入るモードもありますが、
より細かい指定を行って開く場合は、Excel の [データ] タブから、
[外部データの取り込み]-[テキスト ファイル]を選択し、
表示されたテキスト ファイル ウィザードにて、プレビューを確認しながら
 1 ページ目
  ファイル形式 → コンマやタブなどで区切られたデータ
  元のファイル → 正しい文字コードを指定。大抵は 932 (日本語 Shift_JIS) か 65001 (Unicode UTF-8) のいずれか。
 2 ページ目
  区切り文字 → カンマ
 3 ページ目
  列のデータ形式 → 標準のままだと取り込めないこともあるので、いったん、すべて「文字列」にしてみる
などとします。ヘッダー行の扱いなどは適宜調整を。


なんにせよ『文字コード』と『フォーマット』の確認が必要です。
Excel で編集すると、元データが 0120 だったものが、
120 や "120" 表記になってしまうこともありますしね。
引用返信 編集キー/
■102345 / inTopicNo.3)  Re[1]: csvファイルの保存
□投稿者/ WebSurfer (2785回)-(2023/09/05(Tue) 19:32:55)
No102343 (まさ さん) に返信

Windows Forms アプリで、CSV ファイルを読み込んで DataGridView に表示し、
それをユーザーが編集し、編集結果を CSV ファイルに書き出すのでよければ、
以下の記事が参考になると思います。

CSV ファイルを DataGridView に表示
http://surferonwww.info/BlogEngine/post/2020/09/11/show-date-in-csv-file-on-datagridview.aspx
引用返信 編集キー/
■102346 / inTopicNo.4)  Re[1]: csvファイルの保存
□投稿者/ radian (142回)-(2023/09/06(Wed) 09:50:31)
2023/09/06(Wed) 13:52:13 編集(投稿者)

No102343 (まさ さん) に返信
> C# Windowsフォーム アプリケーション .NET Framework
>
> C#で 保存先を filePath = @"C:\test\Data保存" + DateTime.Now.ToString("yyyyMMdd") + ".csv";
>
> としてデータを保存しています
>
> ある日付のデータを変更しようとエクセルで開いて保存を CSV(コンマ区切り)で保存したのですが
>
> C#から読み込もうとするとエラーが出て読み込めなくなってしまいます

単純に、C#側のCSV読み込み処理の実装が正しくないのでは?
エラー内容、CSVの実データ、CSV読み込み処理のソースいずれも載っていないので、
具体的なアドバイスはできません。

Web上の記事の自作CSV読み込み処理のサンプルを適当に拾ってきた場合、
実装が簡易的で、RFCに沿った実装ではないものが殆どなので、
CSVHelperなどのCSV用ライブラリを使ってみてください。

[【C#】CsvHelperでCSVファイルを読み込むする方法]
https://marunaka-blog.com/csharp-csvhelper-csv-read-write/4690/

引用返信 編集キー/
■102347 / inTopicNo.5)  Re[2]: csvファイルの保存
□投稿者/ まさ (2回)-(2023/09/06(Wed) 11:52:04)
WebSurferさん、radianさん
ありがとうございます

すみませんコードも載せずに質問してしまいまして

書き込む時は、日付、時間、データ1(0.0001とか)、データ2(100とか)
private string filePath = @"C:\test\Data保存\" + DateTime.Now.ToString("yyyyMMdd") + ".csv";
private void SaveDataToCSV(string date1, string date2, string data1,string data2)
        {
            try
            {
                using (StreamWriter sw = File.AppendText(filePath))
                {
                    sw.WriteLine($"{date1},{date2},{data1},{data2}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }

読み込む時は日付毎にまとめています

private void ParseCSVFile(string filePath, Dictionary<DateTime, double> dailyTotals)
        {
            foreach (string line in File.ReadLines(filePath))
            {
                string[] fields = line.Split(','); // カンマで分割
                string dateString = fields[0];// 日付を取得します(日付がA列にある場合)
                DateTime date;

                if (DateTime.TryParseExact(dateString, "yyyy/MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
                {
                    double value;
                    if (double.TryParse(fields[2], out value)) // C列値
                    {
                        if (dailyTotals.ContainsKey(date))// 日付毎に集計
                        {
                            dailyTotals[date] += value;
                        }
                        else
                        {
                            dailyTotals[date] = value;
                        }
                    }
                }
            }
        }

以上になります
宜しくお願い致します

引用返信 編集キー/
■102348 / inTopicNo.6)  Re[3]: csvファイルの保存
□投稿者/ まさ (3回)-(2023/09/06(Wed) 13:15:33)
魔界の仮面弁士さん丁寧なお答えありがとうございました
引用返信 編集キー/
■102349 / inTopicNo.7)  Re[3]: csvファイルの保存
□投稿者/ WebSurfer (2786回)-(2023/09/06(Wed) 13:42:33)
No102347 (まさ さん) に返信

そのコードのどの行でエラーが出ていて、エラーメッセージはどういうものかを
省略せずに書きましょう。

エラーメッセージは非常に重要な情報で、場合によってはそれだけ分かれば原因
と対処方法が回答できるケースが多いと認識してください。
引用返信 編集キー/
■102350 / inTopicNo.8)  Re[3]: csvファイルの保存
□投稿者/ radian (143回)-(2023/09/06(Wed) 14:27:26)
2023/09/06(Wed) 14:38:27 編集(投稿者)
No102347 (まさ さん) に返信
> 書き込む時は、日付、時間、データ1(0.0001とか)、データ2(100とか)
> private string filePath = @"C:\test\Data保存\" + DateTime.Now.ToString("yyyyMMdd") + ".csv";
> private void SaveDataToCSV(string date1, string date2, string data1,string data2)
>         {
>             try
>             {
>                 using (StreamWriter sw = File.AppendText(filePath))
>                 {
>                     sw.WriteLine($"{date1},{date2},{data1},{data2}");
>                 }
>             }
>             catch (Exception ex)
>             {
>                 MessageBox.Show("Error: " + ex.Message);
>             }
>         }
> 
> 読み込む時は日付毎にまとめています
> 
> private void ParseCSVFile(string filePath, Dictionary<DateTime, double> dailyTotals)
>         {
>             foreach (string line in File.ReadLines(filePath))
>             {
>                 string[] fields = line.Split(','); // カンマで分割
>                 string dateString = fields[0];// 日付を取得します(日付がA列にある場合)
>                 DateTime date;
> 
>                 if (DateTime.TryParseExact(dateString, "yyyy/MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
>                 {
>                     double value;
>                     if (double.TryParse(fields[2], out value)) // C列値
>                     {
>                         if (dailyTotals.ContainsKey(date))// 日付毎に集計
>                         {
>                             dailyTotals[date] += value;
>                         }
>                         else
>                         {
>                             dailyTotals[date] = value;
>                         }
>                     }
>                 }
>             }
>         }
> 
> 以上になります

実際に

2015/02/13,08:34,1.2345,123
2016/03/13,11:06,2.2345,223

のようなCSVデータをExcel編集前後でParseCSVFileで読ませてみましたが、
別段エラーは発生しませんでした。
ただし、Excel編集後はCSVの内容がDictionaryに入りませんね。
TryParseExactで、日付フォーマットを "yyyy/MM/dd" で決め撃ちしてるから、
2016/03/13が2016/3/13 となったりしたら、そこで失敗します。

[カスタム日時形式文字列]
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings
フォーマットに何を指定すればよいのかは、ここを見て自分で考えてみてください。

Excel編集前後で、自分の作成したCSVデータがどう変化するか突き合わせたり、
デバッグ実行して読み込み処理でブレークポイント設定して調べてみれば、原因はすぐ判る筈です。
きちんと自分でデバッグしましょう。

[超初心者でもわかるデバッグ方法]
https://learn.microsoft.com/ja-jp/visualstudio/debugger/debugging-absolute-beginners?view=vs-2022&tabs=csharp

ただ、結論から言うとCSV処理は真面目に実装するとそれなりに面倒な処理なので、私はCSV処理の自作自体をおすすめしません。
CsvHelperを使用出来るなら使用してください。

引用返信 編集キー/
■102351 / inTopicNo.9)  Re[3]: csvファイルの保存
□投稿者/ 魔界の仮面弁士 (3687回)-(2023/09/06(Wed) 14:28:35)
2023/09/06(Wed) 14:36:02 編集(投稿者)

No102347 (まさ さん) に返信
CSV ファイルの文字コードは何を想定していますか?

No102344 で示したように、 Excel の「テキスト ファイル ウィザード」を通じて
開けば任意の文字コードを指定できるので、編集時の文字化けを防げますが、
*.csv ファイルをダブルクリックして Excel を起動した場合の動作はこんな感じ。
※このあたりの動作は、Excel のバージョンにもよっても変わります。

 (1) Shift_JIS のファイル
    大抵は正しく読み込まれます。
    (ファイルの内容や直前の操作次第では、稀に、誤って別の文字コードと解釈されることもある)
 (2) BOM あり UTF-8 のファイル
    正しく読み込まれます。
 (3) BOM 無し UTF-8 のファイル
    Shift_JIS ファイルと誤解されることがあります。
    その場合、半角の数字やアルファベットは問題無いですが、
    半角カナや平仮名/片仮名/漢字等は文字化けすることになります。


> すみませんコードも載せずに質問してしまいまして
コードの提示もそうですが、質問する上では、
その中のどの行で、何というエラーが発生していて、
その時の変数の値は何になっていたのかまでを明確にしましょう。


> using (StreamWriter sw = File.AppendText(filePath))
File.AppendText メソッドは、文字コードが「BOM 無しの UTF-8」であることが前提となります。
その点は想定通りでしょうか。
(filePath が存在しない場合、AppendText の時点で 0 バイトのファイルが生成されます)

それ以外の文字コード(たとえば US-ASCII や Shift_JIS)のファイルを相手にする場合は、
 using (StreamWriter sw = new StreamWriter(filePath, true, エンコーディング))
を使って追記するようにしてみてください。


>  sw.WriteLine($"{date1},{date2},{data1},{data2}");
data1 などの引数文字列に「カンマや改行が含まれていた場合」の処置が省略されているようですが、
そういった文字の混入が無いことが事前に明確である場合には、省略しても問題無いですね。
事前のデータチェックが無く、任意の文字列が入ってくる前提の場合は、このコードだと NG ですが…。


> private void ParseCSVFile(string filePath, Dictionary<DateTime, double> dailyTotals)
どちらも null 不可な引数のようなので、C#7.3 以下のバージョンでは
 Debug.Assert(dailyTotals == null);
あるいは
 if (dailyTotals == null) { throw new ArgumentNullException(nameof(dailyTotals)); }
などのように、ガード節を入れておいた方がより堅牢です。ガード節は必須では無いですけれどね。


> 読み込む時は日付毎にまとめています
このコードだと、A 列が日付値で、C 列が空欄だった場合、
その日付は Dictionary に登録されない仕様ですね。


>  if (double.TryParse(fields[2], out value)) // C列値
ここの処理が危なっかしいですね。

列数が 3 以上ある場合は良いですが、列数がそれ未満の場合、
[2] へのアクセス時に IndexOutOfRangeException エラーになりそうです。
事前に fields.Length をチェックする仕組みも設けておく方が良いでしょう。

列数の減少理由としては、たとえばセル内改行などでフォーマットが崩れた場合とか、
メモ帳で編集時に誤ってカンマを削ってしまったなどのパターンが考えられます。



-- 以下蛇足 --

日付処理では InvariantCulture を指定していた一方、
数値化の処理には、カルチャ指定が省略されているという非対称性が気になりました。

数値書式もカルチャ依存であるため、変換結果が左右される可能性があります。
(とはいえ日本語環境では、日付ほど問題になることは少ないのですが)


それから、double.TryParse は "1,2,3.4" といった文字列や、"+1e-3" などの指数表記も有効です。
さらには、"NaN" の非数表記、"-∞" などの無限大表記も true になるのでご注意を。
それらが混入するケースは稀なので、あまり気にしなくても良いとは思いますが念のため。
引用返信 編集キー/
■102352 / inTopicNo.10)  Re[3]: csvファイルの保存
□投稿者/ kiku (373回)-(2023/09/06(Wed) 14:54:42)
2023/09/06(Wed) 15:25:03 編集(投稿者)

No102347 (まさ さん) に返信
> WebSurferさん、radianさん
> ありがとうございます
> すみませんコードも載せずに質問してしまいまして
> 書き込む時は、日付、時間、データ1(0.0001とか)、データ2(100とか)

radianさんも指摘していますが、
下記の事実を確認頂くと理解が深まると思います。

下記①のファイルをダブルクリックでExcelに読み込み、
何も編集せずに、
ExcelでCSV(コンマ区切り)で保存した場合、
下記②のようになります。
見てもらえばわかりますが、0が勝手に省略されます。
これはExcel側の仕様です。
※このようにならないように読み込むことは可能です。==>ここは弁士さんが触れています。


11111111,2013/05/06
22222222,2013/15/16


11111111,2013/5/6
22222222,2013/15/16

引用返信 編集キー/
■102353 / inTopicNo.11)  Re[4]: csvファイルの保存
□投稿者/ 魔界の仮面弁士 (3688回)-(2023/09/06(Wed) 16:03:55)
No102350 (radian さん) に補足
> TryParseExactで、日付フォーマットを "yyyy/MM/dd" で決め撃ちしてるから、
> 2016/03/13が2016/3/13 となったりしたら、そこで失敗します。

これについては、DateTime.TryParseExact のフォーマット指定部で、
"yyyy/MM/dd" の代わりに "yyyy/M/d" を渡せば、どっちもいけそう。


スラッシュ以外の区切り文字や、区切り無しyyyyMMdd などにも対応させたいなら
 private static readonly string[] dateFormats = {
  "yyyyMMdd",
  @"yyyy\/M\/d",
  @"yyyy\-M\-d",
  @"yyyy\.M\.d",
 };
などの複数パターンを用意しておき、
 if (DateTime.TryParseExact(dateString, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
のように指定するという手もあり。
引用返信 編集キー/
■102358 / inTopicNo.12)  Re[5]: csvファイルの保存
□投稿者/ radian (145回)-(2023/09/07(Thu) 09:28:57)
No102353 (魔界の仮面弁士 さん) に返信
> ■No102350 (radian さん) に補足
>>TryParseExactで、日付フォーマットを "yyyy/MM/dd" で決め撃ちしてるから、
>>2016/03/13が2016/3/13 となったりしたら、そこで失敗します。
>
> これについては、DateTime.TryParseExact のフォーマット指定部で、
> "yyyy/MM/dd" の代わりに "yyyy/M/d" を渡せば、どっちもいけそう。

必要最低限の事は自分で調べて欲しくてカスタム日時形式文字列のリンクを張っていたので、
出来れば意図を汲み取ってほしかった…(´・ω・`)

引用返信 編集キー/
■102379 / inTopicNo.13)  Re[4]: csvファイルの保存
□投稿者/ まさ (4回)-(2023/09/12(Tue) 22:02:03)
すみません
みなさんのおかげで解決いたしました
ありがとうございました
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -