• ベストアンサー

VBA、Excel、文字列の置換について

エクセルのVBAを勉強しているものなのですが 行き詰ってしまったので有識者の方、アドバイスをお願いします 目的:セルに入力されているカンマで区切られた文字列(例、1,2,5,6,7,8,10,11・・・)で連番の場合間の数字を"-"で省略(例、1,2,5-8,10,11・・・)する関数の作成 以下、プログラム (1)カンマで区切られた文字列をスプリットし、配列化 For Each cl In moji myData = Split(cl, ",") Next (2)3つ以上の連番の場合、"-"で文字列の短縮化 For l = 1 To UBound(myData) If myData(l) = myData(l + 1) - 1 Then If myData(l) = myData(l - 1) + 1 Then myData(l) = "-" ElseIf myData(l) = "-" Then myData(l) = "" Else myData(l) = myData(l) & "," End If Else myData(l) = myData(l) & "," End If Next l (3)配列をカンマで区切られた文字列として出力 For m = 0 To UBound(myData) bunkai = bunkai & myData(m) Next m

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

  • ベストアンサー
  • hotosys
  • ベストアンサー率67% (97/143)
回答No.4

こんなのはどうでしょうか? 連続でなく3連続で省略する場合です。(1,2は省略せず、1,2,3は1-3に省略します。) 配列のデータのあるデータに着目すると、-になるのは自分の前後が連番の場合になると思います。 例えば2,3,4で、3に着目している場合などです。 最初と最後は-になる事は無いのでそのまま出力して、2番目から最後から2番目までをチェックします。 まず、基本的な考え方です。 Sub sample1() Dim cl As String '元文字列 Dim dst As String '結果文字列 Dim myData() As String Dim l As Integer cl = "1,3,5,6,7,8,9,10,11,13,14,15" myData = Split(cl, ",") dst = myData(0) & "," '最初はそのまま For l = 1 To UBound(myData) - 1 If (myData(l) - myData(l - 1) = 1) And (myData(l + 1) - myData(l) = 1) Then '前後が連続なら dst = dst & "-," '- Else dst = dst & myData(l) & "," '前後が連続でない場合はそのまま End If Next dst = dst & myData(UBound(myData)) '最後はそのまま MsgBox dst End Sub ただし、このままでは連続が複数あると-,-,になってしまうのと、-の前後のカンマは不要なので、若干変更します。 Sub sample2() Dim cl As String '元文字列 Dim dst As String '結果文字列 Dim myData() As String Dim l As Integer cl = "1,3,5,6,7,8,9,10,11,13,14,15" myData = Split(cl, ",") dst = myData(0) & "," '最初はそのまま For l = 1 To UBound(myData) - 1 If (myData(l) - myData(l - 1) = 1) And (myData(l + 1) - myData(l) = 1) Then '前後が連続なら If Right(dst, 2) <> "-," Then '前が-でなければ(連続-にならないように) dst = dst & "-," '- End If Else dst = dst & myData(l) & "," '前後が連続でない場合はそのまま End If Next dst = dst & myData(UBound(myData)) '最後はそのまま dst = Replace(dst, ",-,", "-") ',-,を-だけにする MsgBox dst End Sub p.s. No.2さんへ 最後が連続してる場合(flag=trueでnext lを終えた場合)にチェックが必要ではないでしょうか Next l If flag = True Then bunkai = bunkai & "-" & myData(UBound(myData)) End If

sak1982515
質問者

お礼

回答ありがとうございます 三連続の場合の処理を苦しんでいたのですが解決しました シンプルですばらしいですね!

その他の回答 (3)

  • okormazd
  • ベストアンサー率50% (1224/2412)
回答No.3

