只有在公共对象模块中定义的用户定义类型才能被强制转换为变量或从变量强制转移或传递给后期绑定函数

时间:2017-11-02 20:23:03

标签: vba excel-vba compiler-errors excel

我正在尝试创建一个结构,我可以用它来分隔记录的各个元素,以便使用它们的组件。每个记录由记录号,组,分区,类别和5个整数代码组成,这些代码将根据其组,分区和类别用于各种操作。每当我尝试将RecordType传递给我的ArrayList时,我都会收到此问题标题中所述的错误。我曾尝试查看有此错误的其他问题,但没有一个答案似乎有效。我已经尝试为RecordType创建一个单独的类,但它说它不能用公共类类型完成。以下是我要分离和使用的数据:

65f8|gh|l1|9k|985|8437|7894|9495|3730|
4287|gh|w1|uk|7341|5638|7715|8906|698|
3s89|jk|w1|h7|225|487|2013|4328|4066|
62l5|lo|r5|9k|5103|9879|3448|2921|7581|
486p|lo|r5|uk|6882|9879|2672|1015|3160|
a597|lo|r6|m9|385|6915|3615|9195|9817|
1m36|hu|k8|h7|656|8064|3852|9110|9858|

这是我写的代码。注释是我用来测试excel中代码的某些部分的循环。

Type RecordType
    number As String
    group As String
    div As String
    cat As String
    code1 As Integer
    code2 As Integer
    code3 As Integer
    code4 As Integer
    code5 As Integer
End Type

Sub ProgramOne()


Dim fileName As String, textData As String, fileLine As String, rowList() As String, numOfRecords As Integer, someString As String
Dim rowNum As Integer, colNum As Integer, counter As Integer, counter2 As Integer, groupCount As Integer, divCount As Integer, catCount As Integer
Dim groupBool As Boolean, catBool As Boolean, divBool As Boolean, groupList As Object, divList As Object, catList As Object

Set groupList = CreateObject("System.Collections.ArrayList")
Set divList = CreateObject("System.Collections.ArrayList")
Set catList = CreateObject("System.Collections.ArrayList")

fileName = "/Users/Ricky/Desktop/project1Data.txt"
Open fileName For Input As #1
rowNum = 1

Dim records As Object
Set records = CreateObject("System.Collections.ArrayList")
Dim placeholder As RecordType

Do Until EOF(1)
    numOfRecords = numOfRecords + 1
    Line Input #1, fileLine
    rowList = Split(fileLine, "|")

    placeholder.number = rowList(0)
    placeholder.group = rowList(1)
    placeholder.div = rowList(2)
    placeholder.cat = rowList(3)
    placeholder.code1 = rowList(4)
    placeholder.code2 = rowList(5)
    placeholder.code3 = rowList(6)
    placeholder.code4 = rowList(7)
    placeholder.code5 = rowList(8)

    records.Add (placeholder)
Loop

'Dim counter2 As Integer
'counter2 = 2
'    For x = 0 To UBound(records) - LBound(records)
'        Cells(counter2, 1) = records(x).group
'        Cells(counter2, 2) = records(x).div
'        counter2 = counter2 + 1
'    Next

Close #1

'For x = 0 To UBound(records) - LBound(records)

    divBool = False
    catBool = False

groupCount = 0
divCount = 0
catCount = 0
'Dim GroupName As Variant

'For Each GroupName In groupList
'    groupBool = False
'    For num = 0 To UBound(records) - LBound(records)
'        If CStr(records(num).group) = CStr(GroupName) Then
'            groupBool = True
'        End If
'        If Not groupBool Then
'            groupCount = groupCount + 1
'            groupList(groupCount) = records(num).group
'        End If
'    Next num
'Next GroupName
counter = 0
counter2 = 0
For Each GroupName In records
    For Each GroupName2 In groupList
        If records(counter).group = groupList(counter2) Then
            groupBool = True
        End If
        counter2 = counter2 + 1
    Next GroupName2
    If groupBool = False Then

Next GroupName

Cells(1, 1) = "Number of records: " & numOfRecords
Cells(1, 2) = "Number of Groups: " & groupCount
Cells(2, 1) = "records index: " & UBound(records) - LBound(records)
counter = 0
'For Each GroupName In groupList
'    Cells(3, counter) = GroupName
'    counter = counter + 1
'Next GroupName
End Sub

