我正在编写一个应用程序,我需要从数据库中检索一些行并将它们转储到Excel电子表格中。我正在使用Linq来检索这些行。
是否可以将这些行直接转储到Excel工作表中的对应部分(其中Excel中的一个单元格对应于数据库中的一个单元格)?
答案 0 :(得分:18)
我个人并不是使用库来做这些事情的忠实粉丝,因为我总是觉得它稍后会限制...
我使用反射来生成列标题并获取每行的单元格值。如果您使用的是.NET Framework 3.5,则可以利用扩展方法,以便将任何IEnumerable<object>
导出到excel XDocument文件。
我是这样做的:
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;
}
}
}
我还创建了另一种扩展方法,以便在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;
}
希望这有帮助!
答案 1 :(得分:5)
没有直接的方法来连接这两个。听起来你想要LINQ to SQL来处理查询生成,而不是O / R映射(因为Excel不知道如何处理来自LINQ的对象 - 它们看起来不再像数据行了)。您可以通过调用(datacontext).GetCommand(yourLinqQueryHere),然后在SqlCommand中将其作为CommandText运行来完成第一部分。调用ExecuteReader(),然后调用GetSchemaTable()来确定列的顺序。然后(假设您正在自动化Excel)将(DbDataReader).GetValues()的结果传递给Excel(工作表).Row [x] .Values并且它会将结果显示出来。您可能需要重新排序内容。如果您没有自动化Excel,则需要使用带有OleDbConnection的Excel的OLED OLEDB提供程序转储值,或使用第三方组件生成电子表格。
答案 2 :(得分:1)
你可以:
答案 3 :(得分:1)
看看这个Excel Data Object Provider。我没有亲自使用它的写入功能,我调整了阅读支持以允许有序(以及命名)列标识符,但它可能是朝着正确方向迈出的一步。请记住,除非在目标计算机上安装了Excel 2003+,否则无法写入或读取XLSX文件;标准的XLS文件可以在任何Windows机器上使用。
我可以找到带有序数列的改编版here。如果您决定使用该代码,您可能会发现在当前版本(在上面的链接中)实现它是必要/有用的。我的版本是version 2.0和2.5的混合功能 - 它具有所有阅读功能(有2.5次升级),但没有写作。哦 - 与版本2.0或2.5不同,我的版本不要求Excel文档中的第一个工作表命名为“Sheet1”。
希望有所帮助!
答案 4 :(得分:0)
最快的解决方案是创建一个csv文件:
col1, colb, colc
col1, colb, colc
Excel可以很好地处理csv文件。
答案 5 :(得分:0)
您使用LINQ检索数据这一事实有点无关紧要。你真正想要的是一个编写Excel的好库。完成后,您可以简单地遍历结果以在Excel工作表中创建行。
就我使用NPOI的图书馆而言,它很棒。