2014-12-29 73 views
2

我已經編寫了有關TableDef和Field屬性的代碼。這並不難,它只是包含循環遍歷Field.Properties集合並一路做一定數量的錯誤檢查。 Property.Name,Property.Type和Property.Value產生我們需要的一切。MS Access Control Property.Type沒有意義

問題:我剛剛寫了一些代碼來爲窗體和報表控件執行相同類型的屬性枚舉。屬性名稱和值通過罰款,但.Type不正確。舉個例子:

Public Sub TestPropTypes() 
Dim dbs As DAO.Database 

    Set dbs = CurrentDb() 

    Dim td As TableDef 
    Dim fld As DAO.Field 

    Set td = dbs.TableDefs("CalendarEvent_") 
    Set fld = td.Fields("EventDescription") 
    PrintObjectProps fld 

    Dim f As Form 
    Dim c As Control 

    DoCmd.OpenForm "fmCalendarDates", acDesign 
    Set f = Forms!fmCalendarDates 
    Set c = f.Controls("Label7") 
    PrintObjectProps c 
End Sub 

Private Sub PrintObjectProps(c As Object, Optional RecursionDepth As Integer = 0) 
Dim ExistingProperty As DAO.Property 
Dim PropCount As Integer 
Dim GotValue As Boolean 
Dim v As Variant 

    Debug.Print c.Name 

    For Each ExistingProperty In c.Properties 
     If PropCount > 12 Then Exit Sub 

     GotValue = True 
     On Error Resume Next 
     v = ExistingProperty.Value 
     If Err.number <> 0 Then GotValue = False 
     On Error GoTo 0 

     If GotValue Then 
      Debug.Print " " & ExistingProperty.Name & " " _ 
       & GetFieldDDLTypeName(ExistingProperty.Type) & "(" & ExistingProperty.Type & ") " _ 
       & xf.Gen.dq(CStr(ExistingProperty.Value)) 
     End If 

     PropCount = PropCount + 1 
    Next 
End Sub 

Public Function GetFieldDDLTypeName(FieldType As DAO.DataTypeEnum) As String 
Dim rtnStr As String 
    ' as per: http://allenbrowne.com/ser-49.html 

    Select Case FieldType 
     Case dbBoolean: rtnStr = "YESNO" 
     Case dbByte: rtnStr = "BYTE" 
     Case dbInteger: rtnStr = "SHORT" 
     Case dbLong: rtnStr = "LONG" 
     Case dbCurrency: rtnStr = "CURRENCY" 
     Case dbSingle: rtnStr = "SINGLE" 
     Case dbDouble: rtnStr = "DOUBLE" 
     Case dbDate: rtnStr = "DATETIME" 
     Case dbBinary: rtnStr = "BINARY" 
     Case dbText: rtnStr = "TEXT" 
     Case dbLongBinary: rtnStr = "LONGBINARY" 
     Case dbMemo: rtnStr = "MEMO" 
     Case DBGuid: rtnStr = "GUID" 
    End Select 

    GetFieldDDLTypeName = rtnStr 
End Function 

產量:

TestPropTypes 
EventDescription 
    Attributes LONG(4) "2" 
    CollatingOrder SHORT(3) "1033" 
    Type SHORT(3) "10" 
    Name MEMO(12) "EventDescription" 
    OrdinalPosition SHORT(3) "2" 
    Size LONG(4) "100" 
    SourceField MEMO(12) "EventDescription" 
    SourceTable MEMO(12) "CalendarEvent_" 
    DataUpdatable YESNO(1) "False" 
    DefaultValue MEMO(12) "" 
Label7 
    EventProcPrefix DATETIME(8) "Label7" 
    Name DATETIME(8) "Label7" 
    ControlType BYTE(2) "100" 
    Caption DATETIME(8) "Description" 
    Visible LONGBINARY(11) "True" 
    Width BYTE(2) "1875" 
    Height BYTE(2) "285" 
    Top BYTE(2) "425" 
    Left BYTE(2) "1048" 
    BackStyle BYTE(2) "0" 
    BackColor SHORT(3) "16777215" 
    BorderStyle BYTE(2) "0" 
    OldBorderStyle BYTE(2) "0" 

