diff --git a/ExcelHelper.csproj b/ExcelHelper.csproj
index 0da09ee..ce2871e 100644
--- a/ExcelHelper.csproj
+++ b/ExcelHelper.csproj
@@ -50,8 +50,11 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
+
+
+
\ No newline at end of file
diff --git a/MainWindow.xaml b/MainWindow.xaml
index e5dfeb2..d1cd8c3 100644
--- a/MainWindow.xaml
+++ b/MainWindow.xaml
@@ -33,23 +33,29 @@
x:Name="MainFrame"
Grid.Column="1"
NavigationUIVisibility="Hidden" />
-
+
-
-
+
+
-
+
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
index b3c6772..49a0771 100644
--- a/MainWindow.xaml.cs
+++ b/MainWindow.xaml.cs
@@ -5,34 +5,33 @@ using ExcelHelper.Services;
using ExcelHelper.Views;
using ExcelHelper.Views.ViewModels;
-namespace ExcelHelper
+namespace ExcelHelper;
+
+///
+/// MainWindow.xaml 的交互逻辑
+///
+public partial class MainWindow : Window, IView
{
- ///
- /// MainWindow.xaml 的交互逻辑
- ///
- public partial class MainWindow : Window, IView
+ private readonly MainViewModel ViewModel;
+ public MainWindow(MainViewModel viewModel, NavigationService navigationService)
{
- private MainViewModel ViewModel;
- public MainWindow(MainViewModel viewModel, NavigationService navigationService)
- {
- InitializeComponent();
- DataContext = ViewModel = viewModel;
- navigationService.InitForFrame(MainFrame);
+ InitializeComponent();
+ DataContext = ViewModel = viewModel;
+ navigationService.InitForFrame(MainFrame);
- WeakReferenceMessenger.Default.Register(this, (r, message) =>
+ WeakReferenceMessenger.Default.Register(this, (r, message) =>
+ {
+ if (message.Value != null)
{
- if (message.Value != null)
- {
- ViewModel.ErrorMessage = message.Value;
- MessageDialog.Visibility = Visibility.Visible;
- }
- });
- }
-
- private void DialogCloseBtn_Click(object sender, System.Windows.RoutedEventArgs e)
- {
- MessageDialog.Visibility = System.Windows.Visibility.Collapsed;
- }
-
+ ViewModel.ErrorMessage = message.Value;
+ MessageDialog.Visibility = Visibility.Visible;
+ }
+ });
}
+
+ private void DialogCloseBtn_Click(object sender, System.Windows.RoutedEventArgs e)
+ {
+ MessageDialog.Visibility = System.Windows.Visibility.Collapsed;
+ }
+
}
diff --git a/Model/TableColumnModel.cs b/Model/TableColumnModel.cs
new file mode 100644
index 0000000..56149e6
--- /dev/null
+++ b/Model/TableColumnModel.cs
@@ -0,0 +1,18 @@
+namespace ExcelHelper.Model
+{
+ public class TableColumnModel
+ {
+ public string ExcelColumnName
+ {
+ get; set;
+ }
+ public string TableColumnName
+ {
+ get; set;
+ }
+ public string DataType
+ {
+ get; set;
+ }
+ }
+}
diff --git a/Services/ExcelHelperHostedService.cs b/Services/ExcelHelperHostedService.cs
index 4bf73a5..9bf2ecf 100644
--- a/Services/ExcelHelperHostedService.cs
+++ b/Services/ExcelHelperHostedService.cs
@@ -3,25 +3,24 @@ using System.Threading.Tasks;
using ExcelHelper.Views.Pages;
using Microsoft.Extensions.Hosting;
-namespace ExcelHelper.Services
+namespace ExcelHelper.Services;
+
+public class ExcelHelperHostedService : IHostedService
{
- public class ExcelHelperHostedService : IHostedService
+ public Task StartAsync(CancellationToken cancellationToken)
{
- public Task StartAsync(CancellationToken cancellationToken)
+ var mainWindow = App.AppHost.Get();
+ if (mainWindow != null)
{
- var mainWindow = App.AppHost.Get();
- if (mainWindow != null)
- {
- mainWindow.Show();
- App.AppHost.Get().NavigateTo();
- }
-
- return Task.CompletedTask;
+ mainWindow.Show();
+ App.AppHost.Get().NavigateTo();
}
- public Task StopAsync(CancellationToken cancellationToken)
- {
- return Task.CompletedTask;
- }
+ return Task.CompletedTask;
+ }
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+
}
}
diff --git a/Services/NavigationService.cs b/Services/NavigationService.cs
index 97f82fe..7e7a26b 100644
--- a/Services/NavigationService.cs
+++ b/Services/NavigationService.cs
@@ -2,34 +2,33 @@
using System.Windows.Controls;
using ExcelHelper.Views;
-namespace ExcelHelper.Services
-{
- public class NavigationService
- {
- private Frame _frame;
- public static string currentView;
+namespace ExcelHelper.Services;
- public void InitForFrame(Frame frame)
+public class NavigationService
+{
+ private Frame _frame;
+ public static string currentView;
+
+ public void InitForFrame(Frame frame)
+ {
+ _frame = frame;
+ }
+ public void NavigateTo()
+ {
+ var target = App.AppHost.Get();
+ if (target is IView page)
{
- _frame = frame;
+ currentView = typeof(T).Name;
+ _frame.NavigationService.Navigate(page);
}
- public void NavigateTo()
+ }
+ public void NavigateTo(Type type)
+ {
+ var target = App.AppHost.Get(type);
+ if (target is IView page)
{
- var target = App.AppHost.Get();
- if (target is IView page)
- {
- currentView = typeof(T).Name;
- _frame.NavigationService.Navigate(page);
- }
- }
- public void NavigateTo(Type type)
- {
- var target = App.AppHost.Get(type);
- if (target is IView page)
- {
- currentView = type.Name;
- _frame.NavigationService.Navigate(page);
- }
+ currentView = type.Name;
+ _frame.NavigationService.Navigate(page);
}
}
}
diff --git a/Utils/PasswordBoxHelper.cs b/Utils/PasswordBoxHelper.cs
index dde7c02..e6090e9 100644
--- a/Utils/PasswordBoxHelper.cs
+++ b/Utils/PasswordBoxHelper.cs
@@ -57,8 +57,7 @@ public static class PasswordBoxHelper
private static void OnAttachPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
- PasswordBox passwordBox = sender as PasswordBox;
- if (passwordBox == null)
+ if (sender is not PasswordBox passwordBox)
{
return;
}
diff --git a/Views/IView.cs b/Views/IView.cs
index 2e7759d..0cfa35a 100644
--- a/Views/IView.cs
+++ b/Views/IView.cs
@@ -1,6 +1,5 @@
-namespace ExcelHelper.Views
+namespace ExcelHelper.Views;
+
+internal interface IView
{
- internal interface IView
- {
- }
}
diff --git a/Views/IViewModel.cs b/Views/IViewModel.cs
index 4db56bc..cc8d651 100644
--- a/Views/IViewModel.cs
+++ b/Views/IViewModel.cs
@@ -1,6 +1,5 @@
-namespace ExcelHelper.Views
+namespace ExcelHelper.Views;
+
+internal interface IViewModel
{
- internal interface IViewModel
- {
- }
}
diff --git a/Views/Pages/DataListPage.xaml.cs b/Views/Pages/DataListPage.xaml.cs
index 09a832e..e6a3380 100644
--- a/Views/Pages/DataListPage.xaml.cs
+++ b/Views/Pages/DataListPage.xaml.cs
@@ -1,15 +1,14 @@
using System.Windows.Controls;
-namespace ExcelHelper.Views.Pages
+namespace ExcelHelper.Views.Pages;
+
+///
+/// DataListPage.xaml 的交互逻辑
+///
+public partial class DataListPage : Page, IView
{
- ///
- /// DataListPage.xaml 的交互逻辑
- ///
- public partial class DataListPage : Page, IView
+ public DataListPage()
{
- public DataListPage()
- {
- InitializeComponent();
- }
+ InitializeComponent();
}
}
diff --git a/Views/Pages/ImportExcelPage.xaml b/Views/Pages/ImportExcelPage.xaml
index 1c09ed8..63baedf 100644
--- a/Views/Pages/ImportExcelPage.xaml
+++ b/Views/Pages/ImportExcelPage.xaml
@@ -69,8 +69,7 @@
+ ItemsSource="{Binding TableColumns, IsAsync=True}">
-
+
+
@@ -96,74 +96,132 @@
Grid.Column="0"
Width="2"
Margin="0,5" />
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/Views/Pages/ImportExcelPage.xaml.cs b/Views/Pages/ImportExcelPage.xaml.cs
index e31c05e..735b1de 100644
--- a/Views/Pages/ImportExcelPage.xaml.cs
+++ b/Views/Pages/ImportExcelPage.xaml.cs
@@ -3,64 +3,21 @@ using CommunityToolkit.Mvvm.Messaging;
using ExcelHelper.Message;
using ExcelHelper.Views.ViewModels;
-namespace ExcelHelper.Views.Pages
+namespace ExcelHelper.Views.Pages;
+
+///
+/// ImportExcelPage.xaml 的交互逻辑
+///
+public partial class ImportExcelPage : Page, IView, IRecipient
{
- ///
- /// ImportExcelPage.xaml 的交互逻辑
- ///
- public partial class ImportExcelPage : Page, IView, IRecipient
+ private readonly ImportViewModel ViewModel;
+ public ImportExcelPage(ImportViewModel viewModel)
{
- private ImportViewModel ViewModel;
- public ImportExcelPage(ImportViewModel viewModel)
- {
- InitializeComponent();
- this.DataContext = ViewModel = viewModel;
- ViewModel.IsActive = true;
- // Register a message in some module
- WeakReferenceMessenger.Default.Register(this, (r, message) =>
- {
- if (message.Value != null)
- {
- ExcelDataPreviewGrid.Columns.Clear();
- foreach (var column in message.Value)
- {
- ExcelDataPreviewGrid.Columns.Add(column);
- }
- }
- });
- }
- private void Grid_DragEnter(object sender, System.Windows.DragEventArgs e)
- {
- if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop))
- {
- e.Effects = System.Windows.DragDropEffects.Link;
- }
- else
- {
- e.Effects = System.Windows.DragDropEffects.None;
- }
- DropFileMask.Visibility = System.Windows.Visibility.Visible;
- }
-
- private void Grid_Drop(object sender, System.Windows.DragEventArgs e)
- {
- DropFileMask.Visibility = System.Windows.Visibility.Collapsed;
- if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop))
- {
- var files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
- if (files.Length > 0)
- {
- ViewModel.FileDrop(files);
- }
- }
- }
-
- private void Grid_DragLeave(object sender, System.Windows.DragEventArgs e)
- {
- DropFileMask.Visibility = System.Windows.Visibility.Collapsed;
- }
-
- void IRecipient.Receive(UpdateDataGridColumnsMessage message)
+ InitializeComponent();
+ this.DataContext = ViewModel = viewModel;
+ ViewModel.IsActive = true;
+ // Register a message in some module
+ WeakReferenceMessenger.Default.Register(this, (r, message) =>
{
if (message.Value != null)
{
@@ -70,6 +27,48 @@ namespace ExcelHelper.Views.Pages
ExcelDataPreviewGrid.Columns.Add(column);
}
}
+ });
+ }
+ private void Grid_DragEnter(object sender, System.Windows.DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop))
+ {
+ e.Effects = System.Windows.DragDropEffects.Link;
+ }
+ else
+ {
+ e.Effects = System.Windows.DragDropEffects.None;
+ }
+ DropFileMask.Visibility = System.Windows.Visibility.Visible;
+ }
+
+ private void Grid_Drop(object sender, System.Windows.DragEventArgs e)
+ {
+ DropFileMask.Visibility = System.Windows.Visibility.Collapsed;
+ if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop))
+ {
+ var files = (string[])e.Data.GetData(System.Windows.DataFormats.FileDrop);
+ if (files.Length > 0)
+ {
+ ViewModel.FileDrop(files);
+ }
+ }
+ }
+
+ private void Grid_DragLeave(object sender, System.Windows.DragEventArgs e)
+ {
+ DropFileMask.Visibility = System.Windows.Visibility.Collapsed;
+ }
+
+ void IRecipient.Receive(UpdateDataGridColumnsMessage message)
+ {
+ if (message.Value != null)
+ {
+ ExcelDataPreviewGrid.Columns.Clear();
+ foreach (var column in message.Value)
+ {
+ ExcelDataPreviewGrid.Columns.Add(column);
+ }
}
}
}
diff --git a/Views/ViewModels/ImportViewModel.cs b/Views/ViewModels/ImportViewModel.cs
index a307315..0927d91 100644
--- a/Views/ViewModels/ImportViewModel.cs
+++ b/Views/ViewModels/ImportViewModel.cs
@@ -2,12 +2,16 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
+using System.Threading.Tasks;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using ExcelHelper.Message;
+using ExcelHelper.Model;
using MiniExcelLibs;
+using MiniExcelLibs.OpenXml;
+using SqlSugar;
namespace ExcelHelper.Views.ViewModels;
@@ -31,15 +35,23 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
IsLoading = false;
}
- public async void ReadForExcel(string path)
+ public async void ReadForExcel(string path, bool isReload = false)
{
IsLoading = true;
//await Task.Factory.StartNew(async () =>
//{
try
{
- if (string.IsNullOrEmpty(path)) return;
- var excelData = await MiniExcel.QueryAsync(path, sheetName: SelectedSheetName, useHeaderRow: UseHeaderRow, startCell: StartCell);
+ var config = new OpenXmlConfiguration()
+ {
+ FillMergedCells = FillMergedCells
+ };
+ if (string.IsNullOrEmpty(path))
+ {
+ IsLoading = false;
+ return;
+ }
+ var excelData = await GetExcelData(path, config);
if (MaxRow != 0)
{
ExcelData = excelData.Take(Math.Min(MaxRow, 300));
@@ -48,9 +60,20 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
{
ExcelData = excelData.Take(300);
}
- var columns = MiniExcel.GetColumns(path, useHeaderRow: UseHeaderRow, startCell: StartCell, sheetName: SelectedSheetName);
+ var currentSheetName = SelectedSheetName;
+ var columns = MiniExcel.GetColumns(path, useHeaderRow: UseHeaderRow, startCell: StartCell, sheetName: currentSheetName, configuration: config);
+
GenColumns(columns);
+
GetSheets(path);
+ if (string.IsNullOrEmpty(currentSheetName))
+ {
+ SelectedSheetName = Sheets.FirstOrDefault();
+ }
+ else
+ {
+ SelectedSheetName = Sheets.FirstOrDefault(it => it.Equals(currentSheetName));
+ }
MaxRow = ExcelData.Count();
}
catch (Exception ex)
@@ -58,18 +81,22 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
WeakReferenceMessenger.Default.Send(new ErrorDialogMessage($"出现了异常!{ex}"));
}
IsLoading = false;
- //}).ContinueWith(x =>
- // {
-
-
- // });
}
+ public async Task> GetExcelData(string path, Configuration config)
+ {
+
+ return string.IsNullOrEmpty(EndCell)
+ ? await MiniExcel.QueryAsync(path, sheetName: SelectedSheetName, useHeaderRow: UseHeaderRow, startCell: StartCell, configuration: config)
+ : MiniExcel.QueryRange(path, sheetName: SelectedSheetName, useHeaderRow: UseHeaderRow, startCell: StartCell, endCell: EndCell, configuration: config);
+ }
+
+
private void GenColumns(IEnumerable columns)
{
ExcelColumns.Clear();
+ TableColumns.Clear();
if (UseHeaderRow)
{
-
foreach (var columnName in columns)
{
var column = new DataGridTextColumn
@@ -94,8 +121,20 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
ExcelColumns.Add(column);
}
}
+ int columnsSeq = 0;
+ foreach (var item in ExcelColumns)
+ {
+ TableColumns.Add(new TableColumnModel
+ {
+ ExcelColumnName = item.Header.ToString(),
+ TableColumnName = $"Column{columnsSeq}",
+ });
+ columnsSeq++;
+ }
if (ExcelColumns.Count > 0)
+ {
WeakReferenceMessenger.Default.Send(new UpdateDataGridColumnsMessage([.. ExcelColumns]));
+ }
else
{
WeakReferenceMessenger.Default.Send(new ErrorDialogMessage("未读取到列信息!"));
@@ -105,31 +144,100 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
[RelayCommand]
private void OnReLoadExcel()
{
- ReadForExcel(CurrentFilePath);
+ ReadForExcel(CurrentFilePath, isReload: true);
}
[RelayCommand]
private void OnReadSheets()
{
- if (string.IsNullOrWhiteSpace(CurrentFilePath))
+ if (!string.IsNullOrWhiteSpace(CurrentFilePath))
{
GetSheets(CurrentFilePath);
+ SelectedSheetName = Sheets.FirstOrDefault();
+
}
}
private void GetSheets(string excelPath)
{
+ var sheets = MiniExcel.GetSheetNames(excelPath);
if (Sheets == null)
{
- Sheets = new ObservableCollection();
+ Sheets = [];
}
else
{
Sheets.Clear();
}
- MiniExcel.GetSheetNames(excelPath)?.ForEach(sheetName =>
+
+ sheets.ForEach(sheetName =>
{
Sheets.Add(sheetName);
});
- SelectedSheetName = Sheets.FirstOrDefault();
+ }
+
+ [RelayCommand]
+ private void OnTestDbConn()
+ {
+ try
+ {
+ var client = GetClient();
+ var tables = client.Ado.ExecuteCommand("select 1");
+ WeakReferenceMessenger.Default.Send(new ErrorDialogMessage("连接成功!"));
+ }
+ catch (Exception ex)
+ {
+ WeakReferenceMessenger.Default.Send(new ErrorDialogMessage($"连接失败!{ex}"));
+ }
+ }
+
+ private SqlSugarClient GetClient()
+ {
+ var connStr = GetConnStr(DbType);
+ if (string.IsNullOrEmpty(connStr))
+ {
+ WeakReferenceMessenger.Default.Send(new ErrorDialogMessage("未知的数据库类型!"));
+ return null;
+ }
+ try
+ {
+ var client = new SqlSugarClient(new ConnectionConfig
+ {
+ ConnectionString = connStr,
+ DbType = DbType switch
+ {
+ //"MySql" => SqlSugar.DbType.MySql,
+ "Sqlite" => SqlSugar.DbType.Sqlite,
+ "SqlServer" => SqlSugar.DbType.SqlServer,
+ _ => throw new Exception("未知的数据库类型")
+ },
+ IsAutoCloseConnection = true
+ });
+ return client;
+ //WeakReferenceMessenger.Default.Send(new ErrorDialogMessage("连接成功!"));
+ }
+ catch (Exception ex)
+ {
+ WeakReferenceMessenger.Default.Send(new ErrorDialogMessage($"连接失败!{ex}"));
+ return null;
+ }
+ }
+
+
+ private string GetConnStr(string dbType)
+ {
+ var encryptStr = "";
+ if (IsEncrypt)
+ {
+ encryptStr = "Encrypt=True;TrustServerCertificate=True;";
+ }
+
+ return dbType switch
+ {
+ //"MySql" => $"Server={DbServer};Port={DbPort};Database={DbName};User Id={DbUser};Password={DbPassword};{encryptStr}",
+ "SqlServer" => $"Server={DbServer},{DbPort};Database={DbName};User Id={DbUser};Password={DbPassword};{encryptStr}",
+ //"PostgreSql" => $"Server={DbServer};Port={DbPort};Database={DbName};User Id={DbUser};Password={DbPassword};{encryptStr}",
+ "Sqlite" => $"DataSource={DbServer};",
+ _ => ""
+ };
}
#region Props
@@ -142,6 +250,9 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
[ObservableProperty]
private ObservableCollection _excelColumns = [];
+ [ObservableProperty]
+ private ObservableCollection _tableColumns = [];
+
///
/// 是否正在加载
///
@@ -175,6 +286,13 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
///
[ObservableProperty]
private string _endCell;
+
+ ///
+ /// 使用首行作为表头
+ ///
+ [ObservableProperty]
+ private bool _fillMergedCells = false;
+
///
/// 最大行数
///
@@ -201,5 +319,30 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
[ObservableProperty]
private string _excelPassword;
+
+ [ObservableProperty]
+ private string _dbType;
+
+ ///
+ /// 加密连接
+ ///
+ [ObservableProperty]
+ private bool _isEncrypt;
+
+ [ObservableProperty]
+ private string _dbUser;
+ [ObservableProperty]
+ private string _dbPassword;
+
+ [ObservableProperty]
+ private string _dbServer;
+
+ [ObservableProperty]
+ private string _dbPort;
+
+ [ObservableProperty]
+ private string _dbName;
+
+
#endregion
}
diff --git a/Views/ViewModels/MainViewModel.cs b/Views/ViewModels/MainViewModel.cs
index 6e7ad6b..c9a3dc0 100644
--- a/Views/ViewModels/MainViewModel.cs
+++ b/Views/ViewModels/MainViewModel.cs
@@ -3,32 +3,31 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ExcelHelper.Views.Pages;
-namespace ExcelHelper.Views.ViewModels
+namespace ExcelHelper.Views.ViewModels;
+
+public partial class MainViewModel : ObservableObject, IViewModel
{
- public partial class MainViewModel : ObservableObject, IViewModel
+
+ ///
+ /// 异常信息
+ ///
+ [ObservableProperty]
+ private string _errorMessage;
+
+ [RelayCommand]
+ private void OnSideMenuSelect(string itemTag)
{
-
- ///
- /// 异常信息
- ///
- [ObservableProperty]
- private string _errorMessage;
-
- [RelayCommand]
- private void OnSideMenuSelect(string itemTag)
+ Trace.WriteLine($"OnSideMenuSelect -> {itemTag}");
+ var targetPage = itemTag switch
{
- Trace.WriteLine($"OnSideMenuSelect -> {itemTag}");
- var targetPage = itemTag switch
- {
- "ImportExcelPage" => typeof(ImportExcelPage),
- "DataListPage" => typeof(DataListPage),
- _ => null
- };
- if (targetPage != null)
- {
- App.AppHost.Get().NavigateTo(targetPage);
- }
+ "ImportExcelPage" => typeof(ImportExcelPage),
+ "DataListPage" => typeof(DataListPage),
+ _ => null
+ };
+ if (targetPage != null)
+ {
+ App.AppHost.Get().NavigateTo(targetPage);
}
-
}
+
}