通过标题名称而不是列索引引用 VSTO Excel ListObject 的列

发布于 2024-12-22 06:34:58 字数 1733 浏览 3 评论 0原文

实际上,我可以使用以下代码轻松读取 VSTO 中 ListObject 的内容。

在此示例中,我正在读取给定工作表中的所有产品。使用 Excel 表编辑数据,该表转换为 VSTO 内的 ListObject。我使用的是 VS2010 和 .NET 4.0,还有 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;
}

但有时用户想要添加另一行,甚至更改表的列顺序。所以我想知道是否有更好的方法通过列名而不是列索引来引用每一行。

一个可接受的解决方案是这样的:

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

提前感谢您对此的任何建议。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

天生の放荡 2024-12-29 06:34:58

我刚刚遇到了类似的问题。以下是我为获取标题名称所做的操作:

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.
    }
}

希望这有帮助!

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!

世界和平 2024-12-29 06:34:58
Sheet1.ListObjects("dataTable").DataBodyRange(2, "b").Value

假设您的表名为 dataTable,它有 3 列(a、b、c)和 2 行。
注意:我使用的是VBA。我认为您在使用 DataBodyRange 时应该可以工作。

var myValue = Sheet1.ListObjects("dataTable").DataBodyRange[1, "myColumnHeader"];
Sheet1.ListObjects("dataTable").DataBodyRange(2, "b").Value

Assuming your table is named dataTable which has 3 columns (a,b,c) and 2 rows.
Note: I am using VBA. I assume your could should work when using DataBodyRange.

var myValue = Sheet1.ListObjects("dataTable").DataBodyRange[1, "myColumnHeader"];
花开雨落又逢春i 2024-12-29 06:34:58

Sheet1.ListObjects("dataTable").ListColumns["ColumnName"].Range[rowOfInterest] 怎么样?

How about Sheet1.ListObjects("dataTable").ListColumns["ColumnName"].Range[rowOfInterest]?

猫性小仙女 2024-12-29 06:34:58

由于 ListObject 不提供该功能,因此您也可以使用 Range.Find..

Range cellFind = Sheet1.Cells.Find(What: "Column your looking for", After: Type.Missing, LookIn: Excel.XlFindLookIn.xlValues, LookAt: Excel.XlLookAt.xlWhole, SearchOrder: Excel.XlSearchOrder.xlByColumns, SearchDirection: Excel.XlSearchDirection.xlNext, MatchCase: false, SearchFormat: false);

if (cellFind != null)
{
   int columnIndex = cellFind.Column;
   ...
}

Since ListObject doesn't provide that functionality, alternatively you could use Range.Find..

Range cellFind = Sheet1.Cells.Find(What: "Column your looking for", After: Type.Missing, LookIn: Excel.XlFindLookIn.xlValues, LookAt: Excel.XlLookAt.xlWhole, SearchOrder: Excel.XlSearchOrder.xlByColumns, SearchDirection: Excel.XlSearchDirection.xlNext, MatchCase: false, SearchFormat: false);

if (cellFind != null)
{
   int columnIndex = cellFind.Column;
   ...
}
匿名的好友 2024-12-29 06:34:58

可以直接通过列名称访问ListObject列。 @shahkalpesh 和 @gap 很接近,但 ListObjects 上的索引器习惯用法(VBA,而不是 C#)不匹配。下面的示例构建一个简单的表格,通过名称“ColName2”引用第二列,并修改第二列中的第一个数据单元格;

object[,] Data = new object[,] {{  "ColName1", "ColName2"}, {  11, 12 }, {21, 22 }};
Excel.Range tblRange = Globals.SParameters.Range["B20:C22"];
tblRange.Value = Data;

Globals.SParameters.Controls.AddListObject(tblRange, "tblProdutos");
Globals.SParameters.ListObjects["tblProdutos"].ListColumns["ColName2"].DataBodyRange[1] = 55;

请注意,您可以使用“DataBodyRange”或“Range”; “DataBodyRange”不包括列标题,这通常是合适的。

You can access ListObject columns directly by column name. @shahkalpesh and @gap are close, but the indexer idiom (VBA, not c#) on the ListObjects is missmatched. The example below builds a simple table, references the second column by its name, "ColName2", and modifies the first data cell in the second column;

object[,] Data = new object[,] {{  "ColName1", "ColName2"}, {  11, 12 }, {21, 22 }};
Excel.Range tblRange = Globals.SParameters.Range["B20:C22"];
tblRange.Value = Data;

Globals.SParameters.Controls.AddListObject(tblRange, "tblProdutos");
Globals.SParameters.ListObjects["tblProdutos"].ListColumns["ColName2"].DataBodyRange[1] = 55;

Note that you can use 'DataBodyRange' or 'Range'; 'DataBodyRange' excludes the column header, which is usually appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文