ちょっと先の未来クイズ第4問

前回の質問では大変お世話になりました。
引き続き、VB.NETの勉強をしております。

特定のCSVファイルを読み込んで、その内容をラベルに表示させるプログラムを作成しています。
そのCSVファイルには、以下の情報が書かれています。
1:都道府県(北海道、岩手県、神奈川県、兵庫県など)
2:各都道府県の人口
3:各都道府県の面積
3つの情報は、すべてカンマで区切られています。
各都道府県ですので、47行にわたって情報が書かれています。

まず、ボタン1を押したときに、CSVファイルを読み込み
日本の総人口と総面積をラベルに表示させます。
次に、日本を10のエリアに分け(関東地方、近畿地方など)
それぞれにボタンを配置します。
対応する地域のボタンを押すと、新しいウィンドウが開き
地域名・その地域の総人口・総面積が表示されます。

CSVファイルを読み込むという点で調べてみたのですが
複数の行にまたがっている情報をひとつにまとめて表示させる
というのがよくわかりません。
CSVファイルの読み込み自体は、StreamReaderというものを利用する
ということは調べたのですが、まとめて表示させるということがわかりません。
この問題がおわかりになるかたがいましたら、教えていただけますか。
よろしくお願いします。

A 回答 (3件)

> これを書いてみると、「Lengthはdataのメンバではありません」というエラーが出ます。



流れだけを説明するために書いたもので、動作確認してませんのでそのまま貼っても動かないと思います。

# できれば、あなたがお書きになったもので動作がうまくいかないという箇所を質問してくださると助かります。

次のコードは VB.NET 2003 で動作確認してあります。
取り敢えず、参考にしてみてください。

コードの一番先頭に
Imports System.IO
Imports System.Text
を追記

Call SumAll("c:\data.csv") の引数のファイル名をあなたがお使いのファイル名をフルパスで記述して
置き換えれば動作すると思います。

ボタンを押した時にメッセージボックスに合計がでますので、ラベルに表示する部分やその他の部分は
ご自身で考えてください。(この場合もどこまでご自身でなさったかを示して頂けるとよろしいです)

意味がわからないことがありましたら、どの部分かを引用なさった上でお願いいたします。
----------------------------------------
REM ボタンを押した時
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 Call SumAll("c:\data.csv")
End Sub
----------------------------------------
REM 全国
Sub SumAll(ByVal szFileName As String)
 REM 合計表示
 Dim lines()() As String = ReadCSV(szFileName)
 Dim index As Integer = 0
 Dim sum_all_people As Double
 Dim sum_all_area As Double
 For index = 0 To lines.Length - 1
  sum_all_people += Double.Parse(lines(index)(1))
  sum_all_area += Double.Parse(lines(index)(2))
 Next
 MsgBox("総人口は " & sum_all_people.ToString() & " 人" & _
  vbCrLf & "総面積は " & sum_all_area.ToString() & " km2", _
  MsgBoxStyle.OKOnly, "日本全国")
End Sub
----------------------------------------
REM CSV ファイル読み込み処理
Function ReadCSV(ByVal szFileName As String) As String()()
 REM (全般) に Imports 追記
 REM Imports System.IO
 REM Imports System.Text
 Dim arrayTempLines()() As String = {}
 REM ストリームを開く
 Dim reader As New IO.StreamReader(szFileName, System.Text.Encoding.Default)
 Dim iIdx As Integer = 0
 REM 一気に読み込む
 Dim szData As String = reader.ReadToEnd()
 REM 不要な文字を取り除く
 szData = szData.Replace(vbCr, "")
 REM 改行で分離して配列に格納
 Dim arrayLines() = szData.Split(vbLf)
 Dim szLine As String
 For Each szLine In arrayLines
  Dim iCount As Integer = 0
  Dim szTemp As String = ""
  Dim bValid As Boolean = False
  If szLine.Length > 1 Then
   REM 配列の追加
   ReDim Preserve arrayTempLines(iIdx)
   REM カンマ区切りで分離して配列に格納
   arrayTempLines(iIdx) = szLine.Split(",")
   REM データのチェック
   If arrayTempLines(iIdx).Length > 2 And _
    arrayTempLines(iIdx)(0) <> "" Then bValid = True
   REM 不要データを除く
   For Each szTemp In arrayTempLines(iIdx)
    arrayTempLines(iIdx)(iCount) = _
    szTemp.Replace(Chr(34), "").TrimEnd()
    iCount += 1
   Next
   REM 配列数チェック
   If bValid Then iIdx += 1
  End If
 Next
 REM 配列の切り詰め
 ReDim Preserve arrayTempLines(iIdx - 1)
 ReadCSV = arrayTempLines
End Function
------------------------
    • good
    • 0

まずはお詫びと訂正です。



ANo.1 から引用
> フィールドを prefectures()、population()、area() などの
> 変数配列に格納、必要であれば地方の識別子として block()
> なども

これは二次元配列に格納すれば済む話でした、申し訳ありません。
ANo.1 での記述を忘れましたが、TextFieldParser を使う話です。

