oi-metrology/Archive/Controllers/ExportController.cs
2022-07-26 09:34:09 -07:00

162 lines
4.6 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OI.Metrology.Archive.Controllers;
public class ExportController : Controller
{
private ILogger Logger { get; }
protected IMetrologyRepo _Repo;
public ExportController(ILogger<ExportController> logger, IMetrologyRepo repo)
{
Logger = logger;
_Repo = repo;
}
protected static void LoadToolTypes(Export m, IEnumerable<ToolType> toolTypes)
{
m.ToolTypes = toolTypes
.Where(tt => tt.ExportSPName != null)
.Select(tt => new Shared.Models.SelectListItem(tt.ToolTypeName, tt.ID.ToString())).ToList();
}
[HttpGet]
[Route("/Export")]
public ActionResult Index()
{
Export model = new();
LoadToolTypes(model, _Repo.GetToolTypes());
model.ToolType = "";
model.StartTime = DateTime.Now.AddMonths(-1);
model.EndTime = DateTime.Now;
return View(model);
}
[HttpPost]
[Route("/ExportData")]
public ActionResult ExportData(Export model)
{
IEnumerable<ToolType> toolTypes = _Repo.GetToolTypes();
// is tooltype valid
ToolType toolType = toolTypes.Where(tt => tt.ID.ToString() == model.ToolType).SingleOrDefault();
if (toolType == null)
ModelState.AddModelError("ToolType", "Invalid selection");
else if (string.IsNullOrWhiteSpace(toolType.ExportSPName))
ModelState.AddModelError("ToolType", "Tool type is not exportable");
// is enddate after startdate
if (model.StartTime > model.EndTime)
ModelState.AddModelError("EndTime", "End time must be after start time");
if (ModelState.IsValid)
{
try
{
DateTime startDT = model.StartDate.Date.Add(model.StartTime.TimeOfDay);
DateTime endDT = model.EndDate.Date.Add(model.EndTime.TimeOfDay);
return DoCSVExport(toolType.ToolTypeName, toolType.ExportSPName, startDT, endDT);
}
catch (Exception ex)
{
ModelState.AddModelError("", "Error exporting data");
ModelState.AddModelError("", ex.Message);
string errorMessage = $"Error exporting: {ex}";
Logger.LogError(message: errorMessage);
}
}
LoadToolTypes(model, toolTypes);
return View("Index", model);
}
protected ActionResult DoCSVExport(String toolTypeName, string spName, DateTime startTime, DateTime endTime)
{
string fileName = string.Format("Export_{0}_{1:yyyyMMddHHmm}_to_{2:yyyyMMddHHmm}.csv", toolTypeName, startTime, endTime);
StringBuilder sb = new();
System.Data.DataTable dt = _Repo.ExportData(spName, startTime, endTime);
_ = sb.AppendLine(GetColumnHeaders(dt));
foreach (System.Data.DataRow dr in dt.Rows)
{
_ = sb.AppendLine(GetRowData(dr));
}
byte[] contents = Encoding.UTF8.GetBytes(sb.ToString());
return File(contents, "application/octet-stream", fileName);
}
protected static string GetRowData(System.Data.DataRow dr)
{
StringBuilder r = new();
for (int i = 0; i < dr.Table.Columns.Count; i++)
{
if (i > 0)
_ = r.Append(',');
object v = dr[i];
if (!Convert.IsDBNull(v))
_ = r.Append(FormatForCSV(Convert.ToString(v)));
}
return r.ToString();
}
protected static string GetColumnHeaders(System.Data.DataTable dt)
{
StringBuilder r = new();
for (int i = 0; i < dt.Columns.Count; i++)
{
if (i > 0)
_ = r.Append(',');
_ = r.Append(FormatForCSV(dt.Columns[i].ColumnName.TrimEnd('_')));
}
return r.ToString();
}
protected static string FormatForCSV(string v)
{
StringBuilder r = new(v.Length + 2);
bool doubleQuoted = false;
if (v.StartsWith(' ') || v.EndsWith(' ') || v.Contains(',') || v.Contains('"'))
{
_ = r.Append('"');
doubleQuoted = true;
}
foreach (char c in v)
{
_ = c switch
{
'\r' or '\n' => r.Append(' '),
'"' => r.Append("\"\""),
_ => r.Append(c),
};
}
if (doubleQuoted)
_ = r.Append('"');
return r.ToString();
}
}