|
■No103819 (shiro さん) に返信
> Pillarは地下の杭などに使われます。
> 上部構造の柱はcolumnが使われます。
勉強になります! ( ..)φ
> Type Index X Y Stiff
> C 1 40 40
> C 2 40 80
> C 3 80 80
> C 4 80 40
> W 1 {X=0,Y=0} {X=0,Y=0} 2.5
> W 2 {X=0,Y=0} {X=0,Y=0} 2.5
> W 3 {X=0,Y=0} {X=0,Y=0} 2.5
> W 4 {X=0,Y=0} {X=0,Y=0} 2.5
> W 5 {X=40,Y=40} {X=40,Y=80} 2.5
> W 6 {X=40,Y=80} {X=80,Y=80} 2.5
> W 7 {X=80,Y=80} {X=80,Y=40} 2.5
> W 8 {X=80,Y=40} {X=40,Y=40} 2.5
Point 構造体のまま出力すると、「{x,y}」形式のカンマ付き文字列が生成されるので、
タブ区切りテキストならまだしも、CSV(カンマ区切りテキスト)とは相性が悪いかと思います。
このフォーマットにするなら、ヘッダー行は
writer.WriteLine("Type,Index,X,Y,Stiff")
ではなく、
writer.WriteLine("Type,Index,X1,Y1,X2,Y2,Stiff")
に変更することを提案します。
データ部については
For Each pillar In pillarList
writer.WriteLine($"C,{pillar.Index},{pillar.X},{pillar.Y}")
Next
For Each wall In wallList
writer.WriteLine($"W,{wall.Index},{wall.StartPoint},{wall.EndPoint},{wall.Stiffness}")
Next
ではなく、
For Each pillar In pillarList
writer.WriteLine($"C,{pillar.Index},{pillar.X},{pillar.Y},,,")
Next
For Each wall In wallList
writer.WriteLine($"W,{wall.Index},{wall.StartPoint.X},{wall.StartPoint.Y},{wall.EndPoint.X},{wall.EndPoint.Y},{wall.Stiffness}")
Next
のように空値の列を追加することで、すべての行で列数を同一に揃えます。
Type=W の方は列数が多いので、まとめて一行で示す代わりに
For Each wall In wallList
writer.Write($"W,{wall.Index}")
writer.Write($",{wall.StartPoint.X},{wall.StartPoint.X}")
writer.Write($",{wall.EndPoint.X},{wall.EndPoint.X}")
writer.Write($",{wall.Stiffness}")
writer.WriteLine()
Next
のように分けて記述すると言う手もあるかと。
> ' ファイルパスを指定
> Dim filePath As String = "export.csv"
> Using writer As New StreamWriter(filePath)
カレントディレクトリによって、出力先がぶれることになるので、
実際の運用では、フルパスが渡されるようにした方が良いかも。
> 気になるのがWの1〜4が出力されていることでした。
> 関係ない出力だと思うのですが。
恐らく、wallList の中身が 4 件ではなく、8 件あったというだけのことだと思います。
その処理において、wallList.Add(newWall) は何回呼び出されていますか?
たとえば、MouseUp は「壁」モードだけでなく「柱」モードでも発生しますが、
壁モードでは無い時にまで、wallList に Add していないか確認してみてください。
また、ExportToCSV の処理にブレークポイントを貼って一時停止させ、
出力時点での wallList 変数の中身をデバッガで確認してみましょう。
(ローカルウィンドウ、ウォッチ、イミディエイトなど)
<蛇足情報>
Double 値を文字列として出力する場合、書式指定子を付けておかないと
・OS の地域設定によって、小数点記号などが異なる
という問題があります。
たとえば欧州圏では、小数に「.」ではなく「,」を使う国が多いため(fr-FR など)、
CSV との相性が悪く、そのままだとトラブルの元になりかねません。
OS 設定によって、ファイル処理が変化してしまうことを避けるため、
地域依存の無い書式指定として
'writer.Write($",{wall.Stiffness}") '標準書式(地域設定に依存)
writer.Write($",{wall.Stiffness:R}") 'ラウンドトリップ書式
を使うか、あるいはアプリの既定のカルチャを、明示的に InvariantCulture に
設定すると言ったことが行われます。
ただし R 書式は、.NET Core 3.0 以下や .NET Framework で用いた場合、
正確な復元に失敗する可能性があることが知られています。(変換効率も比較的低め)
そのため、値の厳密性を求めるアプリケーションにおいては、
「Double 型では、代わりに G17 書式指定子を使う」
「Single 型では、代わりに G9 書式指定子を使う」
ことが、より望ましいとされています。
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings#RFormatString
ただし、小数点記号や負数記号などといった、カルチャ依存性は残ってしまうため、入出力時のカルチャを固定化する
(InvariantCulture、あるいはアプリで定めた特定のカルチャ(ja-JP など)にする)ことが必要となります。
値によっては指数表記で出力されるという問題もありますが、
このあたりの仕様をどうすべきかは、案件次第といったところ。
</蛇足情報>
|