Looking for new tricks for CSV file creation

Given the XOJO language has expanded and improved over the past few years, I wonder if anyone has come up with a more clever way to building a .CSV file.

I have a pretty generic requirement, but if I can use this chance to update my skillset why not?! CSV files have a simple header, followed by rows, and escaping commas and whitespace by bracketing each entry in quotes… all pretty straight forward.

I need to create the entries programmatically, and the column order is important to maintain. I’ll be writing the result out to disk via a traditional BinaryStream.

If there are any built-in functions I’m overlooking be sure to embarrass me and point them out.

And have a great day! Thanks!

“More clever way” than what?

If you want your code improved, you obviously need to show what you are doing.

Excellent point @Markus_Winter ! I am just starting to code the module, so the code I’d start writing would be something like…

1- Create a String array for Header values, and a String array for every row.
2.- For each value in the header I’d check for offending characters, etc.
3.- Sequentially append a large string variable with each header entry, plus a kComma character.
4.- Insert a NewLine
5.- Grab my first array of “values” and append them to the same growing string, plus a NewLine

…a somewhat “manual” way of constructing this big piece of text.

I know of a few things to READ a csv file (the parsing is really not as straight forward as you may think, to do edge cases correctly). But I am not aware of any existing classes to WRITE a csv file.

My usual way to create any delimited file is to create a string array, add an entry for each “column”, and then Join the array with the delimiter to create a text line. I almost always output using a tab delimiter so I don’t have to mess with escaping.

So my generic WriteTabLine() method looks similar to this:

dim line as string= Join(flds,Chr(9)) + EndOfLine
fs.write line
return

where I just pass in the TextOutputStream (i.e. “fs” above) and the string array of fields to include (i.e. “flds” above).

I tend to just add lines to my output file as I go, including a header before I start looping over data. Then close out the file stream at the end. But you could also build that up in another string array (e.g. “lines()” or whatever) that you ultimately turn into a string again using join() but with an EndOfLine instead of tab or comma delimter.

For csv output, I’d probably do a similar WriteCsvLine() which before doing the join on the passed string array, loops over it and properly escapes each value.

Then in your code you can ignore all the complexities and just create a new “line” of output by clearing the array and appending data as needed.

Might also be worth looking at Norman’s CSV Parser code:

And that is one of the classes I was referring to help READ a CSV file, but I was not aware it may help create one. Since I have the MBS extensions, I tend to just it for parsing instead of Norman’s.

Writing a CSV file is a lot easier than reading one. In the Just Code Challenge, a few years ago, I submitted a simple CSV file editor that reads, edits and writes CSV files. The creation and writing part is very straightforward. The project can be downloaded here:
CSV File Editor Project

4 Likes

Since one is the reverse of the other it can show a few tricks either way.

1 Like

Use a TextOutputStream and WriteLine to write line by line. Building one long string with embedded EndOfLine is not a good approach.

Tab delimited format is much easier and is pretty ubiquitous.

Thanks Tim, comma separated is the users requirement but I’ll heed your advice to iteratively writing it out :+1:

I would say reading / writing each line separately is not a good approach. But maybe that’s just me … :roll_eyes:

Norman has just updated his CSV Parser …

2 Likes
Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.