C#制作用于Wincc的配方程序



一、实现功能

在Wincc项目中,一般可以使用用户归档功能进行参数配方的制作。虽然Wincc所提供的功能可以满足大部分的需求,但是依然存在着参数复制不便、配方参数不便于分组存储、用户归档结构更新导致旧归档数据丢失等问题。因此制作该应用通过另一种方法实现配方的功能:1.实时反应PLC当前运行配方;2.读取和保存的配方文件可以分组。

二、实现步骤

1.引入库

using CCHMIRUNTIME;//Wincc通讯

using unvell.ReoGrid.DataFormat;//表格控件

using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;

其中ReoGrid可以提供近似于Excel表格的功能:
在这里插入图片描述

2.定义公用变量,主程序初始化

public class STEPItem
        {
            public string C1 { get; set; }
            public string C2 { get; set; }
            public string C3 { get; set; }
            public string C4 { get; set; }
            public string C5 { get; set; }
            public string C6 { get; set; }
        }
        public string PCindex;
        public int User = 0;
        private DispatcherTimer timer;

主程序如下:

public MainWindow()
        {
            InitializeComponent();
            ExcelInit(PC1reogrid);
            ExcelInit(PC2reogrid);//ReoGrid控件的外观初始化

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(6);
            timer.Tick += seedListView;
            //timer.Start();
            //runstop.IsChecked = true;

            //获取欲启动进程名
            string strProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
            //检查进程是否已经启动,已经启动则显示报错信息退出程序。
            if (System.Diagnostics.Process.GetProcessesByName(strProcessName).Length > 1)
            {
                MessageBox.Show("多个程序不能同时运行!", "警告");
                try
                {
                    System.Diagnostics.Process.GetCurrentProcess().Kill();
                }
                catch { }
                return;
            }

            if (!Directory.Exists("D:\\配方程序\\PC1")) { Directory.CreateDirectory("D:\\配方程序\\PC1"); }
            if (!Directory.Exists("D:\\配方程序\\PC2")) { Directory.CreateDirectory("D:\\配方程序\\PC2"); }//在系统中生成存放配方文件的文件夹
        }

通过按钮触发定时器启动停止,并增加进度条动画:

private void runstop_Click(object sender, RoutedEventArgs e)
        {
            if (runstop.IsChecked == false)
            {
                //PGbar.IsIndeterminate = false;
                timer.Stop();
                PGbar.Value = 0;
            }
            else
            {
                //PGbar.IsIndeterminate = true;
                timer.Start();
                DoubleAnimation animation = new DoubleAnimation(
                PGbar.Value = 0,                       // From
                PGbar.Value = 100,                  // To
                new Duration(TimeSpan.FromSeconds(6)))      // Duration    间隔是 10s
                {
                    AccelerationRatio = 0,       // 设置加速
                    DecelerationRatio = 0,       // 设置减速
                };
                PGbar.BeginAnimation(ProgressBar.ValueProperty, animation);
            }
                
        }

3.读取正在运行配方

通过使用CCHMIRUNTIME库读取正在运行的Wincc项目的变量。
代码如下:

        private void seedListView(object sender, EventArgs e)
        {
            //Define
            var data = new[]
            {
                new string[6],
                new string[6],
                new string[6],
                new string[6],
                new string[6],
            };
            //Read
            runingrepview.Items.Clear();
            Stopwatch ST = new Stopwatch();
            ST.Start();
            if (pc1.IsSelected)
            {
                PCindex = "PC1";
            }
            else
            {
                PCindex = "PC2";
            }
            int I;
            CCHMIRUNTIME.HMIRuntime HMIRT = new CCHMIRUNTIME.HMIRuntime();
            try
            {
                for (I = 1; I < 6; I++)
                {
                    data[I - 1][0] = I.ToString();
                    data[I - 1][1] = HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_A"].Read();.ToString()
                    data[I - 1][2] = HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_B"].Read().ToString();
                    data[I - 1][3] = HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_C"].Read().ToString();
                    data[I - 1][4] = HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_D"].Read().ToString();
                    data[I - 1][5] = HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_E"].Read().ToString();
                }
                runningrepname.Text = HMIRT.Tags[PCindex + "工艺参数_配方名"].Read();
                readtime.IsChecked = false;
            }
            catch (Exception)
            {
                timer.Stop();
                runstop.IsChecked = false;
                MessageBox.Show("读取失败,请检查WINCC是否运行");
                return;
            }
            //Add
            
            foreach (string[] version in data)
            {
                runingrepview.Items.Add(new STEPItem { C1 = version[0] , C2 = version[1] , C3 = version[2], C4 = version[3], C5 = version[4], C6 = version[5] });
            }
            ST.Stop();
            readtime.Content = "读取时间:" + ST.Elapsed.TotalMilliseconds.ToString()+"ms";
            ST.Reset();
            DoubleAnimation animation = new DoubleAnimation(
                PGbar.Value = 0,                       // From
                PGbar.Value = 100,                  // To
                new Duration(TimeSpan.FromSeconds(6)))      // Duration    间隔是6s的动画
            {
                AccelerationRatio = 0,       // 设置加速
                DecelerationRatio = 0,       // 设置减速
            };
            PGbar.BeginAnimation(ProgressBar.ValueProperty,animation);
        }//读取正在运行配方

