DataGrid to Excel?
本文关键字:Excel to DataGrid | 更新日期: 2023-09-27 18:29:03
我在WPF中创建了一个程序。它显示一个DataGrid
,其中包含MySQL数据库中的数据。我想做的是允许用户将DataGrid
的内容导出到Excel文件中。WPF有可能做到这一点吗?
当我使用此处显示的方法时:https://www.outcoldman.ru/en/blog/show/201
导入到xls文件的唯一一行是标题。
我也在寻找类似的东西来帮助将数据网格中的数据导出到excel中,但没有找到任何有效的方法。至少我刚刚将DataGrid的内容转换为一个2D字符串数组,并使用interop.dll导出它。
代码看起来像这样:
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
Excel.Range rangeToHoldHyperlink;
Excel.Range CellInstance;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlApp.DisplayAlerts = false;
//Dummy initialisation to prevent errors.
rangeToHoldHyperlink = xlWorkSheet.get_Range("A1", Type.Missing);
CellInstance = xlWorkSheet.get_Range("A1", Type.Missing);
for (int i = 0; i < NumberOfCols; i++)
{
for (int j = 0; j <= NumberOfRows; j++)
{
xlWorkSheet.Cells[j + 1, i + 1] = DataToWrite[j][i];
}
}
如果你正在寻找一些格式化,它们也在这里得到支持。我想添加一个超链接,下面的代码做到了:
CellInstance = xlWorkSheet.Cells[j + 1, i + 1];
xlWorkSheet.Hyperlinks.Add(
CellInstance,
DataToWrite[j][i],
Type.Missing,
"Hover Text Comes Here",
"Text to be displayed");
如果你想让第一行成为标题,你可以如下突出显示它们:
Excel.Range Range1 = xlWorkSheet.get_Range("A1");
Range1.EntireRow.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Black);
Range1.EntireRow.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightSkyBlue);
Range1.EntireRow.Font.Size = 14;
Range1.EntireRow.AutoFit();
最后将excel保存在所需路径中:
xlWorkBook.SaveAs(@FilePath, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close();
对interop的引用添加如下:
Right Click on the Project name -> Click "Add reference" -> Goto "COM" tab -> Search for "Microsoft Excel Object Library" click "OK" to add the reference.
您必须使用以下命名空间:
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
您还可以将DataGrid内容导出到CSV文件中。
我不知道你是否在使用数据绑定,这里我假设你使用了。
var items = LoadItemsFromUnderlyingDataStore();
itemsDataGrid.ItemsSource = items;
private void ItemsDataGridExportButton_Click(object sender, EventArgs e) {
var filename = AutoGenerateDateTimedFileName();
using (var csv = new FileStream(filename)) {
// if you want any column header in your Excel file, uncomment line below.
//csv.WriteLine("Column1,Column2,Column3,Column4");
items.ForEach(item =>
csv.WriteLine("{0},{1},{2},{3}"
, item.PropertyFromFirstColumn
, item.PropertyFromSecondColumn
, item.PropertyFromThirdColumn
, item.PropertyFromFourthColumn);
try { csv.Flush(); }
catch(IOException ex) {
// Handle error (log, whatever...)
throw; // If you need to let the exception bubble up...
}
}
}
private string AutoGenerateDateTimedFileName() {
return string.Format("DataGridExport_{0}_{1}.csv"
, DataTime.Today.ToShortDateString()
, DateTime.Now.ToLongTimeString());
}
总之,这个代码示例应该使用CSV文件,之后您可以使用Excel打开它。您甚至可以在创建文件时启动Excel。
private void ItemsDataGridExportButton_Click(object sender, EventArgs e) {
// here's the upper code sample, and add the following:
Process.Start(filename)
}
现在,使用Excel Interop。
object[,] values = BuildTwoDimensionalMatrixFromDataGridContent();
Worksheet.Cells.Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault) = values;
这可能是在Excel文件中设置值的最快方法,而且不需要迭代。
第一个提出的使用CSV文件的解决方案可能是最容易理解和使用的。
免责声明
这段代码是我从头开始创建的,因此还没有经过测试。为了使此代码与程序的上下文正确工作,可能需要进行一些更改。此外,这里显示的带有interop的代码和您将能够与WPF一起使用的代码之间可能需要进行细微的差异分析
最好的方法可能是为自己编写一个类库,该类库将与用普通C#编写的解决方案一起部署,这样您就可以使用简单的Interop指令。
此链接可能对您有用-
从Silverlight/WPF DataGrid 将数据导出到Excel
示例代码从C:''Windows''WinSxS中检索所有目录的列表,将其绑定到DataGrid并将DataGrid导出到Excel。这里的核心是要知道,将数据导出到Excel的最快方法是将数组分配给工作表。但问题是我们不能直接从DataGrid中获取这个数组。因此,我们首先需要填充它。使用一点反射,我们可以获得属性值并填充数组。导出数据完全是一行。我电脑上的WinSxS文件夹包含14880个目录。该代码运行约3秒(填充DataGrid+export)。
using Excel = Microsoft.Office.Interop.Excel;
private void ExportDataGrid()
{
// Fetch directories
var dirInfo = new DirectoryInfo(@"C:'Windows'WinSxS'");
var items = dirInfo.EnumerateDirectories();
dataGrid.ItemsSource = items;
var source = dataGrid.ItemsSource;
// Create Excel app
var excel = new Excel.Application { Visible = true };
excel.ScreenUpdating = false; //Some speed-up
var book = excel.Workbooks.Add();
var sheet = (Excel.Worksheet)book.Sheets[1];
int row = -1; //The row in array
Type type = null;
// Create array to hold data
int rows = items.Count(), cols = dataGrid.Columns.Count;
var arr = new object[rows, cols];
foreach (DirectoryInfo dir_info in dataGrid.ItemsSource)
{
++row;
// You can also use GetType().GetTypeInfo() as of .NET 4.5+.
// The return type will be TypeInfo.
type = dir_info.GetType();
for (int col = 0; col < cols; ++col)
{
var column_name = (string)dataGrid.Columns[col].Header;
var value = type.GetProperty(column_name).GetValue(dir_info);
arr.SetValue(value, row, col);
}
}
// Create header
for (int col = 0; c < cols; ++c)
{
sheet.Cells[1, col + 1].Value = dataGrid.Columns[col].Header;
}
// Dump array - the fastest way
sheet.Range["A2"].Resize[rows, cols].Value = arr;
// Restore screen updating - otherwise Excel will not response to actions
excel.ScreenUpdating = true;
}
private void data2Exel(DataGrid dataGrid)
{
Excel.Application excel = new Excel.Application();
excel.Visible = true; //www.yazilimkodlama.com
Workbook workbook = excel.Workbooks.Add(System.Reflection.Missing.Value);
Worksheet sheet1 = (Worksheet)workbook.Sheets[1];
for (int j = 0; j < dataGrid.Columns.Count; j++) //Başlıklar için
{
Range myRange = (Range)sheet1.Cells[1, j + 1];
sheet1.Cells[1, j + 1].Font.Bold = true; //Başlığın Kalın olması için
sheet1.Columns[j + 1].ColumnWidth = 15; //Sütun genişliği ayarı
myRange.Value2 = dataGrid.Columns[j].Header;
}
for (int i = 0; i < dataGrid.Columns.Count; i++)
{
for (int j = 0; j < dataGrid.Items.Count; j++)
{
TextBlock b = dataGrid.Columns[i].GetCellContent(dataGrid.Items[j]) as TextBlock;
Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[j + 2, i + 1];
myRange.Value2 = b.Text;
}
}
}