Excel – Reference VSTO Excel ListObject’s columns by header name instead of column index

excelvsto

Actually I can easily read the content of a ListObject in VSTO using the following code.

In this example I'm reading all the products from a given sheet. The data is edited using a Excel Table, which tranlates to an ListObject inside VSTO. I'm using VS2010 with .NET 4.0 and also, Excel 2010.

private IEnumerable<Produto> ReadFromWorksheet()
{
    var produtosLidos = new List<Produto>();


    try
    {
        foreach (Excel.ListRow row in Globals.Sheet1.tblProdutos.ListRows)
        {

            var id = RangeUtils.ToInt(row.Range[1, 1]) ?? -1;
            var codigo = RangeUtils.ToString(row.Range[1, 2]);
            var nome = RangeUtils.ToString(row.Range[1, 3]);
            var qtdDisp = RangeUtils.ToDecimal(row.Range[1, 4]);
            var unidMed = RangeUtils.ToString(row.Range[1, 5]);
            var valor = RangeUtils.ToDecimal(row.Range[1, 6]);


            if (string.IsNullOrEmpty(codigo) ||nome == null || qtdDisp == null || unidMed == null || valor == null)
                throw new ApplicationException("Os campos Nome, Qtd. Disponível, Unid. de Medida e Valor são obrigatórios.");


            var p = new Produto();
            p.Id = id;
            p.CodigoProduto = codigo;
            p.Nome = nome;
            p.QtdDisponivel = qtdDisp;
            p.UnidadeMedida = unidMed;
            p.Valor = valor;
            p.DataUltimaAlteracao = DateTime.Now;
            p.Acao = RangeUtils.ToString(row.Range[1, 8]);
            p.Ativo = true;

            produtosLidos.Add(p);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
    return produtosLidos;
}

But sometimes the user wants do add another row or even change the column order of the table. So I would like to know if there's a better way to reference each row by the column name instead of the column index.

An acceptable solution for this would be something like this:

var myValue = row.Range[1, "My Value"];

Thanks in advance for any advice on this.

Best Answer

I just ran into a similar issue. Here is what I did to get to the header names:

private void listSPRData_BeforeDoubleClick(Range Target, ref bool Cancel)
{
    foreach (Range c in Target.ListObject.HeaderRowRange.Cells)
    {
        // Do something...
        // "c.Value" contains the name of your header.
        // When you find your column, you can break to avoid unnecessary looping.
    }
}

Hope this helps!

Related Topic