[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『マクロでリストの形を変換したい』(ぱんだ)
表題の件でアドバイス頂きたくお願いします。
Sheet1に元データがあります。各項目の意味は、A列:ID(1人1つ)、B列:担当者名、C列:分類(1,2,3 :イメージは分類1は関東担当、2は東北担当、3は九州担当)、D列-I列:役割codeと役割名(1人で複数役割を持っている人がいるので役割1-3に列を分けました。実際は役割は5個とか担当している人もいる)です。
(役割codeと役割名は関係性があるので、後から役割名をVlookup等で引っ張ることも可能。)
やりたい事は、Sheet1の元データを、マクロでリストの形を変更して、Sheet2のように変換させたいです。
変換後のSheet2では、役割ごとに、分類1の人、分類2の人、分類3の人を横並びの表に表したい。
(役割code/名はアルファベットの若い順から並べ、かつ、該当する役割の行に分類が同じ人が複数いる場合は、上から詰めて入力していきたい)
これを、マクロでできないかと考えているのですが難しくご教授頂きたく。
例えば、中間テーブル(1人で役割を複数持っている人は、その数分の行を増やす)を設けたらやり易いか?とか考えたのですが、そこからOutputに持っていくやり方が分かりません(参考で、中間テーブル作るマクロは文末添付します)
<Sheet1:元データ>
A B C D E F G H I ID 担当者 分類 役割code1 役割名1 役割code2 役割名2 役割code3 役割名3 A01 Aさん 1 a あ A02 Bさん 2 b い d え g き A03 Cさん 2 a あ b い d え A04 Dさん 2 a あ A05 Eさん 3 d え g き A11 Fさん 2 e お A13 Gさん 2 f か g き A14 Hさん 3 g き
<Sheet2:Outputはこうしたい>
A B C D E F G H 役割code 役割名 分類1のID 分類1担当者 分類2のID 分類2担当者 分類3のID分類3担当者 a あ A01 Aさん A03 Cさん a あ A04 Dさん b い A02 Bさん b い A03 Cさん d え A02 Bさん A05 Eさん d え A03 Cさん e お A11 Fさん f か A13 Gさん g き A02 Bさん A05 Eさん g き A13 Gさん A14 Hさん
参考)中間テーブルを作成してみた
A列:ID、 B列:担当者、 C列:分類、 D列:役割code、 E列:役割名
Sub 中間テーブル作成マクロ()
' ソースデータ範囲 Dim ソース範囲 As Range Set ソース範囲 = Sheets("Sheet1").Range("A1:I9")
' 出力データ開始セル Dim 出力セル As Range Set 出力セル = Sheets("Sheet2").Range("A2")
' 出力ヘッダー行 出力セル.Resize(1, 5).Value = Array("ID", "名前", "分類", "役割code", "役割名")
' ソースデータをループして中間テーブルを作成 Dim 行番号 As Long Dim 出力行 As Long 出力行 = 1
For 行番号 = 2 To ソース範囲.Rows.Count Dim ID As String Dim 名前 As String Dim 分類 As Integer Dim 役割code_1 As String Dim 役割名_1 As String Dim 役割code_2 As String Dim 役割名_2 As String Dim 役割code_3 As String Dim 役割名_3 As String
ID = ソース範囲.Cells(行番号, 1).Value 名前 = ソース範囲.Cells(行番号, 2).Value 分類 = ソース範囲.Cells(行番号, 3).Value 役割code_1 = ソース範囲.Cells(行番号, 4).Value 役割名_1 = ソース範囲.Cells(行番号, 5).Value 役割code_2 = ソース範囲.Cells(行番号, 6).Value 役割名_2 = ソース範囲.Cells(行番号, 7).Value 役割code_3 = ソース範囲.Cells(行番号, 8).Value 役割名_3 = ソース範囲.Cells(行番号, 9).Value
' 役割1の行を出力 If Len(役割code_1) > 0 Then 出力セル.Offset(出力行, 0).Resize(1, 5).Value = Array(ID, 名前, 分類, 役割code_1, 役割名_1) 出力行 = 出力行 + 1 End If
' 役割2の行を出力(役割2が存在する場合) If Len(役割code_2) > 0 Then 出力セル.Offset(出力行, 0).Resize(1, 5).Value = Array(ID, 名前, 分類, 役割code_2, 役割名_2) 出力行 = 出力行 + 1 End If
' 役割3の行を出力(役割3が存在する場合) If Len(役割code_3) > 0 Then 出力セル.Offset(出力行, 0).Resize(1, 5).Value = Array(ID, 名前, 分類, 役割code_3, 役割名_3) 出力行 = 出力行 + 1 End If Next 行番号 End Sub
< 使用 Excel:Microsoft365、使用 OS:Windows10 >
>(役割codeと役割名は関係性があるので、後から役割名をVlookup等で引っ張ることも可能。) とのことなので、ご自身で対応して下さい。
Sub test() Dim dic As Object Dim v, w, tmp(1 To 3), arr, dat Dim i&, j&, n& Dim cn$, id$ Const dlm$ = "★"
Set dic = CreateObject("scripting.dictionary") v = Worksheets("Sheet1").Cells(1).CurrentRegion.Value For i = 2 To UBound(v) For j = 4 To UBound(v, 2) Step 2 cn = v(i, j) id = v(i, 1) n = v(i, 3) If Not v(i, j) = "" Then If Not dic.exists(cn) Then tmp(n) = dlm & id dic(cn) = tmp Else arr = dic(cn) arr(n) = arr(n) & dlm & id dic(cn) = arr End If End If Erase tmp Next Next n = 2 With Worksheets("Sheet2") For Each w In dic.keys arr = dic(w) For i = 1 To UBound(arr) dat = Split(Mid(arr(i), 2), dlm) If Not UBound(dat) < 0 Then With .Cells(n, 1).Resize(UBound(dat) + 1) .Value = w .Offset(, i * 2) = Application.Transpose(dat) .Offset(, i * 2 + 1).FormulaR1C1 = "=IFNA(VLOOKUP(rc[-1],Sheet1!c1:c2,2,0),"""")" End With End If Next n = .Cells(Rows.Count, "A").End(xlUp).Row + 1 Next .Cells(1).CurrentRegion.Sort Key1:=.Cells(1), Order1:=xlAscending, Header:=xlYes End With End Sub (辰) 2024/01/02(火) 11:14:22
下記となってしまいます。
A B C D E F G H 役割code 役割名 分類1のID 分類1担当者 分類2のID 分類2担当者 分類3のID分類3担当者 a あ A01 Aさん A03 Cさん a あ A04 Dさん b い A02 Bさん b い A03 Cさん d え A02 Bさん A05 Eさん d え A03 Cさん e き A02 Bさん A05 Eさん f き A13 Gさん A14 Hさん g お A11 Fさん g か A13 Gさん
正しくは、こうなりたいです。
A B C D E F G H 役割code 役割名 分類1のID 分類1担当者 分類2のID 分類2担当者 分類3のID分類3担当者 a あ A01 Aさん A03 Cさん a あ A04 Dさん b い A02 Bさん b い A03 Cさん d え A02 Bさん A05 Eさん d え A03 Cさん e お A11 Fさん f か A13 Gさん g き A02 Bさん A05 Eさん g き A13 Gさん A14 Hさん (ぱんだ) 2024/01/02(火) 14:43:23
.Cells(1).CurrentRegion.Sort Key1:=.Cells(1), Order1:=xlAscending, Header:=xlYes
デバックで内容確認中ですが、マクロ勉強中の身で、コードの読み解きが出来ていない状況です。
特に、Const dlm$ = "★" としている部分や、
下記以降の意味がよく分かりません。大変恐縮ですが、意味を教えて頂くことは可能でしょうか。
tmp(n) = dlm & id dic(cn) = tmp Else arr = dic(cn) arr(n) = arr(n) & dlm & id dic(cn) = arr End If End If Erase tmp Next Next n = 2 With Worksheets("Sheet2") For Each w In dic.keys arr = dic(w) For i = 1 To UBound(arr) dat = Split(Mid(arr(i), 2), dlm) If Not UBound(dat) < 0 Then With .Cells(n, 1).Resize(UBound(dat) + 1) .Value = w .Offset(, i * 2) = Application.Transpose(dat) .Offset(, i * 2 + 1).FormulaR1C1 = "=IFNA(VLOOKUP(rc[-1],Sheet1!c1:c2,2,0),"""")" End With End If Next (ぱんだ) 2024/01/02(火) 15:09:21
私の方では最初に提示されたサンプルで、想定通りに動作しています。 念のためソートの設定を以下の様に変更してみて下さい。
.Cells(1).CurrentRegion.Sort _ Key1:=.Range("A1"), Order1:=xlAscending, Header:=xlYes, _ MatchCase:=False, Orientation:=1, SortMethod:=1
ただ、追加提示の前半の表だと、B列でソートしている様に見えますけど。
全て説明するのは面倒ですので勘弁して下さい。 学習して分からないところを聞くか、他の方の回答をお待ちください。 明確な質問の部分に関する点のみ。
>Const dlm$ = "★"A01 dlmという文字列型の定数に「★」を代入し、区切り文字として使用しています。 変数tmpは分類(1から3まで)の配列。 tmp(n) = dlm & id でn番目の配列に、★ & A01 つまり、★A01 という様に格納。 同じ分類・同じ役割名が複数になると★A01★A03の様に格納して、書き出す時にSplitしています。 ※Dim tmp(3)と宣言して、tmp(0)に役割名を入れたら、後からVLOOKUPで役割名を呼び出さずとも良いかも。 (辰) 2024/01/02(火) 19:48:07
★のご説明もありがとうございます。イメージ湧いてきました。この後デバックしながら学習してみます。
色々と教えてくださり、ありがとうございました。もう一つやりたい事があり追加でご質問させていただく予定ですが、本来やりたかったことは辰様のおかげで実現できました。大変ありがとうございました。
(ぱんだ) 2024/01/02(火) 20:41:37
<やりたい事>
Outputはこれまでの質問通り、下記、Sheet2のようにしたいのですが、
元データがSheet5の形式の場合、どのようにマクロを組めば、Sheet2のリストの形に変換できますでしょうか。
<Sheet5:元データ> 一人が複数の役割を持っている場合、1人複数行のデータベース
ID 名前 分類 役割ID 役割名 A01 Aさん 1 a あ A02 Bさん 2 b い A02 Bさん 2 d え A02 Bさん 2 g き A03 Cさん 2 a あ A03 Cさん 2 b い A03 Cさん 2 d え A04 Dさん 2 a あ A05 Eさん 3 d え A05 Eさん 3 g き A11 Fさん 2 e お A13 Gさん 2 f か A13 Gさん 2 g き A14 Hさん 3 g き
<Sheet2:Output>役割ごとに、分類1の人、分類2の人、分類3の人を横並びの表に表したい。
(役割code/名はアルファベットの若い順から並べ、かつ、該当する役割の行に分類が同じ人が複数いる場合は、上から詰めて入力していきたい)
A B C D E F G H 役割code 役割名 分類1のID 分類1担当者 分類2のID 分類2担当者 分類3のID 分類3担当者 a あ A01 Aさん A03 Cさん a あ A04 Dさん b い A02 Bさん b い A03 Cさん d え A02 Bさん A05 Eさん d え A03 Cさん e お A11 Fさん f か A13 Gさん g き A02 Bさん A05 Eさん g き A13 Gさん A14 Hさん
(ぱんだ) 2024/01/02(火) 21:04:11
辰さんのコードは、Sheet2の1行目に列タイトルがあらかじめ入力されている前提です。 列タイトルがあらかじめ入力されていないと、B列が空欄になるのでで、 その結果、.Cells(1).CurrentRegion がA列だけになってソート範囲がうまくきまりません .Cells(1).CurrentRegion.Resize(, 8).Sort key1:=.Cells(1), Order1:=xlAscending, Header:=xlYes とすれば大丈夫のはず
Sheet1からSheet5と同じ表形式を経由してSheet2の表形式まで
Sub sampleB() Worksheets("Sheet2").Cells.ClearContents 'STEP1 With Worksheets("Sheet1") .Range(.Cells(1, 1), .Cells(.Rows.Count, "A").End(xlUp)).Resize(, 9).Copy Worksheets("Sheet2").Cells(1, 1) End With 'STEP2 With Worksheets("Sheet2") For i = .Cells(.Rows.Count, "A").End(xlUp).Row To 2 Step -1 For j = 2 To 1 Step -1 If .Cells(i, j * 2 + 4) <> "" Then .Rows(i).Copy .Rows(i).Insert shift:=xlDown .Cells(i + 1, 4).Resize(, j * 2).Delete shift:=xlToLeft End If Next Next .Range("F:I").Delete End With 'STEP3 With Worksheets("Sheet2") .Range("D:E").Cut .Range("A:A").Insert .Range("E:E").Cut .Range("C:C").Insert End With 'STEP4 With Worksheets("Sheet2") With .Cells(1, 1).CurrentRegion.Resize(, 8) .Sort key1:=.Cells(1, 1), key2:=.Cells(1, 3), Order1:=xlAscending, Order2:=xlAscending, Header:=xlYes End With End With 'STEP5 With Worksheets("Sheet2") For i = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row If .Cells(i, "C").Value > 1 Then .Cells(i, "D").Resize(, (.Cells(i, "C").Value - 1) * 2).Insert shift:=xlToRight End If Next End With 'STEP6 With Worksheets("Sheet2") i = .Cells(.Rows.Count, "A").End(xlUp).Row Do While i >= 2 j = i Do While .Cells(j - 1, 1).Value = .Cells(i, 1).Value j = j - 1 Loop With .Rows(j).Resize(i - j + 1, 9) n1 = WorksheetFunction.CountA(.Columns("D")) n2 = WorksheetFunction.CountA(.Columns("F")) n3 = WorksheetFunction.CountA(.Columns("H")) n = WorksheetFunction.Max(n1, n2, n3) If .Rows.Count > n Then .Columns("F").Resize(, 2).Sort key1:=.Cells(1, "F"), Order1:=xlAscending, Header:=xlNo .Columns("H").Resize(, 2).Sort key1:=.Cells(1, "H"), Order1:=xlAscending, Header:=xlNo If .Rows.Count > n Then .Rows(n + 1).Resize(.Rows.Count - n).Delete End If End If End With i = j - 1 Loop End With End Sub (´・ω・`) 2024/01/03(水) 07:56:09
大変勉強になります。ありがとうございます。
> .Cells(1).CurrentRegion.Resize(, 8).Sort key1:=.Cells(1), Order1:=xlAscending, Header:=xlYes
とすれば大丈夫のはず
→無事にできました。
> Sheet1からSheet5と同じ表形式を経由してSheet2の表形式まで
→やりたい事、実現できました。
条件分岐させて、列削除、行削除していく事で実現できるのですね。なるほどと思いました。
特に、STEP6の部分について、対象役割での範囲の取得方法等、大変勉強になりました。
ちなみに、行削除や列削除をしているので、ある程度の時間がかかるのは仕方がないですか?
試しに400件のデータでやると30秒ほどでした。
色々と教えていただき、ありがとうございます。
(ぱんだ) 2024/01/03(水) 10:48:14
私のコードは処理の考え方1例を示したもので、速度は考慮してません Application.ScreenUpdatingをFalseにすれば多少は早くなるとは思います。
辰さんのコードが爆速なので、実践的にはそちらを使わせていただくのがよろしいかと思います。 (´・ω・`) 2024/01/03(水) 12:06:08
辰様
今回は色々教えて頂き、ありがとうございました。
Sheet2への書き出し部分↓↓がまだ理解しきれていませんが、使いこなせるように勉強していきたいと思います。
For Each w In dic.keys arr = dic(w) For i = 1 To UBound(arr) dat = Split(Mid(arr(i), 2), dlm) If Not UBound(dat) < 0 Then With .Cells(n, 1).Resize(UBound(dat) + 1) .Value = w (ぱんだ) 2024/01/03(水) 13:15:04
スピード追求バージョン '----------- 標準モジュール ---------------------------- Sub test() Dim aRow As Range, role As String, Class As Long, person As String Dim RoleList As cRoleList Set RoleList = New cRoleList With Worksheets("Sheet1") For Each aRow In .Range(.Cells(2, 1), .Cells(.rows.Count, "A").End(xlUp)).Rows For i = 4 To 8 Step 2 If aRow.Cells(1, i) <> "" Then role = aRow.Cells(1, i).Value & vbTab & aRow.Cells(1, i + 1).Value Class = aRow.Cells(1, 3).Value person = aRow.Cells(1, 1).Value & vbTab & aRow.Cells(1, 2).Value RoleList.Add(role, Class) = person End If Next Next End With
RoleList.Print5 Worksheets("Sheet5").Cells(2, 1) RoleList.Print2 Worksheets("Sheet2").Cells(2, 1)
End Sub '----------- Class モジュール cRoleList ---------------- Private dic As Object Private mCount As Long Private mClassMax As Long Private Sub Class_Initialize() Set dic = CreateObject("Scripting.Dictionary") End Sub Public Property Let Add(role As String, Class As Long, ByVal vNewValue As Variant) If dic.Exists(role) Then If dic(role).Exists(Class) Then dic(role)(Class).Add dic(role)(Class).Count + 1, vNewValue mCount = mCount + 1 If mClassMax < Class Then mClassMax = Class Else dic(role).Add Class, CreateObject("Scripting.Dictionary") Me.Add(role, Class) = vNewValue End If Else dic.Add role, CreateObject("Scripting.Dictionary") Me.Add(role, Class) = vNewValue End If End Property
Public Sub Print2(target As Range) Dim role As Variant, Class As Variant, d1 As Object, d2 As Object, item1, item2 ReDim buf(1 To mCount, 1 To 2 + mClassMax * 2) As Variant i = 1 For Each item1 In dic.Keys Set d1 = dic(item1) role = Split(item1, vbTab) jmax = 0 For Each Class In d1.Keys Set d2 = d1(Class) j = i For Each item2 In d2.Items person = Split(item2, vbTab) buf(j, 1) = role(0) buf(j, 2) = role(1) buf(j, 1 + Class * 2) = person(0) buf(j, 2 + Class * 2) = person(1) j = j + 1 If jmax < j Then jmax = j Next Next i = jmax Next With target.Resize(i - 1, 2 + mClassMax * 2) .Value = buf .Sort key1:=.Cells(1, "A"), Order1:=xlAscending, Header:=xlNo End With End Sub
Public Sub Print5(target As Range) Dim role As Variant, Class As Variant, d1 As Object, d2 As Object, item1, item2 Dim rows As Variant, persons As Variant Dim i As Long ReDim buf(1 To mCount, 1 To 5) As Variant i = 1 For Each item1 In dic.Keys Set d1 = dic(item1) role = Split(item1, vbTab) For Each Class In d1.Keys Set d2 = d1(Class) For Each item2 In d2.Items person = Split(item2, vbTab) buf(i, 1) = person(0) buf(i, 2) = person(1) buf(i, 3) = Class buf(i, 4) = role(0) buf(i, 5) = role(1) i = i + 1 Next Next Next With target.Resize(UBound(buf), 5) .Value = buf .Sort key1:=.Cells(1, "A"), Order1:=xlAscending, key2:=.Cells(1, "C"), Order2:=xlAscending, key3:=.Cells(1, "D"), Order3:=xlAscending, Header:=xlNo End With End Sub (´・ω・`) 2024/01/03(水) 13:37:18
>ぱんださん For Each w In dic.keys 'dictionaryのkeyを巡回する arr = dic(w) 'dic(w)の配列をarrに複製(これまでのコードで、dic(w)には配列が格納されている) For i = 1 To UBound(arr) '配列arrの要素を1番目から巡回する(dic(w)に格納されている配列は元がtmp(1 to 3)なので、for i = 1 To 3 でも事は同じではある) dat = Split(Mid(arr(i), 2), dlm) 'arr(i)には"★A03★A05"の様に格納されているので、dlm=★で区切って配列datに格納。Mid関数で先頭の★を消している。 If Not UBound(dat) < 0 Then '配列datのインデックスの上限が0未満(arr(i)が空のケース)で無い(not)場合処理を行う。 With .Cells(n, 1).Resize(UBound(dat) + 1) '配列datのインデックスの上限+1分、行方向にResizeする。 .Value = w '上記範囲にwを入力。
>(´・ω・`)さん 大変恐縮です。まだまだ未熟者ですが、精進してまいります。m(__)m (辰) 2024/01/03(水) 14:08:35
辰様
コードのご説明、大変ありがとうございます。
デバックしながら、実際の事例で勉強してみます。色々とありがとうございました。
(ぱんだ) 2024/01/03(水) 17:04:31
Class モジュール cRoleList と書いたのは、クラスの名前を cRoleList にしてくださいという意味です
Classモジュールを挿入したら、プロパティウィンドウを表示して オブジェクト名を Class1から cRoleList に変更します。 (´・ω・`) 2024/01/03(水) 18:03:30
すみません、ご説明ありがとうございます。理解しました。
無事に動いたのですが、一行だけ抽出されませんでした。
役割code 役割名 分類2のID 分類2担当者
d え A03 Cさん
ご提示いただいたコードが高度で理解が追い付かず申し訳ありませんが、理由が分かりましたら教えて頂けますでしょうか。
(ぱんだ) 2024/01/03(水) 18:43:02
すみません バグがありました クラスcRoleListの中の Public Sub Print2 です
(´・ω・`) 2024/01/03(水) 13:37:18 のコードを直接編集してあります。 そこから再度コピーしてやってみてください (´・ω・`) 2024/01/03(水) 19:06:23
ありがとうございます!! 一瞬で出来ました。
一つずつ学習して、理解していきたいと思います。大変ありがとうございました。
(ぱんだ) 2024/01/03(水) 19:47:13
Power Query
let ソース = Excel.CurrentWorkbook(){[Name="テーブル1"]}[Content], ピボット解除された他の列 = Table.UnpivotOtherColumns(ソース, {"ID", "担当者", "分類"}, "属性", "値"), 文字の移行による列の分割 = Table.SplitColumn(ピボット解除された他の列, "属性", Splitter.SplitTextByCharacterTransition((c) => not List.Contains({"0".."9"}, c), {"0".."9"}), {"属性.1", "属性.2"}), ピボットされた列 = Table.Pivot(文字の移行による列の分割, List.Distinct(文字の移行による列の分割[属性.1]), "属性.1", "値"), 削除された列 = Table.RemoveColumns(ピボットされた列,{"属性.2"}), 選択した列のみをピボット解除しました = Table.Unpivot(削除された列, {"ID", "担当者"}, "属性", "値"), 追加されたプレフィックス = Table.TransformColumns(選択した列のみをピボット解除しました, {{"分類", each "分類" & Text.From(_, "ja-JP"), type text}}), 結合された列 = Table.CombineColumns(Table.TransformColumnTypes(追加されたプレフィックス, {{"分類", type text}}, "ja-JP"),{"分類", "属性"},Combiner.CombineTextByDelimiter("の", QuoteStyle.None),"結合済み"), グループ化された行 = Table.Group(結合された列, {"役割code", "役割名", "結合済み"}, {{"tbl", each _, type table [役割code=text, 役割名=text, 結合済み=text, 値=text]}}), 追加されたカスタム = Table.AddColumn(グループ化された行, "カスタム", each Table.AddIndexColumn([tbl],"index")), 削除された他の列 = Table.SelectColumns(追加されたカスタム,{"カスタム"}), #"展開された カスタム" = Table.ExpandTableColumn(削除された他の列, "カスタム", {"役割code", "役割名", "結合済み", "値", "index"}, {"役割code", "役割名", "結合済み", "値", "index"}), ピボットされた列1 = Table.Pivot(#"展開された カスタム", List.Distinct(#"展開された カスタム"[結合済み]), "結合済み", "値"), 削除された列1 = Table.RemoveColumns(ピボットされた列1,{"index"}) in 削除された列1 (マナ) 2024/01/03(水) 20:19:08
一つ教えてください。
このコードを理解するには、ステップを一つずつ確認していく感じでしょうか。
今回元データとして記載しているのは、あくまでサンプルで実際にはもっと列が増えたり条件も複雑になるのですが、
それをこのコードに当てはめるとすると、コード上で編集を加えるべきなのか、一からステップを頼りに作っていくのかどちらが現実的でしょうか。
(ぱんだ) 2024/01/03(水) 20:55:09
>実際にはもっと列が増えたり条件も複雑になるのですが、
あくまで、私の場合ですが
表の並び替えはPower Queryの得意分野なので よく使う操作の組み合わせだけでできることが多いです。 基本的には、コードの編集はしません。 また初心者にコードの直接編集は難しい気がします。
列数の増加は、想定される範囲だったので対応済み。 現状のままで使えるはずです。
その他の条件が追加されれば ステップの挿入でOKな場合もあるかもしれませんが だめなら最初から操作し直します。
簡単操作でできない条件追加の場合は 諦めてマクロを使っちゃいます。 (マナ) 2024/01/03(水) 21:47:38
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.