Merge branch 'feature/excel_in_eni' into develop

This commit is contained in:
Daniel Schick 2021-12-17 07:01:32 +01:00
commit 019fe81a8d
23 changed files with 3436 additions and 22 deletions

View File

@ -8,8 +8,8 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ENI2.Locode;
using bsmd.database; using bsmd.database;
using bsmd.ExcelReadService;
using System.ComponentModel; using System.ComponentModel;
namespace ENI2.Controls namespace ENI2.Controls

View File

@ -10,9 +10,8 @@ using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using ENI2.EditControls; using ENI2.EditControls;
using ENI2.Util; using ENI2.Util;
using bsmd.ExcelReadService; using ENI2.Locode;
using ExcelDataReader; using ExcelDataReader;
using bsmd.database; using bsmd.database;
namespace ENI2.DetailViewControls namespace ENI2.DetailViewControls
@ -35,6 +34,7 @@ namespace ENI2.DetailViewControls
{ {
InitializeComponent(); InitializeComponent();
this.Loaded += BorderPoliceDetailControl_Loaded; this.Loaded += BorderPoliceDetailControl_Loaded;
} }
private void BorderPoliceDetailControl_Loaded(object sender, RoutedEventArgs e) private void BorderPoliceDetailControl_Loaded(object sender, RoutedEventArgs e)

View File

@ -13,7 +13,6 @@ using ENI2.EditControls;
using ENI2.Util; using ENI2.Util;
using bsmd.database; using bsmd.database;
using bsmd.ExcelReadService;
using ExcelDataReader; using ExcelDataReader;
namespace ENI2.DetailViewControls namespace ENI2.DetailViewControls

View File

@ -83,16 +83,16 @@
<Button IsEnabled="False" Name="buttonSendPDF" Grid.Column="3" Grid.Row="6" Margin="2" Click="buttonSendPDF_Click" Content="{x:Static p:Resources.textCreatePDF}"/> <Button IsEnabled="False" Name="buttonSendPDF" Grid.Column="3" Grid.Row="6" Margin="2" Click="buttonSendPDF_Click" Content="{x:Static p:Resources.textCreatePDF}"/>
<Button Name="buttonQueryHIS" Grid.Column="4" Grid.Row="6" Margin="2" Click="buttonQueryHIS_Click" Content="{x:Static p:Resources.textQueryHIS}"/> <Button Name="buttonQueryHIS" Grid.Column="4" Grid.Row="6" Margin="2" Click="buttonQueryHIS_Click" Content="{x:Static p:Resources.textQueryHIS}"/>
<StackPanel Orientation="Horizontal" Grid.Column="5" Grid.Row="6"> <StackPanel Orientation="Horizontal" Grid.Column="5" Grid.Row="6">
<Button Name="buttonRefresh" Margin="2" Click="buttonRefresh_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipRefresh}"> <Button Name="buttonRefresh" Margin="2" Click="buttonRefresh_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipRefresh}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Source="../Resources/nav_refresh_blue.png" Margin="0,0,5,0" Height="24"/> <Image Source="../Resources/nav_refresh_blue.png" Margin="0,0,5,0" Height="24"/>
<!--TextBlock Text="{x:Static p:Resources.textRefresh}" VerticalAlignment="Center"/--> <!--TextBlock Text="{x:Static p:Resources.textRefresh}" VerticalAlignment="Center"/-->
</StackPanel> </StackPanel>
</Button> </Button>
<Button Name="buttonInfoCore" Margin="2" Click="buttonInfoCore_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipDetails}"> <Button Name="buttonInfoCore" Margin="2" Click="buttonInfoCore_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipDetails}">
<Image Source="../Resources/document_view.png" Margin="0,0,5,0" Height="24" /> <Image Source="../Resources/document_view.png" Margin="0,0,5,0" Height="24" />
</Button> </Button>
<Button Name="buttonValidate" Margin="2" Click="buttonValidate_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipValidation}"> <Button Name="buttonValidate" Margin="2" Click="buttonValidate_Click" BorderThickness="0" Background="Transparent" ToolTip="{x:Static p:Resources.textTooltipValidation}">
<Image Source="../Resources/hand_point.png" Margin="0,0,5,0" Height="24" /> <Image Source="../Resources/hand_point.png" Margin="0,0,5,0" Height="24" />
</Button> </Button>
@ -105,6 +105,9 @@
<Label Grid.Column="0" Grid.Row="7" Margin="0,0,10,0" HorizontalContentAlignment="Right" Name="labelCancelled" VerticalContentAlignment="Center" FontWeight="Bold" /> <Label Grid.Column="0" Grid.Row="7" Margin="0,0,10,0" HorizontalContentAlignment="Right" Name="labelCancelled" VerticalContentAlignment="Center" FontWeight="Bold" />
<Label Grid.Column="1" Grid.Row="7" Margin="0,0,10,0" HorizontalContentAlignment="Right" Name="labelHIS" VerticalContentAlignment="Center" Content="{x:Static p:Resources.textSendToHIS}" /> <Label Grid.Column="1" Grid.Row="7" Margin="0,0,10,0" HorizontalContentAlignment="Right" Name="labelHIS" VerticalContentAlignment="Center" Content="{x:Static p:Resources.textSendToHIS}" />
<ComboBox Grid.Column="2" Grid.Row="7" Margin="2" Name="comboBoxInitialHis" VerticalContentAlignment="Center" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedValue="{Binding Path=InitialHIS}" /> <ComboBox Grid.Column="2" Grid.Row="7" Margin="2" Name="comboBoxInitialHis" VerticalContentAlignment="Center" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedValue="{Binding Path=InitialHIS}" />
<Button Grid.Column="3" Grid.Row="7" Margin="2" Name="buttonExcelImport" Content="{x:Static p:Resources.textExcelImport}" Click="buttonExcelImport_Click">
<!-- hier könnte noch ein nettes Icon hin -->
</Button>
<StackPanel Orientation="Horizontal" Grid.Column="3" Grid.Row="7" Visibility="Hidden" Name="stackPanelLock"> <StackPanel Orientation="Horizontal" Grid.Column="3" Grid.Row="7" Visibility="Hidden" Name="stackPanelLock">
<Image Source="../Resources/lock.png" Margin="0,0,5,0" Height="24" /> <Image Source="../Resources/lock.png" Margin="0,0,5,0" Height="24" />

