No.5ベストアンサー
- 回答日時:
クエリで出来るのかな?出来たとしても難解なものになるのでは?
あの御方なら可能かもしれません・・
直感的に分かりやすいレコードセットを操作する方に決定
説明は最後に
'------------------------------------------------------
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 テーブルにはフィールドは一つしかないものと仮定
文字数ぎり
No.11
- 回答日時:
おお!
またやってしまいましたか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
nicotinismさんをはじめ、たくさんの方より助言をいただき光栄です。質問者です。
nicotinismさんの助言を参考に試行錯誤しておりましたが、望みどおりの結果を得ることができました。大変感謝しております。
レコードが25万件ほどありましたので、一時はExcelでちまちま区切り位置で変換しようとも思いましたが、分かりやすい説明のおかげでAccess上で実行することができました。
ありがとうございました。
No.9
- 回答日時:
追伸。
nicotinism です。回答がチンプンカンプンなら・・取り合えず Excel にデータを持って行って
データ→区切り位置で、"-"を指定して分割されたらどうですか?
質問内容からすると、もう御存知のようなのですが一応。
No.8
- 回答日時:
モジュールで自作関数を作る。
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)
結果が伴わないもの、初期化も省略してます。完全ではありません。
こういうのを考えてアレンジしてみてください。
No.6
- 回答日時:
いろいろやり方があると思いますので・・・
標準モジュールに、以下のユーザ定義関数を作成します。
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;
となるので、後はその内容で、
クエリを作成する/既存クエリの内容を書き換える等、
処理を追加すればよいと思います。
参考になる/ならない等々、自己責任でお願いします。
(データ量によっては使えないものかも・・・)
No.4
- 回答日時:
No1、No3です。
DAOを使っているので、コード表のツールから
参照設定を選択して、
Microsoft DAO xx Object Library
にチェックを入れて、OKとします。xxは3.6のような数字です。
このとき、
Microsoft ActiveX Data Objects xx Library
にチェックが入っていたらはずしてください。
以上です。
No.3
- 回答日時:
訂正です。
コードの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データ分割という
テーブルにデータを抽出します。
以上です。コードの中で何をしているかの説明は
省きます。何かあれば補足してください。
No.2
- 回答日時:
この際INSTR関数は覚えておく方が良い。
-を違う文字に置き換えたら区切ることできるか。
固定文字列にすれば何文字めから何文字めまでがB列、何文字めから何文字めまでがC列、となる。
-が何個あるか、あったとして何番目か。1番目見つかるまでがB列、2番目見つかるまでがC列、となる。
どんな情報があれば、置き換えすれば実現出来そうか考えてみる。
VBA、モジュール作成はできますか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAで、特定の文字より後を削除して残った数値を文字列に変換と特定の文字より前も削除したい 3 2022/04/15 19:21
- Excel(エクセル) countif関数について質問 4 2022/06/14 12:11
- Access(アクセス) Accessのクエリの結果を、既存のエクセルに追加したい 2 2022/07/31 22:44
- Excel(エクセル) 表示形式、文字列セル(列)に数式を入力するには マクロ 1 2022/09/18 10:53
- Ruby 初心者プログラミング 3 2022/10/12 11:31
- 計算機科学 Excel ある行と列が交わったところにマークを付けるには 7 2023/01/24 08:46
- Excel(エクセル) SUMIFのIF分岐について 4 2023/04/15 12:57
- その他(データベース) カラム上の重複を削除するクエリを教えてください 3 2022/04/12 14:11
- Excel(エクセル) EXCEL 行内のデータを2行に分けて、表を作り直したいのです。教えてください。 5 2023/06/25 14:00
- Excel(エクセル) capeofdragonと申します Excel2016を使っておりまして 半角又は全角の任意文字列が 2 2022/10/31 13:51
このQ&Aを見た人はこんなQ&Aも見ています
-
「どうして捨てられないの?」前妻の物を捨てられない男性の心理って?
前妻の物を捨てられない理由に加え、捨てるための手段はあるのかを専門家に聞いてみた!
-
アクセスのクエリでSplit関数は使えないのですか
Access(アクセス)
-
Accessフィールド分割
その他(データベース)
-
Accessで、1つの項目に複数の置換えを1度でするには?
Access(アクセス)
-
-
4
「#エラー」の回避
Access(アクセス)
-
5
アクセスで#エラーを表示させない方法は?
Access(アクセス)
-
6
Accessのマクロでモジュールを実行させたい。
Access(アクセス)
-
7
Access で 特定の文字の個数をしりたい
Access(アクセス)
-
8
ACCESS クエリで重複データを最新の1件だけ表示
Access(アクセス)
-
9
前のレコードの値を自動で入れたい
PowerPoint(パワーポイント)
-
10
Accessでテーブルの値をテキストボックスに代入するには?
Access(アクセス)
-
11
電話番号の分割
Access(アクセス)
-
12
ACCESSのフォームからハイパーリンクで開く
Access(アクセス)
-
13
ACCESSのテーブルのデータで、先頭に「000」を付与するほう右方
Access(アクセス)
-
14
フォームを開くときに、コンボボックスの値を選択(アクセスVBA)
Visual Basic(VBA)
-
15
ACCESSで空白のデーターをクエリで判定/識別する方法を教えてくださ
Access(アクセス)
-
16
どこにもフォーカスを当てたくない
Access(アクセス)
-
17
Access テキスト型に対する指定桁での0埋め方法
その他(データベース)
-
18
MS-Accessのレコード内のフィールドを分割し、複数のレコードにする方法について教えてください。
Access(アクセス)
-
19
Accessクエリで特定の行を削除したい
Access(アクセス)
-
20
Accessのスプレッドシートエクスポートで、シートが追加されてしまう
Access(アクセス)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
外部参照してるキーを主キーに...
-
Access:クエリーにて集計後に...
-
SELECT 文 GROUP での1件目を...
-
SQLで列名を変数にできないでし...
-
列番号による項目の取得について
-
【VB.NET】日付型の列にNULLを...
-
テーブル列数とデータファイル...
-
SQLです教えてくださいお願いし...
-
列のヘッダーを含めるのをデフ...
-
ストアドプロシージャに複数のS...
-
DB2のSQL
-
Accessのリストボックスについて
-
重複データの抽出方法(複数項目)
-
Accessでの全データから空白削除
-
SQLによる"あいうえお"順でソー...
-
項目名に大文字と小文字の混在...
-
SQLでn番目からm番目を取得したい
-
差し込み後、元データを変更し...
-
質問です How is your school l...
-
フィルターかけた後、重複を除...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
外部参照してるキーを主キーに...
-
SELECT 文 GROUP での1件目を...
-
列のヘッダーを含めるのをデフ...
-
Access:クエリーにて集計後に...
-
SQLで列名を変数にできないでし...
-
SQLによる"あいうえお"順でソー...
-
列番号による項目の取得について
-
UPDATE文のWHERE条件に他のテー...
-
【VB.NET】日付型の列にNULLを...
-
テーブル列数とデータファイル...
-
特定の文字列で列を区切るには?
-
項目名に大文字と小文字の混在...
-
複数列の最大値を求めたい
-
DB2のSQL
-
特定の列だけをGROUP BYしたい時
-
Accessでの全データから空白削除
-
identity属性の列に自動採番(SQL)
-
IDENTITY列の更新で失敗する
-
v$processのPROGRAM列に関する質問
-
SQLでn番目からm番目を取得したい
おすすめ情報