如何使用 VSTO 顺利地将数据从 C# 获取到 Excel 并再次返回

发布于 2025-01-05 01:32:02 字数 741 浏览 1 评论 0原文

我正在用 C# 编写 Excel 的应用程序级插件。

该加载项用于将外部来源的数据(加载项为此提供一些 GUI 选项等)获取到 Excel 中。该数据不会被更新并发送回数据源或类似的东西 - 尽管用户当然可以自由地在本地 Excel 应用程序中编辑数据。

数据以 XML 格式到达,目前我使用代码生成工具能够将 xml 文档反序列化为 C# 对象。数据遵循关系模型。

我现在正在考虑的事情:

  • 我应该将所有内容都转换为带有 DataTables 的 DataSet 对象吗?
  • 如果我这样做了,我怎样才能将这些数据放入 Excel 工作表中呢?是否可以在 Excel 中创建一个表并将数据绑定到我的数据表/数据集?
  • 实际上,我认为我本身并不想要一个“表”,而是只需将数据放入单元格中,然后用户就可以使用这些单元格。那么只提供 2D 数组是否更好?但是从 DataTable 数据行转换为 2D 数组不是很痛苦吗?

还有其他一些问题...

  • 将数据从 Excel 读回 C# 的最简单/最佳方法是什么?我想我对在这里获得二维数组最满意。但遍历“Range”对象似乎很麻烦。一定有更好的方法吗?
  • 该工作表可能会在第一行中包含列名称,然后在其余行中包含数据。当用户选择组成我的“表格”的单元格时,C# 代码有什么方法可以识别这一点吗?或者这只是我必须在代码中手动处理的事情?

我以前从未处理过这个问题,所以如果有些问题看起来很愚蠢,我深表歉意。任何帮助表示赞赏。

I'm writing an application level add-in for Excel in C#.

The add-in is to be used for getting data from a foreign source (the add-in provides some GUI options for this etc.) into Excel. This data is not going to be updated and sent back to the data source or anything like that - although the user is of course free to edit the data in the local Excel application.

The data arrives in an XML format and currently I have used a code generation tool to be able to deserialize the xml documents into C# objects. The data follows a relational model.

The things I'm thinking about right now:

  • Should I translate everything to a DataSet object with DataTables?
  • If I've done that, how can I then get this data into an Excel sheet? Is it possible to e.g. create a table in excel and databind to my datatables/dataset?
  • Really I don't think I want a "table" per se but just throw in the data into cells and the user can then work with the cells. Is it better then to just supply 2D arrays? But won't it be a pain to go from DataTable data rows to 2D arrays?

Some other questions as well...

  • What is the easiest/best way to read data back from Excel to C#? I think I'd mostly be satisfied with just getting 2D arrays here. But traversing the "Range" objects seems cumbersome. Must be some better way?
  • The sheet will likely have column names in the first row and then data in the rest of the rows. Is there any way for the C# code to recognize this when the user has selected the cells that make up my "table"? Or is this just something I'm going to have to take care of manually in the code?

I've never worked with this before so apologizing if some questions seem stupid. Any help is appreciated.

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

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

发布评论

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

