プロが教えるわが家の防犯対策術!

Access2003を使用しています。

列Aに以下のような値があります。

列A
1111-222
3333-444-55
6666-777-88-99

これをハイフン毎に列を分けて以下のような形に整形したいのです。

列B   |列C   |列D  |列E
1111  |222   |     |
3333  |444  |55   |
6666  |777  |88   | 99

クエリなどで一発で実行できるコマンド等があればご教示いただきたく思います。
説明下手ですみませんが、よろしくお願いします。

A 回答 (11件中1~10件)

クエリで出来るのかな?出来たとしても難解なものになるのでは?


あの御方なら可能かもしれません・・
直感的に分かりやすいレコードセットを操作する方に決定
説明は最後に
'------------------------------------------------------
Const tblName = "T1" '操作したいテーブル名の定数

Function getColCount() As Long '最大の分割数取得
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim t As Long

  Set db = CurrentDb
  Set rs = db.OpenRecordset(tblName, dbOpenSnapshot)

  If rs.EOF = False Then
    t = UBound(Split(rs!F1, "-"))
    Do Until rs.EOF
      If getColCount < t Then
        getColCount = t
      End If
      rs.MoveNext
    Loop
  End If

  getColCount = getColCount + 1
  rs.Close: Set rs = Nothing
  db.Close: Set db = Nothing
End Function

Sub makeTable()  'テーブル操作
Dim db As DAO.Database
Dim rsFrom As DAO.Recordset, rsTo As DAO.Recordset
Dim tdf As DAO.TableDef
Dim strSql As String
Dim i As Integer
Dim tVar As Variant

  Set db = Application.CurrentDb

'既存テーブルにフィールド追加
  i = getColCount + 1
  strSql = "alter table " & tblName & " add column F"
  For i = 1 To i
    db.Execute strSql & CStr(i + 1) & " text(20) ", dbFailOnError
  Next i
  db.TableDefs.Refresh

'各フィールドにF1フィールドの分割した値を格納
  Set rsFrom = db.OpenRecordset(tblName, dbOpenSnapshot)
  Set rsTo = db.OpenRecordset(tblName, dbOpenDynaset)
  Do Until rsFrom.EOF
    tVar = Split(rsFrom!F1, "-")
    rsTo.Edit
    For i = 0 To UBound(tVar)
      rsTo.Fields("F" & CStr(i + 2)) = tVar(i)
    Next i
    rsTo.Update
    rsFrom.MoveNext: rsTo.MoveNext
  Loop

  rsFrom.Close: Set rsFrom = Nothing
  rsTo.Close: Set rsTo = Nothing
  db.Close: Set db = Nothing
End Sub
'------------------------------------------------------
データが入っているテーブルの複製をコピペして、テーブル名を、T1 に
データがあるフィールド名を、F1 に変更

DAOに参照設定がされていなければ・・
Alt + F11 を押してVBEの画面にして
メニュー→ツールから参照設定を選択
参照可能なライブラリから、Microsoft DAO 3.6 Object Library を探して
チェックボックスにチェックを入れます

メニュー→挿入から標準モジュールを選択
新たな窓が出てくるので、上記の点線で囲んだ部分をコピペ
Ctrl + G を押してイミディエイトウィンドウを出して
そこに maketable と入力し Enter

Alt + F11 で Access の 窓に切り替え
先ほどの T1 テーブルを開いてみてください。
なお、DAOのメンバを使うように変数宣言してますので、ADO との共存可能也
また、T1 テーブルにはフィールドは一つしかないものと仮定
文字数ぎり
    • good
    • 0

おお!


またやってしまいましたかorz
試したつもりだったのですが・・・言葉もありません。
鱗の次は冷や汗。。。

piroin654 さん ありがとうございます。
そして、質問者さんごめんなさい。

バグの根っこは、getColCount 関数に有りました。
ついでに見直して データが空(Null)だった場合に対応したつもり。
Nz で囲んだだけです。こんどは大丈夫かな?

Function getColCount() As Long '最大の分割数取得
  Dim db As DAO.Database
  Dim rs As DAO.Recordset
  Dim t As Long
  
  Set db = CurrentDb
  Set rs = db.OpenRecordset(tblName, dbOpenSnapshot)
  
  If rs.EOF = False Then
    Do Until rs.EOF
      t = UBound(Split(Nz(rs!f1, ""), "-"))
      If getColCount < t Then
        getColCount = t
      End If
      rs.MoveNext
    Loop
  End If
  getColCount = getColCount + 1
  rs.Close: Set rs = Nothing
  db.Close: Set db = Nothing