4.将读取到的配方上传至表格

读取的配方先转存在Listview控件里,点击按钮再将控件里的配方变量转移到ReoGrid表格控件里。
代码如下:

private void LoadSTEP_Click(object sender, RoutedEventArgs e)
        {
            unvell.ReoGrid.ReoGridControl worksheet;
            if (pc1.IsSelected)
            {
                worksheet = PC1reogrid;
            }
            else
            {
                worksheet = PC2reogrid;
            }
            try
            {
                int I;
                for (I = 1; I < 6; I++)
                {
                    var version = runingrepview.Items[I - 1] as STEPItem;
                    worksheet.CurrentWorksheet[I + 1, 1] = version.C2;
                    worksheet.CurrentWorksheet[I + 1, 2] = version.C3;
                    worksheet.CurrentWorksheet[I + 1, 3] = version.C4;
                    worksheet.CurrentWorksheet[I + 1, 4] = version.C5;
                    worksheet.CurrentWorksheet[I + 1, 5] = version.C6;
                }
                worksheet.CurrentWorksheet["C1"] = runningrepname.Text;
            }
            catch (Exception)
            {
                MessageBox.Show("上传失败,请读取在线配方");
                return;
            }
        }

5.将表格里的配方写入Wincc

代码如下:

private void WriteSTEP_Click(object sender, RoutedEventArgs e)
        {
            unvell.ReoGrid.ReoGridControl worksheet;
            if (pc1.IsSelected)
            {
                worksheet = PC1reogrid;
            }
            else
            {
                worksheet = PC2reogrid;
            }
            worksheet.CurrentWorksheet.EndEdit(unvell.ReoGrid.EndEditReason.NormalFinish);//先取消选中单元格
            writeAS(worksheet);
        }
        
        private void writeAS(unvell.ReoGrid.ReoGridControl Worksheet)
        {
            int I;
            CCHMIRUNTIME.HMIRuntime HMIRT = new CCHMIRUNTIME.HMIRuntime();
            Stopwatch ST = new Stopwatch();
            ST.Start();
            if (pc1.IsSelected)
            {
                PCindex = "PC1";
            }
            else
            {
                PCindex = "PC2";
            }
            try
            {
                for (I = 1; I < 6; I++)
                {
                    HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_A"].Write(Worksheet.CurrentWorksheet[I + 1, 1]);
                    HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_B"].Write(Worksheet.CurrentWorksheet[I + 1, 2]);
                    HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_C"].Write(Worksheet.CurrentWorksheet[I + 1, 3]);
                    HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_D"].Write(Worksheet.CurrentWorksheet[I + 1, 4]);
                    HMIRT.Tags[PCindex + "工艺参数设定[" + "" + I + "" + "]_E"].Write(Worksheet.CurrentWorksheet[I + 1, 5]);
                }
                HMIRT.Tags[PCindex + "工艺参数_配方名"].Write(Worksheet.CurrentWorksheet["C1"]);
            }
            catch (Exception)
            {
                MessageBox.Show("写入失败");
                return;
            }
            ST.Stop();
            writetime.Content = "写入时间:" + ST.Elapsed.TotalMilliseconds.ToString()+"ms";
            ST.Reset();
        }//写入配方

6.保存编辑好的配方文件

