简体   繁体   English

如何使用Linq写入Excel电子表格?

[英]How can I write to an Excel spreadsheet using Linq?

I'm writing an app where I need to retrieve some rows from a DB and dump them into an Excel spreadsheet. 我正在编写一个应用程序,我需要从数据库中检索一些行并将它们转储到Excel电子表格中。 I'm using Linq to retrieve these rows. 我正在使用Linq来检索这些行。

Is it possible to dump these rows directly into their counterparts in the Excel sheet (where one cell in Excel corresponds to one cell from the DB)? 是否可以将这些行直接转储到Excel工作表中的对应部分(其中Excel中的一个单元格对应于数据库中的一个单元格)?

I am personally not a big fan of using libraries to such things as I always find it limiting at some point later... 我本人并不是使用库来做这些事情的忠实粉丝,因为我总是发现它在某些时候会受到限制......

I used reflection in order to generate the column headers and get the cell values of each row. 我使用反射来生成列标题并获取每行的单元格值。 And if you are using .NET framework 3.5 your can take advantage of extensions methods so that you can export any IEnumerable<object> to an excel XDocument file. 如果您使用的是.NET Framework 3.5,则可以利用扩展方法,以便将任何IEnumerable<object>导出到excel XDocument文件。

Here is how I did it: 我是这样做的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace YourNameSpace
{
    public static class ExcelExportExtensions
    {
        public static XDocument ToExcelXml(this IEnumerable<object> rows)
        {
            return rows.ToExcelXml("Sheet1");
        }

        public static XDocument ToExcelXml(this IEnumerable<object> rows, string sheetName)
        {
            sheetName = sheetName.Replace("/", "-");
            sheetName = sheetName.Replace("\\", "-");

            XNamespace mainNamespace = "urn:schemas-microsoft-com:office:spreadsheet";
            XNamespace o = "urn:schemas-microsoft-com:office:office";
            XNamespace x = "urn:schemas-microsoft-com:office:excel";
            XNamespace ss = "urn:schemas-microsoft-com:office:spreadsheet";
            XNamespace html = "http://www.w3.org/TR/REC-html40";

            XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

            var headerRow = from p in rows.First().GetType().GetProperties()
                            select new XElement(mainNamespace + "Cell",
                                new XElement(mainNamespace + "Data",
                                    new XAttribute(ss + "Type", "String"), p.Name)); //Generate header using reflection

            XElement workbook = new XElement(mainNamespace + "Workbook",
                new XAttribute(XNamespace.Xmlns + "html", html),
                new XAttribute(XName.Get("ss", "http://www.w3.org/2000/xmlns/"), ss),
                new XAttribute(XName.Get("o", "http://www.w3.org/2000/xmlns/"), o),
                new XAttribute(XName.Get("x", "http://www.w3.org/2000/xmlns/"), x),
                new XAttribute(XName.Get("xmlns", ""), mainNamespace),
                new XElement(o + "DocumentProperties",
                        new XAttribute(XName.Get("xmlns", ""), o),
                        new XElement(o + "Author", "Smartdesk Systems Ltd"),
                        new XElement(o + "LastAuthor", "Smartdesk Systems Ltd"),
                        new XElement(o + "Created", DateTime.Now.ToString())
                    ), //end document properties
                new XElement(x + "ExcelWorkbook",
                        new XAttribute(XName.Get("xmlns", ""), x),
                        new XElement(x + "WindowHeight", 12750),
                        new XElement(x + "WindowWidth", 24855),
                        new XElement(x + "WindowTopX", 240),
                        new XElement(x + "WindowTopY", 75),
                        new XElement(x + "ProtectStructure", "False"),
                        new XElement(x + "ProtectWindows", "False")
                    ), //end ExcelWorkbook
                new XElement(mainNamespace + "Styles",
                        new XElement(mainNamespace + "Style",
                            new XAttribute(ss + "ID", "Default"),
                            new XAttribute(ss + "Name", "Normal"),
                            new XElement(mainNamespace + "Alignment",
                                new XAttribute(ss + "Vertical", "Bottom")
                            ),
                            new XElement(mainNamespace + "Borders"),
                            new XElement(mainNamespace + "Font",
                                new XAttribute(ss + "FontName", "Calibri"),
                                new XAttribute(x + "Family", "Swiss"),
                                new XAttribute(ss + "Size", "11"),
                                new XAttribute(ss + "Color", "#000000")
                            ),
                            new XElement(mainNamespace + "Interior"),
                            new XElement(mainNamespace + "NumberFormat"),
                            new XElement(mainNamespace + "Protection")
                        ),
                        new XElement(mainNamespace + "Style",
                            new XAttribute(ss + "ID", "Header"),
                            new XElement(mainNamespace + "Font",
                                new XAttribute(ss + "FontName", "Calibri"),
                                new XAttribute(x + "Family", "Swiss"),
                                new XAttribute(ss + "Size", "11"),
                                new XAttribute(ss + "Color", "#000000"),
                                new XAttribute(ss + "Bold", "1")
                            )
                        )
                    ), // close styles
                    new XElement(mainNamespace + "Worksheet",
                        new XAttribute(ss + "Name", sheetName /* Sheet name */),
                        new XElement(mainNamespace + "Table",
                            new XAttribute(ss + "ExpandedColumnCount", headerRow.Count()),
                            new XAttribute(ss + "ExpandedRowCount", rows.Count() + 1),
                            new XAttribute(x + "FullColumns", 1),
                            new XAttribute(x + "FullRows", 1),
                            new XAttribute(ss + "DefaultRowHeight", 15),
                            new XElement(mainNamespace + "Column",
                                new XAttribute(ss + "Width", 81)
                            ),
                            new XElement(mainNamespace + "Row", new XAttribute(ss + "StyleID", "Header"), headerRow),
                            from contentRow in rows
                            select new XElement(mainNamespace + "Row",
                                new XAttribute(ss + "StyleID", "Default"),
                                    from p in contentRow.GetType().GetProperties()
                                    select new XElement(mainNamespace + "Cell",
                                         new XElement(mainNamespace + "Data", new XAttribute(ss + "Type", "String"), p.GetValue(contentRow, null))) /* Build cells using reflection */ )
                        ), //close table
                        new XElement(x + "WorksheetOptions",
                            new XAttribute(XName.Get("xmlns", ""), x),
                            new XElement(x + "PageSetup",
                                new XElement(x + "Header",
                                    new XAttribute(x + "Margin", "0.3")
                                ),
                                new XElement(x + "Footer",
                                    new XAttribute(x + "Margin", "0.3")
                                ),
                                new XElement(x + "PageMargins",
                                    new XAttribute(x + "Bottom", "0.75"),
                                    new XAttribute(x + "Left", "0.7"),
                                    new XAttribute(x + "Right", "0.7"),
                                    new XAttribute(x + "Top", "0.75")
                                )
                            ),
                            new XElement(x + "Print",
                                new XElement(x + "ValidPrinterInfo"),
                                new XElement(x + "HorizontalResolution", 600),
                                new XElement(x + "VerticalResolution", 600)
                            ),
                            new XElement(x + "Selected"),
                            new XElement(x + "Panes",
                                new XElement(x + "Pane",
                                    new XElement(x + "Number", 3),
                                    new XElement(x + "ActiveRow", 1),
                                    new XElement(x + "ActiveCol", 0)
                                )
                            ),
                            new XElement(x + "ProtectObjects", "False"),
                            new XElement(x + "ProtectScenarios", "False")
                        ) // close worksheet options
                    ) // close Worksheet
                );

            xdoc.Add(workbook);

            return xdoc;
        }
    }
}

