using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using ExcelLibrary.SpreadSheet; using MileageTraker.Web.Models; namespace MileageTraker.Web.Utility { public abstract class ExcelWriter { public static void WriteXls(IEnumerable items, string filename, string worksheetTitle, string worksheetName) { using (var fileStream = new FileStream(filename, FileMode.Create)) WriteXls(items, fileStream, worksheetTitle, worksheetName); } public static byte[] WriteXls(IEnumerable items, string worksheetTitle, string worksheetName) { using (var stream = new MemoryStream()) { WriteXls(items, stream, worksheetTitle, worksheetName); return stream.ToArray(); } } public static void WriteXls(IEnumerable items, Stream stream, string worksheetTitle, string worksheetName) { var workbook = new Workbook(); workbook.Worksheets.Add(WriteWorksheet(items, worksheetTitle, worksheetName)); workbook.Save(stream); } protected static IEnumerable GetProperties() { return typeof (T).GetProperties() .Where(p => !p.PropertyType.IsNonStringEnumerable()) .Where(p => !p.IsHiddenFromModel()) .Where(p => !p.Name.Contains("PreviousLog")) .ToList(); } public static int GetPropertyCount() { return GetProperties().Count(); } public static Worksheet WriteWorksheet(IEnumerable items, string worksheetTitle, string worksheetName) { var worksheet = new Worksheet(worksheetName); // write worksheet header worksheet.Cells[0, 3] = new Cell(worksheetTitle); WriteColumnHeaders(worksheet, 2); WriteItems(worksheet, items, 3); PadWorksheet(worksheet); return worksheet; } public static void WriteColumnHeaders(Worksheet worksheet, int startRow = 0, int startCol = 0, string formatString = "") { // write column headers GetProperties().Zip( CustomExtensions.GetNumbers().Skip(startCol), (p, c) => worksheet.Cells[startRow, c] = new Cell(p.GetName(), formatString) ).ToList(); } public static void WriteItems(Worksheet worksheet, IEnumerable items, int startRow = 0, int startCol = 0) { var r = startRow; foreach (var cell in items.Select(item => new Cell(item))) { worksheet.Cells[r, startCol] = cell; r++; } } public static void WriteItems(Worksheet worksheet, IEnumerable items, int startRow = 0, int startCol = 0) { // write the data items.Zip( CustomExtensions.GetNumbers().Skip(startRow), (item, r) => GetProperties().Zip(CustomExtensions.GetNumbers().Skip(startCol), (p, c) => { var value = p.GetValue(item); string formatString = null; if (value is decimal) // assume that it's currency formatString = "#,##0.00"; if (value is DateTime && p.Name.Contains("Date")) formatString = @"MM/DD/YYYY"; else if (value is DateTime) formatString = @"MM/DD/YYYY hh:mm:ss"; if (p.Name == "GasPurchased") // format to the .000 place formatString = "#,##0.000"; int intValue; // write int-looking values as numbers if (value is string && int.TryParse((string) value, out intValue)) value = intValue; double doubleValue; // write double-looking values as numbers if (value is string && double.TryParse((string) value, out doubleValue)) value = doubleValue; if (value is MileageLogTypeWrapper) value = ((MileageLogTypeWrapper) value).Enum.GetDisplayName(); if (value == null) value = p.GetNullDisplayText(item); var cell = formatString != null ? new Cell(value, formatString) : new Cell(value); worksheet.Cells[r, c] = cell; return (string) null; }).ToList()).ToList(); } /// /// Fill the worksheet with some empty space if not "enough" cells /// public static void PadWorksheet(Worksheet worksheet) { Func totalCells = () => (worksheet.Cells.LastRowIndex + 1)*(worksheet.Cells.LastColIndex + 1); for (var r = worksheet.Cells.LastRowIndex + 1; totalCells() < 320; r++) { for (var c = 0; c < worksheet.Cells.LastColIndex; c++) { worksheet.Cells[r, c] = new Cell(""); } } } } }