「Web出版サイト」ベータ公開

Q&A集[?]

当サイトでのご質問の受付は終了しました

すべてのコンテンツを読み込み専用としたため、回答欄からも投稿できません

Apache OpenOffice/LibreOfficeのご質問はそれぞれのフォーラムへご投稿ください

質問コーナー

サイト内検索

分類メニュー

関連サイト


本日:2
昨日:0
総数:2330
現在:1


テーブルのフィールドコピー

ページOpenOffice.org FAQの登録ページ
投稿者タイガー
分類
edit/refer
優先順位
edit/refer
状態
edit/refer
カテゴリー
edit/refer
投稿日2010-11-28 19:28:46 (日)
OSWin XP
依存するページ
バージョン
edit/refer

メッセージ

回答ページでは行末に「~」を付加する必要はありません

基となるodbファイルのフィールド情報を別のobdファイルのテーブルコピーを したいのですが、後少しの所でエラーが発生しております。 何か良い方法を教えてください。

ヾ陲箸覆odbファイルのテーブルのフィールド オブジェクトを取得

	oBaseContext = CreateUnoService("com.sun.star.sdb.DatabaseContext")
 	oDB = oBaseContext.getByName(ConvertToUrl(mFilePath))
 	oCon = oDB.getConnection("", "")  
	oConTables = oCon.getTables
	oFild = oConTables.getByName(TableName).getColumns()
	FildName = oFild.getElementNames()
	If NOT IsEmpty(FildName) then oFildObj = oFild
	

▲灰圈疾茲odbファイルに,離侫ールドオブジェクトの内容に  テーブルとフィールドを作成する

   Context=CreateUnoService("com.sun.star.sdb.DatabaseContext")
   DB=Context.getByName((oBaseURL) )
   Conn=DB.getConnection("","")
	
	Tables=Conn.Tables
   TableDescriptor=Tables.createDataDescriptor()
   TableDescriptor.Name=TableName
   
   Columns=TableDescriptor.Columns
   ColumnDescriptor=Columns.createDataDescriptor()
	
	REM APPEND COLUMN 
	
	FildName = FildOjb.getElementNames()
	If IsEmpty(FildName) then Exit Function
	
	for i=0 to ubound(FildName)
		oColumn = FildOjb.getByName( FildName(i) )
   	With ColumnDescriptor
   		.Name = oColumn.Name
  			.Type = oColumn.Type
   	End With
   	Columns.appendByDescriptor(ColumnDescriptor)
   next i	
	
	Tables.appendByDescriptor(TableDescriptor)
	

最後の行でエラー発生致します。


name,type 以外のプロパティ

ike@九州 (2010-11-29 13:42:02 (月))

faq/5/295 に新規 ODB ファイルの はにゃ?さん作成コード があります。

VARCHAR タイプなどは文字数の設定が必要なようで
Precision プロパティの設定がそれのようですね。

With 句に
.Precision = oColumn.Precision を追加すれば良いようですが
プライマリキーの設定が後からは出来ません(エラーで不可)

Tables.appendByDescriptor(TableDescriptor) の前にプライマリーキーの設定を faq/5/295 から応用して作成の必要がありますね。

文字数の設定について

タイガー (2010-11-30 16:17:32 (火))

ike@九州さんの言う通り文字数を設定しましたら、上手く行きましたが、

mdbファイルをベースから開き、フィールドサイズを取得したら0になっております。
アクセスで開いたフィールドサイズは5とか3とか設定されていますが、
ベースで開いてみた時には0になります。
なんとかして5とか3とかを取得できないものでしょうか?