2 个答案:

答案 0 :(得分:4)

添加一个新的类模块,将其命名为Record,将Type移到其中,使其成为Private,然后声明该类型的私有字段,并公开{{每个成员1}}和Property Get

Property Let

现在使用该类的实例,它应该可以正常工作。

要获得额外的炫酷因素,请移除+导出类模块,在记事本中打开它,并将其Option Explicit Private Type TRecord Number As String Group As String Division As String Category As String Codes(1 To 5) As Long End Type Private this As TRecord Public Property Get Number() As String Number = this.Number End Property Public Property Let Number(ByVal value As String) this.Number = value End Property Public Property Get Group() As String Group = this.Group End Property Public Property Let Group(ByVal value As String) this.Group = value End Property Public Property Get Division() As String Division = this.Division End Property Public Property Let Division(ByVal value As String) this.Division = value End Property Public Property Get Category() As String Category = this.Category End Property Public Property Let Category(ByVal value As String) this.Category = value End Property Public Property Get Code(ByVal index As Long) As Long Code = this.Codes(index) End Property Public Property Let Code(ByVal index As Long, ByVal value As Long) this.Codes(index) = value End Property 属性设置为VB_PredeclaredId。保存并重新导入模块:现在您的类有一个默认实例,您可以使用工厂方法

True

现在读者循环可能如下所示:

Public Function Create(ByVal pNumber As String, ByVal pGroup As String, ByVal pDivision As String, ByVal pCategory As String, ParamArray pCodes As Variant) As Record
    With New Record
        .Number = pNumber
        .Group = pGroup
        .Division = pDivision
        .Category = pCategory

        'todo assert number of parameters to prevent out-of-bounds error
        Dim i As Long
        For i = LBound(pCodes) To UBound(pCodes)
            .Code(i) = pCodes(i)
        Next

        Set Create = .Self
    End with
End Function

Public Property Get Self() As Record
    Set Self = Me
End Property

请注意,类默认实例 可以被滥用以保持全局状态(例如,某些人使用Do Until EOF(1) numOfRecords = numOfRecords + 1 Line Input #1, fileLine rowList = Split(fileLine, "|") records.Add Record.Create(rowList(0), rowList(1), rowList(2), rowList(3), rowList(4), rowList(5), rowList(6), rowList(7), rowList(8)) Loop 的默认实例的方式)。这并不意味着他们应该。使用属于类型而不是实例的“静态”方法的默认实例,你会做得很好。

结合界面,你甚至可以模拟不变性,但我认为你不需要去那里。

答案 1 :(得分:1)

使用一个类,将其命名为cRecord

Option Explicit

Private Type RecordType
    number As String
    group As String
    div As String
    cat As String
    code1 As Integer
    code2 As Integer
    code3 As Integer
    code4 As Integer
    code5 As Integer
End Type

Dim mElement As RecordType

Property Let number(nval As String)
    mElement.number = nval
End Property

Property Let group(nval As String)
    mElement.group = nval
End Property

Property Let div(nval As String)
    mElement.div = nval
End Property

Property Let cat(nval As String)
    mElement.cat = nval
End Property
Property Let code1(nval As String)
    mElement.code1 = nval
End Property

Property Let code2(nval As String)
    mElement.code2 = nval
End Property

Property Let code3(nval As String)
    mElement.code3 = nval
End Property

Property Let code4(nval As String)
    mElement.code4 = nval
End Property

Property Let code5(nval As String)
    mElement.code5 = nval
End Property

然后将代码更改为

Dim placeholder As cRecord
Do Until EOF(1)
    numOfRecords = numOfRecords + 1
    Line Input #1, fileLine
    rowList = Split(fileLine, "|")
    Set placeholder = New cRecord
    placeholder.number = rowList(0)
    placeholder.group = rowList(1)
    placeholder.div = rowList(2)
    placeholder.cat = rowList(3)
    placeholder.code1 = rowList(4)
    placeholder.code2 = rowList(5)
    placeholder.code3 = rowList(6)
    placeholder.code4 = rowList(7)
    placeholder.code5 = rowList(8)

    records.Add placeholder
Loop`