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

Q&A集[?]

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

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

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

質問コーナー

サイト内検索

分類メニュー

関連サイト


本日:1
昨日:0
総数:4306
現在:1


レコードのコピー作成

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

メッセージ

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

お世話になります。

TEST_A.odb ファイルのテーブル名 TEST_Table を 新規で作成したTest_B.odbにそのままコピーしたいのですが、

OOoでは、リンクテーブルが作成できないみたいなので、 新規odbファイルの方に、テーブル及びフィールドの登録までは作成できました

レコードをTEST_Aから1レコードづつ読み込み 新規テーブルの方へ1行つづ書き込みしておりますが、 2万行有る為すごい時間が掛ります。

ある程度OOoはスピードが遅いと認識しておりますが、 他に良い方法があれば、教えてください。

現状のコードは、 旧テーブルの1レコードを順に呼び出し m_Strに1レコード分のデータ代入して 下記コードで新規テーブルの方に書き込みをしております。

	oSQL = "INSERT INTO " & odbTableName & " VALUES (" & mStr & ")"
	Statement = oBaseCon.createStatement()
	ResultSet= Statement.executeQuery(oSQL)

以上、宜しくお願い致します。


CSVへ出力しリンクしては

M.Kamataki (2010-12-07 17:21:25 (火))

>ある程度OOoはスピードが遅いと認識しております

原因はOpenOffice.orgというよりもBaseが標準で採用しているodbというファイル形式の制約です。データベースエンジンとしてはHSQLDBを採用していますが、さらにHSQLDBが生成するファイル群をZIP圧縮しています。ZIP圧縮に時間がかかるのが難点です。

そこで、TEST_A.odb ファイルのテーブルを直接 Test_B.odb にコピーするのではなく、いったんCSVに出力し、Test_B.odb からはそのCSVファイルをリンクしたらどうでしょうか。もしくは、Base標準のデータベースではなく、その他のデータベース(MySQL、PostgreSQL、Firebird、またファイルとしてのmdb形式など)を利用することも検討してください。

CSVファイルの利用については、faq/4/1812「マクロからodbファイル内のテーブルを別のodbファイルにコピーするには?」やfaq/5/472「csvファイルとリンクしたい」(こちらはフォーム利用に関する注意点を紹介)にマクロ例があります。

MDB形式に変えようと思います

タイガー (2010-12-07 18:26:03 (火))

基となるデータは、MDBファイルを使用しております。
それを一旦
oObjCon.DataSource.URL = "sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=" & mdbFilePath
でベースに取り入れ、ベースファイルにテーブル内容をコピーしようと現状しております。

MDBファイルのテーブル作成及び、コピー基のフィールド情報までは理解できましたが、
フィールドの作成及び、レコードのコピー方法が不明です。
もし、MDBファイルを取り扱った方が、レコードコピーする時間が早くなるのであれば、そちらに変えたい
と思いますので、アドバイスお願いいたします。

'MDBファイルの新規作成
Function CreateMDB(ByVal mdbURL As String) As Boolean
	Dim catDB As Object
	Dim oADOCat As Object
	Dim oURL As String
	
	oURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdbURL + ";"
	'mdbファイルが無ければ作成
	If Not oFilePathCheck(mdbURL) Then 
 		catDB = CreateObject("ADOX.Catalog")
 		oADOCat = catDB.Create(oURL)
 		oADOCat.Close
 		catDB = Nothing
 		oADOCat = Nothing
 	End If
 	CreateMDB = True
End Function

'MDBテーブルの作成
Function CreateMdbTable(ByVal mdbURL As String,ByVal mdbTableName As String) As Boolean
	Dim oURL As String
	Dim oADOCon As Object
	Dim oADOCmd As Object
	
	oURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & mdbURL & ";"
	oADOCon = CreateObject("ADODB.Connection")  
 	oADOCon.Open(oURL)
	oADOCmd = CreateObject("ADODB.Command")
 	oADOCmd.ActiveConnection = oADOCon
 	oADOCmd.CommandText = "CREATE TABLE " + mdbTableName +";"
 	oADOCmd.Execute
 	oADOCon.Close
 	oADOCmd = Nothing  
 	oADOCon = Nothing
 	CreateMdbTable = True
End Function

