找回密码
 注册账号

QQ登录

只需一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

初学者课程:T3自学|T6自学|U8自学软件下载课件下载工具下载资料:通资料|U8资料|NC|培训|年结积分规则 | 使用常见问题Q&A
知识库:U8 | | NC | U9 | OA | 政务U8|U9|NCC|NC65|NC65客开|NCC客开新手必读 | 任务 | 快速增金币用友QQ群[微信群]
查看: 16382|回复: 42

用友按钮开发(C#代码)

  [复制链接]
发表于 2021-3-18 11:35:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册账号

×
利用C# 二次开发单据按钮最大的难点应该就是对象无法转换了,有次反编译查看了VB.NET开发的按钮代码,发现了一种方法可以获取表体、表头的数据。这种方法应该是利用了.net平台的反射技术了

首先我们除了U8的一些必要的dll文件外,还需要引入Microsoft.VisualBasic这个动态链接库。

写代码前还需要引用一下  using Microsoft.VisualBasic.CompilerServices;

可能比较繁琐,但至少是一种方式了,大致的意思就是获取对象objVoucher的数据或者函数,然后new object[]{} 里放入的是函数的参数



//获取表体行数

int BodyRows = Convert.ToInt32(NewLateBinding.LateGet(objVoucher, null, "BodyRows", new object[] { }, null, null, null));

//获取第一行存货编码

string cinvcode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "bodytext", new object[] { 1, "cinvcode" }, null, null, null));

//获取表头客户编码

string cCusCode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "headertext", new object[] { "cCusCode" }, null, null, null));

//设置表体第一行的自定义项13

NewLateBinding.LateSet(objVoucher, null, "bodytext", new object[] {  1, "cdefine33", cCusCode }, null, null);

//调用控件函数