I have also created another extention method to ease return the XDocument in web scenarios: 我还创建了另一种扩展方法,以便在Web场景中轻松返回XDocument:

public static DownloadableFile ToDownloadableXmlFileForExcel2003(this System.Xml.Linq.XDocument file, string fileName)
{
    MemoryStream ms = new MemoryStream();

    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings() { Encoding = Encoding.UTF8 };
    XmlWriter xmlWriter = XmlWriter.Create(ms, xmlWriterSettings);

    file.Save(xmlWriter);   //.Save() adds the <xml /> header tag!
    xmlWriter.Close();      //Must close the writer to dump it's content its output (the memory stream)

    DownloadableFile dbf = 
            new DownloadableFile
            {
                FileName = String.Format("{0}.xls", fileName.Replace(" ", "")),
                Content  = ms.ToArray(),
                MimeType = "application/vnd.ms-excel"
            };

    ms.Close();
    ms.Dispose();

    return dbf;
}

Hope this helps! 希望这可以帮助!

There's no direct way to connect these two. 没有直接的方法来连接这两个。 It sounds like you want LINQ to SQL to handle the query generation, but not the O/R mapping (because Excel wouldn't know what to do with the objects that come out of LINQ- they don't look like data rows any more). 听起来你想要LINQ to SQL来处理查询生成,而不是O / R映射(因为Excel不知道如何处理来自LINQ的对象 - 它们看起来不再像数据行了)。 You can do that first part by calling (datacontext).GetCommand(yourLinqQueryHere), then running that as the CommandText in a SqlCommand. 您可以通过调用(datacontext).GetCommand(yourLinqQueryHere),然后在SqlCommand中将其作为CommandText运行来完成第一部分。 Call ExecuteReader(), then GetSchemaTable() to figure out the order of the columns. 调用ExecuteReader(),然后调用GetSchemaTable()来确定列的顺序。 Then (assuming you're automating Excel) pass the result of (DbDataReader).GetValues() to Excel's (Worksheet).Row[x].Values and it'll splat the results in. You might need to reorder stuff. 然后(假设您正在自动化Excel)将(DbDataReader).GetValues()的结果传递给Excel(工作表).Row [x] .Values并且它会将结果显示出来。您可能需要重新排序内容。 If you're not automating Excel, you'd need to dump the values in using the Jet OLEDB provider for Excel with an OleDbConnection, or use a 3rd party component to generate the spreadsheet. 如果您没有自动化Excel,则需要使用带有OleDbConnection的Excel的OLED OLEDB提供程序转储值,或使用第三方组件生成电子表格。