文件的保存和读取加密参考了汐泽学园的方法,移步https://blog.csdn.net/yutiedun/article/details/105547508

        private void savefilebutton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog();
            saveFileDialog.Filter = "配方(*.rep)|*.rep";
            unvell.ReoGrid.ReoGridControl worksheet;
            if (pc1.IsSelected)
            {
                saveFileDialog.InitialDirectory = "D:\\配方程序\\PC1";
                worksheet = PC1reogrid;
            }
            else
            {
                saveFileDialog.InitialDirectory = "D:\\配方程序\\PC2";
                worksheet = PC2reogrid;
            }
            worksheet.CurrentWorksheet.EndEdit(unvell.ReoGrid.EndEditReason.NormalFinish);//先取消选中单元格
            if (worksheet.CurrentWorksheet["C1"] != null)
            {
                saveFileDialog.FileName = worksheet.CurrentWorksheet["C1"].ToString();

                if (saveFileDialog.ShowDialog() == true)
                {
                    String filePath = saveFileDialog.FileName;
                    try
                    {
                        FileStream fs = new FileStream(filePath, FileMode.Create);
                        StreamWriter sw = new StreamWriter(fs);
                        int I, Y;
                        for (I = 0; I < 5; I++)
                        {
                            for (Y = 0; Y < 4; Y++)
                            {
                                sw.Write(AuthcodeHelper.Encode(worksheet.CurrentWorksheet.GetCellText(I + 2, Y + 1)) + " ");
                            }
                            sw.WriteLine();
                        }
                        sw.Write(worksheet.CurrentWorksheet["C1"]);
                        //清空缓冲区
                        sw.Flush();
                        //关闭流
                        sw.Close();
                        fs.Close();
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("文件保存失败");
                        return;
                    }
                }
            }
            else
            {
                MessageBox.Show("配方名不能为空");
            }
        }

7.读取保存的配方文件

private void openfilebutton_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            //过滤文件类型
            openFileDialog.Filter = "配方(*.rep)|*.rep";
            //单选
            openFileDialog.Multiselect = false;
            unvell.ReoGrid.ReoGridControl worksheet;
            if (pc1.IsSelected)
            {
                openFileDialog.InitialDirectory = "D:\\配方程序\\PC1";
                worksheet = PC1reogrid;
            }
            else
            {
                openFileDialog.InitialDirectory = "D:\\配方程序\\PC2";
                worksheet = PC2reogrid;
            }
            if (log.Password == "123456")
            {
                if (openFileDialog.ShowDialog() == true)
                {
                    String filePath = openFileDialog.FileName;
                    using (FileStream fs = new FileStream(filePath, FileMode.Open))
                    {
                        StreamReader rd = new StreamReader(fs);//读取文件中的数据
                        try
                        {
                            for (int I = 0; I < 5; I++)  //读入数据并赋予数组
                            {
                                string line = rd.ReadLine();
                                string[] data = line.Split(' ');
                                for (int Y = 0; Y < 4; Y++)
                                {
                                    worksheet.CurrentWorksheet[I + 2, Y + 1] = AuthcodeHelper.Decode(data[Y]);
                                }
                            }
                            worksheet.CurrentWorksheet["C1"] = rd.ReadLine();
                        }
                        catch (Exception)
                        {
                            MessageBox.Show("文件读取失败");
                            return;
                        }
                        rd.Close();
                        fs.Close();
                    }
                }
            }
        }

8.ReoGrid表格控件的外观初始化

private void ExcelInit(unvell.ReoGrid.ReoGridControl Worksheet)
        {
            var worksheet = Worksheet.CurrentWorksheet;
            worksheet.Rows = 7;
            worksheet.Columns = 6;
            worksheet.DisableSettings(unvell.ReoGrid.WorksheetSettings.Edit_DragSelectionToMoveCells);
            worksheet.DisableSettings(unvell.ReoGrid.WorksheetSettings.View_ShowColumnHeader);
            worksheet.DisableSettings(unvell.ReoGrid.WorksheetSettings.View_ShowRowHeader);//工作表初始化 行 列

            worksheet.MergeRange("A1:B1");
            worksheet.MergeRange("C1:E1");
            worksheet.Ranges["A1:E1"].Style.TextColor = unvell.ReoGrid.Graphics.SolidColor.Blue;//合并单元格

            worksheet["A1"] = "配方名称";
            worksheet["A2:F2"] = new object[] { "NO", "A", "B", "C", "D", "E" };
            worksheet.Ranges["A2:F2"].IsReadonly = true;//设置只读
            worksheet["A3:A7"] = new object[] { 1, 2, 3, 4, 5};
            worksheet.Ranges["A3:A7"].Style.TextColor = unvell.ReoGrid.Graphics.SolidColor.Black;
            worksheet.Ranges["A2:F2"].IsReadonly = true;//设置只读

            worksheet.Ranges["A1:F7"].Style.HorizontalAlign = unvell.ReoGrid.ReoGridHorAlign.Center;
            worksheet.Ranges["A1:F1"].Style.BackColor = unvell.ReoGrid.Graphics.SolidColor.LightSteelBlue;
            worksheet.Ranges["A2:F2"].Style.BackColor = unvell.ReoGrid.Graphics.SolidColor.LightSkyBlue;
            worksheet.Ranges["A2:F2"].Style.TextColor = unvell.ReoGrid.Graphics.SolidColor.Black;
            worksheet.Ranges["D3:F7"].Style.TextColor = unvell.ReoGrid.Graphics.SolidColor.Black;
            
            worksheet.SetRangeBorders("A1:F7", unvell.ReoGrid.BorderPositions.InsideAll, new unvell.ReoGrid.RangeBorderStyle { Color = unvell.ReoGrid.Graphics.SolidColor.White, Style = unvell.ReoGrid.BorderLineStyle.Dashed });//网格线设置
            worksheet.SetColumnsWidth(0, 12, 80);//列宽度设置
        }

