// Copyright (c) 2017- schick Informatik // Description: // using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; using bsmd.database; namespace ENI2.Excel { internal class ExcelWriter : ExcelBase { #region Fields private readonly string _saveFilePath; #endregion #region Construction public ExcelWriter(string filePath) : base(filePath) { string refFilePath = System.IO.Path.Combine(Environment.CurrentDirectory, @"Excel\Reference_Sheet_DE.xlsx"); this._workBook = _excelWorkbooks.Open(refFilePath, 0, true, 5, "", "", false, XlPlatform.xlWindows, "", false, false, 0, false, false, false); this.InitNameFields(); _saveFilePath = filePath; } #endregion #region public methods public void WriteData(List messages, MessageCore core, out string resultMessage) { resultMessage = ""; foreach (Message message in messages) { try { switch(message.MessageNotificationClass) { case Message.NotificationClass.AGNT: if (message.Elements[0] is AGNT agnt) this.WriteMessage(agnt); break; case Message.NotificationClass.ATA: if (message.Elements[0] is ATA ata) this.WriteMessage(ata); break; case Message.NotificationClass.ATD: if (message.Elements[0] is ATD atd) this.WriteMessage(atd); break; case Message.NotificationClass.BKRA: this.WriteBKRA(message); break; case Message.NotificationClass.BKRD: this.WriteBKRD(message); break; case Message.NotificationClass.BPOL: if (message.Elements[0] is BPOL bpol) { this.WriteMessage(bpol); this.WriteItineraries(bpol); } break; case Message.NotificationClass.CREW: this.WriteCREW(message, true); break; case Message.NotificationClass.CREWD: this.WriteCREW(message, false); break; case Message.NotificationClass.HAZA: this.WriteHAZ(message, true); break; case Message.NotificationClass.HAZD: this.WriteHAZ(message, false); break; case Message.NotificationClass.INFO: if (message.Elements[0] is INFO info) { this.WriteMessage(info); this.WriteINFO(info); } break; case Message.NotificationClass.LADG: this.WriteLADG(message); break; case Message.NotificationClass.MDH: if (message.Elements[0] is MDH mdh) { this.WriteMessage(mdh); this.WriteMDH(mdh); } break; case Message.NotificationClass.NAME: if (message.Elements[0] is NAME name) this.WriteMessage(name); break; case Message.NotificationClass.NOA_NOD: if (message.Elements[0] is NOA_NOD noa_nod) this.WriteNOA_NOD(noa_nod, core.IsTransit); break; case Message.NotificationClass.PAS: this.WritePAS(message, true); break; case Message.NotificationClass.PASD: this.WritePAS(message, false); break; case Message.NotificationClass.POBA: if (message.Elements[0] is POBA poba) this.WriteMessage(poba); break; case Message.NotificationClass.POBD: if (message.Elements[0] is POBD pobd) this.WriteMessage(pobd); break; case Message.NotificationClass.PRE72H: if (message.Elements[0] is PRE72H pre72h) { this.WriteMessage(pre72h); this.WritePRE72H(pre72h); } break; case Message.NotificationClass.SEC: if (message.Elements[0] is SEC sec) this.WriteMessage(sec); this.WriteSEC(message); break; case Message.NotificationClass.SERV: this.WriteSERV(message); break; case Message.NotificationClass.STAT: if (message.Elements[0] is STAT stat) { this.WriteMessage(stat); WriteText("STAT.TransportMode", stat.TransportModeDisplay); } break; case Message.NotificationClass.STO: this.WriteSTO(message); break; case Message.NotificationClass.TIEFA: if (message.Elements[0] is TIEFA tiefa) this.WriteMessage(tiefa); break; case Message.NotificationClass.TIEFD: if (message.Elements[0] is TIEFD tiefd) this.WriteMessage(tiefd); break; case Message.NotificationClass.TOWA: WriteTOWA(message); break; case Message.NotificationClass.TOWD: WriteTOWD(message); break; case Message.NotificationClass.WAS: if (message.Elements[0] is WAS was) this.WriteMessage(was); WriteWAS(message); break; default: _log.InfoFormat("skip writing message class {0}", message.MessageNotificationClassDisplay); break; } } catch (Exception ex) { resultMessage += string.Format("{2}:{0}{1}", ex.Message, Environment.NewLine, message.MessageNotificationClassDisplay); } } WriteCore(core); } public void Save() { this._workBook.SaveAs(_saveFilePath, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); this._workBook.Saved = true; } #endregion #region private excel field writing // generische Methode zum Schreiben der Felder nach Excel für Meldeklassen, die kein // Listentyp sind private void WriteMessage(DatabaseEntity dbEntity) { Type objType = dbEntity.GetType(); List props = new List(); // add lookup properties to scan list props.AddRange(objType.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(LookupNameAttribute)))); foreach (PropertyInfo property in props) { object propValue = property.GetValue(dbEntity, null); string value = (propValue == null) ? string.Empty : propValue.ToString(); LookupNameAttribute lookupNameAttribute = Attribute.GetCustomAttribute(property, typeof(LookupNameAttribute)) as LookupNameAttribute; bool success = true; if (property.PropertyType == typeof(DateTime?)) { success = this.WriteDate(lookupNameAttribute.LookupName, property.GetValue(dbEntity)); } else if (property.PropertyType == typeof(double?)) { success = this.WriteNumber(lookupNameAttribute.LookupName, property.GetValue(dbEntity)); } else if (property.PropertyType == typeof(string)) { success = this.WriteText(lookupNameAttribute.LookupName, property.GetValue(dbEntity)); } else if (property.PropertyType == typeof(int?)) { success = this.WriteNumber(lookupNameAttribute.LookupName, property.GetValue(dbEntity)); } else if (property.PropertyType == typeof(byte?)) { success = this.WriteNumber(lookupNameAttribute.LookupName, property.GetValue(dbEntity)); } else if (property.PropertyType == typeof(Boolean?)) { object boolVal = property.GetValue(dbEntity); if(boolVal != null) success = this.WriteBoolean(lookupNameAttribute.LookupName, boolVal); } else { string message = string.Format("unhandled property type: {0} for lookup {1}", property.PropertyType, lookupNameAttribute.LookupName); _log.Warn(message); } if (!success) { string message = string.Format("Sheet does not contain lookup field {0}", lookupNameAttribute.LookupName); _log.Error(message); System.Diagnostics.Trace.WriteLine(message); // throw new FormatException(message); } } } private void WriteCore(MessageCore core) { WriteText("ID", core.IsTransit ? core.TransitId : core.VisitId); WriteText("Visit.PortOfCall", core.PoC); WriteText("Visit.IMONumber", core.IMO); WriteText("ReferenceNumber", core.HerbergReportType); WriteText("ShipMail", core.HerbergEmailContactReportingVessel); } #region list / special message classes #region LADG private void WriteLADG(Message ladgMessage) { for (int i = 0; i < Math.Min(ladgMessage.NumberOfExcelRows, ladgMessage.Elements.Count); i++) { string lnCHT = string.Format("LADG.CargoHandlingType_{0}", i + 1); string lnType = string.Format("LADG.CargoType_{0}", i + 1); string lnCNOI = string.Format("LADG.CargoNumberOfItems_{0}", i + 1); string lnCGQ = string.Format("LADG.CargoGrossQuantity_TNE_{0}", i + 1); string lnLoad = string.Format("LADG.CargoPortOfLoading_{0}", i + 1); string lnDis = string.Format("LADG.CargoPortOfDischarge_{0}", i + 1); string lnLACode = string.Format("LADG.CargoLACode_{0}", i + 1); string lnZusatz = string.Format("LADG.CargoTypeZusatz_{0}", i + 1); LADG ladg = ladgMessage.Elements[i] as LADG; if (ladg.CargoHandlingType.HasValue) { switch (ladg.CargoHandlingType) { case 0: WriteText(lnCHT, "load"); break; case 1: WriteText(lnCHT, "discharge"); break; case 2: WriteText(lnCHT, "transit"); break; default: break; } } WriteText(lnType, ladg.CargoCodeNST); WriteText(lnZusatz, ladg.CargoCodeNST_3); WriteNumber(lnCNOI, ladg.CargoNumberOfItems); WriteNumber(lnCGQ, ladg.CargoGrossQuantity_TNE); WriteText(lnLoad, ladg.PortOfLoading); WriteText(lnDis, ladg.PortOfDischarge); WriteNumber(lnLACode, ladg.CargoLACode); } } #endregion #region BKRA private void WriteBKRA(Message bkraMessage) { for (int i = 0; i < Math.Min(bkraMessage.NumberOfExcelRows, bkraMessage.Elements.Count); i++) { string lnQuantity = string.Format("BKRA.BunkerFuelQuantity_TNE_{0}", i + 1); string lnType = string.Format("BKRA.BunkerFuelType_{0}", i + 1); BRKA brka = bkraMessage.Elements[i] as BRKA; WriteNumber(lnQuantity, brka.BunkerFuelQuantity_TNE); WriteText(lnType, brka.BunkerFuelType); } } #endregion #region BKRD private void WriteBKRD(Message bkrdMessage) { for (int i = 0; i < Math.Min(bkrdMessage.NumberOfExcelRows, bkrdMessage.Elements.Count); i++) { string lnQuantity = string.Format("BKRD.BunkerFuelQuantity_TNE_{0}", i + 1); string lnType = string.Format("BKRD.BunkerFuelType_{0}", i + 1); BRKD brkd = bkrdMessage.Elements[i] as BRKD; WriteNumber(lnQuantity, brkd.BunkerFuelQuantity_TNE); WriteText(lnType, brkd.BunkerFuelType); } } #endregion #region BPOL private void WriteItineraries(BPOL bpol) { for (int i = 0; i < Math.Min(10, bpol.PortOfItineraries.Count); i++) { string bpolName = string.Format("BPOL.PortOfItineraryName_{0}", i + 1); string bpolLocode = string.Format("BPOL.PortOfItineraryLoCode_{0}", i + 1); string bpolETADate = string.Format("BPOL.PortOfItineraryETADate_{0}", i + 1); string bpolETATime = string.Format("BPOL.PortOfItineraryETATime_{0}", i + 1); PortOfItinerary poi = bpol.PortOfItineraries[i]; WriteText(bpolName, poi.PortOfItineraryName); WriteText(bpolLocode, poi.PortOfItineraryLocode); if (poi.PortOfItineraryETA.HasValue) { WriteDate(bpolETADate, poi.PortOfItineraryETA.Value); WriteTime(bpolETATime, poi.PortOfItineraryETA.Value); } } } #endregion #region CREW private void WriteCREW(Message crewMessage, bool isArrival) { for(int i = 0; i 0) { SERV serv = servMessage.Elements[0] as SERV; WriteMessage(serv); } } #endregion #region STO private void WriteSTO(Message stoMessage) { for(int i = 0; i < Math.Min(stoMessage.Elements.Count, stoMessage.NumberOfExcelRows); i++) { string stoName = string.Format("STO.Name_{0}", i + 1); string stoQuantity = string.Format("STO.Quantity_{0}", i + 1); string stoQuantityUnit = string.Format("STO.QuantityUnit_{0}", i + 1); string stoLocationOnBoard = string.Format("STO.LocationOnBoard_{0}", i + 1); string stoOfficialUse = string.Format("STO.OfficialUse_{0}", i + 1); STO sto = stoMessage.Elements[i] as STO; WriteText(stoName, sto.Name); if (sto.Quantity.HasValue) WriteNumber(stoQuantity, sto.Quantity.Value); WriteText(stoQuantityUnit, sto.QuantityUnit); WriteText(stoLocationOnBoard, sto.LocationOnBoard); WriteText(stoOfficialUse, sto.OfficialUse); } } #endregion #region TOWA private void WriteTOWA(Message towaMessage) { for(int i = 0; i < Math.Min(towaMessage.Elements.Count, towaMessage.NumberOfExcelRows); i++) { string tName = string.Format("TOWA.TowageOnArrivalName_{0}", i + 1); string tFlag = string.Format("TOWA.TowageOnArrivalFlag_{0}", i + 1); string tPoC = string.Format("TOWA.TowageOnArrivalPurposeOfCall_{0}", i + 1); string tDraft = string.Format("TOWA.TowageOnArrivalDraught_DMT_{0}", i + 1); string tGT = string.Format("TOWA.TowageOnArrivalGrossTonnage_{0}", i + 1); string tLen = string.Format("TOWA.TowageOnArrivalLengthOverall_MTR_{0}", i + 1); string tBeam = string.Format("TOWA.TowageOnArrivalBeam_MTR_{0}", i + 1); string tOp = string.Format("TOWA.TowageOnArrivalOperatorCompanyName_{0}", i + 1); TOWA towa = towaMessage.Elements[i] as TOWA; WriteText(tName, towa.TowageOnArrivalName); WriteText(tFlag, towa.TowageOnArrivalFlag); WriteText(tPoC, towa.TowageOnArrivalPurposeOfCall); if (towa.TowageOnArrivalDraught_DMT.HasValue) WriteNumber(tDraft, towa.TowageOnArrivalDraught_DMT.Value); if (towa.TowageOnArrivalGrossTonnage.HasValue) WriteNumber(tGT, towa.TowageOnArrivalGrossTonnage.Value); if (towa.TowageOnArrivalLengthOverall_MTR.HasValue) WriteNumber(tLen, towa.TowageOnArrivalLengthOverall_MTR.Value); if (towa.TowageOnArrivalBeam_MTR.HasValue) WriteNumber(tBeam, towa.TowageOnArrivalBeam_MTR.Value); WriteText(tOp, towa.TowageOnArrivalOperatorCompanyName); } } #endregion #region TOWD private void WriteTOWD(Message towdMessage) { for(int i = 0; i < Math.Min(towdMessage.Elements.Count, towdMessage.NumberOfExcelRows); i++) { string tName = string.Format("TOWD.TowageOnDepartureName_{0}", i + 1); string tFlag = string.Format("TOWD.TowageOnDepartureFlag_{0}", i + 1); string tDraft = string.Format("TOWD.TowageOnDepartureDraught_DMT_{0}", i + 1); string tLen = string.Format("TOWD.TowageOnDepartureLengthOverall_MTR_{0}", i + 1); string tBeam = string.Format("TOWD.TowageOnDepartureBeam_MTR_{0}", i + 1); string tOp = string.Format("TOWD.TowageOnDepartureOperatorCompanyName_{0}", i + 1); TOWD towd = towdMessage.Elements[i] as TOWD; WriteText(tName, towd.TowageOnDepartureName); WriteText(tFlag, towd.TowageOnDepartureFlag); if (towd.TowageOnDepartureDraught_DMT.HasValue) WriteNumber(tDraft, towd.TowageOnDepartureDraught_DMT.Value); if (towd.TowageOnDepartureLengthOverall_MTR.HasValue) WriteNumber(tLen, towd.TowageOnDepartureLengthOverall_MTR.Value); if (towd.TowageOnDepartureBeam_MTR.HasValue) WriteNumber(tBeam, towd.TowageOnDepartureBeam_MTR.Value); WriteText(tOp, towd.TowageOnDepartureOperatorCompanyName); } } #endregion #region WAS private void WriteWAS(Message wasMessage) { if (wasMessage.Elements.Count == 0) return; WAS was = wasMessage.Elements[0] as WAS; WriteText("WAS.WasteDisposalDelivery", was.WasteDisposalDelivery); WriteText("WAS.LastWasteDisposalPort", was.LastWasteDisposalPort); WriteText("WAS.WasteDisposalServiceProviderName", was.WasteDisposalServiceProviderText); for(int i = 0; i < Math.Min(was.NumberOfExcelRows, was.Waste.Count); i++) { string wastetype = string.Format("WAS.WasteType_{0}", i + 1); string wasteCode = string.Format("WAS.WasteCode_{0}", i + 1); string wasteDescription = string.Format("WAS.WasteDescription_{0}", i + 1); string wasteAmount = string.Format("WAS.WasteDisposalAmount_MTQ_{0}", i + 1); string wasteCapacity = string.Format("WAS.WasteCapacity_MTQ_{0}", i + 1); string wasteRetained = string.Format("WAS.WasteAmountRetained_MTQ_{0}", i + 1); string wastePort = string.Format("WAS.WasteDisposalPort_{0}", i + 1); string amountGen = string.Format("WAS.WasteAmountGeneratedTillNextPort_MTQ_{0}", i + 1); string wasteDis = string.Format("WAS.WasteDisposedAtLastPort_MTQ_{0}", i + 1); Waste waste = was.Waste[i]; if(waste.WasteType.HasValue) WriteNumber(wasteCode, waste.WasteType.Value); WriteText(wastetype, waste.WasteTypeDisplay); WriteText(wasteDescription, waste.WasteDescription); if (waste.WasteDisposalAmount_MTQ.HasValue) WriteNumber(wasteAmount, waste.WasteDisposalAmount_MTQ.Value); if (waste.WasteCapacity_MTQ.HasValue) WriteNumber(wasteCapacity, waste.WasteCapacity_MTQ.Value); if (waste.WasteAmountRetained_MTQ.HasValue) WriteNumber(wasteRetained, waste.WasteAmountRetained_MTQ.Value); WriteText(wastePort, waste.WasteDisposalPort); if (waste.WasteAmountGeneratedTillNextPort_MTQ.HasValue) WriteNumber(amountGen, waste.WasteAmountGeneratedTillNextPort_MTQ.Value); if (waste.WasteDisposedAtLastPort_MTQ.HasValue) WriteNumber(wasteDis, waste.WasteDisposedAtLastPort_MTQ.Value); } } #endregion #region INFO private void WriteINFO(INFO info) { if (info != null) { this.WriteBoolean("INFO.FumigatedBulkCargo", info.FumigatedBulkCargoBool); if (info.ShippingArea.HasValue) { switch (info.ShippingArea.Value) { case 0: this.WriteText("INFO.ShippingArea", "NORTH_BALTIC_SEA"); break; case 1: this.WriteText("INFO.ShippingArea", "EUROPE"); break; case 2: this.WriteText("INFO.ShippingArea", "OVERSEAS"); break; } } } } #endregion #region PRE72H private void WritePRE72H(PRE72H pre72h) { if(pre72h != null) { if(pre72h.TankerHullConfiguration.HasValue) { switch(pre72h.TankerHullConfiguration.Value) { case 0: WriteText("PRE72H.TankerHullConfiguration", "SINGLE HULL"); break; case 1: WriteText("PRE72H.TankerHullConfiguration", "SINGLE HULL WITH SBT"); break; case 2: WriteText("PRE72H.TankerHullConfiguration", "DOUBLE HULL"); break; } } if(pre72h.ConditionCargoBallastTanks.HasValue) { switch(pre72h.ConditionCargoBallastTanks.Value) { case 0: WriteText("PRE72H.ConditionCargoBallastTanks", "FULL"); break; case 1: WriteText("PRE72H.ConditionCargoBallastTanks", "EMPTY"); break; case 2: WriteText("PRE72H.ConditionCargoBallastTanks", "INERTED"); break; } } } } #endregion #endregion #region write simple things private void WriteGender(string label, byte? gender) { if(gender.HasValue) { if (gender == 0) WriteText(label, "m"); if (gender == 1) WriteText(label, "w"); if (gender == 2) WriteText(label, "d"); } } #endregion #region write value types private bool WriteBoolean(string lookupName, object v) { bool result = _nameDict.ContainsKey(lookupName); bool? b = (bool?) v; if (result && b.HasValue) { _nameDict[lookupName].RefersToRange.Value = b.Value ? "Y" : "N"; } return result; } private bool WriteText(string lookupName, object v) { bool result = _nameDict.ContainsKey(lookupName); if(result) { _nameDict[lookupName].RefersToRange.Value = v; } return result; } private bool WriteNumber(string lookupName, object v) { bool result = _nameDict.ContainsKey(lookupName); if (result) { _nameDict[lookupName].RefersToRange.Value = v; } return result; } private bool WriteDate(string lookupName, object v) { bool result = _nameDict.ContainsKey(lookupName); if (result) { if(v != null) { _nameDict[lookupName].RefersToRange.Value = ((DateTime) v).ToOADate(); // Test this I dont believe it } } return result; } private bool WriteTime(string lookupName, object v) { bool result = _nameDict.ContainsKey(lookupName); if (result) { if (v != null) { _nameDict[lookupName].RefersToRange.Value = ((DateTime)v).ToLocalTime().ToShortTimeString(); } } return result; } #endregion #endregion } }