You can: 您可以:

Take a look at this Excel Data Object Provider . 看一下这个Excel数据对象提供程序 I haven't personally used the writing functionality of it and I adapted the reading support to allow for ordinal (as well as named) column identifiers, but it may be a step in the right direction. 我没有亲自使用它的写入功能,我调整了阅读支持以允许有序(以及命名)列标识符,但它可能是朝着正确方向迈出的一步。 Keep in mind that you cannot write or read from XLSX files unless Excel 2003+ is installed on the target machine; 请记住,除非在目标计算机上安装了Excel 2003+,否则无法写入或读取XLSX文件; standard XLS files will work on any Windows box though. 标准的XLS文件可以在任何Windows机器上使用。

My adapted version with ordinal columns can be found here . 我可以在这里找到带有序数列的改编版本。 You may find it necessary/helpful to implement that in the current version (at the above link) if you decide to use the code. 如果您决定使用该代码,您可能会发现在当前版本(在上面的链接中)实现它是必要/有用的。 My version is a hybrid of features from the version 2.0 and 2.5- it has all of the reading functionality (with some 2.5 upgrades), but no writing. 我的版本是2.0和2.5版本的混合功能 - 它具有所有阅读功能(有2.5次升级),但没有写作。 Oh- and unlike either version 2.0 or 2.5, my version doesn't require that the first sheet in the Excel document be named "Sheet1". 哦 - 与版本2.0或2.5不同,我的版本不要求Excel文档中的第一个工作表命名为“Sheet1”。

Hope that helps! 希望有所帮助!

The quickest solution will be to create a csv file: 最快的解决方案是创建一个csv文件:

col1, colb, colc
col1, colb, colc

Excel works very well with csv files. Excel与csv文件配合得很好。

The fact that you're retrieving your data with LINQ is sort of irrelevant. 您使用LINQ检索数据的事实是无关紧要的。 What you're really after is a good library to write Excel. 你真正想要的是一个编写Excel的好库。 Once you've got that, you can simply iterate through your results to create rows in your Excel worksheet. 完成后,您可以简单地遍历结果以在Excel工作表中创建行。

As far as a library I've used NPOI , and it's been great. 就图书馆而言,我使用的是NPOI ,它一直很棒。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 OpenXML 仅在 Excel 电子表格中获取可见单元格? - How can I only get visible cells in an Excel spreadsheet using OpenXML? 如何使用EPPlus在excel电子表格中隐藏大量列? - How can I hide a large number of columns in an excel spreadsheet using EPPlus? 如何在 LINQ 中编写此查询 - How can I write this query in LINQ 如何在linq to sql中编写此查询? - How can I write this query in linq to sql? C#:如何导出到Excel电子表格? 使用XSLT / LINQ /其他方法? - C#: How to export to an excel spreadsheet? using XSLT / LINQ / Other methods? 如何从 Sharepoint 文档库自动签出 Excel 电子表格、编辑电子表格并重新签入? - How can I automate the checkout of an excel spreadsheet from a sharepoint document library, edit the spreadsheet, and check it back in? 如何通过链接而不是图像文件通过Spreadsheet Light将图片插入Excel电子表格? - How can I insert a picture into an Excel spreadsheet with Spreadsheet Light from a link rather than an image file? 如何连续写入Excel文件? - How can I write to an excel file continuously? 如何使用LINQ查询语法更优雅地编写以下代码? - How can I write the following code more elegantly using LINQ query syntax? 如何获得Excel更新Excel-DNA RTD电子表格? - How can I get excel to update spreadsheet for Excel-DNA RTD?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM