C# 服务调用RFC函数获取物料信息,并输出生成Excel文件

这个例子是C#服务调用RFC函数,获取物料的信息,并生成Excel文件

上接文章:C#服务

文章目录

  • 创建函数
  • 创建结构
  • 编写源代码
  • 创建批处理文件
  • 运行结果-成功
  • 部署服务器
  • C#代码
  • 配置文件
  • 注意!!

创建函数

在这里插入图片描述

创建结构

在这里插入图片描述

编写源代码

在这里插入图片描述

创建批处理文件

在这里插入图片描述
在这里插入图片描述

echo %~dp0
%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\installUtil.exe %~dp0WindowsService1_SAP_RFC.exe
Net Start C#ServerTest
sc config C#ServerTest=auto
pause

在这里插入图片描述

%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /u %~dp0WindowsService1_SAP_RFC.exe
pause

运行结果-成功

在这里插入图片描述

部署服务器

在这里插入图片描述

C#代码

using SAP.Middleware.Connector;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace WindowsService1_SAP_RFC
{
    //创建人:LiuHongyu
    //创建日期:2024年12月20日
    //描述:测试C#服务的创建以及和SAP进行通讯,并生成Excel文档

    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        //文件路径
        private string filePath = ConfigurationManager.AppSettings["FilePath"];

        //Excel文件路径
        private string excelFilePath = ConfigurationManager.AppSettings["ExcelFilePath"];

        //Excel模板文件路径
        private string excelFileTemplatePath = ConfigurationManager.AppSettings["ExcelFileTemplatePath"];

        private int n = 1;

        //计时器
        Timer timer;

        //rfc的地址
        private RfcDestination _rfcDestination;

        //每天定时器开关
        private bool dayScheduleSwitch;
        //每天定时执行的时间
        private string dayScheduleTime;
        //每月定时器开关
        private bool monthScheduleSwitch;

        //服务启动时调用
        protected override void OnStart(string[] args)
        {
            WriteLog(filePath, "启动服务------");
            InitTimer();
        }

        private void InitTimer()
        {
            try
            {
                WriteLog(filePath, "开始计数------");
                timer = new Timer(60000);//1分钟

                //时间间隔到了之后,执行的操作为Execute
                timer.Elapsed += Execute;

                //是否重复执行
                timer.AutoReset = true;  //如果不设置就是只会执行一次

                //是否执行Elapsed中的事件
                timer.Enabled = true;
            }
            catch (Exception ex)
            {
                WriteLog(filePath, "计时器错误: " + ex.Message);
                throw;
            }
        }

        //执行的操作
        private void Execute(object sender, ElapsedEventArgs e)
        {
            //注册SAP客户端
            this.RegisterDestination();

            //获取当前的每日定时开关状态
            dayScheduleSwitch = Convert.ToBoolean(ConfigurationManager.AppSettings["DayScheduleSwitch"]);
            
            //获取每日定时执行的时间
            dayScheduleTime = ConfigurationManager.AppSettings["DayScheduleTime"];

            //获取当时的每月定时开关状态
            monthScheduleSwitch = Convert.ToBoolean(ConfigurationManager.AppSettings["MonthScheduleSwitch"]);
            
            //如果每日定时开关打开,并且当时是设置的时间
            if (dayScheduleSwitch && DateTime.Now.ToString("t") == dayScheduleTime)
            {
                timer.Stop();
                //获取SAP数据
                this.InvokeRFCFunctionGetJobList();
                WriteLog(filePath, "第 " + n + " 次数据写入完毕------");
                n++;
                timer.Start();
            }
            else if (monthScheduleSwitch) //每月定时开关是打开状态
            {
                DateTime dt = DateTime.Now;
                int year = dt.Date.Year;    //获取当前的年
                int month = dt.Date.Month;  //获取当前的月
                int dayCount = DateTime.DaysInMonth(year, month); //返回这个当前年当前月的天数

                var endDayOfMonth = new DateTime(year, month, dayCount, 0, 0, 0);  //最后一天
                if (DateTime.Now.ToString("g") == endDayOfMonth.ToString("g"))//g:常规(短日期和短时间)
                {
                    timer.Stop();
                    //获取SAP数据
                    this.InvokeRFCFunctionGetJobList();
                    WriteLog(filePath, "第 " + n + " 次数据写入完毕------");
                    n++;
                    timer.Start();
                }
            }
            
            //DateTime dt = DateTime.Now;
            //int year = dt.Date.Year;    //获取当前的年
            //int month = dt.Date.Month;  //获取当前的月
            //int dayCount = DateTime.DaysInMonth(year, month); //返回这个当前年当前月的天数

            //var endDayOfMonth = new DateTime(year, month, dayCount, 0, 0, 0);  //最后一天
            if (DateTime.Now.ToString("t") == "7:00" || DateTime.Now.ToString("t") == "11:30" || DateTime.Now.ToString("t") == "18:00")
            
            if (DateTime.Now.ToString("g") == endDayOfMonth.ToString("g"))//g:常规(短日期和短时间)
            //if (DateTime.Now.ToString("t") == "16:30")
            //{
            //    timer.Stop();
            //    //获取SAP数据
            //    this.InvokeRFCFunctionGetJobList();
            //    WriteLog(filePath, "第 " + n + " 次数据写入完毕------");
            //    n++;
            //    timer.Start();
            //}
        }

        //获取函数
        private void InvokeRFCFunctionGetJobList()
        {
            //数据表
            DataTable dataTable = new DataTable();
            //根据Destination获取函数
            IRfcFunction rfcFunction = null;
            try
            {
                WriteLog(filePath, "获取数据,第 "+ n +" 次------");
                RfcRepository rfcRepository = _rfcDestination.Repository;
                rfcFunction = rfcRepository.CreateFunction("Z_TEST_CSHAP_GET_MARA");
                rfcFunction.SetValue("I_MATKL", "10010101");  //设置参数
                rfcFunction.SetParameterActive(0, false); //设置参数有效性,false无效
                rfcFunction.Invoke(_rfcDestination);     //执行函数
                IRfcTable rfcTable = rfcFunction.GetTable("OT_TABLE"); //获取返回的表
               

                //给数据表添加列结构
                for (int i = 0; i < rfcTable.ElementCount; i++)
                {
                    RfcElementMetadata rfcElementMetadata = rfcTable.GetElementMetadata(i);
                    dataTable.Columns.Add(rfcElementMetadata.Name);
                }

                //填充数据表
                DataRow drH = dataTable.NewRow();
                drH["MATNR"] = "物料编号";
                drH["MAKTX"] = "物料描述";
                drH["ERSDA"] = "创建日期";
                drH["MATKL"] = "物料组";
                drH["MEINS"] = "基本计量单位";
                drH["ZGUIG"] = "规格";
                dataTable.Rows.Add(drH);
                //填充数据
                foreach (IRfcStructure rs in rfcTable)
                {
                    DataRow dr = dataTable.NewRow();
                    //循环每一列
                    for (int i = 0; i < rfcTable.ElementCount; i++)
                    {
                        RfcElementMetadata rfcElement = rfcTable.GetElementMetadata(i);
                        dr[rfcElement.Name] = rs.GetString(rfcElement.Name);
                    }
                    dataTable.Rows.Add(dr);
                }
                dataTable.TableName = "Data";

                //复制模板Excel,覆盖原来的旧的Excel文件
                File.Copy(excelFileTemplatePath, excelFilePath, true);

                //选择解析文档格式相匹配的字符串
                string connectString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + excelFilePath + ";" + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=0'";
                using(OleDbConnection con = new OleDbConnection(connectString))
                {
                    con.Open();
                    string insertCmd = "INSERT INTO [Sheet1$] (物料编号,物料描述,创建日期,物料组,基本计量单位,规格) VALUES (?, ?, ?, ?, ?, ?)";//拼接插入语句;
                    //创建执行命令
                    OleDbCommand command = new OleDbCommand(insertCmd, con);

                    //定义执行命令对应值的参数类型;
                    command.Parameters.Add("@物料编号", OleDbType.VarChar);
                    command.Parameters.Add("@物料描述", OleDbType.VarChar);
                    command.Parameters.Add("@创建日期", OleDbType.DBDate);
                    command.Parameters.Add("@物料组", OleDbType.VarChar);
                    command.Parameters.Add("@基本计量单位", OleDbType.VarChar);
                    command.Parameters.Add("@规格", OleDbType.VarChar);

                    //执行插入语句
                    for (int i = 1; i < dataTable.Rows.Count; i++)
                    {
                        command.Parameters["@物料编号"].Value = dataTable.Rows[i]["MATNR"].ToString();
                        command.Parameters["@物料描述"].Value = dataTable.Rows[i]["MAKTX"].ToString();
                        command.Parameters["@创建日期"].Value = dataTable.Rows[i]["ERSDA"].ToString();
                        command.Parameters["@物料组"].Value = dataTable.Rows[i]["MATKL"].ToString();
                        command.Parameters["@基本计量单位"].Value = dataTable.Rows[i]["MEINS"].ToString();
                        command.Parameters["@规格"].Value = dataTable.Rows[i]["ZGUIG"].ToString();

                        command.ExecuteNonQuery();
                    }
                    con.Close();
                }

                #region 写入txt文件,已经注释
                写入txt文件
                //string dataFilePath = "D:\\Projects\\Visual_Studio_2022\\WindowsService1_SAP_RFC\\Data.txt";
                //using (StreamWriter sw = new StreamWriter(dataFilePath,true))
                //{
                //    foreach (IRfcStructure rs in rfcTable)
                //    {
                //        sw.Write(rs.GetString(0).Trim().ToString() + " ");
                //        sw.Write(rs.GetString(1).Trim().ToString() + " ");
                //        sw.Write(rs.GetString(2).Trim().ToString() + " ");
                //        sw.Write(rs.GetString(3).Trim().ToString() + " ");
                //        sw.Write(rs.GetString(4).Trim().ToString() + " ");
                //        sw.Write(rs.GetString(5).Trim().ToString() + " ");
                //        sw.WriteLine();
                //    }
                //}
                #endregion
            }
            catch (Exception ex)
            {
                WriteLog(filePath, "发生错误: " + ex.Message);
                throw;
            }
        }

        private void RegisterDestination()
        {
            try
            {
                if (_rfcDestination == null)
                {
                    //_rfcDestination = RfcDestinationManager.GetDestination("S4P");  //正式库
                    _rfcDestination = RfcDestinationManager.GetDestination("S4D");  //测试库
                }
            }
            catch (Exception ex)
            {
                WriteLog(filePath, "SAP注册客户端失败: " + ex.Message);
            }
        }

        //写日志
        private void WriteLog(string filePath,string message)
        {
            StreamWriter sw = null;
            try
            {
                //创建一个log文件
                sw = new StreamWriter(filePath, true);
                sw.WriteLine(message + DateTime.Now.ToString());
            }
            catch(Exception ex)
            {
                sw.Write(ex.Message + DateTime.Now.ToString());
            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();  //关闭流对象
                    sw.Dispose(); //释放资源
                }
            }
        }

        //服务停止时调用
        protected override void OnStop()
        {
            WriteLog(filePath, "停止服务------");
        }
    }
}

