我成功地将数据数组导出到 Excel 电子表格。现在用户向我扔了一个曲线球,并希望它在 Excel 中的表格中,而不仅仅是常规范围。我已经搜索过,我只能找到从外部数据源(SQL、文件等)创建查询表的方法。有没有办法将数组导出到查询表?下面是我用来创建数组并将其导出到 excel 的代码。
public class ExcelHelpers
{
/// <summary>
/// Exports a list of objects to Excel. Objects go in the Rows while Object Properties go in the Columns
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objects">List of objects to export.</param>
/// <param name="filePath">Location to save file to. Does not need to exist</param>
/// <param name="fileName">Name of excel file</param>
public static void ExportToExcel<T>(IEnumerable<T> objects, string filePath, string fileName)
{
// Add \ to end of file name if it doesn't exist. Just want to be consistant
if (!filePath.EndsWith(@"\"))
filePath += @"\";
// Create directory if it doesn't exist
if (!Directory.Exists(filePath))
Directory.CreateDirectory(filePath);
// Start Excel and get Application object.
Excel.Application excel = new Excel.Application();
// Set it hidden and hide alerts
excel.Visible = false;
excel.DisplayAlerts = false;
// Create a new workbook.
Excel.Workbook workbook = excel.Workbooks.Add();
// Get the active sheet
Excel.Worksheet sheet = (Excel.Worksheet)workbook.ActiveSheet;
try
{
// Convert the list into a rectangular array that Excel can read
var data = GetObjectArray<T>(objects);
// If at least one record got converted successfully
if (data.Length > 1)
{
// Get the range of cells that the data will go into. Size matches rectangular array size
string xlsRange = string.Format("A1:{0}{1}",
new object[] { GetExcelColumn(data.GetLength(1)), data.GetLength(0) });
// Insert data into the specified range of cells
Excel.Range range = sheet.get_Range(xlsRange);
range.Value = data;
// Auto-Fit the columns
range.EntireColumn.AutoFit();
}
// Save workbook
workbook.SaveAs(
string.Format("{0}{1}", new object[] {filePath, fileName}),
Excel.XlFileFormat.xlWorkbookNormal);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Close
sheet = null;
workbook.Close();
workbook = null;
excel.Quit();
}
// Clean up
// NOTE: When in release mode, this does the trick
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
/// <summary>
/// Takes a List of objects objects and converts the objects and their properties into a rectangular array of objects
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="objects">List of objects to flatten</param>
/// <returns>Rectangular array where objects are stored in [0] and properties are stored in [1]</returns>
private static object[,] GetObjectArray<T>(IEnumerable<T> objects)
{
// Get list of object properties
PropertyInfo[] properties = typeof(T).GetProperties();
// Create rectangular array based on # of objects and # of object properties
object[,] data = new object[objects.Count() + 1, properties.Length];
// Loop through properties on object
for (int j = 0; j < properties.Count(); j++)
{
// Write the property name into the first row of the array
data[0, j] = properties[j].Name.Replace("_", " ");
// Loop through objects and write out the specified property of each one into the array
for (int i = 0; i < objects.Count(); i++)
{
data[i + 1, j] = "'" + properties[j].GetValue(objects.ElementAt(i), null);
}
}
// Return rectangular array
return data;
}
/// <summary>
/// Takes an Integer and converts it into Excel's column header code.
/// </summary>
/// <param name="colNumber">Number of Column in Excel. 1 = A</param>
/// <returns>string that Excel can use</returns>
private static string GetExcelColumn(int colNumber)
{
// If value is zero or less, return an empty string
if (colNumber <= 0)
return string.Empty;
// If the value is less than or equal to 26 (Z), the column header
// is only one character long. If it's greater, call this recursively
// to get the first letter(s) of the column code.
string first = (colNumber <= 26 ? string.Empty :
GetExcelColumn((int)Math.Floor((colNumber - 1) / 26.00)));
// Get the final letter in the column code
int second = colNumber % 26;
if (second == 0) second = 26;
char finalLetter = (char)('A' + second - 1); // Excel column header is the first part + the final character
return string.Format("{0}{1}", new object[] { first, finalLetter });
}
}