NewLateBinding.LateCall(objVoucher,*******************************
获取objLogin对象中数据库的连接信息:Convert.ToString(NewLateBinding.LateGet(objLogin, null, "UFDataConnstringForNet", new object[0], null, null, null));
//获取单据列表选中行,如果要全部行,将true改为false IXMLDOMDocument2 dombody = (IXMLDOMDocument2)NewLateBinding.LateGet(objVoucher, null, "GetListDom", new object[] { true }, null, null, null); IXMLDOMNode dombodynode = dombody.selectSingleNode("//rs:data");
//调用函数修改第一行含税单价 NewLateBinding.LateCall(objVoucher, null, "SimulateInput", new object[] { 1, 1, "itaxprice", 1111, 0 }, null, null, null, true);
发表于 2021-4-6 09:38:16 | 显示全部楼层
本次培训采用简单二次开发案例教学,让大家轻松学会二次开发。
如需详细了解可以加Q群:293892902
1.第一章:用友U8二次开发
1.1用友U8按钮开发
1.1.1讲解了如何添加自定义按钮,介绍了在销售订单和销售订单列表添加按钮。
1.1.2讲解如何获取单据界面的数据库链接、登录人员信息、以及表头内容、表体内容,以及如何给单据界面的表头、表体赋值,可以通过一般赋值,或者模拟输入方式赋值。
1.1.3介绍了三个案例。
第一个是引采购订单生产销售订单,快速生单。
第二个是循环表体,根据表体物料编码获取最新单价,更新的含税单价。
第三个是在列表批改备注,会循环列表,识别打勾的行,获取行销售订单号,根据行销售订单号更新对应备注。
1.2用友单据控件事件开发
1.2.1讲解了如何添加单据控件事件开发,介绍了在采购订单表头、表体控件校验后事件,以及表体单击后事件。
1.2.2介绍了三个案例
第一个表头选择供应商事件触发,循环表体根据供应商+存货编码从价格表获取维护单价,赋值给表体的采购单价栏目。
第二个表头选择供应商事件触发,循环表体根据供应商+存货编码从价格表获取维护单价,赋值给表体的采购单价栏目。
第三个单击表体,根据表体物料编码查询最近一次的采购价格信息,弹窗显示。
1.3用友单据事件开发
1.3.1讲解了如何添加单据事件,介绍了在销售订单添加保存前触发的单据事件开发。
1.3.2介绍了一个案例
第一个是单据保存前检查00001客户不予许销售01000001此类产品,如果检查有此类产品,单据不允许保存,并且提醒用户。
1.4用友嵌入式窗口开发
1.4.1讲解了如何在U8添加菜单以及菜单嵌入式窗口。
1.4.2介绍了一个案例
第一个是开发嵌入式页签窗口,自定义窗口功能,本窗口功能是输入订单号和行号修改销售订单表体备注信息。
1.5用友补丁打包
1.5.1 介绍如何把开发好的dll文件打包成msi补丁,并且介绍如何部署msi补丁。
2.第二章:用友UAP单据开发
2.1用友UAP单据开发设计
2.1.1讲解如何新增UAP单据,设计UAP单据的界面,以及发布UAP单据到ERP。案例是临时发货单据,并且发布到ERP。
2.1.2讲解如何进行UAP单据开发,实现个性化功能发。案例是在临时发货单添加了自定义按钮,按钮功能是点击按钮弹输入框,改变表头备注信息。
3.第三章:用友UAP报表开发
3.1用友UAP报表开发
3.1.1利用SQL储存过程和UAP报表工具开发自定义报表。并且指导如何添加查询条件以及部署报表到ERP。
4.第四章:用友接口功能开发
4.1介绍用友API方式生单
4.1.1U8 API是官方三大接口方式中,功能最强大,实用性最高的对接方式。为U8二次开发提供支持,诞生于开发产业链生态形成时期,面向交付伙伴提供U8二次开发支持。有专门的开发指导工具--“U8API资源管理器”。
4.1.2介绍了采购订单导入案例以及如何快速调整导入模板,快速学会测试API。
4.2介绍用友Co方式生单
4.2.1用友内部的接口,不对外开放。主要针对单据的数据操作。由用友的各个业务开发组封装提供,数据格式为xml(dom)。
4.2.2介绍了采购订单、采购到货单、采购入库单、销售订单、销售发货单、销售出库单导入案例,实现和API一样的效果。
4.3介绍用友U8凭证导入
4.3.1使用用友底层接口方式生成U8凭证,接口具有各种校验,保证导入的凭证准确。
4.3.2提供用友集成的凭证导入案例,供研究。
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-24 09:58:07 | 显示全部楼层
//定义COM组件接口实现
    [ComVisible(true)]
    [Guid("dec342ad-acc6-4531-994b-f3259d2a608a")]//工具-创建GUID
    [ProgId("U8TestButton.clsButtonLinkCc")]
    public class clsButtonLinkCc : U8ButtonInterface.U8Button
    {
        //获取表体行数
        //int BodyRows = Convert.ToInt32(NewLateBinding.LateGet(objVoucher, null, "BodyRows", new object[] { }, null, null, null));
        //获取第一行存货编码
        //string cinvcode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "bodytext", new object[] { 1, "cinvcode" }, null, null, null));
        //获取表头客户编码
        //string cCusCode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "headertext", new object[] { "cCusCode" }, null, null, null));
        //设置表体第一行的自定义项13
        //NewLateBinding.LateSet(objVoucher, null, "bodytext", new object[] {  1, "cdefine33", cCusCode }, null, null);
        //调用控件函数
        //NewLateBinding.LateCall(objVoucher,*******************************
        //获取objLogin对象中数据库的连接信息:Convert.ToString(NewLateBinding.LateGet(objLogin, null, "UFDataConnstringForNet", new object[0], null, null, null));
        //获取单据列表选中行,如果要全部行,将true改为false IXMLDOMDocument2 dombody = (IXMLDOMDocument2)NewLateBinding.LateGet(objVoucher, null, "GetListDom", new object[] { true }, null, null, null); IXMLDOMNode dombodynode = dombody.selectSingleNode("//rs:data");
        //调用函数修改第一行含税单价 NewLateBinding.LateCall(objVoucher, null, "SimulateInput", new object[] { 1, 1, "itaxprice", 1111, 0 }, null, null, null, true);
        // NewLateBinding.LateCall(objForm, null, "ButtonClick", new object[] { "refresh", "refresh" }, null, null, null, true);
        public static ArrayList sbvid_List = new ArrayList();
  
        #region Init
        //初始化时
        public void Init(ref object objLogin, ref object objForm, ref object objVoucher, ref object msbar)
        { }
        //初始化完成时
        public void InitEx(ref object uftoolbar, ref object other)
        {
            return;
        }
        #endregion
        #region SysCommand
      
        //'在执行系统按钮之前调用,Cancel后会不再执行系统方法。
        public void BeforeRunSysCommand(ref object objLogin, ref object objForm, ref  object objVoucher, ref string sKey, ref object VarentValue, ref bool Cancel, ref string other)
        {         
             Cancel = true;
        }
        //'在执行系统按钮时调用。
        public void RunSysCommand(ref object objLogin,ref object objForm,ref  object objVoucher,ref string sKey,ref object VarentValue,ref string other)
        { return; }
        //'在执行系统按钮之后调用,Cancel后会不再执行系统方法。
        public void AfterRunSysCommand(ref object objLogin, ref object objForm, ref  object objVoucher, ref string sKey, ref object VarentValue, ref bool Cancel, ref string other)
        {}
        #endregion
        #region Command
        //'在执行自定义按钮之前调用,Cancel后会不再执行系统方法。
        public void BeforeRunCommand(ref object objLogin,ref object objForm,ref  object objVoucher,ref string sKey,ref object VarentValue,ref string other)
        { return; }
        //'在执行自定义按钮之后调用,Cancel后会不再执行系统方法。
        public void RunCommand(ref object objLogin,ref object objForm,ref  object objVoucher,ref string sKey,ref object VarentValue,ref string other)
        {
            U8Login.clsLogin u8login = new U8Login.clsLogin();
            u8login = objLogin as U8Login.clsLogin;
            U8.DbHelperSQL.connectionString = Convert.ToString(NewLateBinding.LateGet(objLogin, null, "UFDataConnstringForNet", new object[0], null, null, null));
            if (sKey == "_CUSTDEFBtnStudy1")
            {
                string cSoCode = "";
                string cInvCode = "";
                //headText属性设置或返回表头项目的值()
                //bodyText属性设置或返回表体项目的值()
                //获取表头字段cSoCode的值
                cSoCode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "headertext", new object[] { "cSoCode" }, null, null, null));
                //获取某一行的字段cInvCode的值
                cInvCode = Convert.ToString(NewLateBinding.LateGet(objVoucher, null, "bodytext", new object[] { 1, "cinvcode" }, null, null, null));
                //赋值给表头字段cSoCode
                NewLateBinding.LateSet(objVoucher, null, "headertext", new object[] { "cSoCode", "20210220" }, null, null);
                //赋值某一行的字段cInvCode
                NewLateBinding.LateSet(objVoucher, null, "bodytext", new object[] { 1, "cInvCode", "01000001" }, null, null);
                //模拟赋值,赋值之后可以联动给其他栏目
                NewLateBinding.LateCall(objVoucher, null, "SimulateInput", new object[] { 1, 1, "cInvCode", "01000001", 0 }, null, null, null, true);
                NewLateBinding.LateCall(objVoucher, null, "SimulateInput", new object[] { 0, 1, "cMemo", "学习", 0 }, null, null, null, true);
            }
回复 点赞 1 拍砖 0

使用道具 举报

 楼主| 发表于 2021-3-30 11:45:38 | 显示全部楼层
//c#真确的co存货档案,避免很多谣言
//OperationType只是一个传说,或许是个谣言!!!!!
                // int OperationType = Convert.ToInt32(NewLateBinding.LateGet(objForm, null, "OperationType", new object[] { }, null, null, null));

                //'objForm.m_SaveXML 串可以再次加工
                string sXml = Convert.ToString(NewLateBinding.LateGet(objForm, null, "m_SaveXML", new object[] { }, null, null, null));

                DataTable DD = YYU8DAL.CXmlToDatatTable(sXml);

                string sds = ConvertDataTableToXml(DD);

                String sAccID = "(default)@111";//修改的账套
                String sYear = Convert.ToDateTime("2021-03-23 00:00:00.000").Year.ToString();
                String sDate = Convert.ToDateTime("2021-03-23 00:00:00.000").ToString("yyyy-MM-dd");
                String sServer = "MYYY";
                String sUserID = "demo";

               U8Login.clsLogin u8 = new U8Login.clsLogin();
               u8 = U8clsLogin.Login(sAccID, sYear, sDate, sServer, sUserID);
               IClsCommon DS = new IClsCommon();
               bool succeed = false;
               if (DS.InitNew(u8) == true)//OperationType=1是操作失败 && OperationType != 1
               {

                   DataTable DE = YYU8DAL.CXmlToDatatTable(sXml);//转table查bmanualchangecode:1:增加;0:修改
                   int ot= int.Parse(DE.Rows[0]["bmanualchangecode"].ToString());
                   if (ot == 0)//修改保存
                   {
                       ////////谣言在此,编辑把pubufts取出来让二开吃屎////////
                     int start=  sXml.IndexOf("<pubufts>");
                     int end = sXml.IndexOf("</pubufts>");
                     int endleng = "</pubufts>".Length;
                  ////////////////////////////
                     sXml = sXml.Remove(start, end - start + endleng);

                       succeed = DS.Modify(sXml, "Inventory", "");
                   }
                   if (ot == 1)//新增保存
                   {
                       succeed = DS.Add(sXml, "Inventory", "");
                   }


               }
            }
            catch
            {


            }
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-4-5 18:27:27 | 显示全部楼层
'执行按钮前执行该方法,objVoucher为单据或列表对象
    'VarentValue为在表中预置的cVariant的值。
    'objLogin代表UFToolbar上取得的Login信息
    'objForm代表该Toolbar所在的窗体信息
    'objVoucher代表Toolbar所在窗体上的单据控件对象或者单据列表对象
    'sKey代表该按钮的ButtonKey
    'VarentValue代表数据库预置的Varent值
    Public Function BeforeRunSysCommand(ByVal objLogin As Object, ByVal objForm As Object, ByVal objVoucher As Object, _
                            ByVal sKey As String, ByVal VarentValue As Object, ByRef Cancel As Boolean, ByVal other As String) As Boolean
        Dim cCusCode As String
        Dim cInvCode As String
        Dim sql As String
        Dim Dt_data As New DataTable
        U8SQLHelper.U8DB.connectionString = objLogin.UfDbName
        '保存前检查000001客户不予许销售01000001此类产品,如果检查有此类产品,单据不允许保存,并且提醒用户
        If sKey = "save" Then
            For i = 1 To objVoucher.Rows
                If Not String.IsNullOrEmpty(objVoucher.bodyText(i, "cInvCode")) Then
                    cInvCode = objVoucher.bodyText(i, "cInvCode")
                    cCusCode = objVoucher.headerText("cCusCode")
                    If (cCusCode = "00000001" And cInvCode = "01000001") Then
                        MsgBox("此商品01000001,不能销售给该客户!")
                        Cancel = True
                        Exit Function
                    End If
                End If
            Next
        End If
        Cancel = False
    End Function
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-18 11:47:35 | 显示全部楼层
互相交流
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-18 14:02:02 | 显示全部楼层