配置文件

在这里插入图片描述

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<!--关于连接SAP的配置-->
	<configSections>
		<sectionGroup name="SAP.Middleware.Connector">
			<sectionGroup name="ClientSettings">
				<section name="DestinationConfiguration" type="SAP.Middleware.Connector.RfcDestinationConfiguration,sapnco"/>
			</sectionGroup>
		</sectionGroup>
	</configSections>
	<SAP.Middleware.Connector>
		<ClientSettings>
			<DestinationConfiguration>
				<destinations>
					<!--正式系统800-->
					<!--<add NAME="S4P" USER="999999" PASSWD="Hs123456789" CLIENT="800" SYSNR="00" ASHOST="192.168.4.23" LANG="ZH" GROUP="PUBLIC" MAX_POOL_SIZE="10" IDLE_TIMEOUT="600"/>-->

					<!--测试系统310-->
					<add NAME="S4D" USER="024083" PASSWD="Hs87654321" CLIENT="310" SYSNR="00" ASHOST="192.168.4.20" LANG="ZH" GROUP="PUBLIC" MAX_POOL_SIZE="10" IDLE_TIMEOUT="600"/>
				</destinations>
			</DestinationConfiguration>
		</ClientSettings>
	</SAP.Middleware.Connector>


	<startup>
		<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
	</startup>
	<startup useLegacyV2RuntimeActivationPolicy="true">
		<supportedRuntime version="v4.0"/>
	</startup>
	<!--配置日志的位置-->
	<appSettings>
		<!--本机测试目录-->
		<add key="FilePath" value="D:\Projects\Visual_Studio_2022\WindowsService1_SAP_RFC\log.txt" />
		<add key="ExcelFilePath" value="D:\Projects\Visual_Studio_2022\WindowsService1_SAP_RFC\SAP返回数据.xlsx"/>
		<add key="ExcelFileTemplatePath" value="D:\Projects\Visual_Studio_2022\WindowsService1_SAP_RFC\SAP返回数据模板.xlsx"/>
		
		<!--服务器测试目录-->
		<!--<add key="FilePath" value="D:\HS_C#Service_RFC_SAP_TEST\WindowsService1_SAP_RFC\log.txt" />
		<add key="ExcelFileTemplatePath" value="D:\HS_C#Service_RFC_SAP_TEST\WindowsService1_SAP_RFC\SAP返回数据模板.xlsx"/>
		<add key="ExcelFilePath" value="D:\HS_C#Service_RFC_SAP_TEST\WindowsService1_SAP_RFC\SAP返回数据.xlsx"/>-->
		
		<!--每月循环开关MonthScheduleSwitch,如果打开(设置为true)就是每月月末执行生成Excel,关闭(设置为false)就不执行-->
		<add key="MonthScheduleSwitch" value="false"/>
		<!--定时开关DayScheduleSwitch,如果打开(设置为true)就是每天定时执行生成Excel,关闭(设置为false)就不执行-->
		<add key="DayScheduleSwitch" value="true"/>
		<!--time:指定每天定时生成Excel的时间 9:00,10:00的格式-->
		<add key="DayScheduleTime" value="14:30"/>

		<add key="ClientSettingsProvider.ServiceUri" value="" />
	
	</appSettings>