’フィールド情報を取得する
Function GetMDBFildInfo(ByVal mdbURL As String,ByVal mdbTableName As String,FildInfo As Variant) As Boolean
	Dim oADOCon As Object
	Dim oURL As String
	Dim Rs As Object
	
	Const adSchemaColumns = 4
	oURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + mdbURL + ";"
	oADOCon = CreateObject("ADODB.Connection")
	oADOCon.Open(oURL)
	Rs = oADOCon.OpenSchema(adSchemaColumns, Array(,,mdbTableName,))
	
	IF Rs.EOF Then
 		FildInfo = Nothing
	Else
 		FildInfo = Rs.getRows()'2次元配列で取得
	End IF
	Rs.Close
	oADOCon.Close
	Rs = Nothing
	oADOCon = Nothing
	GetMDBFildInfo = True
End Function

mdb内のテーブルをリンクする

M.Kamataki (2010-12-08 11:17:17 (水))

動作検証をしていませんが、古いOpenOffice.orgの掲示板で以下のような、mdbファイルを基にしたBaseファイルでリンクテーブルができたという報告があります。参考になるでしょうか。

http://oooug.jp/cgi-bin/bbs/users/1131663196.html#R111

コピー先のデータソースの種類は?

ike@九州 (2010-12-08 14:46:19 (水))

>mdb ファイルからベースファイルにテーブル内容をコピー

上記のコピー先のベースファイルのデータソースが付属の HSQLDB なのか、他の MDB ファイルに接続設定しているものなのか以前不明です。

BASEドキュメントは MDB ファイルに接続している場合、単なるフロントエンドでの動作ですので、テーブルデータそのものは BASE ドキュメント内に実在しません。
MDB ファイルを移動してしまうと Baseドキュメントは動作しなくなるという事です。

A.mdb ファイル内の "売上"テーブル を B.mdb ファイル内にコピーしたいという事であれば OOo Basic を使う必要はありません。

以下のコードをメモ帳にコピーし hoge.vbs として実行すると
テーブル定義、データ共コピーできました。
既に同じテーブル名があるとエラーとなります。
(郵便番号データ12万件でも一瞬です)

Main

Sub Main
 Const DB_LANG_JAPANESE = ";LANGID=0x0411;CP=932;COUNTRY=0"
 Dim wsMyWS,dbMain , dbExternal
 Dim tdExternal, tdMain
 Dim idxExternal, idxMain
 Dim fldExternal, fldMain
 Dim strSQL,strBaseMDB,strTargetMDB,strTABLE  
 
 'コピー元のmdbURL
 strBaseMDB = "E:\A.mdb"
 'コピー先のmdbURL
 strTargetMDB = "E:\B.mdb."
 'テーブル名
 strTABLE = "売上"
 
 Set DBEngine = CreateObject("DAO.DBEngine.36")
 Set fso = CreateObject("Scripting.FileSystemObject")
 If Not fso.FileExists(strBaseMDB) Then
  MsgBox strBaseMDB & " がありません。中止します"
  Exit Sub
 End IF
 If Not fso.FileExists(strTargetMDB) Then
  Set db = DBEngine.CreateDatabase(strTargetMDB,DB_LANG_JAPANESE)  
 End If
 
 Set wsMyWS = DBEngine.Workspaces(0)
 Set dbMain = wsMyWS.OpenDatabase(strBaseMDB)
 Set dbExternal = wsMyWS.OpenDatabase(strTargetMDB)
 
 strSQL = "SELECT * INTO [;DATABASE=" & strTargetMDB & "].[" & strTABLE & "] " & _
          "FROM [;DATABASE=" & strBaseMDB & "].[" & strTABLE & "];"
 dbMain.Execute strSQL
 
 ' インデックス情報をコピーします。
 dbMain.TableDefs.Refresh
 Set tdMain = dbMain.TableDefs(strTABLE)
 Set tdExternal = dbExternal.TableDefs(strTABLE)
 For Each idxExternal In tdExternal.Indexes
     Set idxMain = tdMain.CreateIndex(idxExternal.Name)
     With idxMain
         For Each fldExternal In idxExternal.Fields
             Set fldMain = .CreateField(fldExternal.Name)
             fldMain.Attributes = fldExternal.Attributes
             .Fields.Append fldMain
         Next
         .Clustered = idxExternal.Clustered
         .IgnoreNulls = idxExternal.IgnoreNulls
         .Primary = idxExternal.Primary
         .Required = idxExternal.Required
         .Unique = idxExternal.Unique
     End With
     tdMain.Indexes.Append idxMain
 Next
 dbMain.Close
 dbExternal.Close
 MsgBox("終了しました")
End Sub


参考
http://support.microsoft.com/kb/407539/ja

Kamatakiさん情報のように mdb ファイルに接続設定した Baseドキュメント上で
ツール>SQL から上記 vbs コード内の SQL を直接実行してもコピー可能でしたがテーブル定義がコピーされません(Primarykey等)

