和PLC對配置的繁瑣工序

孤沉發表於2024-09-13

上位機開發最煩和PLC對軸的位置,點的位置,一大堆的手寫工序,資料不是放在Excel表,就是放在txt或者ini
圖1.
image
圖2
image
這次的需求
我需要手動將圖1的資料寫到圖2
太麻煩
所以我準備寫一個工具實現它
首先,我打算生成圖2,需要使用到XML反序列化,讀取圖1,我使用MiniExcel
所以我先準備三個類

// 用於標記根元素
[XmlRoot("AxisPositionGroupItem")]
public class AxisPositionGroupItem
{
    // 使用XmlAttributeAttribute標記屬性為XML屬性
    [XmlAttribute("GroupName")]
    public string GroupName { get; set; }

    // 使用XmlElementAttribute標記屬性為XML元素
    [XmlElement("AxisPositionItem")]
    public AxisPositionItem[] AxisPositionItems { get; set; }
}

// 用於標記AxisPositionItem元素
public class AxisPositionItem
{
    [XmlAttribute("Label")]
    public string Label { get; set; }

    [XmlAttribute("AxisName")]
    public string AxisName { get; set; }

    [XmlAttribute("AxisId")]
    public string AxisId { get; set; } = "45";

    [XmlAttribute("AxisType")]
    public string AxisType { get; set; } = "PLC";

    [XmlAttribute("GroupName")]
    public string GroupName { get; set; }

    [XmlAttribute("Value")]
    public string Value { get; set; } = "68";

    [XmlAttribute("Speed")]
    public string Speed { get; set; } = "20";

    [XmlAttribute("SpeedDescription")]
    public string SpeedDescription { get; set; }=string.Empty;

    [XmlAttribute("PosIndex")]
    public int PosIndex { get; set; }
}
 public class AxisConfig
 {
     [ExcelColumnName("軸號")]
     public string AxisNumber { get; set; }

     [ExcelColumnName("軸名稱")]
     public string AxisName { get; set; }

     [ExcelColumnName("功能名稱")]
     public string FunctionName { get; set; }

     [ExcelColumnName("位置")]
     public string Position { get; set; }
 }

然後先獲取Excel表格的資料

 public class MiNiHelper
 {
     public static List<AxisConfig> ReadExcel()
     {
         var config = new OpenXmlConfiguration()
         {
             FillMergedCells = true
         };
         string path = "xxxxxx";
         var lists=MiniExcel.Query<AxisConfig>(path,"MotionParaInfo", configuration: config).ToList();
         var newList=lists.Where(x => x.Position != null).Where(y => y.AxisName != null).Where(z => z.FunctionName != null).ToList();
         return newList;
     }
 }

注意Where不能寫在var lists=MiniExcel.Query(path,"MotionParaInfo", configuration: config).ToList();內部,因為MiniExcel會告訴你AxisConfig沒有例項化,所有分開寫
接下來,我們準備前端介面,看看效果

 <Grid>
     <ListView Margin="20" ItemsSource="{Binding DataList}">
         <ListView.View>
             <GridView>
                 <GridViewColumn
                     Width="80"
                     DisplayMemberBinding="{Binding AxisNumber}"
                     Header="軸號" />
                 <GridViewColumn
                     Width="180"
                     DisplayMemberBinding="{Binding AxisName}"
                     Header="軸名稱" />
                 <GridViewColumn
                     Width="280"
                     DisplayMemberBinding="{Binding FunctionName}"
                     Header="功能名稱" />
                 <GridViewColumn
                     Width="280"
                     DisplayMemberBinding="{Binding Position}"
                     Header="位置" />
             </GridView>
         </ListView.View>
     </ListView>
 </Grid>

ViewModel程式碼

  private ObservableCollection<AxisConfig> _dataList;

  public ObservableCollection<AxisConfig> DataList
  {
      get { return _dataList; }
      set { SetProperty(ref _dataList, value); }
  }
 DataList= MiNiHelper.ReadExcel().ToObservableCollection();

image
可以看到介面已經有了資料,說明我們成功了第一步。
現在我們測試一下,本地的XML生成

 public class XMLHelper
 {
     public static void WriteMemory()
     {
         XmlSerializer serializer = new XmlSerializer(typeof(AxisPositionGroupItem));
         using (StringWriter writer = new StringWriter())
         {
             AxisPositionGroupItem groupItem = new AxisPositionGroupItem
             {
                 GroupName = "UnLoad",
                 AxisPositionItems = new AxisPositionItem[]
                 {
                     new AxisPositionItem
                     {
                         Label = "待機(安全)位置",
                         AxisName = "ULD_TurnZ",
                         AxisType = "PLC",
                         GroupName = "ULD_TurnZ",
                         SpeedDescription = "",
                         PosIndex = "1"
                     },
                     // 其他 AxisPositionItem 物件...
                 }
             };

             serializer.Serialize(writer, groupItem);
             string xml = writer.ToString();
         }
     }
}

然後將資料傳遞過去,修改WriteLocal

/// <summary>
/// 使用MiniExcel讀取的資料
/// </summary>
/// <param name="axisConfigs"></param>
public static void WriteLocal(List<AxisConfig> axisConfigs)
{
    XmlSerializer serializer = new XmlSerializer(typeof(AxisPositionGroupItem));

    // 建立 AxisPositionGroupItem 物件
    AxisPositionGroupItem groupItem = new AxisPositionGroupItem
    {
        GroupName = "UnLoad",
        AxisPositionItems = axisConfigs.Select(config => new AxisPositionItem
        {
            Label = config.FunctionName,
            AxisName = config.AxisName,
            GroupName = config.AxisName, // 假設 AxisName 和 GroupName 保持一致
            AxisId = "45", // 如果軸號是固定的,可以直接賦值
            AxisType = "PLC",
            Value = "68", // 如果 Value 是固定的,可以直接賦值
            Speed = "20", // 如果 Speed 是固定的,可以直接賦值
            SpeedDescription = string.Empty, // 如果 SpeedDescription 沒有值,可以直接賦值
            PosIndex = ExtractPosIndex(config.Position) // 假設軸號是整數,並且對應 PosIndex
        }).ToArray()
    };

    // 使用 StringWriter 來序列化物件
    using (StringWriter writer = new StringWriter())
    {
        serializer.Serialize(writer, groupItem);
        string xml = writer.ToString();

        // 指定要儲存的檔案路徑
        string filePath = @"E:\CSharp Project\自定義習題\反序列化XML\file.xml";

        // 使用 StreamWriter 將字串寫入檔案
        using (StreamWriter fileWriter = new StreamWriter(filePath))
        {
            fileWriter.Write(xml);
        }

        Console.WriteLine("XML has been saved to " + filePath);
    }
}
public static string ExtractPosIndex(string axisPosition)
{
    // 使用LINQ刪除中括號並獲取最後一個字元
    string lastString = new string(axisPosition.Where(c => c != '[' && c != ']').ToArray()).LastOrDefault().ToString();

 //   string last = axisPosition.Replace("[", "").Replace("]", "");
    // 獲取最後一個字元
   // string lastString = last[last.Length - 1].ToString();
    return lastString;
    throw new ArgumentException("無法從軸位置字串中提取PosIndex。");
}

接下來修改ViewModel程式碼

 public MainViewModel()
 {
    
     Init();
 }

 private void Init()
 {
     DataList= MiNiHelper.ReadExcel().ToObservableCollection();
     var axisConfigs=MiNiHelper.ReadExcel();
     XMLHelper.WriteLocal(axisConfigs);
 }

完成

相關文章