View File

@ -11,9 +11,12 @@ using System.Timers;
using bsmd.database; using bsmd.database;
using ENI2.EditControls; using ENI2.EditControls;
using ENI2.Import;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media; using System.Windows.Media;
using Microsoft.Win32;
namespace ENI2.DetailViewControls namespace ENI2.DetailViewControls
{ {
@ -80,6 +83,7 @@ namespace ENI2.DetailViewControls
this.comboBoxInitialHis.ItemsSource = Util.EnumHelper.GetAllValuesAndDescription(typeof(Message.NSWProvider)); this.comboBoxInitialHis.ItemsSource = Util.EnumHelper.GetAllValuesAndDescription(typeof(Message.NSWProvider));
this.comboBoxInitialHis.DataContext = this.Core; this.comboBoxInitialHis.DataContext = this.Core;
this.buttonExcelImport.IsEnabled = !this.Core.DisplayId.IsNullOrEmpty();
Binding vtBinding = new Binding Binding vtBinding = new Binding
{ {
@ -325,6 +329,9 @@ namespace ENI2.DetailViewControls
this.labelBSMDStatusInternal.DataContext = null; this.labelBSMDStatusInternal.DataContext = null;
this.labelBSMDStatusInternal.DataContext = this.Core; this.labelBSMDStatusInternal.DataContext = this.Core;
this.labelBSMDStatusInternal.GetBindingExpression(Label.ContentProperty)?.UpdateTarget(); this.labelBSMDStatusInternal.GetBindingExpression(Label.ContentProperty)?.UpdateTarget();
this.buttonExcelImport.IsEnabled = !this.Core.DisplayId.IsNullOrEmpty();
//MessageBox.Show(string.Format("Visit/Transit ID updated: {0}", this.Core.DisplayId)); //MessageBox.Show(string.Format("Visit/Transit ID updated: {0}", this.Core.DisplayId));
//ShowIdDialog sid = new ShowIdDialog(this.Core) //ShowIdDialog sid = new ShowIdDialog(this.Core)
//{ //{
@ -713,6 +720,40 @@ namespace ENI2.DetailViewControls
this.OnRequestValidate(); this.OnRequestValidate();
} }
private void buttonExcelImport_Click(object sender, RoutedEventArgs e)
{
SelectImportClassesDialog sicd = new SelectImportClassesDialog();
sicd.IsTransit = this.Core.IsTransit;
if((sicd.ShowDialog() ?? false) && (sicd.SelectedClasses.Count > 0))
{
// get here if user selected some classes
OpenFileDialog ofd = new OpenFileDialog
{
Filter = "Excel Files|*.xls;*.xlsx"
};
if (ofd.ShowDialog() ?? false)
{
Util.UIHelper.SetBusyState();
ExcelManager em = new ExcelManager();
// start importer
if(em.Import(ofd.FileName, this.Core, sicd.SelectedClasses, out string importResultText))
{
// reload this core
this.OnRequestReload(this.Core.Id.Value);
// validate all selected import classes (Finger with "selection")
this.OnRequestValidate();
}
else
{
MessageBox.Show(importResultText, "Import failed", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
#endregion #endregion
#region mouse wheel #region mouse wheel
@ -725,6 +766,6 @@ namespace ENI2.DetailViewControls
} }
#endregion #endregion
} }
} }

View File

@ -37,7 +37,7 @@
<CreateWebPageOnPublish>true</CreateWebPageOnPublish> <CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.html</WebPage> <WebPage>publish.html</WebPage>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>6.6.3.0</ApplicationVersion> <ApplicationVersion>6.7.3.0</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut> <CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted> <PublishWizardCompleted>true</PublishWizardCompleted>
@ -214,6 +214,10 @@
<Compile Include="Controls\LocodeControl.xaml.cs"> <Compile Include="Controls\LocodeControl.xaml.cs">
<DependentUpon>LocodeControl.xaml</DependentUpon> <DependentUpon>LocodeControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Import\ExcelBase.cs" />
<Compile Include="Import\ExcelManager.cs" />
<Compile Include="Import\ExcelReader.cs" />
<Compile Include="Import\ExcelUtil.cs" />
<Compile Include="Controls\POListControl.xaml.cs"> <Compile Include="Controls\POListControl.xaml.cs">
<DependentUpon>POListControl.xaml</DependentUpon> <DependentUpon>POListControl.xaml</DependentUpon>
</Compile> </Compile>
@ -358,6 +362,9 @@
<Compile Include="EditControls\NewWithIdDialog.xaml.cs"> <Compile Include="EditControls\NewWithIdDialog.xaml.cs">
<DependentUpon>NewWithIdDialog.xaml</DependentUpon> <DependentUpon>NewWithIdDialog.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="EditControls\SelectImportClassesDialog.xaml.cs">
<DependentUpon>SelectImportClassesDialog.xaml</DependentUpon>
</Compile>
<Compile Include="EditControls\ShowIdDialog.xaml.cs"> <Compile Include="EditControls\ShowIdDialog.xaml.cs">
<DependentUpon>ShowIdDialog.xaml</DependentUpon> <DependentUpon>ShowIdDialog.xaml</DependentUpon>
</Compile> </Compile>
@ -607,6 +614,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="EditControls\SelectImportClassesDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="EditControls\ShowIdDialog.xaml"> <Page Include="EditControls\ShowIdDialog.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@ -7,7 +7,7 @@ using ENI2.Controls;
using bsmd.database; using bsmd.database;
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using bsmd.ExcelReadService; using ENI2.Locode;
using System.ComponentModel; using System.ComponentModel;
namespace ENI2.EditControls namespace ENI2.EditControls

View File

@ -7,7 +7,7 @@ using System.Windows;
using ENI2.Controls; using ENI2.Controls;
using bsmd.database; using bsmd.database;
using bsmd.ExcelReadService; using ENI2.Locode;
namespace ENI2.EditControls namespace ENI2.EditControls
{ {

View File

@ -0,0 +1,28 @@
<enictrl:EditWindowBase x:Class="ENI2.EditControls.SelectImportClassesDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ENI2.EditControls"
xmlns:enictrl="clr-namespace:ENI2.Controls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p="clr-namespace:ENI2.Properties"
mc:Ignorable="d"
Title="{x:Static p:Resources.textSelectImportClasses}" Height="600" Width="250" Background="AliceBlue">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="27" />
<RowDefinition Height="1*" />
<RowDefinition Height="27" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*"/>
<ColumnDefinition Width=".5*"/>
</Grid.ColumnDefinitions>
<Button x:Name="buttonAll" Grid.Column="0" Margin="2" Content="{x:Static p:Resources.textSelectAll}" Click="buttonAll_Click" />
<Button x:Name="buttonNone" Grid.Column="1" Margin="2" Content="{x:Static p:Resources.textSelectNone}" Click="buttonNone_Click"/>
</Grid>
<xctk:CheckListBox x:Name="checkListBoxClasses" Grid.Row="1" Margin="2" VerticalAlignment="Stretch" ValueMemberPath="Class" DisplayMemberPath="Name" SelectedMemberPath="IsSelected" />
</Grid>
</enictrl:EditWindowBase>

View File

@ -0,0 +1,132 @@
// Copyright (c) 2017-today schick Informatik
// Description: Select classes for import
// Returns: Array of selected classes as property
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using bsmd.database;
namespace ENI2.EditControls
{
/// <summary>
/// Interaction logic for SelectImportClassesDialog.xaml
/// </summary>
public partial class SelectImportClassesDialog : ENI2.Controls.EditWindowBase
{
private readonly List<SelectClass> _selectClasses = new List<SelectClass>();
private readonly List<bsmd.database.Message.NotificationClass> _selectedClasses = new List<Message.NotificationClass>();
public SelectImportClassesDialog()
{
InitializeComponent();
this.Loaded += SelectImportClassesDialog_Loaded;
}
public List<bsmd.database.Message.NotificationClass> SelectedClasses
{
get { return _selectedClasses; }
}
public bool IsTransit { get; set; }
private void SelectImportClassesDialog_Loaded(object sender, RoutedEventArgs e)
{
foreach(bsmd.database.Message.NotificationClass notificationClass in Enum.GetValues(typeof(bsmd.database.Message.NotificationClass)))
{
if ((notificationClass == Message.NotificationClass.VISIT) ||
(notificationClass == Message.NotificationClass.TRANSIT) ||
(notificationClass == Message.NotificationClass.ATA) ||
(notificationClass == Message.NotificationClass.ATD) ||
(notificationClass == Message.NotificationClass.CREWD) ||
(notificationClass == Message.NotificationClass.STO) ||
(notificationClass == Message.NotificationClass.PASD)
) continue;
if (IsTransit &&
((notificationClass == Message.NotificationClass.BKRD) ||
(notificationClass == Message.NotificationClass.BPOL) ||
(notificationClass == Message.NotificationClass.HAZD) ||
(notificationClass == Message.NotificationClass.INFO) ||
(notificationClass == Message.NotificationClass.LADG) ||
(notificationClass == Message.NotificationClass.NAME) ||
//(notificationClass == Message.NotificationClass.POBD) ||
(notificationClass == Message.NotificationClass.PRE72H) ||
(notificationClass == Message.NotificationClass.SERV) ||
(notificationClass == Message.NotificationClass.TIEFD) ||
(notificationClass == Message.NotificationClass.TOWD) ||
(notificationClass == Message.NotificationClass.WAS)
)) continue;
SelectClass sc = new SelectClass();
sc.Name = Enum.GetName(typeof(bsmd.database.Message.NotificationClass), notificationClass);
sc.Class = notificationClass;
sc.IsSelected = false;
_selectClasses.Add(sc);
}
_selectClasses.Sort();
this.checkListBoxClasses.ItemsSource = _selectClasses;
this.OKClicked += SelectImportClassesDialog_OKClicked;
}
private void SelectImportClassesDialog_OKClicked()
{
foreach(SelectClass sc in _selectClasses)
{
if (sc.IsSelected) _selectedClasses.Add(sc.Class);
}
}
class SelectClass : IComparable, INotifyPropertyChanged
{
private bool _isSelected;
public string Name { get; set; }
public bsmd.database.Message.NotificationClass Class { get; set; }
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public int CompareTo(object obj)
{
return Name.CompareTo(((SelectClass)obj).Name);
}
}
private void buttonAll_Click(object sender, RoutedEventArgs e)
{
foreach (SelectClass sc in _selectClasses)
sc.IsSelected = true;
}
private void buttonNone_Click(object sender, RoutedEventArgs e)
{
foreach (SelectClass sc in _selectClasses)
sc.IsSelected = false;
}
}
}

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Windows; using System.Windows;
using ENI2.Controls; using ENI2.Controls;
using bsmd.ExcelReadService; using ENI2.Locode;
using bsmd.database; using bsmd.database;
namespace ENI2.EditControls namespace ENI2.EditControls

108
ENI2/Import/ExcelBase.cs Normal file
View File

@ -0,0 +1,108 @@
// Copyright (c) 2017-today Informatikbüro Daniel Schick
// Base class excel (writer not yet implemented but eventually..)
using System;
using System.Collections.Generic;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using log4net;
namespace ENI2.Import
{
internal class ExcelBase : IDisposable
{
#region Fields
internal enum CountryMode { NONE, DE, DK };
protected CountryMode _countryMode = CountryMode.NONE;
protected Workbooks _excelWorkbooks;
protected Workbook _portcall;
protected Application _excelApp;
protected Dictionary<string, Name> _nameDict;
protected ILog _log;
#endregion
#region Properties
internal CountryMode Mode { get { return _countryMode; } }
#endregion
#region Saving
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;
}
#endregion
#region Dispose
public void Dispose()
{
try
{
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);
}
}
catch(Exception ex)
{
_log.ErrorFormat("Exception disposing ExcelReader: {0}", ex.Message);
}
}
#endregion
}
}