评论(4

把梦留给海 2025-01-12 01:32:02

以下是我之前工作中打开 excel 并从 excel 获取数据的一些示例:
公共类 ExcelModule
{
私人 Excel.Application excelApp;
私人 Excel.Workbook excelBook;
私人 Excel.Worksheet excelSheet;

    object misValue = System.Reflection.Missing.Value;
    object oMissing = System.Reflection.Missing.Value;

    public ExcelModule()
    {

    }

    public void OpenWorksheet(string fileName, int sheetNum)
    {
        excelApp = new Excel.Application();
        excelBook = excelApp.Workbooks.Open(fileName,
                0,
                true,
                5,
                "",
                "",
                true,
                Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
                "\t",
                false,
                false,
                0,
                true,
                1,
                0);
        excelSheet = (Excel.Worksheet)excelBook.Worksheets.get_Item(sheetNum);

    }

    public string GetValue(string cellAddress)
    {
        if (excelSheet.get_Range(cellAddress, cellAddress).Value2 != null)
            return excelSheet.get_Range(cellAddress, cellAddress).Value2.ToString();
        else
            return "";
    }

    public int Close()
    {
        excelApp.Quit();
        return 0;
    }

    ~ExcelModule()
    {
        excelApp.Quit();
    }
}

要将数据写入 Excel,您可以使用:

excelSheet.get_Range(cellAddress, cellAddress).Value2 = "your text";

注意:
*我使用的是 VS10 和 Office2007

Here are some example from my previous work to open excel and get data from excel:
public class ExcelModule
{
private Excel.Application excelApp;
private Excel.Workbook excelBook;
private Excel.Worksheet excelSheet;

    object misValue = System.Reflection.Missing.Value;
    object oMissing = System.Reflection.Missing.Value;

    public ExcelModule()
    {

    }

    public void OpenWorksheet(string fileName, int sheetNum)
    {
        excelApp = new Excel.Application();
        excelBook = excelApp.Workbooks.Open(fileName,
                0,
                true,
                5,
                "",
                "",
                true,
                Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
                "\t",
                false,
                false,
                0,
                true,
                1,
                0);
        excelSheet = (Excel.Worksheet)excelBook.Worksheets.get_Item(sheetNum);

    }

    public string GetValue(string cellAddress)
    {
        if (excelSheet.get_Range(cellAddress, cellAddress).Value2 != null)
            return excelSheet.get_Range(cellAddress, cellAddress).Value2.ToString();
        else
            return "";
    }

    public int Close()
    {
        excelApp.Quit();
        return 0;
    }

    ~ExcelModule()
    {
        excelApp.Quit();
    }
}

To write data into Excel you may use:

excelSheet.get_Range(cellAddress, cellAddress).Value2 = "your text";

Notes:
*I'm using VS10 with Office2007

夏末的微笑 2025-01-12 01:32:02

不知道为什么我的问题被否决了......至少给出理由,否则他们下次怎样才能变得更好?

反正。在我看来,最好的解决方案是将我的数据放入 DataSet,然后在 Excel 应用程序中创建一个 ListObject,并使用它的数据绑定功能将我的数据放入 Excel。

以前没有意识到这个伟大的控制。

Not sure why my question was downvoted... At least give reasons, how else can they become better next time around?

Anyway. The best solution, it seems to me, is to get my data into a DataSet and then create a ListObject in the Excel application and use it's data binding features to get my data into Excel.

Was not aware of this great control before.

许仙没带伞 2025-01-12 01:32:02

在 Excel 中使用范围和二维数组将为您提供更好的性能。在这里,当您将传入的 xml 反序列化为对象时,无需将其转换为数据集,然后转换为二维数组。建议在代码的视图层中直接将对象转换为二维数组,然后与 Excel 工作表中的范围绑定。用于从范围读回数据到二维数组,然后将其转换回可以序列化的对象并将其发送回服务器。现在,您使用范围或数组的有效或准确程度将取决于工作表中数据的外观。要区分标题和数据,您可以查看命名范围,它会很有帮助。

Using range along with 2d array in Excel will give you beter performance. Here as you are deserializing incoming xml to object, there is no need to convert it into dataset then to 2d array. Would recommend in view layer of your code you directly tranform your object to 2d array and then bind with range in excel sheet. For reading back read data into 2d array from range and then tranform it back to object which you can serialize and send it back to server. Now how effectively or exactly you use range or array will depend on how data in your sheet looks. To distinguish between header and data you may have a look at named range, it can be helpful.

仅此而已 2025-01-12 01:32:02

Excel 表格(又名“ListObjects”)免费为您提供格式设置,并且易于使用。对应的类型是ListObject

您可以将它们与 LINQ 一起使用,而无需创建 DataSet 对象:

ListObject myTable; // usually declared somewhere else, eg. via the designer

var data = from x in myObjects select new
{
    Foo = x.Foo,
    Bar = x.Bar
};

myTable.SetDataBinding(data.ToList());

这将使用反射用您的数据填充表。在上面的示例中,您将有两列标题为 Foo 和 Bar 的行,以及与 myObjects 中的元素一样多的行。

当然,您可以使用更复杂的查询。对于您的情况,使用 Linq to XML 可能是一个好主意。关键是你可以用几行代码准确地完成你想要的事情。

此外,您还可以将任何 IList放入 SetDataBinding 中。

Excel tables (aka "ListObjects") give you formatting for free, and they are easy to use. The corresponding type is ListObject.

You can use them with LINQ, without having to manufacture a DataSet object:

ListObject myTable; // usually declared somewhere else, eg. via the designer

var data = from x in myObjects select new
{
    Foo = x.Foo,
    Bar = x.Bar
};

myTable.SetDataBinding(data.ToList());

This will fill the table with your data using reflection. In the example above, you will have two columns titled Foo and Bar, and as many rows as you had elements in myObjects.

Of course, you can use more complex queries. In your case, using Linq to XML is probably a good idea. The point is that you can do exactly what you want in a handful of lines.

Also, you can put any IList<object> into SetDataBinding.

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