所以你可以看到的第一組,從在的TableDef領域,產生了一種我們所期待的結果。

第二組使用完全相同的呈現代碼來自窗體上的控件。所有MEMO屬性都以DATETIME的形式出現,所有YESNO如LONGBINARY等。它至少是一致的,我可以推斷出類型轉換並編寫轉換算法。我認爲它可能首先使用ADO值(因爲YESNO是11),但是與其他ADO值沒有一致性,並且我們也明確使用DAO對象,所以沒有任何意義。

這是不一致的,我想制定一些合理的解決方案。 有沒有人遇到過這個?

在Access 2003和2007上測試過,所以我確信它在我的Access版本中不是一個奇怪的錯誤。這是一個Access 2003格式的數據庫,所以沒有擴展類型在工作中拋出扳手。

編輯:問題解決感謝HansUp。現在我們正在檢查表/字段與表單/報表屬性是否使用不同的返回值。我提供這樣的:

Public Sub TestPropTypes1() 
Dim prop As DAO.Property 
Dim dbs As DAO.Database 
Set dbs = CurrentDb() 

    DoCmd.OpenForm "fmCalendarDates", acDesign 

    Debug.Print "Property", "Value", "varType(.Value)", ".Type" 
    Debug.Print 

    Set prop = dbs.TableDefs("CalendarEvent_").Fields("EventDate").Properties("Name") 
    Debug.Print prop.Name, prop.Value, varType(prop.Value), prop.Type 

    Set prop = dbs.TableDefs("CalendarEvent_").Fields("EventDate").Properties("Required") 
    Debug.Print prop.Name, prop.Value, varType(prop.Value), prop.Type 

    Set prop = Forms!fmCalendarDates!Label7.Properties("Name") 
    Debug.Print prop.Name, prop.Value, varType(prop.Value), prop.Type 

    Set prop = Forms!fmCalendarDates!Label7.Properties("Visible") 
    Debug.Print prop.Name, prop.Value, varType(prop.Value), prop.Type 
End Sub 

產生

TestPropTypes1 
Property  Value   vartype(.Value) .Type 
Name   EventDate  8    12 
Required  False   11    1 
Name   Label7   8    8 
Visible  True   11    11 

這將有力地表明的TableDef字段屬性確實使用了DAO.DataTypeEnum類型,而表單屬性似乎得到VBA.VbVarType回報。 例如,該字段的Required屬性返回與VbVarType爲NULL相對應的類型,而它是YesNo的DataTypeEnum。

注prop.Type和VARTYPE(prop.Value)之間的細微差別

雖然我們可以使用VARTYPE(prop.value),這通常被認爲是不好的做法,因爲該類型可能取決於內容值(例如Null),而.Type是權威元數據。在這種系統屬性的情況下,這些值可能表現良好,並且可能沒有實際區別。

真正令人驚訝的是參考資料沒有提到這個問題。

回答

1

評估屬性時使用VBA.VbVarType枚舉Type

您的代碼將房產的Type視爲DAO.DataTypeEnum的成員。這會導致代碼錯誤地翻譯Type

其實這不是一個只出現在窗體和報表控件中的問題。您的表格的字段屬性存在相同的問題。例如,輸出採樣不正確地識別該字段的Name屬性作爲備忘錄類型:

Name MEMO(12) "EventDescription" 

但是字段的Name屬性是變體,其亞型是字符串。

? CurrentDb.TableDefs("tblFoo").Fields("long_text").Properties("Name").Type 
12 
? VBA.VbVarType.vbVariant 
12 
' this is the WRONG translation ... 
? DAO.DataTypeEnum.dbMemo 
12 

如果你的目標是把酒店的Type以人性化的文字,考慮TypeName()功能:

? TypeName(CurrentDb.TableDefs("tblFoo").Fields("long_text").Properties("Name").Value) 
String 

如果這一建議是不能接受的,您可以創建自定義函數來翻譯Type到你想要的文字。但是,將Type轉換爲DDL字段數據類型名稱是IMO的錯誤方法。

+0

謝謝一堆,那當然是!雖然我不同意你答案的最後部分。我測試了一下,然後用測試結果編輯問題。 –

相關問題