View File

@ -0,0 +1,57 @@
// Copyright (c) 2017- Informatikbüro Daniel Schick
// Description: Controller class for reading excel sheets (label-based)
using bsmd.database;
using log4net;
using System;
using System.Collections.Generic;
using System.IO;
namespace ENI2.Import
{
public class ExcelManager
{
private readonly ILog _log = LogManager.GetLogger(typeof(ExcelManager));
public ExcelManager()
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
}
public bool Import(string filePath, MessageCore core, List<Message.NotificationClass> classes, out string readMessage)
{
bool result = false;
try
{
using (ExcelReader reader = new ExcelReader(filePath))
{
ImportHeader importHeader = new ImportHeader
{
ImportDate = DateTime.Now
};
result = ExcelUtil.ProcessSheet(reader, out readMessage, core, classes); // actual import
if (result)
{
importHeader.MessageCoreId = core.Id.Value;
importHeader.Filename = Path.GetFileName(filePath);
ReportingParty thisUser = ReportingParty.CurrentReportingParty;
importHeader.SenderEmail = thisUser.EMail;
importHeader.ReportingPartyId = thisUser.Id;
DBManager.Instance.Save(importHeader);
// Saving plaintext data (ImportHeader + ImportValues) for each reading
List<ImportValue> valueList = importHeader.CreateUpdateList(reader.ImportValues);
// Bulk save recommended here..
ImportValue.BulkSave(valueList);
}
}
}
catch (Exception ex)
{
readMessage = ex.Message;
_log.Error(ex);
}
return result;
}
}
}