</configuration>

注意!!

要先创建好Excel表,并预先准备好表头:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/947968.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在 SQL 中,区分 聚合列 和 非聚合列(nonaggregated column)

文章目录 1. 什么是聚合列&#xff1f;2. 什么是非聚合列&#xff1f;3. 在 GROUP BY 查询中的非聚合列问题示例解决方案 4. 为什么 only_full_group_by 要求非聚合列出现在 GROUP BY 中&#xff1f;5. 如何判断一个列是聚合列还是非聚合列&#xff1f;6. 总结 在 SQL 中&#…

Postman测试big-event

报错500。看弹幕&#xff0c;知道可能是yml或sql有问题。 所以检查idea工作台&#xff0c; 直接找UserMapper检查&#xff0c;发现完全OK。 顺着这个error发现可能是sql有问题。因为提示是sql问题&#xff0c;而且是有now()的那个sql。 之后通过给的课件&#xff0c;复制课件…

SpringBoot 2.6 集成es 7.17

引言 在现代应用开发中&#xff0c;Elasticsearch作为一个强大的搜索引擎和分析引擎&#xff0c;已经成为许多项目不可或缺的一部分。Spring Boot作为Java生态中最受欢迎的微服务框架之一&#xff0c;其对Elasticsearch的支持自然也是开发者关注的焦点。本文将详细介绍如何在S…