やっつけ仕事 Sub test() mojiretu = Selection.Value '適当な文字列を指定してください moji = Split(mojiretu, ",") l = UBound(moji) For i = 0 To l - 1 moji(i) = moji(i) & "," 'あらかじめ","をつけてしまう Next i0 = 0 i = 0 Do While i < l - 1 While Val(moji(i)) + 1 = Val(moji(i + 1)) '連続しているかどうか調べる i = i + 1 Wend f = i - i0 '連続している個数 If f = 0 Then i = i + 1 End If i0 = i If f > 2 Then '6-9などの処理 j = i - f moji(j - 1) = Left(moji(j - 1), Len(moji(j - 1)) - 1) 'おしりの","をはずす moji(j) = "-" j = j + 1 While j < i moji(j) = "" '連続しているところは文字数0 j = j + 1 Wend End If Loop For i = 0 To l '組み立て mojiretu2 = mojiretu2 & moji(i) Next End Sub

sak1982515
質問者

お礼

回答ありがとうございます Val関数を使えばカンマが加わった配列でもif文が使えますね 勉強になりました ありがとうございま

  • bkbkb
  • ベストアンサー率33% (97/289)
回答No.2

動くか確かめてませんが For Each cl In moji myData = Split(cl, ",") temp = myData(0) bunkai = myData(0) flag = false For l = 1 To UBound(myData) If myData(l) = temp + 1 Then flag=true '連続しているよの印をつける Else if flag = true then '今まで連続していたら bunkai = bunkai & "-" & myData(l-1) & "," & myData(l) else '連続していなかったら bunkai = bunkai & "," & myData(l) end if flag = false '次に備えて End If temp = myData(l) Next l Next こんなんで多分動作するんじゃないでしょうか。 あんまりスマートじゃないですが…

sak1982515
質問者

お礼

素早い回答ありがとうございます なるほど、連続しているかしていないかの印をつけると分かりやすいですね 上記のプログラムを参考に勉強させていただきます

  • bkbkb
  • ベストアンサー率33% (97/289)
回答No.1

まず、一つ For Each cl In moji    myData = Split(cl, ",") Next myDataは配列になっていないので、この処理はダメですよ。 最後の行のデータしか結果が出ないでしょう myDataを配列にするか、このループの中に処理を入れてください。 If myData(l) = myData(l - 1) + 1 Then myDataは-や,を付けたりする処理を行っているので、myData(l - 1)は数字でない可能性があります。そこに1を足しても思った結果にはならないでしょう(-に1を足して-1になったりしますよ) それと、配列は0から始まります。 1からだとデータが足りなくなりますよ。 これを動くように書きなおすと、結構な変更になりますね…

