Есть ли способ экспортировать данные Silverlight DataGrid в excel или csv?
Я искал в Интернете, но не могу найти примеров!
Спасибо большое
Есть ли способ экспортировать данные Silverlight DataGrid в excel или csv?
Я искал в Интернете, но не могу найти примеров!
Спасибо большое
Silverlight 3 изменяет ответ на этот вопрос, поскольку он дает возможность пользователю создавать файл на рабочем столе пользователя в указанном им местоположении. Я адаптировал код, представленный DaniCE, разбил все на несколько методов для удобочитаемости, и я использую свободно определенный формат CSV, который должен распознать Excel.
private void exportHistoryButton_Click(object sender, RoutedEventArgs e)
{
string data = ExportDataGrid(true, historyDataGrid);
SaveFileDialog sfd = new SaveFileDialog()
{
DefaultExt = "csv",
Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*",
FilterIndex = 1
};
if (sfd.ShowDialog() == true)
{
using (Stream stream = sfd.OpenFile())
{
using (StreamWriter writer = new StreamWriter(stream)) {
writer.Write(data);
writer.Close();
}
stream.Close();
}
}
}
private string FormatCSVField(string data) {
return String.Format("\"{0}\"",
data.Replace("\"", "\"\"\"")
.Replace("\n", "")
.Replace("\r", "")
);
}
public string ExportDataGrid(bool withHeaders, DataGrid grid)
{
string colPath;
System.Reflection.PropertyInfo propInfo;
System.Windows.Data.Binding binding;
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
System.Collections.IList source = (grid.ItemsSource as System.Collections.IList);
if (source == null)
return "";
List<string> headers = new List<string>();
grid.Columns.ToList().ForEach(col => {
if (col is DataGridBoundColumn){
headers.Add(FormatCSVField(col.Header.ToString()));
}
});
strBuilder
.Append(String.Join(",", headers.ToArray()))
.Append("\r\n");
foreach (Object data in source)
{
List<string> csvRow = new List<string>();
foreach (DataGridColumn col in grid.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
propInfo = data.GetType().GetProperty(colPath);
if (propInfo != null)
{
csvRow.Add(FormatCSVField(propInfo.GetValue(data, null).ToString()));
}
}
}
strBuilder
.Append(String.Join(",", csvRow.ToArray()))
.Append("\r\n");
}
return strBuilder.ToString();
}
Я нашел this, используя буфер обмена.
Чтобы создать общий код, вы можете изменить первый пример, чтобы прочитать привязки столбцов и применить их к данным с помощью отражения:
public String ExportDataGrid(DataGrid grid)
{
string colPath;
System.Reflection.PropertyInfo propInfo;
System.Windows.Data.Binding binding;
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
System.Collections.IList source = (grid.DataContext as System.Collections.IList);
if (source == null)
return "";
foreach (Object data in source)
{
foreach (DataGridColumn col in datagrid.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
propInfo = data.GetType().GetProperty(colPath);
if (propInfo != null)
{
strBuilder.Append(propInfo.GetValue(data, null).ToString());
strBuilder.Append(",");
}
}
}
strBuilder.Append("\r\n");
}
return strBuilder.ToString();
}
конечно, он работает только тогда, когда путь привязки является именем свойства. Для более продвинутых путей вам необходимо применить привязку к данным (я полагаю, это было бы лучшим решением, но я не уверен, как это сделать).
Я не думаю, что Silverlight предлагает способ загрузки файлов. Вы можете добавить кнопку в приложение, которое вызывает URL-адрес, http://www.mysite.com/generateexcelfile.aspx. Включить в качестве Querystring значение параметров, используемых для генерации данных, отображаемых в приложении Silverlight, запустить ваш запрос и использовать ваш любимый компонент генерации файлов Excel для генерации файла "на лету". Перенаправите его и загрузите в систему пользователей.
Я знаю, что это старый пост, но это помогло мне. Я сделал некоторые изменения, чтобы заставить его работать с silverlight 4, конвертировать и преуспеть. Мне нужен быстрый экспорт, поэтому я сначала использую CSV, а затем открываю его с помощью excel. Этот код работает в сети silverlight и обеспечивает повышенное доверие. В Web не открывается в excel.
private static void OpenExcelFile(string Path)
{
dynamic excelApp;
excelApp = AutomationFactory.CreateObject("Excel.Application");
dynamic workbook = excelApp.workbooks;
object oMissing = Missing.Value;
workbook = excelApp.Workbooks.Open(Path,
oMissing, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing);
dynamic sheet = excelApp.ActiveSheet;
// open the existing sheet
sheet.Cells.EntireColumn.AutoFit();
excelApp.Visible = true;
}
private static string FormatCSVField(string data)
{
return String.Format("\"{0}\"",
data.Replace("\"", "\"\"\"")
.Replace("\n", "")
.Replace("\r", "")
);
}
public static string ExportDataGrid(DataGrid grid,string SaveFileName,bool AutoOpen)
{
string colPath;
System.Reflection.PropertyInfo propInfo;
System.Windows.Data.Binding binding;
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
var source = grid.ItemsSource;
if (source == null)
return "";
List<string> headers = new List<string>();
grid.Columns.ToList().ForEach(col =>
{
if (col is DataGridBoundColumn)
{
headers.Add(FormatCSVField(col.Header.ToString()));
}
});
strBuilder
.Append(String.Join(",", headers.ToArray()))
.Append("\r\n");
foreach (var data in source)
{
List<string> csvRow = new List<string>();
foreach (DataGridColumn col in grid.Columns)
{
if (col is DataGridBoundColumn)
{
binding = (col as DataGridBoundColumn).Binding;
colPath = binding.Path.Path;
propInfo = data.GetType().GetProperty(colPath);
if (propInfo != null)
{
string valueConverted = "";
if (binding.Converter.GetType().ToString() != "System.Windows.Controls.DataGridValueConverter")
valueConverted = binding.Converter.Convert(propInfo.GetValue(data, null), typeof(System.String), binding.ConverterParameter, System.Globalization.CultureInfo.CurrentCulture).ToString();
else
valueConverted = FormatCSVField(propInfo.GetValue(data, null) == null ? "" : propInfo.GetValue(data, null).ToString());
csvRow.Add(valueConverted.ToString());
}
}
}
strBuilder
.Append(String.Join(",", csvRow.ToArray()))
.Append("\r\n");
}
if (AutomationFactory.IsAvailable)
{
var sampleFile = "\\" + SaveFileName;
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
path += "\\Pement";
if (!System.IO.Directory.Exists(path))
{
System.IO.Directory.CreateDirectory(path);
}
else
{
var files = System.IO.Directory.EnumerateFiles(path);
foreach (var item in files)
{
try
{
System.IO.File.Delete(item);
}
catch { }
}
}
StreamWriter sw = File.CreateText(path + sampleFile);
sw.WriteLine(strBuilder.ToString());
sw.Close();
if (AutoOpen)
OpenExcelFile(path + sampleFile, true, true);
}
else
{
SaveFileDialog sfd = new SaveFileDialog()
{
DefaultExt = "csv",
Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*",
FilterIndex = 1
};
if (sfd.ShowDialog() == true)
{
using (Stream stream = sfd.OpenFile())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(strBuilder.ToString());
writer.Close();
}
stream.Close();
}
}
}
return strBuilder.ToString();
}
В верхней части моей головы я бы сказал, что вы можете добавить кнопку экспорта с помощью ControlTemplate
, а затем перебрать каждый элемент в DataSource
, а затем использовать каждый столбец в Columns
для получения содержимого каждого ячейку, используя метод GetCellContent
, или используйте информацию привязки DataGridColumn, чтобы получить соответствующее значение ячейки. Затем вы можете получить отображаемое значение этого содержимого и записать его в свой отчет.
Что-то вроде...
foreach (YourType item in grid.DataSource)
{
foreach (DataGridColumn column in grid.Columns)
{
FrameworkElement cellContent = column.GetCellContent(item);
// Now, determine the type of cell content and act accordingly.
TextBlock block = cellContent as TextBlock;
if (block != null)
{
// Report text value...
}
// ...etc...
}
}
Или используя информацию привязки, как описано DaniCE.
Проверьте решение Ryan. Выглядит хорошо, не может ручаться за него, хотя, потому что я его нашел. Райан делает то, что запросила DLL.
http://www.rshelby.com/post/exporting-data-from-silverilght-datagrid-to-excel.aspx
Давид в решении Dakota выше выглядит немного проще в реализации, и всегда есть перенаправление на классическую страницу asp.net с сеткой данных на ней, а тип контента - на excel, но тогда у вас есть больше кода для поддержки и этот способ может не работать из-за недоступных браузеров решений (фактически не будет работать).
В любом случае, это обычная задача. Я надеюсь, что некоторые люди здесь или в Microsoft придумают решение для подключения к игре Mort: "
Я нашел метод расширения для экспорта CVS из datagrid Silverlight -
http://www.codeproject.com/KB/silverlight/SilverlightDataGridExport.aspx
У этого есть потенциал, чтобы быть подключи и играй, но я должен был подкрутить его немного, чтобы заставить его работать с datagrids с источниками данных источника (см. комментарии в сообщении). Кто-то более яркий и опытный, чем я, должен быть в состоянии доработать до совершенства. Проверьте это, он должен приблизиться к тому, что вам нужно.
Эти решения не сработали для меня, поэтому я изменил их на один, который работал. (Мое решение не требует котировок вокруг полей, поэтому я не использовал функцию FormatCSVField)
public void SaveAs(string csvPath)
{
string data = ExportDataGrid(true, _flexGrid);
StreamWriter sw = new StreamWriter(csvPath, false, Encoding.UTF8);
sw.Write(data);
sw.Close();
}
public string ExportDataGrid(bool withHeaders, Microsoft.Windows.Controls.DataGrid grid)
{
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder();
System.Collections.IEnumerable source = (grid.ItemsSource as System.Collections.IEnumerable);
if (source == null) return "";
List<string> headers = new List<string>();
grid.Columns.ToList().ForEach(col =>
{
if (col is Microsoft.Windows.Controls.DataGridBoundColumn)
{
headers.Add(col.Header.ToString());
}
});
strBuilder.Append(String.Join(",", headers.ToArray())).Append("\r\n");
foreach (Object data in source)
{
System.Data.DataRowView d = (System.Data.DataRowView)data;
strBuilder.Append(String.Join(",", d.Row.ItemArray)).Append("\r\n");
}
return strBuilder.ToString();
}
Здесь хороший подход, который работал у меня http://forums.silverlight.net/forums/p/179321/404357.aspx
Мне нужно было сделать то же самое. Я использовал реализацию t3rse, но должен был внести несколько изменений. У меня недостаточно репутации, чтобы сделать комментарий к его ответу, поэтому я перечислил их здесь:
Для строки, которая говорит propInfo.GetValue(data, null).ToString(), я проверил, не возвращает ли значение, возвращаемое GetValue, Null перед вызовом ToString().
В методе FormatCSVField() он заменил двойную кавычку тремя двойными кавычками. Он должен заменить его только двумя двойными кавычками.
Реализация использует только столбцы типа DataGridBoundColumn и игнорирует другие. У меня есть столбцы, которые не являются DataGridBoundColumn, которые я хотел включить, поэтому я получил имя свойства источника данных для этих столбцов с col.SortMemberPath.