- ベストアンサー
全角文字列を挿入するには
エクセルVBAで以下のことを効率よくやるにはどうしたらよいでしょうか? 等幅フォントの文字列に全角文字列を挿入(置換え)します。 具体的に言うとホストコンピュータのリスト(等幅フォント半角文字132桁、A列のみ使用)に全角文字コメントを自動挿入します。 ホストリストは2つのファイルを比較するリストで16進数表記になっています。1行目が比較内容、2行目がファイル1の内容、3行目がファイル2の内容、4行目が空白行なっており、4行目にコメントを挿入します。 * IN1 F1000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F1000000CF1F1F2020070430CF0F0F0F0F5000000 COL8,5発生日 コメント挿入は同じ行に複数回入れることがあります。 入れようとする位置に既にコメントがある場合、空白行を追加してから 挿入します。 最初にコメントを入れる場合、特に問題は発生しませんが、2回目に入れる場合、コメントがあるかどうか該当位置を特定しなければなりませんが、全角文字が発生していると単純に位置を決定できません。 該当位置の決め方、そして挿入した場合、後続をズレないようにする必要があります。何故なら後続にコメントが既に入っているケースもあるからです。 一応自分なりにVBAは作っています。 (1)配列を作って1文字づつ配列のマスに入れる。 (2)全角文字の場合配列の2マスに(同じ内容を)入れる。 (3)追加文字列は該当の配列内容を見て、空白の場合、置き換える。 その時も同じように全角文字は2マス分使用する。 (4)以上がおわったら配列から取り出す。 取り出す際、全角文字の場合、次のマスを読み飛ばす。 ホストリストは数万行になる場合があり、配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 もう少し考えれば出来るような気がしますが、これだけ考えるだけで疲れてしまいました。 よろしくお願い申し上げます。
- みんなの回答 (9)
- 専門家の回答
質問者が選んだベストアンサー
#01です。少し変えました。以下のような結果になります ....****************************************** IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF1F0F0F0F6000000 ....COL1,1ファイル区分.COL8,5発生日.COL17,1企業区分 .....COL1,1ファイル区分.COL8,5発生日.COL17,1企業区分 ......COL2,5通番.COL8,5発生日.COL17,1企業区分 .......COL2,5通番.COL8,5発生日.COL17,1企業区分 ........COL2,5通番.COL8,5発生日.COL17,1企業区分 .........COL2,5通番.COL8,5発生日.COL17,1企業区分 ..........COL2,5通番.COL8,5発生日.COL17,1企業区分 ...........COL2,5通番.COL8,5発生日.COL17,1企業区分 ............COL2,5通番...COL8,5発生日.COL17,1企業区分 .............COL2,5通番...COL8,5発生日.COL17,1企業区分 ..............COL8,5発生日.COL8,5発生日.COL17,1企業区分 ...............COL8,5発生日.COL8,5発生日.COL17,1企業区分 ................COL8,5発生日.COL8,5発生日.COL17,1企業区分 ...........................................COL17,1企業区分 ............................................COL17,1企業区分 .............................................COL17,1企業区分 Sub Macro1() Dim idxR As Long Dim ptr, idxA, cnt As Integer Dim str As String Dim psw As Boolean Dim trg, rng As Range Dim aryCol, aryTxt Const cstCol As String = "6,14,30,40" Const cstTxt As String = "COL1,1ファイル区分@COL2,5通番@COL8,5発生日@COL17,1企業区分" aryCol = Split(cstCol, ",") aryTxt = Split(cstTxt, "@") Application.ScreenUpdating = False On Error GoTo end0 For idxR = Range("A65536").End(xlUp).Row To 1 Step -1 ptr = InStr(Cells(idxR, "A"), "*") If ptr > 0 Then Set trg = Cells(idxR, "A").Offset(3, 0) trg.ClearContents End If cnt = 0 Do While ptr > 0 For idxA = 0 To UBound(aryCol) If ptr <= Val(aryCol(idxA)) Then str = aryTxt(idxA) Exit For End If Next idxA psw = False For Each rng In Range(trg, trg.Offset(cnt, 0)) If LenB(StrConv(rng, vbFromUnicode)) < ptr - 1 Then psw = True Exit For End If Next rng If psw = False Then cnt = cnt + 1 trg.Offset(cnt, 0).Insert Set rng = trg.Offset(cnt, 0) End If rng = rng & Application.Rept(" ", ptr - LenB(StrConv(rng, vbFromUnicode)) - 1) rng = rng & str ptr = InStr(ptr + 1, Cells(idxR, "A"), "*") Loop Next idxR end0: Application.ScreenUpdating = True End Sub >私としては以下のような結果を考えております。 「Garbage in,garbage out」です。意味はおわかりですねw
その他の回答 (8)
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。Wendy02です。 >最初に代入された「発生日」が全角であり、半角文字より3桁増えているのが考慮されていないように思われます。 ロジックとしては間違いがないので、おそらく、正規表現パターンの{ "[^ ]+" }ではなくて、何か加えなくてはならないのかもしれません。何か別のものを数えているようです。 ただ、私としては、zap35さんが、集中的におやりになっているので、zap35さんに対して迷惑になりかねますし、believe_meさんへの負担にもなりますので、これ以上は、介入するつもりはありません。誰か一人が解決すればよいことですから。
お礼
皆様、沢山の回答、ありがとうございました。 解決案が見えてきましたので、回答を締めさせていただきます。 最初の質問の仕方にちょっと問題があったようで反省しております。 本当のところ、ホストのリストはもうちょっと複雑です。 ホストのファイル長は数百~数千バイトですし、リストの表示も10桁(16進表記では20桁)毎に空白が空いています。 問題を単純化して質問したつもりが、逆に皆様を混乱させてしまったようです。 また質問させていただくことがあると思いますが、その時はよろしくお願い申し上げます。
- zap35
- ベストアンサー率44% (1383/3079)
#01です。やれやれ私も仕事の精度が低いですね。 テストデータと実行結果の「半角スペースを半角ピリオドにしたもの」は以下の通りです。#06は無視してくださいm(_ _)m テストデータ .............................* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000000CF1F1F2020070430CF0F0F0F0F5000000 .............* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070429CF0F0F0F0F5000000 .............*...............*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF0F0F0F0F5000000 .............*...............*.........*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF1F0F0F0F6000000 実行結果 .............................* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000000CF1F1F2020070430CF0F0F0F0F5000000 .............................COL8,5発生日 .............* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070429CF0F0F0F0F5000000 .............COL2,5通番 .............*...............*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF0F0F0F0F5000000 .............COL2,5通番......COL8,5発生日 .............*...............*.........*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF1F0F0F0F6000000 .............COL2,5通番......COL8,5発生日 .......................................COL17,1企業区分
補足
実行してみました。 サンプルデータでは上手くいきましたが、データによっては思わぬ結果になってしまうようです。 ご提示いただいたプログラムを読みきっていないので何が原因なのかまだ分かっておりません。 ちょっと極端な例ですが、以下のようなデータの場合、 **************************************** IN1 1234567890123456789012345678901234567890 IN2 0000000001111111111222222222233333333334 ........COL1,1ファイル区分 ............COL1,1ファイル区分 ................COL2,5通番 ....................COL2,5通番 ........................COL2,5通番 ............................COL2,5通番 ................................COL2,5通番 ......................................COL2,5通番 ............................................COL2,5通番 ...................................................COL2,5通番 ........................................................COL8,5発生日 ...............................................................COL8,5発生日 となってしまいます。 私としては以下のような結果を考えております。 **************************************** IN1 1234567890123456789012345678901234567890 IN2 0000000001111111111222222222233333333334 ........COL1,1ファイル区分........................COL17,1企業区分 ................COL2,5通番 ........................COL8,5発生日
- zap35
- ベストアンサー率44% (1383/3079)
#01です #05に掲載したテストデータと実行結果をテキストエディタに貼り付けても桁数が狂ってしまっていました。半角スペースを半角ピリオドに置き換えて再掲します。エディタに貼り付けて文字を固定フォントにしてご覧下さい。 .............................* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000000CF1F1F2020070430CF0F0F0F0F5000000 .............................COL8,5発生日 .............* IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070429CF0F0F0F0F5000000 .............COL2,5通番 .............*...............*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF0F0F0F0F5000000 .............COL2,5通番......COL8,5発生日 .............*...............*.........*. IN1.F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2.F10000001CF1F1F2020070430CF1F0F0F0F6000000 .............COL2,5通番......COL8,5発生日 .......................................COL17,1企業区分
- zap35
- ベストアンサー率44% (1383/3079)
#01です。マクロを書いてみました。このマクロではコメントを取り出すところには配列をしようしましたが、文字列処理では配列は使っていません でも正確な仕様がまだ曖昧なので動きがご期待に沿える自信はありません。末尾に実際にテストしたデータと結果をのせましたので、テキストエディタに貼り付けて見てみて下さい(Webではとんでもなく表示が崩れます) このマクロは以下の前提で書いています 1)比較結果で「*」が付くカラムからコメントを表示するようにしました。 2)cstColには各フィールド末尾のカラム数を指定しています。ただしここでい言うカラム数とは「excelのデータで何桁目」を意味します。 ですからファイル区分は「IN1 F1」の6桁目、通番は「IN1 F10000000C」なので14桁目を指定しています。 Sub Macro1() Dim idxR As Long Dim ptr, idxA As Integer Dim str As String Dim trg As Range Dim aryCol, arytxt Const cstCol As String = "6,14,30,40" '各フィールド末尾のカラム数。区切り文字は「,」 Const cstTxt As String = "COL1,1ファイル区分@COL2,5通番@COL8,5発生日@COL17,1企業区分" '区切り文字は「@」 aryCol = Split(cstCol, ",") arytxt = Split(cstTxt, "@") For idxR = Range("A65536").End(xlUp).Row To 1 Step -1 ptr = InStr(Cells(idxR, "A"), "*") If ptr > 0 Then Set trg = Cells(idxR, "A").Offset(3, 0) trg.ClearContents End If Do While ptr > 0 For idxA = 0 To UBound(aryCol) If ptr <= Val(aryCol(idxA)) Then str = arytxt(idxA) Exit For End If Next idxA If LenB(StrConv(trg, vbFromUnicode)) < ptr - 1 Then trg = trg & Application.Rept(" ", ptr - LenB(StrConv(trg, vbFromUnicode)) - 1) trg = trg & str Else trg.Offset(1, 0).Insert Set trg = trg.Offset(1, 0) trg = trg & Application.Rept(" ", ptr - LenB(StrConv(trg, vbFromUnicode)) - 1) trg = trg & str End If ptr = InStr(ptr + 1, Cells(idxR, "A"), "*") Loop Next idxR End Sub テストデータ(桁数を確認するためにエディタに貼り付けて見て下さい) * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000000CF1F1F2020070430CF0F0F0F0F5000000 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070429CF0F0F0F0F5000000 * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF0F0F0F0F5000000 * * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF1F0F0F0F6000000 実行結果(エディタに貼り付けて見て下さい) * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000000CF1F1F2020070430CF0F0F0F0F5000000 COL8,5発生日 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070429CF0F0F0F0F5000000 COL2,5通番 * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF0F0F0F0F5000000 COL2,5通番 COL8,5発生日 * * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF1F0F0F0F6000000 COL2,5通番 COL8,5発生日 COL17,1企業区分 以下は勝手な想像ですが、believe_meさんが文字列処理に配列を使おうとしたのは、文字列を「固定長」で考えているからではないでしょうか(COBOLerですか?)。「可変長」と考えればLen関数で「2行目が必要かどうか」は簡単に判断できます。
補足
回答ありがとうございます。 メインフレームから10年以上遠ざかっていましたが、最近また担当になりました。 使ったことのある言語はアセンブラとPL/Iで、コボルはほとんどやったことはありませんし、クドイ表現の多いコボルは大嫌いです。 現在の職場もPL/Iです。
現在の書式を変更できるなら、レコードを項目ごとに別々のセルに格納たほうが簡単だと思います。 そうすればデータの項目名は先頭行にタイトルとして書いておけば済みます。 値に差異があるところ(セル)は「*」がデータの上についているようですからどの項目に差異があるのかもわかります。
補足
回答ありがとうございます。 ホストコンピュータで実行されているのは汎用のコンペアプルグラムです。 特定のアプリケーションやファイルのものではありません。 従って、各項目の位置・長さを認識していませんので、レコード全体がベタでリストされています。 ホスト側で項目毎に別のセルに入れるのは不可能です。 PC側ではファイルの情報を持っているので分けることは可能ですが、できるだけホストで出力されるリストの体裁を崩さないで、分かりやすい表示にすることが今回の目的の一つでもあります。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんばんは。#2です。 私自身、そういう、文字長を扱ったVBA+ワークシートのセルへの入力のものの取り扱った経験はあるけれど、最終的には、Excelで行っていて、私のスキルとは別に、やりにくいなっていう感じが残りました。 最終的には、そのマクロとヘルプメニューまで作って、気に入らないので投げてしまいました。文字位置などは、同じ文字を使う限り(例 :「半角スペース」+「*」)は、正確に入ります。複雑な内容(質問のような文字を入れる)のような場合は、ワン・セルの1列に入れる限りは、出来るけれども、何かシックリとしてこないのです。(あくまでも、ユーザーは一般の方を想定した場合です。) そういう私は、未だ、この問題を解決しているわけではありません。おそらく、Excelでは無理というか、Web + JavaScript なんていう組み合わせよりも、表現力が落ちるようですね。私は、Web系には向かうことは、まずないだろうとは思いますが、時々、うらやましくなります。 それと、出来れば、#1さんの質問には、積極的に回答してほしかったですね。 私のようなものでも、ある程度のことは理解は出来るはずです。一つ一つの回答自体も経験のうちに入りますので、もし、そういうようなことを公開したくないようでしたら、もう少し、時系列で分かる簡単なサンプルにしたほうがよかったかもしれません。 今、私の分かる範囲は、全角文字で文字を入れると、位置決めが出来ないっていうことだけを回答すると、こんなものになると思います。セル自体は、お決めくださいね。若干、正規表現で、RegExp を使ったのは、面白くないのですが、コードが短くなるので使いました。仮に違っていても、ヒントぐらいにはなると思います。 早い話、これは全角・半角の位置の狂わない上書きの代入サブルーチン型のプロシージャ(厳密にはマクロとは呼びません)です。前の位置にバッティングするようだと、メッセージが出て代入できません。なお、これは、2回までですが、3回目になると、コードが複雑になります。今、調べた限りでは、2度目の文字列代入で、位置(LocationNum)は、正しく入っています。 Sub Test1() '初期入力 InsertCharFirst Range("A4"), "COL8,5発生日", 6 End Sub Sub Test2() '二番目入力 InsertCharSecond Range("A4"), "COL2,5通番", 25 End Sub 'サブルーチン Sub InsertCharFirst(rng As Range, strCell As String, LocationNum As Integer) 'rng:代入対象セル, strCell:代入文字列, LocationNum:位置の桁 Dim buf As String Dim strLen As Integer buf = String(132, " ") '最初 strLen = LenB(StrConv(strCell, vbFromUnicode)) Mid(buf, LocationNum, strLen) = strCell buf = String(132, " ") '132 の半角スペースを入れる strLen = LenB(StrConv(strCell, vbFromUnicode)) Mid(buf, LocationNum, strLen) = strCell rng.Value = buf End Sub Sub InsertCharSecond(rng As Range, strCell As String, LocationNum As Integer) 'rng:代入対象セル, strCell:代入文字列, LocationNum:位置の桁 Dim buf As String Dim newStrLen As Integer Dim oldStrLen As Integer Dim oldLocationNum As Integer Dim oldStrText As String Dim Matches As Object 'Matches Dim Match As Object 'Match Dim Re As Object 'RegExp newStrLen = LenB(StrConv(strCell, vbFromUnicode)) Set Re = CreateObject("VBScript.RegExp") With Re .Pattern = "[^ ]+" .Global = True oldStrLen = LenB(StrConv(strCell, vbFromUnicode)) buf = rng.Value If buf <> "" Then Set Matches = .Execute(buf) If Not Matches Is Nothing Then oldLocationNum = Matches(0).Firstindex oldStrText = Matches(0).Value oldStrLen = LenB(StrConv(oldStrText, vbFromUnicode)) End If End If If (LocationNum < (oldLocationNum - newStrLen)) Or _ (LocationNum > (oldLocationNum + oldStrLen)) Then Mid(buf, LocationNum, newStrLen) = strCell rng.Value = buf Else MsgBox "そこには代入できません。", vbCritical End If End With Set Re = Nothing End Sub なお、 >配列の定義は「Dim Tbl(132) As String」です >1行が132文字ですから、132個の要素がある配列を定義しています。 私も、その方法は知らないわけではありませんが、その方法は、VB系では使いません。もちろん、Unicode文字をByte 型で入れる分には、全角・半角の判定が出来ますので良いとは思いますが、たぶん面倒だと思います。VB系は、また独特の使い方があります。それと、VBAは、配列に使うのは、概ね、セルに対してまでです。
補足
回答ありがとうございます。 >上書きの代入サブルーチン型のプロシージャ 私もFunctionにしています。 代入される側の文字列、代入位置、代入文字列を渡して、代入可能ならその結果を、 代入不可能(その場所にすでに文字が埋まっている)ならば空白を返すように しています。 回答して頂いたマクロなんですが、正規表現(RegExp)を使うとは面白いアイディアですね。 ただ結果が私の意図したものとちょっと違っているようです。 最初の「InsertCharFirst Range("A4"), "COL8,5発生日", 6」では正しく6桁目に代入されますが、2回目の「InsertCharSecond Range("A4"), "COL2,5通番", 25」では25桁目ではなく28桁目になっています。 これは最初に代入された「発生日」が全角であり、半角文字より3桁増えているのが考慮されていないように思われます。 それとすでに文字が埋まっている場所に対して実行しても"そこには代入できません。"というメッセージが返ってこずに、新しい文字列が上書きされてしまいます。 折角回答を頂いてゴチャゴチャ言って申し訳ありません。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。Wendy02です。 #1さんに先を越されてしまいましたが、内容的には同じかもしれません。 しばらく読んでいて、肝心なことが見えてきません。 それは、「元のソース」が、「結果」として、どうなることなのですか? >配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 最終的な質問が、もし、このようなら、回答のしようはないと思います。配列自体の問題ではないからです。ほとんどのプログラム言語は、配列を避けられませんし、それを避けて処理するということはありえません。 >等幅フォントの文字列に全角文字列を挿入(置換え)します。 こういうことって、それは、Excelの表示の問題で、フォント自体は関係ないと思います。 「ソース」が、単なるテキストデータだと想像すると、デフォルトを変えておけば済む話だと思います。 >入れようとする位置に既にコメントがある場合、空白行を追加してから挿入します。 は、どうやっていれるかですね。人間の手で入れるのでしょうか? 次に、マスという概念が分かりません。 「配列を作って1文字づつ配列のマスに入れる。」そういう方法は、VB系にないと思います。かろうじて、Byte 型の変数にしか、そういう痕跡が見られません。 >ホストリストは数万行になる場合があり、配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 もともと、なぜ、ワークシートを使っているのかが見えてこないのです。数万行となると、一人の人間の手では、ほとんど不可能になってきます。もしかしたら、VBAのテキストストリームだけで処理してしまう内容のような気もするのですが、そうしたら、ほとんど配列は使わないですね。
補足
回答ありがとうございます。 ホストの本体は遠隔地にあり、ホストでプリントしたものは数日後でないと入手できません。 私のいる開発環境では大量のプリント時を除き、通常ホストリストはPCにダウンロードし、PCで見るなりプリントアウトします。 数万行というのは滅多にありません。通常は数百行程度です。 配列の定義は「Dim Tbl(132) As String」です。 ホストリストは1行が132文字ですから、132個の要素がある配列を定義しています。 ストリングで定義していますが、配列の1要素に1文字を入れてます。 お聞きしたいことは 「配列を使わないで、文字列の操作だけで処理が実現できないか」 と言うことになると思います。 こちらの方が処理速度が速いような気がします。 尚、テキストストリームではなく、エクセルに取り込まれたリストを 自分で範囲指定し、この処理を実行するように考えております。
- zap35
- ベストアンサー率44% (1383/3079)
やりたいことが今ひとつ理解できません。SE(?)の文章とは思えませんw 以下の質問に回答する形式で補足お願いします。 1)サンプルデータの意味が分かりません * → これが1行目の比較内容ですか? 比較内容の行であることは何で判別すればよいですか? IN1 … → 先頭3ByteがIN1の行がファイル1の内容ですか? (8カラム目から5Byteがパック10進の日付になっていないと思いますが、データの先頭はどこですか) (なお余談ながらF1000000Cの部分は0が一つ足りない、または多くないですか。000000Cのカラムもパック10進では?) IN2 … → 先頭3ByteがIN2の行がファイル2の内容ですか? 2)元のデータで4行目は必ず空白行があるのですか 3)そもそもどのようなコメントを入れるのですか? 4)「コメント挿入は同じ行に複数回入れることがあります。」と「入れようとする位置に既にコメントがある場合、空白行を追加してから挿入します。」は矛盾するように感じるのですが、この点もわかりません。処理を複数回実行するのでしょうか 実際のデータサンプル(10行程度)とVBAによって加工した結果がどうなって欲しいかを(同じく10行程度)書いていただく方が理解が早いと思います。
補足
No1様、No2様 ええと回答ありがとうございます。一応SEでございます。 やりたいことは、ホストでファイル比較した結果をPCにダウンロードしたものに 対して、比較結果が分かりやすいように該当個所に位置・長さ・項目名称を表示 すると言うものです。 ファイルの各項目の位置・長さ・項目名称は既にエクセルで持っております。 コメント挿入、行追加は全てVBAで自動で行います。 処理のイメージは以下の通りです。 自宅にホストデータが無いので手打ちです。(最初はミスってしまいました) 元の状態 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000000CF1F1F2020070430CF0F0F0F0F5000000 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF0F0F0F0F5000000 * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF0F0F0F0F5000000 * * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000000CF1F1F2020070430CF1F0F0F0F6000000 VBAで処理後 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000000CF1F1F2020070430CF0F0F0F0F5000000 COL8,5発生日 * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070429CF0F0F0F0F5000000 COL2,5通番 * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF0F0F0F0F5000000 COL2,5通番 COL8,5発生日 * * * IN1 F10000000CF1F1F2020070429CF0F0F0F0F5000000 IN2 F10000001CF1F1F2020070430CF1F0F0F0F6000000 COL1,1ファイル区分 COL8,5発生日 COL17,1企業区分 ※Webにアップすると中々うまく位置が合いません。 ずれていたらゴメンナサイ。
お礼
「Garbage in,garbage out」とのことですが、例にしたデータはともかく実際のコンペアでほとんどの項目がアンマッチになるケースは存在します。
補足
回答ありがとうございます。少し条件を追加しましたら、思惑通りの結果となりました。 Web上で字下げが見えるように半角スペースを全角スペースに置き換えております。 Sub Macro20() Dim idxR As Long Dim ptr, idxA, cnt As Integer Dim str As String Dim strBefore As String '追加しました。 Dim psw As Boolean Dim trg, rng As Range Dim aryCol, aryTxt Const cstCol As String = "6,14,30,40" Const cstTxt As String = "COL1,1ファイル区分@COL2,5通番@COL8,5発生日@COL17,1企業区分" aryCol = Split(cstCol, ",") aryTxt = Split(cstTxt, "@") Application.ScreenUpdating = False On Error GoTo end0 For idxR = Range("A65536").End(xlUp).Row To 1 Step -1 strBefore = "" '追加しました。 ptr = InStr(Cells(idxR, "A"), "*") If ptr > 0 Then Set trg = Cells(idxR, "A").Offset(3, 0) trg.ClearContents End If cnt = 0 Do While ptr > 0 For idxA = 0 To UBound(aryCol) If ptr <= Val(aryCol(idxA)) Then str = aryTxt(idxA) Exit For End If Next idxA If str <> strBefore Then '追加しました。 strBefore = str '追加しました。 psw = False For Each rng In Range(trg, trg.Offset(cnt, 0)) If LenB(StrConv(rng, vbFromUnicode)) < ptr - 1 Then psw = True Exit For End If Next rng If psw = False Then cnt = cnt + 1 trg.Offset(cnt, 0).Insert Set rng = trg.Offset(cnt, 0) End If rng = rng & Application.Rept(" ", ptr - LenB(StrConv(rng, vbFromUnicode)) - 1) rng = rng & str End If '追加しました。 ptr = InStr(ptr + 1, Cells(idxR, "A"), "*") Loop Next idxR end0: Application.ScreenUpdating = True End Sub