コピー先 Base ドキュメントのデータソースを HSQLDB とした場合は
1レコードずつコピーになると思います。
Kamataki さんご案内のように mdb ファイル内の テーブルを CSVとして出力して HSQLDB から CSV インポートできますが、テーブル定義が必要な為、
予めテーブル、フィールド等作成しておく必要があります。

mdb ファイルからの CSV 出力 ツール>SQL から

SELECT * INTO [TEXT;Database=E:\sample].[Testmdb.csv] FROM [テーブル名];

自動で CREATE 文を作成するのは DAT_TYPE で振り分けてフィールド作成情報を付加していけば可能ですね。

やはり mdb ファイルから、どのデータソースへテーブルのコピーをして
どのような運用したいのか?
全体の構想を明確に提示して頂くのが良いアイデアが浮かぶと思います。

mdb ファイル(12万件超)に接続設定した BASE ドキュメントも結構さくさくと動作して
Windows に限れば mdb + BASE は"アリ"だと思いました。
Access 無くても mdb ファイルのまま OOo は柔軟な運用、連携できますが不都合があるのでしょうか? Linux 移行とか

ちなみに HSQLDB で10万件超ともなると、とても耐えられない BASE の動作ですし、耐えられない限界は数万件かもしれません。

接続方法〜やりたい事

タイガー (2010-12-09 11:11:44 (木))

色々と貴重なアドバイス有難う御座います。

OOoのベーシックのみで対応です。

基となるデータは2つあり、ベースファイルで言えば、
 A:oDataSource.URL = "sdbc:ado:PROVIDER=〜"
 B:oDataSource.URL = "sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=mdbFilePath"
 AとBの接続でつないでいます。(このファイルは読み取り専用ファイルです)

△ら必要なデータ部分だけをベースファイルに取り入れるか、
 OOoベーシックでMDBファイル作りを直接取り入れるかはどちらでも可です。
 (CSVの方でも可です)
 理由は、データ量は数万件〜数十万件ありますので、高速処理できる方が優先です。現在悩んでいます...
 (データフィールドタイプは、テキスト型と数値型しかありません。Primarykeyは無しで可)

きより集計出来たデータをカルクに出力します。
 の集計とは複数のテーブルから加工が必要になりますので・・・
 一番良いのは、直接クエリで△ら必要データを取得してカルクに書き込むのが理想ですが
 加工作業が多くて一旦で加工します。

上記内容より、ベースファイルは処理時間がかかるかと思い
'MDBファイルの新規作成、'MDBテーブルの作成、'フィールド情報を取得する
まで作成致しました(教えて頂きましたが・・・)
ike@九州さんのVBSのサンプルは大変早くもっとも良いと思いますが、
OOoのベーシックのみで対応したいので・・・スイマセン説明不足で。。。

良いアドバイス宜しくお願い致します。

詳細な内容有難うございます。

ike@九州 (2010-12-09 12:29:44 (木))

>A:oDataSource.URL = "sdbc:ado:PROVIDER=〜"

データソース A の種類が不明です。
mdb であればコピー可能ですから、mdb ファイルではないという事で手順を考えると。

・新規に C.mdb ファイルを作成する。
・データソース B の必要なテーブルを C.mdb にコピーする。
・データソース A の必要なテーブルを C.mdb にリンクテーブルとして作成する。
・C.mdb からクエリを実行して得られた結果を CALC へ書き出す。

以上を OOo Basic のみで実現するという事で宜しいでしょうか?
手順がこれで宜しければ
A:oDataSource.URL を全てお知らせ下さい。
リンクテーブルの作成が可能なデータソースか調べる必要があります。

Aについて

タイガー (2010-12-09 13:12:30 (木))

sdbc:ado:Provider=MSDASQL.1;Persist Security Info=False;User ID=XXX;Data Source=XXX

IDとSouceはXXXでふせております。

・新規に C.mdb ファイルを作成する。
・データソース B の必要なテーブルを C.mdb にコピーする。
・データソース A の必要なテーブルを C.mdb にリンクテーブルとして作成する。
・C.mdb からクエリを実行して得られた結果を CALC へ書き出す。
で問題ないと思いますが、リンクテーブルが可能である事願います

宜しくお願い致します。

リンクテーブルで調べた情報

ike@九州 (2010-12-09 18:26:11 (木))

データソース A が SQL Server の場合です。
B もリンクテーブルで作成してみました。(コピーも可能です)

Const scURL = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="

Sub Main
  '作成先の MDB ファイル
  strTargetDB = "E:\TEST2.mdb"

