前言
关于基本的读写可以查看该链接:https://www.cnblogs.com/LynnXue/p/11162452.html
但实际项目中上位机后期经常需要增加读取的PLC内部变量,每次增加在程序内单独写一份读写就很麻烦。所以下面采用读取CSV文件,根据表格内容来改变所需要读取的变量。
一,读取CSV文件返回DataTable数据
代码如下
public class Csv
{
public bool readCSV(string filePath, out DataTable dt)//从csv读取数据返回table
{
dt = new DataTable();
try
{
System.Text.Encoding encoding = Encoding.ASCII;//GetType(filePath); //
// DataTable dt = new DataTable();
System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open,
System.IO.FileAccess.Read);
System.IO.StreamReader sr = new System.IO.StreamReader(fs, Encoding.GetEncoding("gb2312"));
//记录每次读取的一行记录
string strLine = "";
//记录每行记录中的各字段内容
string[] aryLine = null;
string[] tableHead = null;
//标示列数
int columnCount = 0;
//标示是否是读取的第一行
bool IsFirst = true;
// strLine = sr.ReadLine();
//逐行读取CSV中的数据
while ((strLine = sr.ReadLine()) != null)
{
if (IsFirst == true)
{
tableHead = strLine.Split(',');
IsFirst = false;
columnCount = tableHead.Length;
//创建列
for (int i = 0; i < columnCount; i++)
{
DataColumn dc = new DataColumn(tableHead[i]);
dt.Columns.Add(dc);
}
}
else
{
aryLine = strLine.Split(',');
DataRow dr = dt.NewRow();
for (int j = 0; j < columnCount; j++)
{
dr[j] = aryLine[j];
}
dt.Rows.Add(dr);
}
}
if (aryLine != null && aryLine.Length > 0)
{
dt.DefaultView.Sort = tableHead[0] + " " + "asc";
}
sr.Close();
fs.Close();
return true;
}
catch (Exception)
{
return false;
}
}
public bool dt_to_dic(DataTable dt, out Dictionary<string, string> inPut_dic, out Dictionary<string, string> outPut_dic)
{
inPut_dic = new Dictionary<string, string>();
outPut_dic = new Dictionary<string, string>();
foreach (DataRow item in dt.Rows)
{
inPut_dic.Add(item["PLC_INPUT"].ToString(), item["LINK_IN"].ToString());
outPut_dic.Add(item["PLC_OUTPUT"].ToString(), item["LINK_OUT"].ToString());
}
return true;
}
}
二,给按钮添加所需的属性:
由于需要读取倍福变量,所以我增加了字符串Link属性用来保存变量地址,增加State属性显示布尔量。
public class BButton:Button
{
public string Link { get; set; }
public bool State { get; set; }
}
三,界面:
由于读取变量可能较多,所以界面上增加翻页功能。

