Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : Microsoft 365)
セル内で並び替え
投稿日時: 24/03/22 08:00:23
投稿者: nob1122

同一セル内のデータを並び替えしたいです。
具体的には、
 
3日,1日,2日
となっているものを、数字の大きい順に
1日,2日,3日
としたいです。
セル内のデータ数は、一定(例では、3つ)ではありません。
 
よろしくお願いします。

投稿日時: 24/03/22 08:25:59
投稿者: nob1122

並び順をまちがえたので、再投稿します。
同一セル内のデータを並び替えしたいです。
具体的には、
   
3日,1日,2日
となっているものを、数字の大きい順に
3日,2日,1日
としたいです。
セル内のデータ数は、一定(例では、3つ)ではありません。
   
よろしくお願いします。

回答
投稿日時: 24/03/22 08:43:46
投稿者: 半平太

>セル内のデータ数は、一定(例では、3つ)ではありません。
 
サンプルが単純すぎる感があります。
もっと、実際に近い複雑な例を1つ挙げて貰えませんか?

投稿日時: 24/03/22 09:15:28
投稿者: nob1122

  A      B
1 2日,1日,3日 3日,2日,1日  
2 4日,5日   5日,4日
3 1日,10日  10日,1日
  
A列にあるデータをB列のように並び替えたいと考えています。

回答
投稿日時: 24/03/22 10:08:32
投稿者: 竹ちゃん

わざわざVBAにしなくても。
 
B1 =TEXTJOIN("日,",,SORT(TEXTSPLIT(SUBSTITUTE(A1,"日",""),","),,-1,1))&"日"
下にフィルコピー
 
少なくとも例示の場合だとうまくいきます。

回答
投稿日時: 24/03/22 10:28:50
投稿者: 竹ちゃん

すみません。
↓これに変えてください。
 
B1 =TEXTJOIN("日,",,SORT(TEXTSPLIT(SUBSTITUTE(A1,"日",""),",")*1,,-1,1))&"日"
下にフィルコピー
 
さっきのだとソートがうまくいかない場合があったので。

投稿日時: 24/03/22 10:43:02
投稿者: nob1122

竹ちゃんさま、ありがとうございます。
  
実は、データの詳細が、下記のようになっています。最初からお伝えしなくて申し訳ありません。
ご提案の数式素晴らしいです。さらにどう改良するとよいか、ご示唆お願いします。
  
  A              B
1 かぜ2日,家事都合1日,発熱3日 発熱3日,かぜ2日,家事都合1日  
  
    
A列にあるデータをB列のように並び替えたいと考えています。

回答
投稿日時: 24/03/22 10:53:35
投稿者: 竹ちゃん

nob1122 さんの引用:
竹ちゃんさま、ありがとうございます。
  
実は、データの詳細が、下記のようになっています。最初からお伝えしなくて申し訳ありません。
ご提案の数式素晴らしいです。さらにどう改良するとよいか、ご示唆お願いします。
  
  A              B
1 かぜ2日,家事都合1日,発熱3日 発熱3日,かぜ2日,家事都合1日  
  
    
A列にあるデータをB列のように並び替えたいと考えています。

 
申し訳ないですが、↑これは私には無理です。
ワークシート関数だけではおそらく無理でしょう。
なので、他の方の回答(本来のVBAでの回答)をお待ちください。
 

回答
投稿日時: 24/03/22 12:04:54
投稿者: hatena
投稿者のウェブサイトに移動

標準モジュールに下記のコードを記述します。
 

Option Explicit

Function TextSort(s As String) As String
    If s = "" Then Exit Function
    Dim ary
    ary = Split(s, ",")
    Dim ary2()
    ReDim ary2(UBound(ary), 1)

    Dim i As Long
    For i = 0 To UBound(ary)
        ary2(i, 0) = ary(i)
        ary2(i, 1) = extractNum(ary(i))
    Next
    With WorksheetFunction
        ary2 = .Sort(ary2, 2, 1, False)
        TextSort = .TextJoin(",", True, .Index(ary2, 0, 1))
    End With
End Function

Function extractNum(s) As Long
    Dim i As Long, pos1 As Long, Pos2 As Long, flg As Boolean
    For i = 1 To Len(s)
        If Not flg And IsNumeric(Mid(s, i, 1)) Then
            flg = True
            pos1 = i
        ElseIf flg And Not IsNumeric(Mid(s, i, 1)) Then
            Exit For
        End If
    Next
    Pos2 = i
    If pos1 > 0 Then extractNum = Val(Mid(s, pos1, Pos2 - pos1))
End Function

 
B1セルに下記の式を設定
=TextSort(A1)
下にコピー
 
以上でどうでしょう。
 

回答
投稿日時: 24/03/22 13:01:27
投稿者: 半平太

頭の体操(お遊び)ですけども、こんな数式で出来るかもです。
 
B1セル =LET(R,TEXTSPLIT(A1,","),D,BYCOL(SUBSTITUTE(R,"日",""),LAMBDA(F,LOOKUP(99,RIGHT(F,{1,2})*1))),L,COUNT(D),SQ,SEQUENCE(1,L,L-1,-1),INDEX(R,L-MOD(SORT(D*100+SQ,,-1,TRUE),100)))

回答
投稿日時: 24/03/22 14:02:59
投稿者: simple

やっていることは同じですけど。Exce365でない場合を他の閲覧者のために。
 
Function mySort(s As String) As String
    Dim sl As Object
    Dim re As Object
    Dim ary As Variant
    Dim ary2 As Variant
    Dim num As Long
    Dim e As Variant
    Dim k As Long
 
    Set sl = CreateObject("System.Collections.SortedList")
    Set re = CreateObject("VBScript.RegExp")
    re.Pattern = "^.*?(\d+).*?$"
 
    ary = Split(s, ",")
    num = UBound(ary) + 1
    ReDim ary2(1 To num) As String
 
    For Each e In ary
        sl.Add CLng(re.Replace(e, "$1")), e
    Next
    For k = sl.Count - 1 To 0 Step -1
        ary2(num - k) = sl.GetByIndex(k)
    Next
    mySort = Join(ary2, ",")
End Function
 
B1セルに =mySort(A1) などとしてください。
 
# > もっと、実際に近い複雑な例を1つ挙げて
# とわざわざ指摘があって、
# 質問者さんから提示された「実際に近いもの」に対して回答したところ、
# これに条件の後出し。正直、同じ回答者として同情の念を禁じえませんでした。

投稿日時: 24/03/22 14:09:38
投稿者: nob1122

未熟者ですみません。
皆様のおかげで、何とかなりそうです。
ありがとうございました。