精华内容
下载资源
问答
  • VB中 variant与object区别?

    千次阅读 2016-11-13 16:11:35
    Object是对象,是VB中各种控件、组件等的泛称,是类的实例。依上所述,当你给一个Variant变量赋值为对象时,这个变量也自动变为Object。所以从表面上看两者似乎差不多,但事实上是有本质区别的。
    Variant是不定类型,或者说可变类型,是一种“万金油”变量,你给它赋值哪种类型的数据,它就会自动变为哪种类型,比如说赋值1234,它就是Integer型,赋值12.34,它就是Double型。
    Object是对象,是VB中各种控件、组件等的泛称,是类的实例。依上所述,当你给一个Variant变量赋值为对象时,这个变量也自动变为Object。所以从表面上看两者似乎差不多,但事实上是有本质区别的。
    不提倡用Variant来声明变量,因为它要用额外的内存字节来记录变量的实际类型,不但会造成资源的浪费,也会降低程序的运行效率。应该声明为具体的变量类型,比如Integer、Long、Single、Double、Date等等。
    

    同样,也不提倡用Object来声明对象变量,而应该是具体的对象类型,如TextBox、CommandButton、ComboBox等

    Variant 数据类型是所有没被显式声明(用如 Dim、Private、Public 或 Static等语句)为其他类型变量的数据类型。Variant 数据类型并没有类型声明字符。
    Variant 是一种特殊的数据类型,除了定长 String 数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含 Empty、Error、Nothing 及 Null等特殊值。可以用 VarType 函数或 TypeName 函数来决定如何处理 Variant 中的数。

    object 可以代表VB中的任何一个对象。 在某些情况下你在代码中要对一些并不是事先就能够确定类型的对象进行操作就可以用object对象。例如,要遍历一个窗体上的所有控件,并显示出这些控件的名称就要用到object对象了。

    展开全文
  • vb中Variant类型调用mid函数返回的字符串还是在原来字符串里面么?怎么区分Variant类型和字符串类型?vb怎么调用不定长的mid?
  •  前段时间由于该控件基于微软的MSCOMM控件,这个控件如果系统没有安装VB,单独注册好像很难成功,这害的一些没有装VB的用户,为了这个小控件必须安装一次VB,这实在是划算不来,所以直接用API串口函数进行了封装...

      几年前我用VB开发了一个西门子PPI通信控件,由于VB开发的控件是标准的COM组件,所以想当然的认为VC、C#、Delphi等开发语言可以非常容易的使用。

      前段时间由于该控件基于微软的MSCOMM控件,这个控件如果系统没有安装VB,单独注册好像很难成功,这害的一些没有装VB的用户,为了这个小控件必须安装一次VB,这实在是划算不来,所以直接用API串口函数进行了封装改进,这样不仅效率提高了,并且再也不需要MSCOMM控件了。

      这一次,我不仅使该控件支持了浮点运算,并且在VC、C#(VB当然就不用多试了,以前就很好的支持)进行了兼容测试。

      一试问题就来了,没有改进之前的控件,由于C#封装性能甚好,还能使用,唯一不足的是,控件方法中如果不要求返回的参数前面没有添加ByVal参数,在C#中就转换为 ref ***,害的你还得专门定义临时变量进行传参。

      在VC中直接就不行,ReadData和WriteData等几个主要方法根本在VC中无法转换成对应函数,具体错误信息如下:

    // method 'ReadData' not emitted because of invalid return type or parameter type

    // method 'WriteData' not emitted because of invalid return type or parameter type

    // method 'PlcLogin' not emitted because of invalid return type or parameter type

    // method 'PlcRun' not emitted because of invalid return type or parameter type

    // method 'PlcStop' not emitted because of invalid return type or parameter type

      经过测试,最后发现VB函数中的byte和数组在VC中根本找不到合适的对应。

      由于控件中又新添加了浮点数的支持,所以对参数接口又增加了一层复杂性。突然想到微软的MSCOMM控件各语言肯定都能很好的支持,它的接口参数是怎样的定义的。我在VB、VC、C#分别试了一下,VB中和input和Output属性的类型就是Variant类型,在VC中是VARIANT,在C#中是Object。用Variant还有个好处,就是各种类型的数据都可以传输,没有必要在另外添加接口函数了。

      最后我定义的接口如下(主要接口):

    Public Function ReadData(ByVal lngAddr As Long, vData As Variant, Optional ByVal lngNum As Long = 1, Optional ByVal bytLen As PPILEN = PPI_B, Optional ByVal bytType As PPITYPE = PPI_V, Optional ByVal Addr As Long = 0) As Long
    
    Public Function WriteData(ByVal lngAddr As Long, ByVal vData As Variant, Optional ByVal lngNum As Long = 1, Optional ByVal bytLen As PPILEN = PPI_B, Optional ByVal bytType As PPITYPE = PPI_V, Optional ByVal Addr As Long = 0) As Long
    

      在VC中对应的接口如下:

    long ReadData(long lngAddr, VARIANT* vData, long lngNum, long bytLen, long bytType, long Addr);
    
    long WriteData(long lngAddr, const VARIANT& vData, long lngNum, long bytLen, long bytType, long Addr);
    

      在C#中的接口如下:

         public virtual int ReadData(int lngAddr, ref object vData);
    
         public virtual int ReadData(int lngAddr, ref object vData, int lngNum, PPILEN bytLen, PPITYPE bytType, int addr);
    
           public virtual int WriteData(int lngAddr, object vData);
    
       public virtual int WriteData(int lngAddr, object vData, int lngNum, PPILEN bytLen, PPITYPE bytType, int addr);
    

      以为这样定义就万事大吉了,事后一试我又错了,在C#中没有任何问题(看了微软还是在C#上下了很大的功夫),在VC简单的定义一个VARIANT变量直接传递给控件,VB控件老是报错,根本无法使用。后来想为什么MSCOMM控件可以,我的控件不可以。天杀的MSCOMM肯定是VC开发的,而我的控件是VB开发的,VB和C#的包容性都很强,而VC却高高在上不肯屈就。

      正一筹莫展准备放弃的时候,突然想到了以前用VC开发的OPC程序,上面有很多关于VARIANT的应用,一看就明白了,原来在VC中VARIANT的用法是有讲究的。

      下面我就详细说一下控件同样的接口在不同语言中如何使用。

    在VB中:

    Private Sub cmdReadData_Click()
    
        On Error GoTo ToExit '打开错误陷阱
    
        '------------------------------------------------
    
        Dim i As Long
    
        Dim bytType As Byte
    
        Dim lngRet As Long
    
        Dim lngData() As Long
    
        Dim fData() As Single
    
        Dim vData As Variant
    
        Select Case cmbType.ListIndex
    
        Case 0: bytType = PPI_I
    
        Case 1: bytType = PPI_Q
    
        Case 2: bytType = PPI_M
    
        Case 3: bytType = PPI_V
    
        Case 4: bytType = PPI_S
    
        Case 5: bytType = PPI_SM
    
        End Select
    
        S7_PPI1.FixAddr = cmbNo.ListIndex + 1
    
        lngRet = S7_PPI1.ReadData(Val(txtAddr), vData, Val(cmbNum.Text), Val(cmbLen.ListIndex), Val(bytType))
    
        If lngRet = 0 Then
    
            txtData = ""
    
            If cmbLen.ListIndex = 3 Then
    
                fData = vData
    
                For i = 1 To Val(cmbNum.Text)
    
                    txtData = txtData & Format(fData(i - 1), "0.00") & " "
    
                Next
    
            Else
    
                lngData = vData
    
                For i = 1 To Val(cmbNum.Text)
    
                    txtData = txtData & Format(lngData(i - 1), "0") & " "
    
                Next
    
            End If
    
        Else
    
            txtData = "Error"
    
        End If
    
        '------------------------------------------------
    
        Exit Sub
    
        '----------------
    
    ToExit:
    
        MsgBox Err.Description
    
    End Sub
    
    Private Sub cmdWriteData_Click()
    
        On Error GoTo ToExit '打开错误陷阱
    
        '------------------------------------------------
    
        Dim bytType As Byte
    
        Dim strData() As String
    
        Dim lngRet As Long
    
        Dim lngData(100) As Long
    
        Dim fData(100) As Single
    
        Dim i As Long
    
        Select Case cmbType.ListIndex
    
        Case 0: bytType = PPI_I
    
        Case 1: bytType = PPI_Q
    
        Case 2: bytType = PPI_M
    
        Case 3: bytType = PPI_V
    
        Case 4: bytType = PPI_S
    
        Case 5: bytType = PPI_SM
    
        End Select
    
        If Len(txtData) > 0 Then
    
            strData = Split(txtData, " ")
    
            If cmbLen.ListIndex = 3 Then
    
                For i = 0 To UBound(strData)
    
                    fData(i) = Val(strData(i))
    
                Next
    
                lngRet = S7_PPI1.WriteData(Val(txtAddr), fData, UBound(strData) + 1, Val(cmbLen.ListIndex), Val(bytType), cmbNo.ListIndex + 1)
    
            Else
    
                For i = 0 To UBound(strData)
    
                    lngData(i) = Val(strData(i))
    
                Next
    
                lngRet = S7_PPI1.WriteData(Val(txtAddr), lngData, UBound(strData) + 1, Val(cmbLen.ListIndex), Val(bytType), cmbNo.ListIndex + 1)
    
            End If
    
            If lngRet = 0 Then
    
                '
    
            Else
    
                txtData = "Error"
    
            End If
    
        End If
    
        '------------------------------------------------
    
        Exit Sub
    
        '----------------
    
    ToExit:
    
        MsgBox Err.Description
    
    End Sub
    


    在C#中:

    /// <summary>
    
            /// 读数据
    
            /// </summary>
    
            /// <param name="sender"></param>
    
            /// <param name="e"></param>
    
            private void btnRead_Click(object sender, EventArgs e)
    
            {
    
                int intAddr = int.Parse(txtFixAddr.Text);
    
                object vData = new object();
    
              
    
                /*
    
                [PPI_I] = &H81
    
                [PPI_Q] = &H82
    
                [PPI_M] = &H83
    
                [PPI_V] = &H84
    
                [PPI_S] = 4
    
                [PPI_SM] = 5
    
                */
    
                PPIV2.PPITYPE DataType= PPIV2.PPITYPE.PPI_V;
    
                switch (cmbDataType.SelectedIndex)  //数据类型
    
                {
    
                    case 0:
    
                        DataType = PPIV2.PPITYPE.PPI_I;
    
                        break;
    
                    case 1:
    
                        DataType = PPIV2.PPITYPE.PPI_Q;
    
                        break;
    
                    case 2:
    
                        DataType = PPIV2.PPITYPE.PPI_M;
    
                        break;
    
                    case 3:
    
                        DataType = PPIV2.PPITYPE.PPI_V;
    
                        break;
    
                    case 4:
    
                        DataType = PPIV2.PPITYPE.PPI_S;
    
                        break;
    
                    case 5:
    
                        DataType = PPIV2.PPITYPE.PPI_SM;
    
                        break;
    
                }
    
                if (axS7_PPI1.ReadData(int.Parse(txtDataAddr.Text), ref vData, cmbLen.SelectedIndex+1  , (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr) == 0)
    
                {
    
                    if (cmbDataMode.SelectedIndex == 3)
    
                    {
    
                        float[] fData = (float[])vData;
    
                        txtData.Text = "";
    
                        for (int i = 0; i < fData.Length; i++)
    
                        {
    
                            txtData.Text += fData[i].ToString("0.00") + " ";
    
                        }
    
                    }
    
                    else
    
                    {
    
                        Int32[] intData = (Int32[])vData;
    
                        txtData.Text = "";
    
                        for (int i = 0; i < intData.Length; i++)
    
                        {
    
                            txtData.Text += intData[i].ToString() + " ";
    
                        }
    
                    }
    
                }
    
                else
    
                {
    
                    txtData.Text = "ERROR";
    
                }
    
            }
    
     
    
            /// <summary>
    
            /// 写数据
    
            /// </summary>
    
            /// <param name="sender"></param>
    
            /// <param name="e"></param>
    
            private void btnWrite_Click(object sender, EventArgs e)
    
            {        
    
     
    
                int intAddr = int.Parse(txtFixAddr.Text);
    
                object vData = new object();
    
     
    
                /*
    
                [PPI_I] = &H81
    
                [PPI_Q] = &H82
    
                [PPI_M] = &H83
    
                [PPI_V] = &H84
    
                [PPI_S] = 4
    
                [PPI_SM] = 5
    
                */
    
                PPIV2.PPITYPE DataType = PPIV2.PPITYPE.PPI_V;
    
                switch (cmbDataType.SelectedIndex)  //数据类型
    
                {
    
                    case 0:
    
                        DataType = PPIV2.PPITYPE.PPI_I;
    
                        break;
    
                    case 1:
    
                        DataType = PPIV2.PPITYPE.PPI_Q;
    
                        break;
    
                    case 2:
    
                        DataType = PPIV2.PPITYPE.PPI_M;
    
                        break;
    
                    case 3:
    
                        DataType = PPIV2.PPITYPE.PPI_V;
    
                        break;
    
                    case 4:
    
                        DataType = PPIV2.PPITYPE.PPI_S;
    
                        break;
    
                    case 5:
    
                        DataType = PPIV2.PPITYPE.PPI_SM;
    
                        break;
    
                }
    
                long lngRet = 0;
    
                if (cmbDataMode.SelectedIndex == 3)
    
                {
    
                    float[] fData = new float[100];
    
                    fData[0] = float.Parse(txtData.Text);
    
                    lngRet = axS7_PPI1.WriteData(int.Parse(txtDataAddr.Text), fData, 1, (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr);
    
                }
    
                else
    
                {
    
                    Int32[] intData = new Int32[100];
    
                    intData[0] = Int32.Parse(txtData.Text);
    
                    lngRet = axS7_PPI1.WriteData(int.Parse(txtDataAddr.Text), intData, 1, (PPIV2.PPILEN)cmbDataMode.SelectedIndex, DataType, intAddr);
    
                }
    
                if (lngRet != 0)
    
                {
    
                    txtData.Text = "ERROR";
    
                }
    
            }
    


    在VC中:



    //读数据
    
    void CPPI_TestDlg::OnReadData()
    
    {
    
           //pCombo->GetLBText (pCombo->GetCurSel (), strType);
    
           long lngFixAddr=0,lngDataAddr=0;
    
           char strAddr[255];
    
           m_FixAddr.GetWindowText(strAddr,255);
    
           sscanf(strAddr,"%ld",&lngFixAddr);
    
          
    
           m_DataAddr.GetWindowText(strAddr,255);
    
           sscanf(strAddr,"%ld",&lngDataAddr);
    
        /*
    
           [PPI_I] = &H81
    
        [PPI_Q] = &H82
    
        [PPI_M] = &H83
    
        [PPI_V] = &H84
    
        [PPI_S] = 4
    
        [PPI_SM] = 5
    
           */
    
        long DataType;
    
           switch (m_DataType.GetCurSel())  //数据类型
    
           {
    
           case 0:
    
                  DataType=0x81; 
    
                  break;
    
           case 1:
    
                  DataType=0x82;
    
                  break;
    
           case 2:
    
                  DataType=0x83;
    
                  break;
    
           case 3:
    
                  DataType=0x84;
    
                  break;
    
           case 4:
    
                  DataType=0x4;
    
                  break;
    
           case 5:
    
                  DataType=0x5;
    
                  break;
    
           }
    
     
    
           long lngRet;
    
        VARIANT vData;
    
           VariantInit (&vData);
    
           if(m_DataMode.GetCurSel()==3)  //浮点数
    
           {
    
               vData.vt = VT_R4 | VT_ARRAY;
    
               vData.parray=SafeArrayCreateVector(VT_R4, 0, 255 );    
    
           }
    
           else
    
           {
    
               vData.vt = VT_I4 | VT_ARRAY;
    
               vData.parray=SafeArrayCreateVector(VT_I4, 0, 255 );     //SAFEARRAY vd;
    
           }   
    
           lngRet=m_PPI.ReadData(lngDataAddr,&vData,m_DataNum.GetCurSel()+1,m_DataMode.GetCurSel(),DataType,lngFixAddr);
    
           if(lngRet==0)
    
           {
    
                  CString strData;
    
                  if(m_DataMode.GetCurSel()==3)  //浮点数
    
                  {
    
                         float *fData;
    
                         SafeArrayAccessData(vData.parray, (void**)&fData );
    
                         for(int i=0;i<m_DataNum.GetCurSel()+1;i++)  //(int)vData.parray->cbElements
    
                         {
    
                            CString cData;
    
                            cData.Format("%04.2f ",fData[i]);
    
                            strData+= cData;
    
                         }
    
                         SafeArrayUnaccessData(vData.parray);
    
                  }
    
                  else
    
                  {
    
                         long *lngData;
    
                         SafeArrayAccessData(vData.parray, (void**)&lngData );
    
                         for(int i=0;i<m_DataNum.GetCurSel()+1;i++)  //(int)vData.parray->cbElements
    
                         {
    
                            CString cData;
    
                            cData.Format("%ld ",lngData[i]);
    
                            strData+= cData;
    
                         }
    
                         SafeArrayUnaccessData(vData.parray);
    
                  }
    
     
    
                  m_Data.SetWindowText(strData);
    
           }
    
           else
    
           {
    
            m_Data.SetWindowText(_T("ERROR"));
    
           }
    
           SafeArrayUnaccessData(vData.parray);
    
           SafeArrayDestroy(vData.parray);
    
        VariantClear(&vData);
    
    }
    
     
    
    //写数据
    
    void CPPI_TestDlg::OnWrite()
    
    {
    
           long lngFixAddr=0,lngDataAddr=0;
    
           char strAddr[255];
    
           m_FixAddr.GetWindowText(strAddr,255);
    
           sscanf(strAddr,"%ld",&lngFixAddr);
    
          
    
           m_DataAddr.GetWindowText(strAddr,255);
    
           sscanf(strAddr,"%ld",&lngDataAddr);
    
     
    
        long DataType;
    
           switch (m_DataType.GetCurSel())
    
           {
    
           case 0:
    
                  DataType=0x81;
    
                  break;
    
           case 1:
    
                  DataType=0x82;
    
                  break;
    
           case 2:
    
                  DataType=0x83;
    
                  break;
    
           case 3:
    
                  DataType=0x84;
    
                  break;
    
           case 4:
    
                  DataType=0x4;
    
                  break;
    
           case 5:
    
                  DataType=0x5;
    
                  break;
    
           }
    
           long lngRet;
    
        VARIANT vData;
    
           VariantInit (&vData);
    
           if(m_DataMode.GetCurSel()==3)  //浮点数
    
           {
    
               vData.vt = VT_R4 | VT_ARRAY;
    
               vData.parray=SafeArrayCreateVector(VT_R4, 0, 255 );
    
                 
    
                  float *fDatas,fData;
    
                  SafeArrayAccessData(vData.parray, (void**)&fDatas );
    
                  m_Data.GetWindowText(strAddr,255);
    
                  sscanf(strAddr,"%f",&fData);
    
                  fDatas[0]=fData;
    
                  SafeArrayUnaccessData(vData.parray);
    
           }
    
           else
    
           {
    
               vData.vt = VT_I4 | VT_ARRAY;
    
               vData.parray=SafeArrayCreateVector(VT_I4, 0, 255 );     //SAFEARRAY vd;
    
                 
    
                  long *lngDatas,lngData;
    
                  SafeArrayAccessData(vData.parray, (void**)&lngDatas );
    
                  m_Data.GetWindowText(strAddr,255);
    
                  sscanf(strAddr,"%ld",&lngData);
    
                  lngDatas[0]=lngData;
    
                  SafeArrayUnaccessData(vData.parray);
    
           }
    
     
    
        lngRet=m_PPI.WriteData(lngDataAddr,(const VARIANT &)vData,1,m_DataMode.GetCurSel(),DataType,lngFixAddr);
    
           if(lngRet!=0)
    
           {
    
                  m_Data.SetWindowText(_T("ERROR"));
    
           }
    
           SafeArrayUnaccessData(vData.parray);
    
           SafeArrayDestroy(vData.parray);
    
        VariantClear(&vData);
    
    }


    展开全文
  • vb:vbvariant blast)询问hapx档案以进行直系同源序列变异
  • dim tmpA (tmpA是一个控件的.Left,类型为Variant/single)实际数据为1234.05 dim tmpB as Long 当 tmpB=tmpA 后,tmpB的数据变成1234了,这就是数据类型不匹配造成的。...
    dim tmpA (tmpA是一个控件的.Left,类型为Variant/single)实际数据为1234.05
    

    dim tmpB as Long



    tmpB=tmpA

    后,tmpB的数据变成1234了,这就是数据类型不匹配造成的。
    展开全文
  • 在《VB/VBA,请让我点名表扬你》一文指出,立身于教育的Kemeny和Kurtz教授,以其宽广的胸怀赋予BASIC和其继任者宽容的做派。这种宽容,造就了VB的任性。这种任性,塑造了VB的简单。但是,很多人享用完这种简单,...

    前言

    在《VB/VBA,请让我点名表扬你 》一文中指出,立身于教育的Kemeny和Kurtz教授,以其宽广的胸怀赋予BASIC和其继任者宽容的做派。这种宽容,造就了VB的任性。这种任性,塑造了VB的简单。但是,很多人享用完这种简单,开始会那么一拳两脚后,就觉得VB很Low,指责这也不行那也不好。本篇,就给大家伙儿拾掇拾掇,一起品品VB(含VB/VBA/VBS)的”LOW”。

    一、VB的原野,处处都是Variant的小花

    1、有种懒叫VB,你不懂!

    不声明变量,就可随意而为,在其他强类型的语言里简直不可想象。但在VB里,就是这么随意,可以少敲键盘!这在遥远的BASIC时代,是先进。即便现在,也是洒脱。能写出潇洒的,大抵也只有VB了吧。

    虽不推荐,但的确可以这么干!其实这背后,就是VB变量的隐式声明,用的类型正好就是Variant。一个变量名,可同时在VB支持的类型范围内,随意转换。Variant就像1个大容器,包揽所有类型。

    2、开起我心爱的Excel, Variant轻轻地来了。

    单元格放文本,放数字,还可放公式,哪里顺眼放哪里!点一点,拖一拖,都有回应。单元格的好使,将任性演绎的淋淋尽致。在事件驱动下,将消息主导下的人机交互,雕刻的犹如身临其境。

    这背后,正是Variant类型的功劳。Excel内部哪里没有Variant?单元格的Value属性,公式参数,事件参数,可以说有便捷的地方就有Variant,Variant就是便捷的垫脚石。

    3、VBS的脚本,在ASP上挥洒自如。

    VBS应该算是Variant的重病患者,在性能需求不高的交互页面上,各种姿态随你选。洋洋洒洒,能屈能伸,将VB的吊儿郎当玩耍的信手拈来。

    4、系统的基石里,Variant如影随形。

    熟悉Shell32的朋友,肯定知道Application对象下的大部分参数都是Variant的,典型的当数ShellExecute方法。这只是系统中Variant现身的冰山一角,类似的案例非常多,读者朋友们可自行去探索。

    我们知道,COM是Windows系统的基石,COM要想在二进制上跨语言,首要解决的就是兼容各大语言的变量类型。Variant当仁不让的站了出来,这也是VB身为COM语言的有力证据之一,同时也是VB值得深挖的佐证。

    二、自古慈母多败儿,Variant驼背的宠爱,换来的却是声声怨恨。

    1、Variant本身就告诉用户,便捷与性能不能兼得。

    Excel数据处理,堪称巨坑,比起Python,速度简直不要太弱!不知受了什么启发,很多用户像发现了新大陆,昔日的土地仿佛充满了荆棘。于是像负气的孩子,奔走相告间,充满了怨恨。

    VBA解释执行时,用不上后端优化器,你要Variant如何快的起来。享受了方便,就不要抱怨Excel单元格遍历起来很慢,天下哪有两头都占的理!更何况,VB在嘻皮笑脸的背后,也有一本正经的严肃。

    2、Variant本身就告诉用户,性能提升的办法多了去,只是不会送货上门。

    单元格里Variant困扰,让很多试图采用数据库方式的人,屡屡受挫。于是,Excel表单不如数据库,Excel数据超过N行后就是垃圾,Excel数据分析不如Python,总之Excel亏欠人们很多。

    孰不知,Variant也可以整整齐齐。虽然VBA用不上后端优化器,但Excel有数据类型扫描引擎啊!在该引擎的作用下,透视表的美简直不可方物。为何世人只看嬉笑怒骂的酸爽,却不扭头面壁思过,来一份踏实!

    三、Variant的真身,竟然是通票

    1、欲戴皇冠,必承其重。

    Variant造就了VB的任性,也塑造了VB的易用性。但在VB轻描淡写之下,立在其身后的,却是一个长达16字节的庞然大物。很多人也正因为这个,觉得Variant类型比较费内存,运行起来肯定会比较慢,但事实远非如此简单。

    这个16字节里,其实是一个结构体,这是VB众多隐身衣之一。翻译成VB的结构,大概是这个样子的:

    Public Type Variant_

    vt 'VARTYPE [2]指明Vars中有效成员,也即真实的数据类型

    wReserved1 'WORD [2]系统保留

    wReserved2 'WORD [2]系统保留

    wReserved3 'WORD [2]系统保留

    Var 'Vars [8]具体存储数据或数据地址

    End Type

    首成员指明Variant的真实数据类型,尾成员存储数据或数据指针(看指针开始显形了)。

    2、有些事,竟只有Variant能够周旋。

    Variant不仅在与系统COM组件交互时有用,对于深入VB而言,也是必经之路。它的尾成员,将VB的数据进一步划分为数据类型和指针类型,为我们揭开VB的层层伪装提供了入口。

    成熟于32位时代的VB,在64位机器面前受尽嘲讽。缺乏LongLong类型也一直为不知所以然的人所津津乐道,偌大的Variant杵在面前,他们却视而不见。Variant里隐藏的Decimal,有这种洪荒之兽镇宅,拿捏宇宙都不是问题,一区区8字节却难倒诸多英雄好汉。再不然,还有字节数组啊,什么样的妖孽装不下?

    四、善用Variant,方能通行无阻

    1、Variant的任性与犀利并存,谁说Variant就慢了。

    在Variant首尾两个成员的帮助下,VB的后端优化器,可以将该类型还原为真实的类型。所以,Variant的确费内存,但在编译后,与性能却没有多大关系。

    同样在Excel中,扫描引擎会统计表的前几行的数据类型,来确定各列的数据类型。这为Excel表的数据库应用提供了基础,甚至无需代码,就可以利用SQL语句进行增删改查。跟数据库引擎比数据处理速度,谁闲得慌么!

    2、Variant传参,妙笔生花。

    Variant在VB中真正的妙笔,在于参数的传递。任何类型都可以传递给Variant,这为VB建造灵活且复杂的程序提供了极大的方便。

    在VB中自定义结构体容易,但想要在函数中传递结构体,就没那么容易了。具体原因留给读者自己思考。此时,Variant大吼一声,让我来。意不意外?惊不惊喜?

    在VB中ParamArray关键字,想必大家都很熟悉,给函数提供不确定个数的参数时,十分有用。但这货必须要求是Variant类型。如果结合Variant结构,则可以设计出非常巧妙的程序。后面要跟大家分享的函数指针就跟这儿有关。

    五、性能好的,却不一定是适合的

    对于VB而言,有Office这个无敌手的大前端在,让潜在的替代都显得黯然失色。所以,要想在Office的地界上风生水起,熟悉Office的操作是不可忽视的基础,否则闹出笑话就只能贻笑大方了。Office中随处可见的Variant,时时提醒着世人,不是任何地方都需要极致的性能,人机交互的便捷和高效性能的平衡,往往更重要。

    <本篇作为VB内存管理系列的引子,后面会陆续分享变量、指针、句柄、消息等,是进入VB高阶开发前,必要的准备。欢迎大家持续关注!>

    展开全文
  • dim tmpA (tmpA是一个控件的.Left,类型为Variant/single)实际数据为1234.05dim tmpB as Long当tmpB=tmpA后,tmpB的数据变成1234了,这就是数据类型不匹配造成的。
  • 单精度(Single)和双精度(Double)数据类型是VB6里的两种浮点类型;它们被用来保存带有小数的数值。小数的位数可以变化(所以名字叫"浮点"),因为小数点的位置可以变化。例如: 1.23456 12.3456 123.456...
  • double类型的精度确实是可定义类型...double反之而且Decimal 数据类型只能在 Variant中使用,也就是说,不能声明一变量为 Decimal 的类型上面有高手给了你利用Decimal 数据类型解决例题的办法。 另外如果需要,还可...
  • VB几种函数参数传递方法,Variant,数组,Optional,ParamArray  一) 过程的参数被缺省为具有 Variant 数据类型。  1)ByRef按 地址传递参数在 VB 是缺省的  按地址传递参数后,过程返回的也是地址,函数...
  • VB6调用C++DLL: ``` Dim sndData‘缺省类型,自动默认为Variant/empty sndData=data’data为一个二进制数组,赋值结束后sndData的类型自动变为Variant/byte(0 to 65) Result=Msocket.sendto(sndData)'C++...
  • VB中各种数据类型转换函数 1. 各种进制转换函数 一般的数据进制包括十进制,二进制,十六进制.十进制就是我们日常生活用到的数据进制,因此也是我们最熟悉和清楚的;二进制是计算机的基础进制,主要是因为便于用...
  • Variant输入出参数,ocx传递byte数组,safearray使用方法,vc写ocx在vb下调用
  • C++DLL接口是Variant型。 VB6定义缺省变量可以正常传入,VB2012就会报错。 Object到底还算不算Variant类型?...VB2012到底传入一个什么类型,可以让C++Variant类型参数正常接收,不报类型不一致错误?
  • 问下 :自己写的com,其中一个接口方法返回一个variant类型的值,在.net如何接收啊 如题 ! __________________________________________________________________________ 学习,帮你顶吧 ____________________...
  • VB中recordset的用法

    千次阅读 2015-08-12 10:14:16
    Set Rs = Server.CreateObject("ADODB.Recordset") Rs.Open Source, ActiveConnection, CursorType...此 Variant 是为一个有效的 Command 对象变量名称、SQL 陈述式、数据表名称、已存的过程调用,或是一个保存的 Reco
  • 85. BASIC和LotusScriptVariant

    千次阅读 2014-12-02 11:09:39
    缘起最近我回看以前记的关于Notes的笔记,发现在Notes bugs类别下,两条编号间隔一的竟然是相差无几的内容。... when an item of ColumnValues is an array, is assigned to a variant or passed as an argument
  • VB中Http请求测试

    2021-03-10 16:42:42
    最近帮助公司维护一个VB的项目,需要用到Http请求与Java服务进行通信,这里记录下VB端的实现和代码。 1.1页面 1.2代码 'POST发送 Private Sub button1_Click() Dim str As String str = Text3.Text Dim ...
  • <p>I can sample a VBScript to take advantage of functions from .dll files. ... <p>Please help to complete this function. This FalcoNetworkLib.dll is a library to send & get data from hardware....
  • VARIANT 类型说明

    千次阅读 2017-06-15 18:12:16
    string CAdoConnection::VariantToString(const _variant_t &var) { string strValue; TCHAR szValue[1024] = {0x00}; switch (var.vt) { case VT_BSTR://字符串 case VT_LPSTR://字符串 case VT_LPWSTR://...
  • vb中如何定义变量

    千次阅读 2019-07-21 13:41:27
    dima,b as Integer 表明: 定义了一个变体型变量a定义了一个整型变量bDim定义局部变量还可以用:Static Private Public等 声明变量的格式为:<Public|Private|Dim|Static >...四个选项选择...
  • 双精度型 Double 8 # 货币型 Currency 8 @ 日期型 Data 8 对象型 Object 4 字符型 String 与字符长度有关 $ 变体型 Variant 按需分配 三、VB中的变量声明: Dim a As Integer -说明a为整型变量 Dim b As String -...
  • VB 清除数组全部元素的值

    千次阅读 2019-06-12 11:41:58
    固定 Variant 数组 将每个元素设为 Empty。 用户定义类型的数组 将每个元素作为单独的变量来设置。 对象数组 将每个元素设为特定值 Nothing。 Erase 释放动态数组所使用的内存。在下次引用该动态数组之前,程序...
  • vb函数常用的函数

    2019-04-27 22:43:15
    VB程序逆向常用的函数 数据类型转换: a) __vbaI2Str 将一个字符串转为8 位(1个字节)的数值形式(范围在 0 至 255 之间) 或2 个字节的数值形式(范围在 -32,768 到 32,767 之间)。 b)__vbaI4Str 将一个字符串转为长...
  • 在近期工作的过程因为需要C++编写的ActiveX控件需要被C#调用,所以频繁地使用到Variant类型,而SafeArray的各种类型又是用枚举量标识的,所以需要经常查阅,就将MSDN的文档搬运至此
  • 简要分析VB6.0和VB.NET区别

    千次阅读 2019-05-07 10:27:54
    现在随着VB.NET的发展,大部分人都放弃使用VB6.0而选择VB.NET,下面我们就来研究一下VB6.0和VB.NET的区别。VB.NET是微软公司在2002年推出的一种开发基于.Net平台应用程序的开发语言,也是微软公司极力推荐的一种开发...
  • VB实现List集合

    2021-07-25 22:50:17
    Option Explicit '***********************List集合***************************** Private Declare Function SafeArrayGetDim ...Private mArray() As Variant '添加元素 Public Sub Add(E As Variant) Dim Size.
  • VB 的基本数据类型

    万次阅读 2017-06-11 10:12:31
    VB基本数据类型 VB 6.O提供的基本数据类型主要有:字符型数据、数值型数据、货币类型、字节类型、布尔类型、日期类型、通用类型、无符号类型、对象类型等9种数据类型。 1.字符型数据 字符型数据(String)用以定义...
  • VB常见错误和难点分析

    千次阅读 2018-09-10 19:41:42
    1.在选择结构缺少配对的结束语句 对多行式的If块语句,应有配对的End If语句结束。否则,在运行时系统会显示”块 If没有End If”的编译错误。同样对Select Case语句也应有与其相对应的End Select语句。 2....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,126
精华内容 2,850
关键字:

vb中variant