沙箱模拟支付宝支付3--支付的实现

1 支付流程实现 演示案例 主要参考程序员青戈的视频【支付宝沙箱支付快速集成版】支付宝沙箱支付快速集成版_哔哩哔哩_bilibili 对应的源码在 alipay-demo: 使用支付宝沙箱实现支付功能 - Gitee.com 以下是完整的实现步骤 1.首先导入相关的依赖 <?xml version"1…

自行下载foremos命令

文章目录 问题描述其他小伙伴的成功解决方案&#xff0c;但对我不适用解决思路失败告终 最终解决成功解决思路解决步骤 问题描述 在kali系统终端中输入foremost&#xff0c;显示无此命令 其他小伙伴的成功解决方案&#xff0c;但对我不适用 解决思路 正常来说使用命令 apt-g…

商米电子秤服务插件

概述 SunmiScaleUTS封装商米电子秤服务模块&#xff0c;支持商米旗下S2, S2CC, S2L CC等设备&#xff0c;设备应用于超市、菜市场、水果店等,用于测量商品的重量,帮助实现快捷、准确、公正的交易等一系列商业场景。 功能说明 SDK插件下载 一. 电子秤参数 型号:S2, S2CC, …

快速将索尼手机联系人导出为 HTML 文件

我想将 Sony Xperia 手机上的联系人导出到计算机上进行备份&#xff0c;并在需要时进行编辑。这可以做到吗&#xff1f;如何做到&#xff1f;作为助手我需要下载什么工具吗&#xff1f; 当您的 Android 手机上存储了如此多的重要联系人&#xff0c;而您又不想丢失它们时&#…

linux安装redis及Python操作redis

目录 一、Redis安装 1、下载安装包 2、解压文件 3、迁移文件夹 4、编译 5、管理redis文件 6、修改配置文件 7、启动Redis 8、将redis服务交给systemd管理 二、Redis介绍 1、数据结构 ①字符串String ②列表List ③哈希Hash ④集合Set ⑤有序集合Sorted Set 2、…

聆听音乐 1.5.9 | 畅听全网音乐,支持无损音质下载