その他、oColumn.Nameとか.TypeNameは正常と思うのですが、
宜しくお願い致します。

	oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdatabase", "_blank", 0, Array())
	oDoc.DataSource.URL ="sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=C:\Test.mdb"
	oDoc.Title = oDoc.Title + ".odb"
	oDoc.storeAsURL(ConvertToUrl("c:\test.odb"),Array())
	strcompDocName = oDoc.getURL()
	oDBCtx = CreateUnoService("com.sun.star.sdb.DatabaseContext")
	oko = oDoc.DataSource 
 	oDBCtx.registerObject("TEST",oko)


	oCon = oDoc.DataSource.getConnection("", "")  
	oConTables = oCon.getTables
	oFild = oConTables.getByName("テーブル").getColumns()
	
	FildName = oFild.getElementNames()
	If IsEmpty(FildName) then END
   
   oColumn = oFild.getByName(FildName(0))
	
	print oColumn.Precision

MDB ファイルでは不可のようです

ike@九州 (2010-12-01 12:01:43 (水))

接続データベースによって取得、設定できるプロパティに違いがあります。
Precision プロパティは HSQLDB 対応のようですね

色々調べましたら
下記 Function なら取得できました

〜
Msgbox(getMDBColumnSize("C:\Test.mdb","テーブル",FildName(0)))
〜


'フィールドサイズの取得 (MDBファイル名、テーブル名、フィールド名)
Function getMDBColumnSize(sFileName As String,sTableName As String,sFieldName As String) As Long
 Const adCmdTable = 2
 oADOCon = CreateObject("ADODB.Connection")
 Rs = CreateObject("ADODB.Recordset")
 sURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sFileName & ";"
 oADOCon.Open(sURL)
 Rs.Open(sTableName,oADOCon,,,adCmdTable)
 getMDBColumnSize = Rs.Fields.Item(sFieldName).DefinedSize
 Rs.Close
 oADOCon.Close
 Rs = Nothing
 oADOCon = Nothing
End Function


テーブル、列、プライマリキー等の作成は SQL から
Create 句を使用した方が賢明なような気がします。

フィールド名の取得方法について

タイガー (2010-12-05 15:21:22 (日))

ike@九州さん、有難う御座います。

getMDBColumnSize = Rs.Fields.Item(sFieldName).DefinedSize
で上手く取得できました。

教えて頂いたサンプルを基にフィールド名も取得したいと考えております。
getMDBColumnSize = Rs.Fields.Item(sFieldName).DefinedSize
の部分を少し改良するだけで上手く取得できると思い色々試しておりましたが
上手く行きません。

アドバイスお願いいたします。

現時点で収集した内容です

ike@九州 (2010-12-06 13:07:58 (月))

少し長いコードですが
sFileName = "E:\Test.mdb" を適当に変更して試してください
(既存、新規)

Const adSchemaTables = 20
Const adSchemaColumns = 4
Const adCmdTable = 2
Const adSchemaPrimaryKeys = 28
Const scURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
Const COLUMN_NAME = 3
Const DATA_TYPE = 11
Const CHARACTER_MAXIMUM_LENGTH = 13
Const NUMERIC_PRECISION = 15

Sub Test
 sFileName = "E:\Test.mdb"
 Call createMDB(sFileName)
 sTableNames = getMDBTableNames(sFileName)
 IF IsNull(sTableNames) Then
  MsgBox("テーブルがありません")
  Exit Sub
 End If
 
 For c = 0 to uBound(sTableNames)
   sMsg = ""    
   sPKeyNames = getMDBPrimarykeys(sFileName,sTableNames(c)(0))
   IF Not IsNULL(sPkeyNames) then
     For m = 0 to uBound(sPKeyNames)
       sMsg = sMsg & sPKeyNames(m) & ","
     Next
     sMsg = "PrimaryKey = " & sMsg & chr(13)
   End IF
   '2次元配列変数は sFieldInfo(行Index)(列Index) として値を取得します
   sFieldInfo = getMDBColumnInfo(sFileName,sTableNames(c)(0))
   
   'フィールド情報をCALCへ書き出し
   Call ExportCalc(sFieldInfo)
   
   IF Not IsNull(sFieldInfo) then
    For n = 0 to uBound(sFieldInfo)
     sMsg = sMsg & sFieldInfo(n)(COLUMN_NAME) & "(" & sFieldInfo(n)(DATA_TYPE) & ") = "
     'http://msdn.microsoft.com/ja-jp/library/cc389790.aspx
     Select Case sFieldInfo(n)(DATA_TYPE)
      Case 130,200,201,202,203 'WChar,VarChar,LongVarChar,VarWChar,LongVarWChar
       sMsg = sMsg & sFieldInfo(n)(CHARACTER_MAXIMUM_LENGTH) & "文字"
      Case 3,4,5,6 'Long,Single,Double,Currency
       sMsg = sMsg & sFieldInfo(n)(NUMERIC_PRECISION) & "桁"
      Case Else
       'print sFieldInfo(n)(DATA_TYPE)
     End Select      
     sMsg = sMsg & Chr(13)
    Next
    sMsg = "テーブル名 = " & sTableNames(c)(0) & chr(13) & sMsg
   End If   
   MsgBox(sMsg)
 Next
