DataTable rename from multidimensional string array

Lance James 366 Reputation points
2022-02-27T17:49:50.4+00:00

In a previous thread, JackJJun-MSFT explained how to rename columns to generic headers.

I now need to rename just the columns I want to use based on a multidimensional array from a helper class. First element is the Column to rename with the second element.

public class Helper 
{

private string[,] _gacColumns = new string[,] { { "A1", "DateDate" },  { "A4", "Item" },
                            { "A10", "Site" }, { "A11", "TotalStock" }, { "A12", "MRBNonAlloc" }, { "A13", "MinLevel" },
                            { "A14", "MaxLevel" }, { "A18", "LastDateRecd" }, { "A19", "LastQtyRecd" }, { "A20", "LastPackSlipRecd" },
                            { "A35", "Month01" }, { "A36", "Month02" }, { "A37", "Month03" }, { "A38", "Month04" },
                            { "A39", "Month05" }, { "A40", "Month06" }, { "A41", "Month07" }, { "A42", "Month08" },
                            { "A43", "Month09" }, { "A44", "Month10" }, { "A45", "Month011" }, { "A46", "Month12" },
                            { "A47", "UpdatedDate" }, { "A48", "DataSource" } }; 

 public string[,] GACColumns => _gacColumns;

}

I need to apply new column names just to the columns from the array.

Something like this but I am convinced I am mixing and matching what can't be mixed.

        public void ChangeColumnsNew(DataTable table, Helper h)
        {
            foreach (string element in h.GACColumns)
                table.Columns[element].ColumnName = ""; //Don't know what to put on the right side of the assignment;
        }

Regards,
Lance

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,386 Reputation points
    2022-02-28T14:22:26.263+00:00

    Multidimensional arrays are not friendly and certainly do not present easy logic to follow. Your solution dispatches with the confusion.

    We can get even better and make using Json simple by following the code below and here. Make sure to look at how I created the Json here

    A Class for providing a user interface to select a template

    public class ConfigurationItem  
    {  
        public int Id { get; set; }  
        public string Name { get; set; }  
        public override string ToString() => Name;  
    }  
    

    A Class to store mappings

    public class DataMapColumn  
    {  
        public int ConfigurationId { get; set; }  
        public string Name { get; set; }  
        public int Ordinal { get; set; }  
        public string DisplayName { get; set; }  
        public override string ToString() => Name;  
    }  
    

    File operations

    public class FileOperations  
    {  
        public static readonly string ConfigurationFileName = "Configuration.json";  
        public static readonly string DataItemsFileName = "DataItems.json";  
      
        /// <summary>  
        /// Create file if not exists for list of <see cref="ConfigurationItem"/>  
        /// </summary>  
        public static void WriteConfigurationItems()  
        {  
            if (File.Exists(ConfigurationFileName)) return;  
              
            var list = new List<ConfigurationItem>  
            {  
                new ConfigurationItem() { Id = 1, Name = "First" },  
                new ConfigurationItem() { Id = 2, Name = "Second" }  
            };  
      
            File.WriteAllText(ConfigurationFileName,   
                JsonConvert.SerializeObject(list, Formatting.Indented));  
        }  
        /// <summary>  
        /// Create file if not exists for list of <see cref="DataMapColumn"/>  
        /// </summary>  
        public static void WriteDataItems()  
        {  
      
            if (File.Exists(DataItemsFileName)) return;  
      
            var list = new List<DataMapColumn>  
            {  
                new DataMapColumn() { ConfigurationId = 1, Name = "A1", DisplayName = "DateDate" },  
                new DataMapColumn() { ConfigurationId = 2, Name = "A40", DisplayName = "Prod" },  
                new DataMapColumn() { ConfigurationId = 1, Name = "A4", DisplayName = "Item" },  
                new DataMapColumn() { ConfigurationId = 1, Name = "A10", DisplayName = "Site" }  
            };  
      
            File.WriteAllText(DataItemsFileName,   
                JsonConvert.SerializeObject(list, Formatting.Indented));  
        }  
      
        public static List<DataMapColumn> Columns   
            => JsonConvert.DeserializeObject<List<DataMapColumn>>(  
                File.ReadAllText(DataItemsFileName));  
      
        public static List<ConfigurationItem> Configurations  
            => JsonConvert.DeserializeObject<List<ConfigurationItem>>(  
                File.ReadAllText(ConfigurationFileName));  
    }  
    

    Configuration file (generated in FileOperations)

    [  
      {  
        "Id": 1,  
        "Name": "First"  
      },  
      {  
        "Id": 2,  
        "Name": "Second"  
      }  
    ]  
    

    Mapping file (generated in FileOperations)

    [  
      {  
        "ConfigurationId": 1,  
        "Name": "A1",  
        "Ordinal": 0,  
        "DisplayName": "DateDate"  
      },  
      {  
        "ConfigurationId": 2,  
        "Name": "A40",  
        "Ordinal": 0,  
        "DisplayName": "Prod"  
      },  
      {  
        "ConfigurationId": 1,  
        "Name": "A4",  
        "Ordinal": 0,  
        "DisplayName": "Item"  
      },  
      {  
        "ConfigurationId": 1,  
        "Name": "A10",  
        "Ordinal": 0,  
        "DisplayName": "Site"  
      }  
    ]  
    

    Form to show and select a configuration

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Windows.Forms;  
    using DataGridViewColumns.Classes;  
      
    namespace DataGridViewColumns  
    {  
        public partial class ConfigForm : Form  
        {  
            private readonly List<DataMapColumn> _dataMapColumns;  
            public ConfigForm()  
            {  
                InitializeComponent();  
      
                FileOperations.WriteConfigurationItems();  
                FileOperations.WriteDataItems();  
      
                _dataMapColumns = FileOperations.Columns;  
      
                Shown += OnShown;  
            }  
      
            private void OnShown(object sender, EventArgs e)  
            {  
                ConfigurationsListBox.DataSource = FileOperations.Configurations;  
            }  
      
            private void SelectButton_Click(object sender, EventArgs e)  
            {  
                var builder = new StringBuilder();  
      
                var selected = (ConfigurationItem)ConfigurationsListBox.SelectedItem;  
      
                var result =   
                    _dataMapColumns.Where(dataColumnMap =>   
                        dataColumnMap.ConfigurationId == selected.Id);  
      
                foreach (var column in result)  
                {  
                    builder.AppendLine($"{column.Name,-5}{column.DisplayName}");  
                }  
      
                textBox1.Text = builder.ToString();  
            }  
        }  
    }  
      
    

    178516-f1.png


