<ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll <RuntimeDirectory>\System.Data.Entity.Design.dll Amazon.Lambda.S3Events AWSSDK.Core AWSSDK.S3 LINQtoCSV Amazon Amazon.Auth.AccessControlPolicy Amazon.Auth.AccessControlPolicy.ActionIdentifiers Amazon.Internal Amazon.Lambda.S3Events Amazon.MissingTypes Amazon.Runtime Amazon.Runtime.CredentialManagement Amazon.Runtime.CredentialManagement.Internal Amazon.Runtime.EventStreams Amazon.Runtime.EventStreams.Internal Amazon.Runtime.Internal Amazon.Runtime.Internal.Auth Amazon.Runtime.Internal.Settings Amazon.Runtime.Internal.Transform Amazon.Runtime.Internal.Util Amazon.Runtime.SharedInterfaces Amazon.Runtime.SharedInterfaces.Internal Amazon.S3 Amazon.S3.Encryption Amazon.S3.Encryption.Internal Amazon.S3.Internal Amazon.S3.IO Amazon.S3.Model Amazon.S3.Model.Internal.MarshallTransformations Amazon.S3.Transfer Amazon.S3.Util Amazon.Util Amazon.Util.Internal Amazon.Util.Internal.PlatformServices LINQtoCSV Newtonsoft.Json Newtonsoft.Json.Converters Newtonsoft.Json.Linq Newtonsoft.Json.Schema Newtonsoft.Json.Serialization System System.ComponentModel.Composition System.ComponentModel.Composition.Hosting System.ComponentModel.Composition.Primitives System.ComponentModel.Composition.ReflectionModel System.Diagnostics System.Diagnostics.Tracing System.Dynamic System.IO.Compression System.Net.Http System.Net.Http.Headers System.Numerics ThirdParty.BouncyCastle.Asn1 ThirdParty.BouncyCastle.Asn1.Utilities ThirdParty.BouncyCastle.Math ThirdParty.BouncyCastle.OpenSsl ThirdParty.BouncyCastle.Utilities.IO.Pem ThirdParty.Ionic.Zlib ThirdParty.Json.LitJson ThirdParty.MD5 System.Data.Entity.Design.PluralizationServices System.Globalization void Main() { IEnumerable testExpando; var inputFileDescription = new CsvFileDescription { SeparatorChar = '\t', // tab delimited FirstLineHasColumnNames = false, // no column names in first record FileCultureName = "en-US" // use formats used in The Netherlands }; var outputFileDescription = new CsvFileDescription { SeparatorChar = ',', // tab delimited FirstLineHasColumnNames = true, // no column names in first record EnforceCsvColumnAttribute = true, FileCultureName = "en-US" // use formats used in The Netherlands }; var cc = new CsvContext(); var path = @"C:\Users\tlamb\Downloads\"; var files = new[] { @"Outreach - Monthly Inventory Records - Inventory March.tsv", @"Outreach - Monthly Inventory Records - Inventory - April.tsv", @"Outreach - Monthly Inventory Records - Inventory - May.tsv", @"Outreach - Monthly Inventory Records - Inventory - June.tsv" }.ToList(); var nextmonth = new DateTime(2019, 2, 1); var productList = new List(); var purchaseSummary = new List(); var orderSummary = new List(); files.ForEach(inventory => { nextmonth = nextmonth.AddMonths(1); var monthData = cc.Read(Path.Combine(path, inventory), inputFileDescription); testExpando = ConvertMyDataRow(monthData); var products = testExpando.Select(o => new Product(o as ExpandoObject, nextmonth)).ToList(); var purchases = testExpando.Select(o => new Purchase(o as ExpandoObject, nextmonth)).Where(p => p.Rcvd != 0).ToList(); var orders = testExpando.Select(o => new Order(o as ExpandoObject, nextmonth)).Where(o => o.Out != 0).ToList(); productList.AddRange(products); purchaseSummary.AddRange(purchases); orderSummary.AddRange(orders); }); var medicationBrandList = productList.GroupBy(l => new { l.Medicine, l.Brand }).Select(grp => grp.First()).ToList() .Select(mb => new MedicationBrand { Medicine = mb.Medicine, Brand = mb.Brand, Reorder = mb.MinimumRequired }); productList.GroupBy(p => p.Medicine).OrderBy(p => p.Key).Dump("Products"); purchaseSummary.Dump("Purchases"); orderSummary.Dump("Orders"); medicationBrandList.Dump("Medications"); var docsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "SoleHope"); if (!Directory.Exists(docsFolder)) Directory.CreateDirectory(docsFolder); cc.Write(medicationBrandList, Path.Combine(docsFolder, "MedicationBrand.csv"), outputFileDescription); cc.Write(productList, Path.Combine(docsFolder, "Medications.csv"), outputFileDescription); cc.Write(purchaseSummary, Path.Combine(docsFolder, "Intake.csv"), outputFileDescription); cc.Write(orderSummary, Path.Combine(docsFolder, "Outtake.csv"), outputFileDescription); } internal IEnumerable ConvertMyDataRow(IEnumerable data) { var groupData = data.SelectMany(dr => dr.ToList()) .GroupBy(t => t.LineNbr) .Select(t => new { Key = t.Key - 2, Values = t.ToList().Select(v => v.Value).ToArray() }); var properties = groupData.Where(d => d.Key < 0) .SelectMany(d => d.Values.Select(v => Regex.Replace(v, @"[\s()]", "") .Replace("StartingQuantityBeginningofCurrentMonth", "StartQuantity") .Replace("FinalQuantityEndofCurrentMonth", "FinalQuantity") .Replace("MedicationTotalStartQuantity", "StartQuantity")).ToList()).ToArray(); var medication = string.Empty; var expandoData = groupData.Where(d => d.Key >= 0) .Select((t, j) => { dynamic expando = new ExpandoObject(); AddProperty(expando, "MedicineID", j); int i = 0; t.Values.ToList().ForEach(d => { if (properties[i] == "Medication") { if (string.IsNullOrEmpty(d)) { d = medication; } medication = d; } AddProperty(expando, properties[i], d ?? string.Empty); i++; }); return expando; }); return expandoData; } // Define other methods and classes here internal class MyDataRow : List, IDataRow { } public class MedicationBrand { [CsvColumn(Name = "Medication", FieldIndex = 1)] public string Medicine { get; set; } [CsvColumn(Name = "Brand", FieldIndex = 2)] public string Brand { get; set; } [CsvColumn(FieldIndex = 3)] public int Reorder {get;set;} } public class Product { internal string[] Row { get; set; } [CsvColumn(Name = "MedicineID", FieldIndex = 1)] public int index { get; set; } internal string InvDateStr { get; set; } public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr) ? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); [CsvColumn(Name = "Medication", FieldIndex = 2)] public string Medicine { get; set; } [CsvColumn(Name = "Brand", FieldIndex = 3)] public string Brand { get; set; } [CsvColumn(FieldIndex = 4)] public string Label => string.IsNullOrEmpty(Brand) ? $"{Medicine} ({index})" : $"{Medicine} {Brand} ({index})"; public string Dosage { get; set; } public string Per { get; set; } public string Unit { get; set; } internal string StartStr { get; set; } internal string RcvdStr { get; set; } internal string OutStr { get; set; } internal string FinalStr { get; set; } [CsvColumn(Name = "StartingInventory", FieldIndex = 5)] public int Start => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(StartStr) ? "0" : StartStr, "")); public int Rcvd => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(RcvdStr) ? "0" : RcvdStr, "")); public int Out => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(OutStr) ? "0" : OutStr, "")); public int Final => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(FinalStr) ? "0" : FinalStr, "")); [CsvColumn(FieldIndex = 6)] public int InventoryReceived => Rcvd; [CsvColumn(FieldIndex = 7)] public int InventoryShipped => Out; [CsvColumn(FieldIndex = 8)] public int InventoryOnHand => Final; [CsvColumn(FieldIndex = 9)] public int MinimumRequired => Start; [CsvColumn(FieldIndex = 10)] public string NeedsReorder => Start == 0 ? "Yes" : "No"; internal string ExpiryStr { get; set; } [CsvColumn(FieldIndex = 11)] public DateTime Expiry { get; set; } public DateTime Purchased { get; set; } public DateTime OrderDate => InvDate.AddMonths(1).AddDays(-1); public string Notes { get; set; } internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US")); internal Regex regex = new Regex(@"[^\d]"); internal Product() { index = 0; InvDateStr = DateTime.Today.ToString("M/yy"); Medicine = string.Empty; Brand = string.Empty; Dosage = string.Empty; Per = string.Empty; Unit = string.Empty; StartStr = "0"; RcvdStr = "0"; OutStr = "0"; FinalStr = "0"; Expiry = new DateTime(2018, 1, 1); ExpiryStr = Expiry.ToString("M/yy"); Purchased = new DateTime(2999, 12, 31); Notes = string.Empty; } public Product(int i, string[] row) : this() { Row = row; index = i + 1; InvDateStr = row[0]; Medicine = row[1]; Dosage = row[2] ?? string.Empty; Per = row[3] ?? string.Empty; Unit = row[3] ?? string.Empty; Unit = Unit.ToUpper().Contains("TUBE") ? "Tube" : Unit.ToUpper().Contains("BOTTLE") ? "Bottle" : Unit.ToUpper().Contains("VIAL") ? "Vial" : Unit.ToUpper().Contains("TABLET") ? "Tablet" : Unit.ToUpper().Contains("CAPSULE") ? "Capsule" : Unit.ToUpper().Contains("LANCET") ? "Lancet" : Unit; Per = !string.IsNullOrEmpty(Per) ? Per.Replace(Unit, "").TrimEnd("(s) ".ToCharArray()) : string.Empty; StartStr = string.IsNullOrEmpty(row[4]) ? "0" : row[4]; RcvdStr = string.IsNullOrEmpty(row[5]) ? "0" : row[5]; OutStr = string.IsNullOrEmpty(row[6]) ? "0" : row[6]; FinalStr = string.IsNullOrEmpty(row[7]) ? "0" : row[7]; ExpiryStr = row[8]; Notes = string.IsNullOrEmpty(row[9]) ? string.Empty : row[9]; Expiry = !string.IsNullOrEmpty(ExpiryStr) ? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); Purchased = !string.IsNullOrEmpty(Notes) && Notes.StartsWith("Purchased") ? DateTime.ParseExact(Notes.Substring(10), "M/d/yy", System.Globalization.CultureInfo.InvariantCulture) : DateTime.Compare(Expiry, new DateTime(2018, 1, 1)) < 0 ? Expiry.AddMonths(-6) : new DateTime(2018, 1, 1); Notes = Notes.Replace($"Purchased {Purchased:M/d/yy}", ""); } public Product(ExpandoObject expando, DateTime invDate) : this() { InvDateStr = invDate.ToString("M/yy"); var dictionary = expando as IDictionary; dictionary.Keys.ToList() .ForEach(k => { var value = Convert.ToString(dictionary[k]); switch (k) { case "MedicineID": index = Convert.ToInt32(value); break; case "Medicine": case "Medication": Medicine = value; break; case "MedicineBrand": Brand = value; break; case "Dosage": Dosage = value; break; case "PerBox": Per = value; break; case "Unit": Unit = ps.IsPlural(value) ? ps.Singularize(value) : value; break; case "Start": case "StartQuantity": StartStr = value; break; case "Received": RcvdStr = value; break; case "Output": OutStr = value; break; case "Final": FinalStr = value; break; case "ExpirationDate": ExpiryStr = Regex.Replace(value, @"[^\d/]", ""); Expiry = !string.IsNullOrEmpty(ExpiryStr) ? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); break; } }); if (string.IsNullOrEmpty(Unit)) { Unit = FindUnits(Per); if (string.IsNullOrEmpty(Unit)) Unit = FindUnits(Dosage); } } public string FindUnits(string unit) { return unit.ToUpper().Contains("TUBE") ? "Tube" : unit.ToUpper().Contains("BOTTLE") ? "Bottle" : unit.ToUpper().Contains("VIAL") ? "Vial" : unit.ToUpper().Contains("TABLET") ? "Tablet" : unit.ToUpper().Contains("CAPSULE") ? "Capsule" : unit.ToUpper().Contains("LANCET") ? "Lancet" : string.Empty; } object ToDump() => new { MedicineID = index, Medication = Medicine, Brand, Label, Unit, StartingInventory = Start, InventoryReceived, InventoryShipped, InventoryOnHand, MinimumRequired, NeedsReorder, Expiry = $"{Expiry.AddMonths(1).AddDays(-1):MM/dd/yy}" }; } public class Order { internal string[] Row { get; set; } [CsvColumn(Name = "MedicineID", FieldIndex = 1)] public int index { get; set; } internal string InvDateStr { get; set; } public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr) ? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); [CsvColumn(Name = "Medication", FieldIndex = 2)] public string Medicine { get; set; } internal string Brand { get; set; } [CsvColumn(FieldIndex = 3)] public string Label => $"{Medicine} {Brand}"; [CsvColumn(FieldIndex = 4)] public string Customer => string.Empty; internal string OutStr { get; set; } [CsvColumn(Name = "Shipped", FieldIndex = 5)] public int Out => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(OutStr) ? "0" : OutStr, "")); [CsvColumn(Name = "Date", FieldIndex = 6)] public DateTime OrderDate => InvDate.AddMonths(1).AddDays(-1); internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US")); internal Regex regex = new Regex(@"[^\d]"); internal Order() { index = 0; InvDateStr = DateTime.Today.ToString("M/yy"); Medicine = string.Empty; Brand = string.Empty; OutStr = "0"; } public Order(ExpandoObject expando, DateTime invDate) : this() { InvDateStr = invDate.ToString("M/yy"); var dictionary = expando as IDictionary; dictionary.Keys.ToList() .ForEach(k => { var value = Convert.ToString(dictionary[k]); switch (k) { case "MedicineID": index = Convert.ToInt32(value); break; case "Medicine": case "Medication": Medicine = value; break; case "MedicineBrand": Brand = value; break; case "Output": OutStr = value; break; } }); } object ToDump() => new { MedicineID = index, Medication = Medicine, Brand, Label, Customer = "", Shipped = Out, Date = InvDate.AddMonths(1).AddDays(-1) }; } public class Purchase { internal string[] Row { get; set; } [CsvColumn(Name = "MedicineID", FieldIndex = 1)] public int index { get; set; } internal string InvDateStr { get; set; } public DateTime InvDate => !string.IsNullOrEmpty(InvDateStr) ? DateTime.ParseExact(InvDateStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); [CsvColumn(Name = "Medication", FieldIndex = 2)] public string Medicine { get; set; } internal string Brand { get; set; } [CsvColumn(FieldIndex = 3)] public string Label => $"{Medicine} {Brand}"; [CsvColumn(FieldIndex = 4)] public string Supplier => string.Empty; internal string RcvdStr { get; set; } [CsvColumn(Name = "Received", FieldIndex = 5)] public int Rcvd => Convert.ToInt32(regex.Replace(string.IsNullOrEmpty(RcvdStr) ? "0" : RcvdStr, "")); internal string Notes { get; set; } internal string ExpiryStr = ""; internal DateTime Expiry => !string.IsNullOrEmpty(ExpiryStr) ? DateTime.ParseExact(ExpiryStr, "M/yy", System.Globalization.CultureInfo.InvariantCulture) : new DateTime(2999, 12, 31); [CsvColumn(Name = "Date", FieldIndex = 6)] public DateTime Purchased { get; set; } internal PluralizationService ps => PluralizationService.CreateService(new CultureInfo("en-US")); internal Regex regex = new Regex(@"[^\d]"); internal Purchase() { index = 0; InvDateStr = DateTime.Today.ToString("M/yy"); Medicine = string.Empty; Brand = string.Empty; RcvdStr = "0"; Purchased = new DateTime(2999, 12, 31); } public Purchase(ExpandoObject expando, DateTime invDate) : this() { InvDateStr = invDate.ToString("M/yy"); Purchased = InvDate; var dictionary = expando as IDictionary; dictionary.Keys.ToList() .ForEach(k => { var value = Convert.ToString(dictionary[k]); switch (k) { case "MedicineID": index = Convert.ToInt32(value); break; case "Medicine": case "Medication": Medicine = value; break; case "MedicineBrand": Brand = value; break; case "Received": RcvdStr = value; break; case "ExpirationDate": ExpiryStr = Regex.Replace(value, @"[^\d/]", ""); break; case "Notes:": var purchaseStr = !string.IsNullOrEmpty(value) && value.StartsWith("Purchased") ? Regex.Replace(value, @"[^\d/]", "") : string.Empty; Purchased = !string.IsNullOrEmpty(purchaseStr) ? DateTime.ParseExact(purchaseStr, "M/d/yy", System.Globalization.CultureInfo.InvariantCulture) : DateTime.Compare(Expiry, new DateTime(2018, 1, 1)) < 0 ? Expiry.AddMonths(-6) : new DateTime(2018, 1, 1); ; break; } }); } object ToDump() => new { MedicineID = index, Medication = Medicine, Brand, Label, Supplier = "", Received = Rcvd, Date = Purchased }; } public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue) { // ExpandoObject supports IDictionary so we can extend it like this var expandoDict = expando as IDictionary; if (expandoDict.ContainsKey(propertyName)) expandoDict[propertyName] = propertyValue; else expandoDict.Add(propertyName, propertyValue); }