End Sub

'MDBファイルの新規作成
Sub createMDB(sfName As String)
 sURL = scURL & sfName & ";"   
 oSimpleFileAccess = createUnoService( _
   "com.sun.star.ucb.SimpleFileAccess" )
 'mdbファイルが無ければ作成
 If Not oSimpleFileAccess.exists( sfName ) Then
  Msgbox("ファイルを新規に作成します")
  catDB = CreateObject("ADOX.Catalog")
  oADOCat = catDB.Create(sURL)
  oADOCat.Close
  catDB = Nothing
  oADOCat = Nothing
  'テーブルの作成
  oADOCon = CreateObject("ADODB.Connection")  
  oADOCon.Open(sURL)
  'COUNTER はオートナンバー型
  sSQL = "CREATE TABLE テーブル1 (ID COUNTER PRIMARY KEY,日付 DATE," &_
  "テキストCHAR100指定 CHAR(100),テキストCHAR無指定 CHAR,テキストTEXT指定 TEXT(255)," &_
  "テキストTEXT無指定 TEXT,ダブル DOUBLE,通貨 CURRENCY);"
  oADOCon.Execute(sSQL)
  oADOCon.Close 
  oADOCon = Nothing   
 End If
End Sub

'テーブル名の取得(MDBファイル名)
Function getMDBTableNames(sfName As String) As Variant
 oADOCon = CreateObject("ADODB.Connection")
 sURL = scURL & sfName & ";"
 oADOCon.Open(sURL)
 Rs = oADOCon.OpenSchema(adSchemaTables, Array(,,,"TABLE"))
 IF Rs.EOF Then
  getMDBTableNames = Nothing
 Else
  getMDBTableNames = Rs.getRows(,,"TABLE_NAME")
 End IF
  
 Rs.Close
 oADOCon.Close
 Rs = Nothing
 oADOCon = Nothing
End Function

'フィールド情報の取得(MDBファイル名、テーブル名)
Function getMDBColumnInfo(sfName As String,sTableName As String) As Variant
 oADOCon = CreateObject("ADODB.Connection")
 sURL = scURL & sfName & ";"
 oADOCon.Open(sURL)
 Rs = oADOCon.OpenSchema(adSchemaColumns, Array(,,sTableName,))
 IF Rs.EOF Then
  getMDBColumnInfo = Nothing
 Else
  'http://msdn.microsoft.com/ja-jp/library/cc364163.aspx
  'getRows()は 2次元配列で取得
  getMDBColumnInfo = Rs.getRows()
 End IF
 Rs.Close
 oADOCon.Close
 Rs = Nothing
 oADOCon = Nothing  
End Function

