[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『文字列?の検算』(dack)
このサイトを知って1年余り 普段はエクセルを使う事も余り無いので 過去ログから自分の知りたい情報を検索して使っていましたが これはどの様にして検索したらいいのか解らなかったので初めて質問します
D3からD100までセルの表示形式標準で 「1(2,3,4)[A(B,C,D)]」や空白が入っています、 それをD103から下にD3からD100までの Aの合計、Bの合計、Cの合計、Dの合計、をD列一列出す事は可能でしょうか?
D 2 [A(B,C,D)] 3 2(3,0,0) 4 1(2,0,4) 5 6 9(0,1,12) ・ ・
上の例なら 103 12 ←Aの合計 1・・ 5 ←Bの合計 1・・ 1 ←Cの合計 1・・ 16 ←Dの合計 [Windows98 Excel97]
必ず、A(B,C,D)となっているなら Excel97でもいけると思うのですが・・・
Option Explicit
Sub test() Dim r As Range Dim cntA As Long, cntB As Long, cntC As Long, cntD As Long
Application.ScreenUpdating = False For Each r In Range("D2", "D100") If r.Value <> "" Then cntA = cntA + Val(Mid(r.Value, 1, 1)) cntB = cntB + Val(Mid(r.Value, 3, 1)) cntC = cntC + Val(Mid(r.Value, 5, 1)) cntD = cntD + Val(Mid(r.Value, 7, 1)) End If Next Range("D103", "D106").Value = Application.Transpose(Array(cntA, cntB, cntC, cntD)) Application.ScreenUpdating = True
End Sub (SHIOJII)
おっと、衝突〜☆
携帯からなので、直接の式は書けませんが、、、 配列数式を用いて、IF関数の条件でFIND関数などを使用し、"("や","や")"を探し、文字として抜き取る。それを、SUM関数で足してやるのはどうでしょう?
(キリキ)(〃⌒o⌒)b
二桁を考慮していませんでした。 とりあえず、捨ててください。 (SHIOJII)
あんまりきれいじゃないですが。 97はSplitがなかったような。 Sub Test() Dim i As Long Dim MyArray As Variant Dim Kei(3) As Long Dim loc1 As Long, loc2 As Long Dim st As String
MyArray = Range("D3:D100")
For i = LBound(MyArray, 1) To UBound(MyArray, 1) st = Trim(MyArray(i, 1)) If st <> "" Then loc1 = InStr(st, "(") Kei(0) = Kei(0) + Val(Left(st, loc1 - 1)) loc2 = InStr(loc1 + 1, st, ",") Kei(1) = Kei(1) + Val(Mid(st, loc1 + 1, loc2 - 1)) loc1 = InStr(loc2 + 1, st, ",") Kei(2) = Kei(2) + Val(Mid(st, loc2 + 1, loc1 - 1)) loc2 = InStr(loc1 + 1, st, ")") Kei(3) = Kei(3) + Val(Mid(st, loc1 + 1, loc2 - 1)) End If Next i For i = 0 To 3 Cells(i + 103, "D").Value = Kei(i) Next i
End Sub (やっちん)
SHIOJIIさん、キリキさん、やっちんさん 有難うございます 質問して答えが返って来るのがこんなに嬉しい事だとは知りませんでした
今回は複数シートにわたり、 日々列が変わって行くのでやっちんさんのVBAを 毎日修正しながら対応したいと思います^^v これで何度も電卓を叩く必要が無くなります^^;
(やっちんさん、そうなんですよねぇ97はSplitが無いから皆さんが 日々ここに提示してくださるサンプルが実行出来ない時が有るんですよ... (dack)
キリキさんのヒントをモトに具体的な数式を考えてみました。ややこしかった(*_*;) って解決しちゃいましたね^^; 関数だとこんな感じで出来ましたぁ、ということで・・・
いずれも配列数式としてCtrl+Shift+Enterで確定してください。
D103に =SUM(IF(D3:D100<>"",--LEFT(D3:D100,FIND("(",D3:D100)-1))) D104に =SUM(IF(D3:D100<>"",--LEFT(MID(D3:D100,FIND("(",D3:D100)+1,20),FIND(",",MID(D3:D100,FIND("(",D3:D100)+1,20))-1))) D105に =SUM(IF(D3:D100<>"",--LEFT(MID(D3:D100,FIND(",",D3:D100)+1,20),FIND(",",MID(D3:D100,FIND(",",D3:D100)+1,20))-1))) D106に =SUM(IF(D3:D100<>"",--RIGHT(LEFT(D3:D100,LEN(D3:D100)-1),LEN(D3:D100)-FIND(",",D3:D100)-FIND(",",MID(D3:D100,FIND(",",D3:D100)+1,20))-1)))
MID関数の文字数を20としてあるので、「( 」より右側に20文字以上あるのなら変更してください。 (かなれっと)
すいません、おもいっきり間違えていました。 MID関数で取り出す文字列の長さを修正してます。 Sub Test() Dim i As Long Dim MyArray As Variant Dim Kei(3) As Long Dim loc1 As Long, loc2 As Long Dim st As String
MyArray = Range("D3:D100") For i = LBound(MyArray, 1) To UBound(MyArray, 1) st = Trim(MyArray(i, 1)) If st <> "" Then loc1 = InStr(st, "(") Kei(0) = Kei(0) + Val(Left(st, loc1 - 1)) loc2 = InStr(loc1 + 1, st, ",") Kei(1) = Kei(1) + Val(Mid(st, loc1 + 1, loc2 - loc1 - 1)) loc1 = InStr(loc2 + 1, st, ",") Kei(2) = Kei(2) + Val(Mid(st, loc2 + 1, loc1 - loc2 - 1)) loc2 = InStr(loc1 + 1, st, ")") Kei(3) = Kei(3) + Val(Mid(st, loc1 + 1, loc2 - loc1 - 1)) End If Next i For i = 0 To 3 Cells(i + 103, "D").Value = Kei(i) Next i End Sub (やっちん)
おはようございます かなれっとさん、やっちんさん有難う御座います ここに質問投稿して良かったと思います
このかなれっとさんが書いた関数式は、 やはり私のスキルで過去ログをどんなに見ても解らなかったですo( _ _ )o ショボーン
やっちんさん上と下の式 私が作ったサンプルでは同じように動いたんですが、 どの様になった時にバグを起こすのでしょう?
結果は変わりません(^^; 最初のコードは数値の部分を取り出すときに実際より長めに取り出していました。 例を挙げると「1(2,3,4)」の2番目の数字をMID関数で取り出す場合「2,3」を取り出していました。 ただ、これをVAL関数で数値に変換すると「2」になります。結果的に2番目の数値を取得しています。 2番目以降の数値の取り出しでも同じことが起きています。 結果が正しくても、意図した処理と異なるのでそれは間違った処理です。 こういう潜在的なバグは後々のメンテナンスに支障をきたす場合があります。 (やっちん)
SplitX for 97 を作成してみました
Sub test() Dim a, x, ap As Object, i As Long, b(), title, result Set ap = Application.WorksheetFunction a = Range("d2:d100").Value With ap For i = 1 To UBound(a, 1) a(i, 1) = .Substitute(.Substitute(.Substitute(.Substitute(a(i, 1), "(", ","), _ ")", ""), "[", ""), "]", "") Next End With title = SplitX(a(1, 1), ",") ReDim result(UBound(title), 1) For i = 0 To UBound(title) result(i, 0) = title(i) Next For i = 2 To UBound(a, 1) x = SplitX(a(i, 1), ",") On Error Resume Next IsArray (x) If Err.Number = 0 Then For ii = 0 To UBound(x) result(ii, 1) = Val(result(ii, 1)) + Val(x(ii)) Next End If Err.Clear On Error GoTo 0 Next With Range("d103") .CurrentRegion.Clear .Resize(UBound(result, 1) + 1, 2) = result End With Erase result, a End Sub
Function SplitX(txt, Optional delim As String = " ") Dim x(), i As Long, n As Long i = 1 Do If Mid(txt, i, 1) = delim Then ReDim Preserve x(n) x(n) = Left(txt, i - 1) txt = Right(txt, Len(txt) - i) i = 0: n = n + 1 End If i = i + 1 Loop Until i > Len(txt) If Len(txt) Then ReDim Preserve x(n) x(n) = txt End If SplitX = x End Function (seiya)
こんにちは やっちんさん有難う御座います そうなんですか やはり「VBAを設計するには後々の事まで考える」が鉄則なんですよね 数値が変わらないところのを見つけるには 私はまだまだ修行がたりないかな これで明日から仕事がちょっと楽になります(*^.^*)エヘッ
seiyaさん有難う御座います、、、 でもここで ReDim result(UBound(title), 1) 「実行時エラー'9'インデックスが有効範囲にありません。」 というエラーがでます 家のEXCEL97とEXCEL2000でやっても^^;
Dim result を Dim result() に変えてみてください。(seiya)
あらら、範囲が...
range("d3:d100")が違っていました。 range("d2:d100") ですね と、思ったら、あってますね? D2には [A(B,C,D)] がありますか?
いいえ 私のミスで質問するときに「2」を消すのを忘れていました [A(B,C,D)]は質問する前に私が付けたものです^^;; D2には関係ないもの(日付)が入っています(dack)
>D2には関係ないもの(日付)が入っています どのようなデータがどの部分に入っているのかわからないと... 困りましたね、空白に、日付まで混入ですか...(seiya)
お邪魔様です。 今度は何時お邪魔できるか分からないので回答出来る様な身分じゃないんですけどね。 せっかく作ったのでよかったら試してみてください。 Option Explicit Sub てすと() Dim MyA As Variant Dim MyAry() As Variant Dim i As Long Dim j As Long With Application .ScreenUpdating = False Sheets.Add After:=Sheets(Sheets.Count) With Sheets(Sheets.Count) .Range("D1:D98").Value = Sheets("Sheet1").Range("D3:D100").Value .Range("D:D").TextToColumns Comma:=True, OtherChar:="(", Other:=True MyA = .UsedRange.Value End With If IsArray(MyA) Then ReDim MyAry(1 To UBound(MyA, 2), 1 To 1) For j = 1 To UBound(MyA, 2) For i = 1 To UBound(MyA, 1) If Not IsDate(MyA(i, j)) Then MyAry(j, 1) = MyAry(j, 1) + Val(MyA(i, j)) End If Next Next With Sheets("Sheet1") .Range("D103", .Range("D103").End(xlDown)).ClearContents .Range("D103").Resize(UBound(MyA, 2)).Value = MyAry End With Erase MyA, MyAry End If .DisplayAlerts = False Sheets(Sheets.Count).Delete .DisplayAlerts = True .ScreenUpdating = True .Goto Sheets("Sheet1").Range("D103") End With End Sub #2006/3/5 16:35 #日付を無視する様にしました。 (SoulMan)
私の方は、こんな感じです
Sub test() Dim a, x, ap As Object, i As Long, b(), result(3) Set ap = Application.WorksheetFunction a = Range("d2:d100").Value For i = 1 To UBound(a, 1) a(i, 1) = Application.Substitute(a(i, 1), "(", ",") If InStr(a(i, 1), ",") > 0 Then x = SplitX(a(i, 1), ",") On Error Resume Next IsArray (x) If Err.Number = 0 Then For ii = 0 To UBound(x) result(ii) = Val(result(ii)) + Val(x(ii)) Next End If Err.Clear On Error GoTo 0 End If Next With Range("d103") .CurrentRegion.Clear .Resize(4) = Application.Transpose(result) End With Erase result, a End Sub
Function SplitX(txt, Optional delim As String = " ") Dim x(), i As Long, n As Long i = 1 Do If Mid(txt, i, 1) = delim Then ReDim Preserve x(n) x(n) = Left(txt, i - 1) txt = Right(txt, Len(txt) - i) i = 0: n = n + 1 End If i = i + 1 Loop Until i > Len(txt) If Len(txt) Then ReDim Preserve x(n) x(n) = txt End If SplitX = x End Function (seiya) SoulManさんのはなぜか、結果が3種類ですね?
>SoulManさんのはなぜか、結果が3種類ですね? 失礼しました。引数を省略し過ぎていました。m(__)m ちょっと訂正してみましたのでお試し下さい。 あぁ〜〜、、たまに回答するとあせるわ(^^; (SoulMan)
SoulManさん、お久しぶりです〜♪ 待ってました^^
>今度は何時お邪魔できるか分からないので回答出来る様な身分じゃないんですけどね。 そんなこと言わずに、ちょいちょい来て下さいよ〜
(キリキ)(〃⌒o⌒)b
>空白に、日付まで混入ですか... seiyaさんどうもすいませんでした 私は初めに 「D3からD100までのAの合計、Bの合計、Cの合計、Dの合計、をD列一列出す事は可能でしょうか」 と聞いていますのでD2の事はVBAに関係ないだろうと思い日付の事は書きませんでした。
SoulManさん有難う御座いました お久しぶりにSoulManさんのVBAを私の質問に回答くださって、、、 お二人の回答も出来ました^^ (dack)
解決したようですね。 Excel97で使用できるように Split/Join 関数を作ってみました。 使用方法はすべてオリジナルに準拠したつもりです。 よかったら使ってみてください。
Function Split(Expression, Optional delimiter, _ Optional limit As Long = -1, Optional Compare _ As VbCompareMethod = vbTextCompare) Dim x(), i As Long, n As Long, y As Long ReDim x(0) If limit = 0 Or Expression = "" Then Split = x: Exit Function Expression = CStr(Expression) If limit = 1 Then _ x(0) = Expression: Split = x: Exit Function If IsMissing(delimiter) Then delimiter = Chr(32) y = Len(delimiter) i = 1 Do If StrComp(Mid(Expression, i, y), delimiter, Compare) = 0 Then ReDim Preserve x(n) x(n) = Left(Expression, i - 1) Expression = Right(Expression, Len(Expression) - i - y + 1) n = n + 1 If limit <> -1 Then _ If n >= limit - 1 Then Exit Do i = 0 End If i = i + 1 Loop Until i > Len(Expression) If Len(Expression) Then ReDim Preserve x(n) x(n) = Expression End If Split = x End Function
Function Join(SourceArray, Optional delimiter) As String Dim e As Variant On Error GoTo Last If UBound(SourceArray) = -1 Then Exit Function If IsMissing(delimiter) Then delimiter = Chr(32) For Each e In SourceArray Join = Join & e & delimiter Next Join = Left(Join, Len(Join) - Len(delimiter)) Last: End Function
(seiya)
こんばんは^^ 今日、提示してもらった式やVBAを会社の本番データをコピーしてやって見ました 思いどうりの結果がでました^^v
それで上のseiyaさんのSplitを試しにやって見たんですが、、、 Function Split(Expression, Optional delimiter, _ Optional limit As Long = -1, Optional Compare _ As VbCompareMethod = ここが青く光って 「コンパイルエラー: このオートメーションタイプはVisualBasicではサポートされていません」 というエラーが出ます。。。 (dack)
遅くなりました。
Function Split(Expression, Optional delimiter, _ Optional limit As Long = -1, Optional Compare _ As As Long)
に変更してみてください。 もしこれでOKならば、各引数の説明をします。(seiya)
頭の体操を兼ねて...... 皆さんマクロですが、私はマクロが駄目なので関数でチャレンジしてみました。
D103=SUM(IF(D3:D100="","",--MID(D3:D100,1,FIND("(",D3:D100)-1))) D104=SUM(IF(D3:D100="","",--MID(D3:D100,FIND("(",D3:D100)+1,FIND(",",D3:D100)-FIND("(",D3:D100)-1))) D105=SUM(IF(D3:D100="","",--MID(D3:D100,FIND(",",D3:D100)+1,FIND(",",D3:D100,FIND(",",D3:D100)+1)-FIND(",",D3:D100)-1))) D106=SUM(IF(D3:D100="","",--MID(D3:D100,FIND(",",D3:D100,FIND(",",D3:D100)+1)+1,LEN(D3:D100)-FIND(",",D3:D100,FIND(",",D3:D100)+1)-1)))
配列ですので、Ctrl + Shift + Enter です。 ふゥ〜....。朝から疲れた〜。 (SS)
seiyaさんSSさん、こんばんは seiyaさんの修正、最初は動かったんですが、「As」をひとつ取り除いたら 私のマクロでも、他の [[20050423175641]]の中のSplitを使ったマクロでも動いてくれました^^ SSさんの式でもできました^^(でもこの式朝からやってくれたなんて (dack)
>「As」をひとつ取り除いたら..... 失礼しました! でも動いてよかったです。
以下、引数の説明です。 例: myString="Me And You And She And He"
Split(myString,"And",-1)
Split(文字列,区切り文字列,分割数,comparemode)
文字列はいいですよね? 区切り文字は「半角スペース」が規定値になっています。 分割数の規定値は-1で最大分割。 compareの規定値はnullです。 ...null - Option Compare で指定したcompare methodを使用。 ... 0 - Binary compare - 大文字/小文字を区別する。 ... 1 - Text compare - 大文字/小文字を区別しない。
以下、適当に試してください。
msgbox join(split(myString,"And",2,1) msgbox join(split(myString,"and") .... (seiya)
seiyaさん ありがとう御座います お家に帰ってからゆっくりやってみたいと思います^^ (dack)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.