576
ENI2/Import/ExcelReader.cs Normal file
View File

@ -0,0 +1,576 @@
//
// 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.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using ENI2.Locode;
using bsmd.database;
namespace ENI2.Import
{
internal class ExcelReader : ExcelBase
{
internal enum ReadState { NONE, OK, WARN, FAIL };
internal Dictionary<string, string> ImportValues { get; } = new Dictionary<string, string>();
public ExcelReader(string filePath)
{
_log = LogManager.GetLogger(typeof(ExcelReader));
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<string, Name>();
int bookCnt = 0;
foreach(Name name in _portcall.Names)
{
string theValue = name.Value;
// Namensbezug: =SheetZelle. Leere Referenzen überspringen (kommt immer mal wieder vor!)
string nameKey = name.Name;
try
{
if (nameKey.Contains("!"))
nameKey = nameKey.Substring(nameKey.IndexOf('!') + 1);
}
catch(Exception)
{
_log.DebugFormat("Strange name in Sheet: {0}", nameKey);
continue;
}
if ((theValue != "=#REF!#REF!") && (theValue != "=#BEZUG!#BEZUG!"))
{
_nameDict[nameKey] = name;
bookCnt++;
}
}
_log.DebugFormat("{0} named ranges found at Workbook level", bookCnt);
foreach(Worksheet ws in _portcall.Worksheets)
{
int wsCnt = 0;
foreach(Name name in ws.Names)
{
string theValue = name.Value;
// Namensbezug: =SheetZelle. Leere Referenzen überspringen (kommt immer mal wieder vor!)
if (!_nameDict.ContainsKey(name.Name))
{
if ((theValue != "=#REF!#REF!") && (theValue != "=#BEZUG!#BEZUG!"))
{
_nameDict[name.Name] = name;
wsCnt++;
}
}
}
if (wsCnt > 0)
_log.DebugFormat("{0} named ranges found in Worksheet {1}", wsCnt, ws.Name);
}
}
internal string ReadText(string lookup)
{
string result = null;
if (_nameDict.ContainsKey(lookup))
{
try
{
var val = _nameDict[lookup].RefersToRange.Value;
var val2 = _nameDict[lookup].RefersToRange.Value2;
if (val != null)
result = val.ToString().Trim();
else if (val2 != null)
result = val2.ToString().Trim();
}
catch (COMException ex)
{
_log.WarnFormat("COMException reading field {0}: {1}", lookup, ex.ErrorCode);
}
}
if (result != null)
{
result = result.Trim();
this.ImportValues[lookup] = result;
}
return result;
}
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())
{
val = val.ToUpper();
string portName = LocodeDB.PortNameFromLocode(val);
if(portName.IsNullOrEmpty())
_log.WarnFormat("unknown Locode {0}", val);
}
return val;
}
internal int? ReadCargoLACode(string lookup)
{
string val = ReadText(lookup);
if (val.IsNullOrEmpty()) return null;
if(int.TryParse(val, out int result))
{
if ((result < 10) || (result > 99))
_log.WarnFormat("invalid cargo LA code {0}", result);
return result;
}
else
{
_log.ErrorFormat("Cargo LA code parse error for {0}", lookup);
return null;
}
}
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)) {
result = 0;
}
else if (val.Equals("f", StringComparison.CurrentCultureIgnoreCase) || val.Equals("female", StringComparison.CurrentCultureIgnoreCase))
{
result = 1;
}
else
{
result = 2;
}
}
if(result == null)
{
_log.ErrorFormat("error reading gender on {0}", lookup);
}
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) || val.Equals("1")) result = 0;
if (val.Equals("passport", StringComparison.CurrentCultureIgnoreCase) || val.Equals("2")) result = 1;
if (val.Equals("muster_book", StringComparison.CurrentCultureIgnoreCase) || val.Equals("3")) result = 2;
if (val.Equals("picture_id", StringComparison.CurrentCultureIgnoreCase) || val.Equals("4")) result = 3;
if (val.Equals("residental_permit", StringComparison.CurrentCultureIgnoreCase) || val.Equals("5")) result = 4;
if (val.Equals("other_legal_identity_document", StringComparison.CurrentCultureIgnoreCase) || val.Equals("6")) result = 5;
if (val.Equals("ic", StringComparison.CurrentCultureIgnoreCase)) result = 0;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read identity document type {0}", lookup);
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) || (val.Equals("1"))) result = 0;
if ((val.IndexOf("europe", StringComparison.OrdinalIgnoreCase) >= 0) || (val.Equals("2"))) result = 1;
if ((val.IndexOf("overseas", StringComparison.OrdinalIgnoreCase) >= 0) || (val.Equals("3"))) result = 2;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read shipping area {0}", lookup);
return result;
}
internal byte? ReadGeneralDescriptionOfCargo(string lookup)
{
string val = this.ReadText(lookup);
byte? result = null;
if (val != null)
{
if (val.Contains("container", StringComparison.OrdinalIgnoreCase) || val.Equals("1")) result = 0;
if (val.Contains("vehicles", StringComparison.OrdinalIgnoreCase) || val.Equals("2")) result = 1;
if (val.Contains("convent", StringComparison.OrdinalIgnoreCase) || val.Equals("3")) result = 2;
if (val.Contains("dry", StringComparison.OrdinalIgnoreCase) || val.Equals("4")) result = 3;
if (val.Contains("liquid", StringComparison.OrdinalIgnoreCase) || val.Equals("5")) result = 4;
if (val.Contains("empty", StringComparison.OrdinalIgnoreCase) || val.Equals("6")) result = 5;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read general description of cargo {0}", lookup);
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) || val.Equals("1")) result = 0;
if ((val.IndexOf("discharge", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("2")) result = 1;
if ((val.IndexOf("transit", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("3")) result = 2;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read cargo handling type {0}", lookup);
return result;
}
/// <summary>
/// read nationality field an returns 2 Char ISO code (optional lookup) and "confirms"
/// the field
/// </summary>
internal string ReadNationality(string lookup)
{
string val = this.ReadText(lookup);
if ((val != null) && (val.Length == 2))
{
string isoCode = LocodeDB.CountryCodeFromName(val);
if (isoCode == null)
_log.ErrorFormat("Wrong ISO code {0}", val);
}
else
{
_log.ErrorFormat("cannot read nationality {0}", lookup);
}
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.HasValue)
_log.ErrorFormat("cannot read hull configuration {0}", lookup);
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;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read packing group {0}", lookup);
return result;
}
internal string ReadShip2ShipActivityType(string lookup)
{
string val = this.ReadText(lookup);
bool isValid = false;
if(!val.IsNullOrEmpty())
{
if (int.TryParse(val, out int typeVal))
{
if ((typeVal >= 1) && (typeVal <= 23))
isValid = true;
}
}
if (!isValid)
_log.WarnFormat("cannot read ship2ship activity type {0}", lookup);
return val;
}
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.HasValue)
_log.ErrorFormat("cannot read condition tanks {0}", lookup);
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) || val.Equals("1")) result = 0;
if ((val.IndexOf("some", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("2")) result = 1;
if ((val.IndexOf("none", StringComparison.OrdinalIgnoreCase) >= 0) || val.Equals("3")) result = 2;
}
if (!result.HasValue)
_log.ErrorFormat("cannot read delivery {0}", lookup);
return result;
}
internal DateTime? ReadBirthDate(string lookup)
{
DateTime? result = this.ReadDate(lookup);
if(result.HasValue)
{
if (result.Value > DateTime.Now)
_log.WarnFormat("Birth date implausible for {0} : {1}", lookup, result);
}
return result;
}
internal DateTime? ReadDate(string lookup, bool noHighlight = false)
{
try
{
DateTime? date = null;
if (_nameDict.ContainsKey(lookup))
{
var val = _nameDict[lookup].RefersToRange.Value;
if (val is DateTime)
{
date = val;
}
else if (val is double)
{
try
{
date = DateTime.FromOADate(val);
}
catch (ArgumentException) { /* .. */ }
if(date == null)
{
CultureInfo provider = CultureInfo.InvariantCulture;
string dateString = val.ToString();
const string format = "yyyyMMdd";
if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate))
date = tmpDate;
}
}
if (date == null)
{
if (DateTime.TryParse(val, out DateTime tmpDate))
date = tmpDate;
}
if (date != null)
{
if ((date.Value < new DateTime(1899, 1, 1)) || (date.Value > new DateTime(2030, 1, 1)))
{
date = null; // this can't be right
}
}
}
return date;
}
catch (Exception)
{
_log.WarnFormat("error parsing datetime for lookup {0}", lookup);
return null;
}
}
internal DateTime? ReadDateTime(string dateField, string timeField, bool noHighlight = false)
{
DateTime? result = null;
DateTime? etaDate = this.ReadDate(dateField, noHighlight);
DateTime? etaTime = this.ReadTime(timeField, noHighlight);
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, DateTimeKind.Local);
result = result.Value.ToUniversalTime();
}
}
return result;
}
internal DateTime? ReadTime(string lookup, bool noHighlight = false)
{
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(":"))
{
const string format = "HHmm";
if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate))
result = tmpDate;
}
}
}
if (result == null)
{
if (DateTime.TryParseExact(val, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out DateTime date))
result = date;
}
if (result == null)
{
if (DateTime.TryParseExact(val, "HH:mm", CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault, out DateTime date))
result = date;
}
if ((result == null) && (val != null))
{
CultureInfo provider = CultureInfo.InvariantCulture;
string dateString = val.ToString();
if (!dateString.Contains(":"))
{
const string format = "HHmm";
if (DateTime.TryParseExact(dateString, format, provider, DateTimeStyles.None, out DateTime tmpDate))
result = tmpDate;
}
}
}
}
catch (Exception)
{
_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)
{
if (double.TryParse(val, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite,
CultureInfo.InvariantCulture, out double 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))
{
double tmpDouble2 = val[1, 1];
result = tmpDouble2;
}
}
}
catch (Exception)
{
_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;
}
return result.Value;
}
internal bool? ReadBoolean(string lookup, bool noHighlight = false)
{
string val = this.ReadText(lookup);
if (val == null)
return null;
if ((val == "y") || (val == "Y") || val.Equals("yes", StringComparison.OrdinalIgnoreCase) || (val == "1") || (val == "x") || (val == "X"))
return true;
return false;
}
}
}