9.程序画面布局

程序的布局如下:
在这里插入图片描述

代码如下:

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition ></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition ></RowDefinition>
        </Grid.RowDefinitions>
        <ProgressBar x:Name="PGbar" HorizontalAlignment="Left" Height="14" Margin="570,6,0,0" VerticalAlignment="Top" Width="150" Foreground="#FF41A800"/>
        <Grid Grid.Row="0" VerticalAlignment="Stretch" >
            <TabControl x:Name="PCcontrol" Margin="4,27,4,1">
                <TabItem x:Name="pc1" Header="PC1" Margin="-2.2,0,-1.6,-0.2" RenderTransformOrigin="0.5,0.505">
                    <Grid Background="#FFE5E5E5">
                        <ReoGrid:ReoGridControl x:Name="PC1reogrid" SheetTabVisible="False" SnapsToDevicePixels="True" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabWidth="0" OverridesDefaultStyle="True"/>
                    </Grid>
                </TabItem>
                <TabItem x:Name="pc2" Header="PC2" Margin="-2.2,0,-1.6,-0.2" RenderTransformOrigin="0.5,0.505">
                    <Grid Background="#FFE5E5E5">
                        <ReoGrid:ReoGridControl x:Name="PC2reogrid" SheetTabVisible="False" SnapsToDevicePixels="True" SheetTabNewButtonVisible="False" ShowScrollEndSpacing="False" SheetTabWidth="0" OverridesDefaultStyle="True"/>
                    </Grid>
                </TabItem>
            </TabControl>
        </Grid>
        <GridSplitter Grid.Row="1" Height="5" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
        <Grid Grid.Row="2" VerticalAlignment="Stretch" >
            <Expander x:Name="runingrep" Header="运行配方名称" Margin="3,0,2.6,2" Cursor="" IsExpanded="True" ForceCursor="True">
                <Grid Background="#FFE5E5E5" Margin="0">
                    <ListView x:Name="runingrepview" Margin="0,2,0,0">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="配方监控" Width="80" DisplayMemberBinding="{Binding C1}"/>
                                <GridViewColumn Header="A" Width="80" DisplayMemberBinding="{Binding C2}"/>
                                <GridViewColumn Header="B" Width="80" DisplayMemberBinding="{Binding C3}"/>
                                <GridViewColumn Header="C" Width="80" DisplayMemberBinding="{Binding C4}"/>
                                <GridViewColumn Header="D" Width="80" DisplayMemberBinding="{Binding C5}"/>
                                <GridViewColumn Header="E" Width="80" DisplayMemberBinding="{Binding C6}"/>
                            </GridView>
                        </ListView.View>
                    </ListView>
                </Grid>
            </Expander>
            <TextBox x:Name="runningrepname" HorizontalAlignment="Left" Height="20" Margin="135,2,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="82" Background="{x:Null}" SelectionBrush="{x:Null}" TextAlignment="Center" FontWeight="Bold" BorderBrush="{x:Null}" IsEnabled="False"/>
        </Grid>

        <PasswordBox x:Name="log" HorizontalAlignment="Left" Margin="4,4,0,0" VerticalAlignment="Top" Width="72" Height="18"/>
        <Button x:Name="Load" Content="登录" HorizontalAlignment="Left" Height="18" Margin="81,4,0,0" VerticalAlignment="Top" Width="49" Click="Load_Click"/>
        <Button x:Name="LoadSTEP" Content="上传配方" HorizontalAlignment="Left" Height="18" Margin="135,4,0,0" VerticalAlignment="Top" Width="60" Click="LoadSTEP_Click" IsEnabled="False"/>
        <Button x:Name="WriteSTEP" Content="下载配方" HorizontalAlignment="Left" Height="18" Margin="200,4,0,0" VerticalAlignment="Top" Width="60" Click="WriteSTEP_Click" IsEnabled="False"/>
        <Button x:Name="openfilebutton" Content="打开配方文件" HorizontalAlignment="Left" Height="18" Margin="265,4,0,0" VerticalAlignment="Top" Width="100" Click="openfilebutton_Click" IsEnabled="False"/>
        <Button x:Name="savefilebutton" Content="保存配方文件" HorizontalAlignment="Left" Height="18" Margin="370,4,0,0" VerticalAlignment="Top" Width="100" Click="savefilebutton_Click" IsEnabled="False"/>
        <CheckBox x:Name="runstop" Content="读取在线配方" HorizontalAlignment="Left" Height="17" Margin="475,6,0,0" VerticalAlignment="Top" Click="runstop_Click" IsEnabled="False"/>
        <RadioButton x:Name="readtime" Content="" HorizontalAlignment="Left" Height="18" Margin="570,6,0,0" VerticalAlignment="Top" Background="{x:Null}"/>
        <RadioButton x:Name="writetime" Content="" HorizontalAlignment="Left" Height="18" Margin="720,6,5,0" VerticalAlignment="Top"/>
    </Grid>

