Tuesday, April 27, 2010

Code4Food #6: How to join multiple CSV files with the same structure ?

Hi,

Reading another question on Bytes.com I found this question. So assuming these CSV files have the same structure, I can easily join them.

Now to test it I split this CSV file into 5 files: CsvFile1.csv … CsvFile5.csv

"REVIEW_DATE","AUTHOR","ISBN","DISCOUNTED_PRICE"
"1985/01/21","Douglas Adams",0345391802,5.95
"1990/01/12","Douglas Hofstadter",0465026567,9.95
"1998/07/15","Timothy ""The Parser"" Campbell",0968411304,18.99
"1999/12/03","Richard Friedman",0060630353,5.95
"2001/09/19","Karen Armstrong",0345384563,9.95
"2002/06/23","David Jones",0198504691,9.95
"2002/06/23","Julian Jaynes",0618057072,12.50
"2003/09/30","Scott Adams",0740721909,4.95
"2004/10/04","Benjamin Radcliff",0804818088,4.95
"2004/10/04","Randel Helms",0879755725,4.50

Now I made the program which makes the deal. Nothing to special here, just want to mention you do not need joining multiple times the column headers.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Text;

namespace CsvJoiner
{
    static class Program
    {
        public static void Main()
        {
            string[] csvFileNames = Directory.GetFiles(".", "CsvFile*.csv");

            JoinCsvFiles(csvFileNames, "CsvOutput.csv");
        }

        private static void JoinCsvFiles(string[] csvFileNames, string outputDestinationPath)
        {
            StringBuilder sb = new StringBuilder();

            bool columnHeadersRead = false;

            foreach (string csvFileName in csvFileNames)
            {
                TextReader tr = new StreamReader(csvFileName);

                string columnHeaders = tr.ReadLine();

                // Skip appending column headers if already appended
                if (!columnHeadersRead)
                {
                    sb.AppendLine(columnHeaders);
                    columnHeadersRead = true;
                }

                sb.AppendLine(tr.ReadToEnd());  
            }

            File.WriteAllText(outputDestinationPath, sb.ToString());
        }
    }
}
Now I'll show the output. To check out this project
download the sources here
"REVIEW_DATE","AUTHOR","ISBN","DISCOUNTED_PRICE"
"1985/01/21","Douglas Adams",0345391802,5.95
"1990/01/12","Douglas Hofstadter",0465026567,9.95
"1998/07/15","Timothy ""The Parser"" Campbell",0968411304,18.99
"1999/12/03","Richard Friedman",0060630353,5.95
"2001/09/19","Karen Armstrong",0345384563,9.95
"2002/06/23","David Jones",0198504691,9.95
"2002/06/23","Julian Jaynes",0618057072,12.50
"2003/09/30","Scott Adams",0740721909,4.95
"2004/10/04","Benjamin Radcliff",0804818088,4.95
"2004/10/04","Randel Helms",0879755725,4.50

Monday, April 26, 2010

Code4Food #5: How to get specific XML nodes using Linq to XML ?

Hi, another question has been received from Bytes.com.

So the problem was that we needed to get all the tags “Error” from a specific XML without actually caring to much about where exactly in the XML tree is Error tag. And we need to do this using Linq to Xml.

So he got an xml like these:

<Users>
      <User>
           <FirstName>Tom</FirstName>
           <LastName>Won</LastName>
           <Error>Test 2</Error>
       </User>
      <User>
           <FirstName>Jim</FirstName>
           <LastName>Kim</LastName>
           <Error>Test 2</Error>
       </User>
       <Error>Test 3</Error>
</Users>

Now this problem isn't actually a problem at all. All you need is to use Linq to XML objects like XElement, XDocument, XNode, and so on (opposite thing to XmlElement, XmlDocument, and XmlNode). Actually you can do it without directly using Linq, by callings Descendants(XName name) method.

So this is the code that I’ve written to make this done.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;

namespace GetErrorTags.Linq2Xml
{
    static class Program
    {
        static void Main()
        {
            // Load the document into root XElement.
            // Remember in Linq you work with XDocument, XElement, XNode and not with XmlDocument, etc.
            XElement rootElement = XElement.Load("ErrorTags.xml");

            // without directly using Linq
            var errorTags = rootElement.Descendants("Error");

            Console.WriteLine("==============Without using Linq=========");

            foreach (XElement tagError in errorTags)
            {
                Console.WriteLine(tagError);
            }

            Console.ReadKey();

            // using Ling directly, we'll select only "Test 2" errors
            var linqErrorTags = rootElement.Descendants("Error").Where(element => element.Value.Equals("Test 2"));

            Console.WriteLine("==============Using Linq=========");

            foreach (XElement tagError in linqErrorTags)
            {
                Console.WriteLine(tagError);
            }

            Console.ReadKey();

        }
    }
}

