Resolved Help Exporting and Importing CSV

ceobros

Member
Joined
Jul 8, 2022
Messages
10
Programming Experience
Beginner
I need a way to open a csv file and write the contents of it into a listview component.
I tried but it doesn't work.

Here is my export from listview to csv:

Export to CSV:
        private async void savCoord_Click(object sender, EventArgs e)
        {

            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            saveFileDialog.Filter = "CSV|*.csv";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                using (StreamWriter sw = new StreamWriter(new FileStream(saveFileDialog.FileName, FileMode.Create), Encoding.UTF8))
                using (FileStream fileStream = new FileStream(saveFileDialog.FileName, FileMode.Create))
                using (StreamWriter streamWriter = new StreamWriter(fileStream))
                {
                    foreach (ListViewItem item in PositionsListView.Items)
                    {
                        await sw.WriteLineAsync(string.Format("{0},{1},{2},{3}", item.SubItems[0].Text, item.SubItems[1].Text, item.SubItems[2].Text, item.SubItems[3].Text));
                        MessageBox.Show("Success!", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }

            }
        }

And here is my Import Code (can't figure out how to get it to work)

Import from csv to Listview:
        private void openCoord_Click(object sender, EventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            openFileDialog.Filter = "CSV|*.csv";

            try
            {
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    FileStream srcFS;
                    srcFS = new FileStream(openFileDialog.FileName, FileMode.Open);
                    StreamReader srcSR = new StreamReader(srcFS, System.Text.Encoding.Default);
                    foreach (ListViewItem item in PositionsListView.Items)
                    {
                        string ins = srcSR.ReadLine();
                        string[] row = { "X", "Y", "L/R", };
                        ListViewItem listViewItem = new ListViewItem(row);
                        PositionsListView.Items.Add(listViewItem);


                    }
                    
                    }
            }
            catch (Exception errorMsg)
            {
                MessageBox.Show(errorMsg.Message, "Error reading a file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
 
If you don't want to use a third-party library, e.g. CsvHelper, then I suggest that you use the TextFieldParser class to read CSV data. It means referencing the Microsoft.VisualBasic library but that's not the end of the world.

That said, if your data is basic, i.e. values not quoted and no delimiters in the data, then you can read simply use string.Split:
C#:
foreach (var line in File.ReadLines(filePath))
{
    var fields = line.Split(',');

    // Use fields here.
}
 
Why are you creating two StreamWriters when you save the data? You only need one and you don't need to explicitly create a FileStream:
C#:
using (var writer = new StreamWriter(saveFileDialog.FileName))
{
    foreach (ListViewItem item in PositionsListView.Items)
    {
        await writer.WriteLineAsync($"{item.Text},{item.SubItems[1].Text},{item.SubItems[2].Text},{item.SubItems[3].Text}");
You don't even need a StreamWriter:
C#:
await File.WriteAllLinesAsync(saveFileDialog.FileName,
                              PositionsListView.Items
                                               .Cast<ListViewItem>()
                                               .Select(item => $"{item.Text},{item.SubItems[1].Text},{item.SubItems[2].Text},{item.SubItems[3].Text}"));
 
If you don't want to use a third-party library, e.g. CsvHelper, then I suggest that you use the TextFieldParser class to read CSV data. It means referencing the Microsoft.VisualBasic library but that's not the end of the world.

That said, if your data is basic, i.e. values not quoted and no delimiters in the data, then you can read simply use string.Split:
C#:
foreach (var line in File.ReadLines(filePath))
{
    var fields = line.Split(',');

    // Use fields here.
}
Hi, not sure what filepath is from, but I replaced it with "openFileDialog.FileName" but when I try to import data it says the file is in use. What am I missing here?
 
If the CSV file you are trying to import is currently opened by Excel, then you there you have it. Excel likes to lock files to prevent other apps from editing things under it, but it also has the side effect of preventing other apps from reading the files as well. (They could have picked locking modes that allow read while locked, but I'm not sure why they didn't choose to do so.)
 
If the CSV file you are trying to import is currently opened by Excel, then you there you have it. Excel likes to lock files to prevent other apps from editing things under it, but it also has the side effect of preventing other apps from reading the files as well. (They could have picked locking modes that allow read while locked, but I'm not sure why they didn't choose to do so.)
the thing is that it isn't opened at all anywhere.
 
Your computer is telling you otherwise.

Looking at your code from post #1, I see that srcFS is never closed.
 
Your computer is telling you otherwise.

Looking at your code from post #1, I see that srcFS is never closed.
If the advice from post #2 was taken, as seems to be the case, then that variable should no longer exist anyway, but who knows. This is an example of why, if you change your code and it doesn't work, you need to show us the new code. Don't ask us for help with code that we haven't seen.
 
If the advice from post #2 was taken, as seems to be the case, then that variable should no longer exist anyway, but who knows. This is an example of why, if you change your code and it doesn't work, you need to show us the new code. Don't ask us for help with code that we haven't seen.

Doesn't import anything into the ListView and I'm not sure what to replace "filePath" with

C#:
        private async void savCoord_Click(object sender, EventArgs e)
        {

            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            saveFileDialog.Filter = "CSV|*.csv";

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                using (var writer = new StreamWriter(saveFileDialog.FileName))
                {
                    foreach (ListViewItem item in PositionsListView.Items)
                    {
                        await writer.WriteLineAsync($"{item.Text},{item.SubItems[1].Text},{item.SubItems[2].Text},{item.SubItems[3].Text}");
                    }
                    MessageBox.Show("Success!", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

            }
        }


        private void openCoord_Click(object sender, EventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            openFileDialog.Filter = "CSV|*.csv";

            try
            {
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    FileStream srcFS;
                    srcFS = new FileStream(openFileDialog.FileName, FileMode.Open);
                    StreamReader srcSR = new StreamReader(srcFS, System.Text.Encoding.Default);
                    foreach (var line in File.ReadLines(filePath))
                    {
                        var fields = line.Split(',');


                    }
                    
                    }
            }
            catch (Exception errorMsg)
            {
                MessageBox.Show(errorMsg.Message, "Error reading a file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
 
If the advice from post #2 was taken, as seems to be the case, then that variable should no longer exist anyway, but who knows. This is an example of why, if you change your code and it doesn't work, you need to show us the new code. Don't ask us for help with code that we haven't seen.
the string is very simple, its 4 columns, data is stored as such for example

1,2,3,4
 
So the issue is exactly as Skydiver said. I told you to read the file using File.ReadLines and, for some reason, you thought that creating a FileStream and a StreamReader was still a good idea. It's not. You're not using them so why are you creating them?
I'm not sure what to replace "filePath" with
Put your thinking cap on for a moment. I provided you with an example. The point of an example is to demonstrate a principle that you can then apply to your own similar scenarios. If an example demonstrates reading a file and uses a variable named filePath, what do you suppose that represents? It seems fairly obvious that it represents the path of the file that is being read. If you want to apply the demonstrated principle in your own code then you have two choices: either declare a filePath variable and assign the file path to it and then use the example code as is, or else replace filePath in the example code with whatever you have that contains the path of the file.
 
So the issue is exactly as Skydiver said. I told you to read the file using File.ReadLines and, for some reason, you thought that creating a FileStream and a StreamReader was still a good idea. It's not. You're not using them so why are you creating them?

Put your thinking cap on for a moment. I provided you with an example. The point of an example is to demonstrate a principle that you can then apply to your own similar scenarios. If an example demonstrates reading a file and uses a variable named filePath, what do you suppose that represents? It seems fairly obvious that it represents the path of the file that is being read. If you want to apply the demonstrated principle in your own code then you have two choices: either declare a filePath variable and assign the file path to it and then use the example code as is, or else replace filePath in the example code with whatever you have that contains the path of the file.
had a brain fart but its still lingering. The data from the file still won't display in the listview

C#:
        private void openCoord_Click(object sender, EventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            openFileDialog.Filter = "CSV|*.csv";

            try
            {
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string sFileName = openFileDialog.FileName;
                    foreach (var line in File.ReadLines(sFileName))
                    {
                        var fields = line.Split(',');
                    }
                    
                    }
            }
            catch (Exception errorMsg)
            {
                MessageBox.Show(errorMsg.Message, "Error reading a file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
 
Look back at post #2. What does it say in the code after calling Split? Are you doing that? The data won't magically appear in the ListView. You have to put it there. My specific advice was about reading the file. I left the part where you put the data you read into the ListView up to you. Given that the documentation for the ListView class contains a code example that adds items, it's not really something that we need to demonstrate here. That's ignoring the fact that there are probably numerous other examples on the web too. Reading a file is something that can be done several different ways and the way you were doing it was suboptimal for the situation, which is why I showed you a specific way to do it.
 
Look back at post #2. What does it say in the code after calling Split? Are you doing that? The data won't magically appear in the ListView. You have to put it there. My specific advice was about reading the file. I left the part where you put the data you read into the ListView up to you. Given that the documentation for the ListView class contains a code example that adds items, it's not really something that we need to demonstrate here. That's ignoring the fact that there are probably numerous other examples on the web too. Reading a file is something that can be done several different ways and the way you were doing it was suboptimal for the situation, which is why I showed you a specific way to do it.
Still stuck now with an error "InvalidArgument=Value of '1' is not valid for 'index'. Parameter name: index"

C#:
        private void openCoord_Click(object sender, EventArgs e)
        {

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.InitialDirectory = Path.GetPathRoot(Environment.SystemDirectory);
            openFileDialog.Filter = "CSV|*.csv";

            try
            {
                
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    
                    string sFileName = openFileDialog.FileName;
                    foreach (var line in File.ReadLines(sFileName))
                    {
                        var fields = line.Split(',');

                        ListViewItem item = new ListViewItem(line.ToString());

                        item.SubItems.Add($"{item.SubItems[0]},{item.SubItems[1]},{ item.SubItems[2]},{ item.SubItems[3]}");

                    }
                    
                    }
            }
            catch (Exception errorMsg)
            {
                MessageBox.Show(errorMsg.Message, "Error reading a file", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
 
You're not reading the words I'm posting. The specific comment in my code that I directed you to was this:
C#:
// Use fields here.
Here's the code that you just wrote:
C#:
ListViewItem item = new ListViewItem(line.ToString());

item.SubItems.Add($"{item.SubItems[0]},{item.SubItems[1]},{ item.SubItems[2]},{ item.SubItems[3]}");
Where in that code are you using fields? You're not, so you're not doing what I said to do, so why would you expect it to work?

Think about what you're doing. You have a string array containing four elements in the fields variable. You want to create a ListViewItem with those four values. How do you do that? Have you done any research on that? Have you read the documentation I mentioned earlier than contains a relevant code example?

I understand that you're relatively new to this but logic doesn't go out the window because you're new. If you are provided with instructions, follow those instructions. If there's something specific you don't understand, ask about that specifically. Don't just throw stuff at the wall and hope for the best. Don't do something unless there is a logical reason for doing it. Think your way through the steps required first, as though you had to do it manually, then write to implement those steps specifically. If you don't know what the code is supposed to do - that means the steps to get to a result, not just the result itself - then of course you won't be able to write the code to do it.
 
Back
Top Bottom