2411
ENI2/Import/ExcelUtil.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ using System.Data.SQLite;
using System.Collections.Generic; using System.Collections.Generic;
using bsmd.database; using bsmd.database;
using bsmd.ExcelReadService; using ENI2.Locode;
namespace ENI2 namespace ENI2
{ {

View File

@ -21,7 +21,7 @@ using ENI2.Util;
using log4net; using log4net;
using System.ComponentModel; using System.ComponentModel;
using bsmd.ExcelReadService; using ENI2.Locode;
using System.Text; using System.Text;
namespace ENI2 namespace ENI2

View File

@ -2081,6 +2081,15 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized string similar to Excel Import.
/// </summary>
public static string textExcelImport {
get {
return ResourceManager.GetString("textExcelImport", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Excepted quantities. /// Looks up a localized string similar to Excepted quantities.
/// </summary> /// </summary>
@ -4025,6 +4034,33 @@ namespace ENI2.Properties {
} }
} }
/// <summary>
/// Looks up a localized string similar to Select all.
/// </summary>
public static string textSelectAll {
get {
return ResourceManager.GetString("textSelectAll", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select classes to import.
/// </summary>
public static string textSelectImportClasses {
get {
return ResourceManager.GetString("textSelectImportClasses", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select none.
/// </summary>
public static string textSelectNone {
get {
return ResourceManager.GetString("textSelectNone", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Send date. /// Looks up a localized string similar to Send date.
/// </summary> /// </summary>

View File

@ -1738,4 +1738,16 @@
<data name="undo" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="undo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\undo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\undo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="textExcelImport" xml:space="preserve">
<value>Excel Import</value>
</data>
<data name="textSelectAll" xml:space="preserve">
<value>Select all</value>
</data>
<data name="textSelectImportClasses" xml:space="preserve">
<value>Select classes to import</value>
</data>
<data name="textSelectNone" xml:space="preserve">
<value>Select none</value>
</data>
</root> </root>

View File

@ -7,7 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using bsmd.ExcelReadService; using ENI2.Locode;
namespace ENI2.Util namespace ENI2.Util
{ {

View File

@ -14,7 +14,7 @@ using System.Data.SQLite;
using bsmd.database; using bsmd.database;
using log4net; using log4net;
namespace bsmd.ExcelReadService namespace ENI2.Locode
{ {
/// <summary> /// <summary>
/// Locodes suchen (zu Orten), die DB ist aus einem github Projekt: /// Locodes suchen (zu Orten), die DB ist aus einem github Projekt:

View File

@ -2,6 +2,6 @@
[assembly: AssemblyCompany("schick Informatik")] [assembly: AssemblyCompany("schick Informatik")]
[assembly: AssemblyProduct("BSMD NSW interface")] [assembly: AssemblyProduct("BSMD NSW interface")]
[assembly: AssemblyInformationalVersion("6.6.0")] [assembly: AssemblyInformationalVersion("6.7.0")]
[assembly: AssemblyCopyright("Copyright © 2014-2021 schick Informatik")] [assembly: AssemblyCopyright("Copyright © 2014-2021 schick Informatik")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]

View File

@ -1,4 +1,4 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("6.6.0.*")] [assembly: AssemblyVersion("6.7.0.*")]