And here is the output:

Download source

Thursday, April 22, 2010

Code4Food #4: How to change WinForms Treeview control image size?

Hi,

Today I visited Bytes.com and saw a question about Treeview.

Indeed how would one change ImageSize of a node ? So I had 15 free minutes and this is what I found.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TreeView.ImageSize
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            FillTreeView();
        }

        private void FillTreeView()
        {
            // Load the images in an ImageList.
            ImageList myImageList = new ImageList();
            myImageList.Images.Add(Image.FromFile("63vts4.jpg"));
            myImageList.Images.Add(Image.FromFile("ToDeleteIfNotSold.png"));
            
            // Change the size of the images.
            myImageList.ImageSize = new Size(50, 50);

            // Assign the ImageList to the TreeView.
            trvImages.ImageList = myImageList;
            trvImages.ItemHeight = 50;

            // Set the TreeView control's default image and selected image indexes.
            trvImages.ImageIndex = 0;
            trvImages.SelectedImageIndex = 1;

            // Create the root tree node.
            TreeNode rootNode = new TreeNode("CustomerList");

            TreeNode childNode1 = new TreeNode("Customer1");
            TreeNode childNode2 = new TreeNode("Customer2");

            // Add a main root tree node.
            trvImages.Nodes.Add(rootNode);
            trvImages.Nodes[0].Nodes.Add(childNode1);
            trvImages.Nodes[0].Nodes.Add(childNode2);
        }
    }
}

So the magic line was myImageList.ImageSize = new Size(50, 50); Here is the output and the code to download.

Download source code link

Thursday, April 1, 2010

.NET 4.0 : System.Tuple

So, let’s go back to our subject, .NET 4.0 new stuff & features.

One of the newest things that we will have in .NET 4.0 is a tuple, what’s right and it’s not a joke!

A tuple is data structure which can contain different types of data coupled. This is what makes it different from a List or other generic types.

Note: Do not confuse it with Microsoft.Dynamics.Framework.Reports.Tuple. It is another type.

So a tuple which will contain to 7 elements is created with a factory. System.Tuple.Create. A tuple with 8 elements will contain 7 elements and another tuple Rest.

Why would we need this  type? Well, this allows us to return two or more values of different types.

Here is the code which i made to play a little bit with this type.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Intro.Tuple
{
    class Program
    {
        static void Main(string[] args)
        {
            var squaresList = System.Tuple.Create(1, 4, 9, 16, 25, 36, 49, 64);

            Console.WriteLine("1st item: {0}", squaresList.Item1);
            Console.WriteLine("4th item: {0}", squaresList.Item4);
            Console.WriteLine("8th item: {0}", squaresList.Rest);
            Console.ReadKey();

            Console.WriteLine(Environment.NewLine);
            
            var tupleWithMoreThan8Elements =
                System.Tuple.Create("is", 2.3, 4.0f,
                new List { 'e', 't', 'h' }, "udevi", new Stack(4), "best", squaresList);

            // we'll sort the list of chars in descending order
            tupleWithMoreThan8Elements.Item4.Sort();
            tupleWithMoreThan8Elements.Item4.Reverse();

            Console.WriteLine("{0} {1} {2} {3}", tupleWithMoreThan8Elements.Item5,
                tupleWithMoreThan8Elements.Item1,
                string.Concat(tupleWithMoreThan8Elements.Item4),
                tupleWithMoreThan8Elements.Item7);

            Console.WriteLine("Rest: {0}", tupleWithMoreThan8Elements.Rest);
            Console.WriteLine("Rest's 2nd element: {0}", tupleWithMoreThan8Elements.Rest.Item1.Item2);
            Console.WriteLine("Rest's 5th element: {0}", tupleWithMoreThan8Elements.Rest.Item1.Item5);
            Console.ReadKey();

            Console.WriteLine(Environment.NewLine);

            var tuple = GetNameAndAge();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("Name: {0}", tuple.Item1);
            Console.WriteLine("Age: {0}", tuple.Item2);
            Console.ReadKey();
        }

        private static Tuple GetNameAndAge()
        {
            var resultingTuple = System.Tuple.Create(string.Empty, 0);

            Console.WriteLine("Enter your name please: ");
            string name = Console.ReadLine();
            Console.WriteLine("Enter your age please: ");
            string ageValue = Console.ReadLine();

            int age = -1;

            if (int.TryParse(ageValue, out age))
            {
                resultingTuple = new Tuple(name, age);
            }

            return resultingTuple;
        }
    }
}

And here is what in our case the Rest is:

And the output:

Hope it helps you! See you around!