Is there a way I can export my Silverlight DataGrid data to excel or csv?
I searched the web but can\'t find any examples!
Thanks a lot
Here's a nice approach that worked for me http://forums.silverlight.net/forums/p/179321/404357.aspx
I know this is an old post but it did help me. I have done some edits to make it work with silverlight 4, converts and excel. I wanted the fast export so I first use CSV then open it with excel. This code works silverlight web and oob elevated trust. In Web will not open in 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();
}
Those solutions didn't work for me, so I modified them to one that worked. (My solution doesn't require quotes around fields, so I left out the FormatCSVField function)
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();
}
I don't think Silverlight offers a way to download files. You can add a button to your app that calls a URL- i.e. http://www.mysite.com/generateexcelfile.aspx. Include as Querystring values the parameters used to generate the data being displayed in your Silverlight app, run your query and use your favorite Excel file generation component to generate the file on the fly. Redirect to it and it will download to the users' system.
I needed to do the same thing. I used the implementation by t3rse, but had to make a few changes. I don't have enough reputation to do a comment on his answer, so I will list them here:
For the line that says propInfo.GetValue(data, null).ToString(), I checked to see if the value returned by GetValue is Null before calling ToString() on it.
In the method FormatCSVField(), it replaced a double quote with three double quotes. It should only replace it with two double quotes.
The implementation only uses columns of type DataGridBoundColumn and ignores others. I have columns that are not DataGridBoundColumn that I wanted included, so I got the property name of the data source for those columns with col.SortMemberPath.
Silverlight 3 changes the answer to this question because it gives the ability of the user to create a file on the user's desktop in a location that they specify. I adapted the code submitted by DaniCE, split things into a few methods for readability and am using a loosely defined CSV format that Excel should recognize.
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();
}