U8开发合集培训,分别是U8自定义按钮开发、U8控件事件开发、U8单据事件开发、U8嵌入式窗口开发、U8补丁工具打包、UAP单据开发、UAP报表开发、U8API开发培训、用友底层方式API培训、用友凭证导入培训。
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-18 14:02:40 | 显示全部楼层
请问可以分享嘛
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-18 14:27:17 | 显示全部楼层
请问可以分享嘛
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-19 17:53:52 | 显示全部楼层
用友开发大合集可以加 q群 293892902
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-23 08:41:33 | 显示全部楼层
常用的Co类型
CVoucher 凭证类
VoucherCO_Sa.ClsVoucherCO_SA  销售CO类
VoucherCO_PU.clsVoucherCO_PU 采购CO类
USERPCO 库存CO类
UFAPBO  应付CO类
U8SrvTrans 基础类
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-23 08:42:54 | 显示全部楼层
凭证co代码
CVoucher.CVInterface co = new CVoucher.CVInterface();
co.strTempTable=StrHeadName;
ADODB.Connection conn=new ADODB.Connection();
conn.Open(u8Login.UfDbName);
co.set_Connection(conn);
co.Login3(u8Login);
string Msg = "";
if (!Convert.ToBoolean(co.SaveVoucher()))
{
MessageBox.Show(co.strErrMessage);
}
回复 点赞 拍砖