関連するQ&A

  • エクセルVBAの文字列操作について2

    エクセルVBAの文字列操作について2 以前、こちらでご教授いただいた以下のような文字列操作方法があります。 この方法ですと例えば[1-3]から3をひいた際に"1-2"と表示されますが 今回は連続する数字が2つの場合は1,2と表示させ3つ以上の場合は-でつないで表示させたいと思います。 一週間ほど考えたのですが解決できませんでした。 どなたかご協力お願いいたします。 質問内容 例えば、[1-10,15-20,22-38]と入っているセルがあるとします。 このセルに数を足したり引いたりしたいのです。 例えば、このセルから”5”を引いて[1-4,6-10,15-20,22-38]と表示したり、 "21"を足して[1-10,15-38]と表示したい。 いただいたご回答  A1 セル に「1-10,12,15-20,22-38」と入力されているとして、別のセルに =NUMORDER(A1,-5) と入力すると「1-4,6-10,12,15-20,22-38」と表示し =NUMORDER(A1,21) と入力すると「1-10,12,15-38」と表示します。  1つ目の引数には「セル番地」または「文字列」を、2つ目の引数には「1 ~ 99 までの整数」をお入れください。 Function NUMORDER(myStr As Variant, num As Integer) As String  Dim i As Long  Dim j As Double  Dim myNum As Variant   '文字列中の スペース を削除  myStr = Replace(myStr, " ", "")   '文字列の前後に「0」・「100」を挿入  Select Case Left(myStr, 2)   Case "1,", "1-"    myStr = myStr & ",100"   Case Else    myStr = "0," & myStr & ",100"  End Select   '文字列を カンマ で分割し、ハイフン の区間の数字を補完する  myStr = Split(myStr, ",")  For i = 0 To UBound(myStr)   If InStr(myStr(i), "-") > 0 Then    myNum = Split(myStr(i), "-")    myStr(i) = ""    For j = myNum(0) To myNum(1)     myStr(i) = myStr(i) & " " & j    Next    myStr(i) = Trim(myStr(i))   End If  Next   '欠番に「●」を入れ、「数を足したり引いたり」する  myStr = Split(Join(myStr))  For i = 0 To UBound(myStr) - 1   myStr(i) = myStr(i) & Application.WorksheetFunction.Rept(" ●", myStr(i + 1) - myStr(i) - 1)  Next  myStr = Split(Join(myStr))  If num > 0 Then   myStr(num - myStr(0)) = num  Else   myStr(-num - myStr(0)) = "●"  End If   '前後に挿入した「0」・「100」を削除  myStr = Replace(Join(myStr), " 100", "")  If Left(myStr, 2) = "0 " Then myStr = Right(myStr, Len(myStr) - 2)   '連続数字を ハイフン で繋ぐ  myStr = Split(myStr, "●")  For i = 0 To UBound(myStr)   If myStr(i) <> " " Then   myNum = Split(Trim(myStr(i)))    If UBound(myNum) > 0 Then     myStr(i) = myNum(0) & "-" & myNum(UBound(myNum))    End If   End If  Next   'カンマ で文字列に分割する  myStr = Application.Trim(Join(myStr))  NUMORDER = Replace(myStr, " ", ",") End Function

  • 文字列の取り出し方

    今、Visual Basic 2008を使用しています。 textbox2とtextbox3があり、textbox2に複数行にまたがる文字列があります。 この文字列の中で、listbox1の中にある項目の文字列が入ってる場合はカンマ区切りで文字列の後ろにつなげたいのですが、うまくいきません。 具体的には あいうえお あかさたな いろはにほ というtextbox2の内容について、listbox1内に あ い という2つの項目があった場合、 あいうえお,あ,い あかさたな,あ いろはにほ,い という結果をtextbox3に書き出すという内容です。 Dim addtag As String = "" Dim i As Integer For Each part As String In TextBox2.Text.Split(vbCrLf) If part <> "" Then For i = ListBox1.Items.Count - 1 To 0 Step -1 If part.Contains(ListBox1.Items(i)) = True Then addtag = addtag & "," & ListBox1.Items(i) End If Next part = part & addtag TextBox3.Text = TextBox3.Text & part & ControlChars.NewLine part = "" addtag = "" End If Next というプログラムを組んでいますが、どこが間違っているのかわからず、煮詰まってしまいました。 プログラムは初心者で、根本から違っていたら恥ずかしい限りですが、どうかよろしくお願いします。

  • 【Excel VBA】カンマ毎にデータを区切る

    はじめて質問をさせて頂きます。 Excel VBAは初心者です。 仕事で必要なため、本を読みながら考えておりましたが、 手も足も出ない状態です。 【質問内容】 Excel VBAにて、ExcelファイルのA列のみに格納されているデータを カンマ「,」の位置毎に区切ります。 ※格納されているデータ例:A,B,C,D,E Excelの区切り位置にて、カンマで区切る処理と同じです。 A1から処理を開始し、A列のデータがなくなるまで 上記の処理を行います。 下記のプログラムを実行すると、1行目は正常にカンマ毎に 区切られますが、2行目以降はカンマ毎に区切られず、 そのままの状態です。 どこに問題があり、どのように修正すれば良いのでしょうか、 ご教示頂けると助かります。宜しくお願いします。 【プログラム】 Sub カンマ毎に区切る() Dim mydata As String Dim myArray() As String Dim i, j As Integer j = 0 Do While Cells(j + 1, "A").Value <> "" mydata = Cells(j + 1, 1) myArray() = Split(mydata, ",") For i = 0 To UBound(myArray) Cells(1, i + 1).Value = myArray(i) Next j = j + 1 Loop End Sub

  • excel VBAの文字列設定

    VBAで繰り返し作業を行っているのですが変数と文字列の組み合わせの設定に困っています。 for ~next(変数x)で繰り返しを行い medx の文字列を検索したいのですがうまくいきません。 疑問の部分は以下の範囲です 定義 x, y, i, ro, li as integer med1~medx までそれぞれ別の文字列(ex. med1= a med2 = b・・・ 統一性はないです) VBA部分 If y > 1 Then For x = 1 To y - 1 For i = 1 To 13 ←sheet数 For ro = 1 To 150 ←行 For li = 1 To 200 ←列 Worksheets("sheet" & i).Select If InStr(Cells(ro, li), "med" & x) > 0 Then ←疑問部分 med1、med2・・・を含むかどうか Cells(ro, li).Interior.ColorIndex = 3 Else End If Next Next Next Next else end if 上のように書くと"med1"を含むかどうがになってしまい、"a"を含むかどうかになりません。 わかりにくいかもしれませんが回答どうぞお願いします。

  • vba split関数 コンマ区切り

    エクセル・vbaに不慣れなためわかりづらかったら申し訳ありません。 コンマ区切りの数字をsplit関数で分割して指定セルに表示したいと考えており、以前質問し回答をいただいた内容でやりたいことが出来るようになりました。 ただし、若干出力場所等の変更を行いたいのですが、変更することが出来ません。 以前はA~C列にあるものをE~H列・J~M列・O~R列に表示する。 その際、A~C列にあるコンマ区切りの数字は3つのものと4つのものがあります。画像の上段部分をご確認ください。 その際のマクロは下記のとおりです。 Sub Test() Dim i As Long, j As Long, k As Long Dim tmp As Variant For i = 1 To 3 For j = 3 To 11 tmp = Split(Cells(j, i).Value, ",") For k = 0 To UBound(tmp) If k < 4 Then Cells(j, i).Offset(0, i * 4 + k).Value = tmp(k) End If Next Next Next End Sub 変更したいのは、AC8~AE16にコンマ区切りの数字があります。 AC列にある数字はAI8~AL16にAD列にある数字はAS8~AV16に AE列にある数字はBC8~BF16に表示したいと考えています。 コンマ区切りの数字は3つのものと4つのものがあります。 (画像の下段部分をご確認ください。) 上記のマクロでは下記の部分を変更する必要なのかと考えていますが、変更方法がわかりません。 お分かりの方教えていただけたら幸いです。 どうぞよろしくお願いいたします。 For k = 0 To UBound(tmp) If k < 4 Then Cells(j, i).Offset(0, i * 4 + k).Value = tmp(k)

  • 括弧が含まれる文字列の括弧の中身の文字列(VB6)

    括弧()の中身の文字列をそれぞれ配列の文字列変数に設定したいと考えているのですが、Replaceを使えばいいのでしょうか? また、Replaceは置き換える文字の検索の開始場所は設定できると思うのですが、置き換える文字の検索の終了の場所は設定できるのでしょうか? 例えば、(asdf)as(asdfe)as(sf)という文字列のasdf,asdfe,sfをそれぞれ配列を使って文字列変数として表したいのです。 nyuuryoku = Text1.Text For i = 1 To Len(nyuuryoku) If Mid(nyuuryoku, i, 1) = "(" Then k = k + "と" + CStr(i) j = j + 1 ElseIf Mid(nyuuryoku, i, 1) = ")" Then m = m + "と" + CStr(i) l = l + 1 End If Next i Text17.Text = "( は" + CStr(j) + "個" + k + "番目、 " + ") は" + CStr(l) + "個" + m + "番目" For i = 1 To Len(nyuuryoku) If Mid(nyuuryoku, i, 1) = "[" Then kk = kk + "と" + CStr(i) jj = jj + 1 ElseIf Mid(nyuuryoku, i, 1) = "]" Then mm = mm + "と" + CStr(i) ll = ll + 1 End If Next i Text2.Text = "[ は" + CStr(jj) + "個" + kk + "番目、" + "] は" + CStr(ll) + "個" + mm + "番目" Dim kakkohajime(50) As Long Dim kakkoowari(50) As Long Dim kakkonakami(50) As String For i = 1 To CStr(j) kakkohajime(0) = 1 kakkohajime(i) = InStr(kakkohajime(i - 1), nyuuryoku, "(") Next For i = 1 To CStr(j) kakkoowari(0) = 1 kakkoowari(i) = InStr(kakkohajime(CStr(j) + 1 - i), nyuuryoku, ")") Next このあとにkakkohajime(i)の場所からkakkoowari(i)の場所までの文字列をそれぞれkakkonakami(i)の配列の文字列にいれたいのです。 最後に、kakkonakami(i)をtextに表示したいと思っています。

  • 文字列から指定した文字を取り出す

    たとえば $test = "■-●-△-★-■■-■-■"; という文字列があったとして、 -で文字を区切り、■■は含めず■のみを取り出したい場合、 どのようにしたらいいのでしょうか。 $split = split("-",$test); $count_split = count($split); for($i=0; $i < $count_split; $i++){ if($split[$i] == "■"){ echo "{$split[$i]}"; } } としていますが、もっとスマートにできないのでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • 文字列の最後を変化させたい

    業務でマクロを使うことになり、ご教示お願い致します。 (例) 実行前 →実行後 C列     C列 001     001 003     001-1 002     001-2 005     002 001     002-2 001     003 002     005 同じ文字が複数ある場合、2個目以降には”-1”、”-2”と区別し、並べ替えを実行。 (データはA列~BI列まで入っていますので、C列が動いた場合、連動させる形で…。) ActiveWorkbook.Worksheets(BaseSheet).Activate p = HeaderPos + 1 For i = (HeaderPos + 1) To SearchNum CelValue = Range(Inbound & i).Value For m = 0 To SearchNum If KindType(m) = CelValue Then KindCount(m) = KindCount(m) + 1 Range(Inbound & i).Value = KindType(m) + CStr(KindCount(m)) Exit For ElseIf KindType(m) = "" Then KindType(m) = CelValue KindCount(m) = KindCount(m) + 1 Range(Inbound & i).Value = KindType(m) + CStr(KindCount(m)) Exit For End If Next If CelValue = "" Then Exit For End If Next イメージはこんな感じなのですが、お分かりになる方よろしくお願いいたします。

  • マクロ 文字列の比較について質問

    いつもお世話になっています。 マクロの文字列の比較方法について質問致します。 異なるシートの文字列を比較して、一致したら処理をするというマクロを作っているのですが、文字列の比較がうまくいきません。 解る方がいましたらアドバイスをお願いします。 Rangeの使い方がおかしいのでしょうか? For L = 1 to LAST step 1 If Range(Sheet1.Cells(L, 1)).Text = Range(Sheet2.Cells(M, 2)).Text Then ・ ・ ・ end if ※Mは定数です。

  • EXCEL VBA で複数の特定文字に色をつけたい

    マクロ実行で以下のように一括色変更できないでしょうか? 1文字での変更は下記コードでおこなうことができましたが、複数であると初心者でとても分かりません。 ※S25とF30.、F5.は加工進行でいろいろ数値のみ変えます。 ※M100、M101は全体の4文字は変わりませんが数字は増えていき、ランダムにこの先の加工進行上でてきます。 ※M03、M00は3文字で変わりません。 現在以下のコードで1文字ずつならできます。 Sub test01() Dim cl As Range For Each cl In Range("a1:a10") r = InStr(cl, "M00") If r <> 0 Then cl.Characters(r, 3).Font.ColorIndex = 3 End If Next End Sub

専門家に質問してみよう