CSVファイルを読み込むには?[2.0のみ、C#、VB] - @IT
http://www.atmarkit.co.jp/fdotnet/dotnettips/487 …

TextFieldParser と FieldType.Delimited と SetDelimiters(",") を組み合わせると
カンマ区切りの箇所で分割されて配列に格納されるということです。
この場合は結果的に二次元配列に取り込むことになります。

Dim data()() As String

FILE.CSV というファイルの読み込む例として

※ FILE.CSV に空の行、つまり改行のみしかない場合はエラーに
  なるので注意してください。

Dim tfp As New TextFieldParser("FILE.CSV", _
 System.Text.Encoding.GetEncoding("Shift_JIS"))
tfp.TextFieldType = FieldType.Delimited
tfp.SetDelimiters(",")

Dim index As Interger = 0
While Not tfp.EndOfData
 ReDim Preserve data(index)
 data(index) = tfp.ReadFiles()
 index += 1
End While

配列に格納されるデータは次のようになると思われます。

data(0)(0) に「北海道」
data(0)(1) に「北海道の人口」
data(0)(2) に「北海道の面積」
...
data(46)(0) に「沖縄県」
data(46)(1) に「沖縄県の人口」
data(46)(2) に「沖縄の面積」

全国の合計であれば、人口や面積の値を合計すればよいわけです。
for とか使って配列のインデックスを変えていけば実現可能。

全国の人口であればこれで求められると思われます。

Dim index As Integer
For index = 0 To data.Length - 1
 sum_all += data(index)(1)
Next index

面積の合計はあなたご自身で考えてはいかがでしょうか?

> CSVファイルには地方名や地方コードは書かれていません。

では、プログラムの中で地方に仕訳するためのデータを持つしかないのでしょう。

> 上から何番目から何番目までを東北地方、何番目から何番目までを関東地方
> というふうに抜粋して識別するしかないと思っていたのですが
> そのやりかたもいまいちわかりません……。

これも配列に持たせますか?

> CSVファイルを読み込むということは、配列を用意しなければならないのでしょうか?

StreamReader で一行毎に文字列に読み込み、Split で都道府県、人口、
面積にわけます、この場合は一次元配列になので初めて配列を扱うということで
あれば二次元配列よりは簡単だと思います。

この方法はあなたがお考えになってプログラミングに挑んでみてください、もし行き詰まって
しまったら、エラーや問題になったコードを提示されて相談なさってください。

この回答への補足

ありがとうございます。

読み込みについては、StreamReaderを使うとエラーが出るので
FileOpenと、LineInputを使用しました。
(書き忘れましたが、使用しているのは、VB.NET 2003です)

>Dim index As Integer
>For index = 0 To data.Length - 1
> sum_all += data(index)(1)
>Next index

これを書いてみると、「Lengthはdataのメンバではありません」というエラーが出ます。
人口や面積の合計を出すにはfor文を使うことはわかりましたが
合計するための数値を抜き出す方法がわかりません。
Splitを使って、都道府県名と、人口と、面積を分けて
その中から人口だけを必要な数だけ抜き出して、数値を足す
という部分がどうにもわからない状態です。
たびたびの質問で申し訳ありませんが、よろしくお願いします。

補足日時:2008/03/22 05:35
    • good
    • 0

> 複数の行にまたがっている情報をひとつにまとめて表示させる


> というのがよくわかりません。

この「ひとつにまとめる」というのは何を意味するのかが、わかりません。
※ 質問返しのようで申し訳ありませんが確認のためですので。

ひとつにまとめるとは配列に格納して処理したいという意味でしょうか?

※ 引用が前後しますが。
> 1:都道府県(北海道、岩手県、神奈川県、兵庫県など)
> 2:各都道府県の人口
> 3:各都道府県の面積
> 3つの情報は、すべてカンマで区切られています。
> 各都道府県ですので、47行にわたって情報が書かれています。

要するにフォーマットは

[北海道], [xxxx], [xxxx]
...
[沖縄県], [xxxx], [xxxx]

のようになっているのでしょうか?
これらを 47 個の配列に読み込みたいのでしょうか?

> まず、ボタン1を押したときに、CSVファイルを読み込み
> 日本の総人口と総面積をラベルに表示させます。

配列に入れた数値(人口や面積)を集計するという意味でよろしいでしょうか?

> 次に、日本を10のエリアに分け(関東地方、近畿地方など)

この地方毎に分ける際の識別はどうなさるのでしょうか?
CSV ファイルに地方名か地方コード等の情報もないと仕訳が大変かと思われます。

まとめると次のようなことがなさりたいのでしょうか?

1. CSV を配列に読み込む
 あらかじめ 47 個の配列を用意するか、ReDim などを用いる
 ここで StreamReader を使うということならば、それぞれの
 フィールドを prefectures()、population()、area() などの
 変数配列に格納、必要であれば地方の識別子として block()
 なども

2. 全国の集計
 単純に配列の数だけループさせるなどして集計する。
 (他の方法もあると思いますが)

3. エリア別集計
 これは前述のように地区ごとに識別する何かが必要かと思われます。
 CSV のファイルフォーマットが
 東京都, [xxxx], [xxxx], 関東
 のようになっていないと難しいのではないでしょうか?

この回答への補足

ありがとうございます。

>要するにフォーマットは

>[北海道], [xxxx], [xxxx]
...
>[沖縄県], [xxxx], [xxxx]

>のようになっているのでしょうか?

そうです。そのように書かれています。
ひとつにまとめるというのは、たとえば、日本の総人口でしたら
47個の都道府県別の人口をすべて足した数をラベルに表示させる
という意味です。
地域別でしたら、東北地方だけの人口をすべて足す、という感じです。

>この地方毎に分ける際の識別はどうなさるのでしょうか?
>CSV ファイルに地方名か地方コード等の情報もないと仕訳が大変かと思われます。

CSVファイルには地方名や地方コードは書かれていません。
上から何番目から何番目までを東北地方、何番目から何番目までを関東地方
というふうに抜粋して識別するしかないと思っていたのですが
そのやりかたもいまいちわかりません……。

やりたいことは、ご指摘のとおりです。
CSVファイルを読み込むということは、配列を用意しなければならないのでしょうか?

補足日時:2008/03/21 12:48
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報