End Function

Sub makeTable()   'テーブル操作
  Dim db As DAO.Database
  Dim rsFrom As DAO.Recordset, rsTo As DAO.Recordset
  Dim tdf As DAO.TableDef
  Dim strSql As String
  Dim i As Integer
  Dim tVar As Variant
  
  Set db = Application.CurrentDb
  
  '既存テーブルにフィールド追加
  i = getColCount
  strSql = "alter table " & tblName & " add column F"
  For i = 1 To i
    db.Execute strSql & CStr(i + 1) & " text(20) ", dbFailOnError
  Next i
  db.TableDefs.Refresh

  '各フィールドにF1フィールドの分割した値を格納
  Set rsFrom = db.OpenRecordset(tblName, dbOpenSnapshot)
  Set rsTo = db.OpenRecordset(tblName, dbOpenDynaset)
  Do Until rsFrom.EOF
    tVar = Split(Nz(rsFrom!f1, ""), "-")
    rsTo.Edit
    For i = 0 To UBound(tVar)
      rsTo.Fields("F" & CStr(i + 2)) = tVar(i)
    Next i
    rsTo.Update
    rsFrom.MoveNext: rsTo.MoveNext
  Loop

  rsFrom.Close: Set rsFrom = Nothing
  rsTo.Close: Set rsTo = Nothing
  db.Close: Set db = Nothing
End Sub
    • good
    • 0
この回答へのお礼

nicotinismさんをはじめ、たくさんの方より助言をいただき光栄です。質問者です。

nicotinismさんの助言を参考に試行錯誤しておりましたが、望みどおりの結果を得ることができました。大変感謝しております。
レコードが25万件ほどありましたので、一時はExcelでちまちま区切り位置で変換しようとも思いましたが、分かりやすい説明のおかげでAccess上で実行することができました。

ありがとうございました。

お礼日時:2011/04/14 18:01

nicotinismさん フィールド数がたりません。


>For i = 1 To i
 For i = 1 To i + 1
なら、正常なんですが。
    • good
    • 0

追伸。

nicotinism です。
回答がチンプンカンプンなら・・取り合えず Excel にデータを持って行って
データ→区切り位置で、"-"を指定して分割されたらどうですか?
質問内容からすると、もう御存知のようなのですが一応。
    • good
    • 0

モジュールで自作関数を作る。



Function chkst(st As String, sw As Integer)
Dim x As Long
Dim y As Long
Dim z(10) As String
x = Len(st)
y = 1
z(1) = ""
z(2) = ""
z(3) = ""
z(4) = ""
For I = 1 To x
If Mid(st, I, 1) = "-" Then
y = y + 1
z(y) = ""
Else
z(y) = z(y) & Mid(st, I, 1)
End If
If y > sw Then Exit For
Next I
chkst = z(sw)
End Function

クエリデザインで
B項目:CHKST("1111-222-333",1)としたら"1111"
C項目:CHKST("1111-222-333",2)としたら"222"
D項目:CHKST("1111-222-333",3)としたら"333"

母体文字列を与えて"-"出現何番目区切りを受け取るか、
そんな関数を作れば良いです。

サンプルなので、
CHKST("1111-222",3)
結果が伴わないもの、初期化も省略してます。完全ではありません。

こういうのを考えてアレンジしてみてください。
    • good
    • 0

20246kikuさんへ


なあ~るほど!
眼から鱗が4枚ポロリ。
頭を柔軟にしなくてはいけませんね。
ありがとうございます。
    • good
    • 0

いろいろやり方があると思いますので・・・




標準モジュールに、以下のユーザ定義関数を作成します。

Public Function MojiCut(iNum As Integer, vSrc As Variant, _
            Optional sDEL As String = "-") As String
  On Error Resume Next
  MojiCut = ""
  MojiCut = Split(vSrc, sDEL)(iNum)
End Function

"-" で区切った何番目を返すようにします。
何番目は、0スタート

ユーザ定義関数を、クエリから呼び出すようにします。

テーブル名を「TBL_A」と仮定します。

クエリのSQLビュー記述は以下。

SELECT MojiCut(0,列A) AS 列B
, MojiCut(1,列A) AS 列C
, MojiCut(2,列A) AS 列D
, MojiCut(3,列A) AS 列E
FROM TBL_A;

