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

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

ただいまの
回答率

87.78%

更新ボタンで対象の行だけ値を置き換えたい

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 791

score 14

visual studioのwindowsフォームアプリケーションで
vb.netを使用しToDoリストなるものをつくっています。

テキストボックスにタスクを入力し、「登録」ボタン押下でデータをcsvに出力し
それをdatagridviewに表示させるというものですが、表示されているdatagridviewの値を変更して「更新」ボタンを押下したときの処理がうまくいかず困っています。

現在はタスク登録時に乱数でIdを項目として持たせ、「更新」押下時にその乱数が表示されているデータのものと一致していたらデータを上書きという処理にしていますが、更新押下時の画面は更新されていてもcsvファイルが更新されていないので再表示すると元に戻っている状態です。
初心者の質問で恐れ入りますが、ご回答いただけるとありがたいです。

Imports System.IO
Imports System.Text
Imports Microsoft.VisualBasic.FileIO

Public Class ToDoリスト

    Dim FilePath = "C:\ファイルパス\ToDoList.csv"

    Public Sub ToDoリスト_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.ReadCsv()

    End Sub



    '登録ボタン
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        'グリッド初期化
        DataGridView2.Rows.Clear()

        If RichTextBox1.Text = "" Then  'テキストボックスが空の時エラー
            MessageBox.Show("内容を入力してください")

        Else

            Dim Status As String


            If RadioButton1.Checked = True Then
                Status = "未着手"

            ElseIf RadioButton2.Checked = True Then
                Status = "着手中"

            ElseIf RadioButton3.Checked = True Then
                Status = "完了"
            Else             '状態が未選択の時エラー
                MessageBox.Show("状態が選択されていません。")
                Exit Sub
            End If




            'csvファイルへ書き出し
            Dim r As New Random           '乱数作成(Id)
            Dim id As Integer = r.Next(1, 1001)

            Dim sw As New StreamWriter(FilePath, True, Encoding.GetEncoding("shift_jis"))
            sw.WriteLine(MonthCalendar1.SelectionStart.ToString("yyyy/MM/dd") & "," &
                         RichTextBox1.Text.ToString() & "," &
                         Status.ToString() & "," &
                         id.ToString())

            sw.Close()

            'csvデータファイル読み込み
            Me.ReadCsv()

            'テキストボックスクリア
            RichTextBox1.Clear()

        End If
    End Sub




    'ファイルを読み込みDataGridViewに表示
    Public Sub ReadCsv()
        Dim FilePath = "C:\ファイルパス\ToDoList.csv"
        Dim parser As TextFieldParser = New TextFieldParser(FilePath, Encoding.GetEncoding("Shift_JIS"))
        parser.TextFieldType = FieldType.Delimited
        parser.SetDelimiters(",")

        'csvファイルの最終行まで読みこむ
        While (Not parser.EndOfData)

            Dim row As String() = parser.ReadFields()
            If row(0).ToString() = MonthCalendar1.SelectionStart.ToString("yyyy/MM/dd") Then
                DataGridView2.Rows.Add(row)
                '日付は変更不可とする
                DataGridView2.Columns(0).ReadOnly = True

            End If

        End While
    End Sub

    'カレンダー日付押下で対象日データ表示
    Private Sub MonthCalendar1_DateChanged(sender As Object, e As DateRangeEventArgs) Handles MonthCalendar1.DateChanged

        DataGridView2.Rows.Clear()
        Me.ReadCsv()

    End Sub


    '更新ボタン
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click



        Dim FilePath = "C:\ファイルパス\ToDoList.csv"
        Dim sr As New StreamReader(FilePath, Encoding.GetEncoding("shift_jis"))
        Dim tmpPath As String = Path.GetTempFileName()
        Dim sw As New StreamWriter(tmpPath, True, Encoding.GetEncoding("shift_jis"))

        Dim parser As TextFieldParser = New TextFieldParser(FilePath, Encoding.GetEncoding("Shift_JIS"))
        parser.TextFieldType = FieldType.Delimited
        parser.SetDelimiters(",")


        Dim row As String() = parser.ReadFields()
            Dim RowId As String = row(3).ToString()   'ファイル内Idの値

        While sr.Peek() > -1


            Dim i As Integer = DataGridView2.Rows.Count - 1

            '非表示項目IdとデータファイルのIdが一致していたら更新
            If DataGridView2.Rows(i).Cells(3).Value = RowId Then

                sw.WriteLine(DataGridView2.Rows(i).Cells(0).Value.ToString() & "," &
                                 DataGridView2.Rows(i).Cells(1).Value.ToString() & "," &
                                 DataGridView2.Rows(i).Cells(2).Value.ToString() & "," &
                                 DataGridView2.Rows(i).Cells(3).Value.ToString())

            Else
                'Id不一致の場合はそのまま
                Dim line As String = sr.ReadLine()
                sw.WriteLine(line)

            End If

        End While

        sr.Close()
        sw.Close()

        File.Copy(tmpPath, FilePath, True)
        File.Delete(tmpPath)


        MessageBox.Show("更新しました☆")
    End Sub


    '閉じるボタン
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Me.Close()
    End Sub

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YAmaGNZ

    2020/03/09 01:32

    質問内容とは関係ありませんが、同じIDになったらまずいんじゃないですか?
    乱数なので同じ値を取ることがありますよ。
    また、内容にカンマを含む入力をされた場合もまずそうですね。

    キャンセル

回答 2

0

ブレークポイントを使ってF8(ステップイン)を押して
1行ずつデバックしましょう
恐らく 書き込む時 最後のDatagridviewの行が追加可能になってるので Dim i As Integer = DataGridView2.Rows.Count - 1しても空の値を参照している datagridviewの設定が足りない? datagridview2.AllowUserToAddRows=false
Dim i As Integer = DataGridView2.Rows.Count - 1の影響で
書き込む時の比較がおかしい

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

考え方が違うかもしれませんが、CSVファイルのデータを一旦DataTableに読み込んで、そこで日付で要らないレコードはDataTableから削除して、残った結果を

dataGridView1.DataSource = dataTable1

と言う感じにしてはどうでしょうか。
dataGridView1のデータをユーザが書き換えたら、DataTableからではなく、dataGridView1から直接データを拾って書き出して、その後で再度書き出したCSVファイルを読み込んで、dataGridView1に表示するという処理がいいような気もします。

CSVファイルのデータを一旦DataTableに読み込んでDataGridViewに表示する

DataTableのデータをCSVファイルに保存する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る