// // Class: ExcelReader // Current CLR: 4.0.30319.34209 // System: Microsoft Visual Studio 10.0 // Author: dani // Created: 6/15/2015 10:03:40 PM // // Copyright (c) 2015 Informatikbüro Daniel Schick. All rights reserved. using log4net; using Microsoft.Office.Interop.Excel; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using bsmd.database; namespace bsmd.ExcelReadService { public class ExcelReader : IDisposable { private ILog _log = LogManager.GetLogger(typeof(ExcelReader)); private Workbooks _excelWorkbooks; private Workbook _portcall; private Application _excelApp; private Dictionary _nameDict; internal enum ReadState { NONE, OK, WARN, FAIL }; internal enum CountryMode { NONE, DE, DK }; private CountryMode _countryMode = CountryMode.NONE; public ExcelReader(string filePath) { this._excelApp = new Application(); this._excelApp.DisplayAlerts = false; this._excelWorkbooks = _excelApp.Workbooks; this._portcall = _excelWorkbooks.Open(filePath, 0, true, 5, "", "", false, XlPlatform.xlWindows, "", false, false, 0, false, false, false); _nameDict = new Dictionary(); foreach(Name name in _portcall.Names) { _nameDict[name.Name] = name; } } internal Confirmation Conf { get; set; } internal CountryMode Mode { get { return _countryMode; } } internal void SetConfirmation(System.Collections.Specialized.StringCollection templatePaths) { if (templatePaths == Properties.Settings.Default.ConfirmationDE) _countryMode = CountryMode.DE; if (templatePaths == Properties.Settings.Default.ConfirmationDK) _countryMode = CountryMode.DK; this.Conf = new Confirmation(templatePaths, _excelApp); } internal bool Save(string filePath) { bool result = true; if (this._excelApp == null) return false; try { this._excelApp.SaveWorkspace(filePath); } catch(Exception ex) { _log.WarnFormat("cannot save workspace: {0}", ex.Message); result = false; } return result; } internal bool SaveCopy(string filePath) { bool result = true; if (this._excelApp == null) return false; try { this._portcall.Saved = true; this._portcall.SaveCopyAs(filePath); } catch (Exception ex) { _log.WarnFormat("cannot save copy of workbook: {0}", ex.Message); result = false; } return result; } internal List SaveConfirmationSheets(string attachmentLocalPath) { return this.Conf.SaveConfirmationSheets(attachmentLocalPath); } internal string ReadText(string lookup) { if (!_nameDict.ContainsKey(lookup)) return null; try { var val = _nameDict[lookup].RefersToRange.Value; var val2 = _nameDict[lookup].RefersToRange.Value2; if (val != null) return val.ToString(); if (val2 != null) return val2.ToString(); } catch(COMException) { _log.WarnFormat("COMException reading field:{0}", lookup); } return null; } internal string ReadTextNoWhitespace(string lookup) { string val = this.ReadText(lookup); if (val == null) return val; return new string(val.Where(c => !Char.IsWhiteSpace(c)).ToArray()); } internal string ReadLoCode(string lookup) { string val = this.ReadText(lookup); if(!val.IsNullOrEmpty()) { string portName = LocodeDB.PortNameFromLocode(val); if(portName == null) { this.Conf.ConfirmText(lookup, null, ReadState.WARN); } else { this.Conf.ConfirmText(lookup, val, ReadState.OK); } } else { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return val; } internal byte? ReadGender(string lookup) { byte? result = null; string val = this.ReadText(lookup); if (val != null) { if (val.Equals("m", StringComparison.CurrentCultureIgnoreCase) || val.Equals("male", StringComparison.CurrentCultureIgnoreCase)) { this.Conf.ConfirmText(lookup, val, ReadState.OK); result = 0; } else if (val.Equals("f", StringComparison.CurrentCultureIgnoreCase) || val.Equals("female", StringComparison.CurrentCultureIgnoreCase)) { this.Conf.ConfirmText(lookup, val, ReadState.OK); result = 1; } else { result = 2; this.Conf.ConfirmText(lookup, val, ReadState.WARN); } } if(result == null) { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return result; } internal byte? ReadIdentityDocumentType(string lookup) { byte? result = null; string val = this.ReadText(lookup); if (val != null) { if (val.Equals("identity_card", StringComparison.CurrentCultureIgnoreCase)) result = 0; if (val.Equals("passport", StringComparison.CurrentCultureIgnoreCase)) result = 1; if (val.Equals("muster_book", StringComparison.CurrentCultureIgnoreCase)) result = 2; if (val.Equals("picture_id", StringComparison.CurrentCultureIgnoreCase)) result = 3; if (val.Equals("residental_permit", StringComparison.CurrentCultureIgnoreCase)) result = 4; if (val.Equals("other_legal_identity_document", StringComparison.CurrentCultureIgnoreCase)) result = 5; if (val.Equals("ic", StringComparison.CurrentCultureIgnoreCase)) result = 0; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } else { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return result; } internal byte? ReadShippingArea(string lookup) { string val = this.ReadText(lookup); byte? result = null; if (val != null) { if (val.IndexOf("baltic", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("europe", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("overseas", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } else { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return result; } internal byte? ReadCargoHandlingType(string lookup) { string val = this.ReadText(lookup); byte? result = null; if(val != null) { if (val.IndexOf("load", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("discharge", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("transit", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } return result; } /// /// read nationality field an returns 2 Char ISO code (optional lookup) and "confirms" /// the field /// internal string ReadNationality(string lookup) { string val = this.ReadText(lookup); if(val.IsNullOrEmpty()) { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } if(val.Length > 2) { string isoCode = LocodeDB.CountryCodeFromName(val); if(isoCode != null) { this.Conf.ConfirmText(lookup, val, ReadState.OK); val = isoCode; } else { this.Conf.ConfirmText(lookup, val, ReadState.WARN); } } if (val.Length == 2) this.Conf.ConfirmText(lookup, val, ReadState.OK); return val; } internal byte? ReadHullConfiguration(string lookup) { string val = this.ReadText(lookup); byte? result = null; if (val != null) { if (val.IndexOf("sbt", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("single", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("double", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } else { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return result; } internal byte? ReadPackingGroup(string lookup) { string val = this.ReadText(lookup); byte? result = null; if(val!= null) { if (val == "I") result = 1; if (val == "II") result = 2; if (val == "III") result = 3; if (val.Equals("NONE", StringComparison.OrdinalIgnoreCase)) result = 0; this.Conf.ConfirmText(lookup, val, result.HasValue ? ReadState.OK : ReadState.WARN); } return result; } internal byte? ReadConditionTanks(string lookup) { string val = this.ReadText(lookup); byte? result = null; if (val != null) { if (val.IndexOf("full", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("empty", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("inerted", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } else { this.Conf.ConfirmText(lookup, null, ReadState.FAIL); } return result; } internal byte? ReadDelivery(string lookup) { string val = this.ReadText(lookup); byte? result = null; if (val != null) { if (val.IndexOf("all", StringComparison.OrdinalIgnoreCase) >= 0) result = 0; if (val.IndexOf("some", StringComparison.OrdinalIgnoreCase) >= 0) result = 1; if (val.IndexOf("none", StringComparison.OrdinalIgnoreCase) >= 0) result = 2; if (result == null) this.Conf.ConfirmText(lookup, val, ReadState.WARN); else this.Conf.ConfirmText(lookup, val, ReadState.OK); } else { this.Conf.ConfirmText(lookup, val, ReadState.FAIL); } return result; } public void Dispose() { if(this._portcall != null) { this._portcall.Close(0); _log.Debug("Close Worksheet"); Marshal.ReleaseComObject(this._portcall); } if (this._excelWorkbooks != null) { this._excelWorkbooks.Close(); _log.Debug("Close Workbooks"); Marshal.ReleaseComObject(this._excelWorkbooks); // this._excelWorkbooks.Close(); } if (this._excelApp != null) { _log.Debug("Quit Excel"); this._excelApp.Quit(); Marshal.ReleaseComObject(this._excelApp); } } internal DateTime? ReadBirthDate(string lookup) { DateTime? result = this.ReadDate(lookup); // mark fail if date is in the future if(result.HasValue) { if (result.Value > DateTime.Now) this.Conf.ConfirmDate(lookup, result, ReadState.FAIL); } return result; } internal DateTime? ReadDate(string lookup) { try { DateTime? date = null; if (_nameDict.ContainsKey(lookup)) { var val = _nameDict[lookup].RefersToRange.Value; if (val is DateTime) { this.Conf.ConfirmDate(lookup, val, ReadState.OK); return val; } if (val is double) { try { date = DateTime.FromOADate(val); } catch (ArgumentException) { /* .. */ } if(date == null) { CultureInfo provider = CultureInfo.InvariantCulture; string dateString = val.ToString(); string format = "yyyyMMdd"; DateTime tmpDate; if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out tmpDate)) date = tmpDate; } } if (date == null) { DateTime tmpDate; if (DateTime.TryParse(val, out tmpDate)) date = tmpDate; } // TODO: weitere varianten ausprobieren if (date != null) { if ((date.Value < new DateTime(1900, 1, 1)) || (date.Value > new DateTime(2030, 1, 1))) { date = null; this.Conf.ConfirmDate(lookup, date, ReadState.WARN); } else { this.Conf.ConfirmDate(lookup, date, ReadState.OK); } } else { this.Conf.ConfirmDate(lookup, null, ReadState.FAIL); } } return date; } catch (Exception) { this.Conf.ConfirmDate(lookup, null, ReadState.FAIL); _log.WarnFormat("error parsing datetime for lookup {0}", lookup); return null; } } internal DateTime? ReadDateTime(string dateField, string timeField) { DateTime? result = null; DateTime? etaDate = this.ReadDate(dateField); DateTime? etaTime = this.ReadTime(timeField); if (etaDate != null) { result = new DateTime(etaDate.Value.Year, etaDate.Value.Month, etaDate.Value.Day); if (etaTime != null) { result = new DateTime(etaDate.Value.Year, etaDate.Value.Month, etaDate.Value.Day, etaTime.Value.Hour, etaTime.Value.Minute, etaTime.Value.Second); } } if(result.HasValue) { // wir haben local time gelesen, wird jetzt in UTC konvertiert result = result.Value.ToUniversalTime(); } return result; } internal DateTime? ReadTime(string lookup) { DateTime? result = null; try { if (_nameDict.ContainsKey(lookup)) { var val = _nameDict[lookup].RefersToRange.Value; if (val is DateTime) { result = val; } if (val is double) { try { result = DateTime.FromOADate(val); } catch(ArgumentException) { } if (result == null) { CultureInfo provider = CultureInfo.InvariantCulture; string dateString = val.ToString(); if (!dateString.Contains(":")) { string format = "HHmm"; DateTime tmpDate; if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out tmpDate)) result = tmpDate; } } } if (result == null) { DateTime date; if (DateTime.TryParseExact(val, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out date)) result = date; } if (result == null) { DateTime date; if (DateTime.TryParseExact(val, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out date)) result = date; } if ((result == null) && (val != null)) { CultureInfo provider = CultureInfo.InvariantCulture; string dateString = val.ToString(); if (!dateString.Contains(":")) { string format = "HHmm"; DateTime tmpDate; if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out tmpDate)) result = tmpDate; } } if (result != null) { this.Conf.ConfirmTime(lookup, result, ReadState.OK); } else { this.Conf.ConfirmTime(lookup, result, ReadState.WARN); } } } catch (Exception) { this.Conf.ConfirmTime(lookup, null, ReadState.FAIL); _log.WarnFormat("error reading time for lookup {0}", lookup); } return result; } internal double? ReadNumber(string lookup) { double? result = null; try { if (_nameDict.ContainsKey(lookup)) { var val = _nameDict[lookup].RefersToRange.Value; if (val is double) result = val; if (val is string) { double tmpDouble; if (double.TryParse(val, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, CultureInfo.InvariantCulture, out tmpDouble)) result = tmpDouble; if (result == null) { if (double.TryParse(val, out tmpDouble)) // current language style (==GER, mit , statt .) result = tmpDouble; } } if ((result == null) && (val != null)) { try { { double tmpDouble2 = val[1, 1]; result = tmpDouble2; } } catch (Exception) { // .. } } if (result != null) { this.Conf.ConfirmNumber(lookup, result, ReadState.OK); } else { this.Conf.ConfirmNumber(lookup, result, ReadState.FAIL); } } } catch (Exception) { this.Conf.ConfirmNumber(lookup, null, ReadState.FAIL); _log.WarnFormat("error reading number for lookup {0}", lookup); } return result; } internal double ReadNumberDefaultZero(string lookup) { double? result = this.ReadNumber(lookup); if(!result.HasValue) { result = 0; this.Conf.ConfirmNumber(lookup, 0, ReadState.WARN); } return result.Value; } internal bool? ReadBoolean(string lookup) { string val = this.ReadText(lookup); if (val == null) { this.Conf.ConfirmText(lookup, val, ReadState.FAIL); return null; } this.Conf.ConfirmText(lookup, val, ReadState.OK); if ((val == "y") || (val == "Y") || val.Equals("yes", StringComparison.OrdinalIgnoreCase) || (val == "1") || (val == "x") || (val == "X")) return true; return false; } } }