クエリの表示結果は以下

列B   列C   列D   列E
1111   222      
3333   444   55   
6666   777   88   99

区切りを指定しなければ "-" で区切ったものになります。

MojiCut(0,列A,",") AS 列B

とすると、区切りは "," (カンマ)になります。

上記クエリは、"-" 区切りで4つになることを前提としていますが、
何個に区切られるかわからない時には、VBA でクエリの内容を作成します。


Dim rs As New ADODB.Recordset
Dim sSql As String
Dim i As Integer, iLoop As Integer

iLoop = -1
rs.Source = "SELECT Max(Len(列A)-Len(Replace(列A,'-',''))) AS 数 FROM TBL_A;"
rs.Open , CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly
If (Not rs.EOF) Then iLoop = rs(0)
rs.Close

sSql = ""
For i = 0 To iLoop
  sSql = sSql & ", MojiCut(" & i & ",列A) AS 列" & Chr(Asc("A") + i + 1)
Next
If (Len(sSql) > 0) Then
  sSql = "SELECT " & Mid(sSql, 3) & " FROM TBL_A;"
  Debug.Print sSql ' ★ 作成されたSQL
End If


"-" の個数の最大数を求めて、くるくる作成します。
"-" が26個以上ある時には、Chr(Asc("A") + i + 1) 部分は考えてください。


提示サンプルデータで上記を実行した時に作成される ★部分でのSQLは、

SELECT MojiCut(0,列A) AS 列B, MojiCut(1,列A) AS 列C, MojiCut(2,列A) AS 列D, MojiCut(3,列A) AS 列E FROM TBL_A;

となるので、後はその内容で、
クエリを作成する/既存クエリの内容を書き換える等、
処理を追加すればよいと思います。


参考になる/ならない等々、自己責任でお願いします。

(データ量によっては使えないものかも・・・)
    • good
    • 0

No1、No3です。



DAOを使っているので、コード表のツールから
参照設定を選択して、
Microsoft DAO xx Object Library
にチェックを入れて、OKとします。xxは3.6のような数字です。
このとき、
Microsoft ActiveX Data Objects xx Library
にチェックが入っていたらはずしてください。

以上です。
    • good
    • 0

訂正です。


コードのSub cmdData()のところを
以下におきかえてください。

Sub cmdData()
Dim db As Database
Dim rs1 As Recordset
Dim rs2 As Recordset
Dim str As Variant
Dim i As Long
Dim j As Long
Dim k As Long
Dim l As Long

Set db = CurrentDb
Set rs1 = db.OpenRecordset("Tデータ", dbOpenDynaset)
Set rs2 = db.OpenRecordset("Tデータ分割", dbOpenDynaset)

If rs1.RecordCount > 0 Then
rs1.MoveFirst
Do Until rs1.EOF
j = 0
For i = 1 To Len(rs1!列A)
If Mid(rs1!列A, i, 1) = "-" Then
j = j + 1
End If
Next i
str = Split(rs1!列A, "-")
rs2.AddNew
For k = 0 To myCount
rs2.Fields(k) = Null
Next k
rs2.Update
rs2.MoveLast
If j = 0 Then
rs2.Edit
rs2.Fields(0) = str(0)
rs2.Update
End If
If j > 0 Then
rs2.Edit
rs2.Fields(0) = str(0)
rs2.Update
For l = 1 To j
rs2.Edit
rs2.Fields(l).Value = str(l)
rs2.Update
Next l
rs2.MovePrevious
End If
rs1.MoveNext
str = ""
Loop
End If

rs1.Close: Set rs1 = Nothing
rs2.Close: Set rs2 = Nothing
db.Close: Set db = Nothing
End Sub





No1の続きです。文字数がギリギリだったので。


フォームのボタンクリックで、Tデータ分割という
テーブルにデータを抽出します。
以上です。コードの中で何をしているかの説明は
省きます。何かあれば補足してください。
    • good
    • 0

この際INSTR関数は覚えておく方が良い。



-を違う文字に置き換えたら区切ることできるか。

固定文字列にすれば何文字めから何文字めまでがB列、何文字めから何文字めまでがC列、となる。

-が何個あるか、あったとして何番目か。1番目見つかるまでがB列、2番目見つかるまでがC列、となる。

どんな情報があれば、置き換えすれば実現出来そうか考えてみる。

VBA、モジュール作成はできますか。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す


このQ&Aを見た人がよく見るQ&A