'****** 他 MDB ファイル内テーブルへのリンクテーブル作成 ******
  '作成テーブル名(任意)
  strLinkTblName = "売上テーブル"
  '接続文字列
  strProviderString = "DSN=testsql"
  'リンク先テーブル名
  strSourceTbl = "売上テーブル"
  'リンク先 MDB ファイル
  strLinkDataSource = "E:\TEST.mdb"
  
  '作成サブルーチン呼び出し
  CreateLinkedExternalTable(strTargetDB,strProviderString,strSourceTbl,strLinkTblName,strLinkDataSource)
  
'****** SQL Server へのリンクテーブル作成 ******
  '作成テーブル名(任意)
  strLinkTblName = "コードテーブル"
  '接続文字列 UID = ユーザー名、PWD = パスワード
  strProviderString = "ODBC;" & _
           "DRIVER={SQL Server};" & _
           "SERVER=*****;DATABASE=*****;" & _
           "UID=****;PWD=****;"
  'リンク先テーブル名
  strSourceTbl = "コードテーブル"
  
  '作成サブルーチン呼び出し
  CreateLinkedExternalTable(strTargetDB,strProviderString,strSourceTbl,strLinkTblName)   
 
'******* CSVへのリンクテーブル作成 *******
  '作成テーブル名(任意)
  strLinkTblName = "事業所コード"

  '接続文字列
  'HDR=YES,NOは1行目項目名有無、IMX=2はリンクモード FMTは区切り文字 CharacterSet は文字コード
  strProviderString = "TEXT;Driver={Microsoft Text Driver (*.txt; *.csv)};" & _
  "FMT=Delimited;CharacterSet=932;HDR=NO;IMEX=2;"

  'ファイル名がJIGYOSYO.CSVの場合
  strSourceTbl = "JIGYOSYO#CSV"

  'フォルダ名
  strLinkDataSource = "E:\" 

  '作成サブルーチン呼び出し
  CreateLinkedExternalTable(strTargetDB,strProviderString,strSourceTbl,strLinkTblName,strLinkDataSource)

'****** xls ファイルへのリンクテーブル作成 ******
  '作成テーブル名(任意)
  strLinkTblName = "Sheet1"

  '接続文字列
  'HDR=YES,NOは1行目項目名有無、IMX=2はリンクモード
  strProviderString = "Excel 8.0;HDR=YES;IMEX=2;"

  'シート名 Sheet1 へのリンクの場合
  strSourceTbl = "Sheet1$"

  'エクセルファイルのURL
  strLinkDataSource = "E:\Book1.xls"

  '作成サブルーチン呼び出し
  CreateLinkedExternalTable(strTargetDB,strProviderString,strSourceTbl,strLinkTblName,strLinkDataSource)

End Sub

Sub CreateLinkedExternalTable(strTargetDB As String, _
        strProviderString As String, _
        strSourceTbl As String, _
        strLinkTblName As String,Optional strLinkDataSource As String)
  
  sURL = scURL & strTargetDB
  catDB = CreateObject("ADOX.Catalog")

  IF FileExists(strTargetDB) Then

    oADOCon = CreateObject("ADODB.Connection")    
    oADOCon.Open(sURL)   
    catDB.ActiveConnection = oADOCon
  
  Else
    '新規に作成
    catDB.Create(sURL)

  End IF
  
  tblLink = CreateObject("ADOX.Table")
  With tblLink
     .Name = strLinkTblName
     .ParentCatalog = catDB
     ' プロパティを設定してリンクを作成します。
     .Properties.Item("Jet OLEDB:Create Link").Value = True
     .Properties.Item("Jet OLEDB:Link Provider String").Value = strProviderString
     .Properties.Item("Jet OLEDB:Remote Table Name").Value = strSourceTbl
     IF Not IsMissing(strLinkDataSource) Then
       .Properties.Item("Jet OLEDB:Link Datasource").Value = strLinkDataSource
     End IF
  End With

  ' テーブルを Tables コレクションに関連付けます。
  catDB.Tables.Append tblLink
  oADOCon = Nothing
  catDB = Nothing
  Msgbox("リンクテーブル " & strLinkTblName & " を作成しました")
End Sub~

tbl.Properties.Item("Jet OLEDB:Link Provider String").value = "MSDASQL.1〜 の文字列は2重リンクになるので多分不可だという情報アリですが試す価値はアリです。

どうしても上手く行かない場合は、Access から手作業で A のリンクテーブルを作成してプロパティを確認する事になります。

#8/25 xls ファイルリンクテーブル作成を追記しました。

有難う御座いました

タイガー (2010-12-11 14:06:16 (土))

サンプルを参考にさせて頂き、両方とも上手く行きました。
有難う御座いました。

お名前:
題名: