《2022年Net调用SAPRFC接口来读取数据实战纪实 .pdf》由会员分享,可在线阅读,更多相关《2022年Net调用SAPRFC接口来读取数据实战纪实 .pdf(23页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、.Net 调用 SAP RFC 接口来读取数据实战纪实这几天研究 .Net 如何调用 SAP RFC 接口来读取数据, 搞得我重装了三次系统,找资料找到吐血,看了德文、日文、英文、中文几乎所有可以参考的资料,师傅亲自出马,并请教了一堆高手还包括IBM 的帅锅,还割舍了阳光明媚的周日来研究,终于功夫不负有心人,最终还是解决了,汗啊 下面把我调试的全过程都记录一下,以后有人遇到相同问题就可以参考了。1.【关键前提】 : (1) 你安装了 VS2003 (注意:一定要VS2003,原因在下面)(2)安装 SAP .Net Connector 2.0 ( 这东东目前只支持.net framework
2、1.X, 即 IDE 7.5版本,所以只能用 VS2003) (3) 有 Java runtime environment (后面导入SAP的 Function 时有用)(4) 安装 SAP Logon 原理图如下:2.【开始编程】(1)首先是在 SAP里面创建 RFC 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 23 页 - - - - - - - - - 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - -
3、- 名师精心整理 - - - - - - - 第 2 页,共 23 页 - - - - - - - - - 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 23 页 - - - - - - - - - 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 23 页 - - - - - - - - - (2) VS里面编程先以 Winform 程序为例吧a.
4、新建winform项目,因为装了SAP .Net Connector,所以可以添加对SAP .Connector.dll和SAP .Connector .Rfc.dll 的引用。在项目中新建类,你会发现多了一个SAP Connector Proxy 的类,新建一个,就是下面图中的SAPProxy1.sapwsdl文件啦。b.在 Form1.cs 中添加控件名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 23 页 - - - - - - - - - (比较简陋,凑合看了)c
5、.在 SAP Test的 Button 事件里面加入以下代码private void button1_Click(object sender, System.EventArgs e) SAP .Connector.SAPLogonDestination myDest; SAP .Connector.SAPConnection myConn; SAPProxy1 myProx; BRFCKNA1Table xMara; System.Data.DataTable dMara; try myDest = new SAP .Connector.SAPLogonDestination(); myDes
6、t.DestinationName = 这里输入 SAP服务器上的系统名称; myDest.Client = 这里输入 SAP服务器的客户端号; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 23 页 - - - - - - - - - myDest.Username = 这里输入 SAP服务器访问的用户名; myDest.Password = 这里输入 SAP服务器访问的密码; myConn = new SAP .Connector.SAPConnection(myD
7、est); myConn.Open(); xMara = new BRFCKNA1Table();/注意,这个BRFCKNA1Table 可不是随便写的哈,看到下面就明白了 myProx = new SAPProxy1(); myProx.Connection = myConn; myProx.Rfc_Customer_Get(, this.textBox1.Text, ref xMara); / 注意,这个 Rfc_Customer_Get 就是你要 call 的 RFC的 function 名称 dMara = new System.Data.DataTable(); dMara = xM
8、ara.ToADODataTable(); dataGrid1.DataSource = dMara; dataGrid1.Refresh(); myConn.Close(); catch(Exception ex) textBox1.Text = ex.ToString(); d.从 SAP服务器上导入RFC Function 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 23 页 - - - - - - - - - 不要小看这一步哦【支线任务1】在 C:WINDOW
9、S 找到 saplogon.ini,打开后把SysName和 SrvPort 下面的内容清空,不清空的话他会引导你去找SAP 服务器上的Messaging server,总是告诉你无法打开或者无法找到sapmsg.ini 的文件,非常麻烦。MSSysName Item1= MSSrvPort Item1= 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 23 页 - - - - - - - - - (如果机器上没有Java runtime environment 就会一直
10、停留在Loading 的画面 =.= ) e. 启动项目,在textbox 里面输入检索关键字,就可以看到这样的画面,调用成功0 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 23 页 - - - - - - - - - 上面是以 Winform 为例,下面简单说一下Web App 和 Web Service,还是有点差别的哟【Web App】Web app 的不同之处在于(1)在 default.aspx 中加入 button,datagrid 以及 textbox
11、后,在后台程序中加入如下代码:private void Button1_Click(object sender, System.EventArgs e) / Declare parameters here SAPProxy1 proxy = new SAPProxy1(); SAPRFCIF.BRFCKNA1Table brfcknA1Table1 = new BRFCKNA1Table(); try proxy.Connection = SAP .Connector.SAPLoginProvider.GetSAPConnection(this); / Call methods here pr
12、oxy.Rfc_Customer_Get(, this.TextBox1.Text, ref brfcknA1Table1); / Now update Data Bindings. On WinForms this will be automatic, on / WebForms call the following line this.DataBind(); catch(Exception ex) / If SAPLoginProvider.GetSAPConnection(this) cannot get a connection, / we might get an error. /
13、Normally this can be ignored as it will automatically will force a / relogon. (2)需要新建一个SAPLogin1.aspx, 这个也是装了SAP .net Connector 以后,在新增项目的时候可以看到的一个aspx 模板 ,然后在 SAPLogin1.aspx.cs中添加如下代码string systemNumber = 00;/这个也是要看SAP服务器设置的private void Login_Click(object sender, System.EventArgs e) 名师资料总结 - - -精品资料
14、欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 23 页 - - - - - - - - - / Bind data back this.destination1.Username = this.user.Text; this.destination1.Password = this.password.Text; / 设置 sap 服务器start this.destination1.AppServerHost= 这个自己填哈 ; this.destination1.SystemNumber= sho
15、rt.Parse(systemNumber); ; / 设置 sap 服务器end try this.destination1.Client = short.Parse(this.client.Text); catch(Exception) this.destination1.Client = 0; if (this.language.Text.Length 0) this.destination1.Language = this.language.Text; try SAP .Connector.SAPLoginProvider.OpenSAPConnection(this, destina
16、tion1.ConnectionString, this.persist.Checked); catch (System.Exception exception) this.message.Text = exception.ToString(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 23 页 - - - - - - - - - 【Web Service】(1) 在 Service1.asmx 中添加 SAP的 Destination 控件右键,打开代码(2)
17、 在 Service1.asmx.cs中加入以下代码 private void InitializeComponent() 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 23 页 - - - - - - - - - / 以下是定義Destination 的內容 ponents = new System.ComponentModel.Container(); this.destination1 = new SAP.Connector.Destination(ponent
18、s); / / destination1 / this.destination1.AppServerHost = XXXXXXX; this.destination1.Client = (short)(XXX); this.destination1.Language = EN; this.destination1.Password = XXXX; this.destination1.SystemNumber = (short)(00); this.destination1.Username = XXXX; /- WebMethod public DataSet Exploding_BOM(st
19、ring Language) try SAPProxy1 mProxy=new SAPProxy1(); / 實例一個SAPProxy mProxy.Connection=SAP .Connector.Connection.GetConnectionFromPool(this.destination1.ConnectionString); / 鏈接 RFCHOSTSTable mStpoxtable = new RFCHOSTSTable(); / 實 例 一 個 輸 出 資 料 的Table DateTime mNow = DateTime.Now; string str_now = mNo
20、w.ToString(); / 把取到的當前日期轉為字串型 mProxy.Rfc_Get_Local_Destinations(Language, ref mStpoxtable); mProxy.Connection.Close(); mProxy.Connection=null; DataSet mReturn = new DataSet(); / 實例一個DataSet存放 RFC回傳的 Table mReturn.Tables.Add(mStpoxtable.ToADODataTable (); return mReturn; catch (Exception ex) return D
21、ataError(ex); public DataSet DataError(Exception ex) DataSet errDS = new DataSet( Errors); DataTable errTable = errDS.Tables.Add( Error ); errTable.Columns.Add( Message ); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 23 页 - - - - - - - - - errTable.Rows.Add(
22、new Object ex.Message); return errDS; 已投稿到:排行榜圈子阅读 (1051)| 评论 (23)| 收藏 (1)| 打印 | 举报前一篇: DIY输入法皮肤后一篇:龙二去了天堂,都是我的错评论重要提示:警惕虚假中奖信息,点击查看详情发评论 西游梦呓:2008-06-29 23:08:09 ?是你之前的学习资料?还是你又自己搞这个?没明白博主回复:2008-11-21 13:36:12 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 2
23、3 页 - - - - - - - - - 是我最近在做的一个项目要做SAP接口,但是我们部门没人做过,我就自己上了, 借这个机会学到很多东西哈哈新浪网友:2008-07-11 08:41:50 好文,不错,有帮助博主回复:强者:2008-07-18 15:36:32 我在测试此代码时,在执行 myConn.Open();操作时报如下错误: Missing R3NAME=. or ASHOST=. in connect_param in RfcOpenEx 请这是何问题 ,如何解决 ? 博主回复:NaNa:2008-07-18 22:04:19 RFC接口调用 SAP如果有异常会通过com.s
24、ap.mw.jco.JCO$Exception: 抛出异常在开发中遇到的异常有如下用户名密码可能是错误或者用户无权限,确认用户 ,必要时联系SAP负责人 ,检查用户(103) RFC_ERROR_LOGON_FAILURE: #.#,# (103) RFC_ERROR_LOGON_FAILURE: Name or password is incorrect (repeat logon) call 信息没有填写完整,检查配置文件各个SAP配置信息是否完整(101) RFC_ERROR_PROGRAM: Missing R3NAME=. or ASHOST=. in connect_param i
25、n RfcOpenEx ip 地址失败:com.sap.mw.jco.JCO$Exception: (102) RFC_ERROR_COMMUNICATION: Connect to SAP gateway failed 组权限访问 server 文件没更新 . (102) RFC_ERROR_COMMUNICATION:Connect to message server failed 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 23 页 - - - - - - -
26、 - - C:WINNTsystem32driversetc 端口号错误报错信息:(103) RFC_ERROR_LOGON_FAILURE: # 502 # 超时 : (103) RFC_ERROR_LOGON_FAILURE: Timeout 执行函数 ,函数的问题(104) RFC_ERROR_SYSTEM_FAILURE: Error in module RSQL of the database interface.执行函数(104) RFC_ERROR_SYSTEM_FAILURE: An error occurred when receiving a complex paramet
27、er. (106) JCO_ERROR_RESOURCE: Trying to access row values in a table which does not have any rows yet 返回的表没有值.那个表连第一行都没有,取不到(106) JCO_ERROR_RESOURCE: Trying to access row values in a table which does not have any rows yet 语法错误(104) RFC_ERROR_SYSTEM_FAILURE: Syntax error in program SAPMV50A 找不到行(106)
28、 JCO_ERROR_RESOURCE: Trying to access row values in a table which does not ha:ve any rows yet 输入参数不能插入SAP函数输入字段中. (122) JCO_ERROR_CONVERSION: Integer 4234243 has to many digits at field PO_ITEM 博主回复:新浪网友:2008-07-26 14:07:58 string cs = ASH T=SAP SYSNR=00 CLIENT=00 USER=DDIC PASSWD=19920706; System.D
29、ata.DataTable sdt; SAPProxy1 proxy = new SAPProxy1(cs); BAPIADDR1 addr1=new BAPIADDR1(); addr1.Addr_No=0004; addr1.Adr_Notes=dkfjkd; addr1.Build_Long=1; addr1.Building =1; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 23 页 - - - - - - - - - addr1.C_O_Name=sdj
30、fh; addr1.Chckstatus=sdjkf; addr1.E_Mail=sdfjkh; addr1.City=ewrui; addr1.City_No=0001; addr1.Country=AD; string ctry,bankKey; BAPIRET2 i2=new BAPIRET2(); BAPI1011_ADDRESS addr=new BAPI1011_ADDRESS(); / addr.Addr_No=0004; / addr.Bank_Branch=dskjfhk; / addr.Region=; addr.Bank_Name=dsjkfdk; / addr.City
31、=ewrui; / addr.Street=programe; proxy.Bapi_Bank_Create(addr,addr1 ,AD,00004,1, out ctry,out bankKey,out i2); 试了很久 ,还是未能将数据添加到SAP 中,只能查看现有数据!请博主帮我看看这个问题出在什么地方 ! 博主回复:新浪网友:2008-07-28 14:25:57 非常好的文章,但是我和你写的一样,却返回不了数据值SAP .Connector.SAPLogonDestination myTest; SAP .Connector.SAPConnection myConn; SAPPr
32、oxy1 myProx; System.Data.DataTable dMara; ZGET_AUFKTable xMara; try myTest = new SAP .Connector.SAPLogonDestination(); myTest.DestinationName = DEV; myTest.Client = 030 ; myTest.Username = XCN; myTest.Password = Sap0%; /myTest.AppServerHost = 10.1.11.3; myTest.Language = ZF; /myTest.SystemNumber = 0
33、 ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 23 页 - - - - - - - - - myConn = new SAP .Connector.SAPConnection(myTest); xMara = new ZGET_AUFKTable(); myProx = new SAPProxy1(); myProx.Connection = myConn; myConn.Open(); int i ; string s; /myProx.Zget_Aufk_D
34、ata(this.txtAufnrfm.Text,this.txtAufnrto.Text,this.txtGltrsfm.Text,this.txtGltrsto.Text,this.txtGstrsfm.Text,this.txtGstrsto.Text,this.txtWerks.Text,out i ,ref xMara); myProx.Zget_Aufk_Data(this.txtAufnrfm.Text,this.txtAufnrto.Text,this.txtGltrsfm.Text,this.txtGltrsto.Text,this.txtGstrsfm.Text,this.
35、txtGstrsto.Text,this.txtWerks.Text,out i,out s ,ref xMara); dMara = new System.Data.DataTable(); dMara = xMara.ToADODataTable(); dataGrid1.DataSource = dMara; dataGrid1.Refresh(); myConn.Close(); this.label7.Text = s ; 博主回复:2008-08-02 17:09:25 楼上两位, 谢谢光临小站, 请确定你连接上SAP服务器了。 看看配置有没有写对了?或者跟踪调试一下吧。德州扑士:
36、2008-09-19 15:48:47 你的文章跟你人一样美。谢谢博主回复:堕落:2008-10-23 15:48:50 小弟刚玩 SAP ,真是太好了参照你给的示例,但得不到结果 ,在调试过程中myDest.DestinationName = ; 但是我是给赋值的(TEST2003), 是 SAP服务器名 ,请帮忙 ! 博主回复:2008-10-24 11:24:36 你先用 SAP client 窗口登陆一下,确保你的连接信息都是正确的,然后再检查一下代码里面的 sap 配置信息有没有都填写好了。我一开始也有一次连接不了,后来发现是有个配置没写对的原因名师资料总结 - - -精品资料欢迎下
37、载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 23 页 - - - - - - - - - 堕落:2008-10-23 16:20:40 强者的那个问题怎么解决啊,我也碰到了 ,是不是连接SAP错误啊 ?请尽快帮帮忙,谢谢 ! 博主回复:2008-10-24 11:22:41 call 信息没有填写完整,检查配置文件各个SAP配置信息是否完整堕落:2008-10-29 09:35:48 博主你好 ,谢谢你的回复 ,现在一直提示Name or password incorrect, 用户名与密码那是肯定正确
38、的 ,是不是权限不够,需添加什么权限,我新建的用户采用了SAP_ALL权限 ,怎么还不够啊?DDIC系统初始用户也不能用. 博主回复:andybang1126:2008-10-30 15:16:28 一个新手要掌握中的一个模块,大致需要多少时间,如模块, 掌握程度是能做系统的配置,简单的开发,IDOC文档的处理及模块的操作,在无人的指导的情况下博主回复:新浪网友:2008-11-16 22:39:04 代码: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
39、 Button1.Click sap.Connector.SAPLogonDestination myDest ; sap.Connector.SAPConnection myConn ; End Sub 错误提示如下:C:SAP_DEMODEMO1Form1.vb(87): “SAPLogonDestination”是“ Connector”中的类型,不能用作表达式。C:SAP_DEMODEMO1Form1.vb(87): 方法参数必须括在括号中。C:SAP_DEMODEMO1Form1.vb(87): 名称“ myDest”未声明。名师资料总结 - - -精品资料欢迎下载 - - - -
40、- - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 23 页 - - - - - - - - - C:SAP_DEMODEMO1Form1.vb(87): 字符无效。博主回复:sky:2008-11-20 14:32:14 您好 我想问一下BRFCKNA1Table ;这个类型名是从哪里得来的!我的程序一直检查不过去。谢谢!博主回复:2008-11-21 13:34:59 BRFCKNA1Table 这是 SAP的 RFC中的 Table sky:2008-11-20 15:48:32 原来是全局表啊。 。 。博主回复:sky:2
41、008-11-21 18:02:09 谢谢您的回答,我现在又有一个问题,我要从外部对SAP进行数据回写。在RFC中我加了INSERT语句,并在R/3 中调试 RFC一切正常。但是,用C#调用的时候就不好。这个回写我分了 2 种情况, 一种是我直接在IMPORT加了一个循环的次数,由 RFC根据次数插入相应条数的数据(这个数据是在RFC 中生成的)这种好用。但是我把数据封装成表,并从TABLE的参数传时就不好用。你知道这是为什么么?谢谢!博主回复:sky:2008-11-24 10:01:09 也就是说向RFC中传数据,以TABLES 的参数形式向RFC中传传不进去。 。 。博主回复:2008-
42、11-28 21:12:23 你传入的 Table要先转换成SAP Table类型的,有一个方法可以直接转换的。新浪网友:2008-12-10 13:52:27 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 20 页,共 23 页 - - - - - - - - - 奇怪了,我按照你的做法去试,服务器是能连上,但就是myProx.Rfc_Customer_Get(, this.textBox1.Text, ref xMara); 这一步无法通过。原因是myProx 没有该方法,请问
43、NaNa 这种情况应该怎么处理呢?我用的是SAP Connector2.0 博主回复:NaNa:2008-12-12 20:37:54 这位兄弟,那是因为你没有定义代理类,你可以再仔细看一下我文章中关于代理类的定义,你要实例化一个myprox 才行哟博主回复:新浪网友:2008-12-16 14:16:50 楼主,紧接上面的myProx.Rfc_Customer_Get 问题。因为我是没有权限到SAP中建立函数的,Rfc_Customer_Get 这个方法是不是调用自SAP内部的函数呢?所以不同的SAP系统可能不一定存在该函数呢?还是Rfc_Customer_Get 这个函数是定义在SAPco
44、nnector 组件的内部呢 ? ? 所 以 我 现 在 即 使 定 义 了 代 理 类 并 且 已 经 实 例 化 还 是 不能 从myProx 中 找 到Rfc_Customer_Get 这个函数。请楼主指教了博主回复:新浪网友:2009-01-04 10:22:11 楼主,请问目前可以用VS 2008来调用 SAP RFC 吗? 能不能帮帮忙,您会的外文多,而且又认识 IBM 的帅哥 ,嘿嘿 .先谢谢啊 !我会常来看看。博主回复:SM-朽木露綺亞 -杜隆:2009-03-03 15:52:58 博主你好,我在调用proxy.Bapi_Goodsmvt_Create(bapi1,bapi2
45、,bapi8,out bapi3,out strMat,out strMaterial,ref bapi9,ref bapi4,ref bapi5,ref bapi10,ref bapi6);函数写入一些出库信息到SAP 中,但是在调用proxy1.Bapi_Transaction_Commit(X,out bapi11);函数提交时出现了下面的错误,如果把这一段代码删除了是可以正常运行的,但是数据不能提交到SAP中,所以一定要使用这个函数才能提交 Bapi_Goodsmvt_Create 函数中要写入的信息,麻烦你帮我看看,谢谢了! !名师资料总结 - - -精品资料欢迎下载 - - - -
46、 - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 21 页,共 23 页 - - - - - - - - - 命名空间“ urn:sap-com:document:sap:rfc:functions”中名为“ BAPI_TRANSACTION_COMMIT ”的 XML 元素引用方法和类型。使用 WebMethodAttribute 更改方法的消息名称,或使用 XmlRootAttribute 更改类型的根元素。异常详细信息: System.InvalidOperationException: 命名空间“urn:sap-com:docume
47、nt:sap:rfc:functions”中名为 “BAPI_TRANSACTION_COMMIT ”的 XML 元素 引 用 方 法 和 类 型 。 使 用 WebMethodAttribute 更 改 方 法 的 消 息 名 称 , 或 使用 XmlRootAttribute 更改类型的根元素。源错误 : 行 35: / Initializes a new SAPProxy2. 行 36: / 行 37: public SAPProxy2() 行 38:行 39: / 博主回复:NaNa:2009-03-06 13:10:10 SM-朽木露綺亞 -杜隆 ,你好, 我仔细看了你的问题,但是我
48、不知道你具体的代码和逻辑,也无法调试,所以帮不上你的忙了,实在抱歉,但是我可以分享一下我解决问题的方法:我一般是用报错信息作为关键字到网络上搜索一下是否有类似的案例,如果没有, 就搜索我程序中使用到的几个类型和命名空间,查看他们的属性和使用方法介绍,看是不是自己在使用过程中缺少引用或者别的什么原因另外就是设置几个关键的跟踪点,进行单步调试, 或者写一些测试用例来对出问题的地方进行测试。博主回复:新浪网友:2009-03-11 09:50:23 我和上面一个人遇到同样的问题,调试过程中myDest.DestinationName = ; 但是明明赋值了。其他的代码确认没有差错,不知道是不是SAP的配置有问题, 博主能否介绍一下SAP中 SM59名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 22 页,共 23 页 - - - - - - - - - 的设置?不是很明白是怎么设置的,试了很多次。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 23 页,共 23 页 - - - - - - - - -