[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『間の文字列を求めるプログラム』(よねこ)
初めまして。
質問があります。
エクセルでQ4-Q8までの文字が1つのセルに入っているとします。
ここで、関数かVBAで
Q4-Q8の間のQ5.Q6.Q7を表示させるにはどうしたらいいですか?
お願いします。
< 使用 Excel:Excel2019、使用 OS:Windows7 >
Replaceで「Q」を””に置換 「-」でSplit
Splitの0番目の要素と1番目の間を補完、でいかがでしょう? (OK) 2020/09/30(水) 16:23
VBAのサンプルです。 必要に応じて For i = kai + 1 To shu - 1 を For i = kai To shu に変更してください。
Sub test()
Dim celstr As String
Dim kugiri As String
Dim kai As Integer
Dim shu As Integer
Dim newcelstr As String
Dim i As Integer
celstr = ActiveCell.Value
celstr = Replace(celstr, "Q", "")
sp = Split(celstr, "-")
kai = sp(0) * 1
shu = sp(1) * 1
newcelstr = ""
For i = kai + 1 To shu - 1
If newcelstr <> "" Then newcelstr = newcelstr & ","
newcelstr = newcelstr & "Q" & i
Next i
ActiveCell.Value = newcelstr
End Sub
(OK) 2020/09/30(水) 16:34
私の提示したものは、アクティブセルが対象なので、セル範囲を ループ処理してはいかがでしょう? (OK) 2020/09/30(水) 16:42
ループ処理の参考HPです。
http://officetanaka.net/excel/vba/tips/tips111b.htm
↑はループ対象が Selection '選択セル ですが
Selection の部分を
Range("A1:A10")
とするとA1〜A10が対象になります。
A1からA列の最終行まで、という 指定もできます。そこはおいおい勉強して みてください。 (OK) 2020/09/30(水) 17:22
For Each c In Range("A1:A10")
cに対する処理
Next c
のように記述します。
コードの一番最後ループのみを記述しても全く 意味がありません。
ループの中に処理を記述します。 (OK) 2020/09/30(水) 17:40
サンプルコードです。
Sub test2()
Dim rng As Range
Dim c As Range
Dim celstr As String
Dim kugiri As String
Dim kai As Integer
Dim shu As Integer
Dim newcelstr As String
Dim i As Integer
Set rng = ActiveSheet.Range("A2:A5")
For Each c In rng
celstr = c.Value
celstr = Replace(celstr, "Q", "")
sp = Split(celstr, "-")
kai = sp(0) * 1
shu = sp(1) * 1
newcelstr = ""
For i = kai + 1 To shu - 1
If newcelstr <> "" Then newcelstr = newcelstr & ","
newcelstr = newcelstr & "Q" & i
Next i
c.Value = newcelstr
Erase sp
Next c
Set rng = Nothing
End Sub
(OK) 2020/09/30(水) 17:44
sp = Split(celstr, "-")
kai = sp(0) * 1
shu = sp(1) * 1
newcelstr = ""
For i = kai + 1 To shu - 1
If newcelstr <> "" Then newcelstr = newcelstr & ","
newcelstr = newcelstr & "Q" & i
Next i
c.Value = newcelstr
のQの部分を文字は指定しないで補完する事も可能でしょうか?
ご教授お願いします。
(よねこ) 2020/09/30(水) 17:53
無理やり関数! 1-9までの数値のみ
|[A] |[B]
[1]|Q4-Q8|Q5,Q6,Q7
[2]|A5-A7|A6
[3]|B2-B9|B3,B4,B5,B6,B7,B8
[4]|C1-C9|C2,C3,C4,C5,C6,C7,C8
B2=LEFT(A1)&SUBSTITUTE(TRIM(MID(SUBSTITUTE(SUBSTITUTE("1 2 3 4 5 6 7 8 9",MAX(IFERROR(FIND(MID(A1,ROW($1:$5),1),"123456789"),"")),REPT(" ",100)),MIN(IFERROR(FIND(MID(A1,ROW($1:$5),1),"123456789"),"")),REPT(" ",100)),100,100))," ",","&LEFT(A1))
配列数式で確定
(稲葉) 2020/09/30(水) 18:10
Dim c As Range
Dim celstr As String
Dim kugiri As String
Dim kai As Integer
Dim shu As Integer
Dim newcelstr As String
Dim i As Integer
Set rng = ActiveSheet.Range("L1:L500")
For Each c In rng
celstr = c.Value
celstr = Replace(celstr, "", "")
sp = Split(celstr, "-")
kai = sp(0) * 1
shu = sp(1) * 1
newcelstr = ""
For i = kai + 1 To shu - 1
If newcelstr <> "" Then newcelstr = newcelstr & ","
newcelstr = newcelstr & "" & i
Next i
c.Value = newcelstr
Erase sp
Next c
Set rng = Nothing
End Sub
実行すると型が一致しませんとでます。
どこがおかしいでしょうか?
ご教授お願いします。
(よねこ) 2020/09/30(水) 18:25
勝手なお願いばかりして大変恐縮ですがぜひお願いします。
失礼します。
(よねこ) 2020/09/30(水) 18:31
>列の中にはPC1-PC3やD9-D11,D14,D17の他にIC1など補完しなくても良いもの含まれています。
除外対象をDictionaryオブジェクトに格納しておいて、 セルの文字列がDictionaryに含まれてなかったら処理、 でいかがでしょう?
>実行すると型が一致しませんとでます。
コードのどの部分で出ますか? (OK) 2020/09/30(水) 18:40
>celstr = Replace(celstr, "", "")
長さ0の文字列を長さ0の文字列に置換しています。 つまり、何も変わっていません。 (OK) 2020/09/30(水) 18:41
出来たらサンプルコードをお願いします。
大変恐縮ですがよろしくお願いします。
困っています。
(よねこ) 2020/09/30(水) 18:44
急いでいるのなら、稲葉さんの配列数式で 解決しませんか?
試したらうまくいきましたけど。 (OK) 2020/09/30(水) 18:49
(よねこ) 2020/09/30(水) 18:56
kai = sp(0) * 1
これは sp(0) が数字になってないとエラーになります。
前段階の
celstr = Replace(celstr, "", "")
で何も置換されてないので、 celstrを区切り文字でSplitした 一つ目の要素、つまりsp(0)に数字以外 の文字列が含まれていると思われます。
(OK) 2020/09/30(水) 18:58
全然別アプローチで、今のところ全部セルアドレスにできそうだったから・・・
Function UF_BW(moji As String) As String
Dim b As String
Dim r As Range
Dim x As Range
b = ""
If moji Like "*-*" Then
Set r = Range(Replace(moji, "-", ":"))
If r.Count > 2 Then
For Each x In r.Resize(r.Count - 2).Offset(1)
b = b & x.Address(0, 0) & ","
Next x
b = Mid(b, 1, Len(b) - 1)
End If
End If
UF_BW = b
End Function
(稲葉) 2020/09/30(水) 19:08
Dim b As String
Dim r As Range
Dim x As Range
b = ""
If moji Like "*-*" Then
Set r = Range(Replace(moji, "-", ":"))
If r.Count > 2 Then
For Each x In r.Resize(r.Count - 2).Offset(1)
b = b & x.Address(0, 0) & ","
Next x
b = Mid(b, 1, Len(b) - 1)
End If
End If
UF_BW = b
End Function
このプログラムで列の指定はどこにあるでしょうか?
ちなみに実行するにはどうすればよいでしょうか?
フォームボタンを押すと実行できるようにしたいです。
すみがよろしくお願いいたします。
(よねこ) 2020/09/30(水) 19:19
(稲葉) 2020/09/30(水) 19:26
Debug.Print (moji)
End Sub
Function UF_BW(moji As String) As String
Dim b As String
Dim r As Range
Dim x As Range
b = ""
If moji Like "*-*" Then
Set r = Range(Replace(moji, "-", ":"))
If r.Count > 2 Then
For Each x In r.Resize(r.Count - 2).Offset(1)
b = b & x.Address(0, 0) & ","
Next x
b = Mid(b, 1, Len(b) - 1)
End If
End If
UF_BW = b
End Function
でよろしいでしょうか?
(よねこ) 2020/09/30(水) 19:44
もっと時間かけて読みなよ それでできてるなら、いいんじゃない? (稲葉) 2020/09/30(水) 19:45
今までサンプルコードを参考にしてきたせいか知識としてほとんどありません。
場違いなのはわかっていますがどうかご理解ください。
(よねこ) 2020/09/30(水) 20:59
イミディエイトウィンドウに何も表示されない、ということですか?
>Debug.Print (moji)
参考まで。
https://tonari-it.com/excel-vba-debug-print/
(OK) 2020/09/30(水) 21:11
Dim c As Range
Dim celstr As String
Dim kugiri As String
Dim kai As Integer
Dim shu As Integer
Dim newcelstr As String
Dim i As Integer
Set rng = ActiveSheet.Range("L1:L500")
For Each c In rng
celstr = c.Value
celstr = Replace(celstr, "", "")
sp = Split(celstr, "-")
kai = sp(0) * 1
shu = sp(1) * 1
newcelstr = ""
For i = kai + 1 To shu - 1
If newcelstr <> "" Then newcelstr = newcelstr & ","
newcelstr = newcelstr & "" & i
Next i
c.Value = newcelstr
Erase sp
Next c
Set rng = Nothing
End Sub
エラー回避するには
kai = sp(0) * 1をどのように変換すればよろしいでしょうか?
他にも問題があるでしょうか?
ご教授願います。
(よねこ) 2020/09/30(水) 21:21
標準モジュールにコードいれて A1に文字列が記入されているとして、B1セルに表示させたい場合 B1セル=UF_BW(A1)
場違いなんて言葉以前に、本気で覚えようとして無いだけに感じますよ。 そんな態度がみえみえだから、私みたいな性悪に迂遠な回答されちゃうんですよ (稲葉) 2020/09/30(水) 21:46
(よねこ) 2020/10/01(木) 03:41
>PC1-PC3はB1セルにPC2 これは仕様通りでないの? まさか、ひとつのセルに C7,C16,C17,C19,C28-C3 って入ってるの?
可能性があるすべてのパターンと求める答えを箇条書きしてください
(稲葉) 2020/10/01(木) 06:16
(γ) 2020/10/01(木) 06:47
Debug.Print (moji)
End Sub
Function UF_BW(moji As String) As String
Dim b As String
Dim r As Range
Dim x As Range
b = ""
If moji Like "*-*" Then
Set r = Range(Replace(moji, "-", ":"))
If r.Count > 2 Then
For Each x In r.Resize(r.Count - 2).Offset(1)
b = b & x.Address(0, 0) & ","
Next x
b = Mid(b, 1, Len(b) - 1)
End If
End If
UF_BW = b
End Function
を使用しています。
よろしくお願いします。
(よねこ) 2020/10/01(木) 06:55
(γ) 2020/10/01(木) 07:14
D9-D11,D14-D17 この場合は?
>>PC1-PC3はB1セルにPC2 >これは仕様通りでないの こっちに対する回答は? (稲葉) 2020/10/01(木) 07:23
D9-D11,D14-D17は b2セルにD10 D15 D16 です。 PC1-PC3はB1セルにPC2 はこれは仕様通りです。 (γ)様 C1,C2,C3,C4場合は何も返さないです。 あくまでもA列内に D9-D11,D14-D17などの-を含んでいた際に その間のD10 D15 D16を隣のB列に返す仕様にしたいです。 申し訳ありませんがお願いします。
(よねこ) 2020/10/01(木) 07:41
2020/10/01(木) 06:34 にも書きましたが、もう少し説明いただきたかった。
本来は、- という書き方をやめて、
すべて列挙する方式に変更したいのではないんですか?
そうであれば、間にある文字列だけでなく、
列挙方式にした場合の、カンマでひとつひとつを連結した文字列を
返すようにしたほうがよいのではないですか?
間の文字列が得られたら、
その次のステップとして、取り出した文字列を反映した全体の文字列が欲しいんです、
とかいう流れになることはないですね?
(γ) 2020/10/01(木) 07:53
大分終盤になってから横入りすみません。 こうかな...?
Sub sample()
Dim aCell As Range
For Each aCell In Selection
For Each aStr In Split(aCell.Value, ",")
aCell.Offset(, 1).Value = aCell.Offset(, 1).Value & InterStr(aStr)
Next
Next
End Sub
Function InterStr(aStr) As String
Dim ret()
InterStr = ""
If Not aStr Like "*-*" Then Exit Function
buf = Split(aStr, "-")
For i = 1 To WorksheetFunction.Min(Len(buf(0)), Len(buf(1)))
If IsNumeric(Mid(buf(0), i)) And IsNumeric(Mid(buf(0), i)) Then Exit For
Next
If Left(buf(0), i - 1) <> Left(buf(1), i - 1) Then Exit Function
iniLetter = Left(buf(0), i - 1)
For i = Val(Mid(buf(1), i)) - 1 To Val(Mid(buf(0), i)) + 1 Step -1
InterStr = "," & iniLetter & i & InterStr
Next
InterStr = Mid(InterStr, 2)
End Function
(´・ω・`) 2020/10/01(木) 07:54
>取り出した文字列を反映した全体の文字列が欲しいんです 質問掲示板あるあるですね。 (´・ω・`) 2020/10/01(木) 07:55
|[A] |[B] |[C]
[1]|C7,C16,C17,C19,C28-C30 |C29 |B1=UF_BW(A1)
[2]|D9-D11,D14-D17 |D10,D15,D16 |
[3]|R28,R47,R48-R60,R67 |R49,R50,R51,R52,R53,R54,R55,R56,R57,R58,R59|
[4]|A1-B2,C1,D5-F5,H1-G1 |A2,B2,A3,B3,D6,E6,F6 |
コード(再帰処理)
Function UF_BW(ByVal moji As String, Optional rec As Boolean = False) As String
Dim b As String
Dim c As Variant
Dim r As Range
Dim x As Range
b = ""
Select Case True
Case moji Like "*,*"
For Each c In Split(moji, ",")
b = b & UF_BW(c, True)
Next c
Case moji Like "*-*"
Set r = Range(Replace(moji, "-", ":"))
If r.Count > 2 Then
For Each x In r.Resize(r.Count - 2).Offset(1)
b = b & x.Address(0, 0) & ","
Next x
End If
Case Else
b = ""
End Select
If Not rec Then b = Mid(b, 1, Len(b) - 1)
UF_BW = b
End Function
例表にも書いたけど、アルファベットが変わると、セル範囲を行方向にオフセットでループしているので、チグハグな結果になります。
> >取り出した文字列を反映した全体の文字列が欲しいんです >質問掲示板あるあるですね。 いや、ほんとよくありますよね。
今回も、 1)Q4-Q8の間のQ5.Q6.Q7 ↓ 2)PC1-PC3 ↓ 3)A2にC7,C16,C17,C19,C28-C3 ↓ 4) 第4形態 デスタムーアかって・・・ (稲葉) 2020/10/01(木) 08:13
(´・ω・`) さんの試しました D9-D11,D14-D17 これだけ D10D15,D16 ~~↑~ カンマ入らないっす (稲葉) 2020/10/01(木) 08:18
>カンマ入らないっす いれわすれました 誤) aCell.Offset(, 1).Value = aCell.Offset(, 1).Value & InterStr(aStr) 正) aCell.Offset(, 1).Value = aCell.Offset(, 1).Value & "," & InterStr(aStr)
(´・ω・`) 2020/10/01(木) 08:34
(;´Д`)
私もさっき嵌ったんですが、B列の状態判断してカンマ打ってかないとダメっぽいっす
|[A] |[B]
[1]|C7,C16,C17,C19,C28-C30 |,,,,,C29
[2]|D9-D11,D14-D17 |,D10,D15,D16
[3]|R28,R47,R48-R60,R67 |,,,R49,R50,R51,R52,R53,R54,R55,R56,R57,R58,R59,
[4]|A1-B2,C1,D5-F5,H1-G1 |,,,,
(稲葉) 2020/10/01(木) 08:41
>B列の状態判断してカンマ打ってかないとダメっぽいっす いま気づきました。 考え直します。 (´・ω・`) 2020/10/01(木) 08:43
(よねこ) 2020/10/01(木) 12:33
>説明が足りないなら遠慮なくおっしゃってください。 いや、いまボールはよねこさんの方にあるのでは? 回答者から聞かれたことに答えないと。
考え直しました。
Sub sample()
Dim aCell As Range
For Each aCell In Selection
aCell.Offset(, 1).Value = InterStr(aCell.Value)
Next
End Sub
Function InterStr(aStr) As String
InterStr = ""
For Each bStr In Split(aStr, ",")
tmpstr = ""
If bStr Like "*-*" Then
buf = Split(bStr, "-")
For i = 1 To WorksheetFunction.Min(Len(buf(0)), Len(buf(1)))
If IsNumeric(Mid(buf(0), i)) And IsNumeric(Mid(buf(0), i)) Then Exit For
Next
If Left(buf(0), i - 1) <> Left(buf(1), i - 1) Then Exit Function
iniLetter = Left(buf(0), i - 1)
For i = Val(Mid(buf(1), i)) - 1 To Val(Mid(buf(0), i)) + 1 Step -1
tmpstr = "," & iniLetter & i & tmpstr
Next
tmpstr = Mid(tmpstr, 2)
End If
If tmpstr <> "" Then InterStr = InterStr & "," & tmpstr
Next
InterStr = Mid(InterStr, 2)
End Function
(´・ω・`) 2020/10/01(木) 13:36
私の最後のやつは試してもらえたのかしら? (稲葉) 2020/10/01(木) 14:01
皆様大変勉強になりました。
重ね重ね感謝いたします。
(よねこ) 2020/10/02(金) 03:23
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.