RadGridView - Pasting from excel

5 posts, 1 answers
  1. Charles
    Charles avatar
    3 posts
    Member since:
    Feb 2016

    Posted 16 Oct 2017 Link to this post

    How may I configure RadGridView to allow pasting of multiple rows of data?  I am able to paste over existing selected rows, but when I need to paste more rows than are in the RadGridView it just stops at the last existing row.

    This can't be a new requirement, and I imagine there is just some documentation I can't find with my google foo... I found a few very old posts about manually handling pasting from the clipboard, but they were nearly a decade old.

    Basically, I'd like to use the RadGridView to manage x, y, z data rows.  It would start empty, and then be able to paste n rows from Excel into the empty grid.  Is this possible?  I was able to do it with the Spreadsheet control, but it's rather slow to load and crashes on occasion when disposing. 

    Thanks in advance!

  2. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3532 posts

    Posted 19 Oct 2017 Link to this post

    Hello, Charles,    

    Thank you for writing back. 

    Your question has already been answered in the other thread you have opened on the same topic "Pasting new rows from Excel into RadGridView". Please, see our answer there for more information.
    We kindly ask you to use just one thread for a specific problem to contact us. Posting the same questions numerous times slows down our response time because we will need to review and address two or more tickets instead of one. Moreover, threads are handled according to license and time of posting, so if it is an urgent problem, we suggest you use a support ticket, which would be handled before a forum thread.

    Thank you for your understanding.

    Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Charles
    Charles avatar
    3 posts
    Member since:
    Feb 2016

    Posted 21 Oct 2017 Link to this post

    The generic (assuming the datasource implements IList) solution I came up with which allows you to paste from Excel when the gridview is empty or populated while adding rows if over running existing rows, for anyone googling a solution.  I used CsvHelper to reliably parse the string from the clipboard to a dynamic object.  The properties are them mapped in order when it is possible to convert to the property so that it supports partial columns. I wanted to use AutoMapper for that part, but doing an optimistic index based mapping with it looks to be more of a hassle than just doing it manually.

     

    public class CustomGrid : RadGridView
    {
        protected override RadGridViewElement CreateGridViewElement()
        {
            return new CustomRadGridViewElement();
        }
     
        public override string ThemeClassName => typeof(RadGridView).FullName;
    }
     
    public class CustomRadGridViewElement : RadGridViewElement
    {
        protected override MasterGridViewTemplate CreateTemplate()
        {
            return new CustomMasterGridViewTemplate();
        }
     
        protected override Type ThemeEffectiveType => typeof(RadGridViewElement);
    }
     
    public class CustomMasterGridViewTemplate : MasterGridViewTemplate
    {
        public static bool CanChangeType(object value, Type conversionType)
        {
            if (conversionType == null)
            {
                return false;
            }
     
            if (value == null)
            {
                return false;
            }
     
            IConvertible convertible = value as IConvertible;
     
            if (convertible == null)
            {
                return false;
            }
     
            return true;
        }
     
        public override void Paste()
        {
            if (Clipboard.ContainsData(DataFormats.Text))
            {
                var dataSource = this.Owner.DataSource as IList;
                if (dataSource != null)
                {
                    string data = Clipboard.GetData(DataFormats.Text).ToString();
                    if (!string.IsNullOrWhiteSpace(data))
                    {
                        using (TextReader reader = new StringReader(data))
                        {
                            var csv = new CsvReader(reader, new Configuration(){HasHeaderRecord = false, Delimiter = "\t"});
                            IEnumerable<object> records = null;
                            var type = dataSource.GetType().GetGenericArguments().Single();
                            try
                            {
                                records = csv.GetRecords<dynamic>().ToList();
                                var count = records.Count();
                            }
                            catch { }
     
                            if (records != null)
                            {
                                var rowIndex = 0;
                                if (this.Owner.SelectedCells.Any())
                                    rowIndex = this.Owner.SelectedCells.Select(c => c.RowInfo.Index).Min();
                                if (this.Owner.SelectedRows.Any())
                                    rowIndex = this.Owner.SelectedRows.Select(r => r.Index).Min();
                                if (rowIndex == -1)
                                    rowIndex = this.Owner.RowCount;
     
                                foreach (var record in records)
                                {
                                    if (dataSource.Count == rowIndex)
                                    {
                                        dataSource.Add(Activator.CreateInstance(type));
                                    }
                                    var propertyValues = (IDictionary<string, object>)record;
                                    var properties = dataSource[rowIndex].GetType().GetProperties();
                                    var propertyIndex = 0;
                                    foreach (var propertyValue in propertyValues)
                                    {
                                        while (!CanChangeType(propertyValue.Value, properties[propertyIndex].PropertyType) && propertyIndex < properties.Length)
                                        {
                                            propertyIndex++;
                                        }
     
                                        if (propertyIndex < properties.Length)
                                        {
                                            var value = Convert.ChangeType(propertyValue.Value, properties[propertyIndex].PropertyType);
                                            properties[propertyIndex].SetValue(dataSource[rowIndex], value);
                                        }
                                    }
                                    rowIndex++;
                                }
                                this.Refresh();
                                return;
                            }
                        }
                    }
                }
            }
            base.Paste();
        }
    }

     

     

     

     

  4. Charles
    Charles avatar
    3 posts
    Member since:
    Feb 2016

    Posted 21 Oct 2017 in reply to Charles Link to this post

    Missed a line in the paste, but this should be used for the value assignment.  The above missed the propertyIndex++ after writing the value.  

     

    if (propertyIndex < properties.Length)
    {
        var value = Convert.ChangeType(propertyValue.Value, properties[propertyIndex].PropertyType);
        properties[propertyIndex].SetValue(dataSource[rowIndex], value);
        propertyIndex++;
    }
  5. Answer
    Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3532 posts

    Posted 23 Oct 2017 Link to this post

    Hello, Charles,    

    Thank you for writing back. 

    I am glad that the suggested approach in the support thread that you have on the same topic was useful. Thank you for sharing your solution with the community and someone can benefit from it.

    If you have any additional questions, please let me know. 

     Regards,
    Dess
    Progress Telerik
    Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top