2 additional answers

Sort by: Most helpful
  1. Lance James 366 Reputation points
    2022-02-27T18:03:40.37+00:00

    Gents, I just read that multidimensional arrays are not enumerable. With the noise out of the way, this solution dropped into place nicely. Would this be the method to use?

            public void ChangeColumnsNew(DataTable table, Helper h)
            {
                for (int i = 0; i < h.GACColumns.GetLength(0); i++)
                {
                    table.Columns[h.GACColumns[i, 0]].ColumnName = h.GACColumns[i, 1];
                }
            }
    

    Regards,
    Lance


  2. Karen Payne MVP 35,386 Reputation points
    2022-02-27T20:25:51.957+00:00

    A different approach, load configurations into a json file e.g.

    [  
      {  
        "Name": "A1",  
        "Ordinal": 0,  
        "DisplayName": "DateDate"  
      },  
      {  
        "Name": "A4",  
        "Ordinal": 0,  
        "DisplayName": "Item"  
      },  
      {  
        "Name": "A10",  
        "Ordinal": 0,  
        "DisplayName": "Site"  
      }  
    ]  
    

    Class

    public class DataColumn  
    {  
        public string Name { get; set; }  
        public int Ordinal { get; set; }  
        public string DisplayName { get; set; }  
      
    }  
    

    Note, Ordinal is not used but can provide a way to reorder columns if needed.

    Simple example using mocked data

    public partial class Form1 : Form  
    {  
        public Form1()  
        {  
            InitializeComponent();  
            Shown += OnShown;  
        }  
      
        private void OnShown(object sender, EventArgs e)  
        {  
            DataTable dt = LoadData();  
            dataGridView1.DataSource = dt;  
      
            foreach (var column in DataOperations.Columns.Where(column => dt.Columns.Contains(column.Name)))  
            {  
                dt.Columns[column.Name].ColumnName = column.DisplayName;  
            }  
        }  
      
      
        private DataTable LoadData()  
        {  
            var table = new DataTable();  
      
            table.Columns.Add("A1", typeof(DateTime));  
            table.Columns.Add("A4", typeof(string));  
            table.Columns.Add("A10", typeof(string));  
      
      
            table.Rows.Add(DateTime.Now, "Hello", "World");  
            table.Rows.Add(DateTime.Now.AddDays(-1), "Hi", "There");  
      
            return table;  
        }  
    }  
    

    Mocking config file and reading config file using Json.net NuGet package.

    public class DataOperations  
    {  
        private static string _fileName = "Configuration.json";  
      
        /// <summary>  
        /// Mock-up  
        /// </summary>  
        public static void Write()  
        {  
            List<DataColumn> list = new List<DataColumn>  
            {  
                new DataColumn() { Name = "A1", DisplayName = "DateDate" },  
                new DataColumn() { Name = "A4", DisplayName = "Item" },  
                new DataColumn() {Name = "A10", DisplayName = "Site" }  
            };  
      
            File.WriteAllText(_fileName, JsonConvert.SerializeObject(list, Formatting.Indented));  
        }  
      
        public static List<DataColumn> Columns   
            => JsonConvert.DeserializeObject<List<DataColumn>>(File.ReadAllText(_fileName));  
    }  
    

    178167-f1.png