diff --git a/Helper/ExcelHelper.cs b/Helper/ExcelHelper.cs
new file mode 100644
index 0000000..bb5e6cd
--- /dev/null
+++ b/Helper/ExcelHelper.cs
@@ -0,0 +1,275 @@
+
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using NPOI.SS.UserModel;
+using NPOI.XSSF.UserModel;
+using PMSWPF.Enums;
+using PMSWPF.Models;
+
+namespace PMSWPF.Helper
+{
+ ///
+ /// Excel 操作帮助类
+ ///
+ public static class ExcelHelper
+ {
+ ///
+ /// 将数据列表导出到 Excel 文件。
+ ///
+ /// 数据类型。
+ /// 要导出的数据列表。
+ /// Excel 文件的保存路径。
+ /// 工作表的名称。
+ public static void ExportToExcel(IEnumerable data, string filePath, string sheetName = "Sheet1") where T : class
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException(nameof(data));
+ }
+
+ using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ IWorkbook workbook = new XSSFWorkbook();
+ ISheet sheet = workbook.CreateSheet(sheetName);
+
+ // 获取T类型的属性
+ PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+ // 创建表头
+ IRow headerRow = sheet.CreateRow(0);
+ for (int i = 0; i < properties.Length; i++)
+ {
+ headerRow.CreateCell(i).SetCellValue(properties[i].Name);
+ }
+
+ // 填充数据
+ int rowIndex = 1;
+ foreach (var item in data)
+ {
+ IRow dataRow = sheet.CreateRow(rowIndex++);
+ for (int i = 0; i < properties.Length; i++)
+ {
+ object value = properties[i].GetValue(item, null);
+ dataRow.CreateCell(i).SetCellValue(value?.ToString() ?? string.Empty);
+ }
+ }
+
+ workbook.Write(fs);
+ }
+ }
+
+ ///
+ /// 将 DataTable 导出到 Excel 文件。
+ ///
+ /// 要导出的 DataTable。
+ /// Excel 文件的保存路径。
+ /// 工作表的名称。
+ public static void ExportToExcel(DataTable dataTable, string filePath, string sheetName = "Sheet1")
+ {
+ if (dataTable == null)
+ {
+ throw new ArgumentNullException(nameof(dataTable));
+ }
+
+ using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
+ {
+ IWorkbook workbook = new XSSFWorkbook();
+ ISheet sheet = workbook.CreateSheet(sheetName);
+
+ // 创建表头
+ IRow headerRow = sheet.CreateRow(0);
+ for (int i = 0; i < dataTable.Columns.Count; i++)
+ {
+ headerRow.CreateCell(i).SetCellValue(dataTable.Columns[i].ColumnName);
+ }
+
+ // 填充数据
+ for (int i = 0; i < dataTable.Rows.Count; i++)
+ {
+ IRow dataRow = sheet.CreateRow(i + 1);
+ for (int j = 0; j < dataTable.Columns.Count; j++)
+ {
+ dataRow.CreateCell(j).SetCellValue(dataTable.Rows[i][j].ToString());
+ }
+ }
+
+ workbook.Write(fs);
+ }
+ }
+
+ ///
+ /// 从 Excel 文件导入数据到 DataTable。
+ ///
+ /// Excel 文件的路径。
+ /// 工作表的名称。
+ /// 是否包含表头行。
+ /// 包含导入数据的 DataTable。
+ public static DataTable ImportFromExcel(string filePath, string sheetName = "Sheet1", bool hasHeaderRow = true)
+ {
+ if (!File.Exists(filePath))
+ {
+ throw new FileNotFoundException("The specified file does not exist.", filePath);
+ }
+
+ var dt = new DataTable();
+ using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ IWorkbook workbook = new XSSFWorkbook(fs);
+ ISheet sheet = workbook.GetSheet(sheetName) ?? workbook.GetSheetAt(0);
+
+ if (sheet == null)
+ {
+ throw new Exception($"Sheet with name '{sheetName}' not found.");
+ }
+
+ IRow headerRow = hasHeaderRow ? sheet.GetRow(0) : null;
+ int firstRow = hasHeaderRow ? 1 : 0;
+ int cellCount = headerRow?.LastCellNum ?? sheet.GetRow(sheet.FirstRowNum).LastCellNum;
+
+ // 创建列
+ for (int i = 0; i < cellCount; i++)
+ {
+ string columnName = hasHeaderRow ? headerRow.GetCell(i)?.ToString() ?? $"Column{i + 1}" : $"Column{i + 1}";
+ dt.Columns.Add(columnName);
+ }
+
+ // 填充数据
+ for (int i = firstRow; i <= sheet.LastRowNum; i++)
+ {
+ IRow row = sheet.GetRow(i);
+ if (row == null) continue;
+
+ DataRow dataRow = dt.NewRow();
+ for (int j = 0; j < cellCount; j++)
+ {
+ ICell cell = row.GetCell(j);
+ dataRow[j] = cell?.ToString() ?? string.Empty;
+ }
+ dt.Rows.Add(dataRow);
+ }
+ }
+ return dt;
+ }
+
+ ///
+ /// 从博途的变量表中导如变量
+ ///
+ ///
+ ///
+ ///
+ public static List ImprotFromTiaVariableTable(string excelFilePath)
+ {
+ // Act
+ // _testFilePath = "C:\\Users\\Administrator\\Desktop\\浓度变量.xlsx";
+ var dataTable = ExcelHelper.ImportFromExcel(excelFilePath);
+ // 判断表头的名字
+ if (dataTable.Columns[0].ColumnName != "Name" || dataTable.Columns[2].ColumnName != "Data Type" &&
+ dataTable.Columns[3].ColumnName != "Logical Address")
+ throw new AggregateException(
+ "Excel表格式不正确:第一列的名字是:Name,第三列的名字是:Data Type,Data Type,第四列的名字是:Logical Address,请检查");
+
+
+ List variableDatas = new List();
+ foreach (DataRow dataRow in dataTable.Rows)
+ {
+ VariableData variableData = new VariableData();
+ variableData.Name=dataRow["Name"].ToString();
+ variableData.DataType=SiemensHelper.S7ToCSharpTypeString(dataRow["Data Type"].ToString()) ;
+ var exS7Addr=dataRow["Logical Address"].ToString();
+ if (exS7Addr.StartsWith("%"))
+ {
+ variableData.S7Address = exS7Addr.Substring(1);
+ }
+
+ variableData.NodeId = "";
+ variableData.ProtocolType = ProtocolType.S7;
+ variableData.SignalType = SignalType.OtherASignal;
+ variableDatas.Add(variableData);
+ }
+
+ return variableDatas;
+ }
+
+ ///
+ /// 从 Excel 文件导入数据到对象列表。
+ ///
+ /// 要转换的目标类型。
+ /// Excel 文件的路径。
+ /// 工作表的名称。
+ /// 包含导入数据的对象列表。
+ public static List ImportFromExcel(string filePath, string sheetName = "Sheet1") where T : class, new()
+ {
+ if (!File.Exists(filePath))
+ {
+ throw new FileNotFoundException("The specified file does not exist.", filePath);
+ }
+
+ var list = new List();
+ PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
+
+ using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ IWorkbook workbook = new XSSFWorkbook(fs);
+ ISheet sheet = workbook.GetSheet(sheetName) ?? workbook.GetSheetAt(0);
+
+ if (sheet == null)
+ {
+ throw new Exception($"Sheet with name '{sheetName}' not found.");
+ }
+
+ IRow headerRow = sheet.GetRow(0);
+ if (headerRow == null)
+ {
+ throw new Exception("Header row not found.");
+ }
+
+ // 创建列名到属性的映射
+ var columnMap = new Dictionary();
+ for (int i = 0; i < headerRow.LastCellNum; i++)
+ {
+ string columnName = headerRow.GetCell(i)?.ToString();
+ if (!string.IsNullOrEmpty(columnName))
+ {
+ var prop = properties.FirstOrDefault(p => p.Name.Equals(columnName, StringComparison.OrdinalIgnoreCase));
+ if (prop != null)
+ {
+ columnMap[i] = prop;
+ }
+ }
+ }
+
+ // 读取数据行
+ for (int i = 1; i <= sheet.LastRowNum; i++)
+ {
+ IRow row = sheet.GetRow(i);
+ if (row == null) continue;
+
+ var item = new T();
+ foreach (var map in columnMap)
+ {
+ ICell cell = row.GetCell(map.Key);
+ if (cell != null)
+ {
+ try
+ {
+ // 尝试进行类型转换
+ object value = Convert.ChangeType(cell.ToString(), map.Value.PropertyType);
+ map.Value.SetValue(item, value, null);
+ }
+ catch (Exception)
+ {
+ // 转换失败时可以记录日志或设置默认值
+ }
+ }
+ }
+ list.Add(item);
+ }
+ }
+ return list;
+ }
+ }
+}
diff --git a/Helper/SiemensHelper.cs b/Helper/SiemensHelper.cs
new file mode 100644
index 0000000..15a13ca
--- /dev/null
+++ b/Helper/SiemensHelper.cs
@@ -0,0 +1,54 @@
+namespace PMSWPF.Helper;
+
+///
+/// 西门子帮助类
+///
+public static class SiemensHelper
+{
+ ///
+ /// 将S7数据类型字符串转换为C#数据类型字符串
+ ///
+ /// S7数据类型字符串
+ /// 对应的C#数据类型字符串
+ public static string S7ToCSharpTypeString(string s7Type)
+ {
+ switch (s7Type.ToUpper())
+ {
+ case "BOOL":
+ return "bool";
+ case "BYTE":
+ return "byte";
+ case "WORD":
+ return "ushort";
+ case "DWORD":
+ return "uint";
+ case "INT":
+ return "short";
+ case "DINT":
+ return "int";
+ case "REAL":
+ return "float";
+ case "LREAL":
+ return "double";
+ case "CHAR":
+ return "char";
+ case "STRING":
+ return "string";
+ case "TIMER":
+ case "TIME":
+ return "TimeSpan";
+ case "COUNTER":
+ return "ushort";
+ case "DATE":
+ return "DateTime";
+ case "TIME_OF_DAY":
+ case "TOD":
+ return "DateTime";
+ case "DATE_AND_TIME":
+ case "DT":
+ return "DateTime";
+ default:
+ return "object";
+ }
+ }
+}
\ No newline at end of file
diff --git a/ViewModels/Dialogs/ImportExcelDialogViewModel.cs b/ViewModels/Dialogs/ImportExcelDialogViewModel.cs
new file mode 100644
index 0000000..0b11734
--- /dev/null
+++ b/ViewModels/Dialogs/ImportExcelDialogViewModel.cs
@@ -0,0 +1,33 @@
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using PMSWPF.Helper;
+using PMSWPF.Models;
+
+namespace PMSWPF.ViewModels.Dialogs;
+
+public partial class ImportExcelDialogViewModel : ObservableObject
+{
+ [ObservableProperty]
+ private string? _filePath;
+
+ [ObservableProperty]
+ private ObservableCollection _variableData = new();
+
+ partial void OnFilePathChanged(string? value)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ return;
+ }
+
+ try
+ {
+ var data = ExcelHelper.ImprotFromTiaVariableTable(value);
+ VariableData = new ObservableCollection(data);
+ }
+ catch (System.Exception ex)
+ {
+ // Handle exception
+ }
+ }
+}
\ No newline at end of file
diff --git a/Views/Dialogs/ImportExcelDialog.xaml b/Views/Dialogs/ImportExcelDialog.xaml
new file mode 100644
index 0000000..6f2ba28
--- /dev/null
+++ b/Views/Dialogs/ImportExcelDialog.xaml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Views/Dialogs/ImportExcelDialog.xaml.cs b/Views/Dialogs/ImportExcelDialog.xaml.cs
new file mode 100644
index 0000000..5eaf2e3
--- /dev/null
+++ b/Views/Dialogs/ImportExcelDialog.xaml.cs
@@ -0,0 +1,67 @@
+using Microsoft.Win32;
+using PMSWPF.ViewModels.Dialogs;
+using System.IO;
+using System.Windows;
+using iNKORE.UI.WPF.Modern.Controls;
+
+namespace PMSWPF.Views.Dialogs;
+
+public partial class ImportExcelDialog : ContentDialog
+{
+ public ImportExcelDialog(ImportExcelDialogViewModel viewModel)
+ {
+ InitializeComponent();
+ DataContext = viewModel;
+ }
+
+ private void Dialog_DragEnter(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ e.Effects = DragDropEffects.Copy;
+ }
+ else
+ {
+ e.Effects = DragDropEffects.None;
+ }
+ }
+
+ private void Dialog_Drop(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
+ if (files.Length > 0)
+ {
+ string extension = Path.GetExtension(files[0]);
+ if (extension.Equals(".xls", StringComparison.OrdinalIgnoreCase) ||
+ extension.Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
+ {
+ if (DataContext is ImportExcelDialogViewModel viewModel)
+ {
+ viewModel.FilePath = files[0];
+ }
+ }
+ else
+ {
+ // MessageBox.Show("Please drop a valid Excel file (.xls or .xlsx).", "Invalid File Type", MessageBoxButton.OK, MessageBoxImage.Error);
+ }
+ }
+ }
+ }
+
+ private void SelectFile_Click(object sender, RoutedEventArgs e)
+ {
+ var openFileDialog = new OpenFileDialog
+ {
+ Filter = "Excel Files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
+ };
+ if (openFileDialog.ShowDialog() == true)
+ {
+ if (DataContext is ImportExcelDialogViewModel viewModel)
+ {
+ viewModel.FilePath = openFileDialog.FileName;
+ }
+ }
+ }
+}
\ No newline at end of file