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 @@ + + + + + + + + + + + + + + + + +