使用道具 举报

 楼主| 发表于 2021-3-27 21:45:21 | 显示全部楼层
1. 第一章:用友U8二次开发
1.1 用友U8按钮开发
1.1.1 讲解了如何添加自定义按钮,介绍了在销售订单和销售订单列表添加按钮。
1.1.2 讲解如何获取单据界面的数据库链接、登录人员信息、以及表头内容、表体内容,以及如何给单据界面的表头、表体赋值,可以通过一般赋值,或者模拟输入方式赋值。
1.1.3 介绍了三个案例。
第一个是 引采购订单生产销售订单,快速生单。
第二个是 循环表体,根据表体物料编码获取最新单价,更新的含税单价。
第三个是 在列表批改备注 ,会循环列表,识别打勾的行,获取行销售订单号,根据行销售订单号更新 对应备注。
1.2 用友单据控件事件开发
1.2.1 讲解了如何添加单据控件事件开发,介绍了在采购订单表头、表体控件校验后事件,以及表体单击后事件。
1.2.2 介绍了三个案例
第一个 表头选择供应商事件触发,循环表体根据供应商 +存货编码从价格表获取维护单价,赋值给表体的采购单价栏目 。
第二个 表头选择供应商事件触发,循环表体根据供应商 +存货编码从价格表获取维护单价,赋值给表体的采购单价栏目 。
第三个单 击表体,根据表体物料编码查询最近一次的采购价格信息,弹窗显示。
1.3 用友单据事件开发
1.3.1 讲解了如何添加单据事件,介绍了在销售订单添加保存前触发的单据事件开发。
1.3.2 介绍了一个案例
第一个是单据 保存前检查 00001客户不予许销售01000001此类产品,如果检查有此类产品,单据不允许保存,并且提醒用户 。
1.4 用友嵌入式窗口开发
1.4.1 讲解了如何在 U8 添加菜单以及菜单嵌入式窗口。
1.4.2 介绍了一个案例
第一个是 开发嵌入式页签窗口,自定义窗口功能,本窗口功能是输入订单号和行号修改销售订单表体备注信息。
1.5 用友补丁打包
15.1 介绍如何把开发好的 dll 文件打包成 msi 补丁,并且介绍如何部署 msi 补丁。
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-31 12:55:11 | 显示全部楼层
谢谢楼主分享
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-31 12:55:46 | 显示全部楼层
   string cmdLine = "";
            cmdLine = "ID:{0}&&&Name:{1}&&&SubSysID:{2}&&&AuthID:{3}&&&CMDLINE:{4}\t{5}";

            cmdLine = string.Format(cmdLine, menuID, menuName, subID, authID, cardNumber, pkFieldValue);
            IPortalCommandOperator portalCommandOperator = new PortalCommandOperator();
            IPortalCommandArgs portalCommandArgs = new PortalCommandArgs(menuID, subID);
            portalCommandArgs.AuthId = string.Empty;
            portalCommandArgs.DocId = string.Empty;
            portalCommandArgs.DocType = string.Empty;
            portalCommandArgs.ID = menuID;
            portalCommandArgs.Name = menuName;
            portalCommandArgs.SubFunction = string.Empty;
            portalCommandArgs.Extenision = string.Empty;
            portalCommandArgs.SubSysID = subID;
            portalCommandArgs.CmdLine = cmdLine;
            portalCommandArgs.FromUserClick = false;
            portalCommandArgs.ExtProperties.Add("recheck", "1");
            portalCommandOperator.RunBusiness(portalCommandArgs);
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-31 12:55:56 | 显示全部楼层
18928099590 发表于 2021-3-31 12:55
string cmdLine = "";
            cmdLine = "ID:{0}&&&Name:{1}&&&SubSysID:{2}&&&AuthID:{3}&&&CMDLI ...

联查代码
回复 点赞 拍砖

使用道具 举报

发表于 2021-3-31 16:11:34 | 显示全部楼层
objVoucher.SimulateInput(SectionsConstants.sibody, objVoucher.Row, "iquantity", intValue, echeck)   

报下面的错误:
类型不匹配。 (异常来自 HRESULT:0x80020005 (DISP_E_TYPEMISMATCH))

echeck 为false  ,改为1也一样。

目的是回写数量到发货单表体 iquantity 字段,并带出这行价格相关信息。

objVoucher.bodytext(index, "iQuantity") = DtCallBack.Rows(index - 1)("iquantity").ToString()
这样操作数量是回写了,但是不像在发货单做单填写数量回车自动带出价格信息那些。

求教!


回复 点赞 拍砖

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

QQ|站长微信|Archiver|手机版|小黑屋|用友之家 ( 蜀ICP备07505338号|51072502110008 )

GMT+8, 2024-12-22 13:30 , Processed in 0.120639 second(s), 16 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表