Skip to content

Instantly share code, notes, and snippets.

@KenjiOhtsuka
Created October 25, 2013 01:41
Show Gist options
  • Save KenjiOhtsuka/7148201 to your computer and use it in GitHub Desktop.
Save KenjiOhtsuka/7148201 to your computer and use it in GitHub Desktop.
Export Table definitions from Micfosoft Office Access file. アクセスのファイルからテーブル定義をエクスポートするコード。
' 参照設定: Microsoft DAO 3.6 Object Library
Option Explicit
Private Const startingRowNumber = 5
Enum ColumnNumber
TableName = 1
TableDescription = 2
Caption = 2
PrimaryKey = 3
FieldName = 4
DataType = 5
Power = 6
DecimalPlace = 7
Required = 8
DefaultValue = 9
Memo = 10
Index = 11
IndexFieldName = 8
IndexUnique = 9
LinkDatabaseHeader = 2
LinkDatabase = 3
LinkSourceTableHeader = 2
LinkSourceTable = 3
End Enum
Public Sub GetTableDefinitions()
' choose a .mdb file and get the file name
Dim xlAPP As Application
Set xlAPP = Application
' get .mdb file path
Dim strFileName As String
strFileName = xlAPP.GetOpenFilename("Access Database (*.mdb),*.mdb", , _
"Select Access Database")
If StrConv(strFileName, vbUpperCase) = "FALSE" Then Exit Sub
' record file name
Cells(1, 1).Value = strFileName
' initialize .xls sheet
Rows("3:65536").ClearContents
' get database
Dim db As DAO.Database
Set db = OpenDatabase(strFileName)
' Variables used in loop
Dim counterRowNumber As Integer ' Current Row Number in the sheet
counterRowNumber = startingRowNumber
Dim topRowOfCurrentTable As Integer
Dim tempTable As DAO.TableDef
Dim tempField As DAO.Field
Dim tempProperty As DAO.Property
Dim tempIndex As DAO.Index
Dim tempValue As String
Dim tempValue_1 As String
Dim tempValue_2 As String
Dim counterInt As Integer
Dim counterInt_1 As Integer
Dim primaryKeys() As String
Dim primaryKeyExists As Boolean
Dim stringItems() As String
For Each tempTable In db.TableDefs
' avoid linked table and system table
If Left(tempTable.Name, 4) <> "MSys" Then
If ((tempTable.Attributes And dbAttachedTable) <> dbAttachedTable) Then
topRowOfCurrentTable = counterRowNumber
' record Table ID and Table Name
Cells(counterRowNumber, ColumnNumber.TableName).Value = tempTable.Name
For Each tempProperty In tempTable.Properties
Select Case tempProperty.Name
Case "Description"
tempValue = tempProperty.Value
' convert 半角片仮名 to 全角片仮名
tempValue = ConvFullHalf(tempValue, VbStrConv.vbWide)
Cells(counterRowNumber, ColumnNumber.TableDescription).Value = tempValue
End Select
Next
counterRowNumber = counterRowNumber + 1
' start recording field properties
For Each tempField In tempTable.Fields
tempValue = tempField.Name
Cells(counterRowNumber, ColumnNumber.FieldName).Value = tempValue
tempValue_1 = ""
For Each tempProperty In tempField.Properties
Select Case tempProperty.Name
Case "Caption": ' 標題
tempValue = CStr(tempProperty.Value)
' convert 半角片仮名 to 全角片仮名
tempValue = ConvFullHalf(tempValue, VbStrConv.vbWide)
Cells(counterRowNumber, ColumnNumber.Caption).Value = tempValue
Case "Required": ' 値要求
If tempProperty.Value Then
Cells(counterRowNumber, ColumnNumber.Required).Value = "不可"
End If
Case "DefaultValue": ' 規定値
tempValue = CStr(tempProperty.Value)
Select Case tempValue
Case "Date()", "Now ()", "Time()"
tempValue = "SYSDATE"
End Select
Cells(counterRowNumber, ColumnNumber.DefaultValue).Value = "'" & tempValue
Case "Format", "ValidationRule", "InputMask"
tempValue = tempProperty.Value
' modify data
If tempProperty.Name = "Format" Then
tempValue = Replace(tempValue, "yyyy/mm/dd", "yyyy/MM/dd")
tempValue = "'" & tempValue & "'"
End If
If tempProperty.Name = "InputMask" Then
tempValue = "'" & tempValue & "'"
End If
' record
If Cells(counterRowNumber, ColumnNumber.Memo).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Memo).Value = "'" & tempValue
Else
Cells(counterRowNumber, ColumnNumber.Memo).Value = _
Cells(counterRowNumber, ColumnNumber.Memo).Value & ", " & tempValue
End If
Case "RowSourceType"
If tempProperty.Value = "Value List" Then
tempValue = tempField.Properties("RowSource").Value ' record
If Cells(counterRowNumber, ColumnNumber.Memo).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Memo).Value = "'" & tempValue
Else
Cells(counterRowNumber, ColumnNumber.Memo).Value = _
Cells(counterRowNumber, ColumnNumber.Memo).Value & ", " & tempValue
End If
End If
Case "Description" ' 備考
tempValue_1 = tempProperty.Value
Case Else:
tempValue = CStr(tempProperty.Name)
Cells(counterRowNumber, ColumnNumber.Memo + 1).Value = _
Cells(counterRowNumber, ColumnNumber.Memo + 1).Value & ", " & CStr(tempProperty.Name)
End Select
Next
' add 備考 to the last of Memo field
If tempValue_1 <> "" Then
If Cells(counterRowNumber, ColumnNumber.Memo).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Memo).Value = "'" & tempValue_1
Else
Cells(counterRowNumber, ColumnNumber.Memo).Value = _
Cells(counterRowNumber, ColumnNumber.Memo).Value & ", " & tempValue_1
End If
End If
' if caption is not set, copy id to caption.
If Cells(counterRowNumber, ColumnNumber.Caption).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Caption).Value = _
Cells(counterRowNumber, ColumnNumber.FieldName).Value
End If
' record field tyle
Select Case tempField.Type
Case 1: ' Yes/No 型
tempValue = "NUMBER"
tempValue_1 = "1"
tempValue_2 = "0"
Case 2: ' バイト型
tempValue = "NUMBER"
tempValue_1 = "3"
tempValue_2 = "0"
Case 3: ' 整数 (-32768 - 32768)
tempValue = "NUMBER"
tempValue_1 = "5"
tempValue_2 = "0"
Case 4: ' 長整数型 又は オートナンバー
tempValue = "NUMBER"
tempValue_1 = "10"
tempValue_2 = "0"
If (tempField.Attributes And dbAutoIncrField) = dbAutoIncrField Then
If Cells(counterRowNumber, ColumnNumber.Memo).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Memo).Value = "シーケンス使用"
Else
Cells(counterRowNumber, ColumnNumber.Memo).Value = _
Cells(counterRowNumber, ColumnNumber.Memo).Value & ", シーケンス使用"
End If
End If
Case 5: ' 通貨型
tempValue = "NUMBER"
tempValue_2 = CStr(tempField.Properties("DecimalPlaces").Value)
If Information.IsNumeric(tempValue_2) Then
If CInt(tempValue_2) < 0 Or CInt(tempValue_2) > 4 Then
tempValue_2 = "4"
End If
Else
tempValue_2 = "4"
End If
tempValue_1 = CStr(15 + CInt(tempValue_2))
Case 7 ' 倍精度浮動小数点型
' 38-digits floating point
tempValue = "NUMBER"
tempValue_1 = ""
tempValue_2 = ""
Case 8: ' 日付/時刻型
tempValue = "DATE"
tempValue_1 = ""
tempValue_2 = ""
Case 10: ' テキスト
tempValue = "VARCHAR2"
tempValue_1 = tempField.Size
tempValue_2 = ""
Case 11 ' OLEオブジェクト型
tempValue = "BLOB"
tempValue_1 = ""
tempValue_2 = ""
Case 12 ' メモ型 又は ハイパーリンク型
tempValue = "VARCHAR2"
tempValue_1 = "4000"
tempValue_2 = ""
'' take care for character code when you using CLOB.
'' CLOB don't work correctly
'' in variable character code like AL16UTF16.
' tempValue = "CLOB"
' tempValue_1 = ""
' tempValue_2 = ""
Case Else:
tempValue = tempField.Type
tempValue_1 = ""
tempValue_2 = ""
End Select
Cells(counterRowNumber, ColumnNumber.DataType).Value = tempValue
Cells(counterRowNumber, ColumnNumber.Power).Value = tempValue_1
Cells(counterRowNumber, ColumnNumber.DecimalPlace).Value = tempValue_2
' move to next row
counterRowNumber = counterRowNumber + 1
Next
' end recording field properties
' record primary key column
primaryKeyExists = False
For Each tempIndex In tempTable.Indexes
If tempIndex.Primary = True Then
For Each tempField In tempIndex.Fields
If Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = "" Then
Cells(counterRowNumber, ColumnNumber.Caption).Value = "PK_" & tempTable.Name
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = tempField.Name
Else
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = _
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value & _
", " & tempField.Name
End If
Next
primaryKeyExists = True
End If
Next
' mark columns of primary key
If primaryKeyExists Then
primaryKeys = Split(CStr(Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value), ", ")
For counterInt_1 = 0 To UBound(primaryKeys)
For counterInt = topRowOfCurrentTable To counterRowNumber - 1
If Cells(counterInt, ColumnNumber.FieldName) = primaryKeys(counterInt_1) Then
Cells(counterInt, ColumnNumber.PrimaryKey).Value = "○"
Exit For
End If
Next
Next
counterRowNumber = counterRowNumber + 1
End If
' start recording index except for primary key
counterInt = 1
For Each tempIndex In tempTable.Indexes
If tempIndex.Primary = False Then
For Each tempField In tempIndex.Fields
tempValue = tempField.Name
If primaryKeyExists Then
For counterInt_1 = 0 To UBound(primaryKeys)
If tempValue = primaryKeys(counterInt_1) Then
tempValue = ""
Exit For
End If
Next
End If
If tempValue <> "" Then
tempValue_1 = "1"
If Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = "" Then
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = _
tempValue
Else
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value = _
Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value & _
", " & tempValue
End If
End If
Next
If Cells(counterRowNumber, ColumnNumber.IndexFieldName).Value <> "" Then
' when more than one index is recorded
Cells(counterRowNumber, ColumnNumber.Caption).Value = _
"ID_" & tempTable.Name & CStr(counterInt)
If tempIndex.Unique = True Then
Cells(counterRowNumber, ColumnNumber.IndexUnique).Value = "○"
End If
counterRowNumber = counterRowNumber + 1
counterInt = counterInt + 1
End If
End If
Next
' end recording index
Else
' record Table ID and Table Name
Cells(counterRowNumber, ColumnNumber.TableName).Value = tempTable.Name
Cells(counterRowNumber, ColumnNumber.TableDescription).Value = "リンクテーブル"
counterRowNumber = counterRowNumber + 1
' record table source
stringItems = Split(tempTable.Connect, ";")
For counterInt = 0 To UBound(stringItems)
If Left(stringItems(counterInt), 9) = "DATABASE=" Then
Cells(counterRowNumber, ColumnNumber.LinkDatabaseHeader).Value = "元データベース"
Cells(counterRowNumber, ColumnNumber.LinkDatabase).Value = stringItems(counterInt)
counterRowNumber = counterRowNumber + 1
Cells(counterRowNumber, ColumnNumber.LinkSourceTableHeader).Value = "元テーブル"
Cells(counterRowNumber, ColumnNumber.LinkSourceTable).Value = tempTable.SourceTableName
counterRowNumber = counterRowNumber + 1
Exit For
End If
Next
counterRowNumber = counterRowNumber + 1
End If
' move to next row for new table
counterRowNumber = counterRowNumber + 1
End If
Next
Set db = Nothing
Set xlAPP = Nothing
End Sub
' http://www.vbalab.net/vbaqa/data/excel/log/tree_325.htm にあったので借用
Private Function ConvFullHalf(ByVal targetString As String, _
Optional ByVal optKana As Integer = 0, _
Optional ByVal optHira As Integer = 0, _
Optional ByVal optAlph As Integer = 0, _
Optional ByVal optDigt As Integer = 0, _
Optional ByVal optSymb As Integer = 0, _
Optional ByVal optSpac As Integer = 0) As String
Dim character As String
Dim resultString As String
Do Until targetString = ""
character = Left(targetString, 1)
targetString = Right(targetString, Len(targetString) - 1)
Select Case character
Case "ぁ" To "ん" ' ひらがな
resultString = resultString & StrConv(character, optHira)
Case "A" To "Z", "a" To "z", "A" To "Z", "a" To "z" ' アルファベット
resultString = resultString & StrConv(character, optAlph)
Case "0" To "9", "0" To "9" ' 数字
resultString = resultString & StrConv(character, optDigt)
Case " ", " " 'スペース
resultString = resultString & StrConv(character, optSpac)
Case Else
Select Case Left(StrConv(character, vbNarrow), 1)
Case Chr(&H21) To Chr(&H2F), _
Chr(&H3A) To Chr(&H40), _
Chr(&H5B) To Chr(&H60), _
Chr(&H7B) To Chr(&H7E) ' 記号
resultString = resultString & StrConv(character, optSymb)
Case Chr(&HA1) To Chr(&HDF) ' カタカナ
If Left(targetString, 1) = Chr(&HDE) Or _
Left(targetString, 1) = Chr(&HDF) Then
resultString = resultString & StrConv(character & Left(targetString, 1), optKana)
targetString = Right(targetString, Len(targetString) - 1)
Else
resultString = resultString & StrConv(character, optKana)
End If
Case Else
resultString = resultString & character
End Select
End Select
Loop
ConvFullHalf = resultString
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment