• ベストアンサー

全角文字列を挿入するには

エクセル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)以上がおわったら配列から取り出す。  取り出す際、全角文字の場合、次のマスを読み飛ばす。 ホストリストは数万行になる場合があり、配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 もう少し考えれば出来るような気がしますが、これだけ考えるだけで疲れてしまいました。 よろしくお願い申し上げます。

質問者が選んだベストアンサー

  • ベストアンサー
  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.8

#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

believe_me
質問者

お礼

「Garbage in,garbage out」とのことですが、例にしたデータはともかく実際のコンペアでほとんどの項目がアンマッチになるケースは存在します。

believe_me
質問者

補足

回答ありがとうございます。少し条件を追加しましたら、思惑通りの結果となりました。 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

その他の回答 (8)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.9

こんにちは。Wendy02です。 >最初に代入された「発生日」が全角であり、半角文字より3桁増えているのが考慮されていないように思われます。 ロジックとしては間違いがないので、おそらく、正規表現パターンの{  "[^ ]+" }ではなくて、何か加えなくてはならないのかもしれません。何か別のものを数えているようです。 ただ、私としては、zap35さんが、集中的におやりになっているので、zap35さんに対して迷惑になりかねますし、believe_meさんへの負担にもなりますので、これ以上は、介入するつもりはありません。誰か一人が解決すればよいことですから。

believe_me
質問者

お礼

皆様、沢山の回答、ありがとうございました。 解決案が見えてきましたので、回答を締めさせていただきます。 最初の質問の仕方にちょっと問題があったようで反省しております。 本当のところ、ホストのリストはもうちょっと複雑です。 ホストのファイル長は数百~数千バイトですし、リストの表示も10桁(16進表記では20桁)毎に空白が空いています。 問題を単純化して質問したつもりが、逆に皆様を混乱させてしまったようです。 また質問させていただくことがあると思いますが、その時はよろしくお願い申し上げます。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.7

#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企業区分

believe_me
質問者

補足

実行してみました。 サンプルデータでは上手くいきましたが、データによっては思わぬ結果になってしまうようです。 ご提示いただいたプログラムを読みきっていないので何が原因なのかまだ分かっておりません。 ちょっと極端な例ですが、以下のようなデータの場合、 **************************************** 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)
回答No.6

#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)
回答No.5

#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行目が必要かどうか」は簡単に判断できます。

believe_me
質問者

補足

回答ありがとうございます。 メインフレームから10年以上遠ざかっていましたが、最近また担当になりました。 使ったことのある言語はアセンブラとPL/Iで、コボルはほとんどやったことはありませんし、クドイ表現の多いコボルは大嫌いです。 現在の職場もPL/Iです。

noname#258293
noname#258293
回答No.4

現在の書式を変更できるなら、レコードを項目ごとに別々のセルに格納たほうが簡単だと思います。 そうすればデータの項目名は先頭行にタイトルとして書いておけば済みます。 値に差異があるところ(セル)は「*」がデータの上についているようですからどの項目に差異があるのかもわかります。

believe_me
質問者

補足

回答ありがとうございます。 ホストコンピュータで実行されているのは汎用のコンペアプルグラムです。 特定のアプリケーションやファイルのものではありません。 従って、各項目の位置・長さを認識していませんので、レコード全体がベタでリストされています。 ホスト側で項目毎に別のセルに入れるのは不可能です。 PC側ではファイルの情報を持っているので分けることは可能ですが、できるだけホストで出力されるリストの体裁を崩さないで、分かりやすい表示にすることが今回の目的の一つでもあります。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんばんは。#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は、配列に使うのは、概ね、セルに対してまでです。

believe_me
質問者

補足

回答ありがとうございます。 >上書きの代入サブルーチン型のプロシージャ 私もFunctionにしています。 代入される側の文字列、代入位置、代入文字列を渡して、代入可能ならその結果を、 代入不可能(その場所にすでに文字が埋まっている)ならば空白を返すように しています。 回答して頂いたマクロなんですが、正規表現(RegExp)を使うとは面白いアイディアですね。 ただ結果が私の意図したものとちょっと違っているようです。 最初の「InsertCharFirst Range("A4"), "COL8,5発生日", 6」では正しく6桁目に代入されますが、2回目の「InsertCharSecond Range("A4"), "COL2,5通番", 25」では25桁目ではなく28桁目になっています。 これは最初に代入された「発生日」が全角であり、半角文字より3桁増えているのが考慮されていないように思われます。 それとすでに文字が埋まっている場所に対して実行しても"そこには代入できません。"というメッセージが返ってこずに、新しい文字列が上書きされてしまいます。 折角回答を頂いてゴチャゴチャ言って申し訳ありません。

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。Wendy02です。 #1さんに先を越されてしまいましたが、内容的には同じかもしれません。 しばらく読んでいて、肝心なことが見えてきません。 それは、「元のソース」が、「結果」として、どうなることなのですか? >配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。  最終的な質問が、もし、このようなら、回答のしようはないと思います。配列自体の問題ではないからです。ほとんどのプログラム言語は、配列を避けられませんし、それを避けて処理するということはありえません。 >等幅フォントの文字列に全角文字列を挿入(置換え)します。 こういうことって、それは、Excelの表示の問題で、フォント自体は関係ないと思います。 「ソース」が、単なるテキストデータだと想像すると、デフォルトを変えておけば済む話だと思います。 >入れようとする位置に既にコメントがある場合、空白行を追加してから挿入します。 は、どうやっていれるかですね。人間の手で入れるのでしょうか? 次に、マスという概念が分かりません。 「配列を作って1文字づつ配列のマスに入れる。」そういう方法は、VB系にないと思います。かろうじて、Byte 型の変数にしか、そういう痕跡が見られません。 >ホストリストは数万行になる場合があり、配列を使わないでもっと効率よくやるにはどうしたらよいでしょうか。 もともと、なぜ、ワークシートを使っているのかが見えてこないのです。数万行となると、一人の人間の手では、ほとんど不可能になってきます。もしかしたら、VBAのテキストストリームだけで処理してしまう内容のような気もするのですが、そうしたら、ほとんど配列は使わないですね。

believe_me
質問者

補足

回答ありがとうございます。 ホストの本体は遠隔地にあり、ホストでプリントしたものは数日後でないと入手できません。 私のいる開発環境では大量のプリント時を除き、通常ホストリストはPCにダウンロードし、PCで見るなりプリントアウトします。 数万行というのは滅多にありません。通常は数百行程度です。 配列の定義は「Dim Tbl(132) As String」です。 ホストリストは1行が132文字ですから、132個の要素がある配列を定義しています。 ストリングで定義していますが、配列の1要素に1文字を入れてます。 お聞きしたいことは 「配列を使わないで、文字列の操作だけで処理が実現できないか」 と言うことになると思います。 こちらの方が処理速度が速いような気がします。 尚、テキストストリームではなく、エクセルに取り込まれたリストを 自分で範囲指定し、この処理を実行するように考えております。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.1

やりたいことが今ひとつ理解できません。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行程度)書いていただく方が理解が早いと思います。

believe_me
質問者

補足

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にアップすると中々うまく位置が合いません。 ずれていたらゴメンナサイ。