'PrimaryKeyフィールド名の取得(MDBファイル名、テーブル名)
Function getMDBPrimarykeys(sfName As String,sTableName As String) As Variant
 oADOCon = CreateObject("ADODB.Connection")
 sURL = scURL & sfName & ";"
 oADOCon.Open(sURL)
 Rs = oADOCon.OpenSchema(adSchemaPrimaryKeys, Array(,,sTableName))  
 IF Rs.EOF Then
  getMDBPrimarykeys = Nothing
 Else
  n = 0
  Do while NOT Rs.EOF
   ReDim Preserve sKeyNames(n) As string 
	sKeyNames(n) = Rs.Fields.Item("COLUMN_NAME").value
   Rs.MoveNext
   n = n + 1
  Loop
 getMDBPrimarykeys = sKeyNames
 End IF
 Rs.Close
 oADOCon.Close
 Rs = Nothing
 oADOCon = Nothing
End Function

'フィールド情報をCALCに書き出し
Sub ExportCalc(vntArray as object)
 Dim colArray(0) As Variant
 oCalcDoc = StarDesktop.loadComponentFromURL("private:factory/scalc","_blank",0,Array())
 oSheet = oCalcDoc.getSheets().getByIndex(0)
 colArray(0) = Array("TABLE_CATALOG","TABLE_SCHEMA","TABLE_NAME","COLUMN_NAME","COLUMN_GUID",_
 "COLUMN_PROPID","ORDINAL_POSITION","COLUMN_HASDEFAULT","COLUMN_DEFAULT","COLUMN_FLAGS",_
 "IS_NULLABLE","DATA_TYPE","TYPE_GUID","CHARACTER_MAXIMUM_LENGTH","CHARACTER_OCTET_LENGTH",_
 "NUMERIC_PRECISION","NUMERIC_SCALE","DATETIME_PRECISION","CHARACTER_SET_CATALOG",_
 "CHARACTER_SET_SCHEMA","CHARACTER_SET_NAME","COLLATION_CATALOG","COLLATION_SCHEMA",_
 "COLLATION_NAME","DOMAIN_CATALOG","DOMAIN_SCHEMA","DOMAIN_NAME","DESCRIPTION")
 oSheet.getCellRangeByPosition(0,0,Ubound(colArray(0)),0).setDataArray(colArray)
 oSheet.getCellRangeByPosition(0,1,Ubound(vntArray(0)),Ubound(vntArray)+1).setFormulaArray(vntArray)
End Sub


'getRows()は 2次元配列で取得
getMDBColumnInfo = Rs.getRows() は以下の内容を取得してます
http://msdn.microsoft.com/ja-jp/library/ms723052.aspx

取得したDATA_TYPEは以下のAccess のプロバイダにおける型標識参照
http://msdn.microsoft.com/ja-jp/library/cc408010.aspx
テキスト型は全て同じ DATA_TYPE = 130 で取得されるようで
テキスト型の内 CHARACTER_MAXIMUM_LENGTH = 0 の場合は、Accessでのメモ型となるようです。

結果は以下の違いが出ました。
(左がBaseからの情報、右がgetMDBColumnInfoでの情報)

field.png


テキスト型の文字数のみ設定が必要なので
MDBファイルからどの種類のデータベースにコピーするかによって方法を検討した方が宜しいかと思いました。

VBA によるサンプルがネット上に多くありますが
ADO API、ADOX APIを通してのテーブルやフィールドのコレクションから単一のオブジェクトにアクセスするのに OOo Basic からでは For Each〜Next が動作しませんし、Fields(0) や Fields.Item(0) などの Index による方法がとれません。唯一 Fields.Item("名前") でアクセスできます。
つまり前もって個々の名前を知っている必要があるという事ですね。
#追記しました 12/7

大変役立つサンプル有難う御座います。

タイガー (2010-12-07 13:43:41 (火))

事前にフィールド名を取得して、フィールドを作成する事が出来ました。
色々お世話になりました。
次は、レコードのコピーについて考えていきます。
有難う御座いました。

完了にします

M.Kamataki (2010-12-07 17:04:24 (火))

コメントありがとうございます。

お名前:
題名:


添付ファイル: filefield.png 839件 [詳細]