Using Ice.Lib.SharedUtilities.ImportExport for CSV Creation

@Chris_Conn gave a nice example of using this library to read from a CSV. I have a requirement to write to a CSV. My C# knowledge is such that I have managed to assemble some working stuff using lots of help from here, but I don’t have the full understanding of the fundamentals.

Using the same code structure as the CsvReader that compiles, generates these errors:

Error: CS0712 - line 70 (199) - Cannot create an instance of the static class 'Ice.Lib.SharedUtilities.ImportExport.CsvWriter'

Error: CS0723 - line 70 (199) - Cannot declare a variable of static type 'Ice.Lib.SharedUtilities.ImportExport.CsvWriter'

Error: CS1674 - line 70 (199) - 'Ice.Lib.SharedUtilities.ImportExport.CsvWriter': type used in a using statement must be implicitly convertible to 'System.IDisposable' 

I decompiled using ILSpy, and can see that CsvReader is a public class that implements IDisposable (public class CsvReader : IDisposable), where as CsvWriter is a static class (public static class CsvWriter).

How do I go about using the class in my code please?

This is the full output from ILSpy for CsvWriter class:

// Ice.Lib.SharedUtilities.ImportExport.CsvWriter

using Ice.Lib.SharedUtilities.ImportExport;

using System.Collections;

using System.Globalization;

using System.Text;

public static class CsvWriter

{

    public static string GetCSVLine(string[] data)

    {

        StringBuilder sb = new StringBuilder();

        string sep = "";

        IEnumerator iEnum = data.GetEnumerator();

        while (iEnum.MoveNext())

        {

            sb.Append(sep + CsvWriter.parseCSVField((string)iEnum.Current));

            sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

        }

        return sb.ToString();

    }

    private static string parseCSVField(string data)

    {

        string sep = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

        bool wrapInQuotes = data.IndexOf(sep) > -1;

        if (data.IndexOf('"') > -1)

        {

            data = data.Replace("\"",
"\"\"");

            wrapInQuotes = true;

        }

        data = data.Replace("\n",
"\r\n");

        data = data.Replace("\r\r\n",
"\r\n");

        data = data.Replace("\r",
"\r\n");

        data = data.Replace("\r\n\n",
"\r\n");

        if (data.IndexOf("\r\n") > -1)

        {

            data = data.Replace("\r\n",
'\n'.ToString()).Trim();

            wrapInQuotes = true;

        }

        if (wrapInQuotes)

        {

            data = "\"" + data +
"\"";

        }

        return data;

    }

}

Many Thanks

Mark

1 Like

How are you using it? Where is your code… The ILSpy fro CsvWriter doen’t help us… The issue is coming from your code.
Looks like you are trying to create an instance of this class (which is static)

Yeah it’s totally me not understanding how to consume this class. I’m using it in a screen customisation on Ice.UD39.

Looking at the code, there appears to be nothing in that static class that file create a CSV file - is that class just “tidying” up the data and inserting the separators? I still have to setup a filename path, use this method to build a string, then write that string out to the file?

For this static class, how do I use it?? Is it like this:

CsvWriter.GetCSVLine(pass it some data);

Error: CS1502 - line 72 (201) - The best overloaded method match for ‘Ice.Lib.SharedUtilities.ImportExport.CsvWriter.GetCSVLine(string[])’ has some invalid arguments
Error: CS1503 - line 72 (201) - Argument 1: cannot convert from ‘string’ to ‘string[]’

I passed it a string, but it’s asking for a string array?

It wants a string array.

Looks like its less of a “writer” than a formatter

string[] myDatas; //ur data here
CsvWriter.GetCSVLine(myDatas);

Looks like it get the separator from the culture settings:

You’d need to take that output and pipe it into a text file yourself

Really all it does is format to handle quotes

The data that I want to get into a CSV file, is the results of a UBAQ - the control on screen is Ice.Lib.Framework.EpiUltraGrid. Would I therefore pass each row to the method one by one, and it will append each set of values into the string?

For enumerating the columns on the grid, I want to skip over some - best way to do this would be…
?

For each row, you’d need to build your string[] out of the cols you want
Then feed that to GetCSVLine
Take this output and append to a text file

pseudo code

List<string> myList = new List<string>();
foreach(row)
{
  foreach(col i want)
  {
     myList.Add(col value);
  }

var myData =   myList.ToArray();
string writeThisLine = GetCSVLine(myData);
file.Append(writeThisLine);
}
As far as skipping, there are many ways, the easiest I can think of:
List<string> myCols = new List<string>();
myCols.Add(a col name i want);
myCols.Add(another col name i want);

then you can test if myCols.Contains(current col)

Better yet for perfomance, only iterate your cols

foreach(row)
{
  foreach(colName in myCols)
  {
  var colValue = row[colName];
     myList.Add(colValue);
  }

Thank you both very much for the assistance and expanding my understanding :star_struck:

It was a hard decision as to which answer to mark as solved, but I re-read my original query and it was about how to consume the method. @Chris_Conn won this time, so sorry @josecgomez :grin:

2 Likes

@josecgomez

2 Likes