関連するQ&A

  • 全角文字と半角文字を判別して文字列を追加

    全角文字と半角文字が混合している文字列に文字を追加するプログラムを考えています。 仕様としては全角から半角に変わる際には全角文字の後ろに1234を、 半角から全角に変わるときは半角文字の後ろに4321をつけるというものです。 例1 文字列が「あxxxお」ならば出力結果は「あ1234xxx4321お」 そこで質問なのですが 文字列から全角文字と半角文字をプログラム上で判別して 上記のように出力するにはどうしたらいいんでしょうか? ヒント等ございましたらどうぞお願いします。 とりあえず作ってみた例1の結果を無理やり出力するプログラムのコードを載せておきます。 こちらをうまく改変してくださっても結構ですのでよろしくお願いいたします。 #include <stdio.h> #include <string.h> int main(void){ unsigned char str0[256] = "あxxxお", str1[256] = "1234",str2[256]= "4321"; unsigned int zh,hz, len0 = strlen(str0),len1=strlen(str1),len2=strlen(str2); printf("挿入前:%s\n",&str0); zh=2; //全角から半角に変わる位置 hz=5; //半角から全角に変わる位置 //1234を挿入/// memmove(&str0[zh+len1], &str0[zh], len0 - zh+1); memcpy(&str0[zh], str1, len1); //4321を挿入/// memmove(&str0[hz+len1+len2], &str0[hz+len1], len0); memcpy(&str0[hz+len1], str2, len2); printf("挿入後:%s\n",&str0); return 0; }

  • 全角・半角混在の文字列から半角文字のみ取り出す

    エクセル勉強中です。問題集で理解できないところがあります。 数式がどういう意味をもつのか教えて頂けるとありがたいです。 よろしくお願いします。 画像添付の問題になります。 A列に製品名が入っています。(製品番号:半角文字)(製品名:全角文字) B列に半角文字の製品番号だけを取り出しなさいというものです。 半角文字の開始位置がバラバラになっているところが問題のポイントになっています。 回答ですが B2: =MID(A2,MATCH(1,INDEX(LENB(MID(A2,COLUMN(2:2),1))*1,0),),LEN(A2)*2-LENB(A2)) こちらで半角文字のみ取り出せるようです。回答には数式のみで何故この関数を使うのか? 使うことでどういった結果を導くなどの解説が一切ありません。(ちなみに出版会社の便利技的な問題集です) MID関数で製品名A2から開始位置を指定して、全角半角をLEN関数LENB関数で半角文字数を 算出して文字列を抽出するという事は理解できます。 ただ、この開始位置の指定の所が理解できません。 数式を分割してみましたが =MID(A2,COLUMN(2:2),1)の所はどの行も製品名の1文字目ですよね・・・ その値にLENB関数で文字数? 数式の検証で見てみると配列のような結果が次々と現れて・・・ MATCH関数もありますしINDEX関数が何か関係しているような気はしているのですが、 INDEX関数と言えば配列に行番号・列番号と例えば表の該当するセルの位置抽出の 知識しかありません。一つのセルでINDEX関数? すいません。独学で勉強していてこの程度の知識ですが、この数式の考え方教えてくださる方よろしくお願いします。

  • 指定列に文字列を付加する(VBA)

    複数行からなるテキストファイルを読み込んで、各行の10列目に連番をふるマクロを作成しています。 一行が10列に満たない場合はスペースを挿入して連番の位置を揃えたいのですが、 MIDやLENを使用すると全角と半角が混在している行の場合、連番の位置がガタガタになって困っています。 具体的には次のようになってしまいます。 ABCD_001 ABCD_001 次のように整形したいのですがどういった方法が考えられるでしょうか?どうぞご助力下さい。 ABCD__001 ABCDE_____001

  • 文字列の数抽出、行挿入マクロ

    急きょ下記処理を実施することになったのですが、本やネットで下記処理ができるような マクロを色々探していもなかなか見つからず…。(T_T) どなたか詳しい方がいらっしゃいましたら教えていただけませんでしょうか? ・A列に特定の文字列(;)があった場合、その列をコピー。 ・その列の下に文字列(;)の数と同数の行を挿入。 ・挿入した行のAセルに、文字列(;)のすぐ後ろの1ケタを貼り付け。 ・(挿入行が2行の場合) さらに下に挿入した行のAセルに、左から2つ目の文字列(;)の  すぐ後ろの1ケタを貼り付け。 なお、A列の行数は、現時点で500行ほどあり、今後増える可能性もあります。 【処理する前】       A列      B列    C列 1行目  1;32     555   AAA 2行目  29;1;4   222   GGG 3行目  600      111   FFF 【マクロ実行後】       A列    B列   C列 1行目  1     555   AAA 2行目  32    555   AAA 3行目  29    222   GGG 4行目  1     222   GGG 5行目  4     222   GGG  6行目  600   111   FFF どうぞよろしくお願いいたします。

  • 一番初めに文字列が入っている列の文字列を知りたい

    次の条件で、よりA列に近い文字列を引っ張り出すにはどのような関数を使えば良いのでしょうか? 1)行の中にそれぞれ"文字列"が入っている 2)文字列が入っているセル数は行によって異なる   【A】 【B】 【C】 【D】 【E】 【1】りんご 【2】   ばなな 【3】   みかん りんご 【4】ばなな           みかん この回答を【F】列に示す場合、 【F1】はりんご、【F2】はばな、【F3】はみかん、【F4】はばなな、になって欲しいのです。 上手く質問できないのですが、とても困っています。宜しくお願いします。

  • 全角文字と半角文字切れ目に挿入したい

    (任意の)全角文字の次に(任意の)半角文字が続く場合、その間にタブを挿入し、 漢字abc ↓ 漢字     abc (任意の)半角文字の次に(任意の)全角文字が続く場合、その間に改行を挿入したいのですが abc漢字 ↓ abc 漢字 そのようなことができるエディタ等がありましたらお教えください。

  • C言語で全角文字を扱いたいのですが、

    C言語で全角文字を扱いたいのですが、 全角文字列を入力して特定の箇所の文字(例えば3文字目)を抜き出して、表示するという感じのプログラムをしたいのですが、うまくいきません。 半角文字ならば、配列を使ってできるのですが・・・・・

  • fgetcで全角文字列の読み込み

    ファイルから一文字ずつ全角文字を読み込んで、それを配列を格納する場合、C言語では、どのようなコードになるのですか? 一バイトの場合は簡単ですが、2バイトは分かりません。 fgetcはint型を返すみたいです。 教えて下さい。お願いいたします。

  • 全角半角考慮した文字列分割

    A列           B列         C列 あいうえおかきくけこ  あいうえ      おかきくけこ アイウエオカキクケコ   アイウエオカキクケ  コ あいうえオかきくけこ   あいうえオ    かきくけこ A列に全角半角混在のテキスト項目があります。 B列、C列に以下のルールで分割したいのですが、Excel関数で 実現可能でしょうか?可能な場合は式をご教授して 頂けますでしょうか。宜しくお願い致します。 ※全角をバイト数指定で分割して文字化けしないように 全角半角を考慮して分割したいと考えております。 B列  A列9桁目が半角の場合は半角9文字 A列9桁目全角の場合は半角8文字(全角4文字)をB列へ C列  A列10桁目が半角の場合は、左端10桁目~半角9文字 A列10桁目が全角の場合は、左端9桁目~半角9文字

  • 特定の文字列を挿入

    テーブルのセルに特定の文字列を挿入する方法は御座いませんか? 例えば、 HTMLファイル <html> <head> </head> <body> <table> <tr><td> (1) </td><td> (2) </td></tr> <tr><td> (3) </td><td> (4) </td></tr> </table> </body> </html> とあった場合 JavaScriptファルには (1)に挿入する内容 (2)に挿入する内容 (3)に挿入する内容 (4)に挿入する内容 を書いてHTMLファイルに書き出しをしたいのです。 document.write('');を使って書き出す方法は知っていますが、指定した場所に貼り付けたい場合複数ファイルが必要になりますよね? それでは不便なので、JavaScriptファルは外部化で1つのファイルにし、指定箇所に文字列を挿入する方法を教えてください。 printを使えばいいんでしょうか?

専門家に質問してみよう