运行测试

在Wincc的变量管理中新增我们需要的内部变量。(跟PLC通讯时可以直接使用读取的AS符号变量)
在这里插入图片描述

点击激活Wincc项目,再运行配方程序,点击“读取在线配方”
在这里插入图片描述

可以看到Wincc中的变量已经被读取上传了

在这里插入图片描述

再点击“上传配方”按钮,看到当前运行的配方被上传至表格中,可以开始对配方进行编辑了。

在这里插入图片描述

点击“下载配方”按钮,可以看到修改后的配方已经上传到Wincc了。
在这里插入图片描述

在这里插入图片描述

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: c是一种编程语言,常被用于开发操作系统、应用程序、游戏等应用。它是一种结构化编程语言,具有高效、简洁、灵活的特点。c语言是一门底层语言,需要程序员手动管理内存,因此编写的程序更有效率。目前,c语言已成为了计算机领域中最为重要的编程语言之一。 ### 回答2: c 是英文字母表中的第三个字母,也是拉丁字母表中的第三个字母。c 在英语中可以表示不同的意思和用法。 首先,c 在数学中可以表示圆周率π或复数中的实部。在物理学中,c 可以代表光速(光在真空中传播的速度)。 此外,在计算机科学和编程中,c 常常用于表示一种编程语言,即 C 语言。C 语言是一种通用的高级编程语言,用于开发软件应用和系统。它是一种强大而灵活的编程语言,具有高效的执行和底层访问系统资源的能力。C 语言广泛应用于操作系统、嵌入式系统、网络和图形等领域。 同时,c 还可以用于表示摄氏度(Celsius)的单位符号。摄氏度是温度计量中常用的一种单位,以摄氏温标为依据,其中水在 0°C 时沸腾,100°C 时冰点。与摄氏度相对应的另一种温度单位是华氏度(Fahrenheit),两者之间的转换可以通过公式进行计算。 总而言之,c 是一个简单而常用的字母,在不同的领域和语言中有着不同的含义和用途。无论是数学、物理、计算机科学还是其他科学领域,c 都有着重要的地位和作用。 ### 回答3: c是英文字母表中的第三个字母,也是拉丁字母表中的一个字母。在音标中,c代表辅音音素/k/的发音。在英语单词中,c通常与其他字母一起组成不同的发音和单词含义。例如,与字母h相结合,形成"ch"组合,发音为/tʃ/,如"chair"(椅子)、"cheese"(奶酪)等。与字母k相比,c的发音更轻,如"cat"(猫)、"car"(车)等。c还可以与字母e、i、y等元音字母结合,发音为/s/,如"cent"(分)、"city"(城市)等。 此外,c还是化学元素周期表中的一个符号,代表针尖碳(Carbon)的元素符号,是一种常见的化学元素,其原子序数为6,原子量为12.01。碳是地球上最常见的元素之一,它存在于各种有机和无机物质中,是生命的基础。许多自然界中的化合物,如葡萄糖、脂肪等都含有碳元素。碳还是生产人造材料、石墨、石碳化合物和能源的重要原料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值