四,读取CSV,并动态生成按钮绑定事件
代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test
{
public partial class CGS_IO : Form
{
DataTable dt;
Csv ReadCsv;
BButton[] LinkButton;
BButton[] OutPutButton;
int InPut_Page;
int OutPut_Page;
int _len = 0;
int _InPutLen = 0;
int _OutPutLen = 0;
Dictionary<string, string> in_dic;
Dictionary<string, string> out_dic;
public CGS_IO()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void LinkButton_Click(object sender, EventArgs e)
{
BButton linkbut = (BButton)sender;
Beckhoff_PLC.WriteVariable(linkbut.Link, !Beckhoff_PLC.ReadBool(linkbut.Link));
}
private void CGS_IO_Load(object sender, EventArgs e)
{
ReadCsv = new Csv();
dt = new DataTable();
in_dic = new Dictionary<string, string>();
out_dic = new Dictionary<string, string>();
ReadCsv.readCSV(@"E:\IOList.csv", out dt);
ReadCsv.dt_to_dic(dt, out in_dic, out out_dic);
DataRow dr = dt.NewRow();
LinkButton = new BButton[100];
OutPutButton = new BButton[100];
_len = 0;
foreach (KeyValuePair<string, string> kvp in in_dic)
{
LinkButton[_len] = new BButton();
LinkButton[_len].Text = kvp.Key;
LinkButton[_len].Link = kvp.Value;
LinkButton[_len].Click += new EventHandler(LinkButton_Click);
LinkButton[_len].Width = 200;
LinkButton[_len].Height = 48;
LinkButton[_len].Left = 35;
LinkButton[_len].Top = 50 * (_len + 1);
_InPutLen = _len;
_len++;
}
_len = 0;
foreach (KeyValuePair<string, string> kvp in out_dic)
{
OutPutButton[_len] = new BButton();
OutPutButton[_len].Text = kvp.Key;
OutPutButton[_len].Link = kvp.Value;
OutPutButton[_len].Width = 200;
OutPutButton[_len].Height = 48;
OutPutButton[_len].Left = 338;
OutPutButton[_len].Top = 50 * (_len + 1);
_OutPutLen = _len;
_len++;
}
for (int i = 0; i < 11; i++)
{
if (i <= _OutPutLen)
{
OutPutButton[i].Top = 50 * (i + 1);
this.Controls.Add(OutPutButton[i]);
}
}
for (int i = 0; i < 11; i++)
{
if (i <= _InPutLen)
{
LinkButton[i].Top = 50 * (i + 1);
this.Controls.Add(LinkButton[i]);
}
}
Thread thread1 = new Thread(new ThreadStart(ReadPLC));
thread1.Start();
}
void ReadPLC()
{
for (int i = 0; i < 11; i++)
{
if (i < _OutPutLen)
{
OutPutButton[11 * OutPut_Page + i].Top = 50 * (i + 1);
this.Controls.Add(OutPutButton[11 * OutPut_Page + i]);
}
}
while (true)
{
for (int i = 0; i <= _OutPutLen; i++)
{
OutPutButton[i].State = Beckhoff_PLC.ReadBool(OutPutButton[i].Link);
if (OutPutButton[i].State)
{
OutPutButton[i].BackColor = Color.Aqua;
}
else
{
OutPutButton[i].BackColor = Color.Silver;
}
}
for (int i = 0; i <= _InPutLen; i++)
{
LinkButton[i].State = Beckhoff_PLC.ReadBool(LinkButton[i].Link);
if (LinkButton[i].State)
{
LinkButton[i].BackColor = Color.Aqua;
}
else
{
LinkButton[i].BackColor = Color.FromArgb(224, 224, 224);
}
}
}
}
private void UpBut_Click(object sender, EventArgs e)
{
if (!(InPut_Page == 0))
{
for (int i = 0; i < 11; i++)
{
this.Controls.Remove(LinkButton[11 * InPut_Page + i]);
}
InPut_Page--;
for (int i = 0; i < 11; i++)
{
LinkButton[11 * InPut_Page + i].Top = 50 * (i + 1);
this.Controls.Add(LinkButton[11 * InPut_Page + i]);
}
}
}
private void Down_but_Click(object sender, EventArgs e)
{
if ((InPut_Page + 1) * 11 < _InPutLen)
{
for (int i = 0; i < 11; i++)
{
this.Controls.Remove(LinkButton[11 * InPut_Page + i]);
}
InPut_Page++;
for (int i = 0; i < 11; i++)
{
if (11 * InPut_Page + i < _InPutLen)
{
LinkButton[11 * InPut_Page + i].Top = 50 * (i + 1);
this.Controls.Add(LinkButton[11 * InPut_Page + i]);
}
}
}
}
private void OutPut_Up_Click(object sender, EventArgs e)
{
if (!(OutPut_Page == 0))
{
for (int i = 0; i < 11; i++)
{
this.Controls.Remove(OutPutButton[11 * OutPut_Page + i]);
}
OutPut_Page--;
for (int i = 0; i < 11; i++)
{
OutPutButton[11 * OutPut_Page + i].Top = 50 * (i + 1);
this.Controls.Add(OutPutButton[11 * OutPut_Page + i]);
}
}
}
private void OutPut_Down_Click(object sender, EventArgs e)
{
if ((OutPut_Page + 1) * 11 <= _OutPutLen)
{
for (int i = 0; i < 11; i++)
{
this.Controls.Remove(OutPutButton[11 * OutPut_Page + i]);
}
OutPut_Page++;
for (int i = 0; i < 11; i++)
{
if (11 * OutPut_Page + i <= _OutPutLen)
{
OutPutButton[11 * OutPut_Page + i].Top = 50 * (i + 1);
this.Controls.Add(OutPutButton[11 * OutPut_Page + i]);
}
}
}
}
}
}
五,CSV文件准备

第一列为按钮名称,第二列为变量名称。后续需要增加变量,只需在表格内增加相应名称即可。
五,效果演示
C#读取倍福Beckhoff变量演示
以上为我的写法,目前仍在学习。有不对的地方,欢迎各位大神指导。