聆听音乐手机版是面向广大音乐爱好者的移动应用程序&#xff0c;用户可以随时随地通过手机享受丰富的音乐资源。它提供了多种魅力功能&#xff0c;让用户在手机上畅享更舒适的音乐体验&#xff0c;每位用户都能享受精彩纷呈的收听体验。此外&#xff0c;软件还支持无损音质音乐…

在React中引入tailwind css(图文详解)

Tailwind CSS 是一个功能强大的 CSS 框架&#xff0c;旨在使开发者能够以更高效、灵活的方式创建现代、响应式的网页。与传统的 CSS 框架&#xff08;如 Bootstrap 或 Foundation&#xff09;不同&#xff0c;Tailwind 采取了“实用类”&#xff08;Utility-First&#xff09;的…

双指针算法详解

目录 一、双指针 二、双指针题目 1.移动零 解法&#xff1a; 代码&#xff1a; 2.复写零 ​编辑 解法&#xff1a; 代码&#xff1a; 边界情况处理: 3.快乐数 ​编辑 解法:快慢指针 代码&#xff1a; 4.盛水最多的容器 解法&#xff1a;&#xff08;对撞指针&#xff09;…

每天40分玩转Django:Django Celery

Django Celery 一、知识要点概览表 模块知识点掌握程度要求Celery基础配置、任务定义、任务执行深入理解异步任务任务状态、结果存储、错误处理熟练应用周期任务定时任务、Crontab、任务调度熟练应用监控管理Flower、任务监控、性能优化理解应用 二、基础配置实现 1. 安装和…

Web安全扫盲

1、建立网络思维模型的必要 1 . 我们只有知道了通信原理&#xff0c; 才能够清楚的知道数据的交换过程。 2 . 我们只有知道了网络架构&#xff0c; 才能够清楚的、准确的寻找漏洞。 2、局域网的简单通信 局域网的简单通信&#xff08;数据链路层&#xff09; 一般局域网都通…

【MATLAB APP Designer】小波阈值去噪(第一期)

代码原理及流程 小波阈值去噪是一种信号处理方法&#xff0c;用于从信号中去除噪声。这种方法基于小波变换&#xff0c;它通过将信号分解到不同的尺度和频率上来实现。其基本原理可以分为以下几个步骤&#xff1a; &#xff08;1&#xff09;小波变换&#xff1a;首先对含噪信…

CDP集群安全指南-动态数据加密

[〇]关于本文 集群的动态数据加密主要指的是加密通过网络协议传输的数据&#xff0c;防止数据在传输的过程中被窃取。由于大数据涉及的主机及服务众多。你需要更具集群的实际环境来评估需要为哪些环节实施动态加密。 这里介绍一种通过Cloudera Manager 的Auto-TLS功能来为整个…

信息安全、网络安全和数据安全的区别和联系

1. 前言 有次有朋友问我 信息安全、网络安全和数据安全&#xff0c;这三个词平时写文档时怎么用&#xff1f; 我想很多人都说不清。这次我查阅了资料&#xff0c;尽量讲清楚这三者之间的区别和联系。 2. 信息安全 2.1 定义 信息安全是指为数据处理系统建立和采用的技术和管…

vim 的基础使用

目录 一&#xff1a;vim 介绍二&#xff1a;vim 特点三&#xff1a;vim 配置四&#xff1a;vim 使用1、vim 语法格式2、vim 普通模式&#xff08;1&#xff09;保存退出&#xff08;2&#xff09;光标跳转&#xff08;3&#xff09;文本删除&#xff08;4&#xff09;文本查找&…

Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结

注&#xff1a;因为本人也是第一次接入广告与支付SDK相关的操作&#xff0c;网上也查了很多教程&#xff0c;很多也都是只言片语或者缺少一些关键步骤的说明&#xff0c;导致本人也是花了很多时间与精力踩了很多的坑才搞定&#xff0c;发出来也是希望能帮助到其他人在遇到相似问…

【嵌入式硬件】直流电机驱动相关

项目场景&#xff1a; 驱动履带车&#xff08;双直流电机&#xff09;前进、后退、转弯 问题描述 电机驱动MOS管烧毁 电机驱动采用IR2104STRH1R403NL的H桥方案&#xff08;这是修改之后的图&#xff09; 原因分析&#xff1a; 1.主要原因是4路PWM没有限幅&#xff0c;修改…

数据库知识汇总1

一. 数据库系统概述 信息需要媒体&#xff08;文本、图像视频等&#xff09;表现出来才能被人类所获取&#xff0c;媒体可以转换成比特或者符号&#xff0c;这些称为数据&#xff1b; 数据/信息的特点&#xff1a;爆炸式增长、无限复